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

Merge tag 'reset-for-4.19' of git://git.pengutronix.de/git/pza/linux into next/drivers

Reset controller changes for v4.19

This adds new drivers and bindings for the SDM845 AOSS (always on
subsystem) reset controller and for the Uniphier USB3 core reset.
SPI controller resets are added to the Uniphier reset driver.

* tag 'reset-for-4.19' of git://git.pengutronix.de/git/pza/linux:
reset: uniphier: add reset control support for SPI
reset: uniphier: add USB3 core reset control
dt-bindings: reset: uniphier: add USB3 core reset support
reset: simple: export reset_simple_ops to be referred from modules
reset: qcom: AOSS (always on subsystem) reset controller
dt-bindings: reset: Add AOSS reset bindings for SDM845 SoCs

Signed-off-by: Olof Johansson <olof@lixom.net>

+460
+52
Documentation/devicetree/bindings/reset/qcom,aoss-reset.txt
··· 1 + Qualcomm AOSS Reset Controller 2 + ====================================== 3 + 4 + This binding describes a reset-controller found on AOSS-CC (always on subsystem) 5 + for Qualcomm SDM845 SoCs. 6 + 7 + Required properties: 8 + - compatible: 9 + Usage: required 10 + Value type: <string> 11 + Definition: must be: 12 + "qcom,sdm845-aoss-cc" 13 + 14 + - reg: 15 + Usage: required 16 + Value type: <prop-encoded-array> 17 + Definition: must specify the base address and size of the register 18 + space. 19 + 20 + - #reset-cells: 21 + Usage: required 22 + Value type: <uint> 23 + Definition: must be 1; cell entry represents the reset index. 24 + 25 + Example: 26 + 27 + aoss_reset: reset-controller@c2a0000 { 28 + compatible = "qcom,sdm845-aoss-cc"; 29 + reg = <0xc2a0000 0x31000>; 30 + #reset-cells = <1>; 31 + }; 32 + 33 + Specifying reset lines connected to IP modules 34 + ============================================== 35 + 36 + Device nodes that need access to reset lines should 37 + specify them as a reset phandle in their corresponding node as 38 + specified in reset.txt. 39 + 40 + For list of all valid reset indicies see 41 + <dt-bindings/reset/qcom,sdm845-aoss.h> 42 + 43 + Example: 44 + 45 + modem-pil@4080000 { 46 + ... 47 + 48 + resets = <&aoss_reset AOSS_CC_MSS_RESTART>; 49 + reset-names = "mss_restart"; 50 + 51 + ... 52 + };
+56
Documentation/devicetree/bindings/reset/uniphier-reset.txt
··· 118 118 119 119 other nodes ... 120 120 }; 121 + 122 + 123 + USB3 core reset 124 + --------------- 125 + 126 + USB3 core reset belongs to USB3 glue layer. Before using the core reset, 127 + it is necessary to control the clocks and resets to enable this layer. 128 + These clocks and resets should be described in each property. 129 + 130 + Required properties: 131 + - compatible: Should be 132 + "socionext,uniphier-pro4-usb3-reset" - for Pro4 SoC 133 + "socionext,uniphier-pxs2-usb3-reset" - for PXs2 SoC 134 + "socionext,uniphier-ld20-usb3-reset" - for LD20 SoC 135 + "socionext,uniphier-pxs3-usb3-reset" - for PXs3 SoC 136 + - #reset-cells: Should be 1. 137 + - reg: Specifies offset and length of the register set for the device. 138 + - clocks: A list of phandles to the clock gate for USB3 glue layer. 139 + According to the clock-names, appropriate clocks are required. 140 + - clock-names: Should contain 141 + "gio", "link" - for Pro4 SoC 142 + "link" - for others 143 + - resets: A list of phandles to the reset control for USB3 glue layer. 144 + According to the reset-names, appropriate resets are required. 145 + - reset-names: Should contain 146 + "gio", "link" - for Pro4 SoC 147 + "link" - for others 148 + 149 + Example: 150 + 151 + usb-glue@65b00000 { 152 + compatible = "socionext,uniphier-ld20-dwc3-glue", 153 + "simple-mfd"; 154 + #address-cells = <1>; 155 + #size-cells = <1>; 156 + ranges = <0 0x65b00000 0x400>; 157 + 158 + usb_rst: reset@0 { 159 + compatible = "socionext,uniphier-ld20-usb3-reset"; 160 + reg = <0x0 0x4>; 161 + #reset-cells = <1>; 162 + clock-names = "link"; 163 + clocks = <&sys_clk 14>; 164 + reset-names = "link"; 165 + resets = <&sys_rst 14>; 166 + }; 167 + 168 + regulator { 169 + ... 170 + }; 171 + 172 + phy { 173 + ... 174 + }; 175 + ... 176 + };
+19
drivers/reset/Kconfig
··· 82 82 help 83 83 This enables the reset driver for ImgTec Pistachio SoCs. 84 84 85 + config RESET_QCOM_AOSS 86 + bool "Qcom AOSS Reset Driver" 87 + depends on ARCH_QCOM || COMPILE_TEST 88 + help 89 + This enables the AOSS (always on subsystem) reset driver 90 + for Qualcomm SDM845 SoCs. Say Y if you want to control 91 + reset signals provided by AOSS for Modem, Venus, ADSP, 92 + GPU, Camera, Wireless, Display subsystem. Otherwise, say N. 93 + 85 94 config RESET_SIMPLE 86 95 bool "Simple Reset Controller Driver" if COMPILE_TEST 87 96 default ARCH_SOCFPGA || ARCH_STM32 || ARCH_STRATIX10 || ARCH_SUNXI || ARCH_ZX || ARCH_ASPEED ··· 146 137 Support for reset controllers on UniPhier SoCs. 147 138 Say Y if you want to control reset signals provided by System Control 148 139 block, Media I/O block, Peripheral Block. 140 + 141 + config RESET_UNIPHIER_USB3 142 + tristate "USB3 reset driver for UniPhier SoCs" 143 + depends on (ARCH_UNIPHIER || COMPILE_TEST) && OF 144 + default ARCH_UNIPHIER 145 + select RESET_SIMPLE 146 + help 147 + Support for the USB3 core reset on UniPhier SoCs. 148 + Say Y if you want to control reset signals provided by 149 + USB3 glue layer. 149 150 150 151 config RESET_ZYNQ 151 152 bool "ZYNQ Reset Driver" if COMPILE_TEST
+2
drivers/reset/Makefile
··· 14 14 obj-$(CONFIG_RESET_MESON) += reset-meson.o 15 15 obj-$(CONFIG_RESET_OXNAS) += reset-oxnas.o 16 16 obj-$(CONFIG_RESET_PISTACHIO) += reset-pistachio.o 17 + obj-$(CONFIG_RESET_QCOM_AOSS) += reset-qcom-aoss.o 17 18 obj-$(CONFIG_RESET_SIMPLE) += reset-simple.o 18 19 obj-$(CONFIG_RESET_STM32MP157) += reset-stm32mp1.o 19 20 obj-$(CONFIG_RESET_SUNXI) += reset-sunxi.o 20 21 obj-$(CONFIG_RESET_TI_SCI) += reset-ti-sci.o 21 22 obj-$(CONFIG_RESET_TI_SYSCON) += reset-ti-syscon.o 22 23 obj-$(CONFIG_RESET_UNIPHIER) += reset-uniphier.o 24 + obj-$(CONFIG_RESET_UNIPHIER_USB3) += reset-uniphier-usb3.o 23 25 obj-$(CONFIG_RESET_ZYNQ) += reset-zynq.o 24 26
+133
drivers/reset/reset-qcom-aoss.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Copyright (C) 2018 The Linux Foundation. All rights reserved. 4 + */ 5 + 6 + #include <linux/module.h> 7 + #include <linux/platform_device.h> 8 + #include <linux/reset-controller.h> 9 + #include <linux/delay.h> 10 + #include <linux/io.h> 11 + #include <linux/of_device.h> 12 + #include <dt-bindings/reset/qcom,sdm845-aoss.h> 13 + 14 + struct qcom_aoss_reset_map { 15 + unsigned int reg; 16 + }; 17 + 18 + struct qcom_aoss_desc { 19 + const struct qcom_aoss_reset_map *resets; 20 + size_t num_resets; 21 + }; 22 + 23 + struct qcom_aoss_reset_data { 24 + struct reset_controller_dev rcdev; 25 + void __iomem *base; 26 + const struct qcom_aoss_desc *desc; 27 + }; 28 + 29 + static const struct qcom_aoss_reset_map sdm845_aoss_resets[] = { 30 + [AOSS_CC_MSS_RESTART] = {0x10000}, 31 + [AOSS_CC_CAMSS_RESTART] = {0x11000}, 32 + [AOSS_CC_VENUS_RESTART] = {0x12000}, 33 + [AOSS_CC_GPU_RESTART] = {0x13000}, 34 + [AOSS_CC_DISPSS_RESTART] = {0x14000}, 35 + [AOSS_CC_WCSS_RESTART] = {0x20000}, 36 + [AOSS_CC_LPASS_RESTART] = {0x30000}, 37 + }; 38 + 39 + static const struct qcom_aoss_desc sdm845_aoss_desc = { 40 + .resets = sdm845_aoss_resets, 41 + .num_resets = ARRAY_SIZE(sdm845_aoss_resets), 42 + }; 43 + 44 + static inline struct qcom_aoss_reset_data *to_qcom_aoss_reset_data( 45 + struct reset_controller_dev *rcdev) 46 + { 47 + return container_of(rcdev, struct qcom_aoss_reset_data, rcdev); 48 + } 49 + 50 + static int qcom_aoss_control_assert(struct reset_controller_dev *rcdev, 51 + unsigned long idx) 52 + { 53 + struct qcom_aoss_reset_data *data = to_qcom_aoss_reset_data(rcdev); 54 + const struct qcom_aoss_reset_map *map = &data->desc->resets[idx]; 55 + 56 + writel(1, data->base + map->reg); 57 + /* Wait 6 32kHz sleep cycles for reset */ 58 + usleep_range(200, 300); 59 + return 0; 60 + } 61 + 62 + static int qcom_aoss_control_deassert(struct reset_controller_dev *rcdev, 63 + unsigned long idx) 64 + { 65 + struct qcom_aoss_reset_data *data = to_qcom_aoss_reset_data(rcdev); 66 + const struct qcom_aoss_reset_map *map = &data->desc->resets[idx]; 67 + 68 + writel(0, data->base + map->reg); 69 + /* Wait 6 32kHz sleep cycles for reset */ 70 + usleep_range(200, 300); 71 + return 0; 72 + } 73 + 74 + static int qcom_aoss_control_reset(struct reset_controller_dev *rcdev, 75 + unsigned long idx) 76 + { 77 + qcom_aoss_control_assert(rcdev, idx); 78 + 79 + return qcom_aoss_control_deassert(rcdev, idx); 80 + } 81 + 82 + static const struct reset_control_ops qcom_aoss_reset_ops = { 83 + .reset = qcom_aoss_control_reset, 84 + .assert = qcom_aoss_control_assert, 85 + .deassert = qcom_aoss_control_deassert, 86 + }; 87 + 88 + static int qcom_aoss_reset_probe(struct platform_device *pdev) 89 + { 90 + struct qcom_aoss_reset_data *data; 91 + struct device *dev = &pdev->dev; 92 + const struct qcom_aoss_desc *desc; 93 + struct resource *res; 94 + 95 + desc = of_device_get_match_data(dev); 96 + if (!desc) 97 + return -EINVAL; 98 + 99 + data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); 100 + if (!data) 101 + return -ENOMEM; 102 + 103 + data->desc = desc; 104 + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 105 + data->base = devm_ioremap_resource(dev, res); 106 + if (IS_ERR(data->base)) 107 + return PTR_ERR(data->base); 108 + 109 + data->rcdev.owner = THIS_MODULE; 110 + data->rcdev.ops = &qcom_aoss_reset_ops; 111 + data->rcdev.nr_resets = desc->num_resets; 112 + data->rcdev.of_node = dev->of_node; 113 + 114 + return devm_reset_controller_register(dev, &data->rcdev); 115 + } 116 + 117 + static const struct of_device_id qcom_aoss_reset_of_match[] = { 118 + { .compatible = "qcom,sdm845-aoss-cc", .data = &sdm845_aoss_desc }, 119 + {} 120 + }; 121 + 122 + static struct platform_driver qcom_aoss_reset_driver = { 123 + .probe = qcom_aoss_reset_probe, 124 + .driver = { 125 + .name = "qcom_aoss_reset", 126 + .of_match_table = qcom_aoss_reset_of_match, 127 + }, 128 + }; 129 + 130 + builtin_platform_driver(qcom_aoss_reset_driver); 131 + 132 + MODULE_DESCRIPTION("Qualcomm AOSS Reset Driver"); 133 + MODULE_LICENSE("GPL v2");
+1
drivers/reset/reset-simple.c
··· 87 87 .deassert = reset_simple_deassert, 88 88 .status = reset_simple_status, 89 89 }; 90 + EXPORT_SYMBOL_GPL(reset_simple_ops); 90 91 91 92 /** 92 93 * struct reset_simple_devdata - simple reset controller properties
+171
drivers/reset/reset-uniphier-usb3.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + // 3 + // reset-uniphier-usb3.c - USB3 reset driver for UniPhier 4 + // Copyright 2018 Socionext Inc. 5 + // Author: Kunihiko Hayashi <hayashi.kunihiko@socionext.com> 6 + 7 + #include <linux/clk.h> 8 + #include <linux/module.h> 9 + #include <linux/of_device.h> 10 + #include <linux/platform_device.h> 11 + #include <linux/reset.h> 12 + 13 + #include "reset-simple.h" 14 + 15 + #define MAX_CLKS 2 16 + #define MAX_RSTS 2 17 + 18 + struct uniphier_usb3_reset_soc_data { 19 + int nclks; 20 + const char * const *clock_names; 21 + int nrsts; 22 + const char * const *reset_names; 23 + }; 24 + 25 + struct uniphier_usb3_reset_priv { 26 + struct clk_bulk_data clk[MAX_CLKS]; 27 + struct reset_control *rst[MAX_RSTS]; 28 + struct reset_simple_data rdata; 29 + const struct uniphier_usb3_reset_soc_data *data; 30 + }; 31 + 32 + static int uniphier_usb3_reset_probe(struct platform_device *pdev) 33 + { 34 + struct device *dev = &pdev->dev; 35 + struct uniphier_usb3_reset_priv *priv; 36 + struct resource *res; 37 + resource_size_t size; 38 + const char *name; 39 + int i, ret, nr; 40 + 41 + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 42 + if (!priv) 43 + return -ENOMEM; 44 + 45 + priv->data = of_device_get_match_data(dev); 46 + if (WARN_ON(!priv->data || priv->data->nclks > MAX_CLKS || 47 + priv->data->nrsts > MAX_RSTS)) 48 + return -EINVAL; 49 + 50 + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 51 + size = resource_size(res); 52 + priv->rdata.membase = devm_ioremap_resource(dev, res); 53 + if (IS_ERR(priv->rdata.membase)) 54 + return PTR_ERR(priv->rdata.membase); 55 + 56 + for (i = 0; i < priv->data->nclks; i++) 57 + priv->clk[i].id = priv->data->clock_names[i]; 58 + ret = devm_clk_bulk_get(dev, priv->data->nclks, priv->clk); 59 + if (ret) 60 + return ret; 61 + 62 + for (i = 0; i < priv->data->nrsts; i++) { 63 + name = priv->data->reset_names[i]; 64 + priv->rst[i] = devm_reset_control_get_shared(dev, name); 65 + if (IS_ERR(priv->rst[i])) 66 + return PTR_ERR(priv->rst[i]); 67 + } 68 + 69 + ret = clk_bulk_prepare_enable(priv->data->nclks, priv->clk); 70 + if (ret) 71 + return ret; 72 + 73 + for (nr = 0; nr < priv->data->nrsts; nr++) { 74 + ret = reset_control_deassert(priv->rst[nr]); 75 + if (ret) 76 + goto out_rst_assert; 77 + } 78 + 79 + spin_lock_init(&priv->rdata.lock); 80 + priv->rdata.rcdev.owner = THIS_MODULE; 81 + priv->rdata.rcdev.nr_resets = size * BITS_PER_BYTE; 82 + priv->rdata.rcdev.ops = &reset_simple_ops; 83 + priv->rdata.rcdev.of_node = dev->of_node; 84 + priv->rdata.active_low = true; 85 + 86 + platform_set_drvdata(pdev, priv); 87 + 88 + ret = devm_reset_controller_register(dev, &priv->rdata.rcdev); 89 + if (ret) 90 + goto out_rst_assert; 91 + 92 + return 0; 93 + 94 + out_rst_assert: 95 + while (nr--) 96 + reset_control_assert(priv->rst[nr]); 97 + 98 + clk_bulk_disable_unprepare(priv->data->nclks, priv->clk); 99 + 100 + return ret; 101 + } 102 + 103 + static int uniphier_usb3_reset_remove(struct platform_device *pdev) 104 + { 105 + struct uniphier_usb3_reset_priv *priv = platform_get_drvdata(pdev); 106 + int i; 107 + 108 + for (i = 0; i < priv->data->nrsts; i++) 109 + reset_control_assert(priv->rst[i]); 110 + 111 + clk_bulk_disable_unprepare(priv->data->nclks, priv->clk); 112 + 113 + return 0; 114 + } 115 + 116 + static const char * const uniphier_pro4_clock_reset_names[] = { 117 + "gio", "link", 118 + }; 119 + 120 + static const struct uniphier_usb3_reset_soc_data uniphier_pro4_data = { 121 + .nclks = ARRAY_SIZE(uniphier_pro4_clock_reset_names), 122 + .clock_names = uniphier_pro4_clock_reset_names, 123 + .nrsts = ARRAY_SIZE(uniphier_pro4_clock_reset_names), 124 + .reset_names = uniphier_pro4_clock_reset_names, 125 + }; 126 + 127 + static const char * const uniphier_pxs2_clock_reset_names[] = { 128 + "link", 129 + }; 130 + 131 + static const struct uniphier_usb3_reset_soc_data uniphier_pxs2_data = { 132 + .nclks = ARRAY_SIZE(uniphier_pxs2_clock_reset_names), 133 + .clock_names = uniphier_pxs2_clock_reset_names, 134 + .nrsts = ARRAY_SIZE(uniphier_pxs2_clock_reset_names), 135 + .reset_names = uniphier_pxs2_clock_reset_names, 136 + }; 137 + 138 + static const struct of_device_id uniphier_usb3_reset_match[] = { 139 + { 140 + .compatible = "socionext,uniphier-pro4-usb3-reset", 141 + .data = &uniphier_pro4_data, 142 + }, 143 + { 144 + .compatible = "socionext,uniphier-pxs2-usb3-reset", 145 + .data = &uniphier_pxs2_data, 146 + }, 147 + { 148 + .compatible = "socionext,uniphier-ld20-usb3-reset", 149 + .data = &uniphier_pxs2_data, 150 + }, 151 + { 152 + .compatible = "socionext,uniphier-pxs3-usb3-reset", 153 + .data = &uniphier_pxs2_data, 154 + }, 155 + { /* Sentinel */ } 156 + }; 157 + MODULE_DEVICE_TABLE(of, uniphier_usb3_reset_match); 158 + 159 + static struct platform_driver uniphier_usb3_reset_driver = { 160 + .probe = uniphier_usb3_reset_probe, 161 + .remove = uniphier_usb3_reset_remove, 162 + .driver = { 163 + .name = "uniphier-usb3-reset", 164 + .of_match_table = uniphier_usb3_reset_match, 165 + }, 166 + }; 167 + module_platform_driver(uniphier_usb3_reset_driver); 168 + 169 + MODULE_AUTHOR("Kunihiko Hayashi <hayashi.kunihiko@socionext.com>"); 170 + MODULE_DESCRIPTION("UniPhier USB3 Reset Driver"); 171 + MODULE_LICENSE("GPL");
+9
drivers/reset/reset-uniphier.c
··· 202 202 #define UNIPHIER_PERI_RESET_FI2C(id, ch) \ 203 203 UNIPHIER_RESETX((id), 0x114, 24 + (ch)) 204 204 205 + #define UNIPHIER_PERI_RESET_SCSSI(id) \ 206 + UNIPHIER_RESETX((id), 0x110, 17) 207 + 208 + #define UNIPHIER_PERI_RESET_MCSSI(id) \ 209 + UNIPHIER_RESETX((id), 0x114, 14) 210 + 205 211 static const struct uniphier_reset_data uniphier_ld4_peri_reset_data[] = { 206 212 UNIPHIER_PERI_RESET_UART(0, 0), 207 213 UNIPHIER_PERI_RESET_UART(1, 1), ··· 218 212 UNIPHIER_PERI_RESET_I2C(6, 2), 219 213 UNIPHIER_PERI_RESET_I2C(7, 3), 220 214 UNIPHIER_PERI_RESET_I2C(8, 4), 215 + UNIPHIER_PERI_RESET_SCSSI(11), 221 216 UNIPHIER_RESET_END, 222 217 }; 223 218 ··· 234 227 UNIPHIER_PERI_RESET_FI2C(8, 4), 235 228 UNIPHIER_PERI_RESET_FI2C(9, 5), 236 229 UNIPHIER_PERI_RESET_FI2C(10, 6), 230 + UNIPHIER_PERI_RESET_SCSSI(11), 231 + UNIPHIER_PERI_RESET_MCSSI(12), 237 232 UNIPHIER_RESET_END, 238 233 }; 239 234
+17
include/dt-bindings/reset/qcom,sdm845-aoss.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * Copyright (C) 2018 The Linux Foundation. All rights reserved. 4 + */ 5 + 6 + #ifndef _DT_BINDINGS_RESET_AOSS_SDM_845_H 7 + #define _DT_BINDINGS_RESET_AOSS_SDM_845_H 8 + 9 + #define AOSS_CC_MSS_RESTART 0 10 + #define AOSS_CC_CAMSS_RESTART 1 11 + #define AOSS_CC_VENUS_RESTART 2 12 + #define AOSS_CC_GPU_RESTART 3 13 + #define AOSS_CC_DISPSS_RESTART 4 14 + #define AOSS_CC_WCSS_RESTART 5 15 + #define AOSS_CC_LPASS_RESTART 6 16 + 17 + #endif