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]); | ... | ... |