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,7 +55,6 @@ | ||
55 | #define SR_PCK3RDY 0x800 | 55 | #define SR_PCK3RDY 0x800 |
56 | 56 | ||
57 | #define SO_FREQ 32768 | 57 | #define SO_FREQ 32768 |
58 | -#define MO_FREQ 9216000 | ||
59 | 58 | ||
60 | int at91_master_clock_frequency = SO_FREQ; | 59 | int at91_master_clock_frequency = SO_FREQ; |
61 | 60 | ||
@@ -72,6 +71,7 @@ typedef struct PMCState { | @@ -72,6 +71,7 @@ typedef struct PMCState { | ||
72 | uint32_t sr; | 71 | uint32_t sr; |
73 | uint32_t imr; | 72 | uint32_t imr; |
74 | uint32_t mck_freq; | 73 | uint32_t mck_freq; |
74 | + uint32_t mo_freq; | ||
75 | } PMCState; | 75 | } PMCState; |
76 | 76 | ||
77 | static void at91_pmc_update_irq(PMCState *s) | 77 | static void at91_pmc_update_irq(PMCState *s) |
@@ -81,7 +81,7 @@ static void at91_pmc_update_irq(PMCState *s) | @@ -81,7 +81,7 @@ static void at91_pmc_update_irq(PMCState *s) | ||
81 | 81 | ||
82 | static void at91_update_master_clock(PMCState *s) | 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 | /* Clock selection */ | 86 | /* Clock selection */ |
87 | switch (s->mckr & 3) { | 87 | switch (s->mckr & 3) { |
@@ -128,6 +128,10 @@ static uint32_t at91_pmc_mem_read(void *opaque, target_phys_addr_t offset) | @@ -128,6 +128,10 @@ static uint32_t at91_pmc_mem_read(void *opaque, target_phys_addr_t offset) | ||
128 | PMCState *s = opaque; | 128 | PMCState *s = opaque; |
129 | 129 | ||
130 | switch (offset) { | 130 | switch (offset) { |
131 | + case PMC_PLLA: | ||
132 | + return s->plla; | ||
133 | + case PMC_PLLB: | ||
134 | + return s->pllb; | ||
131 | case PMC_SCSR: | 135 | case PMC_SCSR: |
132 | return s->scsr; | 136 | return s->scsr; |
133 | case PMC_PCSR: | 137 | case PMC_PCSR: |
@@ -136,7 +140,7 @@ static uint32_t at91_pmc_mem_read(void *opaque, target_phys_addr_t offset) | @@ -136,7 +140,7 @@ static uint32_t at91_pmc_mem_read(void *opaque, target_phys_addr_t offset) | ||
136 | return s->mor; | 140 | return s->mor; |
137 | case PMC_MCFR: | 141 | case PMC_MCFR: |
138 | if (s->mor & 1) | 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 | return 0; | 144 | return 0; |
141 | case PMC_PCKR ... PMC_PCKR + 15: | 145 | case PMC_PCKR ... PMC_PCKR + 15: |
142 | return s->pckr[(offset - PMC_PCKR) >> 2]; | 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,6 +148,8 @@ static uint32_t at91_pmc_mem_read(void *opaque, target_phys_addr_t offset) | ||
144 | return s->sr; | 148 | return s->sr; |
145 | case PMC_IMR: | 149 | case PMC_IMR: |
146 | return s->imr; | 150 | return s->imr; |
151 | + case PMC_MCKR: | ||
152 | + return s->mckr; | ||
147 | default: | 153 | default: |
148 | return 0; | 154 | return 0; |
149 | } | 155 | } |
@@ -290,9 +296,24 @@ static void at91_pmc_init(SysBusDevice *dev) | @@ -290,9 +296,24 @@ static void at91_pmc_init(SysBusDevice *dev) | ||
290 | register_savevm("at91_pmc", -1, 1, at91_pmc_save, at91_pmc_load, s); | 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 | static void at91_pmc_register(void) | 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 | device_init(at91_pmc_register) | 319 | device_init(at91_pmc_register) |
hw/at91pes.c
@@ -81,6 +81,7 @@ static void at91pes_init(ram_addr_t ram_size, | @@ -81,6 +81,7 @@ static void at91pes_init(ram_addr_t ram_size, | ||
81 | 81 | ||
82 | sysbus_create_simple("at91,dbgu", 0xFFFFF200, pic1[0]); | 82 | sysbus_create_simple("at91,dbgu", 0xFFFFF200, pic1[0]); |
83 | pmc = sysbus_create_simple("at91,pmc", 0xFFFFFC00, pic1[1]); | 83 | pmc = sysbus_create_simple("at91,pmc", 0xFFFFFC00, pic1[1]); |
84 | + qdev_prop_set_uint32(pmc, "mo_freq", 9216000); | ||
84 | sysbus_create_varargs("at91,rstc", 0xFFFFFD00, NULL); | 85 | sysbus_create_varargs("at91,rstc", 0xFFFFFD00, NULL); |
85 | pioa = sysbus_create_simple("at91,pio", 0xFFFFF400, pic[2]); | 86 | pioa = sysbus_create_simple("at91,pio", 0xFFFFF400, pic[2]); |
86 | piob = sysbus_create_simple("at91,pio", 0xFFFFF600, pic[3]); | 87 | piob = sysbus_create_simple("at91,pio", 0xFFFFF600, pic[3]); |