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