Commit f5470d2b4740ea5f99a581375d60fd19cb74657d

Authored by Evgeniy Dushistov
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]);
... ...