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_ALL
46 #define debug_out(flag,out) {\
47 if (flag & DEBUG_FLAG) printf out; \
50 #define debug_out(flag,out)
53 static uint32_t sm502_badwidth_read8(void *opaque
, target_phys_addr_t addr
)
56 /*to make debug easy */
61 static void sm502_badwidth_write8(void *opaque
, target_phys_addr_t addr
,
68 static uint32_t sm502_badwidth_read16(void *opaque
, target_phys_addr_t addr
)
71 /*to make debug easy */
75 static void sm502_badwidth_write16(void *opaque
, target_phys_addr_t addr
,
82 static uint32_t sm502_badwidth_read32(void *opaque
, target_phys_addr_t addr
)
85 /*to make debug easy */
89 static void sm502_badwidth_write32(void *opaque
, target_phys_addr_t addr
,
96 void sm502_gpio_out_set(struct sm502_s
*s
, int line
, qemu_irq handler
)
98 if (line
>= 64 || line
< 0)
99 cpu_abort(cpu_single_env
, "%s: No GPIO line %i\n", __FUNCTION__
, line
);
100 s
->out_handler
[line
& 63] = handler
;
103 qemu_irq
*sm502_gpio_in_get(struct sm502_s
*s
, int line
)
105 if (line
>= 64 || line
< 0)
106 cpu_abort(cpu_single_env
, "%s: No GPIO line %i\n", __FUNCTION__
, line
);
107 return s
->in_handler
+ (line
& 31);
110 void sm502_gpio_set_pin(struct sm502_s
*s
, int line
, int level
)
112 if (line
>= 64 || line
< 0)
113 cpu_abort(cpu_single_env
, "%s: No GPIO line %i\n", __FUNCTION__
, line
);
117 s
->gpio_data_low
|= level
<< line
;
119 s
->gpio_data_high
|= level
<< (line
- 32);
124 s
->gpio_data_low
&= (~(1 << line
));
126 s
->gpio_data_high
&= (~(1 << (line
- 32)));
130 int sm502_gpio_get_pin(struct sm502_s
*s
, int line
)
132 if (line
>= 64 || line
< 0)
133 cpu_abort(cpu_single_env
, "%s: No GPIO line %i\n", __FUNCTION__
, line
);
135 return (s
->gpio_data_low
& (1 << line
)) >> line
;
137 return (s
->gpio_data_high
& (1 << line
)) >> line
;
140 static void sm502_gpio_set(void *opaque
, int line
, int level
)
142 struct sm502_s
*s
= (struct sm502_s
*) opaque
;
143 if (line
>= 64 || line
< 0)
144 cpu_abort(cpu_single_env
, "%s: No GPIO line %i\n", __FUNCTION__
, line
);
145 sm502_gpio_set_pin(s
, line
, level
);
148 static void sm502_gpio_init(struct sm502_s
*s
)
150 s
->in_handler
= qemu_allocate_irqs(sm502_gpio_set
, s
, 64);
153 static uint32_t sm502_read32(void *opaque
, target_phys_addr_t addr
)
155 struct sm502_s
*s
= (struct sm502_s
*) opaque
;
157 debug_out(DEBUG_CONF
,
158 ("%s addr " TARGET_FMT_plx
" pc " TARGET_FMT_plx
"\n",
159 __FUNCTION__
, addr
, cpu_single_env
->active_tc
.PC
));
164 return s
->system_control
;
166 return s
->misc_control
;
168 return s
->gpio_low32
;
170 return s
->gpio_high32
;
172 return s
->dram_control
;
174 return s
->arb_control
;
176 return s
->command_list_status
;
178 return s
->raw_int_status
;
180 return s
->int_status
;
184 return s
->debug_control
;
186 return s
->current_gate
;
188 return s
->current_clock
;
190 return s
->power0_gate
;
192 return s
->power0_clock
;
194 return s
->power1_gate
;
196 return s
->power1_clock
;
198 return s
->sleep_gate
;
200 return s
->power_control
;
202 return s
->pci_master_base
;
204 return s
->endian_control
;
208 return s
->pll_clock_count
;
210 return s
->misc_timing
;
212 return s
->current_sdram_clock
;
214 return s
->non_cache_address
;
216 return s
->pll_control
;
218 return s
->gpio_data_low
;
220 return s
->gpio_data_high
;
222 return s
->gpio_datadir_low
;
224 return s
->gpio_datadir_high
;
226 return s
->gpio_int_setup
;
228 return s
->gpio_int_status
;
230 cpu_abort(cpu_single_env
,
231 "%s undefined addr " TARGET_FMT_plx
232 " pc " TARGET_FMT_plx
"\n", __FUNCTION__
, addr
,
233 cpu_single_env
->active_tc
.PC
);
239 static void sm502_write32(void *opaque
, target_phys_addr_t addr
, uint32_t value
)
241 struct sm502_s
*s
= (struct sm502_s
*) opaque
;
245 debug_out(DEBUG_CONF
,
246 ("%s addr " TARGET_FMT_plx
" value %x pc " TARGET_FMT_plx
"\n",
247 __FUNCTION__
, addr
, value
, cpu_single_env
->active_tc
.PC
));
261 s
->system_control
= value
& 0xff00b8f7;
264 s
->misc_control
= value
& 0xff7fff10;
267 s
->gpio_low32
= value
;
270 s
->gpio_high32
= value
;
273 s
->dram_control
= value
& 0x7fffffc3;
276 s
->arb_control
= value
& 0x77777777;
279 s
->raw_int_status
&= (~(value
& 0x7f));
282 s
->int_status
= value
& 0x400000;
285 s
->int_mask
= value
& 0xffdf3f5f;
288 s
->debug_control
= value
& 0xff;
291 s
->power0_gate
= value
& 0x71dff;
294 s
->power0_clock
= value
& 0xff3f1f1f;
297 s
->power1_gate
= value
& 0x61dff;
300 s
->power1_clock
= value
& 0xff3f1f1f;
303 s
->sleep_gate
= value
& 0x786000;
306 s
->power_control
= value
& 0x7;
309 s
->pci_master_base
= value
& 0xfff00000;
312 s
->endian_control
= value
& 0x1;
315 s
->misc_timing
= value
& 0xf1f1f4f;
318 s
->non_cache_address
= value
& 0x3fff;
321 s
->pll_control
= value
& 0x1fffff;
324 diff
= (s
->gpio_data_low
^ value
) & s
->gpio_datadir_low
;
325 s
->gpio_data_low
= value
;
326 while ((ln
= ffs(diff
)))
329 if (s
->out_handler
[ln
])
330 qemu_set_irq(s
->out_handler
[ln
], (value
>> ln
) & 1);
335 diff
= (s
->gpio_datadir_high
^ value
) & s
->gpio_datadir_high
;
336 s
->gpio_data_high
= value
;
337 while ((ln
= ffs(diff
)))
340 if (s
->out_handler
[ln
+ 32])
341 qemu_set_irq(s
->out_handler
[ln
+ 32], (value
>> ln
) & 1);
346 s
->gpio_datadir_low
= value
;
349 s
->gpio_datadir_high
= value
;
352 s
->gpio_int_setup
= value
& 0x7f7f7f;
355 s
->gpio_int_status
&= (~(value
& 0x7f0000));
358 cpu_abort(cpu_single_env
,
359 "%s undefined addr " TARGET_FMT_plx
360 " value %x pc " TARGET_FMT_plx
"\n", __FUNCTION__
, addr
,
361 value
, cpu_single_env
->active_tc
.PC
);
369 static CPUReadMemoryFunc
*sm502_readfn
[] = {
370 sm502_badwidth_read32
,
371 sm502_badwidth_read32
,
375 static CPUWriteMemoryFunc
*sm502_writefn
[] = {
376 sm502_badwidth_write32
,
377 sm502_badwidth_write32
,
381 static uint32_t sm502_read_config(PCIDevice
* d
, uint32_t address
, int len
)
385 debug_out(DEBUG_PCICONF
, ("%s addr 0x%x len %x pc " TARGET_FMT_plx
"\n",
386 __FUNCTION__
, address
, len
,
387 cpu_single_env
->active_tc
.PC
));
394 val
= le32_to_cpu(*(uint32_t *) (d
->config
+ address
));
399 val
= le16_to_cpu(*(uint16_t *) (d
->config
+ address
));
402 val
= d
->config
[address
];
409 static void sm502_write_config(PCIDevice
* d
, uint32_t address
, uint32_t val
,
414 uint32_t new_sm502_mm_io
;
417 struct sm502_s
*s
= (struct sm502_s
*) d
;
419 debug_out(DEBUG_PCICONF
,
420 ("%s addr 0x%x value %x len %x pc " TARGET_FMT_plx
"\n",
421 __FUNCTION__
, address
, val
, len
, cpu_single_env
->active_tc
.PC
));
423 /* not efficient, but simple */
425 for (i
= 0; i
< len
; i
++)
427 /* default read/write accesses */
487 d
->config
[addr
] = (val
& 0xff);
488 if (addr
== (0x14 + len
- 1))
490 /*write the last byte of mmio */
491 new_sm502_mm_io
= le32_to_cpu(*(uint32_t *) (d
->config
+ 0x14));
492 if (s
->sm502_mm_io
!= new_sm502_mm_io
)
494 /*remapped the Control register to CPU memory space */
496 cpu_register_io_memory(0, sm502_readfn
,
498 cpu_register_physical_memory(new_sm502_mm_io
+
499 s
->pci_mem_base
, 0x200000,
501 debug_out(DEBUG_MMIO
,("new_sm502_mm_io %x pci_mem _base %llx\n",
502 new_sm502_mm_io
, s
->pci_mem_base
));
503 if (s
->sm502_mm_io
!= 0)
504 cpu_register_physical_memory(s
->sm502_mm_io
+
505 pci_mem_base
, 0x200000,
507 s
->sm502_mm_io
= new_sm502_mm_io
;
511 else if (can_write
== 0)
514 "warnning. %s :write to read only pci conf register addr %x\n",
517 else if (can_write
== 2)
520 "warnning. %s :write to reserved pci conf register addr %x\n",
529 static void sm502_reset(struct sm502_s
*s
)
537 s
->config
[10] = 0x30;
538 s
->config
[11] = 0x02;
539 s
->config
[0x34] = 0x40;
540 s
->config
[0x40] = 0x01;
541 s
->config
[0x42] = 0x01;
542 s
->config
[0x43] = 0x06;
544 s
->arb_control
= 0x05146732;
545 s
->current_gate
= 0x00021807;
546 s
->current_clock
= 0x2a1a0a09;
547 s
->power0_gate
= 0x00021807;
548 s
->power0_clock
= 0x2a1a0a09;
549 s
->power1_gate
= 0x00021807;
550 s
->power1_clock
= 0x2a1a0a09;
551 s
->sleep_gate
= 0x00018000;
552 s
->endian_control
= 0x1;
553 s
->device_id
= 0x050100a0;
554 s
->non_cache_address
= 0x0000ffff;
555 s
->pll_control
= 0x0000ffff;
559 struct sm502_s
*sm502_init(PCIBus
* bus
, int devfn
,
560 target_phys_addr_t pci_mem_base
)
562 struct sm502_s
*s
= (struct sm502_s
*) qemu_mallocz(sizeof(*s
));
564 s
= (struct sm502_s
*) pci_register_device(bus
, "SM502 PCI",
565 sizeof(struct sm502_s
), devfn
,
568 s
->pci_mem_base
= pci_mem_base
;