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
25 /*sm502 is used in gdium system.*/
37 #define DEBUG_PCICONF (1<<0x0)
38 #define DEBUG_CONF (1<<0x1)
39 #define DEBUG_GPIO (1<<0x2)
40 #define DEBUG_MMIO (1<<0x3)
42 #define DEBUG_ALL (0xffffffff)
43 #define DEBUG_FLAG DEBUG_MMIO
46 #define debug_out(flag,out) {\
47 if (flag & DEBUG_FLAG) printf out; \
50 #define debug_out(flag,out)
53 //#define PRINT_WARNNING
56 static uint32_t sm502_badwidth_read8(void *opaque
, target_phys_addr_t addr
)
59 /*to make debug easy */
64 static void sm502_badwidth_write8(void *opaque
, target_phys_addr_t addr
,
71 static uint32_t sm502_badwidth_read16(void *opaque
, target_phys_addr_t addr
)
74 /*to make debug easy */
78 static void sm502_badwidth_write16(void *opaque
, target_phys_addr_t addr
,
85 static uint32_t sm502_badwidth_read32(void *opaque
, target_phys_addr_t addr
)
88 /*to make debug easy */
92 static void sm502_badwidth_write32(void *opaque
, target_phys_addr_t addr
,
99 void sm502_gpio_out_set(struct sm502_s
*s
, int line
, qemu_irq handler
)
101 if (line
>= 64 || line
< 0)
102 cpu_abort(cpu_single_env
, "%s: No GPIO line %i\n", __FUNCTION__
, line
);
103 s
->out_handler
[line
& 63] = handler
;
106 qemu_irq
*sm502_gpio_in_get(struct sm502_s
*s
, int line
)
108 if (line
>= 64 || line
< 0)
109 cpu_abort(cpu_single_env
, "%s: No GPIO line %i\n", __FUNCTION__
, line
);
110 return s
->in_handler
+ (line
& 31);
113 void sm502_gpio_set_pin(struct sm502_s
*s
, int line
, int level
)
115 if (line
>= 64 || line
< 0)
116 cpu_abort(cpu_single_env
, "%s: No GPIO line %i\n", __FUNCTION__
, line
);
120 s
->gpio_data_low
|= level
<< line
;
122 s
->gpio_data_high
|= level
<< (line
- 32);
127 s
->gpio_data_low
&= (~(1 << line
));
129 s
->gpio_data_high
&= (~(1 << (line
- 32)));
133 int sm502_gpio_get_pin(struct sm502_s
*s
, int line
)
135 if (line
>= 64 || line
< 0)
136 cpu_abort(cpu_single_env
, "%s: No GPIO line %i\n", __FUNCTION__
, line
);
138 return (s
->gpio_data_low
& (1 << line
)) >> line
;
140 return (s
->gpio_data_high
& (1 << line
)) >> line
;
143 static void sm502_gpio_set(void *opaque
, int line
, int level
)
145 struct sm502_s
*s
= (struct sm502_s
*) opaque
;
146 if (line
>= 64 || line
< 0)
147 cpu_abort(cpu_single_env
, "%s: No GPIO line %i\n", __FUNCTION__
, line
);
148 sm502_gpio_set_pin(s
, line
, level
);
151 static void sm502_gpio_init(struct sm502_s
*s
)
153 s
->in_handler
= qemu_allocate_irqs(sm502_gpio_set
, s
, 64);
156 static uint32_t sm502_read32(void *opaque
, target_phys_addr_t addr
)
158 struct sm502_s
*s
= (struct sm502_s
*) opaque
;
160 debug_out(DEBUG_CONF
,
161 ("%s addr " TARGET_FMT_plx
" pc " TARGET_FMT_plx
"\n",
162 __FUNCTION__
, addr
, cpu_single_env
->active_tc
.PC
));
167 return s
->system_control
;
169 return s
->misc_control
;
171 return s
->gpio_low32
;
173 return s
->gpio_high32
;
175 return s
->dram_control
;
177 return s
->arb_control
;
179 return s
->command_list_status
;
181 return s
->raw_int_status
;
183 return s
->int_status
;
187 return s
->debug_control
;
189 return s
->current_gate
;
191 return s
->current_clock
;
193 return s
->power0_gate
;
195 return s
->power0_clock
;
197 return s
->power1_gate
;
199 return s
->power1_clock
;
201 return s
->sleep_gate
;
203 return s
->power_control
;
205 return s
->pci_master_base
;
207 return s
->endian_control
;
211 return s
->pll_clock_count
;
213 return s
->misc_timing
;
215 return s
->current_sdram_clock
;
217 return s
->non_cache_address
;
219 return s
->pll_control
;
221 return s
->gpio_data_low
;
223 return s
->gpio_data_high
;
225 return s
->gpio_datadir_low
;
227 return s
->gpio_datadir_high
;
229 return s
->gpio_int_setup
;
231 return s
->gpio_int_status
;
233 cpu_abort(cpu_single_env
,
234 "%s undefined addr " TARGET_FMT_plx
235 " pc " TARGET_FMT_plx
"\n", __FUNCTION__
, addr
,
236 cpu_single_env
->active_tc
.PC
);
242 static void sm502_write32(void *opaque
, target_phys_addr_t addr
, uint32_t value
)
244 struct sm502_s
*s
= (struct sm502_s
*) opaque
;
248 debug_out(DEBUG_CONF
,
249 ("%s addr " TARGET_FMT_plx
" value %x pc " TARGET_FMT_plx
"\n",
250 __FUNCTION__
, addr
, value
, cpu_single_env
->active_tc
.PC
));
264 s
->system_control
= value
& 0xff00b8f7;
267 s
->misc_control
= value
& 0xff7fff10;
270 s
->gpio_low32
= value
;
273 s
->gpio_high32
= value
;
276 s
->dram_control
= value
& 0x7fffffc3;
279 s
->arb_control
= value
& 0x77777777;
282 s
->raw_int_status
&= (~(value
& 0x7f));
285 s
->int_status
= value
& 0x400000;
288 s
->int_mask
= value
& 0xffdf3f5f;
291 s
->debug_control
= value
& 0xff;
294 s
->power0_gate
= value
& 0x71dff;
297 s
->power0_clock
= value
& 0xff3f1f1f;
300 s
->power1_gate
= value
& 0x61dff;
303 s
->power1_clock
= value
& 0xff3f1f1f;
306 s
->sleep_gate
= value
& 0x786000;
309 s
->power_control
= value
& 0x7;
312 s
->pci_master_base
= value
& 0xfff00000;
315 s
->endian_control
= value
& 0x1;
318 s
->misc_timing
= value
& 0xf1f1f4f;
321 s
->non_cache_address
= value
& 0x3fff;
324 s
->pll_control
= value
& 0x1fffff;
327 diff
= (s
->gpio_data_low
^ value
) & s
->gpio_datadir_low
;
328 s
->gpio_data_low
= value
;
329 while ((ln
= ffs(diff
)))
332 if (s
->out_handler
[ln
])
333 qemu_set_irq(s
->out_handler
[ln
], (value
>> ln
) & 1);
338 diff
= (s
->gpio_datadir_high
^ value
) & s
->gpio_datadir_high
;
339 s
->gpio_data_high
= value
;
340 while ((ln
= ffs(diff
)))
343 if (s
->out_handler
[ln
+ 32])
344 qemu_set_irq(s
->out_handler
[ln
+ 32], (value
>> ln
) & 1);
349 s
->gpio_datadir_low
= value
;
352 s
->gpio_datadir_high
= value
;
355 s
->gpio_int_setup
= value
& 0x7f7f7f;
358 s
->gpio_int_status
&= (~(value
& 0x7f0000));
361 cpu_abort(cpu_single_env
,
362 "%s undefined addr " TARGET_FMT_plx
363 " value %x pc " TARGET_FMT_plx
"\n", __FUNCTION__
, addr
,
364 value
, cpu_single_env
->active_tc
.PC
);
372 static CPUReadMemoryFunc
*sm502_readfn
[] = {
373 sm502_badwidth_read32
,
374 sm502_badwidth_read32
,
378 static CPUWriteMemoryFunc
*sm502_writefn
[] = {
379 sm502_badwidth_write32
,
380 sm502_badwidth_write32
,
384 static uint32_t sm502_read_config(PCIDevice
* d
, uint32_t address
, int len
)
388 debug_out(DEBUG_PCICONF
, ("%s addr 0x%x len %x pc " TARGET_FMT_plx
"\n",
389 __FUNCTION__
, address
, len
,
390 cpu_single_env
->active_tc
.PC
));
397 val
= le32_to_cpu(*(uint32_t *) (d
->config
+ address
));
402 val
= le16_to_cpu(*(uint16_t *) (d
->config
+ address
));
405 val
= d
->config
[address
];
412 static void sm502_write_config(PCIDevice
* d
, uint32_t address
, uint32_t val
,
417 uint32_t new_sm502_mm_io
;
420 struct sm502_s
*s
= (struct sm502_s
*) d
;
422 debug_out(DEBUG_PCICONF
,
423 ("%s addr 0x%x value %x len %x pc " TARGET_FMT_plx
"\n",
424 __FUNCTION__
, address
, val
, len
, cpu_single_env
->active_tc
.PC
));
426 /* not efficient, but simple */
430 for (i
= 0; i
< len
; i
++)
432 /* default read/write accesses */
465 case 0x12: /*[23:21] of reg10 -> 0x0? */
489 if (d
->config
[4] & 0x2)
496 if (d
->config
[4] & 0x2)
513 d
->config
[addr
] = (val
& write_mask
);
514 if (addr
== (0x14 + len
- 1))
516 /*write the last byte of mmio */
517 new_sm502_mm_io
= le32_to_cpu(*(uint32_t *) (d
->config
+ 0x14));
518 if ((s
->sm502_mm_io
!= new_sm502_mm_io
)
519 && ((pci_mem_base
+ new_sm502_mm_io
) < 0xffffffff))
521 if (s
->mmio_index
!= 0)
523 cpu_register_physical_memory(pci_mem_base
+
524 s
->sm502_mm_io
, 0x200000,
526 cpu_unregister_io_memory(s
->mmio_index
);
528 /*remapped the Control register to CPU memory space */
530 cpu_register_io_memory(0, sm502_readfn
,
532 cpu_register_physical_memory(pci_mem_base
+
533 new_sm502_mm_io
, 0x200000,
535 debug_out(DEBUG_MMIO
,
536 ("new_sm502_mm_io %x pci_mem _base %llx\n",
537 new_sm502_mm_io
, pci_mem_base
));
541 else if (can_write
== 0)
543 #ifdef PRINT_WARNNING
545 "warnning. %s :write to read only pci conf register addr %x\n",
549 else if (can_write
== 2)
551 #ifdef PRINT_WARNNING
553 "warnning. %s :write to reserved pci conf register addr %x\n",
563 static void sm502_reset(struct sm502_s
*s
)
567 pci_conf
= s
->dev
.config
;
568 memset(pci_conf
, 0, 256);
579 pci_conf
[0x34] = 0x40;
580 pci_conf
[0x40] = 0x01;
581 pci_conf
[0x42] = 0x01;
582 pci_conf
[0x43] = 0x06;
584 s
->arb_control
= 0x05146732;
585 s
->current_gate
= 0x00021807;
586 s
->current_clock
= 0x2a1a0a09;
587 s
->power0_gate
= 0x00021807;
588 s
->power0_clock
= 0x2a1a0a09;
589 s
->power1_gate
= 0x00021807;
590 s
->power1_clock
= 0x2a1a0a09;
591 s
->sleep_gate
= 0x00018000;
592 s
->endian_control
= 0x1;
593 s
->device_id
= 0x050100a0;
594 s
->non_cache_address
= 0x0000ffff;
595 s
->pll_control
= 0x0000ffff;
599 struct sm502_s
*sm502_init(PCIBus
* bus
, int devfn
, target_phys_addr_t pci_base
)
601 struct sm502_s
*s
= (struct sm502_s
*) qemu_mallocz(sizeof(*s
));
603 s
= (struct sm502_s
*) pci_register_device(bus
, "SM502 PCI",
604 sizeof(struct sm502_s
), devfn
,
607 pci_mem_base
= pci_base
;