mbox series

[v4,0/9] power: reset: at91-reset: add support for sama7g5

Message ID 20220608083942.1584087-1-claudiu.beznea@microchip.com
Headers show
Series power: reset: at91-reset: add support for sama7g5 | expand

Message

Claudiu Beznea June 8, 2022, 8:39 a.m. UTC
Hi,

The series adds reset controller support for SAMA7G5 SoCs. Compared with
previous version the reset controller embedded on SAMA7G5 is able to
reset individual on SoC devices (e.g. USB PHY controllers).

Among with this I took the change and converted reset controller
bindings to YAML (patch 2/9) and adapt reset controller nodes in
device tree files to comply with DT specifications (patch 1/9).

Thank you,
Claudiu Beznea

Changes in v4:
- removed patch 10/10 from v3 as it has been taken though at91 tree

Changes in v3:
- use spin_lock_irqsave()/spin_unlock_irqrestore() and lock only
  on update path
- collected tags

Changes in v2:
- added patches 5/10 and 10/10
- in patch 2/10 use my microchip email address
- in patch 4/10 added "SAMA7G5_" in front of macros to cope with file
  naming and used (GPL-2.0-only OR BSD-2-Clause)
- in patch 6/10 documented the structure's members
- in patch 7/10:
	- protect access to reset->dev_base with spin lock
	- check for valid values of reset_spec->args[0] in
	  at91_reset_of_xlate()
	- s/if (IS_ERR(reset->rstc_base))/if (IS_ERR(reset->dev_base))
	- include dt-bindings/reset/sama7g5-reset.h
	- document new added structure's members
- collected tags

Claudiu Beznea (9):
  ARM: dts: at91: use generic name for reset controller
  dt-bindings: reset: convert Atmel/Microchip reset controller to YAML
  dt-bindings: reset: atmel,at91sam9260-reset: add sama7g5 bindings
  dt-bindings: reset: add sama7g5 definitions
  power: reset: at91-reset: document structures and enums
  power: reset: at91-reset: add at91_reset_data
  power: reset: at91-reset: add reset_controller_dev support
  power: reset: at91-reset: add support for SAMA7G5
  ARM: dts: at91: sama7g5: add reset-controller node

 .../devicetree/bindings/arm/atmel-sysregs.txt |  15 --
 .../reset/atmel,at91sam9260-reset.yaml        |  68 +++++++
 arch/arm/boot/dts/at91sam9260.dtsi            |   2 +-
 arch/arm/boot/dts/at91sam9261.dtsi            |   2 +-
 arch/arm/boot/dts/at91sam9263.dtsi            |   2 +-
 arch/arm/boot/dts/at91sam9g45.dtsi            |   2 +-
 arch/arm/boot/dts/at91sam9n12.dtsi            |   2 +-
 arch/arm/boot/dts/at91sam9rl.dtsi             |   2 +-
 arch/arm/boot/dts/at91sam9x5.dtsi             |   2 +-
 arch/arm/boot/dts/sam9x60.dtsi                |   2 +-
 arch/arm/boot/dts/sama5d2.dtsi                |   2 +-
 arch/arm/boot/dts/sama5d3.dtsi                |   2 +-
 arch/arm/boot/dts/sama5d4.dtsi                |   2 +-
 arch/arm/boot/dts/sama7g5.dtsi                |   7 +
 drivers/power/reset/at91-reset.c              | 173 ++++++++++++++++--
 include/dt-bindings/reset/sama7g5-reset.h     |  10 +
 16 files changed, 256 insertions(+), 39 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/reset/atmel,at91sam9260-reset.yaml
 create mode 100644 include/dt-bindings/reset/sama7g5-reset.h

Comments

Krzysztof Kozlowski June 8, 2022, 8:41 a.m. UTC | #1
On 08/06/2022 10:39, Claudiu Beznea wrote:
> Use generic name for reset controller of AT91 devices to comply with
> DT specifications.
> 
> Signed-off-by: Claudiu Beznea <claudiu.beznea@microchip.com>
> Reviewed-by: Philipp Zabel <p.zabel@pengutronix.de>


Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>


