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

Merge tag 'at91-reset-sama7g5-signed' into psy-next

This adds reset controller support for SAMA7G5 SoCs. Compared with
previous version the reset controller embedded on SAMA7G5 is able to
reset individual on SoC devices (e.g. USB PHY controllers).

Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>

+247 -30
-15
Documentation/devicetree/bindings/arm/atmel-sysregs.txt
··· 25 25 Its subnodes can be: 26 26 - watchdog: compatible should be "atmel,at91rm9200-wdt" 27 27 28 - RSTC Reset Controller required properties: 29 - - compatible: Should be "atmel,<chip>-rstc". 30 - <chip> can be "at91sam9260", "at91sam9g45", "sama5d3" or "samx7" 31 - it also can be "microchip,sam9x60-rstc" 32 - - reg: Should contain registers location and length 33 - - clocks: phandle to input clock. 34 - 35 - Example: 36 - 37 - rstc@fffffd00 { 38 - compatible = "atmel,at91sam9260-rstc"; 39 - reg = <0xfffffd00 0x10>; 40 - clocks = <&clk32k>; 41 - }; 42 - 43 28 RAMC SDRAM/DDR Controller required properties: 44 29 - compatible: Should be "atmel,at91rm9200-sdramc", "syscon" 45 30 "atmel,at91sam9260-sdramc",
+68
Documentation/devicetree/bindings/reset/atmel,at91sam9260-reset.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/reset/atmel,at91sam9260-reset.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: Atmel/Microchip System Reset Controller 8 + 9 + maintainers: 10 + - Claudiu Beznea <claudiu.beznea@microchip.com> 11 + 12 + description: | 13 + The system reset controller can be used to reset the CPU. In case of 14 + SAMA7G5 it can also reset some devices (e.g. USB PHYs). 15 + 16 + properties: 17 + compatible: 18 + oneOf: 19 + - items: 20 + - enum: 21 + - atmel,at91sam9260-rstc 22 + - atmel,at91sam9g45-rstc 23 + - atmel,sama5d3-rstc 24 + - microchip,sam9x60-rstc 25 + - microchip,sama7g5-rstc 26 + - items: 27 + - const: atmel,sama5d3-rstc 28 + - const: atmel,at91sam9g45-rstc 29 + 30 + reg: 31 + minItems: 1 32 + items: 33 + - description: base registers for system reset control 34 + - description: registers for device specific reset control 35 + 36 + clocks: 37 + maxItems: 1 38 + 39 + "#reset-cells": 40 + const: 1 41 + 42 + required: 43 + - compatible 44 + - reg 45 + - clocks 46 + 47 + allOf: 48 + - if: 49 + properties: 50 + compatible: 51 + contains: 52 + enum: 53 + - microchip,sama7g5-rstc 54 + then: 55 + required: 56 + - "#reset-cells" 57 + 58 + additionalProperties: false 59 + 60 + examples: 61 + - | 62 + #include <dt-bindings/clock/at91.h> 63 + 64 + reset-controller@fffffd00 { 65 + compatible = "atmel,at91sam9260-rstc"; 66 + reg = <0xfffffd00 0x10>; 67 + clocks = <&pmc PMC_TYPE_CORE PMC_SLOW>; 68 + };
+169 -15
drivers/power/reset/at91-reset.c
··· 17 17 #include <linux/of_address.h> 18 18 #include <linux/platform_device.h> 19 19 #include <linux/reboot.h> 20 + #include <linux/reset-controller.h> 20 21 21 22 #include <soc/at91/at91sam9_ddrsdr.h> 22 23 #include <soc/at91/at91sam9_sdramc.h> 24 + 25 + #include <dt-bindings/reset/sama7g5-reset.h> 23 26 24 27 #define AT91_RSTC_CR 0x00 /* Reset Controller Control Register */ 25 28 #define AT91_RSTC_PROCRST BIT(0) /* Processor Reset */ ··· 42 39 #define AT91_RSTC_URSTIEN BIT(4) /* User Reset Interrupt Enable */ 43 40 #define AT91_RSTC_ERSTL GENMASK(11, 8) /* External Reset Length */ 44 41 42 + /** 43 + * enum reset_type - reset types 44 + * @RESET_TYPE_GENERAL: first power-up reset 45 + * @RESET_TYPE_WAKEUP: return from backup mode 46 + * @RESET_TYPE_WATCHDOG: watchdog fault 47 + * @RESET_TYPE_SOFTWARE: processor reset required by software 48 + * @RESET_TYPE_USER: NRST pin detected low 49 + * @RESET_TYPE_CPU_FAIL: CPU clock failure detection 50 + * @RESET_TYPE_XTAL_FAIL: 32KHz crystal failure dectection fault 51 + * @RESET_TYPE_ULP2: ULP2 reset 52 + */ 45 53 enum reset_type { 46 54 RESET_TYPE_GENERAL = 0, 47 55 RESET_TYPE_WAKEUP = 1, ··· 64 50 RESET_TYPE_ULP2 = 8, 65 51 }; 66 52 53 + /** 54 + * struct at91_reset - AT91 reset specific data structure 55 + * @rstc_base: base address for system reset 56 + * @ramc_base: array with base addresses of RAM controllers 57 + * @dev_base: base address for devices reset 58 + * @sclk: slow clock 59 + * @data: platform specific reset data 60 + * @rcdev: reset controller device 61 + * @lock: lock for devices reset register access 62 + * @nb: reset notifier block 63 + * @args: SoC specific system reset arguments 64 + * @ramc_lpr: SDRAM Controller Low Power Register 65 + */ 67 66 struct at91_reset { 68 67 void __iomem *rstc_base; 69 68 void __iomem *ramc_base[2]; 69 + void __iomem *dev_base; 70 70 struct clk *sclk; 71 + const struct at91_reset_data *data; 72 + struct reset_controller_dev rcdev; 73 + spinlock_t lock; 71 74 struct notifier_block nb; 72 75 u32 args; 73 76 u32 ramc_lpr; 77 + }; 78 + 79 + #define to_at91_reset(r) container_of(r, struct at91_reset, rcdev) 80 + 81 + /** 82 + * struct at91_reset_data - AT91 reset data 83 + * @reset_args: SoC specific system reset arguments 84 + * @n_device_reset: number of device resets 85 + * @device_reset_min_id: min id for device reset 86 + * @device_reset_max_id: max id for device reset 87 + */ 88 + struct at91_reset_data { 89 + u32 reset_args; 90 + u32 n_device_reset; 91 + u8 device_reset_min_id; 92 + u8 device_reset_max_id; 74 93 }; 75 94 76 95 /* ··· 142 95 "r" (reset->rstc_base), 143 96 "r" (1), 144 97 "r" cpu_to_le32(AT91_DDRSDRC_LPCB_POWER_DOWN), 145 - "r" (reset->args), 98 + "r" (reset->data->reset_args), 146 99 "r" (reset->ramc_lpr) 147 100 : "r4"); 148 101 ··· 200 153 { /* sentinel */ } 201 154 }; 202 155 156 + static const struct at91_reset_data sam9260 = { 157 + .reset_args = AT91_RSTC_KEY | AT91_RSTC_PERRST | AT91_RSTC_PROCRST, 158 + }; 159 + 160 + static const struct at91_reset_data samx7 = { 161 + .reset_args = AT91_RSTC_KEY | AT91_RSTC_PROCRST, 162 + }; 163 + 164 + static const struct at91_reset_data sama7g5 = { 165 + .reset_args = AT91_RSTC_KEY | AT91_RSTC_PROCRST, 166 + .n_device_reset = 3, 167 + .device_reset_min_id = SAMA7G5_RESET_USB_PHY1, 168 + .device_reset_max_id = SAMA7G5_RESET_USB_PHY3, 169 + }; 170 + 203 171 static const struct of_device_id at91_reset_of_match[] = { 204 172 { 205 173 .compatible = "atmel,at91sam9260-rstc", 206 - .data = (void *)(AT91_RSTC_KEY | AT91_RSTC_PERRST | 207 - AT91_RSTC_PROCRST), 174 + .data = &sam9260, 208 175 }, 209 176 { 210 177 .compatible = "atmel,at91sam9g45-rstc", 211 - .data = (void *)(AT91_RSTC_KEY | AT91_RSTC_PERRST | 212 - AT91_RSTC_PROCRST) 178 + .data = &sam9260, 213 179 }, 214 180 { 215 181 .compatible = "atmel,sama5d3-rstc", 216 - .data = (void *)(AT91_RSTC_KEY | AT91_RSTC_PERRST | 217 - AT91_RSTC_PROCRST) 182 + .data = &sam9260, 218 183 }, 219 184 { 220 185 .compatible = "atmel,samx7-rstc", 221 - .data = (void *)(AT91_RSTC_KEY | AT91_RSTC_PROCRST) 186 + .data = &samx7, 222 187 }, 223 188 { 224 189 .compatible = "microchip,sam9x60-rstc", 225 - .data = (void *)(AT91_RSTC_KEY | AT91_RSTC_PROCRST) 190 + .data = &samx7, 191 + }, 192 + { 193 + .compatible = "microchip,sama7g5-rstc", 194 + .data = &sama7g5, 226 195 }, 227 196 { /* sentinel */ } 228 197 }; 229 198 MODULE_DEVICE_TABLE(of, at91_reset_of_match); 199 + 200 + static int at91_reset_update(struct reset_controller_dev *rcdev, 201 + unsigned long id, bool assert) 202 + { 203 + struct at91_reset *reset = to_at91_reset(rcdev); 204 + unsigned long flags; 205 + u32 val; 206 + 207 + spin_lock_irqsave(&reset->lock, flags); 208 + val = readl_relaxed(reset->dev_base); 209 + if (assert) 210 + val |= BIT(id); 211 + else 212 + val &= ~BIT(id); 213 + writel_relaxed(val, reset->dev_base); 214 + spin_unlock_irqrestore(&reset->lock, flags); 215 + 216 + return 0; 217 + } 218 + 219 + static int at91_reset_assert(struct reset_controller_dev *rcdev, 220 + unsigned long id) 221 + { 222 + return at91_reset_update(rcdev, id, true); 223 + } 224 + 225 + static int at91_reset_deassert(struct reset_controller_dev *rcdev, 226 + unsigned long id) 227 + { 228 + return at91_reset_update(rcdev, id, false); 229 + } 230 + 231 + static int at91_reset_dev_status(struct reset_controller_dev *rcdev, 232 + unsigned long id) 233 + { 234 + struct at91_reset *reset = to_at91_reset(rcdev); 235 + u32 val; 236 + 237 + val = readl_relaxed(reset->dev_base); 238 + 239 + return !!(val & BIT(id)); 240 + } 241 + 242 + static const struct reset_control_ops at91_reset_ops = { 243 + .assert = at91_reset_assert, 244 + .deassert = at91_reset_deassert, 245 + .status = at91_reset_dev_status, 246 + }; 247 + 248 + static int at91_reset_of_xlate(struct reset_controller_dev *rcdev, 249 + const struct of_phandle_args *reset_spec) 250 + { 251 + struct at91_reset *reset = to_at91_reset(rcdev); 252 + 253 + if (!reset->data->n_device_reset || 254 + (reset_spec->args[0] < reset->data->device_reset_min_id || 255 + reset_spec->args[0] > reset->data->device_reset_max_id)) 256 + return -EINVAL; 257 + 258 + return reset_spec->args[0]; 259 + } 260 + 261 + static int at91_rcdev_init(struct at91_reset *reset, 262 + struct platform_device *pdev) 263 + { 264 + if (!reset->data->n_device_reset) 265 + return 0; 266 + 267 + reset->dev_base = devm_of_iomap(&pdev->dev, pdev->dev.of_node, 1, 268 + NULL); 269 + if (IS_ERR(reset->dev_base)) 270 + return -ENODEV; 271 + 272 + spin_lock_init(&reset->lock); 273 + reset->rcdev.ops = &at91_reset_ops; 274 + reset->rcdev.owner = THIS_MODULE; 275 + reset->rcdev.of_node = pdev->dev.of_node; 276 + reset->rcdev.nr_resets = reset->data->n_device_reset; 277 + reset->rcdev.of_reset_n_cells = 1; 278 + reset->rcdev.of_xlate = at91_reset_of_xlate; 279 + 280 + return devm_reset_controller_register(&pdev->dev, &reset->rcdev); 281 + } 230 282 231 283 static int __init at91_reset_probe(struct platform_device *pdev) 232 284 { ··· 358 212 } 359 213 } 360 214 361 - match = of_match_node(at91_reset_of_match, pdev->dev.of_node); 215 + reset->data = device_get_match_data(&pdev->dev); 216 + if (!reset->data) 217 + return -ENODEV; 218 + 362 219 reset->nb.notifier_call = at91_reset; 363 220 reset->nb.priority = 192; 364 - reset->args = (u32)match->data; 365 221 366 222 reset->sclk = devm_clk_get(&pdev->dev, NULL); 367 223 if (IS_ERR(reset->sclk)) ··· 377 229 378 230 platform_set_drvdata(pdev, reset); 379 231 232 + ret = at91_rcdev_init(reset, pdev); 233 + if (ret) 234 + goto disable_clk; 235 + 380 236 if (of_device_is_compatible(pdev->dev.of_node, "microchip,sam9x60-rstc")) { 381 237 u32 val = readl(reset->rstc_base + AT91_RSTC_MR); 382 238 ··· 389 237 } 390 238 391 239 ret = register_restart_handler(&reset->nb); 392 - if (ret) { 393 - clk_disable_unprepare(reset->sclk); 394 - return ret; 395 - } 240 + if (ret) 241 + goto disable_clk; 396 242 397 243 at91_reset_status(pdev, reset->rstc_base); 398 244 399 245 return 0; 246 + 247 + disable_clk: 248 + clk_disable_unprepare(reset->sclk); 249 + return ret; 400 250 } 401 251 402 252 static int __exit at91_reset_remove(struct platform_device *pdev)
+10
include/dt-bindings/reset/sama7g5-reset.h
··· 1 + /* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ 2 + 3 + #ifndef __DT_BINDINGS_RESET_SAMA7G5_H 4 + #define __DT_BINDINGS_RESET_SAMA7G5_H 5 + 6 + #define SAMA7G5_RESET_USB_PHY1 4 7 + #define SAMA7G5_RESET_USB_PHY2 5 8 + #define SAMA7G5_RESET_USB_PHY3 6 9 + 10 + #endif /* __DT_BINDINGS_RESET_SAMA7G5_H */