diff options
| -rw-r--r-- | Documentation/devicetree/bindings/reset/oxnas,reset.txt | 58 | ||||
| -rw-r--r-- | drivers/reset/Kconfig | 3 | ||||
| -rw-r--r-- | drivers/reset/Makefile | 1 | ||||
| -rw-r--r-- | drivers/reset/reset-oxnas.c | 136 | ||||
| -rw-r--r-- | include/linux/reset.h | 6 |
5 files changed, 204 insertions, 0 deletions
diff --git a/Documentation/devicetree/bindings/reset/oxnas,reset.txt b/Documentation/devicetree/bindings/reset/oxnas,reset.txt new file mode 100644 index 000000000000..6f06db930030 --- /dev/null +++ b/Documentation/devicetree/bindings/reset/oxnas,reset.txt | |||
| @@ -0,0 +1,58 @@ | |||
| 1 | Oxford Semiconductor OXNAS SoC Family RESET Controller | ||
| 2 | ================================================ | ||
| 3 | |||
| 4 | Please also refer to reset.txt in this directory for common reset | ||
| 5 | controller binding usage. | ||
| 6 | |||
| 7 | Required properties: | ||
| 8 | - compatible: Should be "oxsemi,ox810se-reset" | ||
| 9 | - #reset-cells: 1, see below | ||
| 10 | |||
| 11 | Parent node should have the following properties : | ||
| 12 | - compatible: Should be "oxsemi,ox810se-sys-ctrl", "syscon", "simple-mfd" | ||
| 13 | |||
| 14 | For OX810SE, the indices are : | ||
| 15 | - 0 : ARM | ||
| 16 | - 1 : COPRO | ||
| 17 | - 2 : Reserved | ||
| 18 | - 3 : Reserved | ||
| 19 | - 4 : USBHS | ||
| 20 | - 5 : USBHSPHY | ||
| 21 | - 6 : MAC | ||
| 22 | - 7 : PCI | ||
| 23 | - 8 : DMA | ||
| 24 | - 9 : DPE | ||
| 25 | - 10 : DDR | ||
| 26 | - 11 : SATA | ||
| 27 | - 12 : SATA_LINK | ||
| 28 | - 13 : SATA_PHY | ||
| 29 | - 14 : Reserved | ||
| 30 | - 15 : NAND | ||
| 31 | - 16 : GPIO | ||
| 32 | - 17 : UART1 | ||
| 33 | - 18 : UART2 | ||
| 34 | - 19 : MISC | ||
| 35 | - 20 : I2S | ||
| 36 | - 21 : AHB_MON | ||
| 37 | - 22 : UART3 | ||
| 38 | - 23 : UART4 | ||
| 39 | - 24 : SGDMA | ||
| 40 | - 25 : Reserved | ||
| 41 | - 26 : Reserved | ||
| 42 | - 27 : Reserved | ||
| 43 | - 28 : Reserved | ||
| 44 | - 29 : Reserved | ||
| 45 | - 30 : Reserved | ||
| 46 | - 31 : BUS | ||
| 47 | |||
| 48 | example: | ||
| 49 | |||
| 50 | sys: sys-ctrl@000000 { | ||
| 51 | compatible = "oxsemi,ox810se-sys-ctrl", "syscon", "simple-mfd"; | ||
| 52 | reg = <0x000000 0x100000>; | ||
| 53 | |||
| 54 | reset: reset-controller { | ||
| 55 | compatible = "oxsemi,ox810se-reset"; | ||
| 56 | #reset-cells = <1>; | ||
| 57 | }; | ||
| 58 | }; | ||
diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig index df37212a5cbd..0b2733db0e9e 100644 --- a/drivers/reset/Kconfig +++ b/drivers/reset/Kconfig | |||
| @@ -12,5 +12,8 @@ menuconfig RESET_CONTROLLER | |||
| 12 | 12 | ||
| 13 | If unsure, say no. | 13 | If unsure, say no. |
| 14 | 14 | ||
| 15 | config RESET_OXNAS | ||
| 16 | bool | ||
| 17 | |||
| 15 | source "drivers/reset/sti/Kconfig" | 18 | source "drivers/reset/sti/Kconfig" |
| 16 | source "drivers/reset/hisilicon/Kconfig" | 19 | source "drivers/reset/hisilicon/Kconfig" |
diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile index a1fc8eda79f3..f173fc3847b4 100644 --- a/drivers/reset/Makefile +++ b/drivers/reset/Makefile | |||
| @@ -8,3 +8,4 @@ obj-$(CONFIG_ARCH_STI) += sti/ | |||
| 8 | obj-$(CONFIG_ARCH_HISI) += hisilicon/ | 8 | obj-$(CONFIG_ARCH_HISI) += hisilicon/ |
| 9 | obj-$(CONFIG_ARCH_ZYNQ) += reset-zynq.o | 9 | obj-$(CONFIG_ARCH_ZYNQ) += reset-zynq.o |
| 10 | obj-$(CONFIG_ATH79) += reset-ath79.o | 10 | obj-$(CONFIG_ATH79) += reset-ath79.o |
| 11 | obj-$(CONFIG_RESET_OXNAS) += reset-oxnas.o | ||
diff --git a/drivers/reset/reset-oxnas.c b/drivers/reset/reset-oxnas.c new file mode 100644 index 000000000000..c60fb2dace3e --- /dev/null +++ b/drivers/reset/reset-oxnas.c | |||
| @@ -0,0 +1,136 @@ | |||
| 1 | /* | ||
| 2 | * drivers/reset/reset-oxnas.c | ||
| 3 | * | ||
| 4 | * Copyright (C) 2016 Neil Armstrong <narmstrong@baylibre.com> | ||
| 5 | * Copyright (C) 2014 Ma Haijun <mahaijuns@gmail.com> | ||
| 6 | * Copyright (C) 2009 Oxford Semiconductor Ltd | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify it | ||
| 9 | * under the terms and conditions of the GNU General Public License, | ||
| 10 | * version 2, as published by the Free Software Foundation. | ||
| 11 | * | ||
| 12 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
| 13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
| 14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
| 15 | * more details. | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU General Public License | ||
| 18 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 19 | */ | ||
| 20 | #include <linux/err.h> | ||
| 21 | #include <linux/module.h> | ||
| 22 | #include <linux/of.h> | ||
| 23 | #include <linux/platform_device.h> | ||
| 24 | #include <linux/reset-controller.h> | ||
| 25 | #include <linux/slab.h> | ||
| 26 | #include <linux/delay.h> | ||
| 27 | #include <linux/types.h> | ||
| 28 | #include <linux/regmap.h> | ||
| 29 | #include <linux/mfd/syscon.h> | ||
| 30 | |||
| 31 | /* Regmap offsets */ | ||
| 32 | #define RST_SET_REGOFFSET 0x34 | ||
| 33 | #define RST_CLR_REGOFFSET 0x38 | ||
| 34 | |||
| 35 | struct oxnas_reset { | ||
| 36 | struct regmap *regmap; | ||
| 37 | struct reset_controller_dev rcdev; | ||
| 38 | }; | ||
| 39 | |||
| 40 | static int oxnas_reset_reset(struct reset_controller_dev *rcdev, | ||
| 41 | unsigned long id) | ||
| 42 | { | ||
| 43 | struct oxnas_reset *data = | ||
| 44 | container_of(rcdev, struct oxnas_reset, rcdev); | ||
| 45 | |||
| 46 | regmap_write(data->regmap, RST_SET_REGOFFSET, BIT(id)); | ||
| 47 | msleep(50); | ||
| 48 | regmap_write(data->regmap, RST_CLR_REGOFFSET, BIT(id)); | ||
| 49 | |||
| 50 | return 0; | ||
| 51 | } | ||
| 52 | |||
| 53 | static int oxnas_reset_assert(struct reset_controller_dev *rcdev, | ||
| 54 | unsigned long id) | ||
| 55 | { | ||
| 56 | struct oxnas_reset *data = | ||
| 57 | container_of(rcdev, struct oxnas_reset, rcdev); | ||
| 58 | |||
| 59 | regmap_write(data->regmap, RST_SET_REGOFFSET, BIT(id)); | ||
| 60 | |||
| 61 | return 0; | ||
| 62 | } | ||
| 63 | |||
| 64 | static int oxnas_reset_deassert(struct reset_controller_dev *rcdev, | ||
| 65 | unsigned long id) | ||
| 66 | { | ||
| 67 | struct oxnas_reset *data = | ||
| 68 | container_of(rcdev, struct oxnas_reset, rcdev); | ||
| 69 | |||
| 70 | regmap_write(data->regmap, RST_CLR_REGOFFSET, BIT(id)); | ||
| 71 | |||
| 72 | return 0; | ||
| 73 | } | ||
| 74 | |||
| 75 | static const struct reset_control_ops oxnas_reset_ops = { | ||
| 76 | .reset = oxnas_reset_reset, | ||
| 77 | .assert = oxnas_reset_assert, | ||
| 78 | .deassert = oxnas_reset_deassert, | ||
| 79 | }; | ||
| 80 | |||
| 81 | static const struct of_device_id oxnas_reset_dt_ids[] = { | ||
| 82 | { .compatible = "oxsemi,ox810se-reset", }, | ||
| 83 | { /* sentinel */ }, | ||
| 84 | }; | ||
| 85 | MODULE_DEVICE_TABLE(of, oxnas_reset_dt_ids); | ||
| 86 | |||
| 87 | static int oxnas_reset_probe(struct platform_device *pdev) | ||
| 88 | { | ||
| 89 | struct oxnas_reset *data; | ||
| 90 | struct device *parent; | ||
| 91 | |||
| 92 | parent = pdev->dev.parent; | ||
| 93 | if (!parent) { | ||
| 94 | dev_err(&pdev->dev, "no parent\n"); | ||
| 95 | return -ENODEV; | ||
| 96 | } | ||
| 97 | |||
| 98 | data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); | ||
| 99 | if (!data) | ||
| 100 | return -ENOMEM; | ||
| 101 | |||
| 102 | data->regmap = syscon_node_to_regmap(parent->of_node); | ||
| 103 | if (IS_ERR(data->regmap)) { | ||
| 104 | dev_err(&pdev->dev, "failed to get parent regmap\n"); | ||
| 105 | return PTR_ERR(data->regmap); | ||
| 106 | } | ||
| 107 | |||
| 108 | platform_set_drvdata(pdev, data); | ||
| 109 | |||
| 110 | data->rcdev.owner = THIS_MODULE; | ||
| 111 | data->rcdev.nr_resets = 32; | ||
| 112 | data->rcdev.ops = &oxnas_reset_ops; | ||
| 113 | data->rcdev.of_node = pdev->dev.of_node; | ||
| 114 | |||
| 115 | return reset_controller_register(&data->rcdev); | ||
| 116 | } | ||
| 117 | |||
| 118 | static int oxnas_reset_remove(struct platform_device *pdev) | ||
| 119 | { | ||
| 120 | struct oxnas_reset *data = platform_get_drvdata(pdev); | ||
| 121 | |||
| 122 | reset_controller_unregister(&data->rcdev); | ||
| 123 | |||
| 124 | return 0; | ||
| 125 | } | ||
| 126 | |||
| 127 | static struct platform_driver oxnas_reset_driver = { | ||
| 128 | .probe = oxnas_reset_probe, | ||
| 129 | .remove = oxnas_reset_remove, | ||
| 130 | .driver = { | ||
| 131 | .name = "oxnas-reset", | ||
| 132 | .of_match_table = oxnas_reset_dt_ids, | ||
| 133 | }, | ||
| 134 | }; | ||
| 135 | |||
| 136 | module_platform_driver(oxnas_reset_driver); | ||
diff --git a/include/linux/reset.h b/include/linux/reset.h index a552134a209e..ec0306ce7b92 100644 --- a/include/linux/reset.h +++ b/include/linux/reset.h | |||
| @@ -56,6 +56,12 @@ static inline void reset_control_put(struct reset_control *rstc) | |||
| 56 | WARN_ON(1); | 56 | WARN_ON(1); |
| 57 | } | 57 | } |
| 58 | 58 | ||
| 59 | static inline int __must_check device_reset(struct device *dev) | ||
| 60 | { | ||
| 61 | WARN_ON(1); | ||
| 62 | return -ENOTSUPP; | ||
| 63 | } | ||
| 64 | |||
| 59 | static inline int device_reset_optional(struct device *dev) | 65 | static inline int device_reset_optional(struct device *dev) |
| 60 | { | 66 | { |
| 61 | return -ENOTSUPP; | 67 | return -ENOTSUPP; |
