From da686685d3013de6d374965da9473e026e894c6b Mon Sep 17 00:00:00 2001 From: Robert Nelson <robertcnelson@gmail.com> Date: Wed, 18 Dec 2013 11:23:54 -0600 Subject: [PATCH 1/5] prcm: port from ti-linux-3.12.y Signed-off-by: Robert Nelson <robertcnelson@gmail.com> --- Documentation/devicetree/bindings/arm/omap/prcm.txt | 13 + arch/arm/boot/dts/am33xx.dtsi | 1 drivers/reset/Kconfig | 14 + drivers/reset/Makefile | 1 drivers/reset/core.c | 32 +++ drivers/reset/ti_reset.c | 184 ++++++++++++++++++++ include/linux/reset-controller.h | 2 include/linux/reset.h | 2 8 files changed, 249 insertions(+) create mode 100644 Documentation/devicetree/bindings/arm/omap/prcm.txt create mode 100644 drivers/reset/ti_reset.c Index: linux-3.12.24-rt38-r7s5/Documentation/devicetree/bindings/arm/omap/prcm.txt =================================================================== @ linux-3.12.24-rt38-r7s5/Documentation/devicetree/bindings/arm/omap/prcm.txt:4 @ +TI Power Reset Clock Manager (PRCM) + +Properties: +- compatible: "ti,am4372-prcm" for prcm in am43x SoC's + "ti,am3352-prcm" for prcm in am335x SoC's +- #reset-cells: 1 (refer generic reset bindings for details) + +example: + prcm: prcm@44df0000 { + compatible = "ti,am4372-prcm"; + reg = <0x44df0000 0xa000>; + #reset-cells = <1>; + }; Index: linux-3.12.24-rt38-r7s5/arch/arm/boot/dts/am33xx.dtsi =================================================================== --- linux-3.12.24-rt38-r7s5.orig/arch/arm/boot/dts/am33xx.dtsi +++ linux-3.12.24-rt38-r7s5/arch/arm/boot/dts/am33xx.dtsi @ linux-3.12.24-rt38-r7s5/Documentation/devicetree/bindings/arm/omap/prcm.txt:102 @ prcm: prcm@44e00000 { compatible = "ti,am3-prcm"; reg = <0x44e00000 0x4000>; + #reset-cells = <1>; prcm_clocks: clocks { #address-cells = <1>; Index: linux-3.12.24-rt38-r7s5/drivers/reset/Kconfig =================================================================== --- linux-3.12.24-rt38-r7s5.orig/drivers/reset/Kconfig +++ linux-3.12.24-rt38-r7s5/drivers/reset/Kconfig @ linux-3.12.24-rt38-r7s5/Documentation/devicetree/bindings/arm/omap/prcm.txt:14 @ menuconfig RESET_CONTROLLER via GPIOs or SoC-internal reset controller modules. If unsure, say no. + +if RESET_CONTROLLER + +config RESET_TI + bool "TI reset controller" + help + Reset controller support for TI SoC's + + Reset controller found in TI's AM series of SoC's like + AM335x and AM43x and OMAP SoC's like OMAP5 and DRA7 + + If unsure, say no. + +endif Index: linux-3.12.24-rt38-r7s5/drivers/reset/Makefile =================================================================== --- linux-3.12.24-rt38-r7s5.orig/drivers/reset/Makefile +++ linux-3.12.24-rt38-r7s5/drivers/reset/Makefile @ linux-3.12.24-rt38-r7s5/Documentation/devicetree/bindings/arm/omap/prcm.txt:1 @ obj-$(CONFIG_RESET_CONTROLLER) += core.o +obj-$(CONFIG_RESET_TI) += ti_reset.o Index: linux-3.12.24-rt38-r7s5/drivers/reset/core.c =================================================================== --- linux-3.12.24-rt38-r7s5.orig/drivers/reset/core.c +++ linux-3.12.24-rt38-r7s5/drivers/reset/core.c @ linux-3.12.24-rt38-r7s5/Documentation/devicetree/bindings/arm/omap/prcm.txt:130 @ int reset_control_deassert(struct reset_ EXPORT_SYMBOL_GPL(reset_control_deassert); /** + * reset_control_is_reset - check reset status + * @rstc: reset controller + * + * Returns a boolean or negative error code + * + */ +int reset_control_is_reset(struct reset_control *rstc) +{ + if (rstc->rcdev->ops->is_reset) + return rstc->rcdev->ops->is_reset(rstc->rcdev, rstc->id); + + return -ENOSYS; +} +EXPORT_SYMBOL_GPL(reset_control_is_reset); + +/** + * reset_control_clear_reset - clear the reset + * @rstc: reset controller + * + * Returns zero on success or negative error code + * + */ +int reset_control_clear_reset(struct reset_control *rstc) +{ + if (rstc->rcdev->ops->clear_reset) + return rstc->rcdev->ops->clear_reset(rstc->rcdev, rstc->id); + + return -ENOSYS; +} +EXPORT_SYMBOL_GPL(reset_control_clear_reset); + +/** * reset_control_get - Lookup and obtain a reference to a reset controller. * @dev: device to be reset by the controller * @id: reset line name Index: linux-3.12.24-rt38-r7s5/drivers/reset/ti_reset.c =================================================================== --- /dev/null +++ linux-3.12.24-rt38-r7s5/drivers/reset/ti_reset.c @ linux-3.12.24-rt38-r7s5/Documentation/devicetree/bindings/arm/omap/prcm.txt:4 @ +/* + * PRCM reset driver for TI SoC's + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ +#include <linux/device.h> +#include <linux/err.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/of_device.h> +#include <linux/reset.h> +#include <linux/reset-controller.h> +#include <linux/platform_device.h> +#include <linux/io.h> + +#define DRIVER_NAME "ti_reset" + +struct ti_reset_reg_data { + u32 rstctrl_offs; + u32 rstst_offs; + u8 rstctrl_bit; + u8 rstst_bit; +}; + +struct ti_reset_data { + struct ti_reset_reg_data *reg_data; + u8 nr_resets; +}; + +static void __iomem *reg_base; +static const struct ti_reset_data *reset_data; + +static struct ti_reset_reg_data am335x_reset_reg_data[] = { + { + .rstctrl_offs = 0x1104, + .rstst_offs = 0x1114, + .rstctrl_bit = 0, + .rstst_bit = 0, + }, + { + .rstctrl_offs = 0x0D00, + .rstst_offs = 0x0D0C, + .rstctrl_bit = 3, + .rstst_bit = 5, + }, +}; + +static struct ti_reset_data am335x_reset_data = { + .reg_data = am335x_reset_reg_data, + .nr_resets = ARRAY_SIZE(am335x_reset_reg_data), +}; + +static struct ti_reset_reg_data am43x_reset_reg_data[] = { + { + .rstctrl_offs = 0x410, + .rstst_offs = 0x414, + .rstctrl_bit = 0, + .rstst_bit = 0, + }, + { + .rstctrl_offs = 0x2010, + .rstst_offs = 0x2014, + .rstctrl_bit = 3, + .rstst_bit = 5, + }, +}; + +static struct ti_reset_data am43x_reset_data = { + .reg_data = am43x_reset_reg_data, + .nr_resets = ARRAY_SIZE(am43x_reset_reg_data), +}; + +static struct ti_reset_reg_data dra7_reset_reg_data[] = { + { + .rstctrl_offs = 0x1310, + .rstst_offs = 0x1314, + .rstctrl_bit = 0, + .rstst_bit = 0, + }, +}; + +static struct ti_reset_data dra7_reset_data = { + .reg_data = dra7_reset_reg_data, + .nr_resets = ARRAY_SIZE(dra7_reset_reg_data), +}; + +static int ti_reset_clear_reset(struct reset_controller_dev *rcdev, + unsigned long id) +{ + void __iomem *reg = reset_data->reg_data[id].rstst_offs + reg_base; + u8 bit = reset_data->reg_data[id].rstst_bit; + u32 val = readl(reg); + + val &= ~(1 << bit); + val |= 1 << bit; + writel(val, reg); + return 0; +} + +static int ti_reset_is_reset(struct reset_controller_dev *rcdev, + unsigned long id) +{ + void __iomem *reg = reset_data->reg_data[id].rstst_offs + reg_base; + u8 bit = reset_data->reg_data[id].rstst_bit; + u32 val = readl(reg); + + val &= (1 << bit); + return !!val; +} + +static int ti_reset_deassert(struct reset_controller_dev *rcdev, + unsigned long id) +{ + void __iomem *reg = reset_data->reg_data[id].rstctrl_offs + + reg_base; + u8 bit = reset_data->reg_data[id].rstctrl_bit; + u32 val = readl(reg); + + val &= ~(1 << bit); + writel(val, reg); + return 0; +} + +static struct reset_control_ops ti_reset_ops = { + .deassert = ti_reset_deassert, + .is_reset = ti_reset_is_reset, + .clear_reset = ti_reset_clear_reset, +}; + +static struct reset_controller_dev ti_reset_controller = { + .ops = &ti_reset_ops, +}; + +static const struct of_device_id ti_reset_of_match[] = { + { .compatible = "ti,am3352-prcm", .data = &am335x_reset_data,}, + { .compatible = "ti,am4372-prcm", .data = &am43x_reset_data,}, + { .compatible = "ti,dra7-prcm", .data = &dra7_reset_data,}, + {}, +}; + +static int ti_reset_probe(struct platform_device *pdev) +{ + struct resource *res; + const struct of_device_id *id; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + reg_base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(reg_base)) + return PTR_ERR(reg_base); + + ti_reset_controller.of_node = pdev->dev.of_node; + id = of_match_device(ti_reset_of_match, &pdev->dev); + reset_data = id->data; + ti_reset_controller.nr_resets = reset_data->nr_resets; + + reset_controller_register(&ti_reset_controller); + + return 0; +} + +static int ti_reset_remove(struct platform_device *pdev) +{ + reset_controller_unregister(&ti_reset_controller); + + return 0; +} + +static struct platform_driver ti_reset_driver = { + .probe = ti_reset_probe, + .remove = ti_reset_remove, + .driver = { + .name = DRIVER_NAME, + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(ti_reset_of_match), + }, +}; +module_platform_driver(ti_reset_driver); + +MODULE_DESCRIPTION("PRCM reset driver for TI SoC's"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:" DRIVER_NAME); Index: linux-3.12.24-rt38-r7s5/include/linux/reset-controller.h =================================================================== --- linux-3.12.24-rt38-r7s5.orig/include/linux/reset-controller.h +++ linux-3.12.24-rt38-r7s5/include/linux/reset-controller.h @ linux-3.12.24-rt38-r7s5/Documentation/devicetree/bindings/arm/omap/prcm.txt:20 @ struct reset_control_ops { int (*reset)(struct reset_controller_dev *rcdev, unsigned long id); int (*assert)(struct reset_controller_dev *rcdev, unsigned long id); int (*deassert)(struct reset_controller_dev *rcdev, unsigned long id); + int (*is_reset)(struct reset_controller_dev *rcdev, unsigned long id); + int (*clear_reset)(struct reset_controller_dev *rcdev, unsigned long i); }; struct module; Index: linux-3.12.24-rt38-r7s5/include/linux/reset.h =================================================================== --- linux-3.12.24-rt38-r7s5.orig/include/linux/reset.h +++ linux-3.12.24-rt38-r7s5/include/linux/reset.h @ linux-3.12.24-rt38-r7s5/Documentation/devicetree/bindings/arm/omap/prcm.txt:10 @ struct reset_control; int reset_control_reset(struct reset_control *rstc); int reset_control_assert(struct reset_control *rstc); int reset_control_deassert(struct reset_control *rstc); +int reset_control_is_reset(struct reset_control *rstc); +int reset_control_clear_reset(struct reset_control *rstc); struct reset_control *reset_control_get(struct device *dev, const char *id); void reset_control_put(struct reset_control *rstc);