Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

reset: Add Broadcom STB RESCAL reset controller

On BCM7216 there is a special purpose reset controller named RESCAL
(reset calibration) which is necessary for SATA and PCIe0/1 to operate
correctly. This commit adds support for such a reset controller to be
available.

Signed-off-by: Jim Quinlan <jim2101024@gmail.com>
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>

authored by

Jim Quinlan and committed by
Philipp Zabel
4cf176e5 f6e1405f

+115
+7
drivers/reset/Kconfig
··· 49 49 This enables the reset controller driver for Broadcom STB SoCs using 50 50 a SUN_TOP_CTRL_SW_INIT style controller. 51 51 52 + config RESET_BRCMSTB_RESCAL 53 + bool "Broadcom STB RESCAL reset controller" 54 + default ARCH_BRCMSTB || COMPILE_TEST 55 + help 56 + This enables the RESCAL reset controller for SATA, PCIe0, or PCIe1 on 57 + BCM7216. 58 + 52 59 config RESET_HSDK 53 60 bool "Synopsys HSDK Reset Driver" 54 61 depends on HAS_IOMEM
+1
drivers/reset/Makefile
··· 8 8 obj-$(CONFIG_RESET_AXS10X) += reset-axs10x.o 9 9 obj-$(CONFIG_RESET_BERLIN) += reset-berlin.o 10 10 obj-$(CONFIG_RESET_BRCMSTB) += reset-brcmstb.o 11 + obj-$(CONFIG_RESET_BRCMSTB_RESCAL) += reset-brcmstb-rescal.o 11 12 obj-$(CONFIG_RESET_HSDK) += reset-hsdk.o 12 13 obj-$(CONFIG_RESET_IMX7) += reset-imx7.o 13 14 obj-$(CONFIG_RESET_INTEL_GW) += reset-intel-gw.o
+107
drivers/reset/reset-brcmstb-rescal.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* Copyright (C) 2018-2020 Broadcom */ 3 + 4 + #include <linux/device.h> 5 + #include <linux/iopoll.h> 6 + #include <linux/module.h> 7 + #include <linux/of.h> 8 + #include <linux/platform_device.h> 9 + #include <linux/reset-controller.h> 10 + 11 + #define BRCM_RESCAL_START 0x0 12 + #define BRCM_RESCAL_START_BIT BIT(0) 13 + #define BRCM_RESCAL_CTRL 0x4 14 + #define BRCM_RESCAL_STATUS 0x8 15 + #define BRCM_RESCAL_STATUS_BIT BIT(0) 16 + 17 + struct brcm_rescal_reset { 18 + void __iomem *base; 19 + struct device *dev; 20 + struct reset_controller_dev rcdev; 21 + }; 22 + 23 + static int brcm_rescal_reset_set(struct reset_controller_dev *rcdev, 24 + unsigned long id) 25 + { 26 + struct brcm_rescal_reset *data = 27 + container_of(rcdev, struct brcm_rescal_reset, rcdev); 28 + void __iomem *base = data->base; 29 + u32 reg; 30 + int ret; 31 + 32 + reg = readl(base + BRCM_RESCAL_START); 33 + writel(reg | BRCM_RESCAL_START_BIT, base + BRCM_RESCAL_START); 34 + reg = readl(base + BRCM_RESCAL_START); 35 + if (!(reg & BRCM_RESCAL_START_BIT)) { 36 + dev_err(data->dev, "failed to start SATA/PCIe rescal\n"); 37 + return -EIO; 38 + } 39 + 40 + ret = readl_poll_timeout(base + BRCM_RESCAL_STATUS, reg, 41 + !(reg & BRCM_RESCAL_STATUS_BIT), 100, 1000); 42 + if (ret) { 43 + dev_err(data->dev, "time out on SATA/PCIe rescal\n"); 44 + return ret; 45 + } 46 + 47 + reg = readl(base + BRCM_RESCAL_START); 48 + writel(reg & ~BRCM_RESCAL_START_BIT, base + BRCM_RESCAL_START); 49 + 50 + dev_dbg(data->dev, "SATA/PCIe rescal success\n"); 51 + 52 + return 0; 53 + } 54 + 55 + static int brcm_rescal_reset_xlate(struct reset_controller_dev *rcdev, 56 + const struct of_phandle_args *reset_spec) 57 + { 58 + /* This is needed if #reset-cells == 0. */ 59 + return 0; 60 + } 61 + 62 + static const struct reset_control_ops brcm_rescal_reset_ops = { 63 + .reset = brcm_rescal_reset_set, 64 + }; 65 + 66 + static int brcm_rescal_reset_probe(struct platform_device *pdev) 67 + { 68 + struct brcm_rescal_reset *data; 69 + struct resource *res; 70 + 71 + data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); 72 + if (!data) 73 + return -ENOMEM; 74 + 75 + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 76 + data->base = devm_ioremap_resource(&pdev->dev, res); 77 + if (IS_ERR(data->base)) 78 + return PTR_ERR(data->base); 79 + 80 + data->rcdev.owner = THIS_MODULE; 81 + data->rcdev.nr_resets = 1; 82 + data->rcdev.ops = &brcm_rescal_reset_ops; 83 + data->rcdev.of_node = pdev->dev.of_node; 84 + data->rcdev.of_xlate = brcm_rescal_reset_xlate; 85 + data->dev = &pdev->dev; 86 + 87 + return devm_reset_controller_register(&pdev->dev, &data->rcdev); 88 + } 89 + 90 + static const struct of_device_id brcm_rescal_reset_of_match[] = { 91 + { .compatible = "brcm,bcm7216-pcie-sata-rescal" }, 92 + { }, 93 + }; 94 + MODULE_DEVICE_TABLE(of, brcm_rescal_reset_of_match); 95 + 96 + static struct platform_driver brcm_rescal_reset_driver = { 97 + .probe = brcm_rescal_reset_probe, 98 + .driver = { 99 + .name = "brcm-rescal-reset", 100 + .of_match_table = brcm_rescal_reset_of_match, 101 + } 102 + }; 103 + module_platform_driver(brcm_rescal_reset_driver); 104 + 105 + MODULE_AUTHOR("Broadcom"); 106 + MODULE_DESCRIPTION("Broadcom SATA/PCIe rescal reset controller"); 107 + MODULE_LICENSE("GPL v2");