port omap3 code to post-displaystate
[qemu] / hw / beagle.c
1 /*\r
2  * Beagle board emulation. http://beagleboard.org/\r
3  * \r
4  * Copyright (C) 2008 yajin(yajin@vm-kernel.org)\r
5  *\r
6  * This program is free software; you can redistribute it and/or\r
7  * modify it under the terms of the GNU General Public License as\r
8  * published by the Free Software Foundation; either version 2 or\r
9  * (at your option) version 3 of the License.\r
10  *\r
11  * This program is distributed in the hope that it will be useful,\r
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
14  * GNU General Public License for more details.\r
15  *\r
16  * You should have received a copy of the GNU General Public License\r
17  * along with this program; if not, write to the Free Software\r
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,\r
19  * MA 02111-1307 USA\r
20  */\r
21 \r
22 #include "qemu-common.h"\r
23 #include "sysemu.h"\r
24 #include "omap.h"\r
25 #include "arm-misc.h"\r
26 #include "irq.h"\r
27 #include "console.h"\r
28 #include "boards.h"\r
29 #include "i2c.h"\r
30 #include "devices.h"\r
31 #include "flash.h"\r
32 #include "hw.h"\r
33 #include "block.h"\r
34 \r
35 #define BEAGLE_NAND_CS                  0\r
36 \r
37 #define GPMC_NOR             0\r
38 #define GPMC_NAND           1\r
39 #define GPMC_MDOC           2\r
40 #define GPMC_ONENAND    3\r
41 #define MMC_NAND            4\r
42 #define MMC_ONENAND     5\r
43 \r
44 \r
45 #define TST_DEVICE              0x0\r
46 #define EMU_DEVICE              0x1\r
47 #define HS_DEVICE               0x2\r
48 #define GP_DEVICE               0x3\r
49 \r
50 #define DEBUG_BEAGLE\r
51 \r
52 #ifdef DEBUG_BEAGLE\r
53 #define BEAGLE_DEBUG(...)    do { fprintf(stderr, __VA_ARGS__); } while(0)\r
54 #else\r
55 #define BEAGLE_DEBUG(x)    \r
56 #endif\r
57 \r
58 /* Beagle board support */\r
59 struct beagle_s {\r
60     struct omap_mpu_state_s *cpu;\r
61     \r
62     struct nand_bflash_s *nand;\r
63     struct omap3_lcd_panel_s *lcd_panel;\r
64     i2c_bus *i2c;\r
65     struct twl4030_s *twl4030;\r
66 };\r
67 \r
68 \r
69 \r
70 static struct arm_boot_info beagle_binfo = {\r
71     .ram_size = 0x08000000,\r
72 };\r
73 \r
74 \r
75 static uint32_t beagle_nand_read16(void *opaque, target_phys_addr_t addr)\r
76 {\r
77         struct beagle_s *s = (struct beagle_s *) opaque;\r
78     //BEAGLE_DEBUG("beagle_nand_read16 offset %x\n",addr);\r
79 \r
80         switch (addr)\r
81         {\r
82                 case 0x7C: /*NAND_COMMAND*/\r
83                 case 0x80: /*NAND_ADDRESS*/\r
84                         OMAP_BAD_REG(addr);\r
85                         break;\r
86                 case 0x84: /*NAND_DATA*/\r
87                         return nandb_read_data16(s->nand);\r
88                         break;\r
89                 default:\r
90                         OMAP_BAD_REG(addr);\r
91                         break;\r
92         }\r
93     return 0;\r
94 }\r
95 \r
96 static void beagle_nand_write16(void *opaque, target_phys_addr_t addr,\r
97                 uint32_t value)\r
98 {\r
99         struct beagle_s *s = (struct beagle_s *) opaque;\r
100     switch (addr)\r
101         {\r
102                 case 0x7C: /*NAND_COMMAND*/\r
103                         nandb_write_command(s->nand,value);\r
104                         break;\r
105                 case 0x80: /*NAND_ADDRESS*/\r
106                         nandb_write_address(s->nand,value);\r
107                         break;\r
108                 case 0x84: /*NAND_DATA*/\r
109                         nandb_write_data16(s->nand,value);\r
110                         break;\r
111                 default:\r
112                         OMAP_BAD_REG(addr);\r
113                         break;\r
114         }\r
115 }\r
116 \r
117 \r
118 static CPUReadMemoryFunc *beagle_nand_readfn[] = {\r
119         beagle_nand_read16,\r
120         beagle_nand_read16,\r
121         omap_badwidth_read32,\r
122 };\r
123 \r
124 static CPUWriteMemoryFunc *beagle_nand_writefn[] = {\r
125         beagle_nand_write16,\r
126         beagle_nand_write16,\r
127         omap_badwidth_write32,\r
128 };\r
129 \r
130 static void beagle_nand_setup(struct beagle_s *s)\r
131 {\r
132         //int iomemtype;\r
133         \r
134         /*MT29F2G16ABC*/\r
135         s->nand = nandb_init(NAND_MFR_MICRON,0xba);\r
136         /*wp=1, no write protect!!! */\r
137         //nand_set_wp(s->nand, 1);\r
138 \r
139 /*      iomemtype = cpu_register_io_memory(0, beagle_nand_readfn,\r
140                     beagle_nand_writefn, s);\r
141     cpu_register_physical_memory(0x6e00007c, 0xc, iomemtype);*/\r
142     omap_gpmc_attach(s->cpu->gpmc, 0, 0, NULL, NULL, s, beagle_nand_readfn, beagle_nand_writefn);\r
143 \r
144          /*BOOT from nand*/\r
145     omap3_set_mem_type(s->cpu,GPMC_NAND);\r
146 \r
147 }\r
148 \r
149 static int beagle_nand_read_page(struct beagle_s *s,uint8_t *buf, uint16_t page_addr)\r
150 {\r
151         uint16_t *p;\r
152         int i;\r
153 \r
154         p=(uint16_t *)buf;\r
155 \r
156         /*send command 0x0*/\r
157         beagle_nand_write16(s,0x7C,0);\r
158         /*send page address */\r
159         beagle_nand_write16(s,0x80,page_addr&0xff);\r
160         beagle_nand_write16(s,0x80,(page_addr>>8)&0x7);\r
161         beagle_nand_write16(s,0x80,(page_addr>>11)&0xff);\r
162         beagle_nand_write16(s,0x80,(page_addr>>19)&0xff);\r
163         beagle_nand_write16(s,0x80,(page_addr>>27)&0xff);\r
164         /*send command 0x30*/\r
165         beagle_nand_write16(s,0x7C,0x30);\r
166 \r
167         for (i=0;i<0x800/2;i++)\r
168         {\r
169                 *p++ = beagle_nand_read16(s,0x84);\r
170         }\r
171         return 1;\r
172 }\r
173 \r
174 /*read the xloader from NAND Flash into internal RAM*/\r
175 static int beagle_boot_from_nand(struct beagle_s *s)\r
176 {\r
177         uint32_t        loadaddr, len;\r
178         uint8_t nand_page[0x800],*load_dest;\r
179         uint32_t nand_pages,i;\r
180 \r
181         /* The first two words(8 bytes) in first nand flash page have special meaning.\r
182                 First word:x-loader len\r
183                 Second word: x-load address in internal ram */\r
184         beagle_nand_read_page(s,nand_page,0);\r
185         len = *((uint32_t*)nand_page);\r
186         loadaddr =  *((uint32_t*)(nand_page+4));\r
187         if ((len==0)||(loadaddr==0)||(len==0xffffffff)||(loadaddr==0xffffffff))\r
188                 return (-1);\r
189 \r
190         /*put the first page into internal ram*/\r
191         load_dest = phys_ram_base +beagle_binfo.ram_size;\r
192         load_dest += loadaddr-OMAP3_SRAM_BASE;\r
193         \r
194         BEAGLE_DEBUG("load_dest %x phys_ram_base %x \n",(unsigned)load_dest,(unsigned)phys_ram_base);\r
195         \r
196         memcpy(load_dest,nand_page+8,0x800-8);\r
197         load_dest += 0x800-8;\r
198 \r
199         nand_pages = len/0x800;\r
200         if (len%0x800!=0)\r
201                 nand_pages++;\r
202 \r
203         for (i=1;i<nand_pages;i++)\r
204         {\r
205                 beagle_nand_read_page(s,nand_page,i*0x800);\r
206                 memcpy(load_dest,nand_page,0x800);\r
207                 load_dest += 0x800;\r
208         }\r
209         s->cpu->env->regs[15] = loadaddr;\r
210         return 0;\r
211 \r
212 }\r
213 \r
214 static int beagle_rom_emu(struct beagle_s *s)\r
215 {\r
216     if (!omap3_mmc_boot(s->cpu))\r
217         if (beagle_boot_from_nand(s) < 0)\r
218             return -1;\r
219         return 0;\r
220 }\r
221 \r
222 static void beagle_dss_setup(struct beagle_s *s)\r
223 {\r
224         s->lcd_panel = omap3_lcd_panel_init();\r
225         omap3_lcd_panel_attach(s->cpu->dss, 0, s->lcd_panel);\r
226         s->lcd_panel->dss = s->cpu->dss;\r
227 }\r
228 \r
229 static void beagle_mmc_cs_cb(void *opaque, int line, int level)\r
230 {\r
231     /* TODO: this seems to actually be connected to the menelaus, to\r
232      * which also both MMC slots connect.  */\r
233     omap_mmc_enable((struct omap_mmc_s *) opaque, !level);\r
234 \r
235     printf("%s: MMC slot %i active\n", __FUNCTION__, level + 1);\r
236 }\r
237 \r
238 static void beagle_i2c_setup(struct beagle_s *s)\r
239 {\r
240     /* Attach the CPU on one end of our I2C bus.  */\r
241     s->i2c = omap_i2c_bus(s->cpu->i2c[0]);\r
242 \r
243     s->twl4030 = twl4030_init(s->i2c, s->cpu->irq[0][OMAP_INT_35XX_SYS_NIRQ]);\r
244 }\r
245 \r
246 \r
247 static void beagle_init(ram_addr_t ram_size, int vga_ram_size,\r
248                 const char *boot_device,\r
249                 const char *kernel_filename, const char *kernel_cmdline,\r
250                 const char *initrd_filename, const char *cpu_model)\r
251 {\r
252     struct beagle_s *s = (struct beagle_s *) qemu_mallocz(sizeof(*s));\r
253     int sdram_size = beagle_binfo.ram_size;\r
254 \r
255         if (ram_size < sdram_size +  OMAP3530_SRAM_SIZE) {\r
256         fprintf(stderr, "This architecture uses %i bytes of memory\n",\r
257                         sdram_size + OMAP3530_SRAM_SIZE);\r
258         exit(1);\r
259     }\r
260         s->cpu = omap3530_mpu_init(sdram_size, NULL);\r
261         beagle_nand_setup(s);\r
262         beagle_i2c_setup(s);\r
263         beagle_dss_setup(s);\r
264         omap3_set_device_type(s->cpu,GP_DEVICE);\r
265     if (beagle_rom_emu(s) < 0) {\r
266                 fprintf(stderr,"boot from MMC and nand failed \n");\r
267                 exit(-1);\r
268         }\r
269 }\r
270 \r
271 \r
272 \r
273 QEMUMachine beagle_machine = {\r
274     .name = "beagle",\r
275     .desc =     "Beagle board (OMAP3530)",\r
276     .init =     beagle_init,\r
277     .ram_require =     (0x08000000 +  OMAP3530_SRAM_SIZE) | RAMSIZE_FIXED,\r
278 };\r
279 \r