mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-26 02:39:48 +00:00
- clock phase setting capability for the rk3288 mmc clocks
- pll init to allow syncing to actual rate table values - some more exported clocks - fixes for some clocks (typos etc) all of them not yet used in actual drivers -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQEcBAABCAAGBQJUd7jIAAoJEPOmecmc0R2BrOkIAJpMe0tqHxtcN1fBSS2rS3/b bgcu37WfGXt1FkBkGPyoVfy0m6tQ9hHx07o62IowVvaWzmvoQppLmC20+y6gKVMj nVGlhbfhZ3bDJBbsbWAyzQvH+fJx+pOTIGQJCCNX/aixSYnfvda/FP0u7EVrY4W/ mF/b5mPmHhah9EeyuAwy4eAT5xCCER5DqR9eryObDwj3N9cUluM9BiK1JWXXWdYt i/p3NS+MEjFG2KrLB+Rzu39yFRsjF8IOBKuYNh752NVcsNy2CuxqbDSpn8NM2niW bxW07X5J8JSpecpuzJmkuOomauE+4pKXMM3W+XL+XO8iF3h9inXXp0nzX31cQRI= =st2A -----END PGP SIGNATURE----- Merge tag 'v3.19-rockchip-clk2' of git://git.kernel.org/pub/scm/linux/kernel/git/mmind/linux-rockchip into clk-next - clock phase setting capability for the rk3288 mmc clocks - pll init to allow syncing to actual rate table values - some more exported clocks - fixes for some clocks (typos etc) all of them not yet used in actual drivers
This commit is contained in:
commit
b572b5f821
8 changed files with 315 additions and 50 deletions
|
@ -6,6 +6,7 @@ obj-y += clk-rockchip.o
|
|||
obj-y += clk.o
|
||||
obj-y += clk-pll.o
|
||||
obj-y += clk-cpu.o
|
||||
obj-y += clk-mmc-phase.o
|
||||
obj-$(CONFIG_RESET_CONTROLLER) += softrst.o
|
||||
|
||||
obj-y += clk-rk3188.o
|
||||
|
|
154
drivers/clk/rockchip/clk-mmc-phase.c
Normal file
154
drivers/clk/rockchip/clk-mmc-phase.c
Normal file
|
@ -0,0 +1,154 @@
|
|||
/*
|
||||
* Copyright 2014 Google, Inc
|
||||
* Author: Alexandru M Stan <amstan@chromium.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/slab.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include "clk.h"
|
||||
|
||||
struct rockchip_mmc_clock {
|
||||
struct clk_hw hw;
|
||||
void __iomem *reg;
|
||||
int id;
|
||||
int shift;
|
||||
};
|
||||
|
||||
#define to_mmc_clock(_hw) container_of(_hw, struct rockchip_mmc_clock, hw)
|
||||
|
||||
#define RK3288_MMC_CLKGEN_DIV 2
|
||||
|
||||
static unsigned long rockchip_mmc_recalc(struct clk_hw *hw,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
return parent_rate / RK3288_MMC_CLKGEN_DIV;
|
||||
}
|
||||
|
||||
#define ROCKCHIP_MMC_DELAY_SEL BIT(10)
|
||||
#define ROCKCHIP_MMC_DEGREE_MASK 0x3
|
||||
#define ROCKCHIP_MMC_DELAYNUM_OFFSET 2
|
||||
#define ROCKCHIP_MMC_DELAYNUM_MASK (0xff << ROCKCHIP_MMC_DELAYNUM_OFFSET)
|
||||
|
||||
#define PSECS_PER_SEC 1000000000000LL
|
||||
|
||||
/*
|
||||
* Each fine delay is between 40ps-80ps. Assume each fine delay is 60ps to
|
||||
* simplify calculations. So 45degs could be anywhere between 33deg and 66deg.
|
||||
*/
|
||||
#define ROCKCHIP_MMC_DELAY_ELEMENT_PSEC 60
|
||||
|
||||
static int rockchip_mmc_get_phase(struct clk_hw *hw)
|
||||
{
|
||||
struct rockchip_mmc_clock *mmc_clock = to_mmc_clock(hw);
|
||||
unsigned long rate = clk_get_rate(hw->clk);
|
||||
u32 raw_value;
|
||||
u16 degrees;
|
||||
u32 delay_num = 0;
|
||||
|
||||
raw_value = readl(mmc_clock->reg) >> (mmc_clock->shift);
|
||||
|
||||
degrees = (raw_value & ROCKCHIP_MMC_DEGREE_MASK) * 90;
|
||||
|
||||
if (raw_value & ROCKCHIP_MMC_DELAY_SEL) {
|
||||
/* degrees/delaynum * 10000 */
|
||||
unsigned long factor = (ROCKCHIP_MMC_DELAY_ELEMENT_PSEC / 10) *
|
||||
36 * (rate / 1000000);
|
||||
|
||||
delay_num = (raw_value & ROCKCHIP_MMC_DELAYNUM_MASK);
|
||||
delay_num >>= ROCKCHIP_MMC_DELAYNUM_OFFSET;
|
||||
degrees += delay_num * factor / 10000;
|
||||
}
|
||||
|
||||
return degrees % 360;
|
||||
}
|
||||
|
||||
static int rockchip_mmc_set_phase(struct clk_hw *hw, int degrees)
|
||||
{
|
||||
struct rockchip_mmc_clock *mmc_clock = to_mmc_clock(hw);
|
||||
unsigned long rate = clk_get_rate(hw->clk);
|
||||
u8 nineties, remainder;
|
||||
u8 delay_num;
|
||||
u32 raw_value;
|
||||
u64 delay;
|
||||
|
||||
/* allow 22 to be 22.5 */
|
||||
degrees++;
|
||||
/* floor to 22.5 increment */
|
||||
degrees -= ((degrees) * 10 % 225) / 10;
|
||||
|
||||
nineties = degrees / 90;
|
||||
/* 22.5 multiples */
|
||||
remainder = (degrees % 90) / 22;
|
||||
|
||||
delay = PSECS_PER_SEC;
|
||||
do_div(delay, rate);
|
||||
/* / 360 / 22.5 */
|
||||
do_div(delay, 16);
|
||||
do_div(delay, ROCKCHIP_MMC_DELAY_ELEMENT_PSEC);
|
||||
|
||||
delay *= remainder;
|
||||
delay_num = (u8) min(delay, 255ULL);
|
||||
|
||||
raw_value = delay_num ? ROCKCHIP_MMC_DELAY_SEL : 0;
|
||||
raw_value |= delay_num << ROCKCHIP_MMC_DELAYNUM_OFFSET;
|
||||
raw_value |= nineties;
|
||||
writel(HIWORD_UPDATE(raw_value, 0x07ff, mmc_clock->shift), mmc_clock->reg);
|
||||
|
||||
pr_debug("%s->set_phase(%d) delay_nums=%u reg[0x%p]=0x%03x actual_degrees=%d\n",
|
||||
__clk_get_name(hw->clk), degrees, delay_num,
|
||||
mmc_clock->reg, raw_value>>(mmc_clock->shift),
|
||||
rockchip_mmc_get_phase(hw)
|
||||
);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct clk_ops rockchip_mmc_clk_ops = {
|
||||
.recalc_rate = rockchip_mmc_recalc,
|
||||
.get_phase = rockchip_mmc_get_phase,
|
||||
.set_phase = rockchip_mmc_set_phase,
|
||||
};
|
||||
|
||||
struct clk *rockchip_clk_register_mmc(const char *name,
|
||||
const char **parent_names, u8 num_parents,
|
||||
void __iomem *reg, int shift)
|
||||
{
|
||||
struct clk_init_data init;
|
||||
struct rockchip_mmc_clock *mmc_clock;
|
||||
struct clk *clk;
|
||||
|
||||
mmc_clock = kmalloc(sizeof(*mmc_clock), GFP_KERNEL);
|
||||
if (!mmc_clock)
|
||||
return NULL;
|
||||
|
||||
init.num_parents = num_parents;
|
||||
init.parent_names = parent_names;
|
||||
init.ops = &rockchip_mmc_clk_ops;
|
||||
|
||||
mmc_clock->hw.init = &init;
|
||||
mmc_clock->reg = reg;
|
||||
mmc_clock->shift = shift;
|
||||
|
||||
if (name)
|
||||
init.name = name;
|
||||
|
||||
clk = clk_register(NULL, &mmc_clock->hw);
|
||||
if (IS_ERR(clk))
|
||||
goto err_free;
|
||||
|
||||
return clk;
|
||||
|
||||
err_free:
|
||||
kfree(mmc_clock);
|
||||
return NULL;
|
||||
}
|
|
@ -39,6 +39,7 @@ struct rockchip_clk_pll {
|
|||
int lock_offset;
|
||||
unsigned int lock_shift;
|
||||
enum rockchip_pll_type type;
|
||||
u8 flags;
|
||||
const struct rockchip_pll_rate_table *rate_table;
|
||||
unsigned int rate_count;
|
||||
spinlock_t *lock;
|
||||
|
@ -257,6 +258,55 @@ static int rockchip_rk3066_pll_is_enabled(struct clk_hw *hw)
|
|||
return !(pllcon & RK3066_PLLCON3_PWRDOWN);
|
||||
}
|
||||
|
||||
static void rockchip_rk3066_pll_init(struct clk_hw *hw)
|
||||
{
|
||||
struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
|
||||
const struct rockchip_pll_rate_table *rate;
|
||||
unsigned int nf, nr, no, bwadj;
|
||||
unsigned long drate;
|
||||
u32 pllcon;
|
||||
|
||||
if (!(pll->flags & ROCKCHIP_PLL_SYNC_RATE))
|
||||
return;
|
||||
|
||||
drate = __clk_get_rate(hw->clk);
|
||||
rate = rockchip_get_pll_settings(pll, drate);
|
||||
|
||||
/* when no rate setting for the current rate, rely on clk_set_rate */
|
||||
if (!rate)
|
||||
return;
|
||||
|
||||
pllcon = readl_relaxed(pll->reg_base + RK3066_PLLCON(0));
|
||||
nr = ((pllcon >> RK3066_PLLCON0_NR_SHIFT) & RK3066_PLLCON0_NR_MASK) + 1;
|
||||
no = ((pllcon >> RK3066_PLLCON0_OD_SHIFT) & RK3066_PLLCON0_OD_MASK) + 1;
|
||||
|
||||
pllcon = readl_relaxed(pll->reg_base + RK3066_PLLCON(1));
|
||||
nf = ((pllcon >> RK3066_PLLCON1_NF_SHIFT) & RK3066_PLLCON1_NF_MASK) + 1;
|
||||
|
||||
pllcon = readl_relaxed(pll->reg_base + RK3066_PLLCON(2));
|
||||
bwadj = (pllcon >> RK3066_PLLCON2_BWADJ_SHIFT) & RK3066_PLLCON2_BWADJ_MASK;
|
||||
|
||||
pr_debug("%s: pll %s@%lu: nr (%d:%d); no (%d:%d); nf(%d:%d), bwadj(%d:%d)\n",
|
||||
__func__, __clk_get_name(hw->clk), drate, rate->nr, nr,
|
||||
rate->no, no, rate->nf, nf, rate->bwadj, bwadj);
|
||||
if (rate->nr != nr || rate->no != no || rate->nf != nf
|
||||
|| rate->bwadj != bwadj) {
|
||||
struct clk *parent = __clk_get_parent(hw->clk);
|
||||
unsigned long prate;
|
||||
|
||||
if (!parent) {
|
||||
pr_warn("%s: parent of %s not available\n",
|
||||
__func__, __clk_get_name(hw->clk));
|
||||
return;
|
||||
}
|
||||
|
||||
pr_debug("%s: pll %s: rate params do not match rate table, adjusting\n",
|
||||
__func__, __clk_get_name(hw->clk));
|
||||
prate = __clk_get_rate(parent);
|
||||
rockchip_rk3066_pll_set_rate(hw, drate, prate);
|
||||
}
|
||||
}
|
||||
|
||||
static const struct clk_ops rockchip_rk3066_pll_clk_norate_ops = {
|
||||
.recalc_rate = rockchip_rk3066_pll_recalc_rate,
|
||||
.enable = rockchip_rk3066_pll_enable,
|
||||
|
@ -271,6 +321,7 @@ static const struct clk_ops rockchip_rk3066_pll_clk_ops = {
|
|||
.enable = rockchip_rk3066_pll_enable,
|
||||
.disable = rockchip_rk3066_pll_disable,
|
||||
.is_enabled = rockchip_rk3066_pll_is_enabled,
|
||||
.init = rockchip_rk3066_pll_init,
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -282,7 +333,7 @@ struct clk *rockchip_clk_register_pll(enum rockchip_pll_type pll_type,
|
|||
void __iomem *base, int con_offset, int grf_lock_offset,
|
||||
int lock_shift, int mode_offset, int mode_shift,
|
||||
struct rockchip_pll_rate_table *rate_table,
|
||||
spinlock_t *lock)
|
||||
u8 clk_pll_flags, spinlock_t *lock)
|
||||
{
|
||||
const char *pll_parents[3];
|
||||
struct clk_init_data init;
|
||||
|
@ -345,8 +396,22 @@ struct clk *rockchip_clk_register_pll(enum rockchip_pll_type pll_type,
|
|||
pll->reg_base = base + con_offset;
|
||||
pll->lock_offset = grf_lock_offset;
|
||||
pll->lock_shift = lock_shift;
|
||||
pll->flags = clk_pll_flags;
|
||||
pll->lock = lock;
|
||||
|
||||
/* create the mux on top of the real pll */
|
||||
pll->pll_mux_ops = &clk_mux_ops;
|
||||
pll_mux = &pll->pll_mux;
|
||||
pll_mux->reg = base + mode_offset;
|
||||
pll_mux->shift = mode_shift;
|
||||
pll_mux->mask = PLL_MODE_MASK;
|
||||
pll_mux->flags = 0;
|
||||
pll_mux->lock = lock;
|
||||
pll_mux->hw.init = &init;
|
||||
|
||||
if (pll_type == pll_rk3066)
|
||||
pll_mux->flags |= CLK_MUX_HIWORD_MASK;
|
||||
|
||||
pll_clk = clk_register(NULL, &pll->hw);
|
||||
if (IS_ERR(pll_clk)) {
|
||||
pr_err("%s: failed to register pll clock %s : %ld\n",
|
||||
|
@ -355,10 +420,6 @@ struct clk *rockchip_clk_register_pll(enum rockchip_pll_type pll_type,
|
|||
goto err_pll;
|
||||
}
|
||||
|
||||
/* create the mux on top of the real pll */
|
||||
pll->pll_mux_ops = &clk_mux_ops;
|
||||
pll_mux = &pll->pll_mux;
|
||||
|
||||
/* the actual muxing is xin24m, pll-output, xin32k */
|
||||
pll_parents[0] = parent_names[0];
|
||||
pll_parents[1] = pll_name;
|
||||
|
@ -370,16 +431,6 @@ struct clk *rockchip_clk_register_pll(enum rockchip_pll_type pll_type,
|
|||
init.parent_names = pll_parents;
|
||||
init.num_parents = ARRAY_SIZE(pll_parents);
|
||||
|
||||
pll_mux->reg = base + mode_offset;
|
||||
pll_mux->shift = mode_shift;
|
||||
pll_mux->mask = PLL_MODE_MASK;
|
||||
pll_mux->flags = 0;
|
||||
pll_mux->lock = lock;
|
||||
pll_mux->hw.init = &init;
|
||||
|
||||
if (pll_type == pll_rk3066)
|
||||
pll_mux->flags |= CLK_MUX_HIWORD_MASK;
|
||||
|
||||
mux_clk = clk_register(NULL, &pll_mux->hw);
|
||||
if (IS_ERR(mux_clk))
|
||||
goto err_mux;
|
||||
|
|
|
@ -212,13 +212,13 @@ PNAME(mux_sclk_macref_p) = { "mac_src", "ext_rmii" };
|
|||
|
||||
static struct rockchip_pll_clock rk3188_pll_clks[] __initdata = {
|
||||
[apll] = PLL(pll_rk3066, PLL_APLL, "apll", mux_pll_p, 0, RK2928_PLL_CON(0),
|
||||
RK2928_MODE_CON, 0, 6, rk3188_pll_rates),
|
||||
RK2928_MODE_CON, 0, 6, 0, rk3188_pll_rates),
|
||||
[dpll] = PLL(pll_rk3066, PLL_DPLL, "dpll", mux_pll_p, 0, RK2928_PLL_CON(4),
|
||||
RK2928_MODE_CON, 4, 5, NULL),
|
||||
RK2928_MODE_CON, 4, 5, 0, NULL),
|
||||
[cpll] = PLL(pll_rk3066, PLL_CPLL, "cpll", mux_pll_p, 0, RK2928_PLL_CON(8),
|
||||
RK2928_MODE_CON, 8, 7, rk3188_pll_rates),
|
||||
RK2928_MODE_CON, 8, 7, ROCKCHIP_PLL_SYNC_RATE, rk3188_pll_rates),
|
||||
[gpll] = PLL(pll_rk3066, PLL_GPLL, "gpll", mux_pll_p, 0, RK2928_PLL_CON(12),
|
||||
RK2928_MODE_CON, 12, 8, rk3188_pll_rates),
|
||||
RK2928_MODE_CON, 12, 8, ROCKCHIP_PLL_SYNC_RATE, rk3188_pll_rates),
|
||||
};
|
||||
|
||||
#define MFLAGS CLK_MUX_HIWORD_MASK
|
||||
|
@ -330,6 +330,15 @@ static struct rockchip_clk_branch common_clk_branches[] __initdata = {
|
|||
RK2928_CLKSEL_CON(24), 8, 8, DFLAGS,
|
||||
RK2928_CLKGATE_CON(2), 8, GFLAGS),
|
||||
|
||||
COMPOSITE_NOMUX(0, "spdif_pre", "i2s_src", 0,
|
||||
RK2928_CLKSEL_CON(5), 0, 7, DFLAGS,
|
||||
RK2928_CLKGATE_CON(0), 13, GFLAGS),
|
||||
COMPOSITE_FRAC(0, "spdif_frac", "spdif_pll", 0,
|
||||
RK2928_CLKSEL_CON(9), 0,
|
||||
RK2928_CLKGATE_CON(0), 14, GFLAGS),
|
||||
MUX(SCLK_SPDIF, "sclk_spdif", mux_sclk_spdif_p, 0,
|
||||
RK2928_CLKSEL_CON(5), 8, 2, MFLAGS),
|
||||
|
||||
/*
|
||||
* Clock-Architecture Diagram 4
|
||||
*/
|
||||
|
@ -410,7 +419,7 @@ static struct rockchip_clk_branch common_clk_branches[] __initdata = {
|
|||
/* hclk_ahb2apb is part of a clk branch */
|
||||
GATE(0, "hclk_vio_bus", "hclk_cpu", 0, RK2928_CLKGATE_CON(6), 12, GFLAGS),
|
||||
GATE(HCLK_LCDC0, "hclk_lcdc0", "hclk_cpu", 0, RK2928_CLKGATE_CON(6), 1, GFLAGS),
|
||||
GATE(HCLK_LCDC1, "hclk_lcdc1", "aclk_cpu", 0, RK2928_CLKGATE_CON(6), 2, GFLAGS),
|
||||
GATE(HCLK_LCDC1, "hclk_lcdc1", "hclk_cpu", 0, RK2928_CLKGATE_CON(6), 2, GFLAGS),
|
||||
GATE(HCLK_CIF0, "hclk_cif0", "hclk_cpu", 0, RK2928_CLKGATE_CON(6), 4, GFLAGS),
|
||||
GATE(HCLK_IPP, "hclk_ipp", "hclk_cpu", 0, RK2928_CLKGATE_CON(6), 9, GFLAGS),
|
||||
GATE(HCLK_RGA, "hclk_rga", "hclk_cpu", 0, RK2928_CLKGATE_CON(6), 10, GFLAGS),
|
||||
|
@ -577,14 +586,6 @@ static struct rockchip_clk_branch rk3066a_clk_branches[] __initdata = {
|
|||
RK2928_CLKGATE_CON(0), 12, GFLAGS),
|
||||
MUX(SCLK_I2S2, "sclk_i2s2", mux_sclk_i2s2_p, 0,
|
||||
RK2928_CLKSEL_CON(4), 8, 2, MFLAGS),
|
||||
COMPOSITE_NOMUX(0, "spdif_pre", "i2s_src", 0,
|
||||
RK2928_CLKSEL_CON(5), 0, 7, DFLAGS,
|
||||
RK2928_CLKGATE_CON(0), 13, GFLAGS),
|
||||
COMPOSITE_FRAC(0, "spdif_frac", "spdif_pll", 0,
|
||||
RK2928_CLKSEL_CON(9), 0,
|
||||
RK2928_CLKGATE_CON(0), 14, GFLAGS),
|
||||
MUX(SCLK_SPDIF, "sclk_spdif", mux_sclk_spdif_p, 0,
|
||||
RK2928_CLKSEL_CON(5), 8, 2, MFLAGS),
|
||||
|
||||
GATE(HCLK_I2S1, "hclk_i2s1", "hclk_cpu", 0, RK2928_CLKGATE_CON(7), 3, GFLAGS),
|
||||
GATE(HCLK_I2S2, "hclk_i2s2", "hclk_cpu", 0, RK2928_CLKGATE_CON(7), 4, GFLAGS),
|
||||
|
@ -663,7 +664,7 @@ static struct rockchip_clk_branch rk3188_clk_branches[] __initdata = {
|
|||
RK2928_CLKSEL_CON(30), 0, 2, DFLAGS,
|
||||
RK2928_CLKGATE_CON(3), 6, GFLAGS),
|
||||
DIV(0, "sclk_hsicphy_12m", "sclk_hsicphy_480m", 0,
|
||||
RK2928_CLKGATE_CON(11), 8, 6, DFLAGS),
|
||||
RK2928_CLKSEL_CON(11), 8, 6, DFLAGS),
|
||||
|
||||
MUX(0, "i2s_src", mux_pll_src_gpll_cpll_p, 0,
|
||||
RK2928_CLKSEL_CON(2), 15, 1, MFLAGS),
|
||||
|
@ -675,14 +676,6 @@ static struct rockchip_clk_branch rk3188_clk_branches[] __initdata = {
|
|||
RK2928_CLKGATE_CON(0), 10, GFLAGS),
|
||||
MUX(SCLK_I2S0, "sclk_i2s0", mux_sclk_i2s0_p, 0,
|
||||
RK2928_CLKSEL_CON(3), 8, 2, MFLAGS),
|
||||
COMPOSITE_NOMUX(0, "spdif_pre", "i2s_src", 0,
|
||||
RK2928_CLKSEL_CON(5), 0, 7, DFLAGS,
|
||||
RK2928_CLKGATE_CON(13), 13, GFLAGS),
|
||||
COMPOSITE_FRAC(0, "spdif_frac", "spdif_pll", 0,
|
||||
RK2928_CLKSEL_CON(9), 0,
|
||||
RK2928_CLKGATE_CON(0), 14, GFLAGS),
|
||||
MUX(SCLK_SPDIF, "sclk_spdif", mux_sclk_spdif_p, 0,
|
||||
RK2928_CLKSEL_CON(5), 8, 2, MFLAGS),
|
||||
|
||||
GATE(0, "hclk_imem0", "hclk_cpu", 0, RK2928_CLKGATE_CON(4), 14, GFLAGS),
|
||||
GATE(0, "hclk_imem1", "hclk_cpu", 0, RK2928_CLKGATE_CON(4), 15, GFLAGS),
|
||||
|
|
|
@ -202,15 +202,15 @@ PNAME(mux_hsicphy12m_p) = { "hsicphy12m_xin12m", "hsicphy12m_usbphy" };
|
|||
|
||||
static struct rockchip_pll_clock rk3288_pll_clks[] __initdata = {
|
||||
[apll] = PLL(pll_rk3066, PLL_APLL, "apll", mux_pll_p, 0, RK3288_PLL_CON(0),
|
||||
RK3288_MODE_CON, 0, 6, rk3288_pll_rates),
|
||||
RK3288_MODE_CON, 0, 6, 0, rk3288_pll_rates),
|
||||
[dpll] = PLL(pll_rk3066, PLL_DPLL, "dpll", mux_pll_p, 0, RK3288_PLL_CON(4),
|
||||
RK3288_MODE_CON, 4, 5, NULL),
|
||||
RK3288_MODE_CON, 4, 5, 0, NULL),
|
||||
[cpll] = PLL(pll_rk3066, PLL_CPLL, "cpll", mux_pll_p, 0, RK3288_PLL_CON(8),
|
||||
RK3288_MODE_CON, 8, 7, rk3288_pll_rates),
|
||||
RK3288_MODE_CON, 8, 7, ROCKCHIP_PLL_SYNC_RATE, rk3288_pll_rates),
|
||||
[gpll] = PLL(pll_rk3066, PLL_GPLL, "gpll", mux_pll_p, 0, RK3288_PLL_CON(12),
|
||||
RK3288_MODE_CON, 12, 8, rk3288_pll_rates),
|
||||
RK3288_MODE_CON, 12, 8, ROCKCHIP_PLL_SYNC_RATE, rk3288_pll_rates),
|
||||
[npll] = PLL(pll_rk3066, PLL_NPLL, "npll", mux_pll_p, 0, RK3288_PLL_CON(16),
|
||||
RK3288_MODE_CON, 14, 9, rk3288_pll_rates),
|
||||
RK3288_MODE_CON, 14, 9, ROCKCHIP_PLL_SYNC_RATE, rk3288_pll_rates),
|
||||
};
|
||||
|
||||
static struct clk_div_table div_hclk_cpu_t[] = {
|
||||
|
@ -308,7 +308,7 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
|
|||
RK3288_CLKGATE_CON(4), 2, GFLAGS),
|
||||
MUX(0, "i2s_pre", mux_i2s_pre_p, CLK_SET_RATE_PARENT,
|
||||
RK3288_CLKSEL_CON(4), 8, 2, MFLAGS),
|
||||
COMPOSITE_NODIV(0, "i2s0_clkout", mux_i2s_clkout_p, 0,
|
||||
COMPOSITE_NODIV(SCLK_I2S0_OUT, "i2s0_clkout", mux_i2s_clkout_p, 0,
|
||||
RK3288_CLKSEL_CON(4), 12, 1, MFLAGS,
|
||||
RK3288_CLKGATE_CON(4), 0, GFLAGS),
|
||||
GATE(SCLK_I2S0, "sclk_i2s0", "i2s_pre", CLK_SET_RATE_PARENT,
|
||||
|
@ -486,6 +486,18 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
|
|||
RK3288_CLKSEL_CON(12), 14, 2, MFLAGS, 8, 6, DFLAGS,
|
||||
RK3288_CLKGATE_CON(13), 3, GFLAGS),
|
||||
|
||||
MMC(SCLK_SDMMC_DRV, "sdmmc_drv", "sclk_sdmmc", RK3288_SDMMC_CON0, 1),
|
||||
MMC(SCLK_SDMMC_SAMPLE, "sdmmc_sample", "sclk_sdmmc", RK3288_SDMMC_CON1, 0),
|
||||
|
||||
MMC(SCLK_SDIO0_DRV, "sdio0_drv", "sclk_sdio0", RK3288_SDIO0_CON0, 1),
|
||||
MMC(SCLK_SDIO0_SAMPLE, "sdio0_sample", "sclk_sdio0", RK3288_SDIO0_CON1, 0),
|
||||
|
||||
MMC(SCLK_SDIO1_DRV, "sdio1_drv", "sclk_sdio1", RK3288_SDIO1_CON0, 1),
|
||||
MMC(SCLK_SDIO1_SAMPLE, "sdio1_sample", "sclk_sdio1", RK3288_SDIO1_CON1, 0),
|
||||
|
||||
MMC(SCLK_EMMC_DRV, "emmc_drv", "sclk_emmc", RK3288_EMMC_CON0, 1),
|
||||
MMC(SCLK_EMMC_SAMPLE, "emmc_sample", "sclk_emmc", RK3288_EMMC_CON1, 0),
|
||||
|
||||
COMPOSITE(0, "sclk_tspout", mux_tspout_p, 0,
|
||||
RK3288_CLKSEL_CON(35), 14, 2, MFLAGS, 8, 5, DFLAGS,
|
||||
RK3288_CLKGATE_CON(4), 11, GFLAGS),
|
||||
|
@ -625,10 +637,10 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
|
|||
GATE(PCLK_TIMER, "pclk_timer", "pclk_cpu", 0, RK3288_CLKGATE_CON(10), 1, GFLAGS),
|
||||
GATE(PCLK_I2C0, "pclk_i2c0", "pclk_cpu", 0, RK3288_CLKGATE_CON(10), 2, GFLAGS),
|
||||
GATE(PCLK_I2C2, "pclk_i2c2", "pclk_cpu", 0, RK3288_CLKGATE_CON(10), 3, GFLAGS),
|
||||
GATE(0, "pclk_ddrupctl0", "pclk_cpu", 0, RK3288_CLKGATE_CON(10), 14, GFLAGS),
|
||||
GATE(0, "pclk_publ0", "pclk_cpu", 0, RK3288_CLKGATE_CON(10), 15, GFLAGS),
|
||||
GATE(0, "pclk_ddrupctl1", "pclk_cpu", 0, RK3288_CLKGATE_CON(11), 0, GFLAGS),
|
||||
GATE(0, "pclk_publ1", "pclk_cpu", 0, RK3288_CLKGATE_CON(11), 1, GFLAGS),
|
||||
GATE(PCLK_DDRUPCTL0, "pclk_ddrupctl0", "pclk_cpu", 0, RK3288_CLKGATE_CON(10), 14, GFLAGS),
|
||||
GATE(PCLK_PUBL0, "pclk_publ0", "pclk_cpu", 0, RK3288_CLKGATE_CON(10), 15, GFLAGS),
|
||||
GATE(PCLK_DDRUPCTL1, "pclk_ddrupctl1", "pclk_cpu", 0, RK3288_CLKGATE_CON(11), 0, GFLAGS),
|
||||
GATE(PCLK_PUBL1, "pclk_publ1", "pclk_cpu", 0, RK3288_CLKGATE_CON(11), 1, GFLAGS),
|
||||
GATE(0, "pclk_efuse_1024", "pclk_cpu", 0, RK3288_CLKGATE_CON(11), 2, GFLAGS),
|
||||
GATE(PCLK_TZPC, "pclk_tzpc", "pclk_cpu", 0, RK3288_CLKGATE_CON(11), 3, GFLAGS),
|
||||
GATE(PCLK_UART2, "pclk_uart2", "pclk_cpu", 0, RK3288_CLKGATE_CON(11), 9, GFLAGS),
|
||||
|
|
|
@ -197,7 +197,8 @@ void __init rockchip_clk_register_plls(struct rockchip_pll_clock *list,
|
|||
list->parent_names, list->num_parents,
|
||||
reg_base, list->con_offset, grf_lock_offset,
|
||||
list->lock_shift, list->mode_offset,
|
||||
list->mode_shift, list->rate_table, &clk_lock);
|
||||
list->mode_shift, list->rate_table,
|
||||
list->pll_flags, &clk_lock);
|
||||
if (IS_ERR(clk)) {
|
||||
pr_err("%s: failed to register clock %s\n", __func__,
|
||||
list->name);
|
||||
|
@ -268,6 +269,14 @@ void __init rockchip_clk_register_branches(
|
|||
list->gate_offset, list->gate_shift,
|
||||
list->gate_flags, flags, &clk_lock);
|
||||
break;
|
||||
case branch_mmc:
|
||||
clk = rockchip_clk_register_mmc(
|
||||
list->name,
|
||||
list->parent_names, list->num_parents,
|
||||
reg_base + list->muxdiv_offset,
|
||||
list->div_shift
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
/* none of the cases above matched */
|
||||
|
|
|
@ -48,6 +48,14 @@
|
|||
#define RK3288_GLB_SRST_SND 0x1b4
|
||||
#define RK3288_SOFTRST_CON(x) (x * 0x4 + 0x1b8)
|
||||
#define RK3288_MISC_CON 0x1e8
|
||||
#define RK3288_SDMMC_CON0 0x200
|
||||
#define RK3288_SDMMC_CON1 0x204
|
||||
#define RK3288_SDIO0_CON0 0x208
|
||||
#define RK3288_SDIO0_CON1 0x20c
|
||||
#define RK3288_SDIO1_CON0 0x210
|
||||
#define RK3288_SDIO1_CON1 0x214
|
||||
#define RK3288_EMMC_CON0 0x218
|
||||
#define RK3288_EMMC_CON1 0x21c
|
||||
|
||||
enum rockchip_pll_type {
|
||||
pll_rk3066,
|
||||
|
@ -90,7 +98,12 @@ struct rockchip_pll_rate_table {
|
|||
* @mode_shift: offset inside the mode-register for the mode of this pll.
|
||||
* @lock_shift: offset inside the lock register for the lock status.
|
||||
* @type: Type of PLL to be registered.
|
||||
* @pll_flags: hardware-specific flags
|
||||
* @rate_table: Table of usable pll rates
|
||||
*
|
||||
* Flags:
|
||||
* ROCKCHIP_PLL_SYNC_RATE - check rate parameters to match against the
|
||||
* rate_table parameters and ajust them if necessary.
|
||||
*/
|
||||
struct rockchip_pll_clock {
|
||||
unsigned int id;
|
||||
|
@ -103,11 +116,14 @@ struct rockchip_pll_clock {
|
|||
int mode_shift;
|
||||
int lock_shift;
|
||||
enum rockchip_pll_type type;
|
||||
u8 pll_flags;
|
||||
struct rockchip_pll_rate_table *rate_table;
|
||||
};
|
||||
|
||||
#define ROCKCHIP_PLL_SYNC_RATE BIT(0)
|
||||
|
||||
#define PLL(_type, _id, _name, _pnames, _flags, _con, _mode, _mshift, \
|
||||
_lshift, _rtable) \
|
||||
_lshift, _pflags, _rtable) \
|
||||
{ \
|
||||
.id = _id, \
|
||||
.type = _type, \
|
||||
|
@ -119,6 +135,7 @@ struct rockchip_pll_clock {
|
|||
.mode_offset = _mode, \
|
||||
.mode_shift = _mshift, \
|
||||
.lock_shift = _lshift, \
|
||||
.pll_flags = _pflags, \
|
||||
.rate_table = _rtable, \
|
||||
}
|
||||
|
||||
|
@ -127,7 +144,7 @@ struct clk *rockchip_clk_register_pll(enum rockchip_pll_type pll_type,
|
|||
void __iomem *base, int con_offset, int grf_lock_offset,
|
||||
int lock_shift, int reg_mode, int mode_shift,
|
||||
struct rockchip_pll_rate_table *rate_table,
|
||||
spinlock_t *lock);
|
||||
u8 clk_pll_flags, spinlock_t *lock);
|
||||
|
||||
struct rockchip_cpuclk_clksel {
|
||||
int reg;
|
||||
|
@ -161,6 +178,10 @@ struct clk *rockchip_clk_register_cpuclk(const char *name,
|
|||
const struct rockchip_cpuclk_rate_table *rates,
|
||||
int nrates, void __iomem *reg_base, spinlock_t *lock);
|
||||
|
||||
struct clk *rockchip_clk_register_mmc(const char *name,
|
||||
const char **parent_names, u8 num_parents,
|
||||
void __iomem *reg, int shift);
|
||||
|
||||
#define PNAME(x) static const char *x[] __initconst
|
||||
|
||||
enum rockchip_clk_branch_type {
|
||||
|
@ -169,6 +190,7 @@ enum rockchip_clk_branch_type {
|
|||
branch_divider,
|
||||
branch_fraction_divider,
|
||||
branch_gate,
|
||||
branch_mmc,
|
||||
};
|
||||
|
||||
struct rockchip_clk_branch {
|
||||
|
@ -361,6 +383,16 @@ struct rockchip_clk_branch {
|
|||
.gate_flags = gf, \
|
||||
}
|
||||
|
||||
#define MMC(_id, cname, pname, offset, shift) \
|
||||
{ \
|
||||
.id = _id, \
|
||||
.branch_type = branch_mmc, \
|
||||
.name = cname, \
|
||||
.parent_names = (const char *[]){ pname }, \
|
||||
.num_parents = 1, \
|
||||
.muxdiv_offset = offset, \
|
||||
.div_shift = shift, \
|
||||
}
|
||||
|
||||
void rockchip_clk_init(struct device_node *np, void __iomem *base,
|
||||
unsigned long nr_clks);
|
||||
|
|
|
@ -71,6 +71,15 @@
|
|||
#define SCLK_HDMI_CEC 110
|
||||
#define SCLK_HEVC_CABAC 111
|
||||
#define SCLK_HEVC_CORE 112
|
||||
#define SCLK_I2S0_OUT 113
|
||||
#define SCLK_SDMMC_DRV 114
|
||||
#define SCLK_SDIO0_DRV 115
|
||||
#define SCLK_SDIO1_DRV 116
|
||||
#define SCLK_EMMC_DRV 117
|
||||
#define SCLK_SDMMC_SAMPLE 118
|
||||
#define SCLK_SDIO0_SAMPLE 119
|
||||
#define SCLK_SDIO1_SAMPLE 120
|
||||
#define SCLK_EMMC_SAMPLE 121
|
||||
|
||||
#define DCLK_VOP0 190
|
||||
#define DCLK_VOP1 191
|
||||
|
@ -141,6 +150,10 @@
|
|||
#define PCLK_VIO2_H2P 361
|
||||
#define PCLK_CPU 362
|
||||
#define PCLK_PERI 363
|
||||
#define PCLK_DDRUPCTL0 364
|
||||
#define PCLK_PUBL0 365
|
||||
#define PCLK_DDRUPCTL1 366
|
||||
#define PCLK_PUBL1 367
|
||||
|
||||
/* hclk gates */
|
||||
#define HCLK_GPS 448
|
||||
|
|
Loading…
Reference in a new issue