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