[PATCH RFC 01/10] drivers: reset: STi SoC system configuration reset controller support
From: Stephen Gallimore This patch adds a reset controller implementation for STMicroelectronics STi family SoCs; it allows a group of related reset like controls found in multiple system configuration registers to be represented by a single controller device. System configuration registers are accessed through the regmap framework and the mfd/syscon driver. The implementation optionally supports waiting for the reset action to be acknowledged in a separate status register and supports both active high and active low reset lines. These properties are common across all the reset channels in a specific reset controller instance, hence all channels in a paritcular controller are expected to behave in the same way. Signed-off-by: Stephen Gallimore --- drivers/reset/Kconfig|2 + drivers/reset/Makefile |3 + drivers/reset/sti/Kconfig|7 ++ drivers/reset/sti/Makefile |1 + drivers/reset/sti/reset-syscfg.c | 186 ++ drivers/reset/sti/reset-syscfg.h | 69 ++ 6 files changed, 268 insertions(+), 0 deletions(-) create mode 100644 drivers/reset/sti/Kconfig create mode 100644 drivers/reset/sti/Makefile create mode 100644 drivers/reset/sti/reset-syscfg.c create mode 100644 drivers/reset/sti/reset-syscfg.h diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig index c9d04f7..0615f50 100644 --- a/drivers/reset/Kconfig +++ b/drivers/reset/Kconfig @@ -11,3 +11,5 @@ menuconfig RESET_CONTROLLER via GPIOs or SoC-internal reset controller modules. If unsure, say no. + +source "drivers/reset/sti/Kconfig" diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile index 1e2d83f..2b2a57c 100644 --- a/drivers/reset/Makefile +++ b/drivers/reset/Makefile @@ -1 +1,4 @@ obj-$(CONFIG_RESET_CONTROLLER) += core.o + +# SoC specific +obj-$(CONFIG_ARCH_STI) += sti/ diff --git a/drivers/reset/sti/Kconfig b/drivers/reset/sti/Kconfig new file mode 100644 index 000..ba13796 --- /dev/null +++ b/drivers/reset/sti/Kconfig @@ -0,0 +1,7 @@ +if ARCH_STI + +config STI_RESET_SYSCFG + bool + select RESET_CONTROLLER + +endif diff --git a/drivers/reset/sti/Makefile b/drivers/reset/sti/Makefile new file mode 100644 index 000..c4a51d9 --- /dev/null +++ b/drivers/reset/sti/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_STI_RESET_SYSCFG) += reset-syscfg.o diff --git a/drivers/reset/sti/reset-syscfg.c b/drivers/reset/sti/reset-syscfg.c new file mode 100644 index 000..a145cc0 --- /dev/null +++ b/drivers/reset/sti/reset-syscfg.c @@ -0,0 +1,186 @@ +/* + * Copyright (C) 2013 STMicroelectronics Limited + * Author: Stephen Gallimore + * + * Inspired by mach-imx/src.c + * + * 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 +#include +#include +#include +#include +#include +#include +#include + +#include "reset-syscfg.h" + +/** + * Reset channel regmap configuration + * + * @reset: regmap field for the channel's reset bit. + * @ack: regmap field for the channel's ack bit (optional). + */ +struct syscfg_reset_channel { + struct regmap_field *reset; + struct regmap_field *ack; +}; + +/** + * A reset controller which groups together a set of related reset bits, which + * may be located in different system configuration registers. + * + * @rst: base reset controller structure. + * @active_low: are the resets in this controller active low, i.e. clearing + * the reset bit puts the hardware into reset. + * @channels: An array of reset channels for this controller. + */ +struct syscfg_reset_controller { + struct reset_controller_dev rst; + bool active_low; + struct syscfg_reset_channel *channels; +}; + +#define to_syscfg_reset_controller(_rst) \ + container_of(_rst, struct syscfg_reset_controller, rst) + +static int syscfg_reset_program_hw(struct reset_controller_dev *rcdev, + unsigned long idx, int assert) +{ + struct syscfg_reset_controller *rst = to_syscfg_reset_controller(rcdev); + const struct syscfg_reset_channel *ch; + u32 ctrl_val = rst->active_low ? !assert : !!assert; + int err; + + if (idx >= rcdev->nr_resets) + return -EINVAL; + + ch = >channels[idx]; + + err = regmap_field_write(ch->reset, ctrl_val); + if (err) + return err; + + if (ch->ack) { + unsigned long timeout = jiffies + msecs_to_jiffies(1000); + u32 ack_val; + + while (true) { + err = regmap_field_read(ch->ack, _val); + if (err) + return err; + + if (ack_val == ctrl_val) + break; + +
[PATCH RFC 01/10] drivers: reset: STi SoC system configuration reset controller support
From: Stephen Gallimore stephen.gallim...@st.com This patch adds a reset controller implementation for STMicroelectronics STi family SoCs; it allows a group of related reset like controls found in multiple system configuration registers to be represented by a single controller device. System configuration registers are accessed through the regmap framework and the mfd/syscon driver. The implementation optionally supports waiting for the reset action to be acknowledged in a separate status register and supports both active high and active low reset lines. These properties are common across all the reset channels in a specific reset controller instance, hence all channels in a paritcular controller are expected to behave in the same way. Signed-off-by: Stephen Gallimore stephen.gallim...@st.com --- drivers/reset/Kconfig|2 + drivers/reset/Makefile |3 + drivers/reset/sti/Kconfig|7 ++ drivers/reset/sti/Makefile |1 + drivers/reset/sti/reset-syscfg.c | 186 ++ drivers/reset/sti/reset-syscfg.h | 69 ++ 6 files changed, 268 insertions(+), 0 deletions(-) create mode 100644 drivers/reset/sti/Kconfig create mode 100644 drivers/reset/sti/Makefile create mode 100644 drivers/reset/sti/reset-syscfg.c create mode 100644 drivers/reset/sti/reset-syscfg.h diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig index c9d04f7..0615f50 100644 --- a/drivers/reset/Kconfig +++ b/drivers/reset/Kconfig @@ -11,3 +11,5 @@ menuconfig RESET_CONTROLLER via GPIOs or SoC-internal reset controller modules. If unsure, say no. + +source drivers/reset/sti/Kconfig diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile index 1e2d83f..2b2a57c 100644 --- a/drivers/reset/Makefile +++ b/drivers/reset/Makefile @@ -1 +1,4 @@ obj-$(CONFIG_RESET_CONTROLLER) += core.o + +# SoC specific +obj-$(CONFIG_ARCH_STI) += sti/ diff --git a/drivers/reset/sti/Kconfig b/drivers/reset/sti/Kconfig new file mode 100644 index 000..ba13796 --- /dev/null +++ b/drivers/reset/sti/Kconfig @@ -0,0 +1,7 @@ +if ARCH_STI + +config STI_RESET_SYSCFG + bool + select RESET_CONTROLLER + +endif diff --git a/drivers/reset/sti/Makefile b/drivers/reset/sti/Makefile new file mode 100644 index 000..c4a51d9 --- /dev/null +++ b/drivers/reset/sti/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_STI_RESET_SYSCFG) += reset-syscfg.o diff --git a/drivers/reset/sti/reset-syscfg.c b/drivers/reset/sti/reset-syscfg.c new file mode 100644 index 000..a145cc0 --- /dev/null +++ b/drivers/reset/sti/reset-syscfg.c @@ -0,0 +1,186 @@ +/* + * Copyright (C) 2013 STMicroelectronics Limited + * Author: Stephen Gallimore stephen.gallim...@st.com + * + * Inspired by mach-imx/src.c + * + * 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/kernel.h +#include linux/platform_device.h +#include linux/module.h +#include linux/err.h +#include linux/types.h +#include linux/of_device.h +#include linux/regmap.h +#include linux/mfd/syscon.h + +#include reset-syscfg.h + +/** + * Reset channel regmap configuration + * + * @reset: regmap field for the channel's reset bit. + * @ack: regmap field for the channel's ack bit (optional). + */ +struct syscfg_reset_channel { + struct regmap_field *reset; + struct regmap_field *ack; +}; + +/** + * A reset controller which groups together a set of related reset bits, which + * may be located in different system configuration registers. + * + * @rst: base reset controller structure. + * @active_low: are the resets in this controller active low, i.e. clearing + * the reset bit puts the hardware into reset. + * @channels: An array of reset channels for this controller. + */ +struct syscfg_reset_controller { + struct reset_controller_dev rst; + bool active_low; + struct syscfg_reset_channel *channels; +}; + +#define to_syscfg_reset_controller(_rst) \ + container_of(_rst, struct syscfg_reset_controller, rst) + +static int syscfg_reset_program_hw(struct reset_controller_dev *rcdev, + unsigned long idx, int assert) +{ + struct syscfg_reset_controller *rst = to_syscfg_reset_controller(rcdev); + const struct syscfg_reset_channel *ch; + u32 ctrl_val = rst-active_low ? !assert : !!assert; + int err; + + if (idx = rcdev-nr_resets) + return -EINVAL; + + ch = rst-channels[idx]; + + err = regmap_field_write(ch-reset, ctrl_val); + if (err) + return err; + + if (ch-ack) { + unsigned long timeout = jiffies + msecs_to_jiffies(1000); + u32 ack_val; + + while (true) { + err = regmap_field_read(ch-ack,