Best regards,
Krzysztof
Sebastian Reichel June 9, 2022, 8:47 p.m. UTC | #2
Hi,

On Wed, Jun 08, 2022 at 11:39:40AM +0300, Claudiu Beznea wrote:
> SAMA7G5 reset controller has 5 extra lines that goes to different devices
> (3 lines to USB PHYs, 1 line to DDR controller, 1 line to DDR PHY
> controller). These reset lines could be requested by different controller
> drivers (e.g. USB PHY driver) and these controllers' drivers could
> assert/deassert these lines when necessary. Thus add support for
> reset_controller_dev which brings this functionality.
> 
> Signed-off-by: Claudiu Beznea <claudiu.beznea@microchip.com>
> Reviewed-by: Philipp Zabel <p.zabel@pengutronix.de>
> ---
>  drivers/power/reset/at91-reset.c | 106 +++++++++++++++++++++++++++++--
>  1 file changed, 102 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/power/reset/at91-reset.c b/drivers/power/reset/at91-reset.c
> index 1b2aca3f490d..e25d8d38a2f8 100644
> --- a/drivers/power/reset/at91-reset.c
> +++ b/drivers/power/reset/at91-reset.c
> @@ -17,10 +17,13 @@
>  #include <linux/of_address.h>
>  #include <linux/platform_device.h>
>  #include <linux/reboot.h>
> +#include <linux/reset-controller.h>
>  
>  #include <soc/at91/at91sam9_ddrsdr.h>
>  #include <soc/at91/at91sam9_sdramc.h>
>  
> +#include <dt-bindings/reset/sama7g5-reset.h>
> +
>  #define AT91_RSTC_CR	0x00		/* Reset Controller Control Register */
>  #define AT91_RSTC_PROCRST	BIT(0)		/* Processor Reset */
>  #define AT91_RSTC_PERRST	BIT(2)		/* Peripheral Reset */
> @@ -65,7 +68,10 @@ enum reset_type {
>   * struct at91_reset - AT91 reset specific data structure
>   * @rstc_base:		base address for system reset
>   * @ramc_base:		array with base addresses of RAM controllers
> + * @dev_base:		base address for devices reset
>   * @sclk:		slow clock
> + * @rcdev:		reset controller device
> + * @lock:		lock for devices reset register access
>   * @nb:			reset notifier block
>   * @args:		SoC specific system reset arguments
>   * @ramc_lpr:		SDRAM Controller Low Power Register
> @@ -73,12 +79,17 @@ enum reset_type {
>  struct at91_reset {
>  	void __iomem *rstc_base;
>  	void __iomem *ramc_base[2];
> +	void __iomem *dev_base;
>  	struct clk *sclk;
> +	struct reset_controller_dev rcdev;
> +	spinlock_t lock;
>  	struct notifier_block nb;
>  	u32 args;
>  	u32 ramc_lpr;
>  };
>  
> +#define to_at91_reset(r)	container_of(r, struct at91_reset, rcdev)
> +
>  /**
>   * struct at91_reset_data - AT91 reset data
>   * @reset_args:		SoC specific system reset arguments
> @@ -216,6 +227,87 @@ static const struct of_device_id at91_reset_of_match[] = {
>  };
>  MODULE_DEVICE_TABLE(of, at91_reset_of_match);
>  
> +static int at91_reset_update(struct reset_controller_dev *rcdev,
> +			     unsigned long id, bool assert)
> +{
> +	struct at91_reset *reset = to_at91_reset(rcdev);
> +	unsigned long flags;
> +	u32 val;
> +
> +	spin_lock_irqsave(&reset->lock, flags);
> +	val = readl_relaxed(reset->dev_base);
> +	if (assert)
> +		val |= BIT(id);
> +	else
> +		val &= ~BIT(id);
> +	writel_relaxed(val, reset->dev_base);
> +	spin_unlock_irqrestore(&reset->lock, flags);
> +
> +	return 0;
> +}
> +
> +static int at91_reset_assert(struct reset_controller_dev *rcdev,
> +			     unsigned long id)
> +{
> +	return at91_reset_update(rcdev, id, true);
> +}
> +
> +static int at91_reset_deassert(struct reset_controller_dev *rcdev,
> +			       unsigned long id)
> +{
> +	return at91_reset_update(rcdev, id, false);
> +}
> +
> +static int at91_reset_dev_status(struct reset_controller_dev *rcdev,
> +				 unsigned long id)
> +{
> +	struct at91_reset *reset = to_at91_reset(rcdev);
> +	u32 val;
> +
> +	val = readl_relaxed(reset->dev_base);
> +
> +	return !!(val & BIT(id));
> +}
> +
> +static const struct reset_control_ops at91_reset_ops = {
> +	.assert = at91_reset_assert,
> +	.deassert = at91_reset_deassert,
> +	.status = at91_reset_dev_status,
> +};
> +
> +static int at91_reset_of_xlate(struct reset_controller_dev *rcdev,
> +			       const struct of_phandle_args *reset_spec)
> +{
> +	if (reset_spec->args[0] < SAMA7G5_RESET_USB_PHY1 ||
> +	    reset_spec->args[0] > SAMA7G5_RESET_USB_PHY3)
> +		return -EINVAL;

Can you move the min/max info to the devce info struct, so that
this stays as generic as the name suggests (and is prepared for
future devices)?

-- Sebastian

> +	return reset_spec->args[0];
> +}
> +
> +static int at91_rcdev_init(struct at91_reset *reset,
> +			   const struct at91_reset_data *data,
> +			   struct platform_device *pdev)
> +{
> +	if (!data->n_device_reset)
> +		return 0;
> +
> +	reset->dev_base = devm_of_iomap(&pdev->dev, pdev->dev.of_node, 1,
> +					NULL);
> +	if (IS_ERR(reset->dev_base))
> +		return -ENODEV;
> +
> +	spin_lock_init(&reset->lock);
> +	reset->rcdev.ops = &at91_reset_ops;
> +	reset->rcdev.owner = THIS_MODULE;
> +	reset->rcdev.of_node = pdev->dev.of_node;
> +	reset->rcdev.nr_resets = data->n_device_reset;
> +	reset->rcdev.of_reset_n_cells = 1;
> +	reset->rcdev.of_xlate = at91_reset_of_xlate;
> +
> +	return devm_reset_controller_register(&pdev->dev, &reset->rcdev);
> +}
> +
>  static int __init at91_reset_probe(struct platform_device *pdev)
>  {
>  	const struct of_device_id *match;
> @@ -269,6 +361,10 @@ static int __init at91_reset_probe(struct platform_device *pdev)
>  
>  	platform_set_drvdata(pdev, reset);
>  
> +	ret = at91_rcdev_init(reset, data, pdev);
> +	if (ret)
> +		goto disable_clk;
> +
>  	if (of_device_is_compatible(pdev->dev.of_node, "microchip,sam9x60-rstc")) {
>  		u32 val = readl(reset->rstc_base + AT91_RSTC_MR);
>  
> @@ -277,14 +373,16 @@ static int __init at91_reset_probe(struct platform_device *pdev)
>  	}
>  
>  	ret = register_restart_handler(&reset->nb);
> -	if (ret) {
> -		clk_disable_unprepare(reset->sclk);
> -		return ret;
> -	}
> +	if (ret)
> +		goto disable_clk;
>  
>  	at91_reset_status(pdev, reset->rstc_base);
>  
>  	return 0;
> +
> +disable_clk:
> +	clk_disable_unprepare(reset->sclk);
> +	return ret;
>  }
>  
>  static int __exit at91_reset_remove(struct platform_device *pdev)
> -- 
> 2.33.0
>