Commit 751cd4aca2a4225eaf4a552c6ad47aade2f06e33
Exists in
smarct4x-processor-sdk-linux-02.00.01
and in
3 other branches
Merge branch 'platform-ti-linux-4.1.y' of git://git.ti.com/~rrnayak/ti-linux-ker…
…nel/platform-linux-feature-tree into ti-linux-4.1.y TI-Feature: platform_base TI-Tree: git://git.ti.com/~rrnayak/ti-linux-kernel/platform-linux-feature-tree.git TI-Branch: platform-ti-linux-4.1.y * 'platform-ti-linux-4.1.y' of git://git.ti.com/~rrnayak/ti-linux-kernel/platform-linux-feature-tree: ARM: dts: k2g: Add DSP GPIO controller node ARM: dts: k2g: Add keystone IRQ controller node ARM: dts: k2g: Add device state controller node ti_config_fragments/baseport: Enable TI SCI reset driver ARM: dts: k2g: Add TI SCI reset-controller node reset: Add the TI SCI reset driver Documentation: dt: reset: Add TI SCI reset binding dt-bindings: reset: Add k2g reset definitions ti_config_fragments/baseport: enable reset-syscon driver ARM: Keystone: Enable ARCH_HAS_RESET_CONTROLLER ARM: dts: keystone: Add PSC reset node reset: add a SYSCON based reset driver Documentation: dt: reset: Add syscon reset binding Signed-off-by: Dan Murphy <DMurphy@ti.com> Conflicts: arch/arm/boot/dts/k2g.dtsi
Showing 11 changed files Side-by-side Diff
- Documentation/devicetree/bindings/reset/syscon-reset.txt
- Documentation/devicetree/bindings/reset/ti,sci-reset.txt
- arch/arm/boot/dts/k2g.dtsi
- arch/arm/boot/dts/keystone.dtsi
- arch/arm/mach-keystone/Kconfig
- drivers/reset/Kconfig
- drivers/reset/Makefile
- drivers/reset/reset-syscon.c
- drivers/reset/reset-ti-sci.c
- include/dt-bindings/reset/k2g.h
- ti_config_fragments/baseport.cfg
Documentation/devicetree/bindings/reset/syscon-reset.txt
1 | +SysCon Reset Controller | |
2 | +======================= | |
3 | + | |
4 | +Almost all SoCs have hardware modules that require reset control in addition | |
5 | +to clock and power control for their functionality. The reset control is | |
6 | +typically provided by means of memory-mapped I/O registers. These registers are | |
7 | +sometimes a part of a larger register space region implementing various | |
8 | +functionalities. This register range is best represented as a syscon node to | |
9 | +allow multiple entities to access their relevant registers in the common | |
10 | +register space. | |
11 | + | |
12 | +A SysCon Reset Controller node defines a device that uses a syscon node | |
13 | +and provides reset management functionality for various hardware modules | |
14 | +present on the SoC. | |
15 | + | |
16 | +SysCon Reset Controller Node | |
17 | +============================ | |
18 | +Each of the reset provider/controller nodes should have the following | |
19 | +properties. | |
20 | + | |
21 | +Required properties: | |
22 | +-------------------- | |
23 | + - compatible : Should be "syscon-reset" | |
24 | + - syscon : phandle to the syscon node containing the reset registers | |
25 | + - #reset-cells : Should be 6. Please see the reset consumer node below for | |
26 | + usage details | |
27 | + | |
28 | +SysCon Reset Consumer Nodes | |
29 | +=========================== | |
30 | +Each of the reset consumer nodes should have the following properties, | |
31 | +in addition to their own properties. | |
32 | + | |
33 | +Required properties: | |
34 | +-------------------- | |
35 | + - resets : A phandle and reset specifier pair, one pair for each reset | |
36 | + signal that affects the device, or that the device manages. | |
37 | + The phandle should point to the syscon node containing the | |
38 | + reset registers, and the reset specifier should have 6 | |
39 | + cell-values. The reset specifier contains two similar pairs | |
40 | + of 3 cell-values each, the first of the pair containing the | |
41 | + reset control register information, and the second of the pair | |
42 | + containing the reset status register information. The reset | |
43 | + control and status registers can be same on some devices/SoCs. | |
44 | + | |
45 | + Each of the pairs of 3 cell-values should have the following | |
46 | + values: | |
47 | + Cell #1 : register offset of the reset control/status | |
48 | + register from the syscon register base | |
49 | + Cell #2 : bit shift value for the reset in the respective | |
50 | + reset control/status register | |
51 | + Cell #3 : polarity of the reset bit. Should be 1 for resets | |
52 | + that are asserted when the bit is set, 0 for | |
53 | + resets that are asserted when the bit is cleared | |
54 | + | |
55 | +Please also refer to Documentation/devicetree/bindings/reset/reset.txt for | |
56 | +common reset controller usage by consumers. | |
57 | + | |
58 | + | |
59 | +Example: | |
60 | +-------- | |
61 | +The following example demonstrates a syscon node, the reset controller node | |
62 | +using the syscon node, and a consumer (a DSP device) on the TI Keystone 2 | |
63 | +Hawking SoC. | |
64 | + | |
65 | +/ { | |
66 | + soc { | |
67 | + psc: power-sleep-controller@02350000 { | |
68 | + compatible = "syscon"; | |
69 | + reg = <0x02350000 0x1000>; | |
70 | + }; | |
71 | + | |
72 | + pscrst: psc-reset { | |
73 | + compatible = "syscon-reset"; | |
74 | + syscon = <&psc>; | |
75 | + #reset-cells = <6>; | |
76 | + }; | |
77 | + | |
78 | + dsp0: dsp0 { | |
79 | + ... | |
80 | + resets = <&pscrst 0xa3c 8 0 0x83c 8 0>; | |
81 | + ... | |
82 | + }; | |
83 | + }; | |
84 | +}; |
Documentation/devicetree/bindings/reset/ti,sci-reset.txt
1 | +Texas Instruments System Control Interface (TI-SCI) Reset Controller | |
2 | +===================================================================== | |
3 | + | |
4 | +Some TI SoCs contain a system controller (like the Power Management Micro | |
5 | +Controller (PMMC) on Keystone 2 Galileo SoC) that are responsible for | |
6 | +controlling the state of the various hardware modules present on the SoC. | |
7 | +Communication between the host processor running an OS and the system | |
8 | +controller happens through a protocol called TI System Control Interface | |
9 | +(TI-SCI protocol). For TI SCI details, please refer to the document, | |
10 | +Documentation/devicetree/bindings/arm/keystone/ti,sci.txt | |
11 | + | |
12 | +TI-SCI Reset Controller Node | |
13 | +============================ | |
14 | +This reset controller node uses the TI SCI protocol to perform the reset | |
15 | +management of various hardware modules present on the SoC. | |
16 | + | |
17 | +Required properties: | |
18 | +-------------------- | |
19 | + - compatible : Should be "ti,sci-reset" | |
20 | + - ti,sci : phandle to the TI SCI device to use for managing resets | |
21 | + - #reset-cells : Should be 2. Please see the reset consumer node below for | |
22 | + usage details. | |
23 | + | |
24 | +TI-SCI Reset Consumer Nodes | |
25 | +=========================== | |
26 | +Each of the reset consumer nodes should have the following properties, | |
27 | +in addition to their own properties. | |
28 | + | |
29 | +Required properties: | |
30 | +-------------------- | |
31 | + - resets : A phandle and reset specifier pair, one pair for each reset | |
32 | + signal that affects the device, or that the device manages. | |
33 | + The phandle should point to the TI-SCI reset controller node, | |
34 | + and the reset specifier should have 2 cell-values. The first | |
35 | + cell should contain the device ID, the values of which are | |
36 | + specified in the <dt-bindings/genpd/<soc>.h> include file. | |
37 | + The second cell should contain the reset mask value used by | |
38 | + system controller, the values of which are specified in the | |
39 | + include file <dt-bindings/reset/<soc>.h>, where <soc> is the | |
40 | + name of the SoC involved, for example 'k2g'. | |
41 | + | |
42 | +Please also refer to Documentation/devicetree/bindings/reset/reset.txt for | |
43 | +common reset controller usage by consumers. | |
44 | + | |
45 | + | |
46 | +Example: | |
47 | +-------- | |
48 | +The following example demonstrates both a TI-SCI reset controller node and a | |
49 | +consumer (a DSP device) on the Keystone 2 Galileo SoC. | |
50 | + | |
51 | +#include <dt-bindings/genpd/k2g.h> | |
52 | +#include <dt-bindings/reset/k2g.h> | |
53 | + | |
54 | +/ { | |
55 | + soc { | |
56 | + k2g_reset: k2g_reset { | |
57 | + compatible = "ti,sci-reset"; | |
58 | + ti,sci = <&pmmc>; | |
59 | + #reset-cells = <2>; | |
60 | + }; | |
61 | + | |
62 | + dsp0: dsp0 { | |
63 | + ... | |
64 | + resets = <&k2g_reset K2G_DEV_CGEM0 K2G_DEV_CGEM0_DSP0_RESET>; | |
65 | + ... | |
66 | + }; | |
67 | + }; | |
68 | +}; |
arch/arm/boot/dts/k2g.dtsi
... | ... | @@ -17,6 +17,7 @@ |
17 | 17 | #include <dt-bindings/pinctrl/keystone.h> |
18 | 18 | #include <dt-bindings/genpd/k2g.h> |
19 | 19 | #include <dt-bindings/clock/k2g.h> |
20 | +#include <dt-bindings/reset/k2g.h> | |
20 | 21 | #include "skeleton.dtsi" |
21 | 22 | |
22 | 23 | / { |
... | ... | @@ -89,6 +90,11 @@ |
89 | 90 | ranges = <0x0 0x0 0x0 0xc0000000>; |
90 | 91 | dma-ranges = <0x80000000 0x8 0x00000000 0x80000000>; |
91 | 92 | |
93 | + devctrl: device-state-control@02620000 { | |
94 | + compatible = "ti,keystone-devctrl", "syscon"; | |
95 | + reg = <0x02620000 0x1000>; | |
96 | + }; | |
97 | + | |
92 | 98 | k2g_pinctrl: pinmux@02621000 { |
93 | 99 | compatible = "pinctrl-single"; |
94 | 100 | reg = <0x02621000 0x410>; |
... | ... | @@ -473,6 +479,27 @@ |
473 | 479 | compatible = "ti,sci-pm-domains"; |
474 | 480 | #power-domain-cells = <1>; |
475 | 481 | ti,sci = <&pmmc>; |
482 | + }; | |
483 | + | |
484 | + k2g_reset: k2g_reset { | |
485 | + compatible = "ti,sci-reset"; | |
486 | + ti,sci = <&pmmc>; | |
487 | + #reset-cells = <2>; | |
488 | + }; | |
489 | + | |
490 | + kirq0: keystone_irq@026202a0 { | |
491 | + compatible = "ti,keystone-irq"; | |
492 | + interrupts = <GIC_SPI 1 IRQ_TYPE_EDGE_RISING>; | |
493 | + interrupt-controller; | |
494 | + #interrupt-cells = <1>; | |
495 | + ti,syscon-dev = <&devctrl 0x2a0>; | |
496 | + }; | |
497 | + | |
498 | + dspgpio0: keystone_dsp_gpio@02620240 { | |
499 | + compatible = "ti,keystone-dsp-gpio"; | |
500 | + gpio-controller; | |
501 | + #gpio-cells = <2>; | |
502 | + gpio,syscon-dev = <&devctrl 0x240>; | |
476 | 503 | }; |
477 | 504 | |
478 | 505 | mdio: mdio@4200f00 { |
arch/arm/boot/dts/keystone.dtsi
arch/arm/mach-keystone/Kconfig
drivers/reset/Kconfig
... | ... | @@ -12,5 +12,24 @@ |
12 | 12 | |
13 | 13 | If unsure, say no. |
14 | 14 | |
15 | +config SYSCON_RESET | |
16 | + tristate "SYSCON Reset Driver" | |
17 | + depends on RESET_CONTROLLER | |
18 | + select MFD_SYSCON | |
19 | + help | |
20 | + This enables the reset driver support for devices with memory-mapped | |
21 | + reset registers as part of a syscon device node. If you wish to use | |
22 | + the reset framework for such memory-mapped devices, say Y here. | |
23 | + Otherwise, say N. | |
24 | + | |
25 | +config TI_SCI_RESET | |
26 | + tristate "TI System Control Interface (TI-SCI) reset driver" | |
27 | + depends on RESET_CONTROLLER | |
28 | + depends on TI_SCI_PROTOCOL | |
29 | + help | |
30 | + This enables the reset driver support over TI System Control Interface | |
31 | + for TI's Keystone family of SoCs. If you wish to use reset resources | |
32 | + managed by the TI System Controller, say Y here. Otherwise, say N. | |
33 | + | |
15 | 34 | source "drivers/reset/sti/Kconfig" |
drivers/reset/Makefile
drivers/reset/reset-syscon.c
1 | +/* | |
2 | + * SYSCON regmap reset driver | |
3 | + * | |
4 | + * Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/ | |
5 | + * Andrew F. Davis <afd@ti.com> | |
6 | + * Suman Anna <afd@ti.com> | |
7 | + * | |
8 | + * This program is free software; you can redistribute it and/or modify | |
9 | + * it under the terms of the GNU General Public License version 2 as | |
10 | + * published by the Free Software Foundation. | |
11 | + * | |
12 | + * This program is distributed "as is" WITHOUT ANY WARRANTY of any | |
13 | + * kind, whether express or implied; without even the implied warranty | |
14 | + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | + * GNU General Public License for more details. | |
16 | + */ | |
17 | + | |
18 | +#include <linux/idr.h> | |
19 | +#include <linux/mfd/syscon.h> | |
20 | +#include <linux/module.h> | |
21 | +#include <linux/of.h> | |
22 | +#include <linux/platform_device.h> | |
23 | +#include <linux/regmap.h> | |
24 | +#include <linux/reset-controller.h> | |
25 | + | |
26 | +/** | |
27 | + * struct syscon_reset_control - reset control structure | |
28 | + * @offset: reset control register offset from syscon base | |
29 | + * @reset_bit: reset bit in the reset control register | |
30 | + * @assert_high: flag to indicate if setting the bit high asserts the reset | |
31 | + * @status_offset: reset status register offset from syscon base | |
32 | + * @status_reset_bit: reset status bit in the reset status register | |
33 | + * @status_assert_high: flag to indicate if a set bit represents asserted state | |
34 | + */ | |
35 | +struct syscon_reset_control { | |
36 | + unsigned int offset; | |
37 | + unsigned int reset_bit; | |
38 | + bool assert_high; | |
39 | + unsigned int status_offset; | |
40 | + unsigned int status_reset_bit; | |
41 | + bool status_assert_high; | |
42 | +}; | |
43 | + | |
44 | +/** | |
45 | + * struct syscon_reset_data - reset controller information structure | |
46 | + * @rcdev: reset controller entity | |
47 | + * @dev: reset controller device pointer | |
48 | + * @memory: regmap handle containing the memory-mapped reset registers | |
49 | + * @idr: idr structure for mapping ids to reset control structures | |
50 | + */ | |
51 | +struct syscon_reset_data { | |
52 | + struct reset_controller_dev rcdev; | |
53 | + struct device *dev; | |
54 | + struct regmap *memory; | |
55 | + struct idr idr; | |
56 | +}; | |
57 | + | |
58 | +#define to_syscon_reset_data(rcdev) \ | |
59 | + container_of(rcdev, struct syscon_reset_data, rcdev) | |
60 | + | |
61 | +/** | |
62 | + * syscon_reset_set() - program a device's reset | |
63 | + * @rcdev: reset controller entity | |
64 | + * @id: ID of the reset to toggle | |
65 | + * @assert: boolean flag to indicate assert or deassert | |
66 | + * | |
67 | + * This is a common internal function used to assert or deassert a device's | |
68 | + * reset using the regmap API. The device's reset is asserted if the @assert | |
69 | + * argument is true, or deasserted if the @assert argument is false. | |
70 | + * | |
71 | + * Return: 0 for successful request, else a corresponding error value | |
72 | + */ | |
73 | +static int syscon_reset_set(struct reset_controller_dev *rcdev, | |
74 | + unsigned long id, bool assert) | |
75 | +{ | |
76 | + struct syscon_reset_data *data = to_syscon_reset_data(rcdev); | |
77 | + struct syscon_reset_control *control; | |
78 | + unsigned int mask, value; | |
79 | + | |
80 | + control = idr_find(&data->idr, id); | |
81 | + if (!control) | |
82 | + return -EINVAL; | |
83 | + | |
84 | + mask = BIT(control->reset_bit); | |
85 | + value = (assert == control->assert_high) ? mask : 0x0; | |
86 | + | |
87 | + return regmap_update_bits(data->memory, control->offset, mask, value); | |
88 | +} | |
89 | + | |
90 | +/** | |
91 | + * syscon_reset_assert() - assert device reset | |
92 | + * @rcdev: reset controller entity | |
93 | + * @id: ID of the reset to be asserted | |
94 | + * | |
95 | + * This function implements the reset driver op to assert a device's reset. | |
96 | + * This invokes the function syscon_reset_set() with the corresponding | |
97 | + * parameters as passed in, but with the @assert argument set to true for | |
98 | + * asserting the reset. | |
99 | + * | |
100 | + * Return: 0 for successful request, else a corresponding error value | |
101 | + */ | |
102 | +static int syscon_reset_assert(struct reset_controller_dev *rcdev, | |
103 | + unsigned long id) | |
104 | +{ | |
105 | + return syscon_reset_set(rcdev, id, true); | |
106 | +} | |
107 | + | |
108 | +/** | |
109 | + * syscon_reset_deassert() - deassert device reset | |
110 | + * @rcdev: reset controller entity | |
111 | + * @id: ID of reset to be deasserted | |
112 | + * | |
113 | + * This function implements the reset driver op to deassert a device's reset. | |
114 | + * This invokes the function syscon_reset_set() with the corresponding | |
115 | + * parameters as passed in, but with the @assert argument set to false for | |
116 | + * deasserting the reset. | |
117 | + * | |
118 | + * Return: 0 for successful request, else a corresponding error value | |
119 | + */ | |
120 | +static int syscon_reset_deassert(struct reset_controller_dev *rcdev, | |
121 | + unsigned long id) | |
122 | +{ | |
123 | + return syscon_reset_set(rcdev, id, false); | |
124 | +} | |
125 | + | |
126 | +/** | |
127 | + * syscon_reset_status() - check device reset status | |
128 | + * @rcdev: reset controller entity | |
129 | + * @id: ID of the reset for which the status is being requested | |
130 | + * | |
131 | + * This function implements the reset driver op to return the status of a | |
132 | + * device's reset. | |
133 | + * | |
134 | + * Return: 0 if reset is deasserted, or a non-zero value if reset is asserted | |
135 | + */ | |
136 | +static int syscon_reset_status(struct reset_controller_dev *rcdev, | |
137 | + unsigned long id) | |
138 | +{ | |
139 | + struct syscon_reset_data *data = to_syscon_reset_data(rcdev); | |
140 | + struct syscon_reset_control *control; | |
141 | + unsigned int reset_state; | |
142 | + int ret; | |
143 | + | |
144 | + control = idr_find(&data->idr, id); | |
145 | + if (!control) | |
146 | + return -EINVAL; | |
147 | + | |
148 | + ret = regmap_read(data->memory, control->status_offset, &reset_state); | |
149 | + if (ret) | |
150 | + return ret; | |
151 | + | |
152 | + return (reset_state & BIT(control->status_reset_bit)) == | |
153 | + control->status_assert_high; | |
154 | +} | |
155 | + | |
156 | +static struct reset_control_ops syscon_reset_ops = { | |
157 | + .assert = syscon_reset_assert, | |
158 | + .deassert = syscon_reset_deassert, | |
159 | + .status = syscon_reset_status, | |
160 | +}; | |
161 | + | |
162 | +/** | |
163 | + * syscon_reset_of_xlate() - translate a set of OF arguments to a reset ID | |
164 | + * @rcdev: reset controller entity | |
165 | + * @reset_spec: OF reset argument specifier | |
166 | + * | |
167 | + * This function performs the translation of the reset argument specifier | |
168 | + * values defined in a reset consumer device node. The function allocates a | |
169 | + * reset control structure for that device reset, that will be used by the | |
170 | + * driver for performing any reset functions on that reset. An idr structure | |
171 | + * is allocated and used to map to the reset control structure. This idr is | |
172 | + * used by the driver to do reset lookups. | |
173 | + * | |
174 | + * Return: 0 for successful request, else a corresponding error value | |
175 | + */ | |
176 | +static int syscon_reset_of_xlate(struct reset_controller_dev *rcdev, | |
177 | + const struct of_phandle_args *reset_spec) | |
178 | +{ | |
179 | + struct syscon_reset_data *data = to_syscon_reset_data(rcdev); | |
180 | + struct syscon_reset_control *control; | |
181 | + | |
182 | + if (WARN_ON(reset_spec->args_count != rcdev->of_reset_n_cells)) | |
183 | + return -EINVAL; | |
184 | + | |
185 | + control = devm_kzalloc(data->dev, sizeof(*control), GFP_KERNEL); | |
186 | + if (!control) | |
187 | + return -ENOMEM; | |
188 | + | |
189 | + control->offset = reset_spec->args[0]; | |
190 | + control->reset_bit = reset_spec->args[1]; | |
191 | + control->assert_high = reset_spec->args[2] == 1; | |
192 | + control->status_offset = reset_spec->args[3]; | |
193 | + control->status_reset_bit = reset_spec->args[4]; | |
194 | + control->status_assert_high = reset_spec->args[5] == 1; | |
195 | + | |
196 | + return idr_alloc(&data->idr, control, 0, 0, GFP_KERNEL); | |
197 | +} | |
198 | + | |
199 | +static const struct of_device_id syscon_reset_of_match[] = { | |
200 | + { .compatible = "syscon-reset", }, | |
201 | + { /* sentinel */ }, | |
202 | +}; | |
203 | +MODULE_DEVICE_TABLE(of, syscon_reset_of_match); | |
204 | + | |
205 | +static int syscon_reset_probe(struct platform_device *pdev) | |
206 | +{ | |
207 | + struct syscon_reset_data *data; | |
208 | + struct device_node *np = pdev->dev.of_node; | |
209 | + struct regmap *memory; | |
210 | + | |
211 | + if (!np) | |
212 | + return -ENODEV; | |
213 | + | |
214 | + data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); | |
215 | + if (!data) | |
216 | + return -ENOMEM; | |
217 | + | |
218 | + memory = syscon_regmap_lookup_by_phandle(np, "syscon"); | |
219 | + if (IS_ERR(memory)) | |
220 | + return PTR_ERR(memory); | |
221 | + | |
222 | + data->rcdev.ops = &syscon_reset_ops; | |
223 | + data->rcdev.owner = THIS_MODULE; | |
224 | + data->rcdev.of_node = np; | |
225 | + data->rcdev.of_reset_n_cells = 6; | |
226 | + data->rcdev.of_xlate = syscon_reset_of_xlate; | |
227 | + data->dev = &pdev->dev; | |
228 | + data->memory = memory; | |
229 | + idr_init(&data->idr); | |
230 | + | |
231 | + platform_set_drvdata(pdev, data); | |
232 | + | |
233 | + return reset_controller_register(&data->rcdev); | |
234 | +} | |
235 | + | |
236 | +static int syscon_reset_remove(struct platform_device *pdev) | |
237 | +{ | |
238 | + struct syscon_reset_data *data = platform_get_drvdata(pdev); | |
239 | + | |
240 | + reset_controller_unregister(&data->rcdev); | |
241 | + | |
242 | + idr_destroy(&data->idr); | |
243 | + | |
244 | + return 0; | |
245 | +} | |
246 | + | |
247 | +static struct platform_driver syscon_reset_driver = { | |
248 | + .probe = syscon_reset_probe, | |
249 | + .remove = syscon_reset_remove, | |
250 | + .driver = { | |
251 | + .name = "syscon-reset", | |
252 | + .of_match_table = syscon_reset_of_match, | |
253 | + }, | |
254 | +}; | |
255 | +module_platform_driver(syscon_reset_driver); | |
256 | + | |
257 | +MODULE_AUTHOR("Andrew F. Davis <afd@ti.com>"); | |
258 | +MODULE_AUTHOR("Suman Anna <s-anna@ti.com>"); | |
259 | +MODULE_DESCRIPTION("SYSCON Regmap Reset Driver"); | |
260 | +MODULE_LICENSE("GPL v2"); |
drivers/reset/reset-ti-sci.c
1 | +/* | |
2 | + * Texas Instrument's System Control Interface (TI-SCI) reset driver for TI's | |
3 | + * Keystone generation devices | |
4 | + * | |
5 | + * Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/ | |
6 | + * Andrew F. Davis <afd@ti.com> | |
7 | + * | |
8 | + * This program is free software; you can redistribute it and/or modify | |
9 | + * it under the terms of the GNU General Public License version 2 as | |
10 | + * published by the Free Software Foundation. | |
11 | + * | |
12 | + * This program is distributed "as is" WITHOUT ANY WARRANTY of any | |
13 | + * kind, whether express or implied; without even the implied warranty | |
14 | + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | + * GNU General Public License for more details. | |
16 | + */ | |
17 | + | |
18 | +#include <linux/idr.h> | |
19 | +#include <linux/module.h> | |
20 | +#include <linux/of.h> | |
21 | +#include <linux/platform_device.h> | |
22 | +#include <linux/reset-controller.h> | |
23 | +#include <linux/ti_sci_protocol.h> | |
24 | + | |
25 | +/** | |
26 | + * struct ti_sci_reset_control - reset control structure | |
27 | + * @dev_id: SoC-specific device identifier | |
28 | + * @reset_mask: reset mask to use for toggling reset | |
29 | + */ | |
30 | +struct ti_sci_reset_control { | |
31 | + u32 dev_id; | |
32 | + u32 reset_mask; | |
33 | +}; | |
34 | + | |
35 | +/** | |
36 | + * struct ti_sci_reset_data - reset controller information structure | |
37 | + * @rcdev: reset controller entity | |
38 | + * @dev: reset controller device pointer | |
39 | + * @sci: TI SCI handle used for communication with system controller | |
40 | + * @idr: idr structure for mapping ids to reset control structures | |
41 | + */ | |
42 | +struct ti_sci_reset_data { | |
43 | + struct reset_controller_dev rcdev; | |
44 | + struct device *dev; | |
45 | + const struct ti_sci_handle *sci; | |
46 | + struct idr idr; | |
47 | +}; | |
48 | + | |
49 | +#define to_ti_sci_reset_data(rcdev) \ | |
50 | + container_of(rcdev, struct ti_sci_reset_data, rcdev) | |
51 | + | |
52 | +/** | |
53 | + * ti_sci_reset_set() - program a device's reset | |
54 | + * @rcdev: reset controller entity | |
55 | + * @id: ID of the reset to toggle | |
56 | + * @assert: boolean flag to indicate assert or deassert | |
57 | + * | |
58 | + * This is a common internal function used to assert or deassert a device's | |
59 | + * reset using the TI SCI protocol. The device's reset is asserted if the | |
60 | + * @assert argument is true, or deasserted if @assert argument is false. | |
61 | + * The mechanism itself is a read-modify-write procedure, the current device | |
62 | + * reset register is read using a TI SCI device operation, the new value is | |
63 | + * set or un-set using the reset's mask, and the new reset value written by | |
64 | + * using another TI SCI device operation. | |
65 | + * | |
66 | + * Return: 0 for successful request, else a corresponding error value | |
67 | + */ | |
68 | +static int ti_sci_reset_set(struct reset_controller_dev *rcdev, | |
69 | + unsigned long id, bool assert) | |
70 | +{ | |
71 | + struct ti_sci_reset_data *data = to_ti_sci_reset_data(rcdev); | |
72 | + const struct ti_sci_handle *sci = data->sci; | |
73 | + const struct ti_sci_dev_ops *dev_ops = &sci->ops.dev_ops; | |
74 | + struct ti_sci_reset_control *control; | |
75 | + u32 reset_state; | |
76 | + int ret; | |
77 | + | |
78 | + control = idr_find(&data->idr, id); | |
79 | + if (!control) | |
80 | + return -EINVAL; | |
81 | + | |
82 | + ret = dev_ops->get_device_resets(sci, control->dev_id, | |
83 | + &reset_state); | |
84 | + if (ret) | |
85 | + return ret; | |
86 | + | |
87 | + if (assert) | |
88 | + reset_state |= control->reset_mask; | |
89 | + else | |
90 | + reset_state &= ~control->reset_mask; | |
91 | + | |
92 | + return dev_ops->set_device_resets(sci, control->dev_id, | |
93 | + reset_state); | |
94 | +} | |
95 | + | |
96 | +/** | |
97 | + * ti_sci_reset_assert() - assert device reset | |
98 | + * @rcdev: reset controller entity | |
99 | + * @id: ID of the reset to be asserted | |
100 | + * | |
101 | + * This function implements the reset driver op to assert a device's reset | |
102 | + * using the TI SCI protocol. This invokes the function ti_sci_reset_set() | |
103 | + * with the corresponding parameters as passed in, but with the @assert | |
104 | + * argument set to true for asserting the reset. | |
105 | + * | |
106 | + * Return: 0 for successful request, else a corresponding error value | |
107 | + */ | |
108 | +static int ti_sci_reset_assert(struct reset_controller_dev *rcdev, | |
109 | + unsigned long id) | |
110 | +{ | |
111 | + return ti_sci_reset_set(rcdev, id, true); | |
112 | +} | |
113 | + | |
114 | +/** | |
115 | + * ti_sci_reset_deassert() - deassert device reset | |
116 | + * @rcdev: reset controller entity | |
117 | + * @id: ID of the reset to be deasserted | |
118 | + * | |
119 | + * This function implements the reset driver op to deassert a device's reset | |
120 | + * using the TI SCI protocol. This invokes the function ti_sci_reset_set() | |
121 | + * with the corresponding parameters as passed in, but with the @assert | |
122 | + * argument set to false for deasserting the reset. | |
123 | + * | |
124 | + * Return: 0 for successful request, else a corresponding error value | |
125 | + */ | |
126 | +static int ti_sci_reset_deassert(struct reset_controller_dev *rcdev, | |
127 | + unsigned long id) | |
128 | +{ | |
129 | + return ti_sci_reset_set(rcdev, id, false); | |
130 | +} | |
131 | + | |
132 | +/** | |
133 | + * ti_sci_reset_status() - check device reset status | |
134 | + * @rcdev: reset controller entity | |
135 | + * @id: ID of reset to be checked | |
136 | + * | |
137 | + * This function implements the reset driver op to return the status of a | |
138 | + * device's reset using the TI SCI protocol. The reset register value is read | |
139 | + * by invoking the TI SCI device opertation .get_device_resets(), and the | |
140 | + * status of the specific reset is extracted and returned using this reset's | |
141 | + * reset mask. | |
142 | + * | |
143 | + * Return: 0 if reset is deasserted, or a non-zero value if reset is asserted | |
144 | + */ | |
145 | +static int ti_sci_reset_status(struct reset_controller_dev *rcdev, | |
146 | + unsigned long id) | |
147 | +{ | |
148 | + struct ti_sci_reset_data *data = to_ti_sci_reset_data(rcdev); | |
149 | + const struct ti_sci_handle *sci = data->sci; | |
150 | + const struct ti_sci_dev_ops *dev_ops = &sci->ops.dev_ops; | |
151 | + struct ti_sci_reset_control *control; | |
152 | + u32 reset_state; | |
153 | + int ret; | |
154 | + | |
155 | + control = idr_find(&data->idr, id); | |
156 | + if (!control) | |
157 | + return -EINVAL; | |
158 | + | |
159 | + ret = dev_ops->get_device_resets(sci, control->dev_id, | |
160 | + &reset_state); | |
161 | + if (ret) | |
162 | + return ret; | |
163 | + | |
164 | + return reset_state & control->reset_mask; | |
165 | +} | |
166 | + | |
167 | +static struct reset_control_ops ti_sci_reset_ops = { | |
168 | + .assert = ti_sci_reset_assert, | |
169 | + .deassert = ti_sci_reset_deassert, | |
170 | + .status = ti_sci_reset_status, | |
171 | +}; | |
172 | + | |
173 | +/** | |
174 | + * ti_sci_reset_of_xlate() - translate a set of OF arguments to a reset ID | |
175 | + * @rcdev: reset controller entity | |
176 | + * @reset_spec: OF reset argument specifier | |
177 | + * | |
178 | + * This function performs the translation of the reset argument specifier | |
179 | + * values defined in a reset consumer device node. The function allocates a | |
180 | + * reset control structure for that device reset, and will be used by the | |
181 | + * driver for performing any reset functions on that reset. An idr structure | |
182 | + * is allocated and used to map to the reset control structure. This idr | |
183 | + * is used by the driver to do reset lookups. | |
184 | + * | |
185 | + * Return: 0 for successful request, else a corresponding error value | |
186 | + */ | |
187 | +static int ti_sci_reset_of_xlate(struct reset_controller_dev *rcdev, | |
188 | + const struct of_phandle_args *reset_spec) | |
189 | +{ | |
190 | + struct ti_sci_reset_data *data = to_ti_sci_reset_data(rcdev); | |
191 | + struct ti_sci_reset_control *control; | |
192 | + | |
193 | + if (WARN_ON(reset_spec->args_count != rcdev->of_reset_n_cells)) | |
194 | + return -EINVAL; | |
195 | + | |
196 | + control = devm_kzalloc(data->dev, sizeof(*control), GFP_KERNEL); | |
197 | + if (!control) | |
198 | + return -ENOMEM; | |
199 | + | |
200 | + control->dev_id = reset_spec->args[0]; | |
201 | + control->reset_mask = reset_spec->args[1]; | |
202 | + | |
203 | + return idr_alloc(&data->idr, control, 0, 0, GFP_KERNEL); | |
204 | +} | |
205 | + | |
206 | +static const struct of_device_id ti_sci_reset_of_match[] = { | |
207 | + { .compatible = "ti,sci-reset", }, | |
208 | + { /* sentinel */ }, | |
209 | +}; | |
210 | +MODULE_DEVICE_TABLE(of, ti_sci_reset_of_match); | |
211 | + | |
212 | +static int ti_sci_reset_probe(struct platform_device *pdev) | |
213 | +{ | |
214 | + struct ti_sci_reset_data *data; | |
215 | + | |
216 | + if (!pdev->dev.of_node) | |
217 | + return -ENODEV; | |
218 | + | |
219 | + data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); | |
220 | + if (!data) | |
221 | + return -ENOMEM; | |
222 | + | |
223 | + data->sci = devm_ti_sci_get_handle(&pdev->dev); | |
224 | + if (IS_ERR(data->sci)) | |
225 | + return PTR_ERR(data->sci); | |
226 | + | |
227 | + data->rcdev.ops = &ti_sci_reset_ops; | |
228 | + data->rcdev.owner = THIS_MODULE; | |
229 | + data->rcdev.of_node = pdev->dev.of_node; | |
230 | + data->rcdev.of_reset_n_cells = 2; | |
231 | + data->rcdev.of_xlate = ti_sci_reset_of_xlate; | |
232 | + data->dev = &pdev->dev; | |
233 | + idr_init(&data->idr); | |
234 | + | |
235 | + platform_set_drvdata(pdev, data); | |
236 | + | |
237 | + return reset_controller_register(&data->rcdev); | |
238 | +} | |
239 | + | |
240 | +static int ti_sci_reset_remove(struct platform_device *pdev) | |
241 | +{ | |
242 | + struct ti_sci_reset_data *data = platform_get_drvdata(pdev); | |
243 | + | |
244 | + reset_controller_unregister(&data->rcdev); | |
245 | + | |
246 | + idr_destroy(&data->idr); | |
247 | + | |
248 | + return 0; | |
249 | +} | |
250 | + | |
251 | +static struct platform_driver ti_sci_reset_driver = { | |
252 | + .probe = ti_sci_reset_probe, | |
253 | + .remove = ti_sci_reset_remove, | |
254 | + .driver = { | |
255 | + .name = "ti-sci-reset", | |
256 | + .of_match_table = ti_sci_reset_of_match, | |
257 | + }, | |
258 | +}; | |
259 | +module_platform_driver(ti_sci_reset_driver); | |
260 | + | |
261 | +MODULE_AUTHOR("Andrew F. Davis <afd@ti.com>"); | |
262 | +MODULE_DESCRIPTION("TI System Control Interface (TI SCI) Reset driver"); | |
263 | +MODULE_LICENSE("GPL v2"); |
include/dt-bindings/reset/k2g.h
1 | +/* | |
2 | + * TI K2G SoC reset definitions | |
3 | + * | |
4 | + * Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/ | |
5 | + * | |
6 | + * This program is free software; you can redistribute it and/or modify | |
7 | + * it under the terms of the GNU General Public License as published by | |
8 | + * the Free Software Foundation; either version 2 of the License, or | |
9 | + * (at your option) any later version. | |
10 | + * | |
11 | + * This program is distributed in the hope that it will be useful, | |
12 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | + * GNU General Public License for more details. | |
15 | + */ | |
16 | + | |
17 | +#ifndef __DT_BINDINGS_RESET_K2G_H__ | |
18 | +#define __DT_BINDINGS_RESET_K2G_H__ | |
19 | + | |
20 | +#define K2G_DEV_CGEM0_DSP0_RESET 0x1 | |
21 | + | |
22 | +#endif |
ti_config_fragments/baseport.cfg