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