4 * Copyright (c) 2009 yajin <yajin@vm-kernel.org>
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26 * Gdium is a loongson 2f CPU based notebook. http://www.gdium.com/
38 #include "qemu-char.h"
40 #include "audio/audio.h"
42 #include "mips_loongson2f.h"
45 //#define DEBUG /*global debug on/off */
46 #define DEBUG_BOARD_INIT (1<<0x0)
47 #define DEBUG_I2C_EMU (1<<0x1)
48 #define DEBUG_RAM_MAPPING (1<<0x2)
50 #define DEBUG_ALL (0xffffffff)
51 #define DEBUG_FLAG (DEBUG_BOARD_INIT|DEBUG_RAM_MAPPING)
54 #define debug_out(flag,out) {\
55 if (flag & DEBUG_FLAG) printf out; \
58 #define debug_out(flag,out)
64 #define BIOS_SIZE (512 * 1024)
65 #define BIOS_SECTOR_BITS (12)
66 #define GDIUM_SDRAM_SIZE (512*1024*1024)
68 #define SM502_DEV_NO 14
69 #define GDIUM_PCI_MEM_BASE (0x10000000)
71 #define GDIUM_GPIO_SCL 6
72 #define GDIUM_GPIO_SDA 13
83 qemu_irq
*emu_i2c_cbs
;
94 uint8_t is_slave_addr
;
104 struct sm502_s
*sm502
;
107 struct emu_i2c
*emu_i2c
;
110 static void main_cpu_reset(void *opaque
)
112 CPUState
*env
= opaque
;
119 static int is_start(struct emu_i2c
*emu_i2c
, int line
, int level
)
121 if ((line
== GDIUM_GPIO_SDA
) && (!level
) && (emu_i2c
->scl
))
127 static int is_stop(struct emu_i2c
*emu_i2c
, int line
, int level
)
129 if ((line
== GDIUM_GPIO_SDA
) && (level
) && (emu_i2c
->scl
))
135 static int one_cycle(struct emu_i2c
*emu_i2c
, int line
, int level
)
137 if ((line
== GDIUM_GPIO_SCL
) && (level
))
142 /*PMON puts the data on GPIO SDA line*/
143 static void send_bit(struct gdium_s
*s
, int line
, int level
)
145 s
->emu_i2c
->out_data
|=
146 sm502_gpio_get_pin(s
->sm502
,
147 GDIUM_GPIO_SDA
) << (s
->emu_i2c
->out_offset
);
148 s
->emu_i2c
->out_offset
--;
151 /*prepare ack to cheat pmon*/
152 static void prepare_ack(struct gdium_s
*s
)
154 /*Set SDA=0 means we received ACK from slave */
155 sm502_gpio_set_pin(s
->sm502
, GDIUM_GPIO_SDA
, 0);
158 static void recv_bit(struct gdium_s
*s
, int line
, int level
)
160 if (s
->emu_i2c
->in_offset
== 7)
162 s
->emu_i2c
->in_data
= i2c_recv(s
->emu_i2c
->emu_i2c_bus
);
166 qemu_set_irq(s
->emu_i2c
->sda_irq
,
167 (s
->emu_i2c
->in_data
>> (s
->emu_i2c
->in_offset
)) & 0x1);
168 s
->emu_i2c
->in_offset
--;
171 static void i2c_emu_cb(void *opaque
, int line
, int level
)
173 struct gdium_s
*s
= (struct gdium_s
*) opaque
;
175 if (line
== GDIUM_GPIO_SCL
)
176 s
->emu_i2c
->scl
= level
;
178 debug_out(DEBUG_I2C_EMU
,
179 ("line %s LEVEL %d \n", line
== GDIUM_GPIO_SCL
? "SCL" : "SDA",
182 /*if we are waiting ack from slave address */
183 if (s
->emu_i2c
->waiting_ack
)
185 debug_out(DEBUG_I2C_EMU
, ("waiting_ack \n"));
187 if (one_cycle(s
->emu_i2c
, line
, level
))
189 s
->emu_i2c
->waiting_ack
= 0;
194 /*it means after sending ack, pmon writes to SDA-> wants STOP */
195 if ((line
== GDIUM_GPIO_SDA
) && (s
->emu_i2c
->i2c_state
== RECV_DATA
))
197 s
->emu_i2c
->i2c_state
= IDLE
;
201 if ((s
->emu_i2c
->i2c_state
== IDLE
) || (s
->emu_i2c
->i2c_state
== SEND_DATA
))
203 /*check whether start signal */
204 if (is_start(s
->emu_i2c
, line
, level
))
206 s
->emu_i2c
->i2c_state
= SEND_DATA
;
207 /*is_slave_addr=1 means the next byte is slave addreses */
208 s
->emu_i2c
->is_slave_addr
= 1;
209 s
->emu_i2c
->i2c_state
= SEND_DATA
;
210 debug_out(DEBUG_I2C_EMU
,
211 ("I2C Start. state %d \n", s
->emu_i2c
->i2c_state
));
212 s
->emu_i2c
->out_offset
= 7;
213 s
->emu_i2c
->out_data
= 0;
214 s
->emu_i2c
->slave_addr
= 0;
219 if (is_stop(s
->emu_i2c
, line
, level
))
221 debug_out(DEBUG_I2C_EMU
, ("STOP \n"));
222 s
->emu_i2c
->i2c_state
= IDLE
;
223 i2c_end_transfer(s
->emu_i2c
->emu_i2c_bus
);
227 if (one_cycle(s
->emu_i2c
, line
, level
))
229 debug_out(DEBUG_I2C_EMU
, ("one cycle \n"));
230 switch (s
->emu_i2c
->i2c_state
)
233 debug_out(DEBUG_I2C_EMU
, ("IDLE \n"));
236 send_bit(s
, line
, level
);
237 if (s
->emu_i2c
->out_offset
< 0)
239 debug_out(DEBUG_I2C_EMU
,
240 ("slave_addr %d out data %d \n",
241 s
->emu_i2c
->slave_addr
, s
->emu_i2c
->out_data
));
242 if (s
->emu_i2c
->is_slave_addr
)
244 /*first send is slave address */
245 s
->emu_i2c
->slave_addr
= s
->emu_i2c
->out_data
;
246 i2c_start_transfer(s
->emu_i2c
->
248 s
->emu_i2c
->slave_addr
& 0xfe,
249 s
->emu_i2c
->slave_addr
& 0x1);
250 debug_out(DEBUG_I2C_EMU
,
251 ("slave_addr %d \n", s
->emu_i2c
->slave_addr
));
253 s
->emu_i2c
->is_slave_addr
= 0;
257 /*send reg address or data */
258 i2c_send(s
->emu_i2c
->emu_i2c_bus
, s
->emu_i2c
->out_data
);
260 s
->emu_i2c
->out_offset
= 7;
261 s
->emu_i2c
->out_data
= 0;
262 if (s
->emu_i2c
->slave_addr
& 0x1)
264 s
->emu_i2c
->in_offset
= 7;
265 s
->emu_i2c
->i2c_state
= RECV_DATA
;
268 s
->emu_i2c
->i2c_state
= SEND_DATA
;
269 s
->emu_i2c
->waiting_ack
= 1;
275 recv_bit(s
, line
, level
);
276 if (s
->emu_i2c
->in_offset
< 0)
277 s
->emu_i2c
->i2c_state
= SEND_ACK
;
280 debug_out(DEBUG_I2C_EMU
, ("SEND_ACK \n"));
281 s
->emu_i2c
->in_offset
= 7;
282 s
->emu_i2c
->i2c_state
= RECV_DATA
;
283 i2c_nack(s
->emu_i2c
->emu_i2c_bus
);
286 fprintf(stderr
, "unknown state %d \n", s
->emu_i2c
->i2c_state
);
294 /*gdium uses SM502 GPIO 6/13 to emulate I2C.*/
295 static void mips_gdium_i2c_emu(struct gdium_s
*s
)
297 s
->emu_i2c
->emu_i2c_cbs
= qemu_allocate_irqs(i2c_emu_cb
, s
, 32);
298 sm502_gpio_out_set(s
->sm502
, GDIUM_GPIO_SCL
,
299 s
->emu_i2c
->emu_i2c_cbs
[GDIUM_GPIO_SCL
]);
300 sm502_gpio_out_set(s
->sm502
, GDIUM_GPIO_SDA
,
301 s
->emu_i2c
->emu_i2c_cbs
[GDIUM_GPIO_SDA
]);
303 s
->emu_i2c
->i2c_state
= IDLE
;
305 s
->emu_i2c
->sda_irq
= sm502_gpio_in_get(s
->sm502
, GDIUM_GPIO_SDA
)[0];
308 /*dumped from my gdium pcb*/
309 uint8_t gdium_spd
[0x80] = {
310 0x80, 0x08, 0x08, 0x0e, 0x0a, 0x60, 0x40, 0x00, /*0x00-0x07 */
311 0x05, 0x3d, 0x50, 0x00, 0x82, 0x00, 0x00, 0x00, /*0x08-0x0f */
312 0x0c, 0x04, 0x38, 0x00, 0x04, 0x00, 0x01, 0x3d, /*0x10-0x17 */
313 0x50, 0x50, 0x60, 0x3c, 0x1e, 0x3c, 0x2d, 0x80, /*0x18-0x1f */
314 0x25, 0x37, 0x10, 0x22, 0x3c, 0x1e, 0x13, 0x00, /*0x20-0x27 */
315 0x00, 0x3c, 0x69, 0x80, 0x1e, 0x28, 0x00, 0x00, /*0x28-0x2f */
316 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*0x30-0x37 */
317 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xb2, /*0x38-0x3f */
318 0x7f, 0x4f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*0x40-0x47 */
319 0x54, 0x4a, 0x4d, 0x35, 0x33, 0x33, 0x51, 0x53, /*0x48-0x4f */
320 0x4a, 0x2d, 0x35, 0x31, 0x32, 0x4d, 0x20, 0x20, /*0x50-0x57 */
321 0x20, 0x20, 0x20, 0x00, 0x00, 0x07, 0x47, 0x00, /*0x58-0x5f */
322 0x07, 0x00, 0xb1, 0x98, 0x00, 0x00, 0x00, 0x00, /*0x60-0x67 */
323 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*0x68-0x6f */
324 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*0x70-0x77 */
325 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*0x78-0x7f */
329 void mips_gdium_init(ram_addr_t ram_size
, int vga_ram_size
,
330 const char *boot_device
,
331 const char *kernel_filename
,
332 const char *kernel_cmdline
,
333 const char *initrd_filename
, const char *cpu_model
)
336 unsigned long bios_offset
;
339 struct gdium_s
*s
= qemu_mallocz(sizeof(*s
));
341 if (cpu_model
== NULL
)
343 cpu_model
= "Loongson-2F";
345 s
->env
= cpu_init(cpu_model
);
348 fprintf(stderr
, "Unable to find CPU definition\n");
352 /*set bit 5:7 of status registerto 1.
353 * Loongson 2f does not have 32bit address space and ux/sx/kx is not used in loongson
354 * But qemu needs this. So just set these bits to 1
356 s
->env
->CP0_Status
|= 0xe0;
358 register_savevm("cpu", 0, 3, cpu_save
, cpu_load
, s
->env
);
359 qemu_register_reset(main_cpu_reset
, s
->env
);
362 if (ram_size
> (GDIUM_SDRAM_SIZE
))
365 "qemu: Too much memory for this machine: %d MB, maximum 512 MB\n",
366 ((unsigned int) ram_size
/ (1 << 20)));
370 /*CPU ADDRESS:[0:256M]<->DDR [0:256M]
371 * DDR_ADDR[256M:512M] mapping determined by loongson 2f address windows configuration.
373 if (ram_size
> (256 * 1024 * 1024))
375 debug_out(DEBUG_RAM_MAPPING
, ("Mapping first 256M RAM\n"));
376 cpu_register_physical_memory(0, (256 * 1024 * 1024), IO_MEM_RAM
);
379 cpu_register_physical_memory(0, ram_size
, IO_MEM_RAM
);
381 bios_offset
= ram_size
+ vga_ram_size
;
382 cpu_register_physical_memory(0x1fc00000LL
, BIOS_SIZE
,
383 bios_offset
| IO_MEM_ROM
);
385 /*sst39vf040 flash */
386 index
= drive_get_index(IF_PFLASH
, 0, 0);
390 "A flash image must be given with the " "'pflash' parameter\n");
394 debug_out(DEBUG_BOARD_INIT
, ("Register sst39vf040 size %x at "
395 "offset %08lx addr %08llx '%s' %x\n",
396 BIOS_SIZE
, bios_offset
, 0x1fc00000LL
,
397 bdrv_get_device_name(drives_table
[index
].bdrv
),
398 (BIOS_SIZE
>> BIOS_SECTOR_BITS
)));
399 pflash_cfi02_register(0x1fc00000LL
, bios_offset
, drives_table
[index
].bdrv
,
400 (1 << BIOS_SECTOR_BITS
),
401 BIOS_SIZE
>> BIOS_SECTOR_BITS
, 1, 1, 0xbf, 0xd7,
402 0x0000, 0x0000, 0x555, 0xaaa);
404 cpu_mips_irq_init_cpu(s
->env
);
405 cpu_mips_clock_init(s
->env
);
407 s
->pci_bus
= bonito_init(s
->env
);
408 s
->sm502
= sm502_init(s
->pci_bus
, SM502_DEV_NO
<< 3, 0x10000000);
409 loongson_ddr2_init();
410 loongson_addwin_init();
412 s
->emu_i2c
= qemu_mallocz(sizeof(*s
->emu_i2c
));
413 s
->emu_i2c
->emu_i2c_bus
= i2c_init_bus();
415 eeprom_buf
= qemu_mallocz(8 * 256); /* XXX: make this persistent */
416 memcpy(eeprom_buf
, gdium_spd
, sizeof(gdium_spd
));
417 smbus_eeprom_device_init(s
->emu_i2c
->emu_i2c_bus
, 0xa2, eeprom_buf
);
420 m41t80_init(s
->emu_i2c
->emu_i2c_bus
, NULL
, 0xd0);
421 /*temperature sensors */
422 stds75_init(s
->emu_i2c
->emu_i2c_bus
, NULL
, 0x90);
424 mips_gdium_i2c_emu(s
);
428 QEMUMachine mips_gdium_machine
= {
430 .desc
= "MIPS Gdium notebook",
431 .init
= mips_gdium_init
,
432 .ram_require
= VGA_RAM_SIZE
+ BIOS_SIZE
,