Commit f5470d2b4740ea5f99a581375d60fd19cb74657d
1 parent
6abe522c
PMC:
- read from some of pmc registers return 0, but it not should work in so way, because of for example linux kernel expect proper values there, and 0 cause divide by zero exception - convert main oscilator freq from constant to device property
Showing
2 changed files
with
26 additions
and
4 deletions
hw/at91_pmc.c
... | ... | @@ -55,7 +55,6 @@ |
55 | 55 | #define SR_PCK3RDY 0x800 |
56 | 56 | |
57 | 57 | #define SO_FREQ 32768 |
58 | -#define MO_FREQ 9216000 | |
59 | 58 | |
60 | 59 | int at91_master_clock_frequency = SO_FREQ; |
61 | 60 | |
... | ... | @@ -72,6 +71,7 @@ typedef struct PMCState { |
72 | 71 | uint32_t sr; |
73 | 72 | uint32_t imr; |
74 | 73 | uint32_t mck_freq; |
74 | + uint32_t mo_freq; | |
75 | 75 | } PMCState; |
76 | 76 | |
77 | 77 | static void at91_pmc_update_irq(PMCState *s) |
... | ... | @@ -81,7 +81,7 @@ static void at91_pmc_update_irq(PMCState *s) |
81 | 81 | |
82 | 82 | static void at91_update_master_clock(PMCState *s) |
83 | 83 | { |
84 | - int mck_freq = MO_FREQ; | |
84 | + int mck_freq = s->mo_freq; | |
85 | 85 | |
86 | 86 | /* Clock selection */ |
87 | 87 | switch (s->mckr & 3) { |
... | ... | @@ -128,6 +128,10 @@ static uint32_t at91_pmc_mem_read(void *opaque, target_phys_addr_t offset) |
128 | 128 | PMCState *s = opaque; |
129 | 129 | |
130 | 130 | switch (offset) { |
131 | + case PMC_PLLA: | |
132 | + return s->plla; | |
133 | + case PMC_PLLB: | |
134 | + return s->pllb; | |
131 | 135 | case PMC_SCSR: |
132 | 136 | return s->scsr; |
133 | 137 | case PMC_PCSR: |
... | ... | @@ -136,7 +140,7 @@ static uint32_t at91_pmc_mem_read(void *opaque, target_phys_addr_t offset) |
136 | 140 | return s->mor; |
137 | 141 | case PMC_MCFR: |
138 | 142 | if (s->mor & 1) |
139 | - return (1 << 16) | (MO_FREQ / SO_FREQ / 16); | |
143 | + return (1 << 16) | (s->mo_freq / SO_FREQ / 16); | |
140 | 144 | return 0; |
141 | 145 | case PMC_PCKR ... PMC_PCKR + 15: |
142 | 146 | return s->pckr[(offset - PMC_PCKR) >> 2]; |
... | ... | @@ -144,6 +148,8 @@ static uint32_t at91_pmc_mem_read(void *opaque, target_phys_addr_t offset) |
144 | 148 | return s->sr; |
145 | 149 | case PMC_IMR: |
146 | 150 | return s->imr; |
151 | + case PMC_MCKR: | |
152 | + return s->mckr; | |
147 | 153 | default: |
148 | 154 | return 0; |
149 | 155 | } |
... | ... | @@ -290,9 +296,24 @@ static void at91_pmc_init(SysBusDevice *dev) |
290 | 296 | register_savevm("at91_pmc", -1, 1, at91_pmc_save, at91_pmc_load, s); |
291 | 297 | } |
292 | 298 | |
299 | +static SysBusDeviceInfo pmc_info = { | |
300 | + .init = at91_pmc_init, | |
301 | + .qdev.name = "at91,pmc", | |
302 | + .qdev.size = sizeof(PMCState), | |
303 | + .qdev.props = (Property[]) { | |
304 | + { | |
305 | + .name = "mo_freq", | |
306 | + .info = &qdev_prop_uint32, | |
307 | + .offset = offsetof(PMCState, mo_freq), | |
308 | + .defval = (uint32_t[]) { 0 }, | |
309 | + }, | |
310 | + {/* end of list */} | |
311 | + } | |
312 | +}; | |
313 | + | |
293 | 314 | static void at91_pmc_register(void) |
294 | 315 | { |
295 | - sysbus_register_dev("at91,pmc", sizeof(PMCState), at91_pmc_init); | |
316 | + sysbus_register_withprop(&pmc_info); | |
296 | 317 | } |
297 | 318 | |
298 | 319 | device_init(at91_pmc_register) | ... | ... |
hw/at91pes.c
... | ... | @@ -81,6 +81,7 @@ static void at91pes_init(ram_addr_t ram_size, |
81 | 81 | |
82 | 82 | sysbus_create_simple("at91,dbgu", 0xFFFFF200, pic1[0]); |
83 | 83 | pmc = sysbus_create_simple("at91,pmc", 0xFFFFFC00, pic1[1]); |
84 | + qdev_prop_set_uint32(pmc, "mo_freq", 9216000); | |
84 | 85 | sysbus_create_varargs("at91,rstc", 0xFFFFFD00, NULL); |
85 | 86 | pioa = sysbus_create_simple("at91,pio", 0xFFFFF400, pic[2]); |
86 | 87 | piob = sysbus_create_simple("at91,pio", 0xFFFFF600, pic[3]); | ... | ... |