#include <mach/rk29_iomap.h>
#include <mach/cru.h>
#include <mach/pmu.h>
+#include <mach/sram.h>
+#include <mach/board.h>
-#define PWM_VCORE_120 40
-#define PWM_VCORE_125 32
-#define PWM_VCORE_130 21
-#define PWM_VCORE_135 10
-#define PWM_VCORE_140 0
-
-/* CRU PLL CON */
-#define PLL_HIGH_BAND (0x01 << 16)
-#define PLL_LOW_BAND (0x00 << 16)
-#define PLL_PD (0x01 << 15)
-
-#define PLL_CLKR(i) ((((i) - 1) & 0x1f) << 10)
-#define PLL_NR(v) ((((v) >> 10) & 0x1f) + 1)
-
-#define PLL_CLKF(i) ((((i) - 1) & 0x7f) << 3)
-#define PLL_NF(v) ((((v) >> 3) & 0x7f) + 1)
-#define PLL_NF2(v) (((((v) >> 3) & 0x7f) + 1) << 1)
-
-#define PLL_CLKOD(i) (((i) & 0x03) << 1)
-#define PLL_NO_1 PLL_CLKOD(0)
-#define PLL_NO_2 PLL_CLKOD(1)
-#define PLL_NO_4 PLL_CLKOD(2)
-#define PLL_NO_8 PLL_CLKOD(3)
-#define PLL_NO_SHIFT(v) (((v) >> 1) & 0x03)
-
-#define PLL_BYPASS (0x01)
-
-/* CRU MODE CON */
-#define CRU_CPU_MODE_MASK (0x03u << 0)
-#define CRU_CPU_MODE_SLOW (0x00u << 0)
-#define CRU_CPU_MODE_NORMAL (0x01u << 0)
-#define CRU_CPU_MODE_DSLOW (0x02u << 0)
-
-#define CRU_GENERAL_MODE_MASK (0x03u << 2)
-#define CRU_GENERAL_MODE_SLOW (0x00u << 2)
-#define CRU_GENERAL_MODE_NORMAL (0x01u << 2)
-#define CRU_GENERAL_MODE_DSLOW (0x02u << 2)
-
-#define CRU_CODEC_MODE_MASK (0x03u << 4)
-#define CRU_CODEC_MODE_SLOW (0x00u << 4)
-#define CRU_CODEC_MODE_NORMAL (0x01u << 4)
-#define CRU_CODEC_MODE_DSLOW (0x02u << 4)
-
-#define CRU_DDR_MODE_MASK (0x03u << 6)
-#define CRU_DDR_MODE_SLOW (0x00u << 6)
-#define CRU_DDR_MODE_NORMAL (0x01u << 6)
-#define CRU_DDR_MODE_DSLOW (0x02u << 6)
-
/* Clock flags */
/* bit 0 is free */
#define RATE_FIXED (1 << 1) /* Fixed clock rate */
#define CONFIG_PARTICIPANT (1 << 10) /* Fundamental clock */
-
-#define cru_readl(offset) readl(RK29_CRU_BASE + offset)
-#define cru_writel(v, offset) writel(v, RK29_CRU_BASE + offset)
-#define cru_writel_force(v, offset) do { u32 _v = v; u32 _count = 5; do { cru_writel(_v, offset); } while (cru_readl(offset) != _v && _count--); } while (0) /* huangtao: when write CRU_xPLL_CON, first time may failed, so try again. unknown why. */
+#define IS_PD (1 << 2) /* Power Domain */
#define regfile_readl(offset) readl(RK29_GRF_BASE + offset)
+#define pmu_readl(offset) readl(RK29_PMU_BASE + offset)
#define MHZ (1000*1000)
#define KHZ 1000
static void __propagate_rate(struct clk *tclk);
static struct clk codec_pll_clk;
static struct clk general_pll_clk;
+static bool has_xin27m = true;
static unsigned long clksel_recalc_div(struct clk *clk)
{
return -ENOENT;
}
+static long clksel_round_rate_div(struct clk *clk, unsigned long rate)
+{
+ u32 div;
+ unsigned long prev = ULONG_MAX, actual;
+
+ for (div = 0; div <= clk->clksel_mask; div++) {
+ actual = clk->parent->rate / (div + 1);
+ if (actual > rate)
+ prev = actual;
+ if (actual && actual <= rate) {
+ if ((prev - rate) <= (rate - actual)) {
+ actual = prev;
+ div--;
+ }
+ break;
+ }
+ }
+ if (div > clk->clksel_mask)
+ div = clk->clksel_mask;
+ pr_debug("clock %s, target rate %ld, rounded rate %ld (div %d)\n", clk->name, rate, actual, div + 1);
+
+ return actual;
+}
+
static int clksel_set_rate_shift(struct clk *clk, unsigned long rate)
{
u32 shift;
return -EINVAL;
}
+/* Work around CRU_CLKGATE3_CON bit21~20 bug */
+volatile u32 cru_clkgate3_con_mirror;
+
static int gate_mode(struct clk *clk, int on)
{
u32 reg;
reg += (idx >> 5) << 2;
idx &= 0x1F;
- v = cru_readl(reg);
- if (on) {
- v &= ~(1 << idx); // clear bit
- } else {
+ if (reg == CRU_CLKGATE3_CON)
+ v = cru_clkgate3_con_mirror;
+ else
+ v = cru_readl(reg);
+
+ if (on)
+ v &= ~(1 << idx); // clear bit
+ else
v |= (1 << idx); // set bit
- }
+
+ if (reg == CRU_CLKGATE3_CON)
+ cru_clkgate3_con_mirror = v;
cru_writel(v, reg);
return 0;
}
+/* Work around CRU_SOFTRST0_CON bit29~27 bug */
+static volatile u32 cru_softrst0_con_mirror;
+
+void cru_set_soft_reset(enum cru_soft_reset idx, bool on)
+{
+ unsigned long flags;
+ u32 reg = CRU_SOFTRST0_CON + ((idx >> 5) << 2);
+ u32 mask = 1 << (idx & 31);
+ u32 v;
+
+ if (idx >= SOFT_RST_MAX)
+ return;
+
+ local_irq_save(flags);
+
+ if (reg == CRU_SOFTRST0_CON)
+ v = cru_softrst0_con_mirror;
+ else
+ v = cru_readl(reg);
+
+ if (on)
+ v |= mask;
+ else
+ v &= ~mask;
+
+ if (reg == CRU_SOFTRST0_CON)
+ cru_softrst0_con_mirror = v;
+ cru_writel(v, reg);
+
+ local_irq_restore(flags);
+}
+
static struct clk xin24m = {
.name = "xin24m",
.rate = 24 * MHZ,
};
-static void delay_500ns(void)
+static noinline void delay_500ns(void)
{
- int delay = 2000;
- while (delay--)
- barrier();
+ if (system_state == SYSTEM_BOOTING) {
+ LOOP(LOOPS_PER_USEC * 1200 / 24);
+ } else {
+ udelay(1);
+ }
}
-static void delay_300us(void)
+static noinline void delay_300us(void)
{
- int i;
- for (i = 0; i < 600; i++)
- delay_500ns();
+ if (system_state == SYSTEM_BOOTING) {
+ LOOP(LOOPS_PER_MSEC * 1200 / 24);
+ } else {
+ mdelay(1);
+ }
+}
+
+static noinline void arm_delay_500ns(void)
+{
+ static unsigned long loops = 0;
+ if (!loops) {
+ loops = general_pll_clk.rate / MHZ;
+ loops = loops * LOOPS_PER_USEC / 24;
+ }
+ LOOP(loops);
+}
+
+static noinline void arm_delay_300us(void)
+{
+ static unsigned long loops = 0;
+ if (!loops) {
+ loops = general_pll_clk.rate / MHZ;
+ loops = loops * LOOPS_PER_MSEC / 24;
+ }
+ LOOP(loops);
}
#define GENERAL_PLL_IDX 0
#define DDR_PLL_IDX 3
#define GRF_SOC_CON0 0xbc
-static void pll_wait_lock(int pll_idx, int delay)
+static void pll_wait_lock(int pll_idx)
{
u32 bit = 0x2000000u << pll_idx;
+ int delay = 2400000;
while (delay > 0) {
if (regfile_readl(GRF_SOC_CON0) & bit)
break;
static const struct arm_pll_set arm_pll[] = {
// rate = 24 * NF / (NR * NO)
// rate NR NF NO adiv hdiv pdiv
- ARM_PLL(1200, 1, 50, 1, 41, 21, 81),
- ARM_PLL(1104, 1, 46, 1, 41, 21, 81),
- ARM_PLL(1008, 1, 42, 1, 41, 21, 81),
+ ARM_PLL(1200, 1, 50, 1, 31, 21, 81),
+ ARM_PLL(1104, 1, 46, 1, 31, 21, 81),
+ ARM_PLL(1008, 1, 42, 1, 31, 21, 81),
ARM_PLL( 912, 1, 38, 1, 31, 21, 81),
ARM_PLL( 888, 2, 74, 1, 31, 21, 81),
ARM_PLL( 816, 1, 34, 1, 31, 21, 81),
#define CORE_PARENT_ARM_PLL (0 << 23)
#define CORE_PARENT_GENERAL_PLL (1 << 23)
-#define PWM_DIV2 (0<<9)
-#define PWM_DIV4 (1<<9)
-#define PWM_DIV8 (2<<9)
-#define PWM_DIV16 (3<<9)
-#define PWM_DIV32 (4<<9)
-#define PWM_DIV64 (5<<9)
-#define PWM_DIV128 (6<<9)
-#define PWM_DIV256 (7<<9)
-#define PWM_DIV512 (8<<9)
-#define PWM_DIV1024 (9<<9)
-
-#define PWM_CAPTURE (1<<8)
-#define PWM_RESET (1<<7)
-#define PWM_INTCLR (1<<6)
-#define PWM_INTEN (1<<5)
-#define PWM_SINGLE (1<<6)
-
-#define PWM_ENABLE (1<<3)
-#define PWM_TimeEN (1)
-
-#define PWM_DIV PWM_DIV2
-
-static struct clk pclk_periph;
-static struct clk clk_pwm;
-void PWMInit(u32 nHz, u32 rate)
-{
- u32 divh;
-
- clk_enable_nolock(&clk_pwm);
- // iomux to pwm2
-#define REG_FILE_BASE_ADDR RK29_GRF_BASE
- volatile unsigned int * pGRF_GPIO2L_IOMUX = (volatile unsigned int *)(REG_FILE_BASE_ADDR + 0x58);
- *pGRF_GPIO2L_IOMUX &= ~(0x3<<6);
- *pGRF_GPIO2L_IOMUX |= (0x2<<6);
- // pwm2 clk enable
-
- // set pwm rate
-#define PWM_BASE_ADDR RK29_PWM_BASE
- volatile unsigned int * pPWM2_CTRL = (volatile unsigned int *)(PWM_BASE_ADDR + 0x2C);
- volatile unsigned int * pPWM2_LRC = (volatile unsigned int *)(PWM_BASE_ADDR + 0x28);
- volatile unsigned int * pPWM2_HRC = (volatile unsigned int *)(PWM_BASE_ADDR + 0x24);
- volatile unsigned int * pPWM2_CNTR = (volatile unsigned int *)(PWM_BASE_ADDR + 0x20);
-
-#define GPIO2_BASE_ADDR RK29_GPIO2_BASE
- volatile unsigned int *pGPIO2_DIR = (volatile unsigned int *)(GPIO2_BASE_ADDR + 0x4);
- volatile unsigned int *pGPIO2_LEVEL = (volatile unsigned int *)GPIO2_BASE_ADDR;
-
- if (rate == 0) {
- // iomux pwm2 to gpio2_a[3]
- *pGRF_GPIO2L_IOMUX &= ~(0x3<<6);
- // set gpio to low level
- *pGPIO2_DIR |= 0x1<<3;
- *pGPIO2_LEVEL &= ~(0x1<<3);
- } else {
- *pPWM2_CTRL= PWM_DIV|PWM_RESET;
- divh = pclk_periph.rate / nHz;
- divh = divh >> (1+(PWM_DIV>>9));
- *pPWM2_LRC = (divh == 0)?1:divh;
-
- divh = (*pPWM2_LRC)*rate/100;
- *pPWM2_HRC = divh?divh:1;
-
- *pPWM2_CNTR = 0x0;
- *pPWM2_CTRL = PWM_DIV|PWM_ENABLE|PWM_TimeEN;
- printk("pclk_periph %d LRC %08x HRC %08x\n", pclk_periph.rate, *pPWM2_LRC, *pPWM2_HRC);
- }
-
- int i; for (i = 0; i < 6000; i++)
- delay_500ns();
-}
-
static int arm_pll_clk_set_rate(struct clk *clk, unsigned long rate)
{
const struct arm_pll_set *ps, *pt;
pt++;
}
- PWMInit(1 * MHZ, PWM_VCORE_130); // 1.30V
-
/* make aclk safe & reparent to general pll */
cru_writel((cru_readl(CRU_CLKSEL0_CON) & ~(CORE_PARENT_MASK | CORE_ACLK_MASK)) | CORE_PARENT_GENERAL_PLL | CORE_ACLK_21, CRU_CLKSEL0_CON);
/* power down */
cru_writel(cru_readl(CRU_APLL_CON) | PLL_PD, CRU_APLL_CON);
- delay_500ns();
+ arm_delay_500ns();
cru_writel(ps->apll_con | PLL_PD, CRU_APLL_CON);
- delay_500ns();
+ arm_delay_500ns();
/* power up */
cru_writel(ps->apll_con, CRU_APLL_CON);
- delay_300us();
- pll_wait_lock(ARM_PLL_IDX, 2400000);
+ arm_delay_300us();
+ pll_wait_lock(ARM_PLL_IDX);
/* reparent to arm pll & set aclk/hclk/pclk */
cru_writel((cru_readl(CRU_CLKSEL0_CON) & ~(CORE_PARENT_MASK | CORE_ACLK_MASK | ACLK_HCLK_MASK | ACLK_PCLK_MASK)) | CORE_PARENT_ARM_PLL | ps->clksel0_con, CRU_CLKSEL0_CON);
return rate;
}
+static int ddr_pll_clk_set_rate(struct clk *clk, unsigned long rate)
+{
+ /* do nothing here */
+ return 0;
+}
+
static struct clk *ddr_pll_parents[4] = { &xin24m, &xin27m, &codec_pll_clk, &general_pll_clk };
static struct clk ddr_pll_clk = {
.name = "ddr_pll",
.parent = &xin24m,
.recalc = ddr_pll_clk_recalc,
+ .set_rate = ddr_pll_clk_set_rate,
.clksel_con = CRU_MODE_CON,
.clksel_parent_mask = 3,
.clksel_parent_shift = 13,
};
-static unsigned long codec_pll_clk_recalc(struct clk *clk)
+static int codec_pll_clk_mode(struct clk *clk, int on)
{
- unsigned long rate;
-
- if ((cru_readl(CRU_MODE_CON) & CRU_CODEC_MODE_MASK) == CRU_CODEC_MODE_NORMAL) {
- u32 v = cru_readl(CRU_CPLL_CON);
- u64 rate64 = (u64) clk->parent->rate * PLL_NF(v);
- do_div(rate64, PLL_NR(v));
- rate = rate64 >> PLL_NO_SHIFT(v);
- pr_debug("%s new clock rate is %ld (NF %d NR %d NO %d)\n", clk->name, rate, PLL_NF(v), PLL_NR(v), 1 << PLL_NO_SHIFT(v));
+ u32 cpll = cru_readl(CRU_CPLL_CON);
+ if (on) {
+ cru_writel(cpll & ~(PLL_PD | PLL_BYPASS), CRU_CPLL_CON);
+ delay_300us();
+ pll_wait_lock(CODEC_PLL_IDX);
+ cru_writel((cru_readl(CRU_MODE_CON) & ~CRU_CODEC_MODE_MASK) | CRU_CODEC_MODE_NORMAL, CRU_MODE_CON);
} else {
- rate = clk->parent->rate;
- pr_debug("%s new clock rate is %ld (slow mode)\n", clk->name, rate);
+ cru_writel((cru_readl(CRU_MODE_CON) & ~CRU_CODEC_MODE_MASK) | CRU_CODEC_MODE_SLOW, CRU_MODE_CON);
+ cru_writel(cpll | PLL_BYPASS, CRU_CPLL_CON);
+ cru_writel(cpll | PLL_PD | PLL_BYPASS, CRU_CPLL_CON);
+ delay_500ns();
}
+ return 0;
+}
+static unsigned long codec_pll_clk_recalc(struct clk *clk)
+{
+ unsigned long rate;
+ u32 v = cru_readl(CRU_CPLL_CON);
+ u64 rate64 = (u64) clk->parent->rate * PLL_NF(v);
+ do_div(rate64, PLL_NR(v));
+ rate = rate64 >> PLL_NO_SHIFT(v);
+ pr_debug("%s new clock rate is %ld (NF %d NR %d NO %d)\n", clk->name, rate, PLL_NF(v), PLL_NR(v), 1 << PLL_NO_SHIFT(v));
+ if ((cru_readl(CRU_MODE_CON) & CRU_CODEC_MODE_MASK) != CRU_CODEC_MODE_NORMAL)
+ pr_debug("%s rate is %ld (slow mode) actually\n", clk->name, clk->parent->rate);
return rate;
}
#define CODEC_PLL_PARENT_DDR_PLL (2 << 11)
#define CODEC_PLL_PARENT_GENERAL_PLL (3 << 11)
+struct codec_pll_set {
+ unsigned long rate;
+ u32 pll_con;
+ u32 parent_con;
+};
+
+#define CODEC_PLL(_khz, _parent, band, nr, nf, no) \
+{ \
+ .rate = _khz * KHZ, \
+ .pll_con = PLL_##band##_BAND | PLL_CLKR(nr) | PLL_CLKF(nf) | PLL_NO_##no, \
+ .parent_con = CODEC_PLL_PARENT_XIN##_parent##M, \
+}
+
+static const struct codec_pll_set codec_pll[] = {
+ // rate parent band NR NF NO
+ CODEC_PLL(108000, 24, LOW, 1, 18, 4), // for TV
+ CODEC_PLL(648000, 24, HIGH, 1, 27, 1),
+ CODEC_PLL(297000, 27, LOW, 1, 22, 2), // for HDMI
+ CODEC_PLL(445500, 27, LOW, 2, 33, 1),
+ CODEC_PLL(594000, 27, HIGH, 1, 22, 1),
+ CODEC_PLL(300000, 24, LOW, 1, 25, 2), // for GPU
+ CODEC_PLL(360000, 24, LOW, 1, 15, 1),
+ CODEC_PLL(408000, 24, LOW, 1, 17, 1),
+ CODEC_PLL(456000, 24, LOW, 1, 19, 1),
+ CODEC_PLL(504000, 24, LOW, 1, 21, 1),
+ CODEC_PLL(552000, 24, LOW, 1, 23, 1),
+ CODEC_PLL(600000, 24, HIGH, 1, 25, 1),
+};
+
static int codec_pll_clk_set_rate(struct clk *clk, unsigned long rate)
{
- u32 pll_con;
- u32 mode_con;
- struct clk *parent;
+ int i;
+ u32 work_mode;
- switch (rate) {
- case 108 * MHZ:
- /* 24 * 18 / 4 */
- pll_con = PLL_LOW_BAND | PLL_CLKR(1) | PLL_CLKF(18) | PLL_NO_4;
- mode_con = CODEC_PLL_PARENT_XIN24M;
- parent = &xin24m;
- break;
- case 648 * MHZ:
- /* 24 * 27 / 1 */
- pll_con = PLL_HIGH_BAND | PLL_CLKR(1) | PLL_CLKF(27) | PLL_NO_1;
- mode_con = CODEC_PLL_PARENT_XIN24M;
- parent = &xin24m;
- break;
- case 297 * MHZ:
- /* 27 * 22 / 2 */
- pll_con = PLL_LOW_BAND | PLL_CLKR(1) | PLL_CLKF(22) | PLL_NO_2;
- mode_con = CODEC_PLL_PARENT_XIN27M;
- parent = &xin27m;
- break;
- case 594 * MHZ:
- /* 27 * 22 / 1 */
- pll_con = PLL_LOW_BAND | PLL_CLKR(1) | PLL_CLKF(22) | PLL_NO_1;
- mode_con = CODEC_PLL_PARENT_XIN27M;
- parent = &xin27m;
- break;
- default:
- return -ENOENT;
- break;
+ const struct codec_pll_set *ps = NULL;
+
+ for (i = 0; i < ARRAY_SIZE(codec_pll); i++) {
+ if (codec_pll[i].rate == rate) {
+ ps = &codec_pll[i];
+ break;
+ }
}
+ if (!ps)
+ return -ENOENT;
+
+ if (!has_xin27m && ps->parent_con == CODEC_PLL_PARENT_XIN27M)
+ return -ENOENT;
+
+ work_mode = cru_readl(CRU_MODE_CON) & CRU_CODEC_MODE_MASK;
/* enter slow mode */
- cru_writel((cru_readl(CRU_MODE_CON) & ~(CRU_CODEC_MODE_MASK | CODEC_PLL_PARENT_MASK)) | CRU_CODEC_MODE_SLOW | mode_con, CRU_MODE_CON);
+ cru_writel((cru_readl(CRU_MODE_CON) & ~(CRU_CODEC_MODE_MASK | CODEC_PLL_PARENT_MASK)) | CRU_CODEC_MODE_SLOW | ps->parent_con, CRU_MODE_CON);
/* power down */
cru_writel(cru_readl(CRU_CPLL_CON) | PLL_PD, CRU_CPLL_CON);
delay_500ns();
- cru_writel(pll_con | PLL_PD, CRU_CPLL_CON);
+ cru_writel(ps->pll_con | PLL_PD, CRU_CPLL_CON);
delay_500ns();
/* power up */
- cru_writel(pll_con, CRU_CPLL_CON);
+ cru_writel(ps->pll_con, CRU_CPLL_CON);
delay_300us();
- pll_wait_lock(CODEC_PLL_IDX, 2400000);
+ pll_wait_lock(CODEC_PLL_IDX);
/* enter normal mode */
- cru_writel((cru_readl(CRU_MODE_CON) & ~CRU_CODEC_MODE_MASK) | CRU_CODEC_MODE_NORMAL, CRU_MODE_CON);
+ cru_writel((cru_readl(CRU_MODE_CON) & ~CRU_CODEC_MODE_MASK) | work_mode, CRU_MODE_CON);
- clk_set_parent_nolock(clk, parent);
+ clk_set_parent_nolock(clk, ps->parent_con == CODEC_PLL_PARENT_XIN24M ? &xin24m : &xin27m);
return 0;
}
static struct clk codec_pll_clk = {
.name = "codec_pll",
.parent = &xin24m,
+ .mode = codec_pll_clk_mode,
.recalc = codec_pll_clk_recalc,
.set_rate = codec_pll_clk_set_rate,
.clksel_con = CRU_MODE_CON,
u32 pll_con;
switch (rate) {
+ case 96 * MHZ:
+ /* 96M: low-band, NR=1, NF=16, NO=4 */
+ pll_con = PLL_LOW_BAND | PLL_CLKR(1) | PLL_CLKF(16) | PLL_NO_4;
+ break;
+ case 144*MHZ:
+ /* 96M: low-band, NR=1, NF=16, NO=4 */
+ pll_con = PLL_LOW_BAND | PLL_CLKR(1) | PLL_CLKF(24) | PLL_NO_4;
+ break;
case 288 * MHZ:
/* 288M: low-band, NR=1, NF=24, NO=2 */
pll_con = PLL_LOW_BAND | PLL_CLKR(1) | PLL_CLKF(24) | PLL_NO_2;
break;
+ case 300 * MHZ:
+ /* 300M: low-band, NR=1, NF=25, NO=2 */
+ pll_con = PLL_LOW_BAND | PLL_CLKR(1) | PLL_CLKF(25) | PLL_NO_2;
+ break;
case 624 * MHZ:
/* 624M: high-band, NR=1, NF=26, NO=1 */
pll_con = PLL_HIGH_BAND | PLL_CLKR(1) | PLL_CLKF(26) | PLL_NO_1;
cru_writel(pll_con, CRU_GPLL_CON);
delay_300us();
- pll_wait_lock(GENERAL_PLL_IDX, 2400000);
+ pll_wait_lock(GENERAL_PLL_IDX);
/* enter normal mode */
cru_writel((cru_readl(CRU_MODE_CON) & ~CRU_GENERAL_MODE_MASK) | CRU_GENERAL_MODE_NORMAL, CRU_MODE_CON);
};
+static unsigned long uhost_recalc(struct clk *clk)
+{
+ unsigned long rate = clksel_recalc_div(clk);
+ if (rate != 48 * MHZ) {
+ clksel_set_rate_div(clk, 48 * MHZ);
+ rate = clksel_recalc_div(clk);
+ }
+ return rate;
+}
+
static struct clk *clk_uhost_parents[8] = { &general_pll_clk, &ddr_pll_clk, &codec_pll_clk, &arm_pll_clk, &otgphy0_clkin, &otgphy1_clkin };
static struct clk clk_uhost = {
.name = "uhost",
.mode = gate_mode,
- .recalc = clksel_recalc_div,
+ .recalc = uhost_recalc,
.set_rate = clksel_set_rate_div,
.gate_idx = CLK_GATE_UHOST,
.clksel_con = CRU_CLKSEL1_CON,
.parents = clk_i2s_div_parents,
};
+static u32 clk_gcd(u32 numerator, u32 denominator)
+{
+ u32 a, b;
+
+ if (!numerator || !denominator)
+ return 0;
+ if (numerator > denominator) {
+ a = numerator;
+ b = denominator;
+ } else {
+ a = denominator;
+ b = numerator;
+ }
+ while (b != 0) {
+ int r = b;
+ b = a % b;
+ a = r;
+ }
+
+ return a;
+}
+
static int clk_i2s_frac_div_set_rate(struct clk *clk, unsigned long rate)
{
- u16 numerator, denominator;
+ u32 numerator, denominator;
+ u32 gcd;
- switch (rate) {
- case 8192000: /* 288*32/1125 */
- numerator = 32;
- denominator = 1125;
- break;
- case 11289600: /* 288*49/1250 */
- numerator = 49;
- denominator = 1250;
- break;
- case 12288000: /* 288*16/375 */
- numerator = 16;
- denominator = 375;
- break;
- default:
+ gcd = clk_gcd(rate, clk->parent->rate);
+ pr_debug("i2s rate=%ld,parent=%ld,gcd=%d\n", rate, clk->parent->rate, gcd);
+ if (!gcd) {
+ pr_err("gcd=0, i2s frac div is not be supported\n");
+ return -ENOENT;
+ }
+
+ numerator = rate / gcd;
+ denominator = clk->parent->rate / gcd;
+ pr_debug("i2s numerator=%d,denominator=%d,times=%d\n",
+ numerator, denominator, denominator / numerator);
+ if (numerator > 0xffff || denominator > 0xffff) {
+ pr_err("i2s can't get a available nume and deno\n");
return -ENOENT;
}
pr_debug("set clock %s to rate %ld (%d/%d)\n", clk->name, rate, numerator, denominator);
- cru_writel((u32)numerator << 16 | denominator, clk->clksel_con);
+ cru_writel(numerator << 16 | denominator, clk->clksel_con);
return 0;
}
static int i2s_set_rate(struct clk *clk, unsigned long rate)
{
- int ret;
+ int ret = 0;
struct clk *parent;
if (rate == 12 * MHZ) {
return ret;
}
if (clk->parent != parent)
- clk_set_parent_nolock(clk, parent);
+ ret = clk_set_parent_nolock(clk, parent);
return ret;
}
static int clk_uart_set_rate(struct clk *clk, unsigned long rate)
{
- int ret;
+ int ret = 0;
struct clk *parent;
struct clk *clk_div = clk->parents[0];
}
if (clk->parent != parent)
- clk_set_parent_nolock(clk, parent);
+ ret = clk_set_parent_nolock(clk, parent);
- return 0;
+ return ret;
}
static int clk_uart_frac_div_set_rate(struct clk *clk, unsigned long rate)
{
- u16 numerator, denominator;
+ u32 numerator, denominator;
+ u32 gcd;
- switch (rate) {
- case 19200*16: /* 288*2/1875 */
- numerator = 2;
- denominator = 1875;
- break;
- case 38400*16: /* 288*4/1875 */
- numerator = 4;
- denominator = 1875;
- break;
- case 57600*16: /* 288*2/625 */
- numerator = 2;
- denominator = 625;
- break;
- case 115200*16: /* 288*8/1250 */
- numerator = 8;
- denominator = 1250;
- break;
- case 230400*16: /* 288*8/625 */
- numerator = 8;
- denominator = 625;
- break;
- case 460800*16: /* 288*16/25 */
- numerator = 16;
- denominator = 625;
- break;
- case 576000*16: /* 288*20/625 */
- numerator = 20;
- denominator = 625;
- break;
- default:
+ gcd = clk_gcd(rate, clk->parent->rate);
+ pr_debug("uart rate=%ld,parent=%ld,gcd=%d\n", rate, clk->parent->rate, gcd);
+ if (!gcd) {
+ pr_err("gcd=0, uart frac div is not be supported\n");
+ return -ENOENT;
+ }
+
+ numerator = rate / gcd;
+ denominator = clk->parent->rate / gcd;
+ pr_debug("uart numerator=%d,denominator=%d,times=%d\n",
+ numerator, denominator, denominator / numerator);
+ if (numerator > 0xffff || denominator > 0xffff) {
+ pr_err("uart_frac can't get a available nume and deno\n");
return -ENOENT;
}
pr_debug("set clock %s to rate %ld (%d/%d)\n", clk->name, rate, numerator, denominator);
- cru_writel((u32)numerator << 16 | denominator, clk->clksel_con);
+ cru_writel(numerator << 16 | denominator, clk->clksel_con);
return 0;
}
+
static struct clk *clk_uart_src_parents[8] = { &general_pll_clk, &ddr_pll_clk, &codec_pll_clk, &arm_pll_clk, &otgphy0_clkin, &otgphy1_clkin };
static struct clk clk_uart01_src = {
};
+static int dclk_lcdc_div_set_rate(struct clk *clk, unsigned long rate)
+{
+ struct clk *parent;
+
+ switch (rate) {
+ case 27000 * KHZ:
+ case 74250 * KHZ:
+ case 148500 * KHZ:
+ case 297 * MHZ:
+ case 594 * MHZ:
+ parent = &codec_pll_clk;
+ break;
+ default:
+ parent = &general_pll_clk;
+ break;
+ }
+ if (clk->parent != parent)
+ clk_set_parent_nolock(clk, parent);
+
+ return clksel_set_rate_div(clk, rate);
+}
+
static struct clk *dclk_lcdc_div_parents[4] = { &codec_pll_clk, &ddr_pll_clk, &general_pll_clk, &arm_pll_clk };
static struct clk dclk_lcdc_div = {
.name = "dclk_lcdc_div",
.recalc = clksel_recalc_div,
- .set_rate = clksel_set_rate_div,
+ .set_rate = dclk_lcdc_div_set_rate,
.clksel_con = CRU_CLKSEL16_CON,
.clksel_mask = 0xFF,
.clksel_shift = 2,
.parents = dclk_lcdc_div_parents,
};
+static int dclk_lcdc_set_rate(struct clk *clk, unsigned long rate)
+{
+ int ret = 0;
+ struct clk *parent;
+
+ if (rate == 27 * MHZ && has_xin27m) {
+ parent = &xin27m;
+ } else {
+ parent = &dclk_lcdc_div;
+ ret = clk_set_rate_nolock(parent, rate);
+ if (ret)
+ return ret;
+ }
+ if (clk->parent != parent)
+ ret = clk_set_parent_nolock(clk, parent);
+
+ return ret;
+}
+
static struct clk *dclk_lcdc_parents[2] = { &dclk_lcdc_div, &xin27m };
static struct clk dclk_lcdc = {
.name = "dclk_lcdc",
.mode = gate_mode,
+ .set_rate = dclk_lcdc_set_rate,
.gate_idx = CLK_GATE_DCLK_LCDC,
.clksel_con = CRU_CLKSEL16_CON,
.clksel_parent_mask = 1,
.mode = gate_mode,
.recalc = clksel_recalc_div,
.set_rate = clksel_set_rate_div,
- .gate_idx = CLK_GAET_ACLK_VEPU,
+ .gate_idx = CLK_GATE_ACLK_VEPU,
.clksel_con = CRU_CLKSEL17_CON,
.clksel_mask = 0x1F,
.clksel_shift = 2,
.clksel_maxdiv = 4,
};
+static int clk_gpu_set_rate(struct clk *clk, unsigned long rate)
+{
+ if (clk->parent == &codec_pll_clk && rate != codec_pll_clk.rate && rate == general_pll_clk.rate) {
+ clk_set_parent_nolock(clk, &general_pll_clk);
+ } else if (clk->parent == &general_pll_clk && rate != general_pll_clk.rate) {
+ clk_set_parent_nolock(clk, &codec_pll_clk);
+ }
+ return clksel_set_rate_div(clk, clksel_round_rate_div(clk, rate));
+}
+
static struct clk clk_gpu = {
.name = "gpu",
.mode = gate_mode,
.gate_idx = CLK_GATE_GPU,
.recalc = clksel_recalc_div,
- .set_rate = clksel_set_rate_div,
+ .set_rate = clk_gpu_set_rate,
.clksel_con = CRU_CLKSEL17_CON,
.clksel_mask = 0x1F,
.clksel_shift = 16,
};
+static struct clk vip_clkin = {
+ .name = "vip_clkin",
+};
+
static struct clk *clk_vip_parents[4] = { &xin24m, &xin27m, &dclk_ebook };
-static struct clk clk_vip = {
- .name = "vip",
+static struct clk clk_vip_out = {
+ .name = "vip_out",
.mode = gate_mode,
- .gate_idx = CLK_GATE_VIP,
+ .gate_idx = CLK_GATE_VIP_OUT,
.clksel_con = CRU_CLKSEL1_CON,
.clksel_parent_mask = 3,
.clksel_parent_shift = 7,
GATE_CLK(pwm, pclk_periph, PWM);
GATE_CLK(vip_bus, aclk_cpu, VIP_BUS);
GATE_CLK(vip_matrix, clk_vip_bus, VIP_MATRIX);
-GATE_CLK(vip_input, hclk_cpu, VIP_INPUT);
+GATE_CLK(vip_input, vip_clkin, VIP_INPUT);
GATE_CLK(jtag, aclk_cpu, JTAG);
GATE_CLK(aclk_ddr_lcdc, aclk_lcdc, ACLK_DDR_LCDC);
GATE_CLK(hclk_mmc1, hclk_periph, HCLK_MMC1);
GATE_CLK(hclk_emmc, hclk_periph, HCLK_EMMC);
+
+static void __sramfunc pmu_set_power_domain_sram(enum pmu_power_domain pd, bool on)
+{
+ if (on)
+ writel(readl(RK29_PMU_BASE + PMU_PD_CON) & ~(1 << pd), RK29_PMU_BASE + PMU_PD_CON);
+ else
+ writel(readl(RK29_PMU_BASE + PMU_PD_CON) | (1 << pd), RK29_PMU_BASE + PMU_PD_CON);
+ dsb();
+
+ while (pmu_power_domain_is_on(pd) != on)
+ ;
+}
+
+static noinline void do_pmu_set_power_domain(enum pmu_power_domain pd, bool on)
+{
+ static unsigned long save_sp;
+
+ DDR_SAVE_SP(save_sp);
+ pmu_set_power_domain_sram(pd, on);
+ DDR_RESTORE_SP(save_sp);
+}
+
+void pmu_set_power_domain(enum pmu_power_domain pd, bool on)
+{
+ unsigned long flags;
+
+ mdelay(10);
+ local_irq_save(flags);
+ do_pmu_set_power_domain(pd, on);
+ local_irq_restore(flags);
+ mdelay(10);
+}
+
+static int pd_vcodec_mode(struct clk *clk, int on)
+{
+ if (on) {
+ u32 gate;
+
+ gate = cru_clkgate3_con_mirror;
+ gate |= (1 << CLK_GATE_ACLK_DDR_VEPU % 32);
+ gate &= ~((1 << CLK_GATE_ACLK_VEPU % 32)
+ | (1 << CLK_GATE_HCLK_VEPU % 32)
+ | (1 << CLK_GATE_HCLK_CPU_VCODEC % 32));
+ cru_writel(gate, CRU_CLKGATE3_CON);
+
+ pmu_set_power_domain(PD_VCODEC, true);
+
+ cru_writel(cru_clkgate3_con_mirror, CRU_CLKGATE3_CON);
+ } else {
+ pmu_set_power_domain(PD_VCODEC, false);
+ }
+
+ return 0;
+}
+
+static struct clk pd_vcodec = {
+ .name = "pd_vcodec",
+ .flags = IS_PD,
+ .mode = pd_vcodec_mode,
+ .gate_idx = PD_VCODEC,
+};
+
+static int pd_display_mode(struct clk *clk, int on)
+{
+#if 0 /* display power domain is buggy, always keep it on. */
+ if (on) {
+ u32 gate, gate2;
+
+ gate = cru_clkgate3_con_mirror;
+ gate |= (1 << CLK_GATE_ACLK_DDR_LCDC % 32);
+ gate &= ~((1 << CLK_GATE_HCLK_CPU_DISPLAY % 32)
+ | (1 << CLK_GATE_HCLK_DISP_MATRIX % 32)
+ | (1 << CLK_GATE_ACLK_DISP_MATRIX % 32)
+ | (1 << CLK_GATE_DCLK_EBOOK % 32)
+ | (1 << CLK_GATE_HCLK_EBOOK % 32)
+ | (1 << CLK_GATE_HCLK_IPP % 32)
+ | (1 << CLK_GATE_ACLK_IPP % 32)
+ | (1 << CLK_GATE_DCLK_LCDC % 32)
+ | (1 << CLK_GATE_HCLK_LCDC % 32)
+ | (1 << CLK_GATE_ACLK_LCDC % 32));
+ cru_writel(gate, CRU_CLKGATE3_CON);
+
+ gate2 = cru_readl(CRU_CLKGATE2_CON);
+ gate = gate2;
+ gate &= ~((1 << CLK_GATE_VIP_OUT % 32)
+ | (1 << CLK_GATE_VIP_SLAVE % 32)
+ | (1 << CLK_GATE_VIP_MATRIX % 32)
+ | (1 << CLK_GATE_VIP_BUS % 32));
+ cru_writel(gate, CRU_CLKGATE2_CON);
+
+ pmu_set_power_domain(PD_DISPLAY, true);
+
+ cru_writel(gate2, CRU_CLKGATE2_CON);
+ cru_writel(cru_clkgate3_con_mirror, CRU_CLKGATE3_CON);
+ } else {
+ pmu_set_power_domain(PD_DISPLAY, false);
+ }
+#endif
+
+ return 0;
+}
+
+static struct clk pd_display = {
+ .name = "pd_display",
+ .flags = IS_PD,
+ .mode = pd_display_mode,
+ .gate_idx = PD_DISPLAY,
+};
+
+static int pd_gpu_mode(struct clk *clk, int on)
+{
+ if (on) {
+ pmu_set_power_domain(PD_GPU, true);
+ } else {
+ pmu_set_power_domain(PD_GPU, false);
+ }
+
+ return 0;
+}
+
+static struct clk pd_gpu = {
+ .name = "pd_gpu",
+ .flags = IS_PD,
+ .mode = pd_gpu_mode,
+ .gate_idx = PD_GPU,
+};
+
+
#define CLK(dev, con, ck) \
{ \
.dev_id = dev, \
CLK(NULL, "otgphy0_clkin", &otgphy0_clkin),
CLK(NULL, "otgphy1_clkin", &otgphy1_clkin),
CLK(NULL, "gpsclk", &gpsclk),
+ CLK(NULL, "vip_clkin", &vip_clkin),
CLK1(12m),
CLK(NULL, "arm_pll", &arm_pll_clk),
CLK(NULL, "hclk_periph", &hclk_periph),
CLK(NULL, "pclk_periph", &pclk_periph),
- CLK1(vip),
+ CLK1(vip_out),
CLK1(otgphy0),
CLK1(otgphy1),
CLK1(uhost),
CLK1(hclk_gpu),
CLK1(hclk_cpu_vcodec),
CLK1(hclk_cpu_display),
+
+ CLK(NULL, "pd_vcodec", &pd_vcodec),
+ CLK(NULL, "pd_display", &pd_display),
+ CLK(NULL, "pd_gpu", &pd_gpu),
};
static LIST_HEAD(clocks);
return 0;
}
-static unsigned int __initdata armclk = 600 * MHZ;
+static unsigned int __initdata armclk = 300 * MHZ;
/*
* You can override arm_clk rate with armclk= cmdline option.
}
early_param("armclk", armclk_setup);
-static void __init rk29_clock_common_init(void)
+static void __init rk29_clock_common_init(unsigned long ppll_rate, unsigned long cpll_rate)
{
+ unsigned long aclk_p, hclk_p, pclk_p;
+ struct clk *aclk_vepu_parent, *aclk_vdpu_parent, *aclk_gpu_parent;
+
/* general pll */
- clk_set_rate_nolock(&general_pll_clk, 288 * MHZ);
+ switch (ppll_rate) {
+ case 96 * MHZ:
+ aclk_p = 96 * MHZ;
+ hclk_p = 48 * MHZ;
+ pclk_p = 24 * MHZ;
+ aclk_gpu_parent = aclk_vdpu_parent = aclk_vepu_parent = &codec_pll_clk;
+ break;
+ case 144 * MHZ:
+ aclk_p = 144 * MHZ;
+ hclk_p = 72 * MHZ;
+ pclk_p = 36 * MHZ;
+ aclk_gpu_parent = aclk_vdpu_parent = aclk_vepu_parent = &codec_pll_clk;
+ break;
+ default:
+ ppll_rate = 288 * MHZ;
+ case 288 * MHZ:
+ case 300 * MHZ:
+ aclk_p = ppll_rate / 2;
+ hclk_p = ppll_rate / 2;
+ pclk_p = ppll_rate / 8;
+ aclk_gpu_parent = aclk_vdpu_parent = aclk_vepu_parent = &general_pll_clk;
+ break;
+ }
+
+ clk_set_rate_nolock(&general_pll_clk, ppll_rate);
clk_set_parent_nolock(&aclk_periph, &general_pll_clk);
- clk_set_rate_nolock(&aclk_periph, 144 * MHZ);
- clk_set_rate_nolock(&hclk_periph, 144 * MHZ);
- clk_set_rate_nolock(&pclk_periph, 36 * MHZ);
+ clk_set_rate_nolock(&aclk_periph, aclk_p);
+ clk_set_rate_nolock(&hclk_periph, hclk_p);
+ clk_set_rate_nolock(&pclk_periph, pclk_p);
clk_set_parent_nolock(&clk_uhost, &general_pll_clk);
clk_set_rate_nolock(&clk_uhost, 48 * MHZ);
clk_set_parent_nolock(&clk_i2s0_div, &general_pll_clk);
clk_set_parent_nolock(&clk_i2s1_div, &general_pll_clk);
clk_set_parent_nolock(&clk_spdif_div, &general_pll_clk);
clk_set_parent_nolock(&clk_spi_src, &general_pll_clk);
+ clk_set_rate_nolock(&clk_spi0, 40 * MHZ);
+ clk_set_rate_nolock(&clk_spi1, 40 * MHZ);
clk_set_parent_nolock(&clk_mmc_src, &general_pll_clk);
clk_set_parent_nolock(&clk_uart01_src, &general_pll_clk);
clk_set_parent_nolock(&clk_uart23_src, &general_pll_clk);
clk_set_parent_nolock(&dclk_lcdc_div, &general_pll_clk);
- clk_set_parent_nolock(&aclk_lcdc, &general_pll_clk);
- clk_set_parent_nolock(&aclk_vepu, &general_pll_clk);
- clk_set_parent_nolock(&aclk_vdpu, &general_pll_clk);
- clk_set_parent_nolock(&aclk_gpu, &general_pll_clk);
clk_set_parent_nolock(&clk_mac_ref_div, &general_pll_clk);
clk_set_parent_nolock(&clk_hsadc_div, &general_pll_clk);
/* codec pll */
- clk_set_rate_nolock(&codec_pll_clk, 648 * MHZ);
+ clk_set_rate_nolock(&codec_pll_clk, cpll_rate);
clk_set_parent_nolock(&clk_gpu, &codec_pll_clk);
- clk_set_parent_nolock(&clk_mac_ref_div, &codec_pll_clk);
+
+ clk_set_parent_nolock(&aclk_lcdc, cpll_rate > ppll_rate ? &codec_pll_clk : &general_pll_clk);
/* arm pll */
clk_set_rate_nolock(&arm_pll_clk, armclk);
+
+ /*you can choose clk parent form codec pll or periph pll for following logic*/
+ clk_set_parent_nolock(&aclk_vepu, aclk_vepu_parent);
+ clk_set_rate_nolock(&aclk_vepu, 300 * MHZ);
+ clk_set_rate_nolock(&clk_aclk_ddr_vepu, 300 * MHZ);
+ clk_set_rate_nolock(&hclk_vepu, 150 * MHZ);
+ clk_set_parent_nolock(&aclk_vdpu, aclk_vdpu_parent);
+ clk_set_parent_nolock(&aclk_gpu, aclk_gpu_parent);
+ clk_set_rate_nolock(&aclk_gpu, 300 * MHZ);
}
static void __init clk_enable_init_clocks(void)
{
+ clk_enable_nolock(&hclk_cpu);
+ clk_enable_nolock(&pclk_cpu);
+ clk_enable_nolock(&hclk_periph);
+ clk_enable_nolock(&pclk_periph);
clk_enable_nolock(&clk_nandc);
clk_enable_nolock(&clk_aclk_cpu_peri);
clk_enable_nolock(&clk_aclk_ddr_peri);
clk_enable_nolock(&clk_gic);
clk_enable_nolock(&clk_dma2);
clk_enable_nolock(&clk_dma1);
-#ifdef CONFIG_DEBUG_LL
+ clk_enable_nolock(&clk_emem);
+ clk_enable_nolock(&clk_intmem);
+ clk_enable_nolock(&clk_ddr);
+ clk_enable_nolock(&clk_debug);
+ clk_enable_nolock(&clk_tpiu);
+ clk_enable_nolock(&clk_jtag);
clk_enable_nolock(&clk_uart1);
-#endif
}
static int __init clk_disable_unused(void)
struct clk *ck;
list_for_each_entry(ck, &clocks, node) {
- if (ck->usecount > 0 || ck->mode == NULL)
+ if (ck->usecount > 0 || ck->mode == NULL || (ck->flags & IS_PD))
continue;
LOCK();
clk_disable_nolock(ck);
UNLOCK();
}
- mutex_unlock(&clocks_mutex);
-
- pmu_set_power_domain(PD_VCODEC, false);
-// pmu_set_power_domain(PD_DISPLAY, false);
- pmu_set_power_domain(PD_GPU, false);
return 0;
}
-void __init rk29_clock_init(void)
+void __init rk29_clock_init2(enum periph_pll ppll_rate, enum codec_pll cpll_rate, bool _has_xin27m)
{
struct clk_lookup *lk;
+ has_xin27m = _has_xin27m;
+
+ cru_clkgate3_con_mirror = cru_readl(CRU_CLKGATE3_CON);
+ cru_softrst0_con_mirror = cru_readl(CRU_SOFTRST0_CON);
+
for (lk = clks; lk < clks + ARRAY_SIZE(clks); lk++)
clk_preinit(lk->clk);
*/
clk_disable_unused();
- rk29_clock_common_init();
+ rk29_clock_common_init(ppll_rate, cpll_rate);
- printk(KERN_INFO "Clocking rate (apll/dpll/cpll/gpll/core/aclk_cpu/hclk_cpu/pclk_cpu/aclk_periph/hclk_periph/pclk_periph): %ld/%ld/%ld/%ld/%ld/%ld/%ld/%ld/%ld/%ld/%ld MHz\n",
+ printk(KERN_INFO "Clocking rate (apll/dpll/cpll/gpll/core/aclk_cpu/hclk_cpu/pclk_cpu/aclk_periph/hclk_periph/pclk_periph): %ld/%ld/%ld/%ld/%ld/%ld/%ld/%ld/%ld/%ld/%ld MHz",
arm_pll_clk.rate / MHZ, ddr_pll_clk.rate / MHZ, codec_pll_clk.rate / MHZ, general_pll_clk.rate / MHZ, clk_core.rate / MHZ,
aclk_cpu.rate / MHZ, hclk_cpu.rate / MHZ, pclk_cpu.rate / MHZ, aclk_periph.rate / MHZ, hclk_periph.rate / MHZ, pclk_periph.rate / MHZ);
+ printk(KERN_CONT " (20110714)\n");
+}
+void __init rk29_clock_init(enum periph_pll ppll_rate)
+{
+ rk29_clock_init2(ppll_rate, codec_pll_445mhz, true);
}
#ifdef CONFIG_PROC_FS
for (i = 0; i < deep; i++)
seq_printf(s, " ");
- seq_printf(s, "%-9s ", clk->name);
+ seq_printf(s, "%-11s ", clk->name);
- if (clk->mode && (clk->gate_idx < CLK_GATE_MAX)) {
+ if (clk->flags & IS_PD) {
+ seq_printf(s, "%s ", pmu_power_domain_is_on(clk->gate_idx) ? "on " : "off");
+ }
+
+ if ((clk->mode == gate_mode) && (clk->gate_idx < CLK_GATE_MAX)) {
u32 reg;
int idx = clk->gate_idx;
u32 v;
reg += (idx >> 5) << 2;
idx &= 0x1F;
- v = cru_readl(reg) & (1 << idx);
-
+ if (reg == CRU_CLKGATE3_CON)
+ v = cru_clkgate3_con_mirror & (1 << idx);
+ else
+ v = cru_readl(reg) & (1 << idx);
+
seq_printf(s, "%s ", v ? "off" : "on ");
}
+ if (clk == &arm_pll_clk) {
+ switch (cru_readl(CRU_MODE_CON) & CRU_CPU_MODE_MASK) {
+ case CRU_CPU_MODE_SLOW: seq_printf(s, "slow "); break;
+ case CRU_CPU_MODE_NORMAL: seq_printf(s, "normal "); break;
+ case CRU_CPU_MODE_SLOW27: seq_printf(s, "slow27 "); break;
+ }
+ if (cru_readl(CRU_APLL_CON) & PLL_BYPASS) seq_printf(s, "bypass ");
+ } else if (clk == &ddr_pll_clk) {
+ switch (cru_readl(CRU_MODE_CON) & CRU_DDR_MODE_MASK) {
+ case CRU_DDR_MODE_SLOW: seq_printf(s, "slow "); break;
+ case CRU_DDR_MODE_NORMAL: seq_printf(s, "normal "); break;
+ case CRU_DDR_MODE_SLOW27: seq_printf(s, "slow27 "); break;
+ }
+ if (cru_readl(CRU_DPLL_CON) & PLL_BYPASS) seq_printf(s, "bypass ");
+ } else if (clk == &codec_pll_clk) {
+ switch (cru_readl(CRU_MODE_CON) & CRU_CODEC_MODE_MASK) {
+ case CRU_CODEC_MODE_SLOW: seq_printf(s, "slow "); break;
+ case CRU_CODEC_MODE_NORMAL: seq_printf(s, "normal "); break;
+ case CRU_CODEC_MODE_SLOW27: seq_printf(s, "slow27 "); break;
+ }
+ if (cru_readl(CRU_CPLL_CON) & PLL_BYPASS) seq_printf(s, "bypass ");
+ } else if (clk == &general_pll_clk) {
+ switch (cru_readl(CRU_MODE_CON) & CRU_GENERAL_MODE_MASK) {
+ case CRU_GENERAL_MODE_SLOW: seq_printf(s, "slow "); break;
+ case CRU_GENERAL_MODE_NORMAL: seq_printf(s, "normal "); break;
+ case CRU_GENERAL_MODE_SLOW27: seq_printf(s, "slow27 "); break;
+ }
+ if (cru_readl(CRU_GPLL_CON) & PLL_BYPASS) seq_printf(s, "bypass ");
+ }
+
if (rate >= MHZ) {
if (rate % MHZ)
seq_printf(s, "%ld.%06ld MHz", rate / MHZ, rate % MHZ);
seq_printf(s, " usecount = %d", clk->usecount);
- seq_printf(s, " parent = %s\n", clk->parent ? clk->parent->name : "NULL");
+ if (clk->parent)
+ seq_printf(s, " parent = %s", clk->parent->name);
+
+ seq_printf(s, "\n");
list_for_each_entry(ck, &clocks, node) {
if (ck->parent == clk)
}
mutex_unlock(&clocks_mutex);
- seq_printf(s, "\nRegisters:\n");
+ seq_printf(s, "\nCRU Registers:\n");
seq_printf(s, "APLL : 0x%08x\n", cru_readl(CRU_APLL_CON));
seq_printf(s, "DPLL : 0x%08x\n", cru_readl(CRU_DPLL_CON));
seq_printf(s, "CPLL : 0x%08x\n", cru_readl(CRU_CPLL_CON));
seq_printf(s, "CLKGATE1 : 0x%08x\n", cru_readl(CRU_CLKGATE1_CON));
seq_printf(s, "CLKGATE2 : 0x%08x\n", cru_readl(CRU_CLKGATE2_CON));
seq_printf(s, "CLKGATE3 : 0x%08x\n", cru_readl(CRU_CLKGATE3_CON));
+ seq_printf(s, "CLKGATE3M: 0x%08x\n", cru_clkgate3_con_mirror);
+ seq_printf(s, "SOFTRST0 : 0x%08x\n", cru_readl(CRU_SOFTRST0_CON));
+ seq_printf(s, "SOFTRST0M: 0x%08x\n", cru_softrst0_con_mirror);
+ seq_printf(s, "SOFTRST1 : 0x%08x\n", cru_readl(CRU_SOFTRST1_CON));
+ seq_printf(s, "SOFTRST2 : 0x%08x\n", cru_readl(CRU_SOFTRST2_CON));
+
+ seq_printf(s, "\nPMU Registers:\n");
+ seq_printf(s, "WAKEUP_EN0 : 0x%08x\n", pmu_readl(PMU_WAKEUP_EN0));
+ seq_printf(s, "WAKEUP_EN1 : 0x%08x\n", pmu_readl(PMU_WAKEUP_EN1));
+ seq_printf(s, "WAKEUP_EN2 : 0x%08x\n", pmu_readl(PMU_WAKEUP_EN2));
+ seq_printf(s, "PD_CON : 0x%08x\n", pmu_readl(PMU_PD_CON));
+ seq_printf(s, "MISC_CON : 0x%08x\n", pmu_readl(PMU_MISC_CON));
+ seq_printf(s, "PLL_CNT : 0x%08x\n", pmu_readl(PMU_PLL_CNT));
+ seq_printf(s, "PD_ST : 0x%08x\n", pmu_readl(PMU_PD_ST));
+ seq_printf(s, "INT_ST : 0x%08x\n", pmu_readl(PMU_INT_ST));
return 0;
}