reset: at91: Add reset driver for basic assert/deassert operations
Add support for at91 reset controller's basic assert/deassert operations. Since this driver conflicts with the SYSRESET driver because they both bind to the same RSTC node, implement a custom bind hook that would manually bind the sysreset driver, if enabled, to the same RSTC DT node. Furthermore, delete the no longer needed compatibles from the SYSRESET driver and rename it to make sure than any possible conflicts are avoided. Signed-off-by: Sergiu Moga <sergiu.moga@microchip.com> Tested-by: Mihai Sain <mihai.sain@microchip.com> Reviewed-by: Claudiu Beznea <claudiu.beznea@microchip.com>
This commit is contained in:
parent
11c037ab92
commit
61040097a9
@ -211,4 +211,12 @@ config RESET_DRA7
|
||||
help
|
||||
Support for TI DRA7-RESET subsystem. Basic Assert/Deassert
|
||||
is supported.
|
||||
|
||||
config RESET_AT91
|
||||
bool "Enable support for Microchip/Atmel Reset Controller driver"
|
||||
depends on DM_RESET && ARCH_AT91
|
||||
help
|
||||
This enables the Reset Controller driver support for Microchip/Atmel
|
||||
SoCs. Mainly used to expose assert/deassert methods to other drivers
|
||||
that require it.
|
||||
endmenu
|
||||
|
@ -31,3 +31,4 @@ obj-$(CONFIG_RESET_RASPBERRYPI) += reset-raspberrypi.o
|
||||
obj-$(CONFIG_RESET_SCMI) += reset-scmi.o
|
||||
obj-$(CONFIG_RESET_ZYNQMP) += reset-zynqmp.o
|
||||
obj-$(CONFIG_RESET_DRA7) += reset-dra7.o
|
||||
obj-$(CONFIG_RESET_AT91) += reset-at91.o
|
||||
|
141
drivers/reset/reset-at91.c
Normal file
141
drivers/reset/reset-at91.c
Normal file
@ -0,0 +1,141 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Support for Atmel/Microchip Reset Controller.
|
||||
*
|
||||
* Copyright (C) 2022 Microchip Technology Inc. and its subsidiaries
|
||||
*
|
||||
* Author: Sergiu Moga <sergiu.moga@microchip.com>
|
||||
*/
|
||||
|
||||
#include <clk.h>
|
||||
#include <asm/io.h>
|
||||
#include <dm.h>
|
||||
#include <dm/lists.h>
|
||||
#include <reset-uclass.h>
|
||||
#include <asm/arch/at91_rstc.h>
|
||||
#include <dt-bindings/reset/sama7g5-reset.h>
|
||||
|
||||
struct at91_reset {
|
||||
void __iomem *dev_base;
|
||||
struct at91_reset_data *data;
|
||||
};
|
||||
|
||||
struct at91_reset_data {
|
||||
u32 n_device_reset;
|
||||
u8 device_reset_min_id;
|
||||
u8 device_reset_max_id;
|
||||
};
|
||||
|
||||
static const struct at91_reset_data sama7g5_data = {
|
||||
.n_device_reset = 3,
|
||||
.device_reset_min_id = SAMA7G5_RESET_USB_PHY1,
|
||||
.device_reset_max_id = SAMA7G5_RESET_USB_PHY3,
|
||||
};
|
||||
|
||||
static int at91_rst_update(struct at91_reset *reset, unsigned long id,
|
||||
bool assert)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
if (!reset->dev_base)
|
||||
return 0;
|
||||
|
||||
val = readl(reset->dev_base);
|
||||
if (assert)
|
||||
val |= BIT(id);
|
||||
else
|
||||
val &= ~BIT(id);
|
||||
writel(val, reset->dev_base);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int at91_reset_of_xlate(struct reset_ctl *reset_ctl,
|
||||
struct ofnode_phandle_args *args)
|
||||
{
|
||||
struct at91_reset *reset = dev_get_priv(reset_ctl->dev);
|
||||
|
||||
if (!reset->data->n_device_reset ||
|
||||
args->args[0] < reset->data->device_reset_min_id ||
|
||||
args->args[0] > reset->data->device_reset_max_id)
|
||||
return -EINVAL;
|
||||
|
||||
reset_ctl->id = args->args[0];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int at91_rst_assert(struct reset_ctl *reset_ctl)
|
||||
{
|
||||
struct at91_reset *reset = dev_get_priv(reset_ctl->dev);
|
||||
|
||||
return at91_rst_update(reset, reset_ctl->id, true);
|
||||
}
|
||||
|
||||
static int at91_rst_deassert(struct reset_ctl *reset_ctl)
|
||||
{
|
||||
struct at91_reset *reset = dev_get_priv(reset_ctl->dev);
|
||||
|
||||
return at91_rst_update(reset, reset_ctl->id, false);
|
||||
}
|
||||
|
||||
struct reset_ops at91_reset_ops = {
|
||||
.of_xlate = at91_reset_of_xlate,
|
||||
.rst_assert = at91_rst_assert,
|
||||
.rst_deassert = at91_rst_deassert,
|
||||
};
|
||||
|
||||
static int at91_reset_probe(struct udevice *dev)
|
||||
{
|
||||
struct at91_reset *reset = dev_get_priv(dev);
|
||||
struct clk sclk;
|
||||
int ret;
|
||||
|
||||
reset->data = (struct at91_reset_data *)dev_get_driver_data(dev);
|
||||
reset->dev_base = dev_remap_addr_index(dev, 1);
|
||||
if (reset->data && reset->data->n_device_reset && !reset->dev_base)
|
||||
return -EINVAL;
|
||||
|
||||
ret = clk_get_by_index(dev, 0, &sclk);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return clk_prepare_enable(&sclk);
|
||||
}
|
||||
|
||||
static int at91_reset_bind(struct udevice *dev)
|
||||
{
|
||||
struct udevice *at91_sysreset;
|
||||
|
||||
if (CONFIG_IS_ENABLED(SYSRESET_AT91))
|
||||
return device_bind_driver_to_node(dev, "at91_sysreset",
|
||||
"at91_sysreset",
|
||||
dev_ofnode(dev),
|
||||
&at91_sysreset);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct udevice_id at91_reset_ids[] = {
|
||||
{
|
||||
.compatible = "microchip,sama7g5-rstc",
|
||||
.data = (ulong)&sama7g5_data,
|
||||
},
|
||||
{
|
||||
.compatible = "atmel,sama5d3-rstc",
|
||||
},
|
||||
{
|
||||
.compatible = "microchip,sam9x60-rstc",
|
||||
},
|
||||
{ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(at91_reset) = {
|
||||
.name = "at91_reset",
|
||||
.id = UCLASS_RESET,
|
||||
.of_match = at91_reset_ids,
|
||||
.bind = at91_reset_bind,
|
||||
.probe = at91_reset_probe,
|
||||
.priv_auto = sizeof(struct at91_reset),
|
||||
.ops = &at91_reset_ops,
|
||||
};
|
@ -56,17 +56,9 @@ static struct sysreset_ops at91_sysreset = {
|
||||
.request = at91_sysreset_request,
|
||||
};
|
||||
|
||||
static const struct udevice_id a91_sysreset_ids[] = {
|
||||
{ .compatible = "atmel,sama5d3-rstc" },
|
||||
{ .compatible = "microchip,sam9x60-rstc" },
|
||||
{ .compatible = "microchip,sama7g5-rstc" },
|
||||
{ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(sysreset_at91) = {
|
||||
.id = UCLASS_SYSRESET,
|
||||
.name = "at91_reset",
|
||||
.name = "at91_sysreset",
|
||||
.ops = &at91_sysreset,
|
||||
.probe = at91_sysreset_probe,
|
||||
.of_match = a91_sysreset_ids,
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user