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)
41 #define DEBUG_ALL (0xffffffff)
42 #define DEBUG_FLAG DEBUG_ALL
45 #define debug_out(flag,out) {\
46 if (flag & DEBUG_FLAG) printf out; \
49 #define debug_out(flag,out)
52 static uint32_t sm502_badwidth_read8(void *opaque
, target_phys_addr_t addr
)
55 /*to make debug easy */
60 static void sm502_badwidth_write8(void *opaque
, target_phys_addr_t addr
,
67 static uint32_t sm502_badwidth_read16(void *opaque
, target_phys_addr_t addr
)
70 /*to make debug easy */
74 static void sm502_badwidth_write16(void *opaque
, target_phys_addr_t addr
,
81 static uint32_t sm502_badwidth_read32(void *opaque
, target_phys_addr_t addr
)
84 /*to make debug easy */
88 static void sm502_badwidth_write32(void *opaque
, target_phys_addr_t addr
,
95 void sm502_gpio_out_set(struct sm502_s
*s
, int line
, qemu_irq handler
)
97 if (line
>= 64 || line
< 0)
98 cpu_abort(cpu_single_env
, "%s: No GPIO line %i\n", __FUNCTION__
, line
);
99 s
->out_handler
[line
& 63] = handler
;
102 qemu_irq
*sm502_gpio_in_get(struct sm502_s
*s
, int line
)
104 if (line
>= 64 || line
< 0)
105 cpu_abort(cpu_single_env
, "%s: No GPIO line %i\n", __FUNCTION__
, line
);
106 return s
->in_handler
+ (line
& 31);
109 void sm502_gpio_set_pin(struct sm502_s
*s
, int line
, int level
)
111 if (line
>= 64 || line
< 0)
112 cpu_abort(cpu_single_env
, "%s: No GPIO line %i\n", __FUNCTION__
, line
);
116 s
->gpio_data_low
|= level
<< line
;
118 s
->gpio_data_high
|= level
<< (line
- 32);
123 s
->gpio_data_low
&= (~(1 << line
));
125 s
->gpio_data_high
&= (~(1 << (line
- 32)));
129 int sm502_gpio_get_pin(struct sm502_s
*s
, int line
)
131 if (line
>= 64 || line
< 0)
132 cpu_abort(cpu_single_env
, "%s: No GPIO line %i\n", __FUNCTION__
, line
);
134 return (s
->gpio_data_low
& (1 << line
)) >> line
;
136 return (s
->gpio_data_high
& (1 << line
)) >> line
;
139 static void sm502_gpio_set(void *opaque
, int line
, int level
)
141 struct sm502_s
*s
= (struct sm502_s
*) opaque
;
142 if (line
>= 64 || line
< 0)
143 cpu_abort(cpu_single_env
, "%s: No GPIO line %i\n", __FUNCTION__
, line
);
144 sm502_gpio_set_pin(s
, line
, level
);
147 static void sm502_gpio_init(struct sm502_s
*s
)
149 s
->in_handler
= qemu_allocate_irqs(sm502_gpio_set
, s
, 64);
152 static uint32_t sm502_read32(void *opaque
, target_phys_addr_t addr
)
154 struct sm502_s
*s
= (struct sm502_s
*) opaque
;
156 debug_out(DEBUG_CONF
,
157 ("%s addr " TARGET_FMT_plx
" pc " TARGET_FMT_plx
"\n",
158 __FUNCTION__
, addr
, cpu_single_env
->active_tc
.PC
));
163 return s
->system_control
;
165 return s
->misc_control
;
167 return s
->gpio_low32
;
169 return s
->gpio_high32
;
171 return s
->dram_control
;
173 return s
->arb_control
;
175 return s
->command_list_status
;
177 return s
->raw_int_status
;
179 return s
->int_status
;
183 return s
->debug_control
;
185 return s
->current_gate
;
187 return s
->current_clock
;
189 return s
->power0_gate
;
191 return s
->power0_clock
;
193 return s
->power1_gate
;
195 return s
->power1_clock
;
197 return s
->sleep_gate
;
199 return s
->power_control
;
201 return s
->pci_master_base
;
203 return s
->endian_control
;
207 return s
->pll_clock_count
;
209 return s
->misc_timing
;
211 return s
->current_sdram_clock
;
213 return s
->non_cache_address
;
215 return s
->pll_control
;
217 return s
->gpio_data_low
;
219 return s
->gpio_data_high
;
221 return s
->gpio_datadir_low
;
223 return s
->gpio_datadir_high
;
225 return s
->gpio_int_setup
;
227 return s
->gpio_int_status
;
229 cpu_abort(cpu_single_env
,
230 "%s undefined addr " TARGET_FMT_plx
231 " pc " TARGET_FMT_plx
"\n", __FUNCTION__
, addr
,
232 cpu_single_env
->active_tc
.PC
);
238 static void sm502_write32(void *opaque
, target_phys_addr_t addr
, uint32_t value
)
240 struct sm502_s
*s
= (struct sm502_s
*) opaque
;
244 debug_out(DEBUG_CONF
,
245 ("%s addr " TARGET_FMT_plx
" value %x pc " TARGET_FMT_plx
"\n",
246 __FUNCTION__
, addr
, value
, cpu_single_env
->active_tc
.PC
));
260 s
->system_control
= value
& 0xff00b8f7;
263 s
->misc_control
= value
& 0xff7fff10;
266 s
->gpio_low32
= value
;
269 s
->gpio_high32
= value
;
272 s
->dram_control
= value
& 0x7fffffc3;
275 s
->arb_control
= value
& 0x77777777;
278 s
->raw_int_status
&= (~(value
& 0x7f));
281 s
->int_status
= value
& 0x400000;
284 s
->int_mask
= value
& 0xffdf3f5f;
287 s
->debug_control
= value
& 0xff;
290 s
->power0_gate
= value
& 0x71dff;
293 s
->power0_clock
= value
& 0xff3f1f1f;
296 s
->power1_gate
= value
& 0x61dff;
299 s
->power1_clock
= value
& 0xff3f1f1f;
302 s
->sleep_gate
= value
& 0x786000;
305 s
->power_control
= value
& 0x7;
308 s
->pci_master_base
= value
& 0xfff00000;
311 s
->endian_control
= value
& 0x1;
314 s
->misc_timing
= value
& 0xf1f1f4f;
317 s
->non_cache_address
= value
& 0x3fff;
320 s
->pll_control
= value
& 0x1fffff;
323 diff
= (s
->gpio_data_low
^ value
) & s
->gpio_datadir_low
;
324 s
->gpio_data_low
= value
;
325 while ((ln
= ffs(diff
)))
328 if (s
->out_handler
[ln
])
329 qemu_set_irq(s
->out_handler
[ln
], (value
>> ln
) & 1);
334 diff
= (s
->gpio_datadir_high
^ value
) & s
->gpio_datadir_high
;
335 s
->gpio_data_high
= value
;
336 while ((ln
= ffs(diff
)))
339 if (s
->out_handler
[ln
+ 32])
340 qemu_set_irq(s
->out_handler
[ln
+ 32], (value
>> ln
) & 1);
345 s
->gpio_datadir_low
= value
;
348 s
->gpio_datadir_high
= value
;
351 s
->gpio_int_setup
= value
& 0x7f7f7f;
354 s
->gpio_int_status
&= (~(value
& 0x7f0000));
357 cpu_abort(cpu_single_env
,
358 "%s undefined addr " TARGET_FMT_plx
359 " value %x pc " TARGET_FMT_plx
"\n", __FUNCTION__
, addr
,
360 value
, cpu_single_env
->active_tc
.PC
);
368 static CPUReadMemoryFunc
*sm502_readfn
[] = {
369 sm502_badwidth_read32
,
370 sm502_badwidth_read32
,
374 static CPUWriteMemoryFunc
*sm502_writefn
[] = {
375 sm502_badwidth_write32
,
376 sm502_badwidth_write32
,
380 static uint32_t sm502_read_config(PCIDevice
* d
, uint32_t address
, int len
)
384 debug_out(DEBUG_PCICONF
, ("%s addr 0x%x len %x pc " TARGET_FMT_plx
"\n",
385 __FUNCTION__
, address
, len
,
386 cpu_single_env
->active_tc
.PC
));
393 val
= le32_to_cpu(*(uint32_t *) (d
->config
+ address
));
398 val
= le16_to_cpu(*(uint16_t *) (d
->config
+ address
));
401 val
= d
->config
[address
];
408 static void sm502_write_config(PCIDevice
* d
, uint32_t address
, uint32_t val
,
413 uint32_t new_sm502_mm_io
;
416 struct sm502_s
*s
= (struct sm502_s
*) d
;
418 debug_out(DEBUG_PCICONF
,
419 ("%s addr 0x%x value %x len %x pc " TARGET_FMT_plx
"\n",
420 __FUNCTION__
, address
, val
, len
, cpu_single_env
->active_tc
.PC
));
422 /* not efficient, but simple */
424 for (i
= 0; i
< len
; i
++)
426 /* default read/write accesses */
486 d
->config
[addr
] = (val
& 0xff);
487 if (addr
== (0x14 + len
- 1))
489 /*write the last byte of mmio */
490 new_sm502_mm_io
= le32_to_cpu(*(uint32_t *) (d
->config
+ 0x14));
491 if (s
->sm502_mm_io
!= new_sm502_mm_io
)
493 /*remapped the Control register to CPU memory space */
495 cpu_register_io_memory(0, sm502_readfn
,
497 cpu_register_physical_memory(new_sm502_mm_io
+
498 s
->pci_mem_base
, 0x200000,
500 printf("new_sm502_mm_io %x pci_mem _base %llx\n",
501 new_sm502_mm_io
, s
->pci_mem_base
);
502 if (s
->sm502_mm_io
!= 0)
503 cpu_register_physical_memory(s
->sm502_mm_io
+
504 pci_mem_base
, 0x200000,
506 s
->sm502_mm_io
= new_sm502_mm_io
;
510 else if (can_write
== 0)
513 "warnning. %s :write to read only pci conf register addr %x\n",
516 else if (can_write
== 2)
519 "warnning. %s :write to reserved pci conf register addr %x\n",
528 static void sm502_reset(struct sm502_s
*s
)
536 s
->config
[10] = 0x30;
537 s
->config
[11] = 0x02;
538 s
->config
[0x34] = 0x40;
539 s
->config
[0x40] = 0x01;
540 s
->config
[0x42] = 0x01;
541 s
->config
[0x43] = 0x06;
543 s
->arb_control
= 0x05146732;
544 s
->current_gate
= 0x00021807;
545 s
->current_clock
= 0x2a1a0a09;
546 s
->power0_gate
= 0x00021807;
547 s
->power0_clock
= 0x2a1a0a09;
548 s
->power1_gate
= 0x00021807;
549 s
->power1_clock
= 0x2a1a0a09;
550 s
->sleep_gate
= 0x00018000;
551 s
->endian_control
= 0x1;
552 s
->device_id
= 0x050100a0;
553 s
->non_cache_address
= 0x0000ffff;
554 s
->pll_control
= 0x0000ffff;
558 struct sm502_s
*sm502_init(PCIBus
* bus
, int devfn
,
559 target_phys_addr_t pci_mem_base
)
561 struct sm502_s
*s
= (struct sm502_s
*) qemu_mallocz(sizeof(*s
));
563 s
= (struct sm502_s
*) pci_register_device(bus
, "SM502 PCI",
564 sizeof(struct sm502_s
), devfn
,
567 s
->pci_mem_base
= pci_mem_base
;