ARM: tegra30: clocks: add AHB and APB clocks
Adding the AHB and APB bus clock for Tegra30. Signed-off-by: Joseph Lo <josephl@nvidia.com> Signed-off-by: Stephen Warren <swarren@nvidia.com>
This commit is contained in:
Родитель
25804d8123
Коммит
d534b5d4a5
|
@ -104,6 +104,10 @@ static __initdata struct tegra_clk_init_table tegra30_clk_init_table[] = {
|
||||||
{ "clk_m", NULL, 0, true },
|
{ "clk_m", NULL, 0, true },
|
||||||
{ "pll_p", "clk_m", 408000000, true },
|
{ "pll_p", "clk_m", 408000000, true },
|
||||||
{ "pll_p_out1", "pll_p", 9600000, true },
|
{ "pll_p_out1", "pll_p", 9600000, true },
|
||||||
|
{ "pll_p_out4", "pll_p", 102000000, true },
|
||||||
|
{ "sclk", "pll_p_out4", 102000000, true },
|
||||||
|
{ "hclk", "sclk", 102000000, true },
|
||||||
|
{ "pclk", "hclk", 51000000, true },
|
||||||
{ NULL, NULL, 0, 0},
|
{ NULL, NULL, 0, 0},
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -791,6 +791,112 @@ struct clk_ops tegra30_twd_ops = {
|
||||||
.recalc_rate = tegra30_twd_clk_recalc_rate,
|
.recalc_rate = tegra30_twd_clk_recalc_rate,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* bus clock functions */
|
||||||
|
static int tegra30_bus_clk_is_enabled(struct clk_hw *hw)
|
||||||
|
{
|
||||||
|
struct clk_tegra *c = to_clk_tegra(hw);
|
||||||
|
u32 val = clk_readl(c->reg);
|
||||||
|
|
||||||
|
c->state = ((val >> c->reg_shift) & BUS_CLK_DISABLE) ? OFF : ON;
|
||||||
|
return c->state;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tegra30_bus_clk_enable(struct clk_hw *hw)
|
||||||
|
{
|
||||||
|
struct clk_tegra *c = to_clk_tegra(hw);
|
||||||
|
u32 val;
|
||||||
|
|
||||||
|
val = clk_readl(c->reg);
|
||||||
|
val &= ~(BUS_CLK_DISABLE << c->reg_shift);
|
||||||
|
clk_writel(val, c->reg);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tegra30_bus_clk_disable(struct clk_hw *hw)
|
||||||
|
{
|
||||||
|
struct clk_tegra *c = to_clk_tegra(hw);
|
||||||
|
u32 val;
|
||||||
|
|
||||||
|
val = clk_readl(c->reg);
|
||||||
|
val |= BUS_CLK_DISABLE << c->reg_shift;
|
||||||
|
clk_writel(val, c->reg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned long tegra30_bus_clk_recalc_rate(struct clk_hw *hw,
|
||||||
|
unsigned long prate)
|
||||||
|
{
|
||||||
|
struct clk_tegra *c = to_clk_tegra(hw);
|
||||||
|
u32 val = clk_readl(c->reg);
|
||||||
|
u64 rate = prate;
|
||||||
|
|
||||||
|
c->div = ((val >> c->reg_shift) & BUS_CLK_DIV_MASK) + 1;
|
||||||
|
c->mul = 1;
|
||||||
|
|
||||||
|
if (c->mul != 0 && c->div != 0) {
|
||||||
|
rate *= c->mul;
|
||||||
|
rate += c->div - 1; /* round up */
|
||||||
|
do_div(rate, c->div);
|
||||||
|
}
|
||||||
|
return rate;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tegra30_bus_clk_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||||
|
unsigned long parent_rate)
|
||||||
|
{
|
||||||
|
struct clk_tegra *c = to_clk_tegra(hw);
|
||||||
|
int ret = -EINVAL;
|
||||||
|
u32 val;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
val = clk_readl(c->reg);
|
||||||
|
for (i = 1; i <= 4; i++) {
|
||||||
|
if (rate == parent_rate / i) {
|
||||||
|
val &= ~(BUS_CLK_DIV_MASK << c->reg_shift);
|
||||||
|
val |= (i - 1) << c->reg_shift;
|
||||||
|
clk_writel(val, c->reg);
|
||||||
|
c->div = i;
|
||||||
|
c->mul = 1;
|
||||||
|
ret = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static long tegra30_bus_clk_round_rate(struct clk_hw *hw, unsigned long rate,
|
||||||
|
unsigned long *prate)
|
||||||
|
{
|
||||||
|
unsigned long parent_rate = *prate;
|
||||||
|
s64 divider;
|
||||||
|
|
||||||
|
if (rate >= parent_rate)
|
||||||
|
return parent_rate;
|
||||||
|
|
||||||
|
divider = parent_rate;
|
||||||
|
divider += rate - 1;
|
||||||
|
do_div(divider, rate);
|
||||||
|
|
||||||
|
if (divider < 0)
|
||||||
|
return divider;
|
||||||
|
|
||||||
|
if (divider > 4)
|
||||||
|
divider = 4;
|
||||||
|
do_div(parent_rate, divider);
|
||||||
|
|
||||||
|
return parent_rate;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct clk_ops tegra30_bus_ops = {
|
||||||
|
.is_enabled = tegra30_bus_clk_is_enabled,
|
||||||
|
.enable = tegra30_bus_clk_enable,
|
||||||
|
.disable = tegra30_bus_clk_disable,
|
||||||
|
.set_rate = tegra30_bus_clk_set_rate,
|
||||||
|
.round_rate = tegra30_bus_clk_round_rate,
|
||||||
|
.recalc_rate = tegra30_bus_clk_recalc_rate,
|
||||||
|
};
|
||||||
|
|
||||||
/* Blink output functions */
|
/* Blink output functions */
|
||||||
static int tegra30_blink_clk_is_enabled(struct clk_hw *hw)
|
static int tegra30_blink_clk_is_enabled(struct clk_hw *hw)
|
||||||
{
|
{
|
||||||
|
|
|
@ -34,6 +34,7 @@ extern struct clk_ops tegra_clk_out_ops;
|
||||||
extern struct clk_ops tegra30_super_ops;
|
extern struct clk_ops tegra30_super_ops;
|
||||||
extern struct clk_ops tegra30_blink_clk_ops;
|
extern struct clk_ops tegra30_blink_clk_ops;
|
||||||
extern struct clk_ops tegra30_twd_ops;
|
extern struct clk_ops tegra30_twd_ops;
|
||||||
|
extern struct clk_ops tegra30_bus_ops;
|
||||||
extern struct clk_ops tegra30_periph_clk_ops;
|
extern struct clk_ops tegra30_periph_clk_ops;
|
||||||
extern struct clk_ops tegra30_dsib_clk_ops;
|
extern struct clk_ops tegra30_dsib_clk_ops;
|
||||||
extern struct clk_ops tegra_nand_clk_ops;
|
extern struct clk_ops tegra_nand_clk_ops;
|
||||||
|
|
|
@ -711,6 +711,50 @@ static struct clk tegra_clk_sclk = {
|
||||||
.num_parents = ARRAY_SIZE(mux_sclk),
|
.num_parents = ARRAY_SIZE(mux_sclk),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const char *tegra_hclk_parent_names[] = {
|
||||||
|
"tegra_sclk",
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct clk *tegra_hclk_parents[] = {
|
||||||
|
&tegra_clk_sclk,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct clk tegra_hclk;
|
||||||
|
static struct clk_tegra tegra_hclk_hw = {
|
||||||
|
.hw = {
|
||||||
|
.clk = &tegra_hclk,
|
||||||
|
},
|
||||||
|
.flags = DIV_BUS,
|
||||||
|
.reg = 0x30,
|
||||||
|
.reg_shift = 4,
|
||||||
|
.max_rate = 378000000,
|
||||||
|
.min_rate = 12000000,
|
||||||
|
};
|
||||||
|
DEFINE_CLK_TEGRA(hclk, 0, &tegra30_bus_ops, 0, tegra_hclk_parent_names,
|
||||||
|
tegra_hclk_parents, &tegra_clk_sclk);
|
||||||
|
|
||||||
|
static const char *tegra_pclk_parent_names[] = {
|
||||||
|
"tegra_hclk",
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct clk *tegra_pclk_parents[] = {
|
||||||
|
&tegra_hclk,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct clk tegra_pclk;
|
||||||
|
static struct clk_tegra tegra_pclk_hw = {
|
||||||
|
.hw = {
|
||||||
|
.clk = &tegra_pclk,
|
||||||
|
},
|
||||||
|
.flags = DIV_BUS,
|
||||||
|
.reg = 0x30,
|
||||||
|
.reg_shift = 0,
|
||||||
|
.max_rate = 167000000,
|
||||||
|
.min_rate = 12000000,
|
||||||
|
};
|
||||||
|
DEFINE_CLK_TEGRA(pclk, 0, &tegra30_bus_ops, 0, tegra_pclk_parent_names,
|
||||||
|
tegra_pclk_parents, &tegra_hclk);
|
||||||
|
|
||||||
static const char *mux_blink[] = {
|
static const char *mux_blink[] = {
|
||||||
"clk_32k",
|
"clk_32k",
|
||||||
};
|
};
|
||||||
|
@ -1325,6 +1369,8 @@ struct clk *tegra_ptr_clks[] = {
|
||||||
&tegra_cml1,
|
&tegra_cml1,
|
||||||
&tegra_pciex,
|
&tegra_pciex,
|
||||||
&tegra_clk_sclk,
|
&tegra_clk_sclk,
|
||||||
|
&tegra_hclk,
|
||||||
|
&tegra_pclk,
|
||||||
&tegra_clk_blink,
|
&tegra_clk_blink,
|
||||||
&tegra30_clk_twd,
|
&tegra30_clk_twd,
|
||||||
};
|
};
|
||||||
|
|
Загрузка…
Ссылка в новой задаче