|
@@ -30,10 +30,12 @@
|
|
|
|
|
|
#define SMSTPCR2 0xe6150138
|
|
|
#define SMSTPCR3 0xe615013c
|
|
|
+#define SMSTPCR4 0xe6150140
|
|
|
#define SMSTPCR5 0xe6150144
|
|
|
|
|
|
#define FRQCRA 0xE6150000
|
|
|
#define FRQCRB 0xE6150004
|
|
|
+#define FRQCRC 0xE61500E0
|
|
|
#define VCLKCR1 0xE6150008
|
|
|
#define VCLKCR2 0xE615000C
|
|
|
#define VCLKCR3 0xE615001C
|
|
@@ -52,6 +54,7 @@
|
|
|
#define HSICKCR 0xE615026C
|
|
|
#define M4CKCR 0xE6150098
|
|
|
#define PLLECR 0xE61500D0
|
|
|
+#define PLL0CR 0xE61500D8
|
|
|
#define PLL1CR 0xE6150028
|
|
|
#define PLL2CR 0xE615002C
|
|
|
#define PLL2SCR 0xE61501F4
|
|
@@ -177,6 +180,7 @@ static struct sh_clk_ops pll_clk_ops = {
|
|
|
.mapping = &cpg_mapping, \
|
|
|
}
|
|
|
|
|
|
+PLL_CLOCK(pll0_clk, &main_clk, pll_parent_main, 1, 20, PLL0CR, 0);
|
|
|
PLL_CLOCK(pll1_clk, &main_clk, pll_parent_main, 1, 7, PLL1CR, 1);
|
|
|
PLL_CLOCK(pll2_clk, &main_div2_clk, pll_parent_main_extal, 3, 5, PLL2CR, 2);
|
|
|
PLL_CLOCK(pll2s_clk, &main_div2_clk, pll_parent_main_extal, 3, 5, PLL2SCR, 4);
|
|
@@ -184,6 +188,157 @@ PLL_CLOCK(pll2h_clk, &main_div2_clk, pll_parent_main_extal, 3, 5, PLL2HCR, 5);
|
|
|
|
|
|
SH_FIXED_RATIO_CLK(pll1_div2_clk, pll1_clk, div2);
|
|
|
|
|
|
+static atomic_t frqcr_lock;
|
|
|
+
|
|
|
+/* Several clocks need to access FRQCRB, have to lock */
|
|
|
+static bool frqcr_kick_check(struct clk *clk)
|
|
|
+{
|
|
|
+ return !(ioread32(CPG_MAP(FRQCRB)) & BIT(31));
|
|
|
+}
|
|
|
+
|
|
|
+static int frqcr_kick_do(struct clk *clk)
|
|
|
+{
|
|
|
+ int i;
|
|
|
+
|
|
|
+ /* set KICK bit in FRQCRB to update hardware setting, check success */
|
|
|
+ iowrite32(ioread32(CPG_MAP(FRQCRB)) | BIT(31), CPG_MAP(FRQCRB));
|
|
|
+ for (i = 1000; i; i--)
|
|
|
+ if (ioread32(CPG_MAP(FRQCRB)) & BIT(31))
|
|
|
+ cpu_relax();
|
|
|
+ else
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ return -ETIMEDOUT;
|
|
|
+}
|
|
|
+
|
|
|
+static int zclk_set_rate(struct clk *clk, unsigned long rate)
|
|
|
+{
|
|
|
+ void __iomem *frqcrc;
|
|
|
+ int ret;
|
|
|
+ unsigned long step, p_rate;
|
|
|
+ u32 val;
|
|
|
+
|
|
|
+ if (!clk->parent || !__clk_get(clk->parent))
|
|
|
+ return -ENODEV;
|
|
|
+
|
|
|
+ if (!atomic_inc_and_test(&frqcr_lock) || !frqcr_kick_check(clk)) {
|
|
|
+ ret = -EBUSY;
|
|
|
+ goto done;
|
|
|
+ }
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Users are supposed to first call clk_set_rate() only with
|
|
|
+ * clk_round_rate() results. So, we don't fix wrong rates here, but
|
|
|
+ * guard against them anyway
|
|
|
+ */
|
|
|
+
|
|
|
+ p_rate = clk_get_rate(clk->parent);
|
|
|
+ if (rate == p_rate) {
|
|
|
+ val = 0;
|
|
|
+ } else {
|
|
|
+ step = DIV_ROUND_CLOSEST(p_rate, 32);
|
|
|
+
|
|
|
+ if (rate > p_rate || rate < step) {
|
|
|
+ ret = -EINVAL;
|
|
|
+ goto done;
|
|
|
+ }
|
|
|
+
|
|
|
+ val = 32 - rate / step;
|
|
|
+ }
|
|
|
+
|
|
|
+ frqcrc = clk->mapped_reg + (FRQCRC - (u32)clk->enable_reg);
|
|
|
+
|
|
|
+ iowrite32((ioread32(frqcrc) & ~(clk->div_mask << clk->enable_bit)) |
|
|
|
+ (val << clk->enable_bit), frqcrc);
|
|
|
+
|
|
|
+ ret = frqcr_kick_do(clk);
|
|
|
+
|
|
|
+done:
|
|
|
+ atomic_dec(&frqcr_lock);
|
|
|
+ __clk_put(clk->parent);
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
+static long zclk_round_rate(struct clk *clk, unsigned long rate)
|
|
|
+{
|
|
|
+ /*
|
|
|
+ * theoretical rate = parent rate * multiplier / 32,
|
|
|
+ * where 1 <= multiplier <= 32. Therefore we should do
|
|
|
+ * multiplier = rate * 32 / parent rate
|
|
|
+ * rounded rate = parent rate * multiplier / 32.
|
|
|
+ * However, multiplication before division won't fit in 32 bits, so
|
|
|
+ * we sacrifice some precision by first dividing and then multiplying.
|
|
|
+ * To find the nearest divisor we calculate both and pick up the best
|
|
|
+ * one. This avoids 64-bit arithmetics.
|
|
|
+ */
|
|
|
+ unsigned long step, mul_min, mul_max, rate_min, rate_max;
|
|
|
+
|
|
|
+ rate_max = clk_get_rate(clk->parent);
|
|
|
+
|
|
|
+ /* output freq <= parent */
|
|
|
+ if (rate >= rate_max)
|
|
|
+ return rate_max;
|
|
|
+
|
|
|
+ step = DIV_ROUND_CLOSEST(rate_max, 32);
|
|
|
+ /* output freq >= parent / 32 */
|
|
|
+ if (step >= rate)
|
|
|
+ return step;
|
|
|
+
|
|
|
+ mul_min = rate / step;
|
|
|
+ mul_max = DIV_ROUND_UP(rate, step);
|
|
|
+ rate_min = step * mul_min;
|
|
|
+ if (mul_max == mul_min)
|
|
|
+ return rate_min;
|
|
|
+
|
|
|
+ rate_max = step * mul_max;
|
|
|
+
|
|
|
+ if (rate_max - rate < rate - rate_min)
|
|
|
+ return rate_max;
|
|
|
+
|
|
|
+ return rate_min;
|
|
|
+}
|
|
|
+
|
|
|
+static unsigned long zclk_recalc(struct clk *clk)
|
|
|
+{
|
|
|
+ void __iomem *frqcrc = FRQCRC - (u32)clk->enable_reg + clk->mapped_reg;
|
|
|
+ unsigned int max = clk->div_mask + 1;
|
|
|
+ unsigned long val = ((ioread32(frqcrc) >> clk->enable_bit) &
|
|
|
+ clk->div_mask);
|
|
|
+
|
|
|
+ return DIV_ROUND_CLOSEST(clk_get_rate(clk->parent), max) *
|
|
|
+ (max - val);
|
|
|
+}
|
|
|
+
|
|
|
+static struct sh_clk_ops zclk_ops = {
|
|
|
+ .recalc = zclk_recalc,
|
|
|
+ .set_rate = zclk_set_rate,
|
|
|
+ .round_rate = zclk_round_rate,
|
|
|
+};
|
|
|
+
|
|
|
+static struct clk z_clk = {
|
|
|
+ .parent = &pll0_clk,
|
|
|
+ .div_mask = 0x1f,
|
|
|
+ .enable_bit = 8,
|
|
|
+ /* We'll need to access FRQCRB and FRQCRC */
|
|
|
+ .enable_reg = (void __iomem *)FRQCRB,
|
|
|
+ .ops = &zclk_ops,
|
|
|
+};
|
|
|
+
|
|
|
+/*
|
|
|
+ * It seems only 1/2 divider is usable in manual mode. 1/2 / 2/3
|
|
|
+ * switching is only available in auto-DVFS mode
|
|
|
+ */
|
|
|
+SH_FIXED_RATIO_CLK(pll0_div2_clk, pll0_clk, div2);
|
|
|
+
|
|
|
+static struct clk z2_clk = {
|
|
|
+ .parent = &pll0_div2_clk,
|
|
|
+ .div_mask = 0x1f,
|
|
|
+ .enable_bit = 0,
|
|
|
+ /* We'll need to access FRQCRB and FRQCRC */
|
|
|
+ .enable_reg = (void __iomem *)FRQCRB,
|
|
|
+ .ops = &zclk_ops,
|
|
|
+};
|
|
|
+
|
|
|
static struct clk *main_clks[] = {
|
|
|
&extalr_clk,
|
|
|
&extal1_clk,
|
|
@@ -195,22 +350,23 @@ static struct clk *main_clks[] = {
|
|
|
&main_div2_clk,
|
|
|
&fsiack_clk,
|
|
|
&fsibck_clk,
|
|
|
+ &pll0_clk,
|
|
|
&pll1_clk,
|
|
|
&pll1_div2_clk,
|
|
|
&pll2_clk,
|
|
|
&pll2s_clk,
|
|
|
&pll2h_clk,
|
|
|
+ &z_clk,
|
|
|
+ &pll0_div2_clk,
|
|
|
+ &z2_clk,
|
|
|
};
|
|
|
|
|
|
/* DIV4 */
|
|
|
static void div4_kick(struct clk *clk)
|
|
|
{
|
|
|
- unsigned long value;
|
|
|
-
|
|
|
- /* set KICK bit in FRQCRB to update hardware setting */
|
|
|
- value = ioread32(CPG_MAP(FRQCRB));
|
|
|
- value |= (1 << 31);
|
|
|
- iowrite32(value, CPG_MAP(FRQCRB));
|
|
|
+ if (!WARN(!atomic_inc_and_test(&frqcr_lock), "FRQCR* lock broken!\n"))
|
|
|
+ frqcr_kick_do(clk);
|
|
|
+ atomic_dec(&frqcr_lock);
|
|
|
}
|
|
|
|
|
|
static int divisors[] = { 2, 3, 4, 6, 8, 12, 16, 18, 24, 0, 36, 48, 10};
|
|
@@ -349,8 +505,10 @@ static struct clk div6_clks[DIV6_NR] = {
|
|
|
/* MSTP */
|
|
|
enum {
|
|
|
MSTP217, MSTP216, MSTP207, MSTP206, MSTP204, MSTP203,
|
|
|
- MSTP315, MSTP314, MSTP313, MSTP312, MSTP305,
|
|
|
- MSTP522,
|
|
|
+ MSTP329, MSTP323, MSTP318, MSTP317, MSTP316,
|
|
|
+ MSTP315, MSTP314, MSTP313, MSTP312, MSTP305, MSTP300,
|
|
|
+ MSTP411, MSTP410, MSTP409,
|
|
|
+ MSTP522, MSTP515,
|
|
|
MSTP_NR
|
|
|
};
|
|
|
|
|
@@ -361,12 +519,22 @@ static struct clk mstp_clks[MSTP_NR] = {
|
|
|
[MSTP207] = SH_CLK_MSTP32(&div6_clks[DIV6_MP], SMSTPCR2, 7, 0), /* SCIFB1 */
|
|
|
[MSTP216] = SH_CLK_MSTP32(&div6_clks[DIV6_MP], SMSTPCR2, 16, 0), /* SCIFB2 */
|
|
|
[MSTP217] = SH_CLK_MSTP32(&div6_clks[DIV6_MP], SMSTPCR2, 17, 0), /* SCIFB3 */
|
|
|
+ [MSTP300] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR3, 0, 0), /* IIC2 */
|
|
|
[MSTP305] = SH_CLK_MSTP32(&div6_clks[DIV6_MMC1],SMSTPCR3, 5, 0), /* MMCIF1 */
|
|
|
[MSTP312] = SH_CLK_MSTP32(&div6_clks[DIV6_SDHI2],SMSTPCR3, 12, 0), /* SDHI2 */
|
|
|
[MSTP313] = SH_CLK_MSTP32(&div6_clks[DIV6_SDHI1],SMSTPCR3, 13, 0), /* SDHI1 */
|
|
|
[MSTP314] = SH_CLK_MSTP32(&div6_clks[DIV6_SDHI0],SMSTPCR3, 14, 0), /* SDHI0 */
|
|
|
[MSTP315] = SH_CLK_MSTP32(&div6_clks[DIV6_MMC0],SMSTPCR3, 15, 0), /* MMCIF0 */
|
|
|
+ [MSTP316] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR3, 16, 0), /* IIC6 */
|
|
|
+ [MSTP317] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR3, 17, 0), /* IIC7 */
|
|
|
+ [MSTP318] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR3, 18, 0), /* IIC0 */
|
|
|
+ [MSTP323] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR3, 23, 0), /* IIC1 */
|
|
|
+ [MSTP329] = SH_CLK_MSTP32(&extalr_clk, SMSTPCR3, 29, 0), /* CMT10 */
|
|
|
+ [MSTP409] = SH_CLK_MSTP32(&main_div2_clk, SMSTPCR4, 9, 0), /* IIC5 */
|
|
|
+ [MSTP410] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR4, 10, 0), /* IIC4 */
|
|
|
+ [MSTP411] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR4, 11, 0), /* IIC3 */
|
|
|
[MSTP522] = SH_CLK_MSTP32(&extal2_clk, SMSTPCR5, 22, 0), /* Thermal */
|
|
|
+ [MSTP515] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR5, 15, 0), /* IIC8 */
|
|
|
};
|
|
|
|
|
|
static struct clk_lookup lookups[] = {
|
|
@@ -386,6 +554,9 @@ static struct clk_lookup lookups[] = {
|
|
|
CLKDEV_CON_ID("pll2s", &pll2s_clk),
|
|
|
CLKDEV_CON_ID("pll2h", &pll2h_clk),
|
|
|
|
|
|
+ /* CPU clock */
|
|
|
+ CLKDEV_DEV_ID("cpufreq-cpu0", &z_clk),
|
|
|
+
|
|
|
/* DIV6 */
|
|
|
CLKDEV_CON_ID("zb", &div6_clks[DIV6_ZB]),
|
|
|
CLKDEV_CON_ID("vck1", &div6_clks[DIV6_VCK1]),
|
|
@@ -408,6 +579,7 @@ static struct clk_lookup lookups[] = {
|
|
|
CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[MSTP216]),
|
|
|
CLKDEV_DEV_ID("sh-sci.5", &mstp_clks[MSTP217]),
|
|
|
CLKDEV_DEV_ID("rcar_thermal", &mstp_clks[MSTP522]),
|
|
|
+ CLKDEV_DEV_ID("e6520000.i2c", &mstp_clks[MSTP300]),
|
|
|
CLKDEV_DEV_ID("sh_mmcif.1", &mstp_clks[MSTP305]),
|
|
|
CLKDEV_DEV_ID("ee220000.mmcif", &mstp_clks[MSTP305]),
|
|
|
CLKDEV_DEV_ID("sh_mobile_sdhi.2", &mstp_clks[MSTP312]),
|
|
@@ -418,6 +590,15 @@ static struct clk_lookup lookups[] = {
|
|
|
CLKDEV_DEV_ID("ee100000.sdhi", &mstp_clks[MSTP314]),
|
|
|
CLKDEV_DEV_ID("sh_mmcif.0", &mstp_clks[MSTP315]),
|
|
|
CLKDEV_DEV_ID("ee200000.mmcif", &mstp_clks[MSTP315]),
|
|
|
+ CLKDEV_DEV_ID("e6550000.i2c", &mstp_clks[MSTP316]),
|
|
|
+ CLKDEV_DEV_ID("e6560000.i2c", &mstp_clks[MSTP317]),
|
|
|
+ CLKDEV_DEV_ID("e6500000.i2c", &mstp_clks[MSTP318]),
|
|
|
+ CLKDEV_DEV_ID("e6510000.i2c", &mstp_clks[MSTP323]),
|
|
|
+ CLKDEV_DEV_ID("sh_cmt.10", &mstp_clks[MSTP329]),
|
|
|
+ CLKDEV_DEV_ID("e60b0000.i2c", &mstp_clks[MSTP409]),
|
|
|
+ CLKDEV_DEV_ID("e6540000.i2c", &mstp_clks[MSTP410]),
|
|
|
+ CLKDEV_DEV_ID("e6530000.i2c", &mstp_clks[MSTP411]),
|
|
|
+ CLKDEV_DEV_ID("e6570000.i2c", &mstp_clks[MSTP515]),
|
|
|
|
|
|
/* for DT */
|
|
|
CLKDEV_DEV_ID("e61f0000.thermal", &mstp_clks[MSTP522]),
|
|
@@ -429,6 +610,8 @@ void __init r8a73a4_clock_init(void)
|
|
|
int k, ret = 0;
|
|
|
u32 ckscr;
|
|
|
|
|
|
+ atomic_set(&frqcr_lock, -1);
|
|
|
+
|
|
|
reg = ioremap_nocache(CKSCR, PAGE_SIZE);
|
|
|
BUG_ON(!reg);
|
|
|
ckscr = ioread32(reg);
|