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 },
|
||||
{ "pll_p", "clk_m", 408000000, 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},
|
||||
};
|
||||
#endif
|
||||
|
|
|
@ -791,6 +791,112 @@ struct clk_ops tegra30_twd_ops = {
|
|||
.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 */
|
||||
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_blink_clk_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_dsib_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),
|
||||
};
|
||||
|
||||
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[] = {
|
||||
"clk_32k",
|
||||
};
|
||||
|
@ -1325,6 +1369,8 @@ struct clk *tegra_ptr_clks[] = {
|
|||
&tegra_cml1,
|
||||
&tegra_pciex,
|
||||
&tegra_clk_sclk,
|
||||
&tegra_hclk,
|
||||
&tegra_pclk,
|
||||
&tegra_clk_blink,
|
||||
&tegra30_clk_twd,
|
||||
};
|
||||
|
|
Загрузка…
Ссылка в новой задаче