Revision 51fec3cc hw/omap2.c
b/hw/omap2.c | ||
---|---|---|
2727 | 2727 |
|
2728 | 2728 |
uint32_t ev; |
2729 | 2729 |
uint32_t evtime[2]; |
2730 |
|
|
2731 |
int dpll_lock, apll_lock[2]; |
|
2730 | 2732 |
}; |
2731 | 2733 |
|
2732 | 2734 |
static void omap_prcm_int_update(struct omap_prcm_s *s, int dom) |
... | ... | |
2739 | 2741 |
{ |
2740 | 2742 |
struct omap_prcm_s *s = (struct omap_prcm_s *) opaque; |
2741 | 2743 |
int offset = addr - s->base; |
2744 |
uint32_t ret; |
|
2742 | 2745 |
|
2743 | 2746 |
switch (offset) { |
2744 | 2747 |
case 0x000: /* PRCM_REVISION */ |
... | ... | |
2922 | 2925 |
case 0x500: /* CM_CLKEN_PLL */ |
2923 | 2926 |
return s->clken[9]; |
2924 | 2927 |
case 0x520: /* CM_IDLEST_CKGEN */ |
2925 |
/* Core uses 32-kHz clock */
|
|
2928 |
ret = 0x0000070 | (s->apll_lock[0] << 9) | (s->apll_lock[1] << 8);
|
|
2926 | 2929 |
if (!(s->clksel[6] & 3)) |
2927 |
return 0x00000377; |
|
2928 |
/* DPLL not in lock mode, core uses ref_clk */ |
|
2929 |
if ((s->clken[9] & 3) != 3) |
|
2930 |
return 0x00000375; |
|
2931 |
/* Core uses DPLL */ |
|
2932 |
return 0x00000376; |
|
2930 |
/* Core uses 32-kHz clock */ |
|
2931 |
ret |= 3 << 0; |
|
2932 |
else if (!s->dpll_lock) |
|
2933 |
/* DPLL not locked, core uses ref_clk */ |
|
2934 |
ret |= 1 << 0; |
|
2935 |
else |
|
2936 |
/* Core uses DPLL */ |
|
2937 |
ret |= 2 << 0; |
|
2938 |
return ret; |
|
2933 | 2939 |
case 0x530: /* CM_AUTOIDLE_PLL */ |
2934 | 2940 |
return s->clkidle[5]; |
2935 | 2941 |
case 0x540: /* CM_CLKSEL1_PLL */ |
... | ... | |
2976 | 2982 |
return 0; |
2977 | 2983 |
} |
2978 | 2984 |
|
2985 |
static void omap_prcm_apll_update(struct omap_prcm_s *s) |
|
2986 |
{ |
|
2987 |
int mode[2]; |
|
2988 |
|
|
2989 |
mode[0] = (s->clken[9] >> 6) & 3; |
|
2990 |
s->apll_lock[0] = (mode[0] == 3); |
|
2991 |
mode[1] = (s->clken[9] >> 2) & 3; |
|
2992 |
s->apll_lock[1] = (mode[1] == 3); |
|
2993 |
/* TODO: update clocks */ |
|
2994 |
|
|
2995 |
if (mode[0] == 1 || mode[0] == 2 || mode[1] == 1 || mode[2] == 2) |
|
2996 |
fprintf(stderr, "%s: bad EN_54M_PLL or bad EN_96M_PLL\n", |
|
2997 |
__FUNCTION__); |
|
2998 |
} |
|
2999 |
|
|
3000 |
static void omap_prcm_dpll_update(struct omap_prcm_s *s) |
|
3001 |
{ |
|
3002 |
omap_clk dpll = omap_findclk(s->mpu, "dpll"); |
|
3003 |
omap_clk dpll_x2 = omap_findclk(s->mpu, "dpll"); |
|
3004 |
omap_clk core = omap_findclk(s->mpu, "core_clk"); |
|
3005 |
int mode = (s->clken[9] >> 0) & 3; |
|
3006 |
int mult, div; |
|
3007 |
|
|
3008 |
mult = (s->clksel[5] >> 12) & 0x3ff; |
|
3009 |
div = (s->clksel[5] >> 8) & 0xf; |
|
3010 |
if (mult == 0 || mult == 1) |
|
3011 |
mode = 1; /* Bypass */ |
|
3012 |
|
|
3013 |
s->dpll_lock = 0; |
|
3014 |
switch (mode) { |
|
3015 |
case 0: |
|
3016 |
fprintf(stderr, "%s: bad EN_DPLL\n", __FUNCTION__); |
|
3017 |
break; |
|
3018 |
case 1: /* Low-power bypass mode (Default) */ |
|
3019 |
case 2: /* Fast-relock bypass mode */ |
|
3020 |
omap_clk_setrate(dpll, 1, 1); |
|
3021 |
omap_clk_setrate(dpll_x2, 1, 1); |
|
3022 |
break; |
|
3023 |
case 3: /* Lock mode */ |
|
3024 |
s->dpll_lock = 1; /* After 20 FINT cycles (ref_clk / (div + 1)). */ |
|
3025 |
|
|
3026 |
omap_clk_setrate(dpll, div + 1, mult); |
|
3027 |
omap_clk_setrate(dpll_x2, div + 1, mult * 2); |
|
3028 |
break; |
|
3029 |
} |
|
3030 |
|
|
3031 |
switch ((s->clksel[6] >> 0) & 3) { |
|
3032 |
case 0: |
|
3033 |
omap_clk_reparent(core, omap_findclk(s->mpu, "clk32-kHz")); |
|
3034 |
break; |
|
3035 |
case 1: |
|
3036 |
omap_clk_reparent(core, dpll); |
|
3037 |
break; |
|
3038 |
case 2: |
|
3039 |
/* Default */ |
|
3040 |
omap_clk_reparent(core, dpll_x2); |
|
3041 |
break; |
|
3042 |
case 3: |
|
3043 |
fprintf(stderr, "%s: bad CORE_CLK_SRC\n", __FUNCTION__); |
|
3044 |
break; |
|
3045 |
} |
|
3046 |
} |
|
3047 |
|
|
2979 | 3048 |
static void omap_prcm_write(void *opaque, target_phys_addr_t addr, |
2980 | 3049 |
uint32_t value) |
2981 | 3050 |
{ |
... | ... | |
3235 | 3304 |
break; |
3236 | 3305 |
|
3237 | 3306 |
case 0x500: /* CM_CLKEN_PLL */ |
3238 |
s->clken[9] = value & 0xcf; |
|
3239 |
/* TODO update clocks */ |
|
3307 |
if (value & 0xffffff30) |
|
3308 |
fprintf(stderr, "%s: write 0s in CM_CLKEN_PLL for " |
|
3309 |
"future compatiblity\n", __FUNCTION__); |
|
3310 |
if ((s->clken[9] ^ value) & 0xcc) { |
|
3311 |
s->clken[9] &= ~0xcc; |
|
3312 |
s->clken[9] |= value & 0xcc; |
|
3313 |
omap_prcm_apll_update(s); |
|
3314 |
} |
|
3315 |
if ((s->clken[9] ^ value) & 3) { |
|
3316 |
s->clken[9] &= ~3; |
|
3317 |
s->clken[9] |= value & 3; |
|
3318 |
omap_prcm_dpll_update(s); |
|
3319 |
} |
|
3240 | 3320 |
break; |
3241 | 3321 |
case 0x530: /* CM_AUTOIDLE_PLL */ |
3242 | 3322 |
s->clkidle[5] = value & 0x000000cf; |
3243 | 3323 |
/* TODO update clocks */ |
3244 | 3324 |
break; |
3245 | 3325 |
case 0x540: /* CM_CLKSEL1_PLL */ |
3326 |
if (value & 0xfc4000d7) |
|
3327 |
fprintf(stderr, "%s: write 0s in CM_CLKSEL1_PLL for " |
|
3328 |
"future compatiblity\n", __FUNCTION__); |
|
3329 |
if ((s->clksel[5] ^ value) & 0x003fff00) { |
|
3330 |
s->clksel[5] = value & 0x03bfff28; |
|
3331 |
omap_prcm_dpll_update(s); |
|
3332 |
} |
|
3333 |
/* TODO update the other clocks */ |
|
3334 |
|
|
3246 | 3335 |
s->clksel[5] = value & 0x03bfff28; |
3247 |
/* TODO update clocks */ |
|
3248 | 3336 |
break; |
3249 | 3337 |
case 0x544: /* CM_CLKSEL2_PLL */ |
3250 |
s->clksel[6] = value & 3; |
|
3251 |
/* TODO update clocks */ |
|
3338 |
if (value & ~3) |
|
3339 |
fprintf(stderr, "%s: write 0s in CM_CLKSEL2_PLL[31:2] for " |
|
3340 |
"future compatiblity\n", __FUNCTION__); |
|
3341 |
if (s->clksel[6] != (value & 3)) { |
|
3342 |
s->clksel[6] = value & 3; |
|
3343 |
omap_prcm_dpll_update(s); |
|
3344 |
} |
|
3252 | 3345 |
break; |
3253 | 3346 |
|
3254 | 3347 |
case 0x800: /* CM_FCLKEN_DSP */ |
... | ... | |
3373 | 3466 |
s->power[3] = 0x14; |
3374 | 3467 |
s->rstctrl[0] = 1; |
3375 | 3468 |
s->rst[3] = 1; |
3469 |
omap_prcm_apll_update(s); |
|
3470 |
omap_prcm_dpll_update(s); |
|
3376 | 3471 |
} |
3377 | 3472 |
|
3378 | 3473 |
static void omap_prcm_coldreset(struct omap_prcm_s *s) |
Also available in: Unified diff