123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145 |
- From c91e8490e45c68ea517f70f24568034b7735e8b9 Mon Sep 17 00:00:00 2001
- From: Sascha Hauer <[email protected]>
- Date: Thu, 23 Apr 2015 10:35:40 +0200
- Subject: [PATCH 03/76] clk: mediatek: Add reset controller support
- The pericfg and infracfg units also provide reset lines to several
- other SoC internal units. This adds a function which can be called
- from the pericfg and infracfg initialization functions which will
- register the reset controller using reset_controller_register. The
- reset controller will provide support for resetting the units
- connected to the pericfg and infracfg controller. The units resetted
- by this controller can use the standard reset device tree binding
- to gain access to the reset lines.
- Signed-off-by: Sascha Hauer <[email protected]>
- Acked-by: Philipp Zabel <[email protected]>
- ---
- drivers/clk/mediatek/Makefile | 1 +
- drivers/clk/mediatek/clk-mtk.h | 10 +++++
- drivers/clk/mediatek/reset.c | 97 ++++++++++++++++++++++++++++++++++++++++
- 3 files changed, 108 insertions(+)
- create mode 100644 drivers/clk/mediatek/reset.c
- --- a/drivers/clk/mediatek/Makefile
- +++ b/drivers/clk/mediatek/Makefile
- @@ -1 +1,2 @@
- obj-y += clk-mtk.o clk-pll.o clk-gate.o
- +obj-$(CONFIG_RESET_CONTROLLER) += reset.o
- --- a/drivers/clk/mediatek/clk-mtk.h
- +++ b/drivers/clk/mediatek/clk-mtk.h
- @@ -156,4 +156,14 @@ void __init mtk_clk_register_plls(struct
- const struct mtk_pll_data *plls, int num_plls,
- struct clk_onecell_data *clk_data);
-
- +#ifdef CONFIG_RESET_CONTROLLER
- +void mtk_register_reset_controller(struct device_node *np,
- + unsigned int num_regs, int regofs);
- +#else
- +static inline void mtk_register_reset_controller(struct device_node *np,
- + unsigned int num_regs, int regofs)
- +{
- +}
- +#endif
- +
- #endif /* __DRV_CLK_MTK_H */
- --- /dev/null
- +++ b/drivers/clk/mediatek/reset.c
- @@ -0,0 +1,97 @@
- +/*
- + * Copyright (c) 2014 MediaTek Inc.
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + *
- + * 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/mfd/syscon.h>
- +#include <linux/module.h>
- +#include <linux/of.h>
- +#include <linux/platform_device.h>
- +#include <linux/regmap.h>
- +#include <linux/reset-controller.h>
- +#include <linux/slab.h>
- +
- +#include "clk-mtk.h"
- +
- +struct mtk_reset {
- + struct regmap *regmap;
- + int regofs;
- + struct reset_controller_dev rcdev;
- +};
- +
- +static int mtk_reset_assert(struct reset_controller_dev *rcdev,
- + unsigned long id)
- +{
- + struct mtk_reset *data = container_of(rcdev, struct mtk_reset, rcdev);
- +
- + return regmap_update_bits(data->regmap, data->regofs + ((id / 32) << 2),
- + BIT(id % 32), ~0);
- +}
- +
- +static int mtk_reset_deassert(struct reset_controller_dev *rcdev,
- + unsigned long id)
- +{
- + struct mtk_reset *data = container_of(rcdev, struct mtk_reset, rcdev);
- +
- + return regmap_update_bits(data->regmap, data->regofs + ((id / 32) << 2),
- + BIT(id % 32), 0);
- +}
- +
- +static int mtk_reset(struct reset_controller_dev *rcdev,
- + unsigned long id)
- +{
- + int ret;
- +
- + ret = mtk_reset_assert(rcdev, id);
- + if (ret)
- + return ret;
- +
- + return mtk_reset_deassert(rcdev, id);
- +}
- +
- +static struct reset_control_ops mtk_reset_ops = {
- + .assert = mtk_reset_assert,
- + .deassert = mtk_reset_deassert,
- + .reset = mtk_reset,
- +};
- +
- +void mtk_register_reset_controller(struct device_node *np,
- + unsigned int num_regs, int regofs)
- +{
- + struct mtk_reset *data;
- + int ret;
- + struct regmap *regmap;
- +
- + regmap = syscon_node_to_regmap(np);
- + if (IS_ERR(regmap)) {
- + pr_err("Cannot find regmap for %s: %ld\n", np->full_name,
- + PTR_ERR(regmap));
- + return;
- + }
- +
- + data = kzalloc(sizeof(*data), GFP_KERNEL);
- + if (!data)
- + return;
- +
- + data->regmap = regmap;
- + data->regofs = regofs;
- + data->rcdev.owner = THIS_MODULE;
- + data->rcdev.nr_resets = num_regs * 32;
- + data->rcdev.ops = &mtk_reset_ops;
- + data->rcdev.of_node = np;
- +
- + ret = reset_controller_register(&data->rcdev);
- + if (ret) {
- + pr_err("could not register reset controller: %d\n", ret);
- + kfree(data);
- + return;
- + }
- +}
|