Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d534b5d4 authored by Joseph Lo's avatar Joseph Lo Committed by Stephen Warren
Browse files

ARM: tegra30: clocks: add AHB and APB clocks



Adding the AHB and APB bus clock for Tegra30.

Signed-off-by: default avatarJoseph Lo <josephl@nvidia.com>
Signed-off-by: default avatarStephen Warren <swarren@nvidia.com>
parent 25804d81
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -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
+106 −0
Original line number Diff line number Diff line
@@ -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)
{
+1 −0
Original line number Diff line number Diff line
@@ -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;
+46 −0
Original line number Diff line number Diff line
@@ -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,
};