diff options
author | Lucas Stach <dev@lynxeye.de> | 2014-05-14 22:45:30 +0200 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2014-05-15 14:17:12 +0200 |
commit | 77d45d43c22ca5aa0a6bcf97e88508355073959b (patch) | |
tree | 6d6fbd658aa367c792c0ef5f3c540a62b210c31f /drivers/clk/tegra/clk.c | |
parent | 7a9d497860994aa87ebaed32ca1d7c3be929bfbb (diff) | |
download | barebox-77d45d43c22ca5aa0a6bcf97e88508355073959b.tar.gz barebox-77d45d43c22ca5aa0a6bcf97e88508355073959b.tar.xz |
reset: add tegra reset controller
Allows us to drop the hack in the clock controller
and implement proper reset at device level.
Signed-off-by: Lucas Stach <dev@lynxeye.de>
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'drivers/clk/tegra/clk.c')
-rw-r--r-- | drivers/clk/tegra/clk.c | 134 |
1 files changed, 133 insertions, 1 deletions
diff --git a/drivers/clk/tegra/clk.c b/drivers/clk/tegra/clk.c index f4013e7e79..a6b81d029b 100644 --- a/drivers/clk/tegra/clk.c +++ b/drivers/clk/tegra/clk.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 Lucas Stach <l.stach@pengutronix.de> + * Copyright (C) 2013-2014 Lucas Stach <l.stach@pengutronix.de> * * Based on the Linux Tegra clock code * @@ -18,9 +18,103 @@ #include <common.h> #include <linux/clk.h> +#include <linux/reset-controller.h> +#include <mach/lowlevel.h> #include "clk.h" +#define CLK_OUT_ENB_L 0x010 +#define CLK_OUT_ENB_H 0x014 +#define CLK_OUT_ENB_U 0x018 +#define CLK_OUT_ENB_V 0x360 +#define CLK_OUT_ENB_W 0x364 +#define CLK_OUT_ENB_X 0x280 +#define CLK_OUT_ENB_SET_L 0x320 +#define CLK_OUT_ENB_CLR_L 0x324 +#define CLK_OUT_ENB_SET_H 0x328 +#define CLK_OUT_ENB_CLR_H 0x32c +#define CLK_OUT_ENB_SET_U 0x330 +#define CLK_OUT_ENB_CLR_U 0x334 +#define CLK_OUT_ENB_SET_V 0x440 +#define CLK_OUT_ENB_CLR_V 0x444 +#define CLK_OUT_ENB_SET_W 0x448 +#define CLK_OUT_ENB_CLR_W 0x44c +#define CLK_OUT_ENB_SET_X 0x284 +#define CLK_OUT_ENB_CLR_X 0x288 + +#define RST_DEVICES_L 0x004 +#define RST_DEVICES_H 0x008 +#define RST_DEVICES_U 0x00C +#define RST_DFLL_DVCO 0x2F4 +#define RST_DEVICES_V 0x358 +#define RST_DEVICES_W 0x35C +#define RST_DEVICES_X 0x28C +#define RST_DEVICES_SET_L 0x300 +#define RST_DEVICES_CLR_L 0x304 +#define RST_DEVICES_SET_H 0x308 +#define RST_DEVICES_CLR_H 0x30c +#define RST_DEVICES_SET_U 0x310 +#define RST_DEVICES_CLR_U 0x314 +#define RST_DEVICES_SET_V 0x430 +#define RST_DEVICES_CLR_V 0x434 +#define RST_DEVICES_SET_W 0x438 +#define RST_DEVICES_CLR_W 0x43c +#define RST_DEVICES_SET_X 0x290 +#define RST_DEVICES_CLR_X 0x294 + +static struct tegra_clk_periph_regs periph_regs[] = { + [0] = { + .enb_reg = CLK_OUT_ENB_L, + .enb_set_reg = CLK_OUT_ENB_SET_L, + .enb_clr_reg = CLK_OUT_ENB_CLR_L, + .rst_reg = RST_DEVICES_L, + .rst_set_reg = RST_DEVICES_SET_L, + .rst_clr_reg = RST_DEVICES_CLR_L, + }, + [1] = { + .enb_reg = CLK_OUT_ENB_H, + .enb_set_reg = CLK_OUT_ENB_SET_H, + .enb_clr_reg = CLK_OUT_ENB_CLR_H, + .rst_reg = RST_DEVICES_H, + .rst_set_reg = RST_DEVICES_SET_H, + .rst_clr_reg = RST_DEVICES_CLR_H, + }, + [2] = { + .enb_reg = CLK_OUT_ENB_U, + .enb_set_reg = CLK_OUT_ENB_SET_U, + .enb_clr_reg = CLK_OUT_ENB_CLR_U, + .rst_reg = RST_DEVICES_U, + .rst_set_reg = RST_DEVICES_SET_U, + .rst_clr_reg = RST_DEVICES_CLR_U, + }, + [3] = { + .enb_reg = CLK_OUT_ENB_V, + .enb_set_reg = CLK_OUT_ENB_SET_V, + .enb_clr_reg = CLK_OUT_ENB_CLR_V, + .rst_reg = RST_DEVICES_V, + .rst_set_reg = RST_DEVICES_SET_V, + .rst_clr_reg = RST_DEVICES_CLR_V, + }, + [4] = { + .enb_reg = CLK_OUT_ENB_W, + .enb_set_reg = CLK_OUT_ENB_SET_W, + .enb_clr_reg = CLK_OUT_ENB_CLR_W, + .rst_reg = RST_DEVICES_W, + .rst_set_reg = RST_DEVICES_SET_W, + .rst_clr_reg = RST_DEVICES_CLR_W, + }, + [5] = { + .enb_reg = CLK_OUT_ENB_X, + .enb_set_reg = CLK_OUT_ENB_SET_X, + .enb_clr_reg = CLK_OUT_ENB_CLR_X, + .rst_reg = RST_DEVICES_X, + .rst_set_reg = RST_DEVICES_SET_X, + .rst_clr_reg = RST_DEVICES_CLR_X, + }, +}; + +static void __iomem *car_base; + void tegra_init_from_table(struct tegra_clk_init_table *tbl, struct clk *clks[], int clk_max) { @@ -55,3 +149,41 @@ void tegra_init_from_table(struct tegra_clk_init_table *tbl, } } } + +static int tegra_clk_rst_assert(struct reset_controller_dev *rcdev, + unsigned long id) +{ + tegra_read_chipid(); + + writel(BIT(id % 32), car_base + periph_regs[id / 32].rst_set_reg); + + return 0; +} + +static int tegra_clk_rst_deassert(struct reset_controller_dev *rcdev, + unsigned long id) +{ + writel(BIT(id % 32), car_base + periph_regs[id / 32].rst_clr_reg); + + return 0; +} + +static struct reset_control_ops rst_ops = { + .assert = tegra_clk_rst_assert, + .deassert = tegra_clk_rst_deassert, +}; + +static struct reset_controller_dev rst_ctlr = { + .ops = &rst_ops, + .of_reset_n_cells = 1, +}; + +void tegra_clk_init_rst_controller(void __iomem *base, struct device_node *np, + unsigned int num) +{ + car_base = base; + + rst_ctlr.of_node = np; + rst_ctlr.nr_resets = num; + reset_controller_register(&rst_ctlr); +} |