Add elementary OMAP3530 Beagleboard support
[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 \r
34 #define BEAGLE_NAND_CS                  0\r
35 #define BEAGLE_TWL4030_ADDR             0x4b    /* Power management */\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 #ifdef DEBUG_BEAGLE\r
51 #define BEAGLE_DEBUG(x)    do {  printf x ; } while(0)\r
52 #else\r
53 #define BEAGLE_DEBUG(x)    do {   } while(0)\r
54 #endif\r
55 \r
56 /* Beagle board support */\r
57 struct beagle_s {\r
58     struct omap_mpu_state_s *cpu;\r
59     \r
60     struct nand_bflash_s *nand;\r
61     struct omap3_lcd_panel_s *lcd_panel;\r
62     i2c_bus *i2c;\r
63 };\r
64 \r
65 \r
66 \r
67 static struct arm_boot_info beagle_binfo = {\r
68     .ram_size = 0x08000000,\r
69 };\r
70 \r
71 \r
72 static uint32_t beagle_nand_read16(void *opaque, target_phys_addr_t addr)\r
73 {\r
74         struct beagle_s *s = (struct beagle_s *) opaque;\r
75     BEAGLE_DEBUG(("beagle_nand_read16 offset %x\n",addr));\r
76 \r
77         switch (addr)\r
78         {\r
79                 case 0x7C: /*NAND_COMMAND*/\r
80                 case 0x80: /*NAND_ADDRESS*/\r
81                         OMAP_BAD_REG(addr);\r
82                         break;\r
83                 case 0x84: /*NAND_DATA*/\r
84                         return nandb_read_data16(s->nand);\r
85                         break;\r
86                 default:\r
87                         OMAP_BAD_REG(addr);\r
88                         break;\r
89         }\r
90     return 0;\r
91 }\r
92 \r
93 static void beagle_nand_write16(void *opaque, target_phys_addr_t addr,\r
94                 uint32_t value)\r
95 {\r
96         struct beagle_s *s = (struct beagle_s *) opaque;\r
97     switch (addr)\r
98         {\r
99                 case 0x7C: /*NAND_COMMAND*/\r
100                         nandb_write_command(s->nand,value);\r
101                         break;\r
102                 case 0x80: /*NAND_ADDRESS*/\r
103                         nandb_write_address(s->nand,value);\r
104                         break;\r
105                 case 0x84: /*NAND_DATA*/\r
106                         nandb_write_data16(s->nand,value);\r
107                         break;\r
108                 default:\r
109                         OMAP_BAD_REG(addr);\r
110                         break;\r
111         }\r
112 }\r
113 \r
114 \r
115 static CPUReadMemoryFunc *beagle_nand_readfn[] = {\r
116         beagle_nand_read16,\r
117         beagle_nand_read16,\r
118         omap_badwidth_read32,\r
119 };\r
120 \r
121 static CPUWriteMemoryFunc *beagle_nand_writefn[] = {\r
122         beagle_nand_write16,\r
123         beagle_nand_write16,\r
124         omap_badwidth_write32,\r
125 };\r
126 \r
127 static void beagle_nand_setup(struct beagle_s *s)\r
128 {\r
129         //int iomemtype;\r
130         \r
131         /*MT29F2G16ABC*/\r
132         s->nand = nandb_init(NAND_MFR_MICRON,0xba);\r
133         /*wp=1, no write protect!!! */\r
134         //nand_set_wp(s->nand, 1);\r
135 \r
136 /*      iomemtype = cpu_register_io_memory(0, beagle_nand_readfn,\r
137                     beagle_nand_writefn, s);\r
138     cpu_register_physical_memory(0x6e00007c, 0xc, iomemtype);*/\r
139     omap_gpmc_attach(s->cpu->gpmc, 0, 0, NULL, NULL, s, beagle_nand_readfn, beagle_nand_writefn);\r
140 \r
141          /*BOOT from nand*/\r
142     omap3_set_mem_type(s->cpu,GPMC_NAND);\r
143 \r
144 }\r
145 \r
146 static int beagle_nand_read_page(struct beagle_s *s,uint8_t *buf, uint16_t page_addr)\r
147 {\r
148         uint16_t *p;\r
149         int i;\r
150 \r
151         p=(uint16_t *)buf;\r
152 \r
153         /*send command 0x0*/\r
154         beagle_nand_write16(s,0x7C,0);\r
155         /*send page address */\r
156         beagle_nand_write16(s,0x80,page_addr&0xff);\r
157         beagle_nand_write16(s,0x80,(page_addr>>8)&0x7);\r
158         beagle_nand_write16(s,0x80,(page_addr>>11)&0xff);\r
159         beagle_nand_write16(s,0x80,(page_addr>>19)&0xff);\r
160         beagle_nand_write16(s,0x80,(page_addr>>27)&0xff);\r
161         /*send command 0x30*/\r
162         beagle_nand_write16(s,0x7C,0x30);\r
163 \r
164         for (i=0;i<0x800/2;i++)\r
165         {\r
166                 *p++ = beagle_nand_read16(s,0x84);\r
167         }\r
168         return 1;\r
169 }\r
170 /*TODO*/\r
171 static int beagle_boot_from_mmc(struct beagle_s *s)\r
172 {\r
173         return (-1);\r
174 }\r
175 \r
176 /*read the xloader from NAND Flash into internal RAM*/\r
177 static int beagle_boot_from_nand(struct beagle_s *s)\r
178 {\r
179         uint32_t        loadaddr, len;\r
180         uint8_t nand_page[0x800],*load_dest;\r
181         uint32_t nand_pages,i;\r
182 \r
183         /* The first two words(8 bytes) in first nand flash page have special meaning.\r
184                 First word:x-loader len\r
185                 Second word: x-load address in internal ram */\r
186         beagle_nand_read_page(s,nand_page,0);\r
187         len = *((uint32_t*)nand_page);\r
188         loadaddr =  *((uint32_t*)(nand_page+4));\r
189         if ((len==0)||(loadaddr==0)||(len==0xffffffff)||(loadaddr==0xffffffff))\r
190                 return (-1);\r
191 \r
192         /*put the first page into internal ram*/\r
193         load_dest = phys_ram_base +beagle_binfo.ram_size;\r
194         load_dest += loadaddr-OMAP3_SRAM_BASE;\r
195         \r
196         BEAGLE_DEBUG(("load_dest %x phys_ram_base %x \n",(unsigned)load_dest,(unsigned)phys_ram_base));\r
197         \r
198         memcpy(load_dest,nand_page+8,0x800-8);\r
199         load_dest += 0x800-8;\r
200 \r
201         nand_pages = len/0x800;\r
202         if (len%0x800!=0)\r
203                 nand_pages++;\r
204 \r
205         for (i=1;i<nand_pages;i++)\r
206         {\r
207                 beagle_nand_read_page(s,nand_page,i*0x800);\r
208                 memcpy(load_dest,nand_page,0x800);\r
209                 load_dest += 0x800;\r
210         }\r
211         s->cpu->env->regs[15] = loadaddr;\r
212         return 0;\r
213 \r
214 }\r
215  static int beagle_rom_emu(struct beagle_s *s)\r
216 {\r
217         if (beagle_boot_from_mmc(s)<0)\r
218         {\r
219                 if (beagle_boot_from_nand(s)<0)\r
220                         return (-1); \r
221         }\r
222         return (0);\r
223 }\r
224 \r
225 static void beagle_dss_setup(struct beagle_s *s, DisplayState *ds)\r
226 {\r
227         s->lcd_panel = omap3_lcd_panel_init(ds);\r
228         omap3_lcd_panel_attach(s->cpu->dss, 0, s->lcd_panel);\r
229         s->lcd_panel->dss = s->cpu->dss;\r
230 }\r
231 \r
232 static void beagle_mmc_cs_cb(void *opaque, int line, int level)\r
233 {\r
234     /* TODO: this seems to actually be connected to the menelaus, to\r
235      * which also both MMC slots connect.  */\r
236     omap_mmc_enable((struct omap_mmc_s *) opaque, !level);\r
237 \r
238     printf("%s: MMC slot %i active\n", __FUNCTION__, level + 1);\r
239 }\r
240 \r
241 static void beagle_i2c_setup(struct beagle_s *s)\r
242 {\r
243 \r
244     /* Attach the CPU on one end of our I2C bus.  */\r
245     s->i2c = omap_i2c_bus(s->cpu->i2c[0]);\r
246 \r
247     /* Attach a menelaus PM chip */\r
248     i2c_set_slave_address(\r
249                     twl4030_init(s->i2c,\r
250                             s->cpu->irq[0][OMAP_INT_35XX_SYS_NIRQ]),\r
251                     BEAGLE_TWL4030_ADDR);\r
252 }\r
253 \r
254 \r
255 static void beagle_init(ram_addr_t ram_size, int vga_ram_size,\r
256                 const char *boot_device, DisplayState *ds,\r
257                 const char *kernel_filename, const char *kernel_cmdline,\r
258                 const char *initrd_filename, const char *cpu_model)\r
259 {\r
260     struct beagle_s *s = (struct beagle_s *) qemu_mallocz(sizeof(*s));\r
261     int sdram_size = beagle_binfo.ram_size;\r
262 \r
263         if (ram_size < sdram_size +  OMAP3530_SRAM_SIZE) {\r
264         fprintf(stderr, "This architecture uses %i bytes of memory\n",\r
265                         sdram_size + OMAP3530_SRAM_SIZE);\r
266         exit(1);\r
267     }\r
268         s->cpu = omap3530_mpu_init(sdram_size, NULL, NULL);\r
269         beagle_nand_setup(s);\r
270         beagle_i2c_setup(s);\r
271         beagle_dss_setup(s,ds);\r
272         omap3_set_device_type(s->cpu,GP_DEVICE);\r
273    if (beagle_rom_emu(s)<0)\r
274         {\r
275                 fprintf(stderr,"boot from MMC and nand failed \n");\r
276                 exit(-1);\r
277         }\r
278         \r
279 \r
280 }\r
281 \r
282 \r
283 \r
284 QEMUMachine beagle_machine = {\r
285     .name = "beagle",\r
286     .desc =     "Beagle board (OMAP3530)",\r
287     .init =     beagle_init,\r
288     .ram_require =     (0x08000000 +  OMAP3530_SRAM_SIZE) | RAMSIZE_FIXED,\r
289 };\r
290 \r