diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-09-11 06:40:00 +0300 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-09-11 06:40:00 +0300 |
commit | ae46654bcff303b33facbbd04a3ad9c21d303f9b (patch) | |
tree | b0027d47d6c949162fa6ae306f34abeb76c559a9 /drivers/reset/reset-hsdk-v1.c | |
parent | 7f1b9be13a7dbe8e51ea541bbcd6c47adae39c71 (diff) | |
parent | a48a7b6b54927159bac77735df00e5b9fc3415fb (diff) | |
download | linux-ae46654bcff303b33facbbd04a3ad9c21d303f9b.tar.xz |
Merge tag 'armsoc-drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
Pull ARM SoC driver updates from Olof Johansson:
"This branch contains platform-related driver updates for ARM and ARM64.
Among them:
- Reset driver updates:
+ New API for dealing with arrays of resets
+ Make unimplemented {de,}assert return success on shared resets
+ MSDKv1 driver
+ Removal of obsolete Gemini reset driver
+ Misc updates for sunxi and Uniphier
- SoC drivers:
+ Platform SoC driver registration on Tegra
+ Shuffle of Qualcomm drivers into a submenu
+ Allwinner A64 support for SRAM
+ Renesas R-Car R3 support
+ Power domains for Rockchip RK3366
- Misc updates and smaller fixes for TEE and memory driver
subsystems"
* tag 'armsoc-drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (54 commits)
firmware: arm_scpi: fix endianness of dev_id in struct dev_pstate_set
soc/tegra: fuse: Add missing semi-colon
soc/tegra: Restrict SoC device registration to Tegra
drivers: soc: sunxi: add support for A64 and its SRAM C
drivers: soc: sunxi: add support for remapping func value to reg value
drivers: soc: sunxi: fix error processing on base address when claiming
dt-bindings: add binding for Allwinner A64 SRAM controller and SRAM C
bus: sunxi-rsb: Enable by default for ARM64
soc/tegra: Register SoC device
firmware: tegra: set drvdata earlier
memory: Convert to using %pOF instead of full_name
soc: Convert to using %pOF instead of full_name
bus: Convert to using %pOF instead of full_name
firmware: Convert to using %pOF instead of full_name
soc: mediatek: add SCPSYS power domain driver for MediaTek MT7622 SoC
soc: mediatek: add header files required for MT7622 SCPSYS dt-binding
soc: mediatek: reduce code duplication of scpsys_probe across all SoCs
dt-bindings: soc: update the binding document for SCPSYS on MediaTek MT7622 SoC
reset: uniphier: add analog amplifiers reset control
reset: uniphier: add video input subsystem reset control
...
Diffstat (limited to 'drivers/reset/reset-hsdk-v1.c')
-rw-r--r-- | drivers/reset/reset-hsdk-v1.c | 137 |
1 files changed, 137 insertions, 0 deletions
diff --git a/drivers/reset/reset-hsdk-v1.c b/drivers/reset/reset-hsdk-v1.c new file mode 100644 index 000000000000..bca13e4bf622 --- /dev/null +++ b/drivers/reset/reset-hsdk-v1.c @@ -0,0 +1,137 @@ +/* + * Copyright (C) 2017 Synopsys. + * + * Synopsys HSDKv1 SDP reset driver. + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include <linux/delay.h> +#include <linux/io.h> +#include <linux/iopoll.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/platform_device.h> +#include <linux/reset-controller.h> +#include <linux/slab.h> +#include <linux/types.h> + +#define to_hsdkv1_rst(p) container_of((p), struct hsdkv1_rst, rcdev) + +struct hsdkv1_rst { + void __iomem *regs_ctl; + void __iomem *regs_rst; + spinlock_t lock; + struct reset_controller_dev rcdev; +}; + +static const u32 rst_map[] = { + BIT(16), /* APB_RST */ + BIT(17), /* AXI_RST */ + BIT(18), /* ETH_RST */ + BIT(19), /* USB_RST */ + BIT(20), /* SDIO_RST */ + BIT(21), /* HDMI_RST */ + BIT(22), /* GFX_RST */ + BIT(25), /* DMAC_RST */ + BIT(31), /* EBI_RST */ +}; + +#define HSDK_MAX_RESETS ARRAY_SIZE(rst_map) + +#define CGU_SYS_RST_CTRL 0x0 +#define CGU_IP_SW_RESET 0x0 +#define CGU_IP_SW_RESET_DELAY_SHIFT 16 +#define CGU_IP_SW_RESET_DELAY_MASK GENMASK(31, CGU_IP_SW_RESET_DELAY_SHIFT) +#define CGU_IP_SW_RESET_DELAY 0 +#define CGU_IP_SW_RESET_RESET BIT(0) +#define SW_RESET_TIMEOUT 10000 + +static void hsdkv1_reset_config(struct hsdkv1_rst *rst, unsigned long id) +{ + writel(rst_map[id], rst->regs_ctl + CGU_SYS_RST_CTRL); +} + +static int hsdkv1_reset_do(struct hsdkv1_rst *rst) +{ + u32 reg; + + reg = readl(rst->regs_rst + CGU_IP_SW_RESET); + reg &= ~CGU_IP_SW_RESET_DELAY_MASK; + reg |= CGU_IP_SW_RESET_DELAY << CGU_IP_SW_RESET_DELAY_SHIFT; + reg |= CGU_IP_SW_RESET_RESET; + writel(reg, rst->regs_rst + CGU_IP_SW_RESET); + + /* wait till reset bit is back to 0 */ + return readl_poll_timeout_atomic(rst->regs_rst + CGU_IP_SW_RESET, reg, + !(reg & CGU_IP_SW_RESET_RESET), 5, SW_RESET_TIMEOUT); +} + +static int hsdkv1_reset_reset(struct reset_controller_dev *rcdev, + unsigned long id) +{ + struct hsdkv1_rst *rst = to_hsdkv1_rst(rcdev); + unsigned long flags; + int ret; + + spin_lock_irqsave(&rst->lock, flags); + hsdkv1_reset_config(rst, id); + ret = hsdkv1_reset_do(rst); + spin_unlock_irqrestore(&rst->lock, flags); + + return ret; +} + +static const struct reset_control_ops hsdkv1_reset_ops = { + .reset = hsdkv1_reset_reset, +}; + +static int hsdkv1_reset_probe(struct platform_device *pdev) +{ + struct hsdkv1_rst *rst; + struct resource *mem; + + rst = devm_kzalloc(&pdev->dev, sizeof(*rst), GFP_KERNEL); + if (!rst) + return -ENOMEM; + + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + rst->regs_ctl = devm_ioremap_resource(&pdev->dev, mem); + if (IS_ERR(rst->regs_ctl)) + return PTR_ERR(rst->regs_ctl); + + mem = platform_get_resource(pdev, IORESOURCE_MEM, 1); + rst->regs_rst = devm_ioremap_resource(&pdev->dev, mem); + if (IS_ERR(rst->regs_rst)) + return PTR_ERR(rst->regs_rst); + + spin_lock_init(&rst->lock); + + rst->rcdev.owner = THIS_MODULE; + rst->rcdev.ops = &hsdkv1_reset_ops; + rst->rcdev.of_node = pdev->dev.of_node; + rst->rcdev.nr_resets = HSDK_MAX_RESETS; + rst->rcdev.of_reset_n_cells = 1; + + return reset_controller_register(&rst->rcdev); +} + +static const struct of_device_id hsdkv1_reset_dt_match[] = { + { .compatible = "snps,hsdk-v1.0-reset" }, + { }, +}; + +static struct platform_driver hsdkv1_reset_driver = { + .probe = hsdkv1_reset_probe, + .driver = { + .name = "hsdk-v1.0-reset", + .of_match_table = hsdkv1_reset_dt_match, + }, +}; +builtin_platform_driver(hsdkv1_reset_driver); + +MODULE_AUTHOR("Eugeniy Paltsev <Eugeniy.Paltsev@synopsys.com>"); +MODULE_DESCRIPTION("Synopsys HSDKv1 SDP reset driver"); +MODULE_LICENSE("GPL v2"); |