diff options
author | James Hogan <james.hogan@imgtec.com> | 2013-06-20 05:26:29 -0400 |
---|---|---|
committer | Linus Walleij <linus.walleij@linaro.org> | 2013-06-24 11:21:38 -0400 |
commit | b58f0273f0858214da2ee4e1675221e56f7712ec (patch) | |
tree | 4b271facfd342bde65323cf0d37cf5ca6841b728 | |
parent | d5025f9f535108ba44c7f00573a2a34c18a3ea2b (diff) |
pinctrl-tz1090-pdc: add TZ1090 PDC pinctrl driver
Add a pin control driver for the TZ1090's low power pins via the
powerdown controller SOC_GPIO_CONTROL registers.
These pins have individually controlled pull-up, and group controlled
schmitt, slew-rate, drive-strength, and power-on-start (pos).
The pdc_gpio0 and pdc_gpio1 pins can also be muxed onto the
ir_mod_stable_out and ir_mod_power_out functions respectively. If no
function is set they remain in GPIO mode. These muxes can be overridden
by requesting them as GPIOs.
Signed-off-by: James Hogan <james.hogan@imgtec.com>
Cc: Grant Likely <grant.likely@linaro.org>
Cc: Rob Herring <rob.herring@calxeda.com>
Cc: Rob Landley <rob@landley.net>
Cc: Linus Walleij <linus.walleij@linaro.org>
Cc: linux-doc@vger.kernel.org
Cc: devicetree-discuss@lists.ozlabs.org
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
-rw-r--r-- | Documentation/devicetree/bindings/pinctrl/img,tz1090-pdc-pinctrl.txt | 130 | ||||
-rw-r--r-- | drivers/pinctrl/Kconfig | 6 | ||||
-rw-r--r-- | drivers/pinctrl/Makefile | 1 | ||||
-rw-r--r-- | drivers/pinctrl/pinctrl-tz1090-pdc.c | 1029 |
4 files changed, 1166 insertions, 0 deletions
diff --git a/Documentation/devicetree/bindings/pinctrl/img,tz1090-pdc-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/img,tz1090-pdc-pinctrl.txt new file mode 100644 index 000000000000..9f7a85bb8fca --- /dev/null +++ b/Documentation/devicetree/bindings/pinctrl/img,tz1090-pdc-pinctrl.txt | |||
@@ -0,0 +1,130 @@ | |||
1 | ImgTec TZ1090 PDC pin controller | ||
2 | |||
3 | Required properties: | ||
4 | - compatible: "img,tz1090-pdc-pinctrl" | ||
5 | - reg: Should contain the register physical address and length of the | ||
6 | SOC_GPIO_CONTROL registers in the PDC register region. | ||
7 | |||
8 | Please refer to pinctrl-bindings.txt in this directory for details of the | ||
9 | common pinctrl bindings used by client devices, including the meaning of the | ||
10 | phrase "pin configuration node". | ||
11 | |||
12 | TZ1090-PDC's pin configuration nodes act as a container for an abitrary number | ||
13 | of subnodes. Each of these subnodes represents some desired configuration for a | ||
14 | pin, a group, or a list of pins or groups. This configuration can include the | ||
15 | mux function to select on those pin(s)/group(s), and various pin configuration | ||
16 | parameters, such as pull-up, drive strength, etc. | ||
17 | |||
18 | The name of each subnode is not important; all subnodes should be enumerated | ||
19 | and processed purely based on their content. | ||
20 | |||
21 | Each subnode only affects those parameters that are explicitly listed. In | ||
22 | other words, a subnode that lists a mux function but no pin configuration | ||
23 | parameters implies no information about any pin configuration parameters. | ||
24 | Similarly, a pin subnode that describes a pullup parameter implies no | ||
25 | information about e.g. the mux function. For this reason, even seemingly boolean | ||
26 | values are actually tristates in this binding: unspecified, off, or on. | ||
27 | Unspecified is represented as an absent property, and off/on are represented as | ||
28 | integer values 0 and 1. | ||
29 | |||
30 | Required subnode-properties: | ||
31 | - tz1090,pins : An array of strings. Each string contains the name of a pin or | ||
32 | group. Valid values for these names are listed below. | ||
33 | |||
34 | Optional subnode-properties: | ||
35 | - tz1090,function: A string containing the name of the function to mux to the | ||
36 | pin or group. Valid values for function names are listed below, including | ||
37 | which pingroups can be muxed to them. | ||
38 | - supported generic pinconfig properties (for further details see | ||
39 | Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt): | ||
40 | - bias-disable | ||
41 | - bias-high-impedance | ||
42 | - bias-bus-hold | ||
43 | - bias-pull-up | ||
44 | - bias-pull-down | ||
45 | - input-schmitt-enable | ||
46 | - input-schmitt-disable | ||
47 | - slew-rate: Integer, control slew rate of pins. | ||
48 | 0: slow (half frequency) | ||
49 | 1: fast | ||
50 | - drive-strength: Integer, control drive strength of pins in mA. | ||
51 | 2: 2mA | ||
52 | 4: 4mA | ||
53 | 8: 8mA | ||
54 | 12: 12mA | ||
55 | - low-power-enable: Flag, power-on-start weak pull-down for invalid power. | ||
56 | - low-power-disable: Flag, power-on-start weak pull-down disabled. | ||
57 | |||
58 | Note that many of these properties are only valid for certain specific pins | ||
59 | or groups. See the TZ1090 TRM for complete details regarding which groups | ||
60 | support which functionality. The Linux pinctrl driver may also be a useful | ||
61 | reference. | ||
62 | |||
63 | Valid values for pin and group names are: | ||
64 | |||
65 | pins: | ||
66 | |||
67 | These all support bias-high-impediance, bias-pull-up, bias-pull-down, and | ||
68 | bias-bus-hold (which can also be provided to any of the groups below to set | ||
69 | it for all gpio pins in that group). | ||
70 | |||
71 | gpio0, gpio1, sys_wake0, sys_wake1, sys_wake2, ir_data, ext_power. | ||
72 | |||
73 | mux groups: | ||
74 | |||
75 | These all support function. | ||
76 | |||
77 | gpio0 | ||
78 | pins: gpio0. | ||
79 | function: ir_mod_stable_out. | ||
80 | gpio1 | ||
81 | pins: gpio1. | ||
82 | function: ir_mod_power_out. | ||
83 | |||
84 | drive groups: | ||
85 | |||
86 | These support input-schmitt-enable, input-schmitt-disable, slew-rate, | ||
87 | drive-strength, low-power-enable, and low-power-disable. | ||
88 | |||
89 | pdc | ||
90 | pins: gpio0, gpio1, sys_wake0, sys_wake1, sys_wake2, ir_data, | ||
91 | ext_power. | ||
92 | |||
93 | Example: | ||
94 | |||
95 | pinctrl_pdc: pinctrl@02006500 { | ||
96 | #gpio-range-cells = <3>; | ||
97 | compatible = "img,tz1090-pdc-pinctrl"; | ||
98 | reg = <0x02006500 0x100>; | ||
99 | }; | ||
100 | |||
101 | Example board file extracts: | ||
102 | |||
103 | &pinctrl_pdc { | ||
104 | pinctrl-names = "default"; | ||
105 | pinctrl-0 = <&syswake_default>; | ||
106 | |||
107 | syswake_default: syswakes { | ||
108 | syswake_cfg { | ||
109 | tz1090,pins = "sys_wake0", | ||
110 | "sys_wake1", | ||
111 | "sys_wake2"; | ||
112 | pull-up; | ||
113 | }; | ||
114 | }; | ||
115 | irmod_default: irmod { | ||
116 | gpio0_cfg { | ||
117 | tz1090,pins = "gpio0"; | ||
118 | tz1090,function = "ir_mod_stable_out"; | ||
119 | }; | ||
120 | gpio1_cfg { | ||
121 | tz1090,pins = "gpio1"; | ||
122 | tz1090,function = "ir_mod_power_out"; | ||
123 | }; | ||
124 | }; | ||
125 | }; | ||
126 | |||
127 | ir: ir@02006200 { | ||
128 | pinctrl-names = "default"; | ||
129 | pinctrl-0 = <&irmod_default>; | ||
130 | }; | ||
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index acdaa08b325c..74ec8348eed6 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig | |||
@@ -218,6 +218,12 @@ config PINCTRL_TZ1090 | |||
218 | select PINMUX | 218 | select PINMUX |
219 | select GENERIC_PINCONF | 219 | select GENERIC_PINCONF |
220 | 220 | ||
221 | config PINCTRL_TZ1090_PDC | ||
222 | bool "Toumaz Xenif TZ1090 PDC pin control driver" | ||
223 | depends on SOC_TZ1090 | ||
224 | select PINMUX | ||
225 | select PINCONF | ||
226 | |||
221 | config PINCTRL_U300 | 227 | config PINCTRL_U300 |
222 | bool "U300 pin controller driver" | 228 | bool "U300 pin controller driver" |
223 | depends on ARCH_U300 | 229 | depends on ARCH_U300 |
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile index 37ff29e1bba3..cf699a519e9a 100644 --- a/drivers/pinctrl/Makefile +++ b/drivers/pinctrl/Makefile | |||
@@ -41,6 +41,7 @@ obj-$(CONFIG_PINCTRL_TEGRA20) += pinctrl-tegra20.o | |||
41 | obj-$(CONFIG_PINCTRL_TEGRA30) += pinctrl-tegra30.o | 41 | obj-$(CONFIG_PINCTRL_TEGRA30) += pinctrl-tegra30.o |
42 | obj-$(CONFIG_PINCTRL_TEGRA114) += pinctrl-tegra114.o | 42 | obj-$(CONFIG_PINCTRL_TEGRA114) += pinctrl-tegra114.o |
43 | obj-$(CONFIG_PINCTRL_TZ1090) += pinctrl-tz1090.o | 43 | obj-$(CONFIG_PINCTRL_TZ1090) += pinctrl-tz1090.o |
44 | obj-$(CONFIG_PINCTRL_TZ1090_PDC) += pinctrl-tz1090-pdc.o | ||
44 | obj-$(CONFIG_PINCTRL_U300) += pinctrl-u300.o | 45 | obj-$(CONFIG_PINCTRL_U300) += pinctrl-u300.o |
45 | obj-$(CONFIG_PINCTRL_COH901) += pinctrl-coh901.o | 46 | obj-$(CONFIG_PINCTRL_COH901) += pinctrl-coh901.o |
46 | obj-$(CONFIG_PINCTRL_SAMSUNG) += pinctrl-samsung.o | 47 | obj-$(CONFIG_PINCTRL_SAMSUNG) += pinctrl-samsung.o |
diff --git a/drivers/pinctrl/pinctrl-tz1090-pdc.c b/drivers/pinctrl/pinctrl-tz1090-pdc.c new file mode 100644 index 000000000000..12e480869468 --- /dev/null +++ b/drivers/pinctrl/pinctrl-tz1090-pdc.c | |||
@@ -0,0 +1,1029 @@ | |||
1 | /* | ||
2 | * Pinctrl driver for the Toumaz Xenif TZ1090 PowerDown Controller pins | ||
3 | * | ||
4 | * Copyright (c) 2013, Imagination Technologies Ltd. | ||
5 | * | ||
6 | * Derived from Tegra code: | ||
7 | * Copyright (c) 2011-2012, NVIDIA CORPORATION. All rights reserved. | ||
8 | * | ||
9 | * Derived from code: | ||
10 | * Copyright (C) 2010 Google, Inc. | ||
11 | * Copyright (C) 2010 NVIDIA Corporation | ||
12 | * Copyright (C) 2009-2011 ST-Ericsson AB | ||
13 | * | ||
14 | * This program is free software; you can redistribute it and/or modify it | ||
15 | * under the terms and conditions of the GNU General Public License, | ||
16 | * version 2, as published by the Free Software Foundation. | ||
17 | * | ||
18 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
19 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
20 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
21 | * more details. | ||
22 | */ | ||
23 | |||
24 | #include <linux/bitops.h> | ||
25 | #include <linux/io.h> | ||
26 | #include <linux/module.h> | ||
27 | #include <linux/of.h> | ||
28 | #include <linux/platform_device.h> | ||
29 | #include <linux/pinctrl/machine.h> | ||
30 | #include <linux/pinctrl/pinconf-generic.h> | ||
31 | #include <linux/pinctrl/pinctrl.h> | ||
32 | #include <linux/pinctrl/pinmux.h> | ||
33 | #include <linux/slab.h> | ||
34 | |||
35 | /* | ||
36 | * The registers may be shared with other threads/cores, so we need to use the | ||
37 | * metag global lock2 for atomicity. | ||
38 | */ | ||
39 | #include <asm/global_lock.h> | ||
40 | |||
41 | #include "core.h" | ||
42 | #include "pinconf.h" | ||
43 | |||
44 | /* Register offsets from bank base address */ | ||
45 | #define REG_GPIO_CONTROL0 0x00 | ||
46 | #define REG_GPIO_CONTROL2 0x08 | ||
47 | |||
48 | /* Register field information */ | ||
49 | #define REG_GPIO_CONTROL2_PU_PD_S 16 | ||
50 | #define REG_GPIO_CONTROL2_PDC_POS_S 4 | ||
51 | #define REG_GPIO_CONTROL2_PDC_DR_S 2 | ||
52 | #define REG_GPIO_CONTROL2_PDC_SR_S 1 | ||
53 | #define REG_GPIO_CONTROL2_PDC_SCHMITT_S 0 | ||
54 | |||
55 | /* PU_PD field values */ | ||
56 | #define REG_PU_PD_TRISTATE 0 | ||
57 | #define REG_PU_PD_UP 1 | ||
58 | #define REG_PU_PD_DOWN 2 | ||
59 | #define REG_PU_PD_REPEATER 3 | ||
60 | |||
61 | /* DR field values */ | ||
62 | #define REG_DR_2mA 0 | ||
63 | #define REG_DR_4mA 1 | ||
64 | #define REG_DR_8mA 2 | ||
65 | #define REG_DR_12mA 3 | ||
66 | |||
67 | /** | ||
68 | * struct tz1090_pdc_function - TZ1090 PDC pinctrl mux function | ||
69 | * @name: The name of the function, exported to pinctrl core. | ||
70 | * @groups: An array of pin groups that may select this function. | ||
71 | * @ngroups: The number of entries in @groups. | ||
72 | */ | ||
73 | struct tz1090_pdc_function { | ||
74 | const char *name; | ||
75 | const char * const *groups; | ||
76 | unsigned int ngroups; | ||
77 | }; | ||
78 | |||
79 | /** | ||
80 | * struct tz1090_pdc_pingroup - TZ1090 PDC pin group | ||
81 | * @name: Name of pin group. | ||
82 | * @pins: Array of pin numbers in this pin group. | ||
83 | * @npins: Number of pins in this pin group. | ||
84 | * @func: Function enabled by the mux. | ||
85 | * @reg: Mux register offset. | ||
86 | * @bit: Mux register bit. | ||
87 | * @drv: Drive control supported, otherwise it's a mux. | ||
88 | * This means Schmitt, Slew, and Drive strength. | ||
89 | * | ||
90 | * A representation of a group of pins (possibly just one pin) in the TZ1090 | ||
91 | * PDC pin controller. Each group allows some parameter or parameters to be | ||
92 | * configured. The most common is mux function selection. | ||
93 | */ | ||
94 | struct tz1090_pdc_pingroup { | ||
95 | const char *name; | ||
96 | const unsigned int *pins; | ||
97 | unsigned int npins; | ||
98 | int func; | ||
99 | u16 reg; | ||
100 | u8 bit; | ||
101 | bool drv; | ||
102 | }; | ||
103 | |||
104 | /* | ||
105 | * All PDC pins can be GPIOs. Define these first to match how the GPIO driver | ||
106 | * names/numbers its pins. | ||
107 | */ | ||
108 | |||
109 | enum tz1090_pdc_pin { | ||
110 | TZ1090_PDC_PIN_GPIO0, | ||
111 | TZ1090_PDC_PIN_GPIO1, | ||
112 | TZ1090_PDC_PIN_SYS_WAKE0, | ||
113 | TZ1090_PDC_PIN_SYS_WAKE1, | ||
114 | TZ1090_PDC_PIN_SYS_WAKE2, | ||
115 | TZ1090_PDC_PIN_IR_DATA, | ||
116 | TZ1090_PDC_PIN_EXT_POWER, | ||
117 | }; | ||
118 | |||
119 | /* Pin names */ | ||
120 | |||
121 | static const struct pinctrl_pin_desc tz1090_pdc_pins[] = { | ||
122 | /* PDC GPIOs */ | ||
123 | PINCTRL_PIN(TZ1090_PDC_PIN_GPIO0, "gpio0"), | ||
124 | PINCTRL_PIN(TZ1090_PDC_PIN_GPIO1, "gpio1"), | ||
125 | PINCTRL_PIN(TZ1090_PDC_PIN_SYS_WAKE0, "sys_wake0"), | ||
126 | PINCTRL_PIN(TZ1090_PDC_PIN_SYS_WAKE1, "sys_wake1"), | ||
127 | PINCTRL_PIN(TZ1090_PDC_PIN_SYS_WAKE2, "sys_wake2"), | ||
128 | PINCTRL_PIN(TZ1090_PDC_PIN_IR_DATA, "ir_data"), | ||
129 | PINCTRL_PIN(TZ1090_PDC_PIN_EXT_POWER, "ext_power"), | ||
130 | }; | ||
131 | |||
132 | /* Pin group pins */ | ||
133 | |||
134 | static const unsigned int gpio0_pins[] = { | ||
135 | TZ1090_PDC_PIN_GPIO0, | ||
136 | }; | ||
137 | |||
138 | static const unsigned int gpio1_pins[] = { | ||
139 | TZ1090_PDC_PIN_GPIO1, | ||
140 | }; | ||
141 | |||
142 | static const unsigned int pdc_pins[] = { | ||
143 | TZ1090_PDC_PIN_GPIO0, | ||
144 | TZ1090_PDC_PIN_GPIO1, | ||
145 | TZ1090_PDC_PIN_SYS_WAKE0, | ||
146 | TZ1090_PDC_PIN_SYS_WAKE1, | ||
147 | TZ1090_PDC_PIN_SYS_WAKE2, | ||
148 | TZ1090_PDC_PIN_IR_DATA, | ||
149 | TZ1090_PDC_PIN_EXT_POWER, | ||
150 | }; | ||
151 | |||
152 | /* Mux functions */ | ||
153 | |||
154 | enum tz1090_pdc_mux { | ||
155 | /* PDC_GPIO0 mux */ | ||
156 | TZ1090_PDC_MUX_IR_MOD_STABLE_OUT, | ||
157 | /* PDC_GPIO1 mux */ | ||
158 | TZ1090_PDC_MUX_IR_MOD_POWER_OUT, | ||
159 | }; | ||
160 | |||
161 | /* Pin groups a function can be muxed to */ | ||
162 | |||
163 | static const char * const gpio0_groups[] = { | ||
164 | "gpio0", | ||
165 | }; | ||
166 | |||
167 | static const char * const gpio1_groups[] = { | ||
168 | "gpio1", | ||
169 | }; | ||
170 | |||
171 | #define FUNCTION(mux, fname, group) \ | ||
172 | [(TZ1090_PDC_MUX_ ## mux)] = { \ | ||
173 | .name = #fname, \ | ||
174 | .groups = group##_groups, \ | ||
175 | .ngroups = ARRAY_SIZE(group##_groups), \ | ||
176 | } | ||
177 | |||
178 | /* Must correlate with enum tz1090_pdc_mux */ | ||
179 | static const struct tz1090_pdc_function tz1090_pdc_functions[] = { | ||
180 | /* MUX fn pingroups */ | ||
181 | FUNCTION(IR_MOD_STABLE_OUT, ir_mod_stable_out, gpio0), | ||
182 | FUNCTION(IR_MOD_POWER_OUT, ir_mod_power_out, gpio1), | ||
183 | }; | ||
184 | |||
185 | /** | ||
186 | * MUX_PG() - Initialise a pin group with mux control | ||
187 | * @pg_name: Pin group name (stringified, _pins appended to get pins array) | ||
188 | * @f0: Function 0 (TZ1090_PDC_MUX_ is prepended) | ||
189 | * @mux_r: Mux register (REG_PINCTRL_ is prepended) | ||
190 | * @mux_b: Bit number in register of mux field | ||
191 | */ | ||
192 | #define MUX_PG(pg_name, f0, mux_r, mux_b) \ | ||
193 | { \ | ||
194 | .name = #pg_name, \ | ||
195 | .pins = pg_name##_pins, \ | ||
196 | .npins = ARRAY_SIZE(pg_name##_pins), \ | ||
197 | .func = TZ1090_PDC_MUX_ ## f0, \ | ||
198 | .reg = (REG_ ## mux_r), \ | ||
199 | .bit = (mux_b), \ | ||
200 | } | ||
201 | |||
202 | /** | ||
203 | * DRV_PG() - Initialise a pin group with drive control | ||
204 | * @pg_name: Pin group name (stringified, _pins appended to get pins array) | ||
205 | */ | ||
206 | #define DRV_PG(pg_name) \ | ||
207 | { \ | ||
208 | .name = #pg_name, \ | ||
209 | .pins = pg_name##_pins, \ | ||
210 | .npins = ARRAY_SIZE(pg_name##_pins), \ | ||
211 | .drv = true, \ | ||
212 | } | ||
213 | |||
214 | static const struct tz1090_pdc_pingroup tz1090_pdc_groups[] = { | ||
215 | /* Muxing pin groups */ | ||
216 | /* pg_name, f0, mux register, mux bit */ | ||
217 | MUX_PG(gpio0, IR_MOD_STABLE_OUT, GPIO_CONTROL0, 7), | ||
218 | MUX_PG(gpio1, IR_MOD_POWER_OUT, GPIO_CONTROL0, 6), | ||
219 | |||
220 | /* Drive pin groups */ | ||
221 | /* pg_name */ | ||
222 | DRV_PG(pdc), | ||
223 | }; | ||
224 | |||
225 | /** | ||
226 | * struct tz1090_pdc_pmx - Private pinctrl data | ||
227 | * @dev: Platform device | ||
228 | * @pctl: Pin control device | ||
229 | * @regs: Register region | ||
230 | * @lock: Lock protecting coherency of mux_en and gpio_en | ||
231 | * @mux_en: Muxes that have been enabled | ||
232 | * @gpio_en: Muxable GPIOs that have been enabled | ||
233 | */ | ||
234 | struct tz1090_pdc_pmx { | ||
235 | struct device *dev; | ||
236 | struct pinctrl_dev *pctl; | ||
237 | void __iomem *regs; | ||
238 | spinlock_t lock; | ||
239 | u32 mux_en; | ||
240 | u32 gpio_en; | ||
241 | }; | ||
242 | |||
243 | static inline u32 pmx_read(struct tz1090_pdc_pmx *pmx, u32 reg) | ||
244 | { | ||
245 | return ioread32(pmx->regs + reg); | ||
246 | } | ||
247 | |||
248 | static inline void pmx_write(struct tz1090_pdc_pmx *pmx, u32 val, u32 reg) | ||
249 | { | ||
250 | iowrite32(val, pmx->regs + reg); | ||
251 | } | ||
252 | |||
253 | /* | ||
254 | * Pin control operations | ||
255 | */ | ||
256 | |||
257 | static int tz1090_pdc_pinctrl_get_groups_count(struct pinctrl_dev *pctldev) | ||
258 | { | ||
259 | return ARRAY_SIZE(tz1090_pdc_groups); | ||
260 | } | ||
261 | |||
262 | static const char *tz1090_pdc_pinctrl_get_group_name(struct pinctrl_dev *pctl, | ||
263 | unsigned int group) | ||
264 | { | ||
265 | return tz1090_pdc_groups[group].name; | ||
266 | } | ||
267 | |||
268 | static int tz1090_pdc_pinctrl_get_group_pins(struct pinctrl_dev *pctldev, | ||
269 | unsigned int group, | ||
270 | const unsigned int **pins, | ||
271 | unsigned int *num_pins) | ||
272 | { | ||
273 | *pins = tz1090_pdc_groups[group].pins; | ||
274 | *num_pins = tz1090_pdc_groups[group].npins; | ||
275 | |||
276 | return 0; | ||
277 | } | ||
278 | |||
279 | #ifdef CONFIG_DEBUG_FS | ||
280 | static void tz1090_pdc_pinctrl_pin_dbg_show(struct pinctrl_dev *pctldev, | ||
281 | struct seq_file *s, | ||
282 | unsigned int offset) | ||
283 | { | ||
284 | seq_printf(s, " %s", dev_name(pctldev->dev)); | ||
285 | } | ||
286 | #endif | ||
287 | |||
288 | static int reserve_map(struct device *dev, struct pinctrl_map **map, | ||
289 | unsigned int *reserved_maps, unsigned int *num_maps, | ||
290 | unsigned int reserve) | ||
291 | { | ||
292 | unsigned int old_num = *reserved_maps; | ||
293 | unsigned int new_num = *num_maps + reserve; | ||
294 | struct pinctrl_map *new_map; | ||
295 | |||
296 | if (old_num >= new_num) | ||
297 | return 0; | ||
298 | |||
299 | new_map = krealloc(*map, sizeof(*new_map) * new_num, GFP_KERNEL); | ||
300 | if (!new_map) { | ||
301 | dev_err(dev, "krealloc(map) failed\n"); | ||
302 | return -ENOMEM; | ||
303 | } | ||
304 | |||
305 | memset(new_map + old_num, 0, (new_num - old_num) * sizeof(*new_map)); | ||
306 | |||
307 | *map = new_map; | ||
308 | *reserved_maps = new_num; | ||
309 | |||
310 | return 0; | ||
311 | } | ||
312 | |||
313 | static int add_map_mux(struct pinctrl_map **map, unsigned int *reserved_maps, | ||
314 | unsigned int *num_maps, const char *group, | ||
315 | const char *function) | ||
316 | { | ||
317 | if (WARN_ON(*num_maps == *reserved_maps)) | ||
318 | return -ENOSPC; | ||
319 | |||
320 | (*map)[*num_maps].type = PIN_MAP_TYPE_MUX_GROUP; | ||
321 | (*map)[*num_maps].data.mux.group = group; | ||
322 | (*map)[*num_maps].data.mux.function = function; | ||
323 | (*num_maps)++; | ||
324 | |||
325 | return 0; | ||
326 | } | ||
327 | |||
328 | /** | ||
329 | * get_group_selector() - returns the group selector for a group | ||
330 | * @pin_group: the pin group to look up | ||
331 | * | ||
332 | * This is the same as pinctrl_get_group_selector except it doesn't produce an | ||
333 | * error message if the group isn't found or debug messages. | ||
334 | */ | ||
335 | static int get_group_selector(const char *pin_group) | ||
336 | { | ||
337 | unsigned int group; | ||
338 | |||
339 | for (group = 0; group < ARRAY_SIZE(tz1090_pdc_groups); ++group) | ||
340 | if (!strcmp(tz1090_pdc_groups[group].name, pin_group)) | ||
341 | return group; | ||
342 | |||
343 | return -EINVAL; | ||
344 | } | ||
345 | |||
346 | static int add_map_configs(struct device *dev, | ||
347 | struct pinctrl_map **map, | ||
348 | unsigned int *reserved_maps, unsigned int *num_maps, | ||
349 | const char *group, unsigned long *configs, | ||
350 | unsigned int num_configs) | ||
351 | { | ||
352 | unsigned long *dup_configs; | ||
353 | enum pinctrl_map_type type; | ||
354 | |||
355 | if (WARN_ON(*num_maps == *reserved_maps)) | ||
356 | return -ENOSPC; | ||
357 | |||
358 | dup_configs = kmemdup(configs, num_configs * sizeof(*dup_configs), | ||
359 | GFP_KERNEL); | ||
360 | if (!dup_configs) { | ||
361 | dev_err(dev, "kmemdup(configs) failed\n"); | ||
362 | return -ENOMEM; | ||
363 | } | ||
364 | |||
365 | /* | ||
366 | * We support both pins and pin groups, but we need to figure out which | ||
367 | * one we have. | ||
368 | */ | ||
369 | if (get_group_selector(group) >= 0) | ||
370 | type = PIN_MAP_TYPE_CONFIGS_GROUP; | ||
371 | else | ||
372 | type = PIN_MAP_TYPE_CONFIGS_PIN; | ||
373 | (*map)[*num_maps].type = type; | ||
374 | (*map)[*num_maps].data.configs.group_or_pin = group; | ||
375 | (*map)[*num_maps].data.configs.configs = dup_configs; | ||
376 | (*map)[*num_maps].data.configs.num_configs = num_configs; | ||
377 | (*num_maps)++; | ||
378 | |||
379 | return 0; | ||
380 | } | ||
381 | |||
382 | static void tz1090_pdc_pinctrl_dt_free_map(struct pinctrl_dev *pctldev, | ||
383 | struct pinctrl_map *map, | ||
384 | unsigned int num_maps) | ||
385 | { | ||
386 | int i; | ||
387 | |||
388 | for (i = 0; i < num_maps; i++) | ||
389 | if (map[i].type == PIN_MAP_TYPE_CONFIGS_GROUP) | ||
390 | kfree(map[i].data.configs.configs); | ||
391 | |||
392 | kfree(map); | ||
393 | } | ||
394 | |||
395 | static int tz1090_pdc_pinctrl_dt_subnode_to_map(struct device *dev, | ||
396 | struct device_node *np, | ||
397 | struct pinctrl_map **map, | ||
398 | unsigned int *reserved_maps, | ||
399 | unsigned int *num_maps) | ||
400 | { | ||
401 | int ret; | ||
402 | const char *function; | ||
403 | unsigned long *configs = NULL; | ||
404 | unsigned int num_configs = 0; | ||
405 | unsigned int reserve; | ||
406 | struct property *prop; | ||
407 | const char *group; | ||
408 | |||
409 | ret = of_property_read_string(np, "tz1090,function", &function); | ||
410 | if (ret < 0) { | ||
411 | /* EINVAL=missing, which is fine since it's optional */ | ||
412 | if (ret != -EINVAL) | ||
413 | dev_err(dev, | ||
414 | "could not parse property function\n"); | ||
415 | function = NULL; | ||
416 | } | ||
417 | |||
418 | ret = pinconf_generic_parse_dt_config(np, &configs, &num_configs); | ||
419 | if (ret) | ||
420 | return ret; | ||
421 | |||
422 | reserve = 0; | ||
423 | if (function != NULL) | ||
424 | reserve++; | ||
425 | if (num_configs) | ||
426 | reserve++; | ||
427 | ret = of_property_count_strings(np, "tz1090,pins"); | ||
428 | if (ret < 0) { | ||
429 | dev_err(dev, "could not parse property pins\n"); | ||
430 | goto exit; | ||
431 | } | ||
432 | reserve *= ret; | ||
433 | |||
434 | ret = reserve_map(dev, map, reserved_maps, num_maps, reserve); | ||
435 | if (ret < 0) | ||
436 | goto exit; | ||
437 | |||
438 | of_property_for_each_string(np, "tz1090,pins", prop, group) { | ||
439 | if (function) { | ||
440 | ret = add_map_mux(map, reserved_maps, num_maps, | ||
441 | group, function); | ||
442 | if (ret < 0) | ||
443 | goto exit; | ||
444 | } | ||
445 | |||
446 | if (num_configs) { | ||
447 | ret = add_map_configs(dev, map, reserved_maps, | ||
448 | num_maps, group, configs, | ||
449 | num_configs); | ||
450 | if (ret < 0) | ||
451 | goto exit; | ||
452 | } | ||
453 | } | ||
454 | |||
455 | ret = 0; | ||
456 | |||
457 | exit: | ||
458 | kfree(configs); | ||
459 | return ret; | ||
460 | } | ||
461 | |||
462 | static int tz1090_pdc_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev, | ||
463 | struct device_node *np_config, | ||
464 | struct pinctrl_map **map, | ||
465 | unsigned int *num_maps) | ||
466 | { | ||
467 | unsigned int reserved_maps; | ||
468 | struct device_node *np; | ||
469 | int ret; | ||
470 | |||
471 | reserved_maps = 0; | ||
472 | *map = NULL; | ||
473 | *num_maps = 0; | ||
474 | |||
475 | for_each_child_of_node(np_config, np) { | ||
476 | ret = tz1090_pdc_pinctrl_dt_subnode_to_map(pctldev->dev, np, | ||
477 | map, &reserved_maps, | ||
478 | num_maps); | ||
479 | if (ret < 0) { | ||
480 | tz1090_pdc_pinctrl_dt_free_map(pctldev, *map, | ||
481 | *num_maps); | ||
482 | return ret; | ||
483 | } | ||
484 | } | ||
485 | |||
486 | return 0; | ||
487 | } | ||
488 | |||
489 | static struct pinctrl_ops tz1090_pdc_pinctrl_ops = { | ||
490 | .get_groups_count = tz1090_pdc_pinctrl_get_groups_count, | ||
491 | .get_group_name = tz1090_pdc_pinctrl_get_group_name, | ||
492 | .get_group_pins = tz1090_pdc_pinctrl_get_group_pins, | ||
493 | #ifdef CONFIG_DEBUG_FS | ||
494 | .pin_dbg_show = tz1090_pdc_pinctrl_pin_dbg_show, | ||
495 | #endif | ||
496 | .dt_node_to_map = tz1090_pdc_pinctrl_dt_node_to_map, | ||
497 | .dt_free_map = tz1090_pdc_pinctrl_dt_free_map, | ||
498 | }; | ||
499 | |||
500 | /* | ||
501 | * Pin mux operations | ||
502 | */ | ||
503 | |||
504 | static int tz1090_pdc_pinctrl_get_funcs_count(struct pinctrl_dev *pctldev) | ||
505 | { | ||
506 | return ARRAY_SIZE(tz1090_pdc_functions); | ||
507 | } | ||
508 | |||
509 | static const char *tz1090_pdc_pinctrl_get_func_name(struct pinctrl_dev *pctldev, | ||
510 | unsigned int function) | ||
511 | { | ||
512 | return tz1090_pdc_functions[function].name; | ||
513 | } | ||
514 | |||
515 | static int tz1090_pdc_pinctrl_get_func_groups(struct pinctrl_dev *pctldev, | ||
516 | unsigned int function, | ||
517 | const char * const **groups, | ||
518 | unsigned int * const num_groups) | ||
519 | { | ||
520 | *groups = tz1090_pdc_functions[function].groups; | ||
521 | *num_groups = tz1090_pdc_functions[function].ngroups; | ||
522 | |||
523 | return 0; | ||
524 | } | ||
525 | |||
526 | /** | ||
527 | * tz1090_pdc_pinctrl_mux() - update mux bit | ||
528 | * @pmx: Pinmux data | ||
529 | * @grp: Pin mux group | ||
530 | */ | ||
531 | static void tz1090_pdc_pinctrl_mux(struct tz1090_pdc_pmx *pmx, | ||
532 | const struct tz1090_pdc_pingroup *grp) | ||
533 | { | ||
534 | u32 reg, select; | ||
535 | unsigned int pin_shift = grp->pins[0]; | ||
536 | unsigned long flags; | ||
537 | |||
538 | /* select = mux && !gpio */ | ||
539 | select = ((pmx->mux_en & ~pmx->gpio_en) >> pin_shift) & 1; | ||
540 | |||
541 | /* set up the mux */ | ||
542 | __global_lock2(flags); | ||
543 | reg = pmx_read(pmx, grp->reg); | ||
544 | reg &= ~BIT(grp->bit); | ||
545 | reg |= select << grp->bit; | ||
546 | pmx_write(pmx, reg, grp->reg); | ||
547 | __global_unlock2(flags); | ||
548 | } | ||
549 | |||
550 | static int tz1090_pdc_pinctrl_enable(struct pinctrl_dev *pctldev, | ||
551 | unsigned int function, unsigned int group) | ||
552 | { | ||
553 | struct tz1090_pdc_pmx *pmx = pinctrl_dev_get_drvdata(pctldev); | ||
554 | const struct tz1090_pdc_pingroup *grp = &tz1090_pdc_groups[group]; | ||
555 | |||
556 | dev_dbg(pctldev->dev, "%s(func=%u (%s), group=%u (%s))\n", | ||
557 | __func__, | ||
558 | function, tz1090_pdc_functions[function].name, | ||
559 | group, tz1090_pdc_groups[group].name); | ||
560 | |||
561 | /* is it even a mux? */ | ||
562 | if (grp->drv) | ||
563 | return -EINVAL; | ||
564 | |||
565 | /* does this group even control the function? */ | ||
566 | if (function != grp->func) | ||
567 | return -EINVAL; | ||
568 | |||
569 | /* record the pin being muxed and update mux bit */ | ||
570 | spin_lock(&pmx->lock); | ||
571 | pmx->mux_en |= BIT(grp->pins[0]); | ||
572 | tz1090_pdc_pinctrl_mux(pmx, grp); | ||
573 | spin_unlock(&pmx->lock); | ||
574 | return 0; | ||
575 | } | ||
576 | |||
577 | static void tz1090_pdc_pinctrl_disable(struct pinctrl_dev *pctldev, | ||
578 | unsigned int function, | ||
579 | unsigned int group) | ||
580 | { | ||
581 | struct tz1090_pdc_pmx *pmx = pinctrl_dev_get_drvdata(pctldev); | ||
582 | const struct tz1090_pdc_pingroup *grp = &tz1090_pdc_groups[group]; | ||
583 | |||
584 | dev_dbg(pctldev->dev, "%s(func=%u (%s), group=%u (%s))\n", | ||
585 | __func__, | ||
586 | function, tz1090_pdc_functions[function].name, | ||
587 | group, tz1090_pdc_groups[group].name); | ||
588 | |||
589 | /* is it even a mux? */ | ||
590 | if (grp->drv) | ||
591 | return; | ||
592 | |||
593 | /* does this group even control the function? */ | ||
594 | if (function != grp->func) | ||
595 | return; | ||
596 | |||
597 | /* record the pin being unmuxed and update mux bit */ | ||
598 | spin_lock(&pmx->lock); | ||
599 | pmx->mux_en &= ~BIT(grp->pins[0]); | ||
600 | tz1090_pdc_pinctrl_mux(pmx, grp); | ||
601 | spin_unlock(&pmx->lock); | ||
602 | } | ||
603 | |||
604 | static const struct tz1090_pdc_pingroup *find_mux_group( | ||
605 | struct tz1090_pdc_pmx *pmx, | ||
606 | unsigned int pin) | ||
607 | { | ||
608 | const struct tz1090_pdc_pingroup *grp; | ||
609 | unsigned int group; | ||
610 | |||
611 | grp = tz1090_pdc_groups; | ||
612 | for (group = 0; group < ARRAY_SIZE(tz1090_pdc_groups); ++group, ++grp) { | ||
613 | /* only match muxes */ | ||
614 | if (grp->drv) | ||
615 | continue; | ||
616 | |||
617 | /* with a matching pin */ | ||
618 | if (grp->pins[0] == pin) | ||
619 | return grp; | ||
620 | } | ||
621 | |||
622 | return NULL; | ||
623 | } | ||
624 | |||
625 | static int tz1090_pdc_pinctrl_gpio_request_enable( | ||
626 | struct pinctrl_dev *pctldev, | ||
627 | struct pinctrl_gpio_range *range, | ||
628 | unsigned int pin) | ||
629 | { | ||
630 | struct tz1090_pdc_pmx *pmx = pinctrl_dev_get_drvdata(pctldev); | ||
631 | const struct tz1090_pdc_pingroup *grp = find_mux_group(pmx, pin); | ||
632 | |||
633 | if (grp) { | ||
634 | /* record the pin in GPIO use and update mux bit */ | ||
635 | spin_lock(&pmx->lock); | ||
636 | pmx->gpio_en |= BIT(pin); | ||
637 | tz1090_pdc_pinctrl_mux(pmx, grp); | ||
638 | spin_unlock(&pmx->lock); | ||
639 | } | ||
640 | return 0; | ||
641 | } | ||
642 | |||
643 | static void tz1090_pdc_pinctrl_gpio_disable_free( | ||
644 | struct pinctrl_dev *pctldev, | ||
645 | struct pinctrl_gpio_range *range, | ||
646 | unsigned int pin) | ||
647 | { | ||
648 | struct tz1090_pdc_pmx *pmx = pinctrl_dev_get_drvdata(pctldev); | ||
649 | const struct tz1090_pdc_pingroup *grp = find_mux_group(pmx, pin); | ||
650 | |||
651 | if (grp) { | ||
652 | /* record the pin not in GPIO use and update mux bit */ | ||
653 | spin_lock(&pmx->lock); | ||
654 | pmx->gpio_en &= ~BIT(pin); | ||
655 | tz1090_pdc_pinctrl_mux(pmx, grp); | ||
656 | spin_unlock(&pmx->lock); | ||
657 | } | ||
658 | } | ||
659 | |||
660 | static struct pinmux_ops tz1090_pdc_pinmux_ops = { | ||
661 | .get_functions_count = tz1090_pdc_pinctrl_get_funcs_count, | ||
662 | .get_function_name = tz1090_pdc_pinctrl_get_func_name, | ||
663 | .get_function_groups = tz1090_pdc_pinctrl_get_func_groups, | ||
664 | .enable = tz1090_pdc_pinctrl_enable, | ||
665 | .disable = tz1090_pdc_pinctrl_disable, | ||
666 | .gpio_request_enable = tz1090_pdc_pinctrl_gpio_request_enable, | ||
667 | .gpio_disable_free = tz1090_pdc_pinctrl_gpio_disable_free, | ||
668 | }; | ||
669 | |||
670 | /* | ||
671 | * Pin config operations | ||
672 | */ | ||
673 | |||
674 | static int tz1090_pdc_pinconf_reg(struct pinctrl_dev *pctldev, | ||
675 | unsigned int pin, | ||
676 | enum pin_config_param param, | ||
677 | bool report_err, | ||
678 | u32 *reg, u32 *width, u32 *mask, u32 *shift, | ||
679 | u32 *val) | ||
680 | { | ||
681 | /* Find information about parameter's register */ | ||
682 | switch (param) { | ||
683 | case PIN_CONFIG_BIAS_DISABLE: | ||
684 | case PIN_CONFIG_BIAS_HIGH_IMPEDANCE: | ||
685 | *val = REG_PU_PD_TRISTATE; | ||
686 | break; | ||
687 | case PIN_CONFIG_BIAS_PULL_UP: | ||
688 | *val = REG_PU_PD_UP; | ||
689 | break; | ||
690 | case PIN_CONFIG_BIAS_PULL_DOWN: | ||
691 | *val = REG_PU_PD_DOWN; | ||
692 | break; | ||
693 | case PIN_CONFIG_BIAS_BUS_HOLD: | ||
694 | *val = REG_PU_PD_REPEATER; | ||
695 | break; | ||
696 | default: | ||
697 | return -ENOTSUPP; | ||
698 | }; | ||
699 | |||
700 | /* Only input bias parameters supported */ | ||
701 | *reg = REG_GPIO_CONTROL2; | ||
702 | *shift = REG_GPIO_CONTROL2_PU_PD_S + pin*2; | ||
703 | *width = 2; | ||
704 | |||
705 | /* Calculate field information */ | ||
706 | *mask = (BIT(*width) - 1) << *shift; | ||
707 | |||
708 | return 0; | ||
709 | } | ||
710 | |||
711 | static int tz1090_pdc_pinconf_get(struct pinctrl_dev *pctldev, | ||
712 | unsigned int pin, unsigned long *config) | ||
713 | { | ||
714 | struct tz1090_pdc_pmx *pmx = pinctrl_dev_get_drvdata(pctldev); | ||
715 | enum pin_config_param param = pinconf_to_config_param(*config); | ||
716 | int ret; | ||
717 | u32 reg, width, mask, shift, val, tmp, arg; | ||
718 | |||
719 | /* Get register information */ | ||
720 | ret = tz1090_pdc_pinconf_reg(pctldev, pin, param, true, | ||
721 | ®, &width, &mask, &shift, &val); | ||
722 | if (ret < 0) | ||
723 | return ret; | ||
724 | |||
725 | /* Extract field from register */ | ||
726 | tmp = pmx_read(pmx, reg); | ||
727 | arg = ((tmp & mask) >> shift) == val; | ||
728 | |||
729 | /* Config not active */ | ||
730 | if (!arg) | ||
731 | return -EINVAL; | ||
732 | |||
733 | /* And pack config */ | ||
734 | *config = pinconf_to_config_packed(param, arg); | ||
735 | |||
736 | return 0; | ||
737 | } | ||
738 | |||
739 | static int tz1090_pdc_pinconf_set(struct pinctrl_dev *pctldev, | ||
740 | unsigned int pin, unsigned long config) | ||
741 | { | ||
742 | struct tz1090_pdc_pmx *pmx = pinctrl_dev_get_drvdata(pctldev); | ||
743 | enum pin_config_param param = pinconf_to_config_param(config); | ||
744 | unsigned int arg = pinconf_to_config_argument(config); | ||
745 | int ret; | ||
746 | u32 reg, width, mask, shift, val, tmp; | ||
747 | unsigned long flags; | ||
748 | |||
749 | dev_dbg(pctldev->dev, "%s(pin=%s, config=%#lx)\n", | ||
750 | __func__, tz1090_pdc_pins[pin].name, config); | ||
751 | |||
752 | /* Get register information */ | ||
753 | ret = tz1090_pdc_pinconf_reg(pctldev, pin, param, true, | ||
754 | ®, &width, &mask, &shift, &val); | ||
755 | if (ret < 0) | ||
756 | return ret; | ||
757 | |||
758 | /* Unpack argument and range check it */ | ||
759 | if (arg > 1) { | ||
760 | dev_dbg(pctldev->dev, "%s: arg %u out of range\n", | ||
761 | __func__, arg); | ||
762 | return -EINVAL; | ||
763 | } | ||
764 | |||
765 | /* Write register field */ | ||
766 | __global_lock2(flags); | ||
767 | tmp = pmx_read(pmx, reg); | ||
768 | tmp &= ~mask; | ||
769 | if (arg) | ||
770 | tmp |= val << shift; | ||
771 | pmx_write(pmx, tmp, reg); | ||
772 | __global_unlock2(flags); | ||
773 | |||
774 | return 0; | ||
775 | } | ||
776 | |||
777 | static const int tz1090_pdc_boolean_map[] = { | ||
778 | [0] = -EINVAL, | ||
779 | [1] = 1, | ||
780 | }; | ||
781 | |||
782 | static const int tz1090_pdc_dr_map[] = { | ||
783 | [REG_DR_2mA] = 2, | ||
784 | [REG_DR_4mA] = 4, | ||
785 | [REG_DR_8mA] = 8, | ||
786 | [REG_DR_12mA] = 12, | ||
787 | }; | ||
788 | |||
789 | static int tz1090_pdc_pinconf_group_reg(struct pinctrl_dev *pctldev, | ||
790 | const struct tz1090_pdc_pingroup *g, | ||
791 | enum pin_config_param param, | ||
792 | bool report_err, u32 *reg, u32 *width, | ||
793 | u32 *mask, u32 *shift, const int **map) | ||
794 | { | ||
795 | /* Drive configuration applies in groups, but not to all groups. */ | ||
796 | if (!g->drv) { | ||
797 | if (report_err) | ||
798 | dev_dbg(pctldev->dev, | ||
799 | "%s: group %s has no drive control\n", | ||
800 | __func__, g->name); | ||
801 | return -ENOTSUPP; | ||
802 | } | ||
803 | |||
804 | /* Find information about drive parameter's register */ | ||
805 | *reg = REG_GPIO_CONTROL2; | ||
806 | switch (param) { | ||
807 | case PIN_CONFIG_INPUT_SCHMITT_ENABLE: | ||
808 | *shift = REG_GPIO_CONTROL2_PDC_SCHMITT_S; | ||
809 | *width = 1; | ||
810 | *map = tz1090_pdc_boolean_map; | ||
811 | break; | ||
812 | case PIN_CONFIG_SLEW_RATE: | ||
813 | *shift = REG_GPIO_CONTROL2_PDC_SR_S; | ||
814 | *width = 1; | ||
815 | *map = tz1090_pdc_boolean_map; | ||
816 | break; | ||
817 | case PIN_CONFIG_DRIVE_STRENGTH: | ||
818 | *shift = REG_GPIO_CONTROL2_PDC_DR_S; | ||
819 | *width = 2; | ||
820 | *map = tz1090_pdc_dr_map; | ||
821 | break; | ||
822 | case PIN_CONFIG_LOW_POWER_MODE: | ||
823 | *shift = REG_GPIO_CONTROL2_PDC_POS_S; | ||
824 | *width = 1; | ||
825 | *map = tz1090_pdc_boolean_map; | ||
826 | break; | ||
827 | default: | ||
828 | return -ENOTSUPP; | ||
829 | }; | ||
830 | |||
831 | /* Calculate field information */ | ||
832 | *mask = (BIT(*width) - 1) << *shift; | ||
833 | |||
834 | return 0; | ||
835 | } | ||
836 | |||
837 | static int tz1090_pdc_pinconf_group_get(struct pinctrl_dev *pctldev, | ||
838 | unsigned int group, | ||
839 | unsigned long *config) | ||
840 | { | ||
841 | struct tz1090_pdc_pmx *pmx = pinctrl_dev_get_drvdata(pctldev); | ||
842 | const struct tz1090_pdc_pingroup *g = &tz1090_pdc_groups[group]; | ||
843 | enum pin_config_param param = pinconf_to_config_param(*config); | ||
844 | int ret, arg; | ||
845 | u32 reg, width, mask, shift, val; | ||
846 | const int *map; | ||
847 | |||
848 | /* Get register information */ | ||
849 | ret = tz1090_pdc_pinconf_group_reg(pctldev, g, param, true, | ||
850 | ®, &width, &mask, &shift, &map); | ||
851 | if (ret < 0) | ||
852 | return ret; | ||
853 | |||
854 | /* Extract field from register */ | ||
855 | val = pmx_read(pmx, reg); | ||
856 | arg = map[(val & mask) >> shift]; | ||
857 | if (arg < 0) | ||
858 | return arg; | ||
859 | |||
860 | /* And pack config */ | ||
861 | *config = pinconf_to_config_packed(param, arg); | ||
862 | |||
863 | return 0; | ||
864 | } | ||
865 | |||
866 | static int tz1090_pdc_pinconf_group_set(struct pinctrl_dev *pctldev, | ||
867 | unsigned int group, | ||
868 | unsigned long config) | ||
869 | { | ||
870 | struct tz1090_pdc_pmx *pmx = pinctrl_dev_get_drvdata(pctldev); | ||
871 | const struct tz1090_pdc_pingroup *g = &tz1090_pdc_groups[group]; | ||
872 | enum pin_config_param param = pinconf_to_config_param(config); | ||
873 | const unsigned int *pit; | ||
874 | unsigned int i; | ||
875 | int ret, arg; | ||
876 | u32 reg, width, mask, shift, val; | ||
877 | unsigned long flags; | ||
878 | const int *map; | ||
879 | |||
880 | dev_dbg(pctldev->dev, "%s(group=%s, config=%#lx)\n", | ||
881 | __func__, g->name, config); | ||
882 | |||
883 | /* Get register information */ | ||
884 | ret = tz1090_pdc_pinconf_group_reg(pctldev, g, param, true, | ||
885 | ®, &width, &mask, &shift, &map); | ||
886 | if (ret < 0) { | ||
887 | /* | ||
888 | * Maybe we're trying to set a per-pin configuration of a group, | ||
889 | * so do the pins one by one. This is mainly as a convenience. | ||
890 | */ | ||
891 | for (i = 0, pit = g->pins; i < g->npins; ++i, ++pit) { | ||
892 | ret = tz1090_pdc_pinconf_set(pctldev, *pit, config); | ||
893 | if (ret) | ||
894 | return ret; | ||
895 | } | ||
896 | return 0; | ||
897 | } | ||
898 | |||
899 | /* Unpack argument and map it to register value */ | ||
900 | arg = pinconf_to_config_argument(config); | ||
901 | for (i = 0; i < BIT(width); ++i) { | ||
902 | if (map[i] == arg || (map[i] == -EINVAL && !arg)) { | ||
903 | /* Write register field */ | ||
904 | __global_lock2(flags); | ||
905 | val = pmx_read(pmx, reg); | ||
906 | val &= ~mask; | ||
907 | val |= i << shift; | ||
908 | pmx_write(pmx, val, reg); | ||
909 | __global_unlock2(flags); | ||
910 | return 0; | ||
911 | } | ||
912 | } | ||
913 | |||
914 | dev_dbg(pctldev->dev, "%s: arg %u not supported\n", | ||
915 | __func__, arg); | ||
916 | return 0; | ||
917 | } | ||
918 | |||
919 | static struct pinconf_ops tz1090_pdc_pinconf_ops = { | ||
920 | .is_generic = true, | ||
921 | .pin_config_get = tz1090_pdc_pinconf_get, | ||
922 | .pin_config_set = tz1090_pdc_pinconf_set, | ||
923 | .pin_config_group_get = tz1090_pdc_pinconf_group_get, | ||
924 | .pin_config_group_set = tz1090_pdc_pinconf_group_set, | ||
925 | .pin_config_config_dbg_show = pinconf_generic_dump_config, | ||
926 | }; | ||
927 | |||
928 | /* | ||
929 | * Pin control driver setup | ||
930 | */ | ||
931 | |||
932 | static struct pinctrl_desc tz1090_pdc_pinctrl_desc = { | ||
933 | .pctlops = &tz1090_pdc_pinctrl_ops, | ||
934 | .pmxops = &tz1090_pdc_pinmux_ops, | ||
935 | .confops = &tz1090_pdc_pinconf_ops, | ||
936 | .owner = THIS_MODULE, | ||
937 | }; | ||
938 | |||
939 | static int tz1090_pdc_pinctrl_probe(struct platform_device *pdev) | ||
940 | { | ||
941 | struct tz1090_pdc_pmx *pmx; | ||
942 | struct resource *res; | ||
943 | |||
944 | pmx = devm_kzalloc(&pdev->dev, sizeof(*pmx), GFP_KERNEL); | ||
945 | if (!pmx) { | ||
946 | dev_err(&pdev->dev, "Can't alloc tz1090_pdc_pmx\n"); | ||
947 | return -ENOMEM; | ||
948 | } | ||
949 | pmx->dev = &pdev->dev; | ||
950 | spin_lock_init(&pmx->lock); | ||
951 | |||
952 | tz1090_pdc_pinctrl_desc.name = dev_name(&pdev->dev); | ||
953 | tz1090_pdc_pinctrl_desc.pins = tz1090_pdc_pins; | ||
954 | tz1090_pdc_pinctrl_desc.npins = ARRAY_SIZE(tz1090_pdc_pins); | ||
955 | |||
956 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
957 | if (!res) { | ||
958 | dev_err(&pdev->dev, "Missing MEM resource\n"); | ||
959 | return -ENODEV; | ||
960 | } | ||
961 | |||
962 | if (!devm_request_mem_region(&pdev->dev, res->start, | ||
963 | resource_size(res), | ||
964 | dev_name(&pdev->dev))) { | ||
965 | dev_err(&pdev->dev, | ||
966 | "Couldn't request MEM resource\n"); | ||
967 | return -ENODEV; | ||
968 | } | ||
969 | |||
970 | pmx->regs = devm_ioremap(&pdev->dev, res->start, | ||
971 | resource_size(res)); | ||
972 | if (!pmx->regs) { | ||
973 | dev_err(&pdev->dev, "Couldn't ioremap regs\n"); | ||
974 | return -ENODEV; | ||
975 | } | ||
976 | |||
977 | pmx->pctl = pinctrl_register(&tz1090_pdc_pinctrl_desc, &pdev->dev, pmx); | ||
978 | if (!pmx->pctl) { | ||
979 | dev_err(&pdev->dev, "Couldn't register pinctrl driver\n"); | ||
980 | return -ENODEV; | ||
981 | } | ||
982 | |||
983 | platform_set_drvdata(pdev, pmx); | ||
984 | |||
985 | dev_info(&pdev->dev, "TZ1090 PDC pinctrl driver initialised\n"); | ||
986 | |||
987 | return 0; | ||
988 | } | ||
989 | |||
990 | static int tz1090_pdc_pinctrl_remove(struct platform_device *pdev) | ||
991 | { | ||
992 | struct tz1090_pdc_pmx *pmx = platform_get_drvdata(pdev); | ||
993 | |||
994 | pinctrl_unregister(pmx->pctl); | ||
995 | |||
996 | return 0; | ||
997 | } | ||
998 | |||
999 | static struct of_device_id tz1090_pdc_pinctrl_of_match[] = { | ||
1000 | { .compatible = "img,tz1090-pdc-pinctrl", }, | ||
1001 | { }, | ||
1002 | }; | ||
1003 | |||
1004 | static struct platform_driver tz1090_pdc_pinctrl_driver = { | ||
1005 | .driver = { | ||
1006 | .name = "tz1090-pdc-pinctrl", | ||
1007 | .owner = THIS_MODULE, | ||
1008 | .of_match_table = tz1090_pdc_pinctrl_of_match, | ||
1009 | }, | ||
1010 | .probe = tz1090_pdc_pinctrl_probe, | ||
1011 | .remove = tz1090_pdc_pinctrl_remove, | ||
1012 | }; | ||
1013 | |||
1014 | static int __init tz1090_pdc_pinctrl_init(void) | ||
1015 | { | ||
1016 | return platform_driver_register(&tz1090_pdc_pinctrl_driver); | ||
1017 | } | ||
1018 | arch_initcall(tz1090_pdc_pinctrl_init); | ||
1019 | |||
1020 | static void __exit tz1090_pdc_pinctrl_exit(void) | ||
1021 | { | ||
1022 | platform_driver_unregister(&tz1090_pdc_pinctrl_driver); | ||
1023 | } | ||
1024 | module_exit(tz1090_pdc_pinctrl_exit); | ||
1025 | |||
1026 | MODULE_AUTHOR("Imagination Technologies Ltd."); | ||
1027 | MODULE_DESCRIPTION("Toumaz Xenif TZ1090 PDC pinctrl driver"); | ||
1028 | MODULE_LICENSE("GPL v2"); | ||
1029 | MODULE_DEVICE_TABLE(of, tz1090_pdc_pinctrl_of_match); | ||