mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-23 04:04:26 +08:00
Reset controller updates for v6.13
* Split the Amlogic reset-meson driver into platform and auxiliary bus drivers. Add support for the reset controller in the G12 and SM1 audio clock controllers. * Replace the list of boolean parameters to the internal reset_control_get functions with an enum reset_flags bitfield, to make the code more self-descriptive. * Add devres helpers to request pre-deasserted (and automatically re-asserting during cleanup) reset controls. This allows reducing boilerplate in drivers that deassert resets for the lifetime of a device. * Use the new auto-deasserting devres helpers in reset-uniphier-glue as an example. * Add support for the LAN966x PCI device in drivers/misc, as a dependency for the following reset-microchip-sparx5 patches. * Add support for being used on the LAN966x PCI device to the reset-microchip-sparx5 driver. Commit86f134941a
("MAINTAINERS: Add the Microchip LAN966x PCI driver entry") introduces a trivial merge conflict with commit7280f01e79
("net: lan969x: add match data for lan969x") from the net-next tree [1]. [1] https://lore.kernel.org/all/20241101122505.3eacd183@canb.auug.org.au/ -----BEGIN PGP SIGNATURE----- iI0EABYIADUWIQRRO6F6WdpH1R0vGibVhaclGDdiwAUCZyn4gxcccC56YWJlbEBw ZW5ndXRyb25peC5kZQAKCRDVhaclGDdiwFJZAP0fjXG07qnGp1Sgai/pmCesg5xJ PAEL5/hKaYwQsAQHhwEAwaJg+kVeb74ez3ae4akyvngasJJT9LLDmqWEdxPIcw0= =cyUW -----END PGP SIGNATURE----- gpgsig -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEiK/NIGsWEZVxh/FrYKtH/8kJUicFAmczbWkACgkQYKtH/8kJ UifcZQ/+O0Mek2EdY0VB0nFe3HIzFJU2RAdzAE2ivcwRwzsnpXz21UtYWnDjrIn7 eTPS6oOTKPbukP/fKwz/u7G7iXdM6VcrVJHfE58z5DqBNGGuou/+sRdTNU01XCrw y/TmWwsppGbzpRZ6Wd3aAl6+PldLSNUIKSuDUZ87rpKw8XYzXSvFpd7FhJ8ZQ+sh 0U8E9o9bj0jwJoCT2azx4peiMnsJbFZON9a5DII/3BCEG/mYc+uO1Q0xJeaalawn UCLDEsYi8+zNRYwoH7zBxLSDac2S/3k4KpzFXSWmY4JsCiRRh2x7/HFkt5+Mn27L W4grUYsy1c2h3SvZAcs5KKSOZlJT3UtYtKRErVaruHAVkeBw7Cgg4pjm4qjOWdmv ke4IOOl6VBgJS55ptFuWJdvCUY62IZfnchjlDcAfMy7BxsB7zxXlP4UaO2DzVLCv KokE7dEB30jlwqfOMZQNMqw9OaGYQXv58FN6bXp5Te49oyEWuWoPTaQgQSbcUMf6 97wyTn8hDF1LwFRnHqued6lfv2BmZoX8ej4BDQ51wKU+ppgFOuFODD367rXJrka2 73fpbMf5WMHiIH2063d/ShXiwvowggbb7SeAprZFI9ZWCdj6YUSHKYTCDvgRVV9W D/HjuoTHf4Y7ueD0oQSsOKycSqkEVjYpsOOD++rRzc7xnUmNBww= =rxJh -----END PGP SIGNATURE----- Merge tag 'reset-for-v6.13' of git://git.pengutronix.de/pza/linux into soc/drivers Reset controller updates for v6.13 * Split the Amlogic reset-meson driver into platform and auxiliary bus drivers. Add support for the reset controller in the G12 and SM1 audio clock controllers. * Replace the list of boolean parameters to the internal reset_control_get functions with an enum reset_flags bitfield, to make the code more self-descriptive. * Add devres helpers to request pre-deasserted (and automatically re-asserting during cleanup) reset controls. This allows reducing boilerplate in drivers that deassert resets for the lifetime of a device. * Use the new auto-deasserting devres helpers in reset-uniphier-glue as an example. * Add support for the LAN966x PCI device in drivers/misc, as a dependency for the following reset-microchip-sparx5 patches. * Add support for being used on the LAN966x PCI device to the reset-microchip-sparx5 driver. Commit86f134941a
("MAINTAINERS: Add the Microchip LAN966x PCI driver entry") introduces a trivial merge conflict with commit7280f01e79
("net: lan969x: add match data for lan969x") from the net-next tree [1]. [1] https://lore.kernel.org/all/20241101122505.3eacd183@canb.auug.org.au/ * tag 'reset-for-v6.13' of git://git.pengutronix.de/pza/linux: (21 commits) misc: lan966x_pci: Fix dtc warn 'Missing interrupt-parent' misc: lan966x_pci: Fix dtc warns 'missing or empty reg/ranges property' reset: mchp: sparx5: set the dev member of the reset controller reset: mchp: sparx5: Allow building as a module reset: mchp: sparx5: Add MCHP_LAN966X_PCI dependency reset: mchp: sparx5: Map cpu-syscon locally in case of LAN966x MAINTAINERS: Add the Microchip LAN966x PCI driver entry misc: Add support for LAN966x PCI device reset: uniphier-glue: Use devm_reset_control_bulk_get_shared_deasserted() reset: Add devres helpers to request pre-deasserted reset controls reset: replace boolean parameters with flags parameter reset: amlogic: Fix small whitespace issue reset: amlogic: add auxiliary reset driver support reset: amlogic: split the device core and platform probe reset: amlogic: move drivers to a dedicated directory reset: amlogic: add reset status support reset: amlogic: use reset number instead of register count reset: amlogic: add driver parameters reset: amlogic: make parameters unsigned reset: amlogic: use generic data matching function ... Link: https://lore.kernel.org/r/20241105105229.3729474-1-p.zabel@pengutronix.de Signed-off-by: Arnd Bergmann <arnd@arndb.de>
This commit is contained in:
commit
7d6f7cfc34
@ -15087,6 +15087,12 @@ S: Maintained
|
||||
F: Documentation/devicetree/bindings/interrupt-controller/microchip,lan966x-oic.yaml
|
||||
F: drivers/irqchip/irq-lan966x-oic.c
|
||||
|
||||
MICROCHIP LAN966X PCI DRIVER
|
||||
M: Herve Codina <herve.codina@bootlin.com>
|
||||
S: Maintained
|
||||
F: drivers/misc/lan966x_pci.c
|
||||
F: drivers/misc/lan966x_pci.dtso
|
||||
|
||||
MICROCHIP LCDFB DRIVER
|
||||
M: Nicolas Ferre <nicolas.ferre@microchip.com>
|
||||
L: linux-fbdev@vger.kernel.org
|
||||
|
@ -610,6 +610,30 @@ config MARVELL_CN10K_DPI
|
||||
To compile this driver as a module, choose M here: the module
|
||||
will be called mrvl_cn10k_dpi.
|
||||
|
||||
config MCHP_LAN966X_PCI
|
||||
tristate "Microchip LAN966x PCIe Support"
|
||||
depends on PCI
|
||||
select OF
|
||||
select OF_OVERLAY
|
||||
select IRQ_DOMAIN
|
||||
help
|
||||
This enables the support for the LAN966x PCIe device.
|
||||
|
||||
This is used to drive the LAN966x PCIe device from the host system
|
||||
to which it is connected. The driver uses a device tree overlay to
|
||||
load other drivers to support for LAN966x internal components.
|
||||
|
||||
Even if this driver does not depend on those other drivers, in order
|
||||
to have a fully functional board, the following drivers are needed:
|
||||
- fixed-clock (COMMON_CLK)
|
||||
- lan966x-oic (LAN966X_OIC)
|
||||
- lan966x-cpu-syscon (MFD_SYSCON)
|
||||
- lan966x-switch-reset (RESET_MCHP_SPARX5)
|
||||
- lan966x-pinctrl (PINCTRL_OCELOT)
|
||||
- lan966x-serdes (PHY_LAN966X_SERDES)
|
||||
- lan966x-miim (MDIO_MSCC_MIIM)
|
||||
- lan966x-switch (LAN966X_SWITCH)
|
||||
|
||||
source "drivers/misc/c2port/Kconfig"
|
||||
source "drivers/misc/eeprom/Kconfig"
|
||||
source "drivers/misc/cb710/Kconfig"
|
||||
|
@ -71,4 +71,7 @@ obj-$(CONFIG_TPS6594_ESM) += tps6594-esm.o
|
||||
obj-$(CONFIG_TPS6594_PFSM) += tps6594-pfsm.o
|
||||
obj-$(CONFIG_NSM) += nsm.o
|
||||
obj-$(CONFIG_MARVELL_CN10K_DPI) += mrvl_cn10k_dpi.o
|
||||
lan966x-pci-objs := lan966x_pci.o
|
||||
lan966x-pci-objs += lan966x_pci.dtbo.o
|
||||
obj-$(CONFIG_MCHP_LAN966X_PCI) += lan966x-pci.o
|
||||
obj-y += keba/
|
||||
|
215
drivers/misc/lan966x_pci.c
Normal file
215
drivers/misc/lan966x_pci.c
Normal file
@ -0,0 +1,215 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Microchip LAN966x PCI driver
|
||||
*
|
||||
* Copyright (c) 2024 Microchip Technology Inc. and its subsidiaries.
|
||||
*
|
||||
* Authors:
|
||||
* Clément Léger <clement.leger@bootlin.com>
|
||||
* Hervé Codina <herve.codina@bootlin.com>
|
||||
*/
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/irqdomain.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/pci_ids.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
/* Embedded dtbo symbols created by cmd_wrap_S_dtb in scripts/Makefile.lib */
|
||||
extern char __dtbo_lan966x_pci_begin[];
|
||||
extern char __dtbo_lan966x_pci_end[];
|
||||
|
||||
struct pci_dev_intr_ctrl {
|
||||
struct pci_dev *pci_dev;
|
||||
struct irq_domain *irq_domain;
|
||||
int irq;
|
||||
};
|
||||
|
||||
static int pci_dev_irq_domain_map(struct irq_domain *d, unsigned int virq, irq_hw_number_t hw)
|
||||
{
|
||||
irq_set_chip_and_handler(virq, &dummy_irq_chip, handle_simple_irq);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct irq_domain_ops pci_dev_irq_domain_ops = {
|
||||
.map = pci_dev_irq_domain_map,
|
||||
.xlate = irq_domain_xlate_onecell,
|
||||
};
|
||||
|
||||
static irqreturn_t pci_dev_irq_handler(int irq, void *data)
|
||||
{
|
||||
struct pci_dev_intr_ctrl *intr_ctrl = data;
|
||||
int ret;
|
||||
|
||||
ret = generic_handle_domain_irq(intr_ctrl->irq_domain, 0);
|
||||
return ret ? IRQ_NONE : IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static struct pci_dev_intr_ctrl *pci_dev_create_intr_ctrl(struct pci_dev *pdev)
|
||||
{
|
||||
struct pci_dev_intr_ctrl *intr_ctrl __free(kfree) = NULL;
|
||||
struct fwnode_handle *fwnode;
|
||||
int ret;
|
||||
|
||||
fwnode = dev_fwnode(&pdev->dev);
|
||||
if (!fwnode)
|
||||
return ERR_PTR(-ENODEV);
|
||||
|
||||
intr_ctrl = kmalloc(sizeof(*intr_ctrl), GFP_KERNEL);
|
||||
if (!intr_ctrl)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
intr_ctrl->pci_dev = pdev;
|
||||
|
||||
intr_ctrl->irq_domain = irq_domain_create_linear(fwnode, 1, &pci_dev_irq_domain_ops,
|
||||
intr_ctrl);
|
||||
if (!intr_ctrl->irq_domain) {
|
||||
pci_err(pdev, "Failed to create irqdomain\n");
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_INTX);
|
||||
if (ret < 0) {
|
||||
pci_err(pdev, "Unable alloc irq vector (%d)\n", ret);
|
||||
goto err_remove_domain;
|
||||
}
|
||||
intr_ctrl->irq = pci_irq_vector(pdev, 0);
|
||||
ret = request_irq(intr_ctrl->irq, pci_dev_irq_handler, IRQF_SHARED,
|
||||
pci_name(pdev), intr_ctrl);
|
||||
if (ret) {
|
||||
pci_err(pdev, "Unable to request irq %d (%d)\n", intr_ctrl->irq, ret);
|
||||
goto err_free_irq_vector;
|
||||
}
|
||||
|
||||
return_ptr(intr_ctrl);
|
||||
|
||||
err_free_irq_vector:
|
||||
pci_free_irq_vectors(pdev);
|
||||
err_remove_domain:
|
||||
irq_domain_remove(intr_ctrl->irq_domain);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
static void pci_dev_remove_intr_ctrl(struct pci_dev_intr_ctrl *intr_ctrl)
|
||||
{
|
||||
free_irq(intr_ctrl->irq, intr_ctrl);
|
||||
pci_free_irq_vectors(intr_ctrl->pci_dev);
|
||||
irq_dispose_mapping(irq_find_mapping(intr_ctrl->irq_domain, 0));
|
||||
irq_domain_remove(intr_ctrl->irq_domain);
|
||||
kfree(intr_ctrl);
|
||||
}
|
||||
|
||||
static void devm_pci_dev_remove_intr_ctrl(void *intr_ctrl)
|
||||
{
|
||||
pci_dev_remove_intr_ctrl(intr_ctrl);
|
||||
}
|
||||
|
||||
static int devm_pci_dev_create_intr_ctrl(struct pci_dev *pdev)
|
||||
{
|
||||
struct pci_dev_intr_ctrl *intr_ctrl;
|
||||
|
||||
intr_ctrl = pci_dev_create_intr_ctrl(pdev);
|
||||
if (IS_ERR(intr_ctrl))
|
||||
return PTR_ERR(intr_ctrl);
|
||||
|
||||
return devm_add_action_or_reset(&pdev->dev, devm_pci_dev_remove_intr_ctrl, intr_ctrl);
|
||||
}
|
||||
|
||||
struct lan966x_pci {
|
||||
struct device *dev;
|
||||
int ovcs_id;
|
||||
};
|
||||
|
||||
static int lan966x_pci_load_overlay(struct lan966x_pci *data)
|
||||
{
|
||||
u32 dtbo_size = __dtbo_lan966x_pci_end - __dtbo_lan966x_pci_begin;
|
||||
void *dtbo_start = __dtbo_lan966x_pci_begin;
|
||||
|
||||
return of_overlay_fdt_apply(dtbo_start, dtbo_size, &data->ovcs_id, dev_of_node(data->dev));
|
||||
}
|
||||
|
||||
static void lan966x_pci_unload_overlay(struct lan966x_pci *data)
|
||||
{
|
||||
of_overlay_remove(&data->ovcs_id);
|
||||
}
|
||||
|
||||
static int lan966x_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct lan966x_pci *data;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* On ACPI system, fwnode can point to the ACPI node.
|
||||
* This driver needs an of_node to be used as the device-tree overlay
|
||||
* target. This of_node should be set by the PCI core if it succeeds in
|
||||
* creating it (CONFIG_PCI_DYNAMIC_OF_NODES feature).
|
||||
* Check here for the validity of this of_node.
|
||||
*/
|
||||
if (!dev_of_node(dev))
|
||||
return dev_err_probe(dev, -EINVAL, "Missing of_node for device\n");
|
||||
|
||||
/* Need to be done before devm_pci_dev_create_intr_ctrl.
|
||||
* It allocates an IRQ and so pdev->irq is updated.
|
||||
*/
|
||||
ret = pcim_enable_device(pdev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = devm_pci_dev_create_intr_ctrl(pdev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
pci_set_drvdata(pdev, data);
|
||||
data->dev = dev;
|
||||
|
||||
ret = lan966x_pci_load_overlay(data);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
pci_set_master(pdev);
|
||||
|
||||
ret = of_platform_default_populate(dev_of_node(dev), NULL, dev);
|
||||
if (ret)
|
||||
goto err_unload_overlay;
|
||||
|
||||
return 0;
|
||||
|
||||
err_unload_overlay:
|
||||
lan966x_pci_unload_overlay(data);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void lan966x_pci_remove(struct pci_dev *pdev)
|
||||
{
|
||||
struct lan966x_pci *data = pci_get_drvdata(pdev);
|
||||
|
||||
of_platform_depopulate(data->dev);
|
||||
|
||||
lan966x_pci_unload_overlay(data);
|
||||
}
|
||||
|
||||
static struct pci_device_id lan966x_pci_ids[] = {
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_EFAR, 0x9660) },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, lan966x_pci_ids);
|
||||
|
||||
static struct pci_driver lan966x_pci_driver = {
|
||||
.name = "mchp_lan966x_pci",
|
||||
.id_table = lan966x_pci_ids,
|
||||
.probe = lan966x_pci_probe,
|
||||
.remove = lan966x_pci_remove,
|
||||
};
|
||||
module_pci_driver(lan966x_pci_driver);
|
||||
|
||||
MODULE_AUTHOR("Herve Codina <herve.codina@bootlin.com>");
|
||||
MODULE_DESCRIPTION("Microchip LAN966x PCI driver");
|
||||
MODULE_LICENSE("GPL");
|
177
drivers/misc/lan966x_pci.dtso
Normal file
177
drivers/misc/lan966x_pci.dtso
Normal file
@ -0,0 +1,177 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (C) 2022 Microchip UNG
|
||||
*/
|
||||
|
||||
#include <dt-bindings/clock/microchip,lan966x.h>
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
#include <dt-bindings/mfd/atmel-flexcom.h>
|
||||
#include <dt-bindings/phy/phy-lan966x-serdes.h>
|
||||
|
||||
/dts-v1/;
|
||||
/plugin/;
|
||||
|
||||
/ {
|
||||
fragment@0 {
|
||||
target-path = "";
|
||||
|
||||
/*
|
||||
* These properties allow to avoid a dtc warnings.
|
||||
* The real interrupt controller is the PCI device itself. It
|
||||
* is the node on which the device tree overlay will be applied.
|
||||
* This node has those properties.
|
||||
*/
|
||||
#interrupt-cells = <1>;
|
||||
interrupt-controller;
|
||||
|
||||
__overlay__ {
|
||||
#address-cells = <3>;
|
||||
#size-cells = <2>;
|
||||
|
||||
cpu_clk: clock-600000000 {
|
||||
compatible = "fixed-clock";
|
||||
#clock-cells = <0>;
|
||||
clock-frequency = <600000000>; /* CPU clock = 600MHz */
|
||||
};
|
||||
|
||||
ddr_clk: clock-30000000 {
|
||||
compatible = "fixed-clock";
|
||||
#clock-cells = <0>;
|
||||
clock-frequency = <30000000>; /* Fabric clock = 30MHz */
|
||||
};
|
||||
|
||||
sys_clk: clock-15625000 {
|
||||
compatible = "fixed-clock";
|
||||
#clock-cells = <0>;
|
||||
clock-frequency = <15625000>; /* System clock = 15.625MHz */
|
||||
};
|
||||
|
||||
pci-ep-bus@0 {
|
||||
compatible = "simple-bus";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
/*
|
||||
* map @0xe2000000 (32MB) to BAR0 (CPU)
|
||||
* map @0xe0000000 (16MB) to BAR1 (AMBA)
|
||||
*/
|
||||
ranges = <0xe2000000 0x00 0x00 0x00 0x2000000
|
||||
0xe0000000 0x01 0x00 0x00 0x1000000>;
|
||||
|
||||
oic: oic@e00c0120 {
|
||||
compatible = "microchip,lan966x-oic";
|
||||
#interrupt-cells = <2>;
|
||||
interrupt-controller;
|
||||
interrupts = <0>; /* PCI INTx assigned interrupt */
|
||||
reg = <0xe00c0120 0x190>;
|
||||
};
|
||||
|
||||
cpu_ctrl: syscon@e00c0000 {
|
||||
compatible = "microchip,lan966x-cpu-syscon", "syscon";
|
||||
reg = <0xe00c0000 0xa8>;
|
||||
};
|
||||
|
||||
reset: reset@e200400c {
|
||||
compatible = "microchip,lan966x-switch-reset";
|
||||
reg = <0xe200400c 0x4>, <0xe00c0000 0xa8>;
|
||||
reg-names = "gcb","cpu";
|
||||
#reset-cells = <1>;
|
||||
cpu-syscon = <&cpu_ctrl>;
|
||||
};
|
||||
|
||||
gpio: pinctrl@e2004064 {
|
||||
compatible = "microchip,lan966x-pinctrl";
|
||||
reg = <0xe2004064 0xb4>,
|
||||
<0xe2010024 0x138>;
|
||||
resets = <&reset 0>;
|
||||
reset-names = "switch";
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
gpio-ranges = <&gpio 0 0 78>;
|
||||
interrupt-parent = <&oic>;
|
||||
interrupt-controller;
|
||||
interrupts = <17 IRQ_TYPE_LEVEL_HIGH>;
|
||||
#interrupt-cells = <2>;
|
||||
|
||||
tod_pins: tod_pins {
|
||||
pins = "GPIO_36";
|
||||
function = "ptpsync_1";
|
||||
};
|
||||
|
||||
fc0_a_pins: fcb4-i2c-pins {
|
||||
/* RXD, TXD */
|
||||
pins = "GPIO_9", "GPIO_10";
|
||||
function = "fc0_a";
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
serdes: serdes@e202c000 {
|
||||
compatible = "microchip,lan966x-serdes";
|
||||
reg = <0xe202c000 0x9c>,
|
||||
<0xe2004010 0x4>;
|
||||
#phy-cells = <2>;
|
||||
};
|
||||
|
||||
mdio1: mdio@e200413c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
compatible = "microchip,lan966x-miim";
|
||||
reg = <0xe200413c 0x24>,
|
||||
<0xe2010020 0x4>;
|
||||
|
||||
resets = <&reset 0>;
|
||||
reset-names = "switch";
|
||||
|
||||
lan966x_phy0: ethernet-lan966x_phy@1 {
|
||||
reg = <1>;
|
||||
};
|
||||
|
||||
lan966x_phy1: ethernet-lan966x_phy@2 {
|
||||
reg = <2>;
|
||||
};
|
||||
};
|
||||
|
||||
switch: switch@e0000000 {
|
||||
compatible = "microchip,lan966x-switch";
|
||||
reg = <0xe0000000 0x0100000>,
|
||||
<0xe2000000 0x0800000>;
|
||||
reg-names = "cpu", "gcb";
|
||||
|
||||
interrupt-parent = <&oic>;
|
||||
interrupts = <12 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<9 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-names = "xtr", "ana";
|
||||
|
||||
resets = <&reset 0>;
|
||||
reset-names = "switch";
|
||||
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&tod_pins>;
|
||||
|
||||
ethernet-ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port0: port@0 {
|
||||
phy-handle = <&lan966x_phy0>;
|
||||
|
||||
reg = <0>;
|
||||
phy-mode = "gmii";
|
||||
phys = <&serdes 0 CU(0)>;
|
||||
};
|
||||
|
||||
port1: port@1 {
|
||||
phy-handle = <&lan966x_phy1>;
|
||||
|
||||
reg = <1>;
|
||||
phy-mode = "gmii";
|
||||
phys = <&serdes 1 CU(1)>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
@ -6266,6 +6266,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0xa76e, dpc_log_size);
|
||||
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_XILINX, 0x5020, of_pci_make_dev_node);
|
||||
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_XILINX, 0x5021, of_pci_make_dev_node);
|
||||
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_REDHAT, 0x0005, of_pci_make_dev_node);
|
||||
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_EFAR, 0x9660, of_pci_make_dev_node);
|
||||
|
||||
/*
|
||||
* Devices known to require a longer delay before first config space access
|
||||
|
@ -146,27 +146,13 @@ config RESET_LPC18XX
|
||||
This enables the reset controller driver for NXP LPC18xx/43xx SoCs.
|
||||
|
||||
config RESET_MCHP_SPARX5
|
||||
bool "Microchip Sparx5 reset driver"
|
||||
depends on ARCH_SPARX5 || SOC_LAN966 || COMPILE_TEST
|
||||
tristate "Microchip Sparx5 reset driver"
|
||||
depends on ARCH_SPARX5 || SOC_LAN966 || MCHP_LAN966X_PCI || COMPILE_TEST
|
||||
default y if SPARX5_SWITCH
|
||||
select MFD_SYSCON
|
||||
help
|
||||
This driver supports switch core reset for the Microchip Sparx5 SoC.
|
||||
|
||||
config RESET_MESON
|
||||
tristate "Meson Reset Driver"
|
||||
depends on ARCH_MESON || COMPILE_TEST
|
||||
default ARCH_MESON
|
||||
help
|
||||
This enables the reset driver for Amlogic Meson SoCs.
|
||||
|
||||
config RESET_MESON_AUDIO_ARB
|
||||
tristate "Meson Audio Memory Arbiter Reset Driver"
|
||||
depends on ARCH_MESON || COMPILE_TEST
|
||||
help
|
||||
This enables the reset driver for Audio Memory Arbiter of
|
||||
Amlogic's A113 based SoCs
|
||||
|
||||
config RESET_NPCM
|
||||
bool "NPCM BMC Reset Driver" if COMPILE_TEST
|
||||
default ARCH_NPCM
|
||||
@ -356,6 +342,7 @@ config RESET_ZYNQMP
|
||||
help
|
||||
This enables the reset controller driver for Xilinx ZynqMP SoCs.
|
||||
|
||||
source "drivers/reset/amlogic/Kconfig"
|
||||
source "drivers/reset/starfive/Kconfig"
|
||||
source "drivers/reset/sti/Kconfig"
|
||||
source "drivers/reset/hisilicon/Kconfig"
|
||||
|
@ -1,5 +1,6 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
obj-y += core.o
|
||||
obj-y += amlogic/
|
||||
obj-y += hisilicon/
|
||||
obj-y += starfive/
|
||||
obj-y += sti/
|
||||
@ -21,8 +22,6 @@ obj-$(CONFIG_RESET_K210) += reset-k210.o
|
||||
obj-$(CONFIG_RESET_LANTIQ) += reset-lantiq.o
|
||||
obj-$(CONFIG_RESET_LPC18XX) += reset-lpc18xx.o
|
||||
obj-$(CONFIG_RESET_MCHP_SPARX5) += reset-microchip-sparx5.o
|
||||
obj-$(CONFIG_RESET_MESON) += reset-meson.o
|
||||
obj-$(CONFIG_RESET_MESON_AUDIO_ARB) += reset-meson-audio-arb.o
|
||||
obj-$(CONFIG_RESET_NPCM) += reset-npcm.o
|
||||
obj-$(CONFIG_RESET_NUVOTON_MA35D1) += reset-ma35d1.o
|
||||
obj-$(CONFIG_RESET_PISTACHIO) += reset-pistachio.o
|
||||
|
27
drivers/reset/amlogic/Kconfig
Normal file
27
drivers/reset/amlogic/Kconfig
Normal file
@ -0,0 +1,27 @@
|
||||
config RESET_MESON_COMMON
|
||||
tristate
|
||||
select REGMAP
|
||||
|
||||
config RESET_MESON
|
||||
tristate "Meson Reset Driver"
|
||||
depends on ARCH_MESON || COMPILE_TEST
|
||||
default ARCH_MESON
|
||||
select REGMAP_MMIO
|
||||
select RESET_MESON_COMMON
|
||||
help
|
||||
This enables the reset driver for Amlogic SoCs.
|
||||
|
||||
config RESET_MESON_AUX
|
||||
tristate "Meson Reset Auxiliary Driver"
|
||||
depends on ARCH_MESON || COMPILE_TEST
|
||||
select AUXILIARY_BUS
|
||||
select RESET_MESON_COMMON
|
||||
help
|
||||
This enables the reset auxiliary driver for Amlogic SoCs.
|
||||
|
||||
config RESET_MESON_AUDIO_ARB
|
||||
tristate "Meson Audio Memory Arbiter Reset Driver"
|
||||
depends on ARCH_MESON || COMPILE_TEST
|
||||
help
|
||||
This enables the reset driver for Audio Memory Arbiter of
|
||||
Amlogic's A113 based SoCs
|
4
drivers/reset/amlogic/Makefile
Normal file
4
drivers/reset/amlogic/Makefile
Normal file
@ -0,0 +1,4 @@
|
||||
obj-$(CONFIG_RESET_MESON) += reset-meson.o
|
||||
obj-$(CONFIG_RESET_MESON_AUX) += reset-meson-aux.o
|
||||
obj-$(CONFIG_RESET_MESON_COMMON) += reset-meson-common.o
|
||||
obj-$(CONFIG_RESET_MESON_AUDIO_ARB) += reset-meson-audio-arb.o
|
136
drivers/reset/amlogic/reset-meson-aux.c
Normal file
136
drivers/reset/amlogic/reset-meson-aux.c
Normal file
@ -0,0 +1,136 @@
|
||||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Amlogic Meson Reset Auxiliary driver
|
||||
*
|
||||
* Copyright (c) 2024 BayLibre, SAS.
|
||||
* Author: Jerome Brunet <jbrunet@baylibre.com>
|
||||
*/
|
||||
|
||||
#include <linux/err.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/auxiliary_bus.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/reset-controller.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include "reset-meson.h"
|
||||
#include <soc/amlogic/reset-meson-aux.h>
|
||||
|
||||
static DEFINE_IDA(meson_rst_aux_ida);
|
||||
|
||||
struct meson_reset_adev {
|
||||
struct auxiliary_device adev;
|
||||
struct regmap *map;
|
||||
};
|
||||
|
||||
#define to_meson_reset_adev(_adev) \
|
||||
container_of((_adev), struct meson_reset_adev, adev)
|
||||
|
||||
static const struct meson_reset_param meson_g12a_audio_param = {
|
||||
.reset_ops = &meson_reset_toggle_ops,
|
||||
.reset_num = 26,
|
||||
.level_offset = 0x24,
|
||||
};
|
||||
|
||||
static const struct meson_reset_param meson_sm1_audio_param = {
|
||||
.reset_ops = &meson_reset_toggle_ops,
|
||||
.reset_num = 39,
|
||||
.level_offset = 0x28,
|
||||
};
|
||||
|
||||
static const struct auxiliary_device_id meson_reset_aux_ids[] = {
|
||||
{
|
||||
.name = "axg-audio-clkc.rst-g12a",
|
||||
.driver_data = (kernel_ulong_t)&meson_g12a_audio_param,
|
||||
}, {
|
||||
.name = "axg-audio-clkc.rst-sm1",
|
||||
.driver_data = (kernel_ulong_t)&meson_sm1_audio_param,
|
||||
}, {}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(auxiliary, meson_reset_aux_ids);
|
||||
|
||||
static int meson_reset_aux_probe(struct auxiliary_device *adev,
|
||||
const struct auxiliary_device_id *id)
|
||||
{
|
||||
const struct meson_reset_param *param =
|
||||
(const struct meson_reset_param *)(id->driver_data);
|
||||
struct meson_reset_adev *raux =
|
||||
to_meson_reset_adev(adev);
|
||||
|
||||
return meson_reset_controller_register(&adev->dev, raux->map, param);
|
||||
}
|
||||
|
||||
static struct auxiliary_driver meson_reset_aux_driver = {
|
||||
.probe = meson_reset_aux_probe,
|
||||
.id_table = meson_reset_aux_ids,
|
||||
};
|
||||
module_auxiliary_driver(meson_reset_aux_driver);
|
||||
|
||||
static void meson_rst_aux_release(struct device *dev)
|
||||
{
|
||||
struct auxiliary_device *adev = to_auxiliary_dev(dev);
|
||||
struct meson_reset_adev *raux =
|
||||
to_meson_reset_adev(adev);
|
||||
|
||||
ida_free(&meson_rst_aux_ida, adev->id);
|
||||
kfree(raux);
|
||||
}
|
||||
|
||||
static void meson_rst_aux_unregister_adev(void *_adev)
|
||||
{
|
||||
struct auxiliary_device *adev = _adev;
|
||||
|
||||
auxiliary_device_delete(adev);
|
||||
auxiliary_device_uninit(adev);
|
||||
}
|
||||
|
||||
int devm_meson_rst_aux_register(struct device *dev,
|
||||
struct regmap *map,
|
||||
const char *adev_name)
|
||||
{
|
||||
struct meson_reset_adev *raux;
|
||||
struct auxiliary_device *adev;
|
||||
int ret;
|
||||
|
||||
raux = kzalloc(sizeof(*raux), GFP_KERNEL);
|
||||
if (!raux)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = ida_alloc(&meson_rst_aux_ida, GFP_KERNEL);
|
||||
if (ret < 0)
|
||||
goto raux_free;
|
||||
|
||||
raux->map = map;
|
||||
|
||||
adev = &raux->adev;
|
||||
adev->id = ret;
|
||||
adev->name = adev_name;
|
||||
adev->dev.parent = dev;
|
||||
adev->dev.release = meson_rst_aux_release;
|
||||
device_set_of_node_from_dev(&adev->dev, dev);
|
||||
|
||||
ret = auxiliary_device_init(adev);
|
||||
if (ret)
|
||||
goto ida_free;
|
||||
|
||||
ret = __auxiliary_device_add(adev, dev->driver->name);
|
||||
if (ret) {
|
||||
auxiliary_device_uninit(adev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return devm_add_action_or_reset(dev, meson_rst_aux_unregister_adev,
|
||||
adev);
|
||||
|
||||
ida_free:
|
||||
ida_free(&meson_rst_aux_ida, adev->id);
|
||||
raux_free:
|
||||
kfree(raux);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devm_meson_rst_aux_register);
|
||||
|
||||
MODULE_DESCRIPTION("Amlogic Meson Reset Auxiliary driver");
|
||||
MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>");
|
||||
MODULE_LICENSE("Dual BSD/GPL");
|
||||
MODULE_IMPORT_NS(MESON_RESET);
|
142
drivers/reset/amlogic/reset-meson-common.c
Normal file
142
drivers/reset/amlogic/reset-meson-common.c
Normal file
@ -0,0 +1,142 @@
|
||||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Amlogic Meson Reset core functions
|
||||
*
|
||||
* Copyright (c) 2016-2024 BayLibre, SAS.
|
||||
* Authors: Neil Armstrong <narmstrong@baylibre.com>
|
||||
* Jerome Brunet <jbrunet@baylibre.com>
|
||||
*/
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/reset-controller.h>
|
||||
|
||||
#include "reset-meson.h"
|
||||
|
||||
struct meson_reset {
|
||||
const struct meson_reset_param *param;
|
||||
struct reset_controller_dev rcdev;
|
||||
struct regmap *map;
|
||||
};
|
||||
|
||||
static void meson_reset_offset_and_bit(struct meson_reset *data,
|
||||
unsigned long id,
|
||||
unsigned int *offset,
|
||||
unsigned int *bit)
|
||||
{
|
||||
unsigned int stride = regmap_get_reg_stride(data->map);
|
||||
|
||||
*offset = (id / (stride * BITS_PER_BYTE)) * stride;
|
||||
*bit = id % (stride * BITS_PER_BYTE);
|
||||
}
|
||||
|
||||
static int meson_reset_reset(struct reset_controller_dev *rcdev,
|
||||
unsigned long id)
|
||||
{
|
||||
struct meson_reset *data =
|
||||
container_of(rcdev, struct meson_reset, rcdev);
|
||||
unsigned int offset, bit;
|
||||
|
||||
meson_reset_offset_and_bit(data, id, &offset, &bit);
|
||||
offset += data->param->reset_offset;
|
||||
|
||||
return regmap_write(data->map, offset, BIT(bit));
|
||||
}
|
||||
|
||||
static int meson_reset_level(struct reset_controller_dev *rcdev,
|
||||
unsigned long id, bool assert)
|
||||
{
|
||||
struct meson_reset *data =
|
||||
container_of(rcdev, struct meson_reset, rcdev);
|
||||
unsigned int offset, bit;
|
||||
|
||||
meson_reset_offset_and_bit(data, id, &offset, &bit);
|
||||
offset += data->param->level_offset;
|
||||
assert ^= data->param->level_low_reset;
|
||||
|
||||
return regmap_update_bits(data->map, offset,
|
||||
BIT(bit), assert ? BIT(bit) : 0);
|
||||
}
|
||||
|
||||
static int meson_reset_status(struct reset_controller_dev *rcdev,
|
||||
unsigned long id)
|
||||
{
|
||||
struct meson_reset *data =
|
||||
container_of(rcdev, struct meson_reset, rcdev);
|
||||
unsigned int val, offset, bit;
|
||||
|
||||
meson_reset_offset_and_bit(data, id, &offset, &bit);
|
||||
offset += data->param->level_offset;
|
||||
|
||||
regmap_read(data->map, offset, &val);
|
||||
val = !!(BIT(bit) & val);
|
||||
|
||||
return val ^ data->param->level_low_reset;
|
||||
}
|
||||
|
||||
static int meson_reset_assert(struct reset_controller_dev *rcdev,
|
||||
unsigned long id)
|
||||
{
|
||||
return meson_reset_level(rcdev, id, true);
|
||||
}
|
||||
|
||||
static int meson_reset_deassert(struct reset_controller_dev *rcdev,
|
||||
unsigned long id)
|
||||
{
|
||||
return meson_reset_level(rcdev, id, false);
|
||||
}
|
||||
|
||||
static int meson_reset_level_toggle(struct reset_controller_dev *rcdev,
|
||||
unsigned long id)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = meson_reset_assert(rcdev, id);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return meson_reset_deassert(rcdev, id);
|
||||
}
|
||||
|
||||
const struct reset_control_ops meson_reset_ops = {
|
||||
.reset = meson_reset_reset,
|
||||
.assert = meson_reset_assert,
|
||||
.deassert = meson_reset_deassert,
|
||||
.status = meson_reset_status,
|
||||
};
|
||||
EXPORT_SYMBOL_NS_GPL(meson_reset_ops, MESON_RESET);
|
||||
|
||||
const struct reset_control_ops meson_reset_toggle_ops = {
|
||||
.reset = meson_reset_level_toggle,
|
||||
.assert = meson_reset_assert,
|
||||
.deassert = meson_reset_deassert,
|
||||
.status = meson_reset_status,
|
||||
};
|
||||
EXPORT_SYMBOL_NS_GPL(meson_reset_toggle_ops, MESON_RESET);
|
||||
|
||||
int meson_reset_controller_register(struct device *dev, struct regmap *map,
|
||||
const struct meson_reset_param *param)
|
||||
{
|
||||
struct meson_reset *data;
|
||||
|
||||
data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
data->param = param;
|
||||
data->map = map;
|
||||
data->rcdev.owner = dev->driver->owner;
|
||||
data->rcdev.nr_resets = param->reset_num;
|
||||
data->rcdev.ops = data->param->reset_ops;
|
||||
data->rcdev.of_node = dev->of_node;
|
||||
|
||||
return devm_reset_controller_register(dev, &data->rcdev);
|
||||
}
|
||||
EXPORT_SYMBOL_NS_GPL(meson_reset_controller_register, MESON_RESET);
|
||||
|
||||
MODULE_DESCRIPTION("Amlogic Meson Reset Core function");
|
||||
MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>");
|
||||
MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>");
|
||||
MODULE_LICENSE("Dual BSD/GPL");
|
||||
MODULE_IMPORT_NS(MESON_RESET);
|
105
drivers/reset/amlogic/reset-meson.c
Normal file
105
drivers/reset/amlogic/reset-meson.c
Normal file
@ -0,0 +1,105 @@
|
||||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Amlogic Meson Reset Controller driver
|
||||
*
|
||||
* Copyright (c) 2016-2024 BayLibre, SAS.
|
||||
* Authors: Neil Armstrong <narmstrong@baylibre.com>
|
||||
* Jerome Brunet <jbrunet@baylibre.com>
|
||||
*/
|
||||
|
||||
#include <linux/err.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/reset-controller.h>
|
||||
|
||||
#include "reset-meson.h"
|
||||
|
||||
static const struct meson_reset_param meson8b_param = {
|
||||
.reset_ops = &meson_reset_ops,
|
||||
.reset_num = 256,
|
||||
.reset_offset = 0x0,
|
||||
.level_offset = 0x7c,
|
||||
.level_low_reset = true,
|
||||
};
|
||||
|
||||
static const struct meson_reset_param meson_a1_param = {
|
||||
.reset_ops = &meson_reset_ops,
|
||||
.reset_num = 96,
|
||||
.reset_offset = 0x0,
|
||||
.level_offset = 0x40,
|
||||
.level_low_reset = true,
|
||||
};
|
||||
|
||||
static const struct meson_reset_param meson_s4_param = {
|
||||
.reset_ops = &meson_reset_ops,
|
||||
.reset_num = 192,
|
||||
.reset_offset = 0x0,
|
||||
.level_offset = 0x40,
|
||||
.level_low_reset = true,
|
||||
};
|
||||
|
||||
static const struct meson_reset_param t7_param = {
|
||||
.reset_num = 224,
|
||||
.reset_offset = 0x0,
|
||||
.level_offset = 0x40,
|
||||
.level_low_reset = true,
|
||||
};
|
||||
|
||||
static const struct of_device_id meson_reset_dt_ids[] = {
|
||||
{ .compatible = "amlogic,meson8b-reset", .data = &meson8b_param},
|
||||
{ .compatible = "amlogic,meson-gxbb-reset", .data = &meson8b_param},
|
||||
{ .compatible = "amlogic,meson-axg-reset", .data = &meson8b_param},
|
||||
{ .compatible = "amlogic,meson-a1-reset", .data = &meson_a1_param},
|
||||
{ .compatible = "amlogic,meson-s4-reset", .data = &meson_s4_param},
|
||||
{ .compatible = "amlogic,c3-reset", .data = &meson_s4_param},
|
||||
{ .compatible = "amlogic,t7-reset", .data = &t7_param},
|
||||
{ /* sentinel */ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, meson_reset_dt_ids);
|
||||
|
||||
static const struct regmap_config regmap_config = {
|
||||
.reg_bits = 32,
|
||||
.val_bits = 32,
|
||||
.reg_stride = 4,
|
||||
};
|
||||
|
||||
static int meson_reset_probe(struct platform_device *pdev)
|
||||
{
|
||||
const struct meson_reset_param *param;
|
||||
struct device *dev = &pdev->dev;
|
||||
struct regmap *map;
|
||||
void __iomem *base;
|
||||
|
||||
base = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(base))
|
||||
return PTR_ERR(base);
|
||||
|
||||
param = device_get_match_data(dev);
|
||||
if (!param)
|
||||
return -ENODEV;
|
||||
|
||||
map = devm_regmap_init_mmio(dev, base, ®map_config);
|
||||
if (IS_ERR(map))
|
||||
return dev_err_probe(dev, PTR_ERR(map),
|
||||
"can't init regmap mmio region\n");
|
||||
|
||||
return meson_reset_controller_register(dev, map, param);
|
||||
}
|
||||
|
||||
static struct platform_driver meson_reset_driver = {
|
||||
.probe = meson_reset_probe,
|
||||
.driver = {
|
||||
.name = "meson_reset",
|
||||
.of_match_table = meson_reset_dt_ids,
|
||||
},
|
||||
};
|
||||
module_platform_driver(meson_reset_driver);
|
||||
|
||||
MODULE_DESCRIPTION("Amlogic Meson Reset Controller driver");
|
||||
MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>");
|
||||
MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>");
|
||||
MODULE_LICENSE("Dual BSD/GPL");
|
||||
MODULE_IMPORT_NS(MESON_RESET);
|
28
drivers/reset/amlogic/reset-meson.h
Normal file
28
drivers/reset/amlogic/reset-meson.h
Normal file
@ -0,0 +1,28 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (c) 2024 BayLibre, SAS.
|
||||
* Author: Jerome Brunet <jbrunet@baylibre.com>
|
||||
*/
|
||||
|
||||
#ifndef __MESON_RESET_H
|
||||
#define __MESON_RESET_H
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/reset-controller.h>
|
||||
|
||||
struct meson_reset_param {
|
||||
const struct reset_control_ops *reset_ops;
|
||||
unsigned int reset_num;
|
||||
unsigned int reset_offset;
|
||||
unsigned int level_offset;
|
||||
bool level_low_reset;
|
||||
};
|
||||
|
||||
int meson_reset_controller_register(struct device *dev, struct regmap *map,
|
||||
const struct meson_reset_param *param);
|
||||
|
||||
extern const struct reset_control_ops meson_reset_ops;
|
||||
extern const struct reset_control_ops meson_reset_toggle_ops;
|
||||
|
||||
#endif /* __MESON_RESET_H */
|
@ -773,12 +773,19 @@ EXPORT_SYMBOL_GPL(reset_control_bulk_release);
|
||||
|
||||
static struct reset_control *
|
||||
__reset_control_get_internal(struct reset_controller_dev *rcdev,
|
||||
unsigned int index, bool shared, bool acquired)
|
||||
unsigned int index, enum reset_control_flags flags)
|
||||
{
|
||||
bool shared = flags & RESET_CONTROL_FLAGS_BIT_SHARED;
|
||||
bool acquired = flags & RESET_CONTROL_FLAGS_BIT_ACQUIRED;
|
||||
struct reset_control *rstc;
|
||||
|
||||
lockdep_assert_held(&reset_list_mutex);
|
||||
|
||||
/* Expect callers to filter out OPTIONAL and DEASSERTED bits */
|
||||
if (WARN_ON(flags & ~(RESET_CONTROL_FLAGS_BIT_SHARED |
|
||||
RESET_CONTROL_FLAGS_BIT_ACQUIRED)))
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
list_for_each_entry(rstc, &rcdev->reset_control_head, list) {
|
||||
if (rstc->id == index) {
|
||||
/*
|
||||
@ -994,8 +1001,9 @@ static struct reset_controller_dev *__reset_find_rcdev(const struct of_phandle_a
|
||||
|
||||
struct reset_control *
|
||||
__of_reset_control_get(struct device_node *node, const char *id, int index,
|
||||
bool shared, bool optional, bool acquired)
|
||||
enum reset_control_flags flags)
|
||||
{
|
||||
bool optional = flags & RESET_CONTROL_FLAGS_BIT_OPTIONAL;
|
||||
bool gpio_fallback = false;
|
||||
struct reset_control *rstc;
|
||||
struct reset_controller_dev *rcdev;
|
||||
@ -1059,8 +1067,10 @@ __of_reset_control_get(struct device_node *node, const char *id, int index,
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
flags &= ~RESET_CONTROL_FLAGS_BIT_OPTIONAL;
|
||||
|
||||
/* reset_list_mutex also protects the rcdev's reset_control list */
|
||||
rstc = __reset_control_get_internal(rcdev, rstc_id, shared, acquired);
|
||||
rstc = __reset_control_get_internal(rcdev, rstc_id, flags);
|
||||
|
||||
out_unlock:
|
||||
mutex_unlock(&reset_list_mutex);
|
||||
@ -1091,8 +1101,9 @@ __reset_controller_by_name(const char *name)
|
||||
|
||||
static struct reset_control *
|
||||
__reset_control_get_from_lookup(struct device *dev, const char *con_id,
|
||||
bool shared, bool optional, bool acquired)
|
||||
enum reset_control_flags flags)
|
||||
{
|
||||
bool optional = flags & RESET_CONTROL_FLAGS_BIT_OPTIONAL;
|
||||
const struct reset_control_lookup *lookup;
|
||||
struct reset_controller_dev *rcdev;
|
||||
const char *dev_id = dev_name(dev);
|
||||
@ -1116,9 +1127,11 @@ __reset_control_get_from_lookup(struct device *dev, const char *con_id,
|
||||
return ERR_PTR(-EPROBE_DEFER);
|
||||
}
|
||||
|
||||
flags &= ~RESET_CONTROL_FLAGS_BIT_OPTIONAL;
|
||||
|
||||
rstc = __reset_control_get_internal(rcdev,
|
||||
lookup->index,
|
||||
shared, acquired);
|
||||
flags);
|
||||
mutex_unlock(&reset_list_mutex);
|
||||
break;
|
||||
}
|
||||
@ -1133,30 +1146,29 @@ __reset_control_get_from_lookup(struct device *dev, const char *con_id,
|
||||
}
|
||||
|
||||
struct reset_control *__reset_control_get(struct device *dev, const char *id,
|
||||
int index, bool shared, bool optional,
|
||||
bool acquired)
|
||||
int index, enum reset_control_flags flags)
|
||||
{
|
||||
bool shared = flags & RESET_CONTROL_FLAGS_BIT_SHARED;
|
||||
bool acquired = flags & RESET_CONTROL_FLAGS_BIT_ACQUIRED;
|
||||
|
||||
if (WARN_ON(shared && acquired))
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
if (dev->of_node)
|
||||
return __of_reset_control_get(dev->of_node, id, index, shared,
|
||||
optional, acquired);
|
||||
return __of_reset_control_get(dev->of_node, id, index, flags);
|
||||
|
||||
return __reset_control_get_from_lookup(dev, id, shared, optional,
|
||||
acquired);
|
||||
return __reset_control_get_from_lookup(dev, id, flags);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(__reset_control_get);
|
||||
|
||||
int __reset_control_bulk_get(struct device *dev, int num_rstcs,
|
||||
struct reset_control_bulk_data *rstcs,
|
||||
bool shared, bool optional, bool acquired)
|
||||
enum reset_control_flags flags)
|
||||
{
|
||||
int ret, i;
|
||||
|
||||
for (i = 0; i < num_rstcs; i++) {
|
||||
rstcs[i].rstc = __reset_control_get(dev, rstcs[i].id, 0,
|
||||
shared, optional, acquired);
|
||||
rstcs[i].rstc = __reset_control_get(dev, rstcs[i].id, 0, flags);
|
||||
if (IS_ERR(rstcs[i].rstc)) {
|
||||
ret = PTR_ERR(rstcs[i].rstc);
|
||||
goto err;
|
||||
@ -1224,23 +1236,46 @@ static void devm_reset_control_release(struct device *dev, void *res)
|
||||
reset_control_put(*(struct reset_control **)res);
|
||||
}
|
||||
|
||||
static void devm_reset_control_release_deasserted(struct device *dev, void *res)
|
||||
{
|
||||
struct reset_control *rstc = *(struct reset_control **)res;
|
||||
|
||||
reset_control_assert(rstc);
|
||||
reset_control_put(rstc);
|
||||
}
|
||||
|
||||
struct reset_control *
|
||||
__devm_reset_control_get(struct device *dev, const char *id, int index,
|
||||
bool shared, bool optional, bool acquired)
|
||||
enum reset_control_flags flags)
|
||||
{
|
||||
struct reset_control **ptr, *rstc;
|
||||
bool deasserted = flags & RESET_CONTROL_FLAGS_BIT_DEASSERTED;
|
||||
|
||||
ptr = devres_alloc(devm_reset_control_release, sizeof(*ptr),
|
||||
ptr = devres_alloc(deasserted ? devm_reset_control_release_deasserted :
|
||||
devm_reset_control_release, sizeof(*ptr),
|
||||
GFP_KERNEL);
|
||||
if (!ptr)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
rstc = __reset_control_get(dev, id, index, shared, optional, acquired);
|
||||
flags &= ~RESET_CONTROL_FLAGS_BIT_DEASSERTED;
|
||||
|
||||
rstc = __reset_control_get(dev, id, index, flags);
|
||||
if (IS_ERR_OR_NULL(rstc)) {
|
||||
devres_free(ptr);
|
||||
return rstc;
|
||||
}
|
||||
|
||||
if (deasserted) {
|
||||
int ret;
|
||||
|
||||
ret = reset_control_deassert(rstc);
|
||||
if (ret) {
|
||||
reset_control_put(rstc);
|
||||
devres_free(ptr);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
}
|
||||
|
||||
*ptr = rstc;
|
||||
devres_add(dev, ptr);
|
||||
|
||||
@ -1260,24 +1295,45 @@ static void devm_reset_control_bulk_release(struct device *dev, void *res)
|
||||
reset_control_bulk_put(devres->num_rstcs, devres->rstcs);
|
||||
}
|
||||
|
||||
static void devm_reset_control_bulk_release_deasserted(struct device *dev, void *res)
|
||||
{
|
||||
struct reset_control_bulk_devres *devres = res;
|
||||
|
||||
reset_control_bulk_assert(devres->num_rstcs, devres->rstcs);
|
||||
reset_control_bulk_put(devres->num_rstcs, devres->rstcs);
|
||||
}
|
||||
|
||||
int __devm_reset_control_bulk_get(struct device *dev, int num_rstcs,
|
||||
struct reset_control_bulk_data *rstcs,
|
||||
bool shared, bool optional, bool acquired)
|
||||
enum reset_control_flags flags)
|
||||
{
|
||||
struct reset_control_bulk_devres *ptr;
|
||||
bool deasserted = flags & RESET_CONTROL_FLAGS_BIT_DEASSERTED;
|
||||
int ret;
|
||||
|
||||
ptr = devres_alloc(devm_reset_control_bulk_release, sizeof(*ptr),
|
||||
ptr = devres_alloc(deasserted ? devm_reset_control_bulk_release_deasserted :
|
||||
devm_reset_control_bulk_release, sizeof(*ptr),
|
||||
GFP_KERNEL);
|
||||
if (!ptr)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = __reset_control_bulk_get(dev, num_rstcs, rstcs, shared, optional, acquired);
|
||||
flags &= ~RESET_CONTROL_FLAGS_BIT_DEASSERTED;
|
||||
|
||||
ret = __reset_control_bulk_get(dev, num_rstcs, rstcs, flags);
|
||||
if (ret < 0) {
|
||||
devres_free(ptr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (deasserted) {
|
||||
ret = reset_control_bulk_deassert(num_rstcs, rstcs);
|
||||
if (ret) {
|
||||
reset_control_bulk_put(num_rstcs, rstcs);
|
||||
devres_free(ptr);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
ptr->num_rstcs = num_rstcs;
|
||||
ptr->rstcs = rstcs;
|
||||
devres_add(dev, ptr);
|
||||
@ -1298,6 +1354,7 @@ EXPORT_SYMBOL_GPL(__devm_reset_control_bulk_get);
|
||||
*/
|
||||
int __device_reset(struct device *dev, bool optional)
|
||||
{
|
||||
enum reset_control_flags flags;
|
||||
struct reset_control *rstc;
|
||||
int ret;
|
||||
|
||||
@ -1313,7 +1370,8 @@ int __device_reset(struct device *dev, bool optional)
|
||||
}
|
||||
#endif
|
||||
|
||||
rstc = __reset_control_get(dev, NULL, 0, 0, optional, true);
|
||||
flags = optional ? RESET_CONTROL_OPTIONAL_EXCLUSIVE : RESET_CONTROL_EXCLUSIVE;
|
||||
rstc = __reset_control_get(dev, NULL, 0, flags);
|
||||
if (IS_ERR(rstc))
|
||||
return PTR_ERR(rstc);
|
||||
|
||||
@ -1356,17 +1414,14 @@ static int of_reset_control_get_count(struct device_node *node)
|
||||
* device node.
|
||||
*
|
||||
* @np: device node for the device that requests the reset controls array
|
||||
* @shared: whether reset controls are shared or not
|
||||
* @optional: whether it is optional to get the reset controls
|
||||
* @acquired: only one reset control may be acquired for a given controller
|
||||
* and ID
|
||||
* @flags: whether reset controls are shared, optional, acquired
|
||||
*
|
||||
* Returns pointer to allocated reset_control on success or error on failure
|
||||
*/
|
||||
struct reset_control *
|
||||
of_reset_control_array_get(struct device_node *np, bool shared, bool optional,
|
||||
bool acquired)
|
||||
of_reset_control_array_get(struct device_node *np, enum reset_control_flags flags)
|
||||
{
|
||||
bool optional = flags & RESET_CONTROL_FLAGS_BIT_OPTIONAL;
|
||||
struct reset_control_array *resets;
|
||||
struct reset_control *rstc;
|
||||
int num, i;
|
||||
@ -1381,8 +1436,7 @@ of_reset_control_array_get(struct device_node *np, bool shared, bool optional,
|
||||
resets->num_rstcs = num;
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
rstc = __of_reset_control_get(np, NULL, i, shared, optional,
|
||||
acquired);
|
||||
rstc = __of_reset_control_get(np, NULL, i, flags);
|
||||
if (IS_ERR(rstc))
|
||||
goto err_rst;
|
||||
resets->rstc[i] = rstc;
|
||||
@ -1407,8 +1461,7 @@ EXPORT_SYMBOL_GPL(of_reset_control_array_get);
|
||||
* devm_reset_control_array_get - Resource managed reset control array get
|
||||
*
|
||||
* @dev: device that requests the list of reset controls
|
||||
* @shared: whether reset controls are shared or not
|
||||
* @optional: whether it is optional to get the reset controls
|
||||
* @flags: whether reset controls are shared, optional, acquired
|
||||
*
|
||||
* The reset control array APIs are intended for a list of resets
|
||||
* that just have to be asserted or deasserted, without any
|
||||
@ -1417,7 +1470,7 @@ EXPORT_SYMBOL_GPL(of_reset_control_array_get);
|
||||
* Returns pointer to allocated reset_control on success or error on failure
|
||||
*/
|
||||
struct reset_control *
|
||||
devm_reset_control_array_get(struct device *dev, bool shared, bool optional)
|
||||
devm_reset_control_array_get(struct device *dev, enum reset_control_flags flags)
|
||||
{
|
||||
struct reset_control **ptr, *rstc;
|
||||
|
||||
@ -1426,7 +1479,7 @@ devm_reset_control_array_get(struct device *dev, bool shared, bool optional)
|
||||
if (!ptr)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
rstc = of_reset_control_array_get(dev->of_node, shared, optional, true);
|
||||
rstc = of_reset_control_array_get(dev->of_node, flags);
|
||||
if (IS_ERR_OR_NULL(rstc)) {
|
||||
devres_free(ptr);
|
||||
return rstc;
|
||||
|
@ -1,159 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Amlogic Meson Reset Controller driver
|
||||
*
|
||||
* Copyright (c) 2016 BayLibre, SAS.
|
||||
* Author: Neil Armstrong <narmstrong@baylibre.com>
|
||||
*/
|
||||
#include <linux/err.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/reset-controller.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#define BITS_PER_REG 32
|
||||
|
||||
struct meson_reset_param {
|
||||
int reg_count;
|
||||
int level_offset;
|
||||
};
|
||||
|
||||
struct meson_reset {
|
||||
void __iomem *reg_base;
|
||||
const struct meson_reset_param *param;
|
||||
struct reset_controller_dev rcdev;
|
||||
spinlock_t lock;
|
||||
};
|
||||
|
||||
static int meson_reset_reset(struct reset_controller_dev *rcdev,
|
||||
unsigned long id)
|
||||
{
|
||||
struct meson_reset *data =
|
||||
container_of(rcdev, struct meson_reset, rcdev);
|
||||
unsigned int bank = id / BITS_PER_REG;
|
||||
unsigned int offset = id % BITS_PER_REG;
|
||||
void __iomem *reg_addr = data->reg_base + (bank << 2);
|
||||
|
||||
writel(BIT(offset), reg_addr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int meson_reset_level(struct reset_controller_dev *rcdev,
|
||||
unsigned long id, bool assert)
|
||||
{
|
||||
struct meson_reset *data =
|
||||
container_of(rcdev, struct meson_reset, rcdev);
|
||||
unsigned int bank = id / BITS_PER_REG;
|
||||
unsigned int offset = id % BITS_PER_REG;
|
||||
void __iomem *reg_addr;
|
||||
unsigned long flags;
|
||||
u32 reg;
|
||||
|
||||
reg_addr = data->reg_base + data->param->level_offset + (bank << 2);
|
||||
|
||||
spin_lock_irqsave(&data->lock, flags);
|
||||
|
||||
reg = readl(reg_addr);
|
||||
if (assert)
|
||||
writel(reg & ~BIT(offset), reg_addr);
|
||||
else
|
||||
writel(reg | BIT(offset), reg_addr);
|
||||
|
||||
spin_unlock_irqrestore(&data->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int meson_reset_assert(struct reset_controller_dev *rcdev,
|
||||
unsigned long id)
|
||||
{
|
||||
return meson_reset_level(rcdev, id, true);
|
||||
}
|
||||
|
||||
static int meson_reset_deassert(struct reset_controller_dev *rcdev,
|
||||
unsigned long id)
|
||||
{
|
||||
return meson_reset_level(rcdev, id, false);
|
||||
}
|
||||
|
||||
static const struct reset_control_ops meson_reset_ops = {
|
||||
.reset = meson_reset_reset,
|
||||
.assert = meson_reset_assert,
|
||||
.deassert = meson_reset_deassert,
|
||||
};
|
||||
|
||||
static const struct meson_reset_param meson8b_param = {
|
||||
.reg_count = 8,
|
||||
.level_offset = 0x7c,
|
||||
};
|
||||
|
||||
static const struct meson_reset_param meson_a1_param = {
|
||||
.reg_count = 3,
|
||||
.level_offset = 0x40,
|
||||
};
|
||||
|
||||
static const struct meson_reset_param meson_s4_param = {
|
||||
.reg_count = 6,
|
||||
.level_offset = 0x40,
|
||||
};
|
||||
|
||||
static const struct meson_reset_param t7_param = {
|
||||
.reg_count = 7,
|
||||
.level_offset = 0x40,
|
||||
};
|
||||
|
||||
static const struct of_device_id meson_reset_dt_ids[] = {
|
||||
{ .compatible = "amlogic,meson8b-reset", .data = &meson8b_param},
|
||||
{ .compatible = "amlogic,meson-gxbb-reset", .data = &meson8b_param},
|
||||
{ .compatible = "amlogic,meson-axg-reset", .data = &meson8b_param},
|
||||
{ .compatible = "amlogic,meson-a1-reset", .data = &meson_a1_param},
|
||||
{ .compatible = "amlogic,meson-s4-reset", .data = &meson_s4_param},
|
||||
{ .compatible = "amlogic,c3-reset", .data = &meson_s4_param},
|
||||
{ .compatible = "amlogic,t7-reset", .data = &t7_param},
|
||||
{ /* sentinel */ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, meson_reset_dt_ids);
|
||||
|
||||
static int meson_reset_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct meson_reset *data;
|
||||
|
||||
data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
data->reg_base = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(data->reg_base))
|
||||
return PTR_ERR(data->reg_base);
|
||||
|
||||
data->param = of_device_get_match_data(&pdev->dev);
|
||||
if (!data->param)
|
||||
return -ENODEV;
|
||||
|
||||
spin_lock_init(&data->lock);
|
||||
|
||||
data->rcdev.owner = THIS_MODULE;
|
||||
data->rcdev.nr_resets = data->param->reg_count * BITS_PER_REG;
|
||||
data->rcdev.ops = &meson_reset_ops;
|
||||
data->rcdev.of_node = pdev->dev.of_node;
|
||||
|
||||
return devm_reset_controller_register(&pdev->dev, &data->rcdev);
|
||||
}
|
||||
|
||||
static struct platform_driver meson_reset_driver = {
|
||||
.probe = meson_reset_probe,
|
||||
.driver = {
|
||||
.name = "meson_reset",
|
||||
.of_match_table = meson_reset_dt_ids,
|
||||
},
|
||||
};
|
||||
module_platform_driver(meson_reset_driver);
|
||||
|
||||
MODULE_DESCRIPTION("Amlogic Meson Reset Controller driver");
|
||||
MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>");
|
||||
MODULE_LICENSE("Dual BSD/GPL");
|
@ -62,6 +62,28 @@ static const struct reset_control_ops sparx5_reset_ops = {
|
||||
.reset = sparx5_reset_noop,
|
||||
};
|
||||
|
||||
static const struct regmap_config mchp_lan966x_syscon_regmap_config = {
|
||||
.reg_bits = 32,
|
||||
.val_bits = 32,
|
||||
.reg_stride = 4,
|
||||
};
|
||||
|
||||
static struct regmap *mchp_lan966x_syscon_to_regmap(struct device *dev,
|
||||
struct device_node *syscon_np)
|
||||
{
|
||||
struct regmap_config regmap_config = mchp_lan966x_syscon_regmap_config;
|
||||
resource_size_t size;
|
||||
void __iomem *base;
|
||||
|
||||
base = devm_of_iomap(dev, syscon_np, 0, &size);
|
||||
if (IS_ERR(base))
|
||||
return ERR_CAST(base);
|
||||
|
||||
regmap_config.max_register = size - 4;
|
||||
|
||||
return devm_regmap_init_mmio(dev, base, ®map_config);
|
||||
}
|
||||
|
||||
static int mchp_sparx5_map_syscon(struct platform_device *pdev, char *name,
|
||||
struct regmap **target)
|
||||
{
|
||||
@ -72,7 +94,18 @@ static int mchp_sparx5_map_syscon(struct platform_device *pdev, char *name,
|
||||
syscon_np = of_parse_phandle(pdev->dev.of_node, name, 0);
|
||||
if (!syscon_np)
|
||||
return -ENODEV;
|
||||
regmap = syscon_node_to_regmap(syscon_np);
|
||||
|
||||
/*
|
||||
* The syscon API doesn't support syscon device removal.
|
||||
* When used in LAN966x PCI device, the cpu-syscon device needs to be
|
||||
* removed when the PCI device is removed.
|
||||
* In case of LAN966x, map the syscon device locally to support the
|
||||
* device removal.
|
||||
*/
|
||||
if (of_device_is_compatible(pdev->dev.of_node, "microchip,lan966x-switch-reset"))
|
||||
regmap = mchp_lan966x_syscon_to_regmap(&pdev->dev, syscon_np);
|
||||
else
|
||||
regmap = syscon_node_to_regmap(syscon_np);
|
||||
of_node_put(syscon_np);
|
||||
if (IS_ERR(regmap)) {
|
||||
err = PTR_ERR(regmap);
|
||||
@ -121,6 +154,7 @@ static int mchp_sparx5_reset_probe(struct platform_device *pdev)
|
||||
return err;
|
||||
|
||||
ctx->rcdev.owner = THIS_MODULE;
|
||||
ctx->rcdev.dev = &pdev->dev;
|
||||
ctx->rcdev.nr_resets = 1;
|
||||
ctx->rcdev.ops = &sparx5_reset_ops;
|
||||
ctx->rcdev.of_node = dn;
|
||||
@ -158,6 +192,7 @@ static const struct of_device_id mchp_sparx5_reset_of_match[] = {
|
||||
},
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, mchp_sparx5_reset_of_match);
|
||||
|
||||
static struct platform_driver mchp_sparx5_reset_driver = {
|
||||
.probe = mchp_sparx5_reset_probe,
|
||||
@ -180,3 +215,4 @@ postcore_initcall(mchp_sparx5_reset_init);
|
||||
|
||||
MODULE_DESCRIPTION("Microchip Sparx5 switch reset driver");
|
||||
MODULE_AUTHOR("Steen Hegelund <steen.hegelund@microchip.com>");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
@ -35,13 +35,6 @@ static void uniphier_clk_disable(void *_priv)
|
||||
clk_bulk_disable_unprepare(priv->data->nclks, priv->clk);
|
||||
}
|
||||
|
||||
static void uniphier_rst_assert(void *_priv)
|
||||
{
|
||||
struct uniphier_glue_reset_priv *priv = _priv;
|
||||
|
||||
reset_control_bulk_assert(priv->data->nrsts, priv->rst);
|
||||
}
|
||||
|
||||
static int uniphier_glue_reset_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
@ -68,13 +61,6 @@ static int uniphier_glue_reset_probe(struct platform_device *pdev)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
for (i = 0; i < priv->data->nrsts; i++)
|
||||
priv->rst[i].id = priv->data->reset_names[i];
|
||||
ret = devm_reset_control_bulk_get_shared(dev, priv->data->nrsts,
|
||||
priv->rst);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = clk_bulk_prepare_enable(priv->data->nclks, priv->clk);
|
||||
if (ret)
|
||||
return ret;
|
||||
@ -83,11 +69,11 @@ static int uniphier_glue_reset_probe(struct platform_device *pdev)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = reset_control_bulk_deassert(priv->data->nrsts, priv->rst);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = devm_add_action_or_reset(dev, uniphier_rst_assert, priv);
|
||||
for (i = 0; i < priv->data->nrsts; i++)
|
||||
priv->rst[i].id = priv->data->reset_names[i];
|
||||
ret = devm_reset_control_bulk_get_shared_deasserted(dev,
|
||||
priv->data->nrsts,
|
||||
priv->rst);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
@ -25,6 +25,48 @@ struct reset_control_bulk_data {
|
||||
struct reset_control *rstc;
|
||||
};
|
||||
|
||||
#define RESET_CONTROL_FLAGS_BIT_SHARED BIT(0) /* not exclusive */
|
||||
#define RESET_CONTROL_FLAGS_BIT_OPTIONAL BIT(1)
|
||||
#define RESET_CONTROL_FLAGS_BIT_ACQUIRED BIT(2) /* iff exclusive, not released */
|
||||
#define RESET_CONTROL_FLAGS_BIT_DEASSERTED BIT(3)
|
||||
|
||||
/**
|
||||
* enum reset_control_flags - Flags that can be passed to the reset_control_get functions
|
||||
* to determine the type of reset control.
|
||||
* These values cannot be OR'd.
|
||||
*
|
||||
* @RESET_CONTROL_EXCLUSIVE: exclusive, acquired,
|
||||
* @RESET_CONTROL_EXCLUSIVE_DEASSERTED: exclusive, acquired, deasserted
|
||||
* @RESET_CONTROL_EXCLUSIVE_RELEASED: exclusive, released,
|
||||
* @RESET_CONTROL_SHARED: shared
|
||||
* @RESET_CONTROL_SHARED_DEASSERTED: shared, deasserted
|
||||
* @RESET_CONTROL_OPTIONAL_EXCLUSIVE: optional, exclusive, acquired
|
||||
* @RESET_CONTROL_OPTIONAL_EXCLUSIVE_DEASSERTED: optional, exclusive, acquired, deasserted
|
||||
* @RESET_CONTROL_OPTIONAL_EXCLUSIVE_RELEASED: optional, exclusive, released
|
||||
* @RESET_CONTROL_OPTIONAL_SHARED: optional, shared
|
||||
* @RESET_CONTROL_OPTIONAL_SHARED_DEASSERTED: optional, shared, deasserted
|
||||
*/
|
||||
enum reset_control_flags {
|
||||
RESET_CONTROL_EXCLUSIVE = RESET_CONTROL_FLAGS_BIT_ACQUIRED,
|
||||
RESET_CONTROL_EXCLUSIVE_DEASSERTED = RESET_CONTROL_FLAGS_BIT_ACQUIRED |
|
||||
RESET_CONTROL_FLAGS_BIT_DEASSERTED,
|
||||
RESET_CONTROL_EXCLUSIVE_RELEASED = 0,
|
||||
RESET_CONTROL_SHARED = RESET_CONTROL_FLAGS_BIT_SHARED,
|
||||
RESET_CONTROL_SHARED_DEASSERTED = RESET_CONTROL_FLAGS_BIT_SHARED |
|
||||
RESET_CONTROL_FLAGS_BIT_DEASSERTED,
|
||||
RESET_CONTROL_OPTIONAL_EXCLUSIVE = RESET_CONTROL_FLAGS_BIT_OPTIONAL |
|
||||
RESET_CONTROL_FLAGS_BIT_ACQUIRED,
|
||||
RESET_CONTROL_OPTIONAL_EXCLUSIVE_DEASSERTED = RESET_CONTROL_FLAGS_BIT_OPTIONAL |
|
||||
RESET_CONTROL_FLAGS_BIT_ACQUIRED |
|
||||
RESET_CONTROL_FLAGS_BIT_DEASSERTED,
|
||||
RESET_CONTROL_OPTIONAL_EXCLUSIVE_RELEASED = RESET_CONTROL_FLAGS_BIT_OPTIONAL,
|
||||
RESET_CONTROL_OPTIONAL_SHARED = RESET_CONTROL_FLAGS_BIT_OPTIONAL |
|
||||
RESET_CONTROL_FLAGS_BIT_SHARED,
|
||||
RESET_CONTROL_OPTIONAL_SHARED_DEASSERTED = RESET_CONTROL_FLAGS_BIT_OPTIONAL |
|
||||
RESET_CONTROL_FLAGS_BIT_SHARED |
|
||||
RESET_CONTROL_FLAGS_BIT_DEASSERTED,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_RESET_CONTROLLER
|
||||
|
||||
int reset_control_reset(struct reset_control *rstc);
|
||||
@ -42,30 +84,25 @@ int reset_control_bulk_acquire(int num_rstcs, struct reset_control_bulk_data *rs
|
||||
void reset_control_bulk_release(int num_rstcs, struct reset_control_bulk_data *rstcs);
|
||||
|
||||
struct reset_control *__of_reset_control_get(struct device_node *node,
|
||||
const char *id, int index, bool shared,
|
||||
bool optional, bool acquired);
|
||||
const char *id, int index, enum reset_control_flags flags);
|
||||
struct reset_control *__reset_control_get(struct device *dev, const char *id,
|
||||
int index, bool shared,
|
||||
bool optional, bool acquired);
|
||||
int index, enum reset_control_flags flags);
|
||||
void reset_control_put(struct reset_control *rstc);
|
||||
int __reset_control_bulk_get(struct device *dev, int num_rstcs,
|
||||
struct reset_control_bulk_data *rstcs,
|
||||
bool shared, bool optional, bool acquired);
|
||||
enum reset_control_flags flags);
|
||||
void reset_control_bulk_put(int num_rstcs, struct reset_control_bulk_data *rstcs);
|
||||
|
||||
int __device_reset(struct device *dev, bool optional);
|
||||
struct reset_control *__devm_reset_control_get(struct device *dev,
|
||||
const char *id, int index, bool shared,
|
||||
bool optional, bool acquired);
|
||||
const char *id, int index, enum reset_control_flags flags);
|
||||
int __devm_reset_control_bulk_get(struct device *dev, int num_rstcs,
|
||||
struct reset_control_bulk_data *rstcs,
|
||||
bool shared, bool optional, bool acquired);
|
||||
enum reset_control_flags flags);
|
||||
|
||||
struct reset_control *devm_reset_control_array_get(struct device *dev,
|
||||
bool shared, bool optional);
|
||||
struct reset_control *of_reset_control_array_get(struct device_node *np,
|
||||
bool shared, bool optional,
|
||||
bool acquired);
|
||||
enum reset_control_flags flags);
|
||||
struct reset_control *of_reset_control_array_get(struct device_node *np, enum reset_control_flags);
|
||||
|
||||
int reset_control_get_count(struct device *dev);
|
||||
|
||||
@ -116,17 +153,19 @@ static inline int __device_reset(struct device *dev, bool optional)
|
||||
|
||||
static inline struct reset_control *__of_reset_control_get(
|
||||
struct device_node *node,
|
||||
const char *id, int index, bool shared,
|
||||
bool optional, bool acquired)
|
||||
const char *id, int index, enum reset_control_flags flags)
|
||||
{
|
||||
bool optional = flags & RESET_CONTROL_FLAGS_BIT_OPTIONAL;
|
||||
|
||||
return optional ? NULL : ERR_PTR(-ENOTSUPP);
|
||||
}
|
||||
|
||||
static inline struct reset_control *__reset_control_get(
|
||||
struct device *dev, const char *id,
|
||||
int index, bool shared, bool optional,
|
||||
bool acquired)
|
||||
int index, enum reset_control_flags flags)
|
||||
{
|
||||
bool optional = flags & RESET_CONTROL_FLAGS_BIT_OPTIONAL;
|
||||
|
||||
return optional ? NULL : ERR_PTR(-ENOTSUPP);
|
||||
}
|
||||
|
||||
@ -162,8 +201,10 @@ reset_control_bulk_release(int num_rstcs, struct reset_control_bulk_data *rstcs)
|
||||
static inline int
|
||||
__reset_control_bulk_get(struct device *dev, int num_rstcs,
|
||||
struct reset_control_bulk_data *rstcs,
|
||||
bool shared, bool optional, bool acquired)
|
||||
enum reset_control_flags flags)
|
||||
{
|
||||
bool optional = flags & RESET_CONTROL_FLAGS_BIT_OPTIONAL;
|
||||
|
||||
return optional ? 0 : -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
@ -174,30 +215,36 @@ reset_control_bulk_put(int num_rstcs, struct reset_control_bulk_data *rstcs)
|
||||
|
||||
static inline struct reset_control *__devm_reset_control_get(
|
||||
struct device *dev, const char *id,
|
||||
int index, bool shared, bool optional,
|
||||
bool acquired)
|
||||
int index, enum reset_control_flags flags)
|
||||
{
|
||||
bool optional = flags & RESET_CONTROL_FLAGS_BIT_OPTIONAL;
|
||||
|
||||
return optional ? NULL : ERR_PTR(-ENOTSUPP);
|
||||
}
|
||||
|
||||
static inline int
|
||||
__devm_reset_control_bulk_get(struct device *dev, int num_rstcs,
|
||||
struct reset_control_bulk_data *rstcs,
|
||||
bool shared, bool optional, bool acquired)
|
||||
enum reset_control_flags flags)
|
||||
{
|
||||
bool optional = flags & RESET_CONTROL_FLAGS_BIT_OPTIONAL;
|
||||
|
||||
return optional ? 0 : -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static inline struct reset_control *
|
||||
devm_reset_control_array_get(struct device *dev, bool shared, bool optional)
|
||||
devm_reset_control_array_get(struct device *dev, enum reset_control_flags flags)
|
||||
{
|
||||
bool optional = flags & RESET_CONTROL_FLAGS_BIT_OPTIONAL;
|
||||
|
||||
return optional ? NULL : ERR_PTR(-ENOTSUPP);
|
||||
}
|
||||
|
||||
static inline struct reset_control *
|
||||
of_reset_control_array_get(struct device_node *np, bool shared, bool optional,
|
||||
bool acquired)
|
||||
of_reset_control_array_get(struct device_node *np, enum reset_control_flags flags)
|
||||
{
|
||||
bool optional = flags & RESET_CONTROL_FLAGS_BIT_OPTIONAL;
|
||||
|
||||
return optional ? NULL : ERR_PTR(-ENOTSUPP);
|
||||
}
|
||||
|
||||
@ -236,7 +283,7 @@ static inline int device_reset_optional(struct device *dev)
|
||||
static inline struct reset_control *
|
||||
__must_check reset_control_get_exclusive(struct device *dev, const char *id)
|
||||
{
|
||||
return __reset_control_get(dev, id, 0, false, false, true);
|
||||
return __reset_control_get(dev, id, 0, RESET_CONTROL_EXCLUSIVE);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -253,7 +300,7 @@ static inline int __must_check
|
||||
reset_control_bulk_get_exclusive(struct device *dev, int num_rstcs,
|
||||
struct reset_control_bulk_data *rstcs)
|
||||
{
|
||||
return __reset_control_bulk_get(dev, num_rstcs, rstcs, false, false, true);
|
||||
return __reset_control_bulk_get(dev, num_rstcs, rstcs, RESET_CONTROL_EXCLUSIVE);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -274,7 +321,7 @@ static inline struct reset_control *
|
||||
__must_check reset_control_get_exclusive_released(struct device *dev,
|
||||
const char *id)
|
||||
{
|
||||
return __reset_control_get(dev, id, 0, false, false, false);
|
||||
return __reset_control_get(dev, id, 0, RESET_CONTROL_EXCLUSIVE_RELEASED);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -295,7 +342,7 @@ static inline int __must_check
|
||||
reset_control_bulk_get_exclusive_released(struct device *dev, int num_rstcs,
|
||||
struct reset_control_bulk_data *rstcs)
|
||||
{
|
||||
return __reset_control_bulk_get(dev, num_rstcs, rstcs, false, false, false);
|
||||
return __reset_control_bulk_get(dev, num_rstcs, rstcs, RESET_CONTROL_EXCLUSIVE_RELEASED);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -316,7 +363,8 @@ static inline int __must_check
|
||||
reset_control_bulk_get_optional_exclusive_released(struct device *dev, int num_rstcs,
|
||||
struct reset_control_bulk_data *rstcs)
|
||||
{
|
||||
return __reset_control_bulk_get(dev, num_rstcs, rstcs, false, true, false);
|
||||
return __reset_control_bulk_get(dev, num_rstcs, rstcs,
|
||||
RESET_CONTROL_OPTIONAL_EXCLUSIVE_RELEASED);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -344,7 +392,7 @@ reset_control_bulk_get_optional_exclusive_released(struct device *dev, int num_r
|
||||
static inline struct reset_control *reset_control_get_shared(
|
||||
struct device *dev, const char *id)
|
||||
{
|
||||
return __reset_control_get(dev, id, 0, true, false, false);
|
||||
return __reset_control_get(dev, id, 0, RESET_CONTROL_SHARED);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -361,7 +409,7 @@ static inline int __must_check
|
||||
reset_control_bulk_get_shared(struct device *dev, int num_rstcs,
|
||||
struct reset_control_bulk_data *rstcs)
|
||||
{
|
||||
return __reset_control_bulk_get(dev, num_rstcs, rstcs, true, false, false);
|
||||
return __reset_control_bulk_get(dev, num_rstcs, rstcs, RESET_CONTROL_SHARED);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -378,7 +426,7 @@ reset_control_bulk_get_shared(struct device *dev, int num_rstcs,
|
||||
static inline struct reset_control *reset_control_get_optional_exclusive(
|
||||
struct device *dev, const char *id)
|
||||
{
|
||||
return __reset_control_get(dev, id, 0, false, true, true);
|
||||
return __reset_control_get(dev, id, 0, RESET_CONTROL_OPTIONAL_EXCLUSIVE);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -398,7 +446,7 @@ static inline int __must_check
|
||||
reset_control_bulk_get_optional_exclusive(struct device *dev, int num_rstcs,
|
||||
struct reset_control_bulk_data *rstcs)
|
||||
{
|
||||
return __reset_control_bulk_get(dev, num_rstcs, rstcs, false, true, true);
|
||||
return __reset_control_bulk_get(dev, num_rstcs, rstcs, RESET_CONTROL_OPTIONAL_EXCLUSIVE);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -415,7 +463,7 @@ reset_control_bulk_get_optional_exclusive(struct device *dev, int num_rstcs,
|
||||
static inline struct reset_control *reset_control_get_optional_shared(
|
||||
struct device *dev, const char *id)
|
||||
{
|
||||
return __reset_control_get(dev, id, 0, true, true, false);
|
||||
return __reset_control_get(dev, id, 0, RESET_CONTROL_OPTIONAL_SHARED);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -435,7 +483,7 @@ static inline int __must_check
|
||||
reset_control_bulk_get_optional_shared(struct device *dev, int num_rstcs,
|
||||
struct reset_control_bulk_data *rstcs)
|
||||
{
|
||||
return __reset_control_bulk_get(dev, num_rstcs, rstcs, true, true, false);
|
||||
return __reset_control_bulk_get(dev, num_rstcs, rstcs, RESET_CONTROL_OPTIONAL_SHARED);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -451,7 +499,7 @@ reset_control_bulk_get_optional_shared(struct device *dev, int num_rstcs,
|
||||
static inline struct reset_control *of_reset_control_get_exclusive(
|
||||
struct device_node *node, const char *id)
|
||||
{
|
||||
return __of_reset_control_get(node, id, 0, false, false, true);
|
||||
return __of_reset_control_get(node, id, 0, RESET_CONTROL_EXCLUSIVE);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -471,7 +519,7 @@ static inline struct reset_control *of_reset_control_get_exclusive(
|
||||
static inline struct reset_control *of_reset_control_get_optional_exclusive(
|
||||
struct device_node *node, const char *id)
|
||||
{
|
||||
return __of_reset_control_get(node, id, 0, false, true, true);
|
||||
return __of_reset_control_get(node, id, 0, RESET_CONTROL_OPTIONAL_EXCLUSIVE);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -496,7 +544,7 @@ static inline struct reset_control *of_reset_control_get_optional_exclusive(
|
||||
static inline struct reset_control *of_reset_control_get_shared(
|
||||
struct device_node *node, const char *id)
|
||||
{
|
||||
return __of_reset_control_get(node, id, 0, true, false, false);
|
||||
return __of_reset_control_get(node, id, 0, RESET_CONTROL_SHARED);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -513,7 +561,7 @@ static inline struct reset_control *of_reset_control_get_shared(
|
||||
static inline struct reset_control *of_reset_control_get_exclusive_by_index(
|
||||
struct device_node *node, int index)
|
||||
{
|
||||
return __of_reset_control_get(node, NULL, index, false, false, true);
|
||||
return __of_reset_control_get(node, NULL, index, RESET_CONTROL_EXCLUSIVE);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -541,7 +589,7 @@ static inline struct reset_control *of_reset_control_get_exclusive_by_index(
|
||||
static inline struct reset_control *of_reset_control_get_shared_by_index(
|
||||
struct device_node *node, int index)
|
||||
{
|
||||
return __of_reset_control_get(node, NULL, index, true, false, false);
|
||||
return __of_reset_control_get(node, NULL, index, RESET_CONTROL_SHARED);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -560,7 +608,26 @@ static inline struct reset_control *
|
||||
__must_check devm_reset_control_get_exclusive(struct device *dev,
|
||||
const char *id)
|
||||
{
|
||||
return __devm_reset_control_get(dev, id, 0, false, false, true);
|
||||
return __devm_reset_control_get(dev, id, 0, RESET_CONTROL_EXCLUSIVE);
|
||||
}
|
||||
|
||||
/**
|
||||
* devm_reset_control_get_exclusive_deasserted - resource managed
|
||||
* reset_control_get_exclusive() +
|
||||
* reset_control_deassert()
|
||||
* @dev: device to be reset by the controller
|
||||
* @id: reset line name
|
||||
*
|
||||
* Managed reset_control_get_exclusive() + reset_control_deassert(). For reset
|
||||
* controllers returned from this function, reset_control_assert() +
|
||||
* reset_control_put() is called automatically on driver detach.
|
||||
*
|
||||
* See reset_control_get_exclusive() for more information.
|
||||
*/
|
||||
static inline struct reset_control * __must_check
|
||||
devm_reset_control_get_exclusive_deasserted(struct device *dev, const char *id)
|
||||
{
|
||||
return __devm_reset_control_get(dev, id, 0, RESET_CONTROL_EXCLUSIVE_DEASSERTED);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -580,7 +647,8 @@ static inline int __must_check
|
||||
devm_reset_control_bulk_get_exclusive(struct device *dev, int num_rstcs,
|
||||
struct reset_control_bulk_data *rstcs)
|
||||
{
|
||||
return __devm_reset_control_bulk_get(dev, num_rstcs, rstcs, false, false, true);
|
||||
return __devm_reset_control_bulk_get(dev, num_rstcs, rstcs,
|
||||
RESET_CONTROL_EXCLUSIVE);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -599,7 +667,7 @@ static inline struct reset_control *
|
||||
__must_check devm_reset_control_get_exclusive_released(struct device *dev,
|
||||
const char *id)
|
||||
{
|
||||
return __devm_reset_control_get(dev, id, 0, false, false, false);
|
||||
return __devm_reset_control_get(dev, id, 0, RESET_CONTROL_EXCLUSIVE_RELEASED);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -619,7 +687,8 @@ static inline int __must_check
|
||||
devm_reset_control_bulk_get_exclusive_released(struct device *dev, int num_rstcs,
|
||||
struct reset_control_bulk_data *rstcs)
|
||||
{
|
||||
return __devm_reset_control_bulk_get(dev, num_rstcs, rstcs, false, false, false);
|
||||
return __devm_reset_control_bulk_get(dev, num_rstcs, rstcs,
|
||||
RESET_CONTROL_EXCLUSIVE_RELEASED);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -638,7 +707,7 @@ static inline struct reset_control *
|
||||
__must_check devm_reset_control_get_optional_exclusive_released(struct device *dev,
|
||||
const char *id)
|
||||
{
|
||||
return __devm_reset_control_get(dev, id, 0, false, true, false);
|
||||
return __devm_reset_control_get(dev, id, 0, RESET_CONTROL_OPTIONAL_EXCLUSIVE_RELEASED);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -658,7 +727,8 @@ static inline int __must_check
|
||||
devm_reset_control_bulk_get_optional_exclusive_released(struct device *dev, int num_rstcs,
|
||||
struct reset_control_bulk_data *rstcs)
|
||||
{
|
||||
return __devm_reset_control_bulk_get(dev, num_rstcs, rstcs, false, true, false);
|
||||
return __devm_reset_control_bulk_get(dev, num_rstcs, rstcs,
|
||||
RESET_CONTROL_OPTIONAL_EXCLUSIVE_RELEASED);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -673,7 +743,26 @@ devm_reset_control_bulk_get_optional_exclusive_released(struct device *dev, int
|
||||
static inline struct reset_control *devm_reset_control_get_shared(
|
||||
struct device *dev, const char *id)
|
||||
{
|
||||
return __devm_reset_control_get(dev, id, 0, true, false, false);
|
||||
return __devm_reset_control_get(dev, id, 0, RESET_CONTROL_SHARED);
|
||||
}
|
||||
|
||||
/**
|
||||
* devm_reset_control_get_shared_deasserted - resource managed
|
||||
* reset_control_get_shared() +
|
||||
* reset_control_deassert()
|
||||
* @dev: device to be reset by the controller
|
||||
* @id: reset line name
|
||||
*
|
||||
* Managed reset_control_get_shared() + reset_control_deassert(). For reset
|
||||
* controllers returned from this function, reset_control_assert() +
|
||||
* reset_control_put() is called automatically on driver detach.
|
||||
*
|
||||
* See devm_reset_control_get_shared() for more information.
|
||||
*/
|
||||
static inline struct reset_control * __must_check
|
||||
devm_reset_control_get_shared_deasserted(struct device *dev, const char *id)
|
||||
{
|
||||
return __devm_reset_control_get(dev, id, 0, RESET_CONTROL_SHARED_DEASSERTED);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -693,7 +782,29 @@ static inline int __must_check
|
||||
devm_reset_control_bulk_get_shared(struct device *dev, int num_rstcs,
|
||||
struct reset_control_bulk_data *rstcs)
|
||||
{
|
||||
return __devm_reset_control_bulk_get(dev, num_rstcs, rstcs, true, false, false);
|
||||
return __devm_reset_control_bulk_get(dev, num_rstcs, rstcs, RESET_CONTROL_SHARED);
|
||||
}
|
||||
|
||||
/**
|
||||
* devm_reset_control_bulk_get_shared_deasserted - resource managed
|
||||
* reset_control_bulk_get_shared() +
|
||||
* reset_control_bulk_deassert()
|
||||
* @dev: device to be reset by the controller
|
||||
* @num_rstcs: number of entries in rstcs array
|
||||
* @rstcs: array of struct reset_control_bulk_data with reset line names set
|
||||
*
|
||||
* Managed reset_control_bulk_get_shared() + reset_control_bulk_deassert(). For
|
||||
* reset controllers returned from this function, reset_control_bulk_assert() +
|
||||
* reset_control_bulk_put() are called automatically on driver detach.
|
||||
*
|
||||
* See devm_reset_control_bulk_get_shared() for more information.
|
||||
*/
|
||||
static inline int __must_check
|
||||
devm_reset_control_bulk_get_shared_deasserted(struct device *dev, int num_rstcs,
|
||||
struct reset_control_bulk_data *rstcs)
|
||||
{
|
||||
return __devm_reset_control_bulk_get(dev, num_rstcs, rstcs,
|
||||
RESET_CONTROL_SHARED_DEASSERTED);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -711,7 +822,26 @@ devm_reset_control_bulk_get_shared(struct device *dev, int num_rstcs,
|
||||
static inline struct reset_control *devm_reset_control_get_optional_exclusive(
|
||||
struct device *dev, const char *id)
|
||||
{
|
||||
return __devm_reset_control_get(dev, id, 0, false, true, true);
|
||||
return __devm_reset_control_get(dev, id, 0, RESET_CONTROL_OPTIONAL_EXCLUSIVE);
|
||||
}
|
||||
|
||||
/**
|
||||
* devm_reset_control_get_optional_exclusive_deasserted - resource managed
|
||||
* reset_control_get_optional_exclusive() +
|
||||
* reset_control_deassert()
|
||||
* @dev: device to be reset by the controller
|
||||
* @id: reset line name
|
||||
*
|
||||
* Managed reset_control_get_optional_exclusive() + reset_control_deassert().
|
||||
* For reset controllers returned from this function, reset_control_assert() +
|
||||
* reset_control_put() is called automatically on driver detach.
|
||||
*
|
||||
* See devm_reset_control_get_optional_exclusive() for more information.
|
||||
*/
|
||||
static inline struct reset_control *
|
||||
devm_reset_control_get_optional_exclusive_deasserted(struct device *dev, const char *id)
|
||||
{
|
||||
return __devm_reset_control_get(dev, id, 0, RESET_CONTROL_OPTIONAL_EXCLUSIVE_DEASSERTED);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -731,7 +861,8 @@ static inline int __must_check
|
||||
devm_reset_control_bulk_get_optional_exclusive(struct device *dev, int num_rstcs,
|
||||
struct reset_control_bulk_data *rstcs)
|
||||
{
|
||||
return __devm_reset_control_bulk_get(dev, num_rstcs, rstcs, false, true, true);
|
||||
return __devm_reset_control_bulk_get(dev, num_rstcs, rstcs,
|
||||
RESET_CONTROL_OPTIONAL_EXCLUSIVE);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -749,7 +880,26 @@ devm_reset_control_bulk_get_optional_exclusive(struct device *dev, int num_rstcs
|
||||
static inline struct reset_control *devm_reset_control_get_optional_shared(
|
||||
struct device *dev, const char *id)
|
||||
{
|
||||
return __devm_reset_control_get(dev, id, 0, true, true, false);
|
||||
return __devm_reset_control_get(dev, id, 0, RESET_CONTROL_OPTIONAL_SHARED);
|
||||
}
|
||||
|
||||
/**
|
||||
* devm_reset_control_get_optional_shared_deasserted - resource managed
|
||||
* reset_control_get_optional_shared() +
|
||||
* reset_control_deassert()
|
||||
* @dev: device to be reset by the controller
|
||||
* @id: reset line name
|
||||
*
|
||||
* Managed reset_control_get_optional_shared() + reset_control_deassert(). For
|
||||
* reset controllers returned from this function, reset_control_assert() +
|
||||
* reset_control_put() is called automatically on driver detach.
|
||||
*
|
||||
* See devm_reset_control_get_optional_shared() for more information.
|
||||
*/
|
||||
static inline struct reset_control *
|
||||
devm_reset_control_get_optional_shared_deasserted(struct device *dev, const char *id)
|
||||
{
|
||||
return __devm_reset_control_get(dev, id, 0, RESET_CONTROL_OPTIONAL_SHARED_DEASSERTED);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -769,7 +919,7 @@ static inline int __must_check
|
||||
devm_reset_control_bulk_get_optional_shared(struct device *dev, int num_rstcs,
|
||||
struct reset_control_bulk_data *rstcs)
|
||||
{
|
||||
return __devm_reset_control_bulk_get(dev, num_rstcs, rstcs, true, true, false);
|
||||
return __devm_reset_control_bulk_get(dev, num_rstcs, rstcs, RESET_CONTROL_OPTIONAL_SHARED);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -787,7 +937,7 @@ devm_reset_control_bulk_get_optional_shared(struct device *dev, int num_rstcs,
|
||||
static inline struct reset_control *
|
||||
devm_reset_control_get_exclusive_by_index(struct device *dev, int index)
|
||||
{
|
||||
return __devm_reset_control_get(dev, NULL, index, false, false, true);
|
||||
return __devm_reset_control_get(dev, NULL, index, RESET_CONTROL_EXCLUSIVE);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -803,7 +953,7 @@ devm_reset_control_get_exclusive_by_index(struct device *dev, int index)
|
||||
static inline struct reset_control *
|
||||
devm_reset_control_get_shared_by_index(struct device *dev, int index)
|
||||
{
|
||||
return __devm_reset_control_get(dev, NULL, index, true, false, false);
|
||||
return __devm_reset_control_get(dev, NULL, index, RESET_CONTROL_SHARED);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -851,54 +1001,54 @@ static inline struct reset_control *devm_reset_control_get_by_index(
|
||||
static inline struct reset_control *
|
||||
devm_reset_control_array_get_exclusive(struct device *dev)
|
||||
{
|
||||
return devm_reset_control_array_get(dev, false, false);
|
||||
return devm_reset_control_array_get(dev, RESET_CONTROL_EXCLUSIVE);
|
||||
}
|
||||
|
||||
static inline struct reset_control *
|
||||
devm_reset_control_array_get_shared(struct device *dev)
|
||||
{
|
||||
return devm_reset_control_array_get(dev, true, false);
|
||||
return devm_reset_control_array_get(dev, RESET_CONTROL_SHARED);
|
||||
}
|
||||
|
||||
static inline struct reset_control *
|
||||
devm_reset_control_array_get_optional_exclusive(struct device *dev)
|
||||
{
|
||||
return devm_reset_control_array_get(dev, false, true);
|
||||
return devm_reset_control_array_get(dev, RESET_CONTROL_OPTIONAL_EXCLUSIVE);
|
||||
}
|
||||
|
||||
static inline struct reset_control *
|
||||
devm_reset_control_array_get_optional_shared(struct device *dev)
|
||||
{
|
||||
return devm_reset_control_array_get(dev, true, true);
|
||||
return devm_reset_control_array_get(dev, RESET_CONTROL_OPTIONAL_SHARED);
|
||||
}
|
||||
|
||||
static inline struct reset_control *
|
||||
of_reset_control_array_get_exclusive(struct device_node *node)
|
||||
{
|
||||
return of_reset_control_array_get(node, false, false, true);
|
||||
return of_reset_control_array_get(node, RESET_CONTROL_EXCLUSIVE);
|
||||
}
|
||||
|
||||
static inline struct reset_control *
|
||||
of_reset_control_array_get_exclusive_released(struct device_node *node)
|
||||
{
|
||||
return of_reset_control_array_get(node, false, false, false);
|
||||
return of_reset_control_array_get(node, RESET_CONTROL_EXCLUSIVE_RELEASED);
|
||||
}
|
||||
|
||||
static inline struct reset_control *
|
||||
of_reset_control_array_get_shared(struct device_node *node)
|
||||
{
|
||||
return of_reset_control_array_get(node, true, false, true);
|
||||
return of_reset_control_array_get(node, RESET_CONTROL_SHARED);
|
||||
}
|
||||
|
||||
static inline struct reset_control *
|
||||
of_reset_control_array_get_optional_exclusive(struct device_node *node)
|
||||
{
|
||||
return of_reset_control_array_get(node, false, true, true);
|
||||
return of_reset_control_array_get(node, RESET_CONTROL_OPTIONAL_EXCLUSIVE);
|
||||
}
|
||||
|
||||
static inline struct reset_control *
|
||||
of_reset_control_array_get_optional_shared(struct device_node *node)
|
||||
{
|
||||
return of_reset_control_array_get(node, true, true, true);
|
||||
return of_reset_control_array_get(node, RESET_CONTROL_OPTIONAL_SHARED);
|
||||
}
|
||||
#endif
|
||||
|
23
include/soc/amlogic/reset-meson-aux.h
Normal file
23
include/soc/amlogic/reset-meson-aux.h
Normal file
@ -0,0 +1,23 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef __SOC_RESET_MESON_AUX_H
|
||||
#define __SOC_RESET_MESON_AUX_H
|
||||
|
||||
#include <linux/err.h>
|
||||
|
||||
struct device;
|
||||
struct regmap;
|
||||
|
||||
#if IS_ENABLED(CONFIG_RESET_MESON_AUX)
|
||||
int devm_meson_rst_aux_register(struct device *dev,
|
||||
struct regmap *map,
|
||||
const char *adev_name);
|
||||
#else
|
||||
static inline int devm_meson_rst_aux_register(struct device *dev,
|
||||
struct regmap *map,
|
||||
const char *adev_name)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __SOC_RESET_MESON_AUX_H */
|
Loading…
Reference in New Issue
Block a user