1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * Pinmux & pinconf driver for the IP block found in the Nomadik SoC. This |
4 | * depends on gpio-nomadik and some handling is intertwined; see nmk_gpio_chips |
5 | * which is used by this driver to access the GPIO banks array. |
6 | * |
7 | * Copyright (C) 2008,2009 STMicroelectronics |
8 | * Copyright (C) 2009 Alessandro Rubini <rubini@unipv.it> |
9 | * Rewritten based on work by Prafulla WADASKAR <prafulla.wadaskar@st.com> |
10 | * Copyright (C) 2011-2013 Linus Walleij <linus.walleij@linaro.org> |
11 | */ |
12 | |
13 | #include <linux/bitops.h> |
14 | #include <linux/cleanup.h> |
15 | #include <linux/clk.h> |
16 | #include <linux/device.h> |
17 | #include <linux/err.h> |
18 | #include <linux/gpio/driver.h> |
19 | #include <linux/init.h> |
20 | #include <linux/interrupt.h> |
21 | #include <linux/io.h> |
22 | #include <linux/kernel.h> |
23 | #include <linux/of.h> |
24 | #include <linux/of_address.h> |
25 | #include <linux/of_platform.h> |
26 | #include <linux/platform_device.h> |
27 | #include <linux/property.h> |
28 | #include <linux/seq_file.h> |
29 | #include <linux/slab.h> |
30 | #include <linux/spinlock.h> |
31 | #include <linux/types.h> |
32 | |
33 | /* Since we request GPIOs from ourself */ |
34 | #include <linux/pinctrl/consumer.h> |
35 | #include <linux/pinctrl/machine.h> |
36 | #include <linux/pinctrl/pinconf.h> |
37 | #include <linux/pinctrl/pinctrl.h> |
38 | #include <linux/pinctrl/pinmux.h> |
39 | |
40 | #include "../core.h" |
41 | #include "../pinctrl-utils.h" |
42 | |
43 | #include <linux/gpio/gpio-nomadik.h> |
44 | |
45 | /* |
46 | * pin configurations are represented by 32-bit integers: |
47 | * |
48 | * bit 0.. 8 - Pin Number (512 Pins Maximum) |
49 | * bit 9..10 - Alternate Function Selection |
50 | * bit 11..12 - Pull up/down state |
51 | * bit 13 - Sleep mode behaviour |
52 | * bit 14 - Direction |
53 | * bit 15 - Value (if output) |
54 | * bit 16..18 - SLPM pull up/down state |
55 | * bit 19..20 - SLPM direction |
56 | * bit 21..22 - SLPM Value (if output) |
57 | * bit 23..25 - PDIS value (if input) |
58 | * bit 26 - Gpio mode |
59 | * bit 27 - Sleep mode |
60 | * |
61 | * to facilitate the definition, the following macros are provided |
62 | * |
63 | * PIN_CFG_DEFAULT - default config (0): |
64 | * pull up/down = disabled |
65 | * sleep mode = input/wakeup |
66 | * direction = input |
67 | * value = low |
68 | * SLPM direction = same as normal |
69 | * SLPM pull = same as normal |
70 | * SLPM value = same as normal |
71 | * |
72 | * PIN_CFG - default config with alternate function |
73 | */ |
74 | |
75 | #define PIN_NUM_MASK 0x1ff |
76 | #define PIN_NUM(x) ((x) & PIN_NUM_MASK) |
77 | |
78 | #define PIN_ALT_SHIFT 9 |
79 | #define PIN_ALT_MASK (0x3 << PIN_ALT_SHIFT) |
80 | #define PIN_ALT(x) (((x) & PIN_ALT_MASK) >> PIN_ALT_SHIFT) |
81 | #define PIN_GPIO (NMK_GPIO_ALT_GPIO << PIN_ALT_SHIFT) |
82 | #define PIN_ALT_A (NMK_GPIO_ALT_A << PIN_ALT_SHIFT) |
83 | #define PIN_ALT_B (NMK_GPIO_ALT_B << PIN_ALT_SHIFT) |
84 | #define PIN_ALT_C (NMK_GPIO_ALT_C << PIN_ALT_SHIFT) |
85 | |
86 | #define PIN_PULL_SHIFT 11 |
87 | #define PIN_PULL_MASK (0x3 << PIN_PULL_SHIFT) |
88 | #define PIN_PULL(x) (((x) & PIN_PULL_MASK) >> PIN_PULL_SHIFT) |
89 | #define PIN_PULL_NONE (NMK_GPIO_PULL_NONE << PIN_PULL_SHIFT) |
90 | #define PIN_PULL_UP (NMK_GPIO_PULL_UP << PIN_PULL_SHIFT) |
91 | #define PIN_PULL_DOWN (NMK_GPIO_PULL_DOWN << PIN_PULL_SHIFT) |
92 | |
93 | #define PIN_SLPM_SHIFT 13 |
94 | #define PIN_SLPM_MASK (0x1 << PIN_SLPM_SHIFT) |
95 | #define PIN_SLPM(x) (((x) & PIN_SLPM_MASK) >> PIN_SLPM_SHIFT) |
96 | #define PIN_SLPM_MAKE_INPUT (NMK_GPIO_SLPM_INPUT << PIN_SLPM_SHIFT) |
97 | #define PIN_SLPM_NOCHANGE (NMK_GPIO_SLPM_NOCHANGE << PIN_SLPM_SHIFT) |
98 | /* These two replace the above in DB8500v2+ */ |
99 | #define PIN_SLPM_WAKEUP_ENABLE (NMK_GPIO_SLPM_WAKEUP_ENABLE << PIN_SLPM_SHIFT) |
100 | #define PIN_SLPM_WAKEUP_DISABLE (NMK_GPIO_SLPM_WAKEUP_DISABLE << PIN_SLPM_SHIFT) |
101 | #define PIN_SLPM_USE_MUX_SETTINGS_IN_SLEEP PIN_SLPM_WAKEUP_DISABLE |
102 | |
103 | #define PIN_SLPM_GPIO PIN_SLPM_WAKEUP_ENABLE /* In SLPM, pin is a gpio */ |
104 | #define PIN_SLPM_ALTFUNC PIN_SLPM_WAKEUP_DISABLE /* In SLPM, pin is altfunc */ |
105 | |
106 | #define PIN_DIR_SHIFT 14 |
107 | #define PIN_DIR_MASK (0x1 << PIN_DIR_SHIFT) |
108 | #define PIN_DIR(x) (((x) & PIN_DIR_MASK) >> PIN_DIR_SHIFT) |
109 | #define PIN_DIR_INPUT (0 << PIN_DIR_SHIFT) |
110 | #define PIN_DIR_OUTPUT (1 << PIN_DIR_SHIFT) |
111 | |
112 | #define PIN_VAL_SHIFT 15 |
113 | #define PIN_VAL_MASK (0x1 << PIN_VAL_SHIFT) |
114 | #define PIN_VAL(x) (((x) & PIN_VAL_MASK) >> PIN_VAL_SHIFT) |
115 | #define PIN_VAL_LOW (0 << PIN_VAL_SHIFT) |
116 | #define PIN_VAL_HIGH (1 << PIN_VAL_SHIFT) |
117 | |
118 | #define PIN_SLPM_PULL_SHIFT 16 |
119 | #define PIN_SLPM_PULL_MASK (0x7 << PIN_SLPM_PULL_SHIFT) |
120 | #define PIN_SLPM_PULL(x) \ |
121 | (((x) & PIN_SLPM_PULL_MASK) >> PIN_SLPM_PULL_SHIFT) |
122 | #define PIN_SLPM_PULL_NONE \ |
123 | ((1 + NMK_GPIO_PULL_NONE) << PIN_SLPM_PULL_SHIFT) |
124 | #define PIN_SLPM_PULL_UP \ |
125 | ((1 + NMK_GPIO_PULL_UP) << PIN_SLPM_PULL_SHIFT) |
126 | #define PIN_SLPM_PULL_DOWN \ |
127 | ((1 + NMK_GPIO_PULL_DOWN) << PIN_SLPM_PULL_SHIFT) |
128 | |
129 | #define PIN_SLPM_DIR_SHIFT 19 |
130 | #define PIN_SLPM_DIR_MASK (0x3 << PIN_SLPM_DIR_SHIFT) |
131 | #define PIN_SLPM_DIR(x) \ |
132 | (((x) & PIN_SLPM_DIR_MASK) >> PIN_SLPM_DIR_SHIFT) |
133 | #define PIN_SLPM_DIR_INPUT ((1 + 0) << PIN_SLPM_DIR_SHIFT) |
134 | #define PIN_SLPM_DIR_OUTPUT ((1 + 1) << PIN_SLPM_DIR_SHIFT) |
135 | |
136 | #define PIN_SLPM_VAL_SHIFT 21 |
137 | #define PIN_SLPM_VAL_MASK (0x3 << PIN_SLPM_VAL_SHIFT) |
138 | #define PIN_SLPM_VAL(x) \ |
139 | (((x) & PIN_SLPM_VAL_MASK) >> PIN_SLPM_VAL_SHIFT) |
140 | #define PIN_SLPM_VAL_LOW ((1 + 0) << PIN_SLPM_VAL_SHIFT) |
141 | #define PIN_SLPM_VAL_HIGH ((1 + 1) << PIN_SLPM_VAL_SHIFT) |
142 | |
143 | #define PIN_SLPM_PDIS_SHIFT 23 |
144 | #define PIN_SLPM_PDIS_MASK (0x3 << PIN_SLPM_PDIS_SHIFT) |
145 | #define PIN_SLPM_PDIS(x) \ |
146 | (((x) & PIN_SLPM_PDIS_MASK) >> PIN_SLPM_PDIS_SHIFT) |
147 | #define PIN_SLPM_PDIS_NO_CHANGE (0 << PIN_SLPM_PDIS_SHIFT) |
148 | #define PIN_SLPM_PDIS_DISABLED (1 << PIN_SLPM_PDIS_SHIFT) |
149 | #define PIN_SLPM_PDIS_ENABLED (2 << PIN_SLPM_PDIS_SHIFT) |
150 | |
151 | #define PIN_LOWEMI_SHIFT 25 |
152 | #define PIN_LOWEMI_MASK (0x1 << PIN_LOWEMI_SHIFT) |
153 | #define PIN_LOWEMI(x) (((x) & PIN_LOWEMI_MASK) >> PIN_LOWEMI_SHIFT) |
154 | #define PIN_LOWEMI_DISABLED (0 << PIN_LOWEMI_SHIFT) |
155 | #define PIN_LOWEMI_ENABLED (1 << PIN_LOWEMI_SHIFT) |
156 | |
157 | #define PIN_GPIOMODE_SHIFT 26 |
158 | #define PIN_GPIOMODE_MASK (0x1 << PIN_GPIOMODE_SHIFT) |
159 | #define PIN_GPIOMODE(x) (((x) & PIN_GPIOMODE_MASK) >> PIN_GPIOMODE_SHIFT) |
160 | #define PIN_GPIOMODE_DISABLED (0 << PIN_GPIOMODE_SHIFT) |
161 | #define PIN_GPIOMODE_ENABLED (1 << PIN_GPIOMODE_SHIFT) |
162 | |
163 | #define PIN_SLEEPMODE_SHIFT 27 |
164 | #define PIN_SLEEPMODE_MASK (0x1 << PIN_SLEEPMODE_SHIFT) |
165 | #define PIN_SLEEPMODE(x) (((x) & PIN_SLEEPMODE_MASK) >> PIN_SLEEPMODE_SHIFT) |
166 | #define PIN_SLEEPMODE_DISABLED (0 << PIN_SLEEPMODE_SHIFT) |
167 | #define PIN_SLEEPMODE_ENABLED (1 << PIN_SLEEPMODE_SHIFT) |
168 | |
169 | /* Shortcuts. Use these instead of separate DIR, PULL, and VAL. */ |
170 | #define PIN_INPUT_PULLDOWN (PIN_DIR_INPUT | PIN_PULL_DOWN) |
171 | #define PIN_INPUT_PULLUP (PIN_DIR_INPUT | PIN_PULL_UP) |
172 | #define PIN_INPUT_NOPULL (PIN_DIR_INPUT | PIN_PULL_NONE) |
173 | #define PIN_OUTPUT_LOW (PIN_DIR_OUTPUT | PIN_VAL_LOW) |
174 | #define PIN_OUTPUT_HIGH (PIN_DIR_OUTPUT | PIN_VAL_HIGH) |
175 | |
176 | #define PIN_SLPM_INPUT_PULLDOWN (PIN_SLPM_DIR_INPUT | PIN_SLPM_PULL_DOWN) |
177 | #define PIN_SLPM_INPUT_PULLUP (PIN_SLPM_DIR_INPUT | PIN_SLPM_PULL_UP) |
178 | #define PIN_SLPM_INPUT_NOPULL (PIN_SLPM_DIR_INPUT | PIN_SLPM_PULL_NONE) |
179 | #define PIN_SLPM_OUTPUT_LOW (PIN_SLPM_DIR_OUTPUT | PIN_SLPM_VAL_LOW) |
180 | #define PIN_SLPM_OUTPUT_HIGH (PIN_SLPM_DIR_OUTPUT | PIN_SLPM_VAL_HIGH) |
181 | |
182 | #define PIN_CFG_DEFAULT (0) |
183 | |
184 | #define PIN_CFG(num, alt) \ |
185 | (PIN_CFG_DEFAULT |\ |
186 | (PIN_NUM(num) | PIN_##alt)) |
187 | |
188 | #define PIN_CFG_INPUT(num, alt, pull) \ |
189 | (PIN_CFG_DEFAULT |\ |
190 | (PIN_NUM(num) | PIN_##alt | PIN_INPUT_##pull)) |
191 | |
192 | #define PIN_CFG_OUTPUT(num, alt, val) \ |
193 | (PIN_CFG_DEFAULT |\ |
194 | (PIN_NUM(num) | PIN_##alt | PIN_OUTPUT_##val)) |
195 | |
196 | /** |
197 | * struct nmk_pinctrl - state container for the Nomadik pin controller |
198 | * @dev: containing device pointer |
199 | * @pctl: corresponding pin controller device |
200 | * @soc: SoC data for this specific chip |
201 | * @prcm_base: PRCM register range virtual base |
202 | */ |
203 | struct nmk_pinctrl { |
204 | struct device *dev; |
205 | struct pinctrl_dev *pctl; |
206 | const struct nmk_pinctrl_soc_data *soc; |
207 | void __iomem *prcm_base; |
208 | }; |
209 | |
210 | /* See nmk_gpio_populate_chip() that fills this array. */ |
211 | struct nmk_gpio_chip *nmk_gpio_chips[NMK_MAX_BANKS]; |
212 | |
213 | DEFINE_SPINLOCK(nmk_gpio_slpm_lock); |
214 | |
215 | static void __nmk_gpio_set_mode(struct nmk_gpio_chip *nmk_chip, |
216 | unsigned int offset, int gpio_mode) |
217 | { |
218 | u32 afunc, bfunc; |
219 | |
220 | afunc = readl(addr: nmk_chip->addr + NMK_GPIO_AFSLA) & ~BIT(offset); |
221 | bfunc = readl(addr: nmk_chip->addr + NMK_GPIO_AFSLB) & ~BIT(offset); |
222 | if (gpio_mode & NMK_GPIO_ALT_A) |
223 | afunc |= BIT(offset); |
224 | if (gpio_mode & NMK_GPIO_ALT_B) |
225 | bfunc |= BIT(offset); |
226 | writel(val: afunc, addr: nmk_chip->addr + NMK_GPIO_AFSLA); |
227 | writel(val: bfunc, addr: nmk_chip->addr + NMK_GPIO_AFSLB); |
228 | } |
229 | |
230 | static void __nmk_gpio_set_pull(struct nmk_gpio_chip *nmk_chip, |
231 | unsigned int offset, enum nmk_gpio_pull pull) |
232 | { |
233 | u32 pdis; |
234 | |
235 | pdis = readl(addr: nmk_chip->addr + NMK_GPIO_PDIS); |
236 | if (pull == NMK_GPIO_PULL_NONE) { |
237 | pdis |= BIT(offset); |
238 | nmk_chip->pull_up &= ~BIT(offset); |
239 | } else { |
240 | pdis &= ~BIT(offset); |
241 | } |
242 | |
243 | writel(val: pdis, addr: nmk_chip->addr + NMK_GPIO_PDIS); |
244 | |
245 | if (pull == NMK_GPIO_PULL_UP) { |
246 | nmk_chip->pull_up |= BIT(offset); |
247 | writel(BIT(offset), addr: nmk_chip->addr + NMK_GPIO_DATS); |
248 | } else if (pull == NMK_GPIO_PULL_DOWN) { |
249 | nmk_chip->pull_up &= ~BIT(offset); |
250 | writel(BIT(offset), addr: nmk_chip->addr + NMK_GPIO_DATC); |
251 | } |
252 | } |
253 | |
254 | static void __nmk_gpio_set_lowemi(struct nmk_gpio_chip *nmk_chip, |
255 | unsigned int offset, bool lowemi) |
256 | { |
257 | bool enabled = nmk_chip->lowemi & BIT(offset); |
258 | |
259 | if (lowemi == enabled) |
260 | return; |
261 | |
262 | if (lowemi) |
263 | nmk_chip->lowemi |= BIT(offset); |
264 | else |
265 | nmk_chip->lowemi &= ~BIT(offset); |
266 | |
267 | writel_relaxed(nmk_chip->lowemi, |
268 | nmk_chip->addr + NMK_GPIO_LOWEMI); |
269 | } |
270 | |
271 | static void __nmk_gpio_make_input(struct nmk_gpio_chip *nmk_chip, |
272 | unsigned int offset) |
273 | { |
274 | writel(BIT(offset), addr: nmk_chip->addr + NMK_GPIO_DIRC); |
275 | } |
276 | |
277 | static void __nmk_gpio_set_mode_safe(struct nmk_gpio_chip *nmk_chip, |
278 | unsigned int offset, int gpio_mode, |
279 | bool glitch) |
280 | { |
281 | u32 rwimsc = nmk_chip->rwimsc; |
282 | u32 fwimsc = nmk_chip->fwimsc; |
283 | |
284 | if (glitch && nmk_chip->set_ioforce) { |
285 | u32 bit = BIT(offset); |
286 | |
287 | /* Prevent spurious wakeups */ |
288 | writel(val: rwimsc & ~bit, addr: nmk_chip->addr + NMK_GPIO_RWIMSC); |
289 | writel(val: fwimsc & ~bit, addr: nmk_chip->addr + NMK_GPIO_FWIMSC); |
290 | |
291 | nmk_chip->set_ioforce(true); |
292 | } |
293 | |
294 | __nmk_gpio_set_mode(nmk_chip, offset, gpio_mode); |
295 | |
296 | if (glitch && nmk_chip->set_ioforce) { |
297 | nmk_chip->set_ioforce(false); |
298 | |
299 | writel(val: rwimsc, addr: nmk_chip->addr + NMK_GPIO_RWIMSC); |
300 | writel(val: fwimsc, addr: nmk_chip->addr + NMK_GPIO_FWIMSC); |
301 | } |
302 | } |
303 | |
304 | static void |
305 | nmk_gpio_disable_lazy_irq(struct nmk_gpio_chip *nmk_chip, unsigned int offset) |
306 | { |
307 | u32 falling = nmk_chip->fimsc & BIT(offset); |
308 | u32 rising = nmk_chip->rimsc & BIT(offset); |
309 | int gpio = nmk_chip->chip.base + offset; |
310 | int irq = irq_find_mapping(domain: nmk_chip->chip.irq.domain, hwirq: offset); |
311 | struct irq_data *d = irq_get_irq_data(irq); |
312 | |
313 | if (!rising && !falling) |
314 | return; |
315 | |
316 | if (!d || !irqd_irq_disabled(d)) |
317 | return; |
318 | |
319 | if (rising) { |
320 | nmk_chip->rimsc &= ~BIT(offset); |
321 | writel_relaxed(nmk_chip->rimsc, |
322 | nmk_chip->addr + NMK_GPIO_RIMSC); |
323 | } |
324 | |
325 | if (falling) { |
326 | nmk_chip->fimsc &= ~BIT(offset); |
327 | writel_relaxed(nmk_chip->fimsc, |
328 | nmk_chip->addr + NMK_GPIO_FIMSC); |
329 | } |
330 | |
331 | dev_dbg(nmk_chip->chip.parent, "%d: clearing interrupt mask\n" , gpio); |
332 | } |
333 | |
334 | static void nmk_write_masked(void __iomem *reg, u32 mask, u32 value) |
335 | { |
336 | u32 val; |
337 | |
338 | val = readl(addr: reg); |
339 | val = ((val & ~mask) | (value & mask)); |
340 | writel(val, addr: reg); |
341 | } |
342 | |
343 | static void nmk_prcm_altcx_set_mode(struct nmk_pinctrl *npct, |
344 | unsigned int offset, unsigned int alt_num) |
345 | { |
346 | int i; |
347 | u16 reg; |
348 | u8 bit; |
349 | u8 alt_index; |
350 | const struct prcm_gpiocr_altcx_pin_desc *pin_desc; |
351 | const u16 *gpiocr_regs; |
352 | |
353 | if (!npct->prcm_base) |
354 | return; |
355 | |
356 | if (alt_num > PRCM_IDX_GPIOCR_ALTC_MAX) { |
357 | dev_err(npct->dev, "PRCM GPIOCR: alternate-C%i is invalid\n" , |
358 | alt_num); |
359 | return; |
360 | } |
361 | |
362 | for (i = 0 ; i < npct->soc->npins_altcx ; i++) { |
363 | if (npct->soc->altcx_pins[i].pin == offset) |
364 | break; |
365 | } |
366 | if (i == npct->soc->npins_altcx) { |
367 | dev_dbg(npct->dev, "PRCM GPIOCR: pin %i is not found\n" , |
368 | offset); |
369 | return; |
370 | } |
371 | |
372 | pin_desc = npct->soc->altcx_pins + i; |
373 | gpiocr_regs = npct->soc->prcm_gpiocr_registers; |
374 | |
375 | /* |
376 | * If alt_num is NULL, just clear current ALTCx selection |
377 | * to make sure we come back to a pure ALTC selection |
378 | */ |
379 | if (!alt_num) { |
380 | for (i = 0 ; i < PRCM_IDX_GPIOCR_ALTC_MAX ; i++) { |
381 | if (pin_desc->altcx[i].used) { |
382 | reg = gpiocr_regs[pin_desc->altcx[i].reg_index]; |
383 | bit = pin_desc->altcx[i].control_bit; |
384 | if (readl(addr: npct->prcm_base + reg) & BIT(bit)) { |
385 | nmk_write_masked(reg: npct->prcm_base + reg, BIT(bit), value: 0); |
386 | dev_dbg(npct->dev, |
387 | "PRCM GPIOCR: pin %i: alternate-C%i has been disabled\n" , |
388 | offset, i + 1); |
389 | } |
390 | } |
391 | } |
392 | return; |
393 | } |
394 | |
395 | alt_index = alt_num - 1; |
396 | if (!pin_desc->altcx[alt_index].used) { |
397 | dev_warn(npct->dev, |
398 | "PRCM GPIOCR: pin %i: alternate-C%i does not exist\n" , |
399 | offset, alt_num); |
400 | return; |
401 | } |
402 | |
403 | /* |
404 | * Check if any other ALTCx functions are activated on this pin |
405 | * and disable it first. |
406 | */ |
407 | for (i = 0 ; i < PRCM_IDX_GPIOCR_ALTC_MAX ; i++) { |
408 | if (i == alt_index) |
409 | continue; |
410 | if (pin_desc->altcx[i].used) { |
411 | reg = gpiocr_regs[pin_desc->altcx[i].reg_index]; |
412 | bit = pin_desc->altcx[i].control_bit; |
413 | if (readl(addr: npct->prcm_base + reg) & BIT(bit)) { |
414 | nmk_write_masked(reg: npct->prcm_base + reg, BIT(bit), value: 0); |
415 | dev_dbg(npct->dev, |
416 | "PRCM GPIOCR: pin %i: alternate-C%i has been disabled\n" , |
417 | offset, i + 1); |
418 | } |
419 | } |
420 | } |
421 | |
422 | reg = gpiocr_regs[pin_desc->altcx[alt_index].reg_index]; |
423 | bit = pin_desc->altcx[alt_index].control_bit; |
424 | dev_dbg(npct->dev, "PRCM GPIOCR: pin %i: alternate-C%i has been selected\n" , |
425 | offset, alt_index + 1); |
426 | nmk_write_masked(reg: npct->prcm_base + reg, BIT(bit), BIT(bit)); |
427 | } |
428 | |
429 | /* |
430 | * Safe sequence used to switch IOs between GPIO and Alternate-C mode: |
431 | * - Save SLPM registers |
432 | * - Set SLPM=0 for the IOs you want to switch and others to 1 |
433 | * - Configure the GPIO registers for the IOs that are being switched |
434 | * - Set IOFORCE=1 |
435 | * - Modify the AFLSA/B registers for the IOs that are being switched |
436 | * - Set IOFORCE=0 |
437 | * - Restore SLPM registers |
438 | * - Any spurious wake up event during switch sequence to be ignored and |
439 | * cleared |
440 | */ |
441 | static void nmk_gpio_glitch_slpm_init(unsigned int *slpm) |
442 | { |
443 | int i; |
444 | |
445 | for (i = 0; i < NMK_MAX_BANKS; i++) { |
446 | struct nmk_gpio_chip *chip = nmk_gpio_chips[i]; |
447 | unsigned int temp = slpm[i]; |
448 | |
449 | if (!chip) |
450 | break; |
451 | |
452 | clk_enable(clk: chip->clk); |
453 | |
454 | slpm[i] = readl(addr: chip->addr + NMK_GPIO_SLPC); |
455 | writel(val: temp, addr: chip->addr + NMK_GPIO_SLPC); |
456 | } |
457 | } |
458 | |
459 | static void nmk_gpio_glitch_slpm_restore(unsigned int *slpm) |
460 | { |
461 | int i; |
462 | |
463 | for (i = 0; i < NMK_MAX_BANKS; i++) { |
464 | struct nmk_gpio_chip *chip = nmk_gpio_chips[i]; |
465 | |
466 | if (!chip) |
467 | break; |
468 | |
469 | writel(val: slpm[i], addr: chip->addr + NMK_GPIO_SLPC); |
470 | |
471 | clk_disable(clk: chip->clk); |
472 | } |
473 | } |
474 | |
475 | /* Only called by gpio-nomadik but requires knowledge of struct nmk_pinctrl. */ |
476 | int __maybe_unused nmk_prcm_gpiocr_get_mode(struct pinctrl_dev *pctldev, int gpio) |
477 | { |
478 | int i; |
479 | u16 reg; |
480 | u8 bit; |
481 | struct nmk_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev); |
482 | const struct prcm_gpiocr_altcx_pin_desc *pin_desc; |
483 | const u16 *gpiocr_regs; |
484 | |
485 | if (!npct->prcm_base) |
486 | return NMK_GPIO_ALT_C; |
487 | |
488 | for (i = 0; i < npct->soc->npins_altcx; i++) { |
489 | if (npct->soc->altcx_pins[i].pin == gpio) |
490 | break; |
491 | } |
492 | if (i == npct->soc->npins_altcx) |
493 | return NMK_GPIO_ALT_C; |
494 | |
495 | pin_desc = npct->soc->altcx_pins + i; |
496 | gpiocr_regs = npct->soc->prcm_gpiocr_registers; |
497 | for (i = 0; i < PRCM_IDX_GPIOCR_ALTC_MAX; i++) { |
498 | if (pin_desc->altcx[i].used) { |
499 | reg = gpiocr_regs[pin_desc->altcx[i].reg_index]; |
500 | bit = pin_desc->altcx[i].control_bit; |
501 | if (readl(addr: npct->prcm_base + reg) & BIT(bit)) |
502 | return NMK_GPIO_ALT_C + i + 1; |
503 | } |
504 | } |
505 | return NMK_GPIO_ALT_C; |
506 | } |
507 | |
508 | static int nmk_get_groups_cnt(struct pinctrl_dev *pctldev) |
509 | { |
510 | struct nmk_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev); |
511 | |
512 | return npct->soc->ngroups; |
513 | } |
514 | |
515 | static const char *nmk_get_group_name(struct pinctrl_dev *pctldev, |
516 | unsigned int selector) |
517 | { |
518 | struct nmk_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev); |
519 | |
520 | return npct->soc->groups[selector].grp.name; |
521 | } |
522 | |
523 | static int nmk_get_group_pins(struct pinctrl_dev *pctldev, unsigned int selector, |
524 | const unsigned int **pins, |
525 | unsigned int *num_pins) |
526 | { |
527 | struct nmk_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev); |
528 | |
529 | *pins = npct->soc->groups[selector].grp.pins; |
530 | *num_pins = npct->soc->groups[selector].grp.npins; |
531 | return 0; |
532 | } |
533 | |
534 | /* This makes the mapping from pin number to a GPIO chip. We also return the pin |
535 | * offset in the GPIO chip for convenience (and to avoid a second loop). |
536 | */ |
537 | static struct nmk_gpio_chip *find_nmk_gpio_from_pin(unsigned int pin, |
538 | unsigned int *offset) |
539 | { |
540 | int i, j = 0; |
541 | struct nmk_gpio_chip *nmk_gpio; |
542 | |
543 | /* We assume that pins are allocated in bank order. */ |
544 | for (i = 0; i < NMK_MAX_BANKS; i++) { |
545 | nmk_gpio = nmk_gpio_chips[i]; |
546 | if (!nmk_gpio) |
547 | continue; |
548 | if (pin >= j && pin < j + nmk_gpio->chip.ngpio) { |
549 | if (offset) |
550 | *offset = pin - j; |
551 | return nmk_gpio; |
552 | } |
553 | j += nmk_gpio->chip.ngpio; |
554 | } |
555 | return NULL; |
556 | } |
557 | |
558 | static struct gpio_chip *find_gc_from_pin(unsigned int pin) |
559 | { |
560 | struct nmk_gpio_chip *nmk_gpio = find_nmk_gpio_from_pin(pin, NULL); |
561 | |
562 | if (nmk_gpio) |
563 | return &nmk_gpio->chip; |
564 | return NULL; |
565 | } |
566 | |
567 | static void nmk_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s, |
568 | unsigned int offset) |
569 | { |
570 | struct gpio_chip *chip = find_gc_from_pin(pin: offset); |
571 | |
572 | if (!chip) { |
573 | seq_printf(m: s, fmt: "invalid pin offset" ); |
574 | return; |
575 | } |
576 | nmk_gpio_dbg_show_one(s, pctldev, chip, offset: offset - chip->base, gpio: offset); |
577 | } |
578 | |
579 | static int nmk_dt_add_map_mux(struct pinctrl_map **map, unsigned int *reserved_maps, |
580 | unsigned int *num_maps, const char *group, |
581 | const char *function) |
582 | { |
583 | if (*num_maps == *reserved_maps) |
584 | return -ENOSPC; |
585 | |
586 | (*map)[*num_maps].type = PIN_MAP_TYPE_MUX_GROUP; |
587 | (*map)[*num_maps].data.mux.group = group; |
588 | (*map)[*num_maps].data.mux.function = function; |
589 | (*num_maps)++; |
590 | |
591 | return 0; |
592 | } |
593 | |
594 | static int nmk_dt_add_map_configs(struct pinctrl_map **map, |
595 | unsigned int *reserved_maps, |
596 | unsigned int *num_maps, const char *group, |
597 | unsigned long *configs, unsigned int num_configs) |
598 | { |
599 | unsigned long *dup_configs; |
600 | |
601 | if (*num_maps == *reserved_maps) |
602 | return -ENOSPC; |
603 | |
604 | dup_configs = kmemdup(p: configs, size: num_configs * sizeof(*dup_configs), |
605 | GFP_KERNEL); |
606 | if (!dup_configs) |
607 | return -ENOMEM; |
608 | |
609 | (*map)[*num_maps].type = PIN_MAP_TYPE_CONFIGS_PIN; |
610 | |
611 | (*map)[*num_maps].data.configs.group_or_pin = group; |
612 | (*map)[*num_maps].data.configs.configs = dup_configs; |
613 | (*map)[*num_maps].data.configs.num_configs = num_configs; |
614 | (*num_maps)++; |
615 | |
616 | return 0; |
617 | } |
618 | |
619 | #define NMK_CONFIG_PIN(x, y) { .property = x, .config = y, } |
620 | #define NMK_CONFIG_PIN_ARRAY(x, y) { .property = x, .choice = y, \ |
621 | .size = ARRAY_SIZE(y), } |
622 | |
623 | static const unsigned long nmk_pin_input_modes[] = { |
624 | PIN_INPUT_NOPULL, |
625 | PIN_INPUT_PULLUP, |
626 | PIN_INPUT_PULLDOWN, |
627 | }; |
628 | |
629 | static const unsigned long nmk_pin_output_modes[] = { |
630 | PIN_OUTPUT_LOW, |
631 | PIN_OUTPUT_HIGH, |
632 | PIN_DIR_OUTPUT, |
633 | }; |
634 | |
635 | static const unsigned long nmk_pin_sleep_modes[] = { |
636 | PIN_SLEEPMODE_DISABLED, |
637 | PIN_SLEEPMODE_ENABLED, |
638 | }; |
639 | |
640 | static const unsigned long nmk_pin_sleep_input_modes[] = { |
641 | PIN_SLPM_INPUT_NOPULL, |
642 | PIN_SLPM_INPUT_PULLUP, |
643 | PIN_SLPM_INPUT_PULLDOWN, |
644 | PIN_SLPM_DIR_INPUT, |
645 | }; |
646 | |
647 | static const unsigned long nmk_pin_sleep_output_modes[] = { |
648 | PIN_SLPM_OUTPUT_LOW, |
649 | PIN_SLPM_OUTPUT_HIGH, |
650 | PIN_SLPM_DIR_OUTPUT, |
651 | }; |
652 | |
653 | static const unsigned long nmk_pin_sleep_wakeup_modes[] = { |
654 | PIN_SLPM_WAKEUP_DISABLE, |
655 | PIN_SLPM_WAKEUP_ENABLE, |
656 | }; |
657 | |
658 | static const unsigned long nmk_pin_gpio_modes[] = { |
659 | PIN_GPIOMODE_DISABLED, |
660 | PIN_GPIOMODE_ENABLED, |
661 | }; |
662 | |
663 | static const unsigned long nmk_pin_sleep_pdis_modes[] = { |
664 | PIN_SLPM_PDIS_DISABLED, |
665 | PIN_SLPM_PDIS_ENABLED, |
666 | }; |
667 | |
668 | struct nmk_cfg_param { |
669 | const char *property; |
670 | unsigned long config; |
671 | const unsigned long *choice; |
672 | int size; |
673 | }; |
674 | |
675 | static const struct nmk_cfg_param nmk_cfg_params[] = { |
676 | NMK_CONFIG_PIN_ARRAY("ste,input" , nmk_pin_input_modes), |
677 | NMK_CONFIG_PIN_ARRAY("ste,output" , nmk_pin_output_modes), |
678 | NMK_CONFIG_PIN_ARRAY("ste,sleep" , nmk_pin_sleep_modes), |
679 | NMK_CONFIG_PIN_ARRAY("ste,sleep-input" , nmk_pin_sleep_input_modes), |
680 | NMK_CONFIG_PIN_ARRAY("ste,sleep-output" , nmk_pin_sleep_output_modes), |
681 | NMK_CONFIG_PIN_ARRAY("ste,sleep-wakeup" , nmk_pin_sleep_wakeup_modes), |
682 | NMK_CONFIG_PIN_ARRAY("ste,gpio" , nmk_pin_gpio_modes), |
683 | NMK_CONFIG_PIN_ARRAY("ste,sleep-pull-disable" , nmk_pin_sleep_pdis_modes), |
684 | }; |
685 | |
686 | static int nmk_dt_pin_config(int index, int val, unsigned long *config) |
687 | { |
688 | if (!nmk_cfg_params[index].choice) { |
689 | *config = nmk_cfg_params[index].config; |
690 | } else { |
691 | /* test if out of range */ |
692 | if (val < nmk_cfg_params[index].size) { |
693 | *config = nmk_cfg_params[index].config | |
694 | nmk_cfg_params[index].choice[val]; |
695 | } |
696 | } |
697 | return 0; |
698 | } |
699 | |
700 | static const char *nmk_find_pin_name(struct pinctrl_dev *pctldev, const char *pin_name) |
701 | { |
702 | int i, pin_number; |
703 | struct nmk_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev); |
704 | |
705 | if (sscanf((char *)pin_name, "GPIO%d" , &pin_number) == 1) |
706 | for (i = 0; i < npct->soc->npins; i++) |
707 | if (npct->soc->pins[i].number == pin_number) |
708 | return npct->soc->pins[i].name; |
709 | return NULL; |
710 | } |
711 | |
712 | static bool nmk_pinctrl_dt_get_config(struct device_node *np, |
713 | unsigned long *configs) |
714 | { |
715 | bool has_config = 0; |
716 | unsigned long cfg = 0; |
717 | int i, val, ret; |
718 | |
719 | for (i = 0; i < ARRAY_SIZE(nmk_cfg_params); i++) { |
720 | ret = of_property_read_u32(np, propname: nmk_cfg_params[i].property, out_value: &val); |
721 | if (ret != -EINVAL) { |
722 | if (nmk_dt_pin_config(index: i, val, config: &cfg) == 0) { |
723 | *configs |= cfg; |
724 | has_config = 1; |
725 | } |
726 | } |
727 | } |
728 | |
729 | return has_config; |
730 | } |
731 | |
732 | static int nmk_pinctrl_dt_subnode_to_map(struct pinctrl_dev *pctldev, |
733 | struct device_node *np, |
734 | struct pinctrl_map **map, |
735 | unsigned int *reserved_maps, |
736 | unsigned int *num_maps) |
737 | { |
738 | int ret; |
739 | const char *function = NULL; |
740 | unsigned long configs = 0; |
741 | bool has_config = 0; |
742 | struct property *prop; |
743 | struct device_node *np_config; |
744 | |
745 | ret = of_property_read_string(np, propname: "function" , out_string: &function); |
746 | if (ret >= 0) { |
747 | const char *group; |
748 | |
749 | ret = of_property_count_strings(np, propname: "groups" ); |
750 | if (ret < 0) |
751 | goto exit; |
752 | |
753 | ret = pinctrl_utils_reserve_map(pctldev, map, |
754 | reserved_maps, |
755 | num_maps, reserve: ret); |
756 | if (ret < 0) |
757 | goto exit; |
758 | |
759 | of_property_for_each_string(np, "groups" , prop, group) { |
760 | ret = nmk_dt_add_map_mux(map, reserved_maps, num_maps, |
761 | group, function); |
762 | if (ret < 0) |
763 | goto exit; |
764 | } |
765 | } |
766 | |
767 | has_config = nmk_pinctrl_dt_get_config(np, configs: &configs); |
768 | np_config = of_parse_phandle(np, phandle_name: "ste,config" , index: 0); |
769 | if (np_config) { |
770 | has_config |= nmk_pinctrl_dt_get_config(np: np_config, configs: &configs); |
771 | of_node_put(node: np_config); |
772 | } |
773 | if (has_config) { |
774 | const char *gpio_name; |
775 | const char *pin; |
776 | |
777 | ret = of_property_count_strings(np, propname: "pins" ); |
778 | if (ret < 0) |
779 | goto exit; |
780 | ret = pinctrl_utils_reserve_map(pctldev, map, |
781 | reserved_maps, |
782 | num_maps, reserve: ret); |
783 | if (ret < 0) |
784 | goto exit; |
785 | |
786 | of_property_for_each_string(np, "pins" , prop, pin) { |
787 | gpio_name = nmk_find_pin_name(pctldev, pin_name: pin); |
788 | |
789 | ret = nmk_dt_add_map_configs(map, reserved_maps, |
790 | num_maps, |
791 | group: gpio_name, configs: &configs, num_configs: 1); |
792 | if (ret < 0) |
793 | goto exit; |
794 | } |
795 | } |
796 | |
797 | exit: |
798 | return ret; |
799 | } |
800 | |
801 | static int nmk_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev, |
802 | struct device_node *np_config, |
803 | struct pinctrl_map **map, |
804 | unsigned int *num_maps) |
805 | { |
806 | unsigned int reserved_maps; |
807 | struct device_node *np; |
808 | int ret; |
809 | |
810 | reserved_maps = 0; |
811 | *map = NULL; |
812 | *num_maps = 0; |
813 | |
814 | for_each_child_of_node(np_config, np) { |
815 | ret = nmk_pinctrl_dt_subnode_to_map(pctldev, np, map, |
816 | reserved_maps: &reserved_maps, num_maps); |
817 | if (ret < 0) { |
818 | pinctrl_utils_free_map(pctldev, map: *map, num_maps: *num_maps); |
819 | of_node_put(node: np); |
820 | return ret; |
821 | } |
822 | } |
823 | |
824 | return 0; |
825 | } |
826 | |
827 | static const struct pinctrl_ops nmk_pinctrl_ops = { |
828 | .get_groups_count = nmk_get_groups_cnt, |
829 | .get_group_name = nmk_get_group_name, |
830 | .get_group_pins = nmk_get_group_pins, |
831 | .pin_dbg_show = nmk_pin_dbg_show, |
832 | .dt_node_to_map = nmk_pinctrl_dt_node_to_map, |
833 | .dt_free_map = pinctrl_utils_free_map, |
834 | }; |
835 | |
836 | static int nmk_pmx_get_funcs_cnt(struct pinctrl_dev *pctldev) |
837 | { |
838 | struct nmk_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev); |
839 | |
840 | return npct->soc->nfunctions; |
841 | } |
842 | |
843 | static const char *nmk_pmx_get_func_name(struct pinctrl_dev *pctldev, |
844 | unsigned int function) |
845 | { |
846 | struct nmk_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev); |
847 | |
848 | return npct->soc->functions[function].name; |
849 | } |
850 | |
851 | static int nmk_pmx_get_func_groups(struct pinctrl_dev *pctldev, |
852 | unsigned int function, |
853 | const char * const **groups, |
854 | unsigned * const num_groups) |
855 | { |
856 | struct nmk_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev); |
857 | |
858 | *groups = npct->soc->functions[function].groups; |
859 | *num_groups = npct->soc->functions[function].ngroups; |
860 | |
861 | return 0; |
862 | } |
863 | |
864 | static int nmk_pmx_set(struct pinctrl_dev *pctldev, unsigned int function, |
865 | unsigned int group) |
866 | { |
867 | struct nmk_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev); |
868 | const struct nmk_pingroup *g; |
869 | static unsigned int slpm[NMK_MAX_BANKS]; |
870 | unsigned long flags = 0; |
871 | bool glitch; |
872 | int ret = -EINVAL; |
873 | int i; |
874 | |
875 | g = &npct->soc->groups[group]; |
876 | |
877 | if (g->altsetting < 0) |
878 | return -EINVAL; |
879 | |
880 | dev_dbg(npct->dev, "enable group %s, %zu pins\n" , g->grp.name, g->grp.npins); |
881 | |
882 | /* |
883 | * If we're setting altfunc C by setting both AFSLA and AFSLB to 1, |
884 | * we may pass through an undesired state. In this case we take |
885 | * some extra care. |
886 | * |
887 | * Safe sequence used to switch IOs between GPIO and Alternate-C mode: |
888 | * - Save SLPM registers (since we have a shadow register in the |
889 | * nmk_chip we're using that as backup) |
890 | * - Set SLPM=0 for the IOs you want to switch and others to 1 |
891 | * - Configure the GPIO registers for the IOs that are being switched |
892 | * - Set IOFORCE=1 |
893 | * - Modify the AFLSA/B registers for the IOs that are being switched |
894 | * - Set IOFORCE=0 |
895 | * - Restore SLPM registers |
896 | * - Any spurious wake up event during switch sequence to be ignored |
897 | * and cleared |
898 | * |
899 | * We REALLY need to save ALL slpm registers, because the external |
900 | * IOFORCE will switch *all* ports to their sleepmode setting to as |
901 | * to avoid glitches. (Not just one port!) |
902 | */ |
903 | glitch = ((g->altsetting & NMK_GPIO_ALT_C) == NMK_GPIO_ALT_C); |
904 | |
905 | if (glitch) { |
906 | spin_lock_irqsave(&nmk_gpio_slpm_lock, flags); |
907 | |
908 | /* Initially don't put any pins to sleep when switching */ |
909 | memset(slpm, 0xff, sizeof(slpm)); |
910 | |
911 | /* |
912 | * Then mask the pins that need to be sleeping now when we're |
913 | * switching to the ALT C function. |
914 | */ |
915 | for (i = 0; i < g->grp.npins; i++) { |
916 | struct nmk_gpio_chip *nmk_chip; |
917 | unsigned int bit; |
918 | |
919 | nmk_chip = find_nmk_gpio_from_pin(pin: g->grp.pins[i], offset: &bit); |
920 | if (!nmk_chip) { |
921 | dev_err(npct->dev, |
922 | "invalid pin offset %d in group %s at index %d\n" , |
923 | g->grp.pins[i], g->grp.name, i); |
924 | goto out_pre_slpm_init; |
925 | } |
926 | |
927 | slpm[nmk_chip->bank] &= ~BIT(bit); |
928 | } |
929 | nmk_gpio_glitch_slpm_init(slpm); |
930 | } |
931 | |
932 | for (i = 0; i < g->grp.npins; i++) { |
933 | struct nmk_gpio_chip *nmk_chip; |
934 | unsigned int bit; |
935 | |
936 | nmk_chip = find_nmk_gpio_from_pin(pin: g->grp.pins[i], offset: &bit); |
937 | if (!nmk_chip) { |
938 | dev_err(npct->dev, |
939 | "invalid pin offset %d in group %s at index %d\n" , |
940 | g->grp.pins[i], g->grp.name, i); |
941 | goto out_glitch; |
942 | } |
943 | dev_dbg(npct->dev, "setting pin %d to altsetting %d\n" , |
944 | g->grp.pins[i], g->altsetting); |
945 | |
946 | clk_enable(clk: nmk_chip->clk); |
947 | /* |
948 | * If the pin is switching to altfunc, and there was an |
949 | * interrupt installed on it which has been lazy disabled, |
950 | * actually mask the interrupt to prevent spurious interrupts |
951 | * that would occur while the pin is under control of the |
952 | * peripheral. Only SKE does this. |
953 | */ |
954 | nmk_gpio_disable_lazy_irq(nmk_chip, offset: bit); |
955 | |
956 | __nmk_gpio_set_mode_safe(nmk_chip, offset: bit, |
957 | gpio_mode: (g->altsetting & NMK_GPIO_ALT_C), glitch); |
958 | clk_disable(clk: nmk_chip->clk); |
959 | |
960 | /* |
961 | * Call PRCM GPIOCR config function in case ALTC |
962 | * has been selected: |
963 | * - If selection is a ALTCx, some bits in PRCM GPIOCR registers |
964 | * must be set. |
965 | * - If selection is pure ALTC and previous selection was ALTCx, |
966 | * then some bits in PRCM GPIOCR registers must be cleared. |
967 | */ |
968 | if ((g->altsetting & NMK_GPIO_ALT_C) == NMK_GPIO_ALT_C) |
969 | nmk_prcm_altcx_set_mode(npct, offset: g->grp.pins[i], |
970 | alt_num: g->altsetting >> NMK_GPIO_ALT_CX_SHIFT); |
971 | } |
972 | |
973 | /* When all pins are successfully reconfigured we get here */ |
974 | ret = 0; |
975 | |
976 | out_glitch: |
977 | if (glitch) |
978 | nmk_gpio_glitch_slpm_restore(slpm); |
979 | out_pre_slpm_init: |
980 | if (glitch) |
981 | spin_unlock_irqrestore(lock: &nmk_gpio_slpm_lock, flags); |
982 | |
983 | return ret; |
984 | } |
985 | |
986 | static int nmk_gpio_request_enable(struct pinctrl_dev *pctldev, |
987 | struct pinctrl_gpio_range *range, |
988 | unsigned int pin) |
989 | { |
990 | struct nmk_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev); |
991 | struct nmk_gpio_chip *nmk_chip; |
992 | struct gpio_chip *chip; |
993 | unsigned int bit; |
994 | |
995 | if (!range) { |
996 | dev_err(npct->dev, "invalid range\n" ); |
997 | return -EINVAL; |
998 | } |
999 | if (!range->gc) { |
1000 | dev_err(npct->dev, "missing GPIO chip in range\n" ); |
1001 | return -EINVAL; |
1002 | } |
1003 | chip = range->gc; |
1004 | nmk_chip = gpiochip_get_data(gc: chip); |
1005 | |
1006 | dev_dbg(npct->dev, "enable pin %u as GPIO\n" , pin); |
1007 | |
1008 | find_nmk_gpio_from_pin(pin, offset: &bit); |
1009 | |
1010 | clk_enable(clk: nmk_chip->clk); |
1011 | /* There is no glitch when converting any pin to GPIO */ |
1012 | __nmk_gpio_set_mode(nmk_chip, offset: bit, NMK_GPIO_ALT_GPIO); |
1013 | clk_disable(clk: nmk_chip->clk); |
1014 | |
1015 | return 0; |
1016 | } |
1017 | |
1018 | static void nmk_gpio_disable_free(struct pinctrl_dev *pctldev, |
1019 | struct pinctrl_gpio_range *range, |
1020 | unsigned int pin) |
1021 | { |
1022 | struct nmk_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev); |
1023 | |
1024 | dev_dbg(npct->dev, "disable pin %u as GPIO\n" , pin); |
1025 | /* Set the pin to some default state, GPIO is usually default */ |
1026 | } |
1027 | |
1028 | static const struct pinmux_ops nmk_pinmux_ops = { |
1029 | .get_functions_count = nmk_pmx_get_funcs_cnt, |
1030 | .get_function_name = nmk_pmx_get_func_name, |
1031 | .get_function_groups = nmk_pmx_get_func_groups, |
1032 | .set_mux = nmk_pmx_set, |
1033 | .gpio_request_enable = nmk_gpio_request_enable, |
1034 | .gpio_disable_free = nmk_gpio_disable_free, |
1035 | .strict = true, |
1036 | }; |
1037 | |
1038 | static int nmk_pin_config_get(struct pinctrl_dev *pctldev, unsigned int pin, |
1039 | unsigned long *config) |
1040 | { |
1041 | /* Not implemented */ |
1042 | return -EINVAL; |
1043 | } |
1044 | |
1045 | static int nmk_pin_config_set(struct pinctrl_dev *pctldev, unsigned int pin, |
1046 | unsigned long *configs, unsigned int num_configs) |
1047 | { |
1048 | static const char * const pullnames[] = { |
1049 | [NMK_GPIO_PULL_NONE] = "none" , |
1050 | [NMK_GPIO_PULL_UP] = "up" , |
1051 | [NMK_GPIO_PULL_DOWN] = "down" , |
1052 | [3] /* illegal */ = "??" |
1053 | }; |
1054 | static const char * const slpmnames[] = { |
1055 | [NMK_GPIO_SLPM_INPUT] = "input/wakeup" , |
1056 | [NMK_GPIO_SLPM_NOCHANGE] = "no-change/no-wakeup" , |
1057 | }; |
1058 | struct nmk_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev); |
1059 | struct nmk_gpio_chip *nmk_chip; |
1060 | unsigned int bit; |
1061 | unsigned long cfg; |
1062 | int pull, slpm, output, val, i; |
1063 | bool lowemi, gpiomode, sleep; |
1064 | |
1065 | nmk_chip = find_nmk_gpio_from_pin(pin, offset: &bit); |
1066 | if (!nmk_chip) { |
1067 | dev_err(npct->dev, |
1068 | "invalid pin offset %d\n" , pin); |
1069 | return -EINVAL; |
1070 | } |
1071 | |
1072 | for (i = 0; i < num_configs; i++) { |
1073 | /* |
1074 | * The pin config contains pin number and altfunction fields, |
1075 | * here we just ignore that part. It's being handled by the |
1076 | * framework and pinmux callback respectively. |
1077 | */ |
1078 | cfg = configs[i]; |
1079 | pull = PIN_PULL(cfg); |
1080 | slpm = PIN_SLPM(cfg); |
1081 | output = PIN_DIR(cfg); |
1082 | val = PIN_VAL(cfg); |
1083 | lowemi = PIN_LOWEMI(cfg); |
1084 | gpiomode = PIN_GPIOMODE(cfg); |
1085 | sleep = PIN_SLEEPMODE(cfg); |
1086 | |
1087 | if (sleep) { |
1088 | int slpm_pull = PIN_SLPM_PULL(cfg); |
1089 | int slpm_output = PIN_SLPM_DIR(cfg); |
1090 | int slpm_val = PIN_SLPM_VAL(cfg); |
1091 | |
1092 | /* All pins go into GPIO mode at sleep */ |
1093 | gpiomode = true; |
1094 | |
1095 | /* |
1096 | * The SLPM_* values are normal values + 1 to allow zero |
1097 | * to mean "same as normal". |
1098 | */ |
1099 | if (slpm_pull) |
1100 | pull = slpm_pull - 1; |
1101 | if (slpm_output) |
1102 | output = slpm_output - 1; |
1103 | if (slpm_val) |
1104 | val = slpm_val - 1; |
1105 | |
1106 | dev_dbg(nmk_chip->chip.parent, |
1107 | "pin %d: sleep pull %s, dir %s, val %s\n" , |
1108 | pin, |
1109 | slpm_pull ? pullnames[pull] : "same" , |
1110 | slpm_output ? (output ? "output" : "input" ) |
1111 | : "same" , |
1112 | slpm_val ? (val ? "high" : "low" ) : "same" ); |
1113 | } |
1114 | |
1115 | dev_dbg(nmk_chip->chip.parent, |
1116 | "pin %d [%#lx]: pull %s, slpm %s (%s%s), lowemi %s\n" , |
1117 | pin, cfg, pullnames[pull], slpmnames[slpm], |
1118 | output ? "output " : "input" , |
1119 | output ? (val ? "high" : "low" ) : "" , |
1120 | lowemi ? "on" : "off" ); |
1121 | |
1122 | clk_enable(clk: nmk_chip->clk); |
1123 | if (gpiomode) |
1124 | /* No glitch when going to GPIO mode */ |
1125 | __nmk_gpio_set_mode(nmk_chip, offset: bit, NMK_GPIO_ALT_GPIO); |
1126 | if (output) { |
1127 | __nmk_gpio_make_output(nmk_chip, offset: bit, val); |
1128 | } else { |
1129 | __nmk_gpio_make_input(nmk_chip, offset: bit); |
1130 | __nmk_gpio_set_pull(nmk_chip, offset: bit, pull); |
1131 | } |
1132 | /* TODO: isn't this only applicable on output pins? */ |
1133 | __nmk_gpio_set_lowemi(nmk_chip, offset: bit, lowemi); |
1134 | |
1135 | __nmk_gpio_set_slpm(nmk_chip, offset: bit, mode: slpm); |
1136 | clk_disable(clk: nmk_chip->clk); |
1137 | } /* for each config */ |
1138 | |
1139 | return 0; |
1140 | } |
1141 | |
1142 | static const struct pinconf_ops nmk_pinconf_ops = { |
1143 | .pin_config_get = nmk_pin_config_get, |
1144 | .pin_config_set = nmk_pin_config_set, |
1145 | }; |
1146 | |
1147 | static struct pinctrl_desc nmk_pinctrl_desc = { |
1148 | .name = "pinctrl-nomadik" , |
1149 | .pctlops = &nmk_pinctrl_ops, |
1150 | .pmxops = &nmk_pinmux_ops, |
1151 | .confops = &nmk_pinconf_ops, |
1152 | .owner = THIS_MODULE, |
1153 | }; |
1154 | |
1155 | static const struct of_device_id nmk_pinctrl_match[] = { |
1156 | { |
1157 | .compatible = "stericsson,stn8815-pinctrl" , |
1158 | .data = (void *)PINCTRL_NMK_STN8815, |
1159 | }, |
1160 | { |
1161 | .compatible = "stericsson,db8500-pinctrl" , |
1162 | .data = (void *)PINCTRL_NMK_DB8500, |
1163 | }, |
1164 | {}, |
1165 | }; |
1166 | |
1167 | #ifdef CONFIG_PM_SLEEP |
1168 | static int nmk_pinctrl_suspend(struct device *dev) |
1169 | { |
1170 | struct nmk_pinctrl *npct; |
1171 | |
1172 | npct = dev_get_drvdata(dev); |
1173 | if (!npct) |
1174 | return -EINVAL; |
1175 | |
1176 | return pinctrl_force_sleep(pctldev: npct->pctl); |
1177 | } |
1178 | |
1179 | static int nmk_pinctrl_resume(struct device *dev) |
1180 | { |
1181 | struct nmk_pinctrl *npct; |
1182 | |
1183 | npct = dev_get_drvdata(dev); |
1184 | if (!npct) |
1185 | return -EINVAL; |
1186 | |
1187 | return pinctrl_force_default(pctldev: npct->pctl); |
1188 | } |
1189 | #endif |
1190 | |
1191 | static int nmk_pinctrl_probe(struct platform_device *pdev) |
1192 | { |
1193 | struct fwnode_handle *fwnode = dev_fwnode(&pdev->dev); |
1194 | struct fwnode_handle *prcm_fwnode; |
1195 | struct nmk_pinctrl *npct; |
1196 | uintptr_t version = 0; |
1197 | int i; |
1198 | |
1199 | npct = devm_kzalloc(dev: &pdev->dev, size: sizeof(*npct), GFP_KERNEL); |
1200 | if (!npct) |
1201 | return -ENOMEM; |
1202 | |
1203 | version = (uintptr_t)device_get_match_data(dev: &pdev->dev); |
1204 | |
1205 | /* Poke in other ASIC variants here */ |
1206 | if (version == PINCTRL_NMK_STN8815) |
1207 | nmk_pinctrl_stn8815_init(soc: &npct->soc); |
1208 | if (version == PINCTRL_NMK_DB8500) |
1209 | nmk_pinctrl_db8500_init(soc: &npct->soc); |
1210 | |
1211 | /* |
1212 | * Since we depend on the GPIO chips to provide clock and register base |
1213 | * for the pin control operations, make sure that we have these |
1214 | * populated before we continue. Follow the phandles to instantiate |
1215 | * them. The GPIO portion of the actual hardware may be probed before |
1216 | * or after this point: it shouldn't matter as the APIs are orthogonal. |
1217 | */ |
1218 | for (i = 0; i < NMK_MAX_BANKS; i++) { |
1219 | struct fwnode_handle *gpio_fwnode; |
1220 | struct nmk_gpio_chip *nmk_chip; |
1221 | |
1222 | gpio_fwnode = fwnode_find_reference(fwnode, name: "nomadik-gpio-chips" , index: i); |
1223 | if (IS_ERR(ptr: gpio_fwnode)) |
1224 | continue; |
1225 | |
1226 | dev_info(&pdev->dev, "populate NMK GPIO %d \"%pfwP\"\n" , i, gpio_fwnode); |
1227 | nmk_chip = nmk_gpio_populate_chip(fwnode: gpio_fwnode, pdev); |
1228 | if (IS_ERR(ptr: nmk_chip)) |
1229 | dev_err(&pdev->dev, |
1230 | "could not populate nmk chip struct - continue anyway\n" ); |
1231 | else |
1232 | /* We are NOT compatible with mobileye,eyeq5-gpio. */ |
1233 | BUG_ON(nmk_chip->is_mobileye_soc); |
1234 | fwnode_handle_put(fwnode: gpio_fwnode); |
1235 | } |
1236 | |
1237 | prcm_fwnode = fwnode_find_reference(fwnode, name: "prcm" , index: 0); |
1238 | if (!IS_ERR(ptr: prcm_fwnode)) { |
1239 | npct->prcm_base = fwnode_iomap(fwnode: prcm_fwnode, index: 0); |
1240 | fwnode_handle_put(fwnode: prcm_fwnode); |
1241 | } |
1242 | if (!npct->prcm_base) { |
1243 | if (version == PINCTRL_NMK_STN8815) { |
1244 | dev_info(&pdev->dev, |
1245 | "No PRCM base, assuming no ALT-Cx control is available\n" ); |
1246 | } else { |
1247 | dev_err(&pdev->dev, "missing PRCM base address\n" ); |
1248 | return -EINVAL; |
1249 | } |
1250 | } |
1251 | |
1252 | nmk_pinctrl_desc.pins = npct->soc->pins; |
1253 | nmk_pinctrl_desc.npins = npct->soc->npins; |
1254 | npct->dev = &pdev->dev; |
1255 | |
1256 | npct->pctl = devm_pinctrl_register(dev: &pdev->dev, pctldesc: &nmk_pinctrl_desc, driver_data: npct); |
1257 | if (IS_ERR(ptr: npct->pctl)) { |
1258 | dev_err(&pdev->dev, "could not register Nomadik pinctrl driver\n" ); |
1259 | return PTR_ERR(ptr: npct->pctl); |
1260 | } |
1261 | |
1262 | platform_set_drvdata(pdev, data: npct); |
1263 | dev_info(&pdev->dev, "initialized Nomadik pin control driver\n" ); |
1264 | |
1265 | return 0; |
1266 | } |
1267 | |
1268 | static SIMPLE_DEV_PM_OPS(nmk_pinctrl_pm_ops, |
1269 | nmk_pinctrl_suspend, |
1270 | nmk_pinctrl_resume); |
1271 | |
1272 | static struct platform_driver nmk_pinctrl_driver = { |
1273 | .driver = { |
1274 | .name = "pinctrl-nomadik" , |
1275 | .of_match_table = nmk_pinctrl_match, |
1276 | .pm = &nmk_pinctrl_pm_ops, |
1277 | }, |
1278 | .probe = nmk_pinctrl_probe, |
1279 | }; |
1280 | |
1281 | static int __init nmk_pinctrl_init(void) |
1282 | { |
1283 | return platform_driver_register(&nmk_pinctrl_driver); |
1284 | } |
1285 | core_initcall(nmk_pinctrl_init); |
1286 | |