blob: bc013599a9a3840359d024e97281da069f69349a [file] [log] [blame]
Andy Shevchenko875a92b2018-06-29 15:36:34 +03001// SPDX-License-Identifier: GPL-2.0
Mika Westerberg7981c0012015-03-30 17:31:49 +03002/*
3 * Intel pinctrl/GPIO core driver.
4 *
5 * Copyright (C) 2015, Intel Corporation
6 * Authors: Mathias Nyman <mathias.nyman@linux.intel.com>
7 * Mika Westerberg <mika.westerberg@linux.intel.com>
Mika Westerberg7981c0012015-03-30 17:31:49 +03008 */
9
Andy Shevchenko924cf802018-08-30 19:27:36 +030010#include <linux/acpi.h>
Mika Westerberg193b40c2015-10-21 13:08:43 +030011#include <linux/interrupt.h>
Mika Westerberg7981c0012015-03-30 17:31:49 +030012#include <linux/gpio/driver.h>
Mika Westerberge57725e2017-01-27 13:07:14 +030013#include <linux/log2.h>
Andy Shevchenko6a33a1d2019-08-07 16:41:50 +030014#include <linux/module.h>
Mika Westerberg7981c0012015-03-30 17:31:49 +030015#include <linux/platform_device.h>
Andy Shevchenko924cf802018-08-30 19:27:36 +030016#include <linux/property.h>
Andy Shevchenko6a33a1d2019-08-07 16:41:50 +030017#include <linux/time.h>
Andy Shevchenko924cf802018-08-30 19:27:36 +030018
Mika Westerberg7981c0012015-03-30 17:31:49 +030019#include <linux/pinctrl/pinctrl.h>
20#include <linux/pinctrl/pinmux.h>
21#include <linux/pinctrl/pinconf.h>
22#include <linux/pinctrl/pinconf-generic.h>
23
Mika Westerbergc538b942016-10-10 16:39:31 +030024#include "../core.h"
Mika Westerberg7981c0012015-03-30 17:31:49 +030025#include "pinctrl-intel.h"
26
Mika Westerberg7981c0012015-03-30 17:31:49 +030027/* Offset from regs */
Mika Westerberge57725e2017-01-27 13:07:14 +030028#define REVID 0x000
29#define REVID_SHIFT 16
30#define REVID_MASK GENMASK(31, 16)
31
Mika Westerberg7981c0012015-03-30 17:31:49 +030032#define PADBAR 0x00c
Mika Westerberg7981c0012015-03-30 17:31:49 +030033
34#define PADOWN_BITS 4
35#define PADOWN_SHIFT(p) ((p) % 8 * PADOWN_BITS)
Andy Shevchenkoe58926e2019-04-01 15:06:44 +030036#define PADOWN_MASK(p) (GENMASK(3, 0) << PADOWN_SHIFT(p))
Qipeng Zha99a735b2015-11-30 19:20:16 +080037#define PADOWN_GPP(p) ((p) / 8)
Mika Westerberg7981c0012015-03-30 17:31:49 +030038
39/* Offset from pad_regs */
40#define PADCFG0 0x000
41#define PADCFG0_RXEVCFG_SHIFT 25
Andy Shevchenkoe58926e2019-04-01 15:06:44 +030042#define PADCFG0_RXEVCFG_MASK GENMASK(26, 25)
Mika Westerberg7981c0012015-03-30 17:31:49 +030043#define PADCFG0_RXEVCFG_LEVEL 0
44#define PADCFG0_RXEVCFG_EDGE 1
45#define PADCFG0_RXEVCFG_DISABLED 2
46#define PADCFG0_RXEVCFG_EDGE_BOTH 3
Mika Westerberge57725e2017-01-27 13:07:14 +030047#define PADCFG0_PREGFRXSEL BIT(24)
Mika Westerberg7981c0012015-03-30 17:31:49 +030048#define PADCFG0_RXINV BIT(23)
49#define PADCFG0_GPIROUTIOXAPIC BIT(20)
50#define PADCFG0_GPIROUTSCI BIT(19)
51#define PADCFG0_GPIROUTSMI BIT(18)
52#define PADCFG0_GPIROUTNMI BIT(17)
53#define PADCFG0_PMODE_SHIFT 10
Andy Shevchenkoe58926e2019-04-01 15:06:44 +030054#define PADCFG0_PMODE_MASK GENMASK(13, 10)
Mika Westerberg7981c0012015-03-30 17:31:49 +030055#define PADCFG0_GPIORXDIS BIT(9)
56#define PADCFG0_GPIOTXDIS BIT(8)
57#define PADCFG0_GPIORXSTATE BIT(1)
58#define PADCFG0_GPIOTXSTATE BIT(0)
59
60#define PADCFG1 0x004
61#define PADCFG1_TERM_UP BIT(13)
62#define PADCFG1_TERM_SHIFT 10
Andy Shevchenkoe58926e2019-04-01 15:06:44 +030063#define PADCFG1_TERM_MASK GENMASK(12, 10)
Mika Westerberg7981c0012015-03-30 17:31:49 +030064#define PADCFG1_TERM_20K 4
65#define PADCFG1_TERM_2K 3
66#define PADCFG1_TERM_5K 2
67#define PADCFG1_TERM_1K 1
68
Mika Westerberge57725e2017-01-27 13:07:14 +030069#define PADCFG2 0x008
70#define PADCFG2_DEBEN BIT(0)
71#define PADCFG2_DEBOUNCE_SHIFT 1
72#define PADCFG2_DEBOUNCE_MASK GENMASK(4, 1)
73
Andy Shevchenko6a33a1d2019-08-07 16:41:50 +030074#define DEBOUNCE_PERIOD_NSEC 31250
Mika Westerberge57725e2017-01-27 13:07:14 +030075
Mika Westerberg7981c0012015-03-30 17:31:49 +030076struct intel_pad_context {
77 u32 padcfg0;
78 u32 padcfg1;
Mika Westerberge57725e2017-01-27 13:07:14 +030079 u32 padcfg2;
Mika Westerberg7981c0012015-03-30 17:31:49 +030080};
81
82struct intel_community_context {
83 u32 *intmask;
Chris Chiua0a5f762019-04-15 13:53:58 +080084 u32 *hostown;
Mika Westerberg7981c0012015-03-30 17:31:49 +030085};
86
87struct intel_pinctrl_context {
88 struct intel_pad_context *pads;
89 struct intel_community_context *communities;
90};
91
92/**
93 * struct intel_pinctrl - Intel pinctrl private structure
94 * @dev: Pointer to the device structure
95 * @lock: Lock to serialize register access
96 * @pctldesc: Pin controller description
97 * @pctldev: Pointer to the pin controller device
98 * @chip: GPIO chip in this pin controller
Andy Shevchenko57ff2df2019-09-16 17:47:51 +030099 * @irqchip: IRQ chip in this pin controller
Mika Westerberg7981c0012015-03-30 17:31:49 +0300100 * @soc: SoC/PCH specific pin configuration data
101 * @communities: All communities in this pin controller
102 * @ncommunities: Number of communities in this pin controller
103 * @context: Configuration saved over system sleep
Nilesh Bacchewar01dabe92016-09-21 16:35:23 -0700104 * @irq: pinctrl/GPIO chip irq number
Mika Westerberg7981c0012015-03-30 17:31:49 +0300105 */
106struct intel_pinctrl {
107 struct device *dev;
Mika Westerberg27d90982016-06-16 11:25:36 +0300108 raw_spinlock_t lock;
Mika Westerberg7981c0012015-03-30 17:31:49 +0300109 struct pinctrl_desc pctldesc;
110 struct pinctrl_dev *pctldev;
111 struct gpio_chip chip;
Andy Shevchenko57ff2df2019-09-16 17:47:51 +0300112 struct irq_chip irqchip;
Mika Westerberg7981c0012015-03-30 17:31:49 +0300113 const struct intel_pinctrl_soc_data *soc;
114 struct intel_community *communities;
115 size_t ncommunities;
116 struct intel_pinctrl_context context;
Nilesh Bacchewar01dabe92016-09-21 16:35:23 -0700117 int irq;
Mika Westerberg7981c0012015-03-30 17:31:49 +0300118};
119
Mika Westerberg7981c0012015-03-30 17:31:49 +0300120#define pin_to_padno(c, p) ((p) - (c)->pin_base)
Mika Westerberg919eb472017-06-06 16:18:17 +0300121#define padgroup_offset(g, p) ((p) - (g)->base)
Mika Westerberg7981c0012015-03-30 17:31:49 +0300122
123static struct intel_community *intel_get_community(struct intel_pinctrl *pctrl,
Andy Shevchenko04035f72018-09-26 17:50:26 +0300124 unsigned int pin)
Mika Westerberg7981c0012015-03-30 17:31:49 +0300125{
126 struct intel_community *community;
127 int i;
128
129 for (i = 0; i < pctrl->ncommunities; i++) {
130 community = &pctrl->communities[i];
131 if (pin >= community->pin_base &&
132 pin < community->pin_base + community->npins)
133 return community;
134 }
135
136 dev_warn(pctrl->dev, "failed to find community for pin %u\n", pin);
137 return NULL;
138}
139
Mika Westerberg919eb472017-06-06 16:18:17 +0300140static const struct intel_padgroup *
141intel_community_get_padgroup(const struct intel_community *community,
Andy Shevchenko04035f72018-09-26 17:50:26 +0300142 unsigned int pin)
Mika Westerberg919eb472017-06-06 16:18:17 +0300143{
144 int i;
145
146 for (i = 0; i < community->ngpps; i++) {
147 const struct intel_padgroup *padgrp = &community->gpps[i];
148
149 if (pin >= padgrp->base && pin < padgrp->base + padgrp->size)
150 return padgrp;
151 }
152
153 return NULL;
154}
155
Andy Shevchenko04035f72018-09-26 17:50:26 +0300156static void __iomem *intel_get_padcfg(struct intel_pinctrl *pctrl,
157 unsigned int pin, unsigned int reg)
Mika Westerberg7981c0012015-03-30 17:31:49 +0300158{
159 const struct intel_community *community;
Andy Shevchenko04035f72018-09-26 17:50:26 +0300160 unsigned int padno;
Mika Westerberge57725e2017-01-27 13:07:14 +0300161 size_t nregs;
Mika Westerberg7981c0012015-03-30 17:31:49 +0300162
163 community = intel_get_community(pctrl, pin);
164 if (!community)
165 return NULL;
166
167 padno = pin_to_padno(community, pin);
Mika Westerberge57725e2017-01-27 13:07:14 +0300168 nregs = (community->features & PINCTRL_FEATURE_DEBOUNCE) ? 4 : 2;
169
Andy Shevchenko7eb7ecd2019-07-23 18:55:14 +0300170 if (reg >= nregs * 4)
Mika Westerberge57725e2017-01-27 13:07:14 +0300171 return NULL;
172
173 return community->pad_regs + reg + padno * nregs * 4;
Mika Westerberg7981c0012015-03-30 17:31:49 +0300174}
175
Andy Shevchenko04035f72018-09-26 17:50:26 +0300176static bool intel_pad_owned_by_host(struct intel_pinctrl *pctrl, unsigned int pin)
Mika Westerberg7981c0012015-03-30 17:31:49 +0300177{
178 const struct intel_community *community;
Mika Westerberg919eb472017-06-06 16:18:17 +0300179 const struct intel_padgroup *padgrp;
Andy Shevchenko04035f72018-09-26 17:50:26 +0300180 unsigned int gpp, offset, gpp_offset;
Mika Westerberg7981c0012015-03-30 17:31:49 +0300181 void __iomem *padown;
182
183 community = intel_get_community(pctrl, pin);
184 if (!community)
185 return false;
186 if (!community->padown_offset)
187 return true;
188
Mika Westerberg919eb472017-06-06 16:18:17 +0300189 padgrp = intel_community_get_padgroup(community, pin);
190 if (!padgrp)
191 return false;
192
193 gpp_offset = padgroup_offset(padgrp, pin);
194 gpp = PADOWN_GPP(gpp_offset);
195 offset = community->padown_offset + padgrp->padown_num * 4 + gpp * 4;
Mika Westerberg7981c0012015-03-30 17:31:49 +0300196 padown = community->regs + offset;
197
Mika Westerberg919eb472017-06-06 16:18:17 +0300198 return !(readl(padown) & PADOWN_MASK(gpp_offset));
Mika Westerberg7981c0012015-03-30 17:31:49 +0300199}
200
Andy Shevchenko04035f72018-09-26 17:50:26 +0300201static bool intel_pad_acpi_mode(struct intel_pinctrl *pctrl, unsigned int pin)
Mika Westerberg7981c0012015-03-30 17:31:49 +0300202{
203 const struct intel_community *community;
Mika Westerberg919eb472017-06-06 16:18:17 +0300204 const struct intel_padgroup *padgrp;
Andy Shevchenko04035f72018-09-26 17:50:26 +0300205 unsigned int offset, gpp_offset;
Mika Westerberg7981c0012015-03-30 17:31:49 +0300206 void __iomem *hostown;
207
208 community = intel_get_community(pctrl, pin);
209 if (!community)
210 return true;
211 if (!community->hostown_offset)
212 return false;
213
Mika Westerberg919eb472017-06-06 16:18:17 +0300214 padgrp = intel_community_get_padgroup(community, pin);
215 if (!padgrp)
216 return true;
217
218 gpp_offset = padgroup_offset(padgrp, pin);
219 offset = community->hostown_offset + padgrp->reg_num * 4;
Mika Westerberg7981c0012015-03-30 17:31:49 +0300220 hostown = community->regs + offset;
221
Mika Westerberg919eb472017-06-06 16:18:17 +0300222 return !(readl(hostown) & BIT(gpp_offset));
Mika Westerberg7981c0012015-03-30 17:31:49 +0300223}
224
Andy Shevchenko1bd23152019-08-12 19:14:01 +0300225/**
226 * enum - Locking variants of the pad configuration
227 *
228 * @PAD_UNLOCKED: pad is fully controlled by the configuration registers
229 * @PAD_LOCKED: pad configuration registers, except TX state, are locked
230 * @PAD_LOCKED_TX: pad configuration TX state is locked
231 * @PAD_LOCKED_FULL: pad configuration registers are locked completely
232 *
233 * Locking is considered as read-only mode for corresponding registers and
234 * their respective fields. That said, TX state bit is locked separately from
235 * the main locking scheme.
236 */
237enum {
238 PAD_UNLOCKED = 0,
239 PAD_LOCKED = 1,
240 PAD_LOCKED_TX = 2,
241 PAD_LOCKED_FULL = PAD_LOCKED | PAD_LOCKED_TX,
242};
243
244static int intel_pad_locked(struct intel_pinctrl *pctrl, unsigned int pin)
Mika Westerberg7981c0012015-03-30 17:31:49 +0300245{
246 struct intel_community *community;
Mika Westerberg919eb472017-06-06 16:18:17 +0300247 const struct intel_padgroup *padgrp;
Andy Shevchenko04035f72018-09-26 17:50:26 +0300248 unsigned int offset, gpp_offset;
Mika Westerberg7981c0012015-03-30 17:31:49 +0300249 u32 value;
Andy Shevchenko1bd23152019-08-12 19:14:01 +0300250 int ret = PAD_UNLOCKED;
Mika Westerberg7981c0012015-03-30 17:31:49 +0300251
252 community = intel_get_community(pctrl, pin);
253 if (!community)
Andy Shevchenko1bd23152019-08-12 19:14:01 +0300254 return PAD_LOCKED_FULL;
Mika Westerberg7981c0012015-03-30 17:31:49 +0300255 if (!community->padcfglock_offset)
Andy Shevchenko1bd23152019-08-12 19:14:01 +0300256 return PAD_UNLOCKED;
Mika Westerberg7981c0012015-03-30 17:31:49 +0300257
Mika Westerberg919eb472017-06-06 16:18:17 +0300258 padgrp = intel_community_get_padgroup(community, pin);
259 if (!padgrp)
Andy Shevchenko1bd23152019-08-12 19:14:01 +0300260 return PAD_LOCKED_FULL;
Mika Westerberg919eb472017-06-06 16:18:17 +0300261
262 gpp_offset = padgroup_offset(padgrp, pin);
Mika Westerberg7981c0012015-03-30 17:31:49 +0300263
264 /*
265 * If PADCFGLOCK and PADCFGLOCKTX bits are both clear for this pad,
266 * the pad is considered unlocked. Any other case means that it is
Andy Shevchenko1bd23152019-08-12 19:14:01 +0300267 * either fully or partially locked.
Mika Westerberg7981c0012015-03-30 17:31:49 +0300268 */
Andy Shevchenko1bd23152019-08-12 19:14:01 +0300269 offset = community->padcfglock_offset + 0 + padgrp->reg_num * 8;
Mika Westerberg7981c0012015-03-30 17:31:49 +0300270 value = readl(community->regs + offset);
Mika Westerberg919eb472017-06-06 16:18:17 +0300271 if (value & BIT(gpp_offset))
Andy Shevchenko1bd23152019-08-12 19:14:01 +0300272 ret |= PAD_LOCKED;
Mika Westerberg7981c0012015-03-30 17:31:49 +0300273
Mika Westerberg919eb472017-06-06 16:18:17 +0300274 offset = community->padcfglock_offset + 4 + padgrp->reg_num * 8;
Mika Westerberg7981c0012015-03-30 17:31:49 +0300275 value = readl(community->regs + offset);
Mika Westerberg919eb472017-06-06 16:18:17 +0300276 if (value & BIT(gpp_offset))
Andy Shevchenko1bd23152019-08-12 19:14:01 +0300277 ret |= PAD_LOCKED_TX;
Mika Westerberg7981c0012015-03-30 17:31:49 +0300278
Andy Shevchenko1bd23152019-08-12 19:14:01 +0300279 return ret;
280}
281
282static bool intel_pad_is_unlocked(struct intel_pinctrl *pctrl, unsigned int pin)
283{
284 return (intel_pad_locked(pctrl, pin) & PAD_LOCKED) == PAD_UNLOCKED;
Mika Westerberg7981c0012015-03-30 17:31:49 +0300285}
286
Andy Shevchenko04035f72018-09-26 17:50:26 +0300287static bool intel_pad_usable(struct intel_pinctrl *pctrl, unsigned int pin)
Mika Westerberg7981c0012015-03-30 17:31:49 +0300288{
Andy Shevchenko1bd23152019-08-12 19:14:01 +0300289 return intel_pad_owned_by_host(pctrl, pin) && intel_pad_is_unlocked(pctrl, pin);
Mika Westerberg7981c0012015-03-30 17:31:49 +0300290}
291
292static int intel_get_groups_count(struct pinctrl_dev *pctldev)
293{
294 struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
295
296 return pctrl->soc->ngroups;
297}
298
299static const char *intel_get_group_name(struct pinctrl_dev *pctldev,
Andy Shevchenko04035f72018-09-26 17:50:26 +0300300 unsigned int group)
Mika Westerberg7981c0012015-03-30 17:31:49 +0300301{
302 struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
303
304 return pctrl->soc->groups[group].name;
305}
306
Andy Shevchenko04035f72018-09-26 17:50:26 +0300307static int intel_get_group_pins(struct pinctrl_dev *pctldev, unsigned int group,
308 const unsigned int **pins, unsigned int *npins)
Mika Westerberg7981c0012015-03-30 17:31:49 +0300309{
310 struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
311
312 *pins = pctrl->soc->groups[group].pins;
313 *npins = pctrl->soc->groups[group].npins;
314 return 0;
315}
316
317static void intel_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s,
Andy Shevchenko04035f72018-09-26 17:50:26 +0300318 unsigned int pin)
Mika Westerberg7981c0012015-03-30 17:31:49 +0300319{
320 struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
Mika Westerberge57725e2017-01-27 13:07:14 +0300321 void __iomem *padcfg;
Mika Westerberg7981c0012015-03-30 17:31:49 +0300322 u32 cfg0, cfg1, mode;
Andy Shevchenko1bd23152019-08-12 19:14:01 +0300323 int locked;
324 bool acpi;
Mika Westerberg7981c0012015-03-30 17:31:49 +0300325
326 if (!intel_pad_owned_by_host(pctrl, pin)) {
327 seq_puts(s, "not available");
328 return;
329 }
330
331 cfg0 = readl(intel_get_padcfg(pctrl, pin, PADCFG0));
332 cfg1 = readl(intel_get_padcfg(pctrl, pin, PADCFG1));
333
334 mode = (cfg0 & PADCFG0_PMODE_MASK) >> PADCFG0_PMODE_SHIFT;
335 if (!mode)
336 seq_puts(s, "GPIO ");
337 else
338 seq_printf(s, "mode %d ", mode);
339
340 seq_printf(s, "0x%08x 0x%08x", cfg0, cfg1);
341
Mika Westerberge57725e2017-01-27 13:07:14 +0300342 /* Dump the additional PADCFG registers if available */
343 padcfg = intel_get_padcfg(pctrl, pin, PADCFG2);
344 if (padcfg)
345 seq_printf(s, " 0x%08x", readl(padcfg));
346
Mika Westerberg7981c0012015-03-30 17:31:49 +0300347 locked = intel_pad_locked(pctrl, pin);
Mika Westerberg4341e8a2015-10-21 13:08:44 +0300348 acpi = intel_pad_acpi_mode(pctrl, pin);
Mika Westerberg7981c0012015-03-30 17:31:49 +0300349
350 if (locked || acpi) {
351 seq_puts(s, " [");
Andy Shevchenko1bd23152019-08-12 19:14:01 +0300352 if (locked)
Mika Westerberg7981c0012015-03-30 17:31:49 +0300353 seq_puts(s, "LOCKED");
Andy Shevchenko1bd23152019-08-12 19:14:01 +0300354 if ((locked & PAD_LOCKED_FULL) == PAD_LOCKED_TX)
355 seq_puts(s, " tx");
356 else if ((locked & PAD_LOCKED_FULL) == PAD_LOCKED_FULL)
357 seq_puts(s, " full");
358
359 if (locked && acpi)
360 seq_puts(s, ", ");
361
Mika Westerberg7981c0012015-03-30 17:31:49 +0300362 if (acpi)
363 seq_puts(s, "ACPI");
364 seq_puts(s, "]");
365 }
366}
367
368static const struct pinctrl_ops intel_pinctrl_ops = {
369 .get_groups_count = intel_get_groups_count,
370 .get_group_name = intel_get_group_name,
371 .get_group_pins = intel_get_group_pins,
372 .pin_dbg_show = intel_pin_dbg_show,
373};
374
375static int intel_get_functions_count(struct pinctrl_dev *pctldev)
376{
377 struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
378
379 return pctrl->soc->nfunctions;
380}
381
382static const char *intel_get_function_name(struct pinctrl_dev *pctldev,
Andy Shevchenko04035f72018-09-26 17:50:26 +0300383 unsigned int function)
Mika Westerberg7981c0012015-03-30 17:31:49 +0300384{
385 struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
386
387 return pctrl->soc->functions[function].name;
388}
389
390static int intel_get_function_groups(struct pinctrl_dev *pctldev,
Andy Shevchenko04035f72018-09-26 17:50:26 +0300391 unsigned int function,
Mika Westerberg7981c0012015-03-30 17:31:49 +0300392 const char * const **groups,
Andy Shevchenko04035f72018-09-26 17:50:26 +0300393 unsigned int * const ngroups)
Mika Westerberg7981c0012015-03-30 17:31:49 +0300394{
395 struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
396
397 *groups = pctrl->soc->functions[function].groups;
398 *ngroups = pctrl->soc->functions[function].ngroups;
399 return 0;
400}
401
Andy Shevchenko04035f72018-09-26 17:50:26 +0300402static int intel_pinmux_set_mux(struct pinctrl_dev *pctldev,
403 unsigned int function, unsigned int group)
Mika Westerberg7981c0012015-03-30 17:31:49 +0300404{
405 struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
406 const struct intel_pingroup *grp = &pctrl->soc->groups[group];
407 unsigned long flags;
408 int i;
409
Mika Westerberg27d90982016-06-16 11:25:36 +0300410 raw_spin_lock_irqsave(&pctrl->lock, flags);
Mika Westerberg7981c0012015-03-30 17:31:49 +0300411
412 /*
413 * All pins in the groups needs to be accessible and writable
414 * before we can enable the mux for this group.
415 */
416 for (i = 0; i < grp->npins; i++) {
417 if (!intel_pad_usable(pctrl, grp->pins[i])) {
Mika Westerberg27d90982016-06-16 11:25:36 +0300418 raw_spin_unlock_irqrestore(&pctrl->lock, flags);
Mika Westerberg7981c0012015-03-30 17:31:49 +0300419 return -EBUSY;
420 }
421 }
422
423 /* Now enable the mux setting for each pin in the group */
424 for (i = 0; i < grp->npins; i++) {
425 void __iomem *padcfg0;
426 u32 value;
427
428 padcfg0 = intel_get_padcfg(pctrl, grp->pins[i], PADCFG0);
429 value = readl(padcfg0);
430
431 value &= ~PADCFG0_PMODE_MASK;
Mika Westerberg1f6b4192017-06-06 16:18:18 +0300432
433 if (grp->modes)
434 value |= grp->modes[i] << PADCFG0_PMODE_SHIFT;
435 else
436 value |= grp->mode << PADCFG0_PMODE_SHIFT;
Mika Westerberg7981c0012015-03-30 17:31:49 +0300437
438 writel(value, padcfg0);
439 }
440
Mika Westerberg27d90982016-06-16 11:25:36 +0300441 raw_spin_unlock_irqrestore(&pctrl->lock, flags);
Mika Westerberg7981c0012015-03-30 17:31:49 +0300442
443 return 0;
444}
445
Andy Shevchenko17fab472017-01-02 14:07:22 +0200446static void __intel_gpio_set_direction(void __iomem *padcfg0, bool input)
447{
448 u32 value;
449
450 value = readl(padcfg0);
451 if (input) {
452 value &= ~PADCFG0_GPIORXDIS;
453 value |= PADCFG0_GPIOTXDIS;
454 } else {
455 value &= ~PADCFG0_GPIOTXDIS;
456 value |= PADCFG0_GPIORXDIS;
457 }
458 writel(value, padcfg0);
459}
460
Mika Westerbergf5a26ac2017-11-29 16:25:44 +0300461static void intel_gpio_set_gpio_mode(void __iomem *padcfg0)
462{
463 u32 value;
464
465 /* Put the pad into GPIO mode */
466 value = readl(padcfg0) & ~PADCFG0_PMODE_MASK;
467 /* Disable SCI/SMI/NMI generation */
468 value &= ~(PADCFG0_GPIROUTIOXAPIC | PADCFG0_GPIROUTSCI);
469 value &= ~(PADCFG0_GPIROUTSMI | PADCFG0_GPIROUTNMI);
470 writel(value, padcfg0);
471}
472
Mika Westerberg7981c0012015-03-30 17:31:49 +0300473static int intel_gpio_request_enable(struct pinctrl_dev *pctldev,
474 struct pinctrl_gpio_range *range,
Andy Shevchenko04035f72018-09-26 17:50:26 +0300475 unsigned int pin)
Mika Westerberg7981c0012015-03-30 17:31:49 +0300476{
477 struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
478 void __iomem *padcfg0;
479 unsigned long flags;
Mika Westerberg7981c0012015-03-30 17:31:49 +0300480
Mika Westerberg27d90982016-06-16 11:25:36 +0300481 raw_spin_lock_irqsave(&pctrl->lock, flags);
Mika Westerberg7981c0012015-03-30 17:31:49 +0300482
Andy Shevchenko1bd23152019-08-12 19:14:01 +0300483 if (!intel_pad_owned_by_host(pctrl, pin)) {
Mika Westerberg27d90982016-06-16 11:25:36 +0300484 raw_spin_unlock_irqrestore(&pctrl->lock, flags);
Mika Westerberg7981c0012015-03-30 17:31:49 +0300485 return -EBUSY;
486 }
487
Andy Shevchenko1bd23152019-08-12 19:14:01 +0300488 if (!intel_pad_is_unlocked(pctrl, pin)) {
489 raw_spin_unlock_irqrestore(&pctrl->lock, flags);
490 return 0;
491 }
492
Mika Westerberg7981c0012015-03-30 17:31:49 +0300493 padcfg0 = intel_get_padcfg(pctrl, pin, PADCFG0);
Mika Westerbergf5a26ac2017-11-29 16:25:44 +0300494 intel_gpio_set_gpio_mode(padcfg0);
Andy Shevchenko17fab472017-01-02 14:07:22 +0200495 /* Disable TX buffer and enable RX (this will be input) */
496 __intel_gpio_set_direction(padcfg0, true);
497
Mika Westerberg27d90982016-06-16 11:25:36 +0300498 raw_spin_unlock_irqrestore(&pctrl->lock, flags);
Mika Westerberg7981c0012015-03-30 17:31:49 +0300499
500 return 0;
501}
502
503static int intel_gpio_set_direction(struct pinctrl_dev *pctldev,
504 struct pinctrl_gpio_range *range,
Andy Shevchenko04035f72018-09-26 17:50:26 +0300505 unsigned int pin, bool input)
Mika Westerberg7981c0012015-03-30 17:31:49 +0300506{
507 struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
508 void __iomem *padcfg0;
509 unsigned long flags;
Mika Westerberg7981c0012015-03-30 17:31:49 +0300510
Mika Westerberg27d90982016-06-16 11:25:36 +0300511 raw_spin_lock_irqsave(&pctrl->lock, flags);
Mika Westerberg7981c0012015-03-30 17:31:49 +0300512
513 padcfg0 = intel_get_padcfg(pctrl, pin, PADCFG0);
Andy Shevchenko17fab472017-01-02 14:07:22 +0200514 __intel_gpio_set_direction(padcfg0, input);
Mika Westerberg7981c0012015-03-30 17:31:49 +0300515
Mika Westerberg27d90982016-06-16 11:25:36 +0300516 raw_spin_unlock_irqrestore(&pctrl->lock, flags);
Mika Westerberg7981c0012015-03-30 17:31:49 +0300517
518 return 0;
519}
520
521static const struct pinmux_ops intel_pinmux_ops = {
522 .get_functions_count = intel_get_functions_count,
523 .get_function_name = intel_get_function_name,
524 .get_function_groups = intel_get_function_groups,
525 .set_mux = intel_pinmux_set_mux,
526 .gpio_request_enable = intel_gpio_request_enable,
527 .gpio_set_direction = intel_gpio_set_direction,
528};
529
Andy Shevchenko04035f72018-09-26 17:50:26 +0300530static int intel_config_get(struct pinctrl_dev *pctldev, unsigned int pin,
Mika Westerberg7981c0012015-03-30 17:31:49 +0300531 unsigned long *config)
532{
533 struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
534 enum pin_config_param param = pinconf_to_config_param(*config);
Mika Westerberg04cc0582017-01-27 13:07:15 +0300535 const struct intel_community *community;
Mika Westerberg7981c0012015-03-30 17:31:49 +0300536 u32 value, term;
Mika Westerberge57725e2017-01-27 13:07:14 +0300537 u32 arg = 0;
Mika Westerberg7981c0012015-03-30 17:31:49 +0300538
539 if (!intel_pad_owned_by_host(pctrl, pin))
540 return -ENOTSUPP;
541
Mika Westerberg04cc0582017-01-27 13:07:15 +0300542 community = intel_get_community(pctrl, pin);
Mika Westerberg7981c0012015-03-30 17:31:49 +0300543 value = readl(intel_get_padcfg(pctrl, pin, PADCFG1));
544 term = (value & PADCFG1_TERM_MASK) >> PADCFG1_TERM_SHIFT;
545
546 switch (param) {
547 case PIN_CONFIG_BIAS_DISABLE:
548 if (term)
549 return -EINVAL;
550 break;
551
552 case PIN_CONFIG_BIAS_PULL_UP:
553 if (!term || !(value & PADCFG1_TERM_UP))
554 return -EINVAL;
555
556 switch (term) {
557 case PADCFG1_TERM_1K:
558 arg = 1000;
559 break;
560 case PADCFG1_TERM_2K:
561 arg = 2000;
562 break;
563 case PADCFG1_TERM_5K:
564 arg = 5000;
565 break;
566 case PADCFG1_TERM_20K:
567 arg = 20000;
568 break;
569 }
570
571 break;
572
573 case PIN_CONFIG_BIAS_PULL_DOWN:
574 if (!term || value & PADCFG1_TERM_UP)
575 return -EINVAL;
576
577 switch (term) {
Mika Westerberg04cc0582017-01-27 13:07:15 +0300578 case PADCFG1_TERM_1K:
579 if (!(community->features & PINCTRL_FEATURE_1K_PD))
580 return -EINVAL;
581 arg = 1000;
582 break;
Mika Westerberg7981c0012015-03-30 17:31:49 +0300583 case PADCFG1_TERM_5K:
584 arg = 5000;
585 break;
586 case PADCFG1_TERM_20K:
587 arg = 20000;
588 break;
589 }
590
591 break;
592
Mika Westerberge57725e2017-01-27 13:07:14 +0300593 case PIN_CONFIG_INPUT_DEBOUNCE: {
594 void __iomem *padcfg2;
595 u32 v;
596
597 padcfg2 = intel_get_padcfg(pctrl, pin, PADCFG2);
598 if (!padcfg2)
599 return -ENOTSUPP;
600
601 v = readl(padcfg2);
602 if (!(v & PADCFG2_DEBEN))
603 return -EINVAL;
604
605 v = (v & PADCFG2_DEBOUNCE_MASK) >> PADCFG2_DEBOUNCE_SHIFT;
Andy Shevchenko6a33a1d2019-08-07 16:41:50 +0300606 arg = BIT(v) * DEBOUNCE_PERIOD_NSEC / NSEC_PER_USEC;
Mika Westerberge57725e2017-01-27 13:07:14 +0300607
608 break;
609 }
610
Mika Westerberg7981c0012015-03-30 17:31:49 +0300611 default:
612 return -ENOTSUPP;
613 }
614
615 *config = pinconf_to_config_packed(param, arg);
616 return 0;
617}
618
Andy Shevchenko04035f72018-09-26 17:50:26 +0300619static int intel_config_set_pull(struct intel_pinctrl *pctrl, unsigned int pin,
Mika Westerberg7981c0012015-03-30 17:31:49 +0300620 unsigned long config)
621{
Andy Shevchenko04035f72018-09-26 17:50:26 +0300622 unsigned int param = pinconf_to_config_param(config);
623 unsigned int arg = pinconf_to_config_argument(config);
Mika Westerberg04cc0582017-01-27 13:07:15 +0300624 const struct intel_community *community;
Mika Westerberg7981c0012015-03-30 17:31:49 +0300625 void __iomem *padcfg1;
626 unsigned long flags;
627 int ret = 0;
628 u32 value;
629
Mika Westerberg27d90982016-06-16 11:25:36 +0300630 raw_spin_lock_irqsave(&pctrl->lock, flags);
Mika Westerberg7981c0012015-03-30 17:31:49 +0300631
Mika Westerberg04cc0582017-01-27 13:07:15 +0300632 community = intel_get_community(pctrl, pin);
Mika Westerberg7981c0012015-03-30 17:31:49 +0300633 padcfg1 = intel_get_padcfg(pctrl, pin, PADCFG1);
634 value = readl(padcfg1);
635
636 switch (param) {
637 case PIN_CONFIG_BIAS_DISABLE:
638 value &= ~(PADCFG1_TERM_MASK | PADCFG1_TERM_UP);
639 break;
640
641 case PIN_CONFIG_BIAS_PULL_UP:
642 value &= ~PADCFG1_TERM_MASK;
643
644 value |= PADCFG1_TERM_UP;
645
646 switch (arg) {
647 case 20000:
648 value |= PADCFG1_TERM_20K << PADCFG1_TERM_SHIFT;
649 break;
650 case 5000:
651 value |= PADCFG1_TERM_5K << PADCFG1_TERM_SHIFT;
652 break;
653 case 2000:
654 value |= PADCFG1_TERM_2K << PADCFG1_TERM_SHIFT;
655 break;
656 case 1000:
657 value |= PADCFG1_TERM_1K << PADCFG1_TERM_SHIFT;
658 break;
659 default:
660 ret = -EINVAL;
661 }
662
663 break;
664
665 case PIN_CONFIG_BIAS_PULL_DOWN:
666 value &= ~(PADCFG1_TERM_UP | PADCFG1_TERM_MASK);
667
668 switch (arg) {
669 case 20000:
670 value |= PADCFG1_TERM_20K << PADCFG1_TERM_SHIFT;
671 break;
672 case 5000:
673 value |= PADCFG1_TERM_5K << PADCFG1_TERM_SHIFT;
674 break;
Mika Westerberg04cc0582017-01-27 13:07:15 +0300675 case 1000:
Dan Carpenteraa1dd802017-02-07 16:20:08 +0300676 if (!(community->features & PINCTRL_FEATURE_1K_PD)) {
677 ret = -EINVAL;
678 break;
679 }
Mika Westerberg04cc0582017-01-27 13:07:15 +0300680 value |= PADCFG1_TERM_1K << PADCFG1_TERM_SHIFT;
681 break;
Mika Westerberg7981c0012015-03-30 17:31:49 +0300682 default:
683 ret = -EINVAL;
684 }
685
686 break;
687 }
688
689 if (!ret)
690 writel(value, padcfg1);
691
Mika Westerberg27d90982016-06-16 11:25:36 +0300692 raw_spin_unlock_irqrestore(&pctrl->lock, flags);
Mika Westerberg7981c0012015-03-30 17:31:49 +0300693
694 return ret;
695}
696
Andy Shevchenko04035f72018-09-26 17:50:26 +0300697static int intel_config_set_debounce(struct intel_pinctrl *pctrl,
698 unsigned int pin, unsigned int debounce)
Mika Westerberge57725e2017-01-27 13:07:14 +0300699{
700 void __iomem *padcfg0, *padcfg2;
701 unsigned long flags;
702 u32 value0, value2;
703 int ret = 0;
704
705 padcfg2 = intel_get_padcfg(pctrl, pin, PADCFG2);
706 if (!padcfg2)
707 return -ENOTSUPP;
708
709 padcfg0 = intel_get_padcfg(pctrl, pin, PADCFG0);
710
711 raw_spin_lock_irqsave(&pctrl->lock, flags);
712
713 value0 = readl(padcfg0);
714 value2 = readl(padcfg2);
715
716 /* Disable glitch filter and debouncer */
717 value0 &= ~PADCFG0_PREGFRXSEL;
718 value2 &= ~(PADCFG2_DEBEN | PADCFG2_DEBOUNCE_MASK);
719
720 if (debounce) {
721 unsigned long v;
722
Andy Shevchenko6a33a1d2019-08-07 16:41:50 +0300723 v = order_base_2(debounce * NSEC_PER_USEC / DEBOUNCE_PERIOD_NSEC);
Mika Westerberge57725e2017-01-27 13:07:14 +0300724 if (v < 3 || v > 15) {
725 ret = -EINVAL;
726 goto exit_unlock;
727 } else {
728 /* Enable glitch filter and debouncer */
729 value0 |= PADCFG0_PREGFRXSEL;
730 value2 |= v << PADCFG2_DEBOUNCE_SHIFT;
731 value2 |= PADCFG2_DEBEN;
732 }
733 }
734
735 writel(value0, padcfg0);
736 writel(value2, padcfg2);
737
738exit_unlock:
739 raw_spin_unlock_irqrestore(&pctrl->lock, flags);
740
741 return ret;
742}
743
Andy Shevchenko04035f72018-09-26 17:50:26 +0300744static int intel_config_set(struct pinctrl_dev *pctldev, unsigned int pin,
745 unsigned long *configs, unsigned int nconfigs)
Mika Westerberg7981c0012015-03-30 17:31:49 +0300746{
747 struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
748 int i, ret;
749
750 if (!intel_pad_usable(pctrl, pin))
751 return -ENOTSUPP;
752
753 for (i = 0; i < nconfigs; i++) {
754 switch (pinconf_to_config_param(configs[i])) {
755 case PIN_CONFIG_BIAS_DISABLE:
756 case PIN_CONFIG_BIAS_PULL_UP:
757 case PIN_CONFIG_BIAS_PULL_DOWN:
758 ret = intel_config_set_pull(pctrl, pin, configs[i]);
759 if (ret)
760 return ret;
761 break;
762
Mika Westerberge57725e2017-01-27 13:07:14 +0300763 case PIN_CONFIG_INPUT_DEBOUNCE:
764 ret = intel_config_set_debounce(pctrl, pin,
765 pinconf_to_config_argument(configs[i]));
766 if (ret)
767 return ret;
768 break;
769
Mika Westerberg7981c0012015-03-30 17:31:49 +0300770 default:
771 return -ENOTSUPP;
772 }
773 }
774
775 return 0;
776}
777
778static const struct pinconf_ops intel_pinconf_ops = {
779 .is_generic = true,
780 .pin_config_get = intel_config_get,
781 .pin_config_set = intel_config_set,
782};
783
784static const struct pinctrl_desc intel_pinctrl_desc = {
785 .pctlops = &intel_pinctrl_ops,
786 .pmxops = &intel_pinmux_ops,
787 .confops = &intel_pinconf_ops,
788 .owner = THIS_MODULE,
789};
790
Mika Westerberga60eac32017-11-27 16:54:43 +0300791/**
792 * intel_gpio_to_pin() - Translate from GPIO offset to pin number
793 * @pctrl: Pinctrl structure
794 * @offset: GPIO offset from gpiolib
Andy Shevchenko946ffef2018-09-26 17:43:17 +0300795 * @community: Community is filled here if not %NULL
Mika Westerberga60eac32017-11-27 16:54:43 +0300796 * @padgrp: Pad group is filled here if not %NULL
797 *
798 * When coming through gpiolib irqchip, the GPIO offset is not
799 * automatically translated to pinctrl pin number. This function can be
800 * used to find out the corresponding pinctrl pin.
801 */
Andy Shevchenko04035f72018-09-26 17:50:26 +0300802static int intel_gpio_to_pin(struct intel_pinctrl *pctrl, unsigned int offset,
Mika Westerberga60eac32017-11-27 16:54:43 +0300803 const struct intel_community **community,
804 const struct intel_padgroup **padgrp)
805{
806 int i;
807
808 for (i = 0; i < pctrl->ncommunities; i++) {
809 const struct intel_community *comm = &pctrl->communities[i];
810 int j;
811
812 for (j = 0; j < comm->ngpps; j++) {
813 const struct intel_padgroup *pgrp = &comm->gpps[j];
814
815 if (pgrp->gpio_base < 0)
816 continue;
817
818 if (offset >= pgrp->gpio_base &&
819 offset < pgrp->gpio_base + pgrp->size) {
820 int pin;
821
822 pin = pgrp->base + offset - pgrp->gpio_base;
823 if (community)
824 *community = comm;
825 if (padgrp)
826 *padgrp = pgrp;
827
828 return pin;
829 }
830 }
831 }
832
833 return -EINVAL;
834}
835
Chris Chiu6cb08802019-08-16 17:38:38 +0800836/**
837 * intel_pin_to_gpio() - Translate from pin number to GPIO offset
838 * @pctrl: Pinctrl structure
839 * @pin: pin number
840 *
841 * Translate the pin number of pinctrl to GPIO offset
842 */
Arnd Bergmann55dac432019-09-06 20:51:59 +0200843static __maybe_unused int intel_pin_to_gpio(struct intel_pinctrl *pctrl, int pin)
Chris Chiu6cb08802019-08-16 17:38:38 +0800844{
845 const struct intel_community *community;
846 const struct intel_padgroup *padgrp;
847
848 community = intel_get_community(pctrl, pin);
849 if (!community)
850 return -EINVAL;
851
852 padgrp = intel_community_get_padgroup(community, pin);
853 if (!padgrp)
854 return -EINVAL;
855
856 return pin - padgrp->base + padgrp->gpio_base;
857}
858
Andy Shevchenko04035f72018-09-26 17:50:26 +0300859static int intel_gpio_get(struct gpio_chip *chip, unsigned int offset)
Andy Shevchenko55aedef52018-07-25 15:42:08 +0300860{
Mika Westerberg96147db2018-09-18 18:36:21 +0300861 struct intel_pinctrl *pctrl = gpiochip_get_data(chip);
862 void __iomem *reg;
863 u32 padcfg0;
Andy Shevchenko55aedef52018-07-25 15:42:08 +0300864 int pin;
865
Mika Westerberg96147db2018-09-18 18:36:21 +0300866 pin = intel_gpio_to_pin(pctrl, offset, NULL, NULL);
867 if (pin < 0)
868 return -EINVAL;
869
870 reg = intel_get_padcfg(pctrl, pin, PADCFG0);
871 if (!reg)
872 return -EINVAL;
873
874 padcfg0 = readl(reg);
875 if (!(padcfg0 & PADCFG0_GPIOTXDIS))
876 return !!(padcfg0 & PADCFG0_GPIOTXSTATE);
877
878 return !!(padcfg0 & PADCFG0_GPIORXSTATE);
Andy Shevchenko55aedef52018-07-25 15:42:08 +0300879}
880
Andy Shevchenko04035f72018-09-26 17:50:26 +0300881static void intel_gpio_set(struct gpio_chip *chip, unsigned int offset,
882 int value)
Mika Westerberg96147db2018-09-18 18:36:21 +0300883{
884 struct intel_pinctrl *pctrl = gpiochip_get_data(chip);
885 unsigned long flags;
886 void __iomem *reg;
887 u32 padcfg0;
888 int pin;
889
890 pin = intel_gpio_to_pin(pctrl, offset, NULL, NULL);
891 if (pin < 0)
892 return;
893
894 reg = intel_get_padcfg(pctrl, pin, PADCFG0);
895 if (!reg)
896 return;
897
898 raw_spin_lock_irqsave(&pctrl->lock, flags);
899 padcfg0 = readl(reg);
900 if (value)
901 padcfg0 |= PADCFG0_GPIOTXSTATE;
902 else
903 padcfg0 &= ~PADCFG0_GPIOTXSTATE;
904 writel(padcfg0, reg);
905 raw_spin_unlock_irqrestore(&pctrl->lock, flags);
906}
907
908static int intel_gpio_get_direction(struct gpio_chip *chip, unsigned int offset)
909{
910 struct intel_pinctrl *pctrl = gpiochip_get_data(chip);
911 void __iomem *reg;
912 u32 padcfg0;
913 int pin;
914
915 pin = intel_gpio_to_pin(pctrl, offset, NULL, NULL);
916 if (pin < 0)
917 return -EINVAL;
918
919 reg = intel_get_padcfg(pctrl, pin, PADCFG0);
920 if (!reg)
921 return -EINVAL;
922
923 padcfg0 = readl(reg);
924
925 if (padcfg0 & PADCFG0_PMODE_MASK)
926 return -EINVAL;
927
928 return !!(padcfg0 & PADCFG0_GPIOTXDIS);
929}
930
Andy Shevchenko04035f72018-09-26 17:50:26 +0300931static int intel_gpio_direction_input(struct gpio_chip *chip, unsigned int offset)
Mika Westerberg96147db2018-09-18 18:36:21 +0300932{
933 return pinctrl_gpio_direction_input(chip->base + offset);
934}
935
Andy Shevchenko04035f72018-09-26 17:50:26 +0300936static int intel_gpio_direction_output(struct gpio_chip *chip, unsigned int offset,
Mika Westerberg96147db2018-09-18 18:36:21 +0300937 int value)
938{
939 intel_gpio_set(chip, offset, value);
940 return pinctrl_gpio_direction_output(chip->base + offset);
941}
942
943static const struct gpio_chip intel_gpio_chip = {
944 .owner = THIS_MODULE,
945 .request = gpiochip_generic_request,
946 .free = gpiochip_generic_free,
947 .get_direction = intel_gpio_get_direction,
948 .direction_input = intel_gpio_direction_input,
949 .direction_output = intel_gpio_direction_output,
950 .get = intel_gpio_get,
951 .set = intel_gpio_set,
952 .set_config = gpiochip_generic_config,
953};
954
Mika Westerberg7981c0012015-03-30 17:31:49 +0300955static void intel_gpio_irq_ack(struct irq_data *d)
956{
957 struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
Linus Walleijacfd4c62015-12-08 00:18:59 +0100958 struct intel_pinctrl *pctrl = gpiochip_get_data(gc);
Mika Westerberg7981c0012015-03-30 17:31:49 +0300959 const struct intel_community *community;
Mika Westerberga60eac32017-11-27 16:54:43 +0300960 const struct intel_padgroup *padgrp;
961 int pin;
Mika Westerberg7981c0012015-03-30 17:31:49 +0300962
Mika Westerberga60eac32017-11-27 16:54:43 +0300963 pin = intel_gpio_to_pin(pctrl, irqd_to_hwirq(d), &community, &padgrp);
964 if (pin >= 0) {
Andy Shevchenko04035f72018-09-26 17:50:26 +0300965 unsigned int gpp, gpp_offset, is_offset;
Mika Westerberg7981c0012015-03-30 17:31:49 +0300966
Mika Westerberg919eb472017-06-06 16:18:17 +0300967 gpp = padgrp->reg_num;
968 gpp_offset = padgroup_offset(padgrp, pin);
Mika Westerbergcf769bd2017-10-23 15:40:25 +0300969 is_offset = community->is_offset + gpp * 4;
Mika Westerberg919eb472017-06-06 16:18:17 +0300970
971 raw_spin_lock(&pctrl->lock);
Mika Westerbergcf769bd2017-10-23 15:40:25 +0300972 writel(BIT(gpp_offset), community->regs + is_offset);
Mika Westerberg919eb472017-06-06 16:18:17 +0300973 raw_spin_unlock(&pctrl->lock);
Mika Westerberg7981c0012015-03-30 17:31:49 +0300974 }
Mika Westerberg7981c0012015-03-30 17:31:49 +0300975}
976
977static void intel_gpio_irq_mask_unmask(struct irq_data *d, bool mask)
978{
979 struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
Linus Walleijacfd4c62015-12-08 00:18:59 +0100980 struct intel_pinctrl *pctrl = gpiochip_get_data(gc);
Mika Westerberg7981c0012015-03-30 17:31:49 +0300981 const struct intel_community *community;
Mika Westerberga60eac32017-11-27 16:54:43 +0300982 const struct intel_padgroup *padgrp;
983 int pin;
Mika Westerberg7981c0012015-03-30 17:31:49 +0300984
Mika Westerberga60eac32017-11-27 16:54:43 +0300985 pin = intel_gpio_to_pin(pctrl, irqd_to_hwirq(d), &community, &padgrp);
986 if (pin >= 0) {
Andy Shevchenko04035f72018-09-26 17:50:26 +0300987 unsigned int gpp, gpp_offset;
Mika Westerberg919eb472017-06-06 16:18:17 +0300988 unsigned long flags;
Kai-Heng Feng670784f2019-04-30 16:37:53 +0800989 void __iomem *reg, *is;
Mika Westerberg7981c0012015-03-30 17:31:49 +0300990 u32 value;
991
Mika Westerberg919eb472017-06-06 16:18:17 +0300992 gpp = padgrp->reg_num;
993 gpp_offset = padgroup_offset(padgrp, pin);
994
Mika Westerberg7981c0012015-03-30 17:31:49 +0300995 reg = community->regs + community->ie_offset + gpp * 4;
Kai-Heng Feng670784f2019-04-30 16:37:53 +0800996 is = community->regs + community->is_offset + gpp * 4;
Mika Westerberg919eb472017-06-06 16:18:17 +0300997
998 raw_spin_lock_irqsave(&pctrl->lock, flags);
Kai-Heng Feng670784f2019-04-30 16:37:53 +0800999
1000 /* Clear interrupt status first to avoid unexpected interrupt */
1001 writel(BIT(gpp_offset), is);
1002
Mika Westerberg7981c0012015-03-30 17:31:49 +03001003 value = readl(reg);
1004 if (mask)
1005 value &= ~BIT(gpp_offset);
1006 else
1007 value |= BIT(gpp_offset);
1008 writel(value, reg);
Mika Westerberg919eb472017-06-06 16:18:17 +03001009 raw_spin_unlock_irqrestore(&pctrl->lock, flags);
Mika Westerberg7981c0012015-03-30 17:31:49 +03001010 }
Mika Westerberg7981c0012015-03-30 17:31:49 +03001011}
1012
1013static void intel_gpio_irq_mask(struct irq_data *d)
1014{
1015 intel_gpio_irq_mask_unmask(d, true);
1016}
1017
1018static void intel_gpio_irq_unmask(struct irq_data *d)
1019{
1020 intel_gpio_irq_mask_unmask(d, false);
1021}
1022
Andy Shevchenko04035f72018-09-26 17:50:26 +03001023static int intel_gpio_irq_type(struct irq_data *d, unsigned int type)
Mika Westerberg7981c0012015-03-30 17:31:49 +03001024{
1025 struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
Linus Walleijacfd4c62015-12-08 00:18:59 +01001026 struct intel_pinctrl *pctrl = gpiochip_get_data(gc);
Andy Shevchenko04035f72018-09-26 17:50:26 +03001027 unsigned int pin = intel_gpio_to_pin(pctrl, irqd_to_hwirq(d), NULL, NULL);
Mika Westerberg7981c0012015-03-30 17:31:49 +03001028 unsigned long flags;
1029 void __iomem *reg;
1030 u32 value;
1031
1032 reg = intel_get_padcfg(pctrl, pin, PADCFG0);
1033 if (!reg)
1034 return -EINVAL;
1035
Mika Westerberg4341e8a2015-10-21 13:08:44 +03001036 /*
1037 * If the pin is in ACPI mode it is still usable as a GPIO but it
1038 * cannot be used as IRQ because GPI_IS status bit will not be
1039 * updated by the host controller hardware.
1040 */
1041 if (intel_pad_acpi_mode(pctrl, pin)) {
1042 dev_warn(pctrl->dev, "pin %u cannot be used as IRQ\n", pin);
1043 return -EPERM;
1044 }
1045
Mika Westerberg27d90982016-06-16 11:25:36 +03001046 raw_spin_lock_irqsave(&pctrl->lock, flags);
Mika Westerberg7981c0012015-03-30 17:31:49 +03001047
Mika Westerbergf5a26ac2017-11-29 16:25:44 +03001048 intel_gpio_set_gpio_mode(reg);
1049
Mika Westerberg7981c0012015-03-30 17:31:49 +03001050 value = readl(reg);
1051
1052 value &= ~(PADCFG0_RXEVCFG_MASK | PADCFG0_RXINV);
1053
1054 if ((type & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH) {
1055 value |= PADCFG0_RXEVCFG_EDGE_BOTH << PADCFG0_RXEVCFG_SHIFT;
1056 } else if (type & IRQ_TYPE_EDGE_FALLING) {
1057 value |= PADCFG0_RXEVCFG_EDGE << PADCFG0_RXEVCFG_SHIFT;
1058 value |= PADCFG0_RXINV;
1059 } else if (type & IRQ_TYPE_EDGE_RISING) {
1060 value |= PADCFG0_RXEVCFG_EDGE << PADCFG0_RXEVCFG_SHIFT;
Qipeng Zhabf380cf2016-03-17 02:15:25 +08001061 } else if (type & IRQ_TYPE_LEVEL_MASK) {
1062 if (type & IRQ_TYPE_LEVEL_LOW)
1063 value |= PADCFG0_RXINV;
Mika Westerberg7981c0012015-03-30 17:31:49 +03001064 } else {
1065 value |= PADCFG0_RXEVCFG_DISABLED << PADCFG0_RXEVCFG_SHIFT;
1066 }
1067
1068 writel(value, reg);
1069
1070 if (type & IRQ_TYPE_EDGE_BOTH)
Thomas Gleixnerfc756bc2015-06-23 15:52:45 +02001071 irq_set_handler_locked(d, handle_edge_irq);
Mika Westerberg7981c0012015-03-30 17:31:49 +03001072 else if (type & IRQ_TYPE_LEVEL_MASK)
Thomas Gleixnerfc756bc2015-06-23 15:52:45 +02001073 irq_set_handler_locked(d, handle_level_irq);
Mika Westerberg7981c0012015-03-30 17:31:49 +03001074
Mika Westerberg27d90982016-06-16 11:25:36 +03001075 raw_spin_unlock_irqrestore(&pctrl->lock, flags);
Mika Westerberg7981c0012015-03-30 17:31:49 +03001076
1077 return 0;
1078}
1079
1080static int intel_gpio_irq_wake(struct irq_data *d, unsigned int on)
1081{
1082 struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
Linus Walleijacfd4c62015-12-08 00:18:59 +01001083 struct intel_pinctrl *pctrl = gpiochip_get_data(gc);
Andy Shevchenko04035f72018-09-26 17:50:26 +03001084 unsigned int pin = intel_gpio_to_pin(pctrl, irqd_to_hwirq(d), NULL, NULL);
Mika Westerberg7981c0012015-03-30 17:31:49 +03001085
Mika Westerberg7981c0012015-03-30 17:31:49 +03001086 if (on)
Nilesh Bacchewar01dabe92016-09-21 16:35:23 -07001087 enable_irq_wake(pctrl->irq);
Mika Westerberg7981c0012015-03-30 17:31:49 +03001088 else
Nilesh Bacchewar01dabe92016-09-21 16:35:23 -07001089 disable_irq_wake(pctrl->irq);
Andy Shevchenko9a520fd2016-07-08 14:30:46 +03001090
Mika Westerberg7981c0012015-03-30 17:31:49 +03001091 dev_dbg(pctrl->dev, "%sable wake for pin %u\n", on ? "en" : "dis", pin);
1092 return 0;
1093}
1094
Mika Westerberg193b40c2015-10-21 13:08:43 +03001095static irqreturn_t intel_gpio_community_irq_handler(struct intel_pinctrl *pctrl,
Mika Westerberg7981c0012015-03-30 17:31:49 +03001096 const struct intel_community *community)
1097{
Mika Westerberg193b40c2015-10-21 13:08:43 +03001098 struct gpio_chip *gc = &pctrl->chip;
1099 irqreturn_t ret = IRQ_NONE;
Mika Westerberg7981c0012015-03-30 17:31:49 +03001100 int gpp;
1101
1102 for (gpp = 0; gpp < community->ngpps; gpp++) {
Mika Westerberg919eb472017-06-06 16:18:17 +03001103 const struct intel_padgroup *padgrp = &community->gpps[gpp];
Mika Westerberg7981c0012015-03-30 17:31:49 +03001104 unsigned long pending, enabled, gpp_offset;
1105
Mika Westerbergcf769bd2017-10-23 15:40:25 +03001106 pending = readl(community->regs + community->is_offset +
1107 padgrp->reg_num * 4);
Mika Westerberg7981c0012015-03-30 17:31:49 +03001108 enabled = readl(community->regs + community->ie_offset +
Mika Westerberg919eb472017-06-06 16:18:17 +03001109 padgrp->reg_num * 4);
Mika Westerberg7981c0012015-03-30 17:31:49 +03001110
1111 /* Only interrupts that are enabled */
1112 pending &= enabled;
1113
Mika Westerberg919eb472017-06-06 16:18:17 +03001114 for_each_set_bit(gpp_offset, &pending, padgrp->size) {
Mika Westerberga60eac32017-11-27 16:54:43 +03001115 unsigned irq;
Mika Westerberg7981c0012015-03-30 17:31:49 +03001116
Thierry Redingf0fbe7b2017-11-07 19:15:47 +01001117 irq = irq_find_mapping(gc->irq.domain,
Mika Westerberga60eac32017-11-27 16:54:43 +03001118 padgrp->gpio_base + gpp_offset);
Mika Westerberg7981c0012015-03-30 17:31:49 +03001119 generic_handle_irq(irq);
Mika Westerberg193b40c2015-10-21 13:08:43 +03001120
1121 ret |= IRQ_HANDLED;
Mika Westerberg7981c0012015-03-30 17:31:49 +03001122 }
1123 }
Mika Westerberg193b40c2015-10-21 13:08:43 +03001124
1125 return ret;
Mika Westerberg7981c0012015-03-30 17:31:49 +03001126}
1127
Mika Westerberg193b40c2015-10-21 13:08:43 +03001128static irqreturn_t intel_gpio_irq(int irq, void *data)
Mika Westerberg7981c0012015-03-30 17:31:49 +03001129{
Mika Westerberg193b40c2015-10-21 13:08:43 +03001130 const struct intel_community *community;
1131 struct intel_pinctrl *pctrl = data;
1132 irqreturn_t ret = IRQ_NONE;
Mika Westerberg7981c0012015-03-30 17:31:49 +03001133 int i;
1134
Mika Westerberg7981c0012015-03-30 17:31:49 +03001135 /* Need to check all communities for pending interrupts */
Mika Westerberg193b40c2015-10-21 13:08:43 +03001136 for (i = 0; i < pctrl->ncommunities; i++) {
1137 community = &pctrl->communities[i];
1138 ret |= intel_gpio_community_irq_handler(pctrl, community);
1139 }
Mika Westerberg7981c0012015-03-30 17:31:49 +03001140
Mika Westerberg193b40c2015-10-21 13:08:43 +03001141 return ret;
Mika Westerberg7981c0012015-03-30 17:31:49 +03001142}
1143
Mika Westerberga60eac32017-11-27 16:54:43 +03001144static int intel_gpio_add_pin_ranges(struct intel_pinctrl *pctrl,
1145 const struct intel_community *community)
1146{
Colin Ian King33b6cb52017-12-04 17:08:15 +00001147 int ret = 0, i;
Mika Westerberga60eac32017-11-27 16:54:43 +03001148
1149 for (i = 0; i < community->ngpps; i++) {
1150 const struct intel_padgroup *gpp = &community->gpps[i];
1151
1152 if (gpp->gpio_base < 0)
1153 continue;
1154
1155 ret = gpiochip_add_pin_range(&pctrl->chip, dev_name(pctrl->dev),
1156 gpp->gpio_base, gpp->base,
1157 gpp->size);
1158 if (ret)
1159 return ret;
1160 }
1161
1162 return ret;
1163}
1164
1165static unsigned intel_gpio_ngpio(const struct intel_pinctrl *pctrl)
1166{
1167 const struct intel_community *community;
Andy Shevchenko04035f72018-09-26 17:50:26 +03001168 unsigned int ngpio = 0;
Mika Westerberga60eac32017-11-27 16:54:43 +03001169 int i, j;
1170
1171 for (i = 0; i < pctrl->ncommunities; i++) {
1172 community = &pctrl->communities[i];
1173 for (j = 0; j < community->ngpps; j++) {
1174 const struct intel_padgroup *gpp = &community->gpps[j];
1175
1176 if (gpp->gpio_base < 0)
1177 continue;
1178
1179 if (gpp->gpio_base + gpp->size > ngpio)
1180 ngpio = gpp->gpio_base + gpp->size;
1181 }
1182 }
1183
1184 return ngpio;
1185}
1186
Mika Westerberg7981c0012015-03-30 17:31:49 +03001187static int intel_gpio_probe(struct intel_pinctrl *pctrl, int irq)
1188{
Mika Westerberga60eac32017-11-27 16:54:43 +03001189 int ret, i;
Mika Westerberg7981c0012015-03-30 17:31:49 +03001190
1191 pctrl->chip = intel_gpio_chip;
1192
Andy Shevchenko57ff2df2019-09-16 17:47:51 +03001193 /* Setup GPIO chip */
Mika Westerberga60eac32017-11-27 16:54:43 +03001194 pctrl->chip.ngpio = intel_gpio_ngpio(pctrl);
Mika Westerberg7981c0012015-03-30 17:31:49 +03001195 pctrl->chip.label = dev_name(pctrl->dev);
Linus Walleij58383c782015-11-04 09:56:26 +01001196 pctrl->chip.parent = pctrl->dev;
Mika Westerberg7981c0012015-03-30 17:31:49 +03001197 pctrl->chip.base = -1;
Nilesh Bacchewar01dabe92016-09-21 16:35:23 -07001198 pctrl->irq = irq;
Mika Westerberg7981c0012015-03-30 17:31:49 +03001199
Andy Shevchenko57ff2df2019-09-16 17:47:51 +03001200 /* Setup IRQ chip */
1201 pctrl->irqchip.name = dev_name(pctrl->dev);
1202 pctrl->irqchip.irq_ack = intel_gpio_irq_ack;
1203 pctrl->irqchip.irq_mask = intel_gpio_irq_mask;
1204 pctrl->irqchip.irq_unmask = intel_gpio_irq_unmask;
1205 pctrl->irqchip.irq_set_type = intel_gpio_irq_type;
1206 pctrl->irqchip.irq_set_wake = intel_gpio_irq_wake;
1207 pctrl->irqchip.flags = IRQCHIP_MASK_ON_SUSPEND;
1208
Mika Westerbergf25c3aa2017-01-10 17:31:57 +03001209 ret = devm_gpiochip_add_data(pctrl->dev, &pctrl->chip, pctrl);
Mika Westerberg7981c0012015-03-30 17:31:49 +03001210 if (ret) {
1211 dev_err(pctrl->dev, "failed to register gpiochip\n");
1212 return ret;
1213 }
1214
Mika Westerberga60eac32017-11-27 16:54:43 +03001215 for (i = 0; i < pctrl->ncommunities; i++) {
1216 struct intel_community *community = &pctrl->communities[i];
1217
1218 ret = intel_gpio_add_pin_ranges(pctrl, community);
1219 if (ret) {
1220 dev_err(pctrl->dev, "failed to add GPIO pin range\n");
1221 return ret;
1222 }
Mika Westerberg193b40c2015-10-21 13:08:43 +03001223 }
1224
1225 /*
1226 * We need to request the interrupt here (instead of providing chip
1227 * to the irq directly) because on some platforms several GPIO
1228 * controllers share the same interrupt line.
1229 */
Mika Westerberg1a7d1cb2016-06-16 11:25:37 +03001230 ret = devm_request_irq(pctrl->dev, irq, intel_gpio_irq,
1231 IRQF_SHARED | IRQF_NO_THREAD,
Mika Westerberg193b40c2015-10-21 13:08:43 +03001232 dev_name(pctrl->dev), pctrl);
1233 if (ret) {
1234 dev_err(pctrl->dev, "failed to request interrupt\n");
Mika Westerbergf25c3aa2017-01-10 17:31:57 +03001235 return ret;
Mika Westerberg7981c0012015-03-30 17:31:49 +03001236 }
1237
Andy Shevchenko57ff2df2019-09-16 17:47:51 +03001238 ret = gpiochip_irqchip_add(&pctrl->chip, &pctrl->irqchip, 0,
Andy Shevchenko3ae02c12016-11-25 13:31:16 +02001239 handle_bad_irq, IRQ_TYPE_NONE);
Mika Westerberg7981c0012015-03-30 17:31:49 +03001240 if (ret) {
1241 dev_err(pctrl->dev, "failed to add irqchip\n");
Mika Westerbergf25c3aa2017-01-10 17:31:57 +03001242 return ret;
Mika Westerberg7981c0012015-03-30 17:31:49 +03001243 }
1244
Andy Shevchenko57ff2df2019-09-16 17:47:51 +03001245 gpiochip_set_chained_irqchip(&pctrl->chip, &pctrl->irqchip, irq, NULL);
Mika Westerberg7981c0012015-03-30 17:31:49 +03001246 return 0;
1247}
1248
Mika Westerberg919eb472017-06-06 16:18:17 +03001249static int intel_pinctrl_add_padgroups(struct intel_pinctrl *pctrl,
1250 struct intel_community *community)
1251{
1252 struct intel_padgroup *gpps;
Andy Shevchenko04035f72018-09-26 17:50:26 +03001253 unsigned int npins = community->npins;
1254 unsigned int padown_num = 0;
Mika Westerberg919eb472017-06-06 16:18:17 +03001255 size_t ngpps, i;
1256
1257 if (community->gpps)
1258 ngpps = community->ngpps;
1259 else
1260 ngpps = DIV_ROUND_UP(community->npins, community->gpp_size);
1261
1262 gpps = devm_kcalloc(pctrl->dev, ngpps, sizeof(*gpps), GFP_KERNEL);
1263 if (!gpps)
1264 return -ENOMEM;
1265
1266 for (i = 0; i < ngpps; i++) {
1267 if (community->gpps) {
1268 gpps[i] = community->gpps[i];
1269 } else {
Andy Shevchenko04035f72018-09-26 17:50:26 +03001270 unsigned int gpp_size = community->gpp_size;
Mika Westerberg919eb472017-06-06 16:18:17 +03001271
1272 gpps[i].reg_num = i;
1273 gpps[i].base = community->pin_base + i * gpp_size;
1274 gpps[i].size = min(gpp_size, npins);
1275 npins -= gpps[i].size;
1276 }
1277
1278 if (gpps[i].size > 32)
1279 return -EINVAL;
1280
Mika Westerberga60eac32017-11-27 16:54:43 +03001281 if (!gpps[i].gpio_base)
1282 gpps[i].gpio_base = gpps[i].base;
1283
Mika Westerberg919eb472017-06-06 16:18:17 +03001284 gpps[i].padown_num = padown_num;
1285
1286 /*
1287 * In older hardware the number of padown registers per
1288 * group is fixed regardless of the group size.
1289 */
1290 if (community->gpp_num_padown_regs)
1291 padown_num += community->gpp_num_padown_regs;
1292 else
1293 padown_num += DIV_ROUND_UP(gpps[i].size * 4, 32);
1294 }
1295
1296 community->ngpps = ngpps;
1297 community->gpps = gpps;
1298
1299 return 0;
1300}
1301
Mika Westerberg7981c0012015-03-30 17:31:49 +03001302static int intel_pinctrl_pm_init(struct intel_pinctrl *pctrl)
1303{
1304#ifdef CONFIG_PM_SLEEP
1305 const struct intel_pinctrl_soc_data *soc = pctrl->soc;
1306 struct intel_community_context *communities;
1307 struct intel_pad_context *pads;
1308 int i;
1309
1310 pads = devm_kcalloc(pctrl->dev, soc->npins, sizeof(*pads), GFP_KERNEL);
1311 if (!pads)
1312 return -ENOMEM;
1313
1314 communities = devm_kcalloc(pctrl->dev, pctrl->ncommunities,
1315 sizeof(*communities), GFP_KERNEL);
1316 if (!communities)
1317 return -ENOMEM;
1318
1319
1320 for (i = 0; i < pctrl->ncommunities; i++) {
1321 struct intel_community *community = &pctrl->communities[i];
Chris Chiua0a5f762019-04-15 13:53:58 +08001322 u32 *intmask, *hostown;
Mika Westerberg7981c0012015-03-30 17:31:49 +03001323
1324 intmask = devm_kcalloc(pctrl->dev, community->ngpps,
1325 sizeof(*intmask), GFP_KERNEL);
1326 if (!intmask)
1327 return -ENOMEM;
1328
1329 communities[i].intmask = intmask;
Chris Chiua0a5f762019-04-15 13:53:58 +08001330
1331 hostown = devm_kcalloc(pctrl->dev, community->ngpps,
1332 sizeof(*hostown), GFP_KERNEL);
1333 if (!hostown)
1334 return -ENOMEM;
1335
1336 communities[i].hostown = hostown;
Mika Westerberg7981c0012015-03-30 17:31:49 +03001337 }
1338
1339 pctrl->context.pads = pads;
1340 pctrl->context.communities = communities;
1341#endif
1342
1343 return 0;
1344}
1345
Andy Shevchenko0dd519e2018-10-17 19:10:27 +03001346static int intel_pinctrl_probe(struct platform_device *pdev,
1347 const struct intel_pinctrl_soc_data *soc_data)
Mika Westerberg7981c0012015-03-30 17:31:49 +03001348{
1349 struct intel_pinctrl *pctrl;
1350 int i, ret, irq;
1351
1352 if (!soc_data)
1353 return -EINVAL;
1354
1355 pctrl = devm_kzalloc(&pdev->dev, sizeof(*pctrl), GFP_KERNEL);
1356 if (!pctrl)
1357 return -ENOMEM;
1358
1359 pctrl->dev = &pdev->dev;
1360 pctrl->soc = soc_data;
Mika Westerberg27d90982016-06-16 11:25:36 +03001361 raw_spin_lock_init(&pctrl->lock);
Mika Westerberg7981c0012015-03-30 17:31:49 +03001362
1363 /*
1364 * Make a copy of the communities which we can use to hold pointers
1365 * to the registers.
1366 */
1367 pctrl->ncommunities = pctrl->soc->ncommunities;
1368 pctrl->communities = devm_kcalloc(&pdev->dev, pctrl->ncommunities,
1369 sizeof(*pctrl->communities), GFP_KERNEL);
1370 if (!pctrl->communities)
1371 return -ENOMEM;
1372
1373 for (i = 0; i < pctrl->ncommunities; i++) {
1374 struct intel_community *community = &pctrl->communities[i];
Mika Westerberg7981c0012015-03-30 17:31:49 +03001375 void __iomem *regs;
1376 u32 padbar;
1377
1378 *community = pctrl->soc->communities[i];
1379
Andy Shevchenko9d5b6a92019-07-03 17:44:20 +03001380 regs = devm_platform_ioremap_resource(pdev, community->barno);
Mika Westerberg7981c0012015-03-30 17:31:49 +03001381 if (IS_ERR(regs))
1382 return PTR_ERR(regs);
1383
Mika Westerberge57725e2017-01-27 13:07:14 +03001384 /*
1385 * Determine community features based on the revision if
1386 * not specified already.
1387 */
1388 if (!community->features) {
1389 u32 rev;
1390
1391 rev = (readl(regs + REVID) & REVID_MASK) >> REVID_SHIFT;
Mika Westerberg04cc0582017-01-27 13:07:15 +03001392 if (rev >= 0x94) {
Mika Westerberge57725e2017-01-27 13:07:14 +03001393 community->features |= PINCTRL_FEATURE_DEBOUNCE;
Mika Westerberg04cc0582017-01-27 13:07:15 +03001394 community->features |= PINCTRL_FEATURE_1K_PD;
1395 }
Mika Westerberge57725e2017-01-27 13:07:14 +03001396 }
1397
Mika Westerberg7981c0012015-03-30 17:31:49 +03001398 /* Read offset of the pad configuration registers */
1399 padbar = readl(regs + PADBAR);
1400
1401 community->regs = regs;
1402 community->pad_regs = regs + padbar;
Mika Westerberg919eb472017-06-06 16:18:17 +03001403
1404 ret = intel_pinctrl_add_padgroups(pctrl, community);
1405 if (ret)
1406 return ret;
Mika Westerberg7981c0012015-03-30 17:31:49 +03001407 }
1408
1409 irq = platform_get_irq(pdev, 0);
Stephen Boyd4e73d022019-07-30 11:15:34 -07001410 if (irq < 0)
Mika Westerberg7981c0012015-03-30 17:31:49 +03001411 return irq;
Mika Westerberg7981c0012015-03-30 17:31:49 +03001412
1413 ret = intel_pinctrl_pm_init(pctrl);
1414 if (ret)
1415 return ret;
1416
1417 pctrl->pctldesc = intel_pinctrl_desc;
1418 pctrl->pctldesc.name = dev_name(&pdev->dev);
1419 pctrl->pctldesc.pins = pctrl->soc->pins;
1420 pctrl->pctldesc.npins = pctrl->soc->npins;
1421
Laxman Dewangan54d46cd2016-02-28 14:42:47 +05301422 pctrl->pctldev = devm_pinctrl_register(&pdev->dev, &pctrl->pctldesc,
1423 pctrl);
Masahiro Yamada323de9e2015-06-09 13:01:16 +09001424 if (IS_ERR(pctrl->pctldev)) {
Mika Westerberg7981c0012015-03-30 17:31:49 +03001425 dev_err(&pdev->dev, "failed to register pinctrl driver\n");
Masahiro Yamada323de9e2015-06-09 13:01:16 +09001426 return PTR_ERR(pctrl->pctldev);
Mika Westerberg7981c0012015-03-30 17:31:49 +03001427 }
1428
1429 ret = intel_gpio_probe(pctrl, irq);
Laxman Dewangan54d46cd2016-02-28 14:42:47 +05301430 if (ret)
Mika Westerberg7981c0012015-03-30 17:31:49 +03001431 return ret;
Mika Westerberg7981c0012015-03-30 17:31:49 +03001432
1433 platform_set_drvdata(pdev, pctrl);
1434
1435 return 0;
1436}
Mika Westerberg7981c0012015-03-30 17:31:49 +03001437
Andy Shevchenko70c263c2018-08-30 19:27:40 +03001438int intel_pinctrl_probe_by_hid(struct platform_device *pdev)
1439{
1440 const struct intel_pinctrl_soc_data *data;
1441
1442 data = device_get_match_data(&pdev->dev);
1443 return intel_pinctrl_probe(pdev, data);
1444}
1445EXPORT_SYMBOL_GPL(intel_pinctrl_probe_by_hid);
1446
Andy Shevchenko924cf802018-08-30 19:27:36 +03001447int intel_pinctrl_probe_by_uid(struct platform_device *pdev)
1448{
1449 const struct intel_pinctrl_soc_data *data = NULL;
1450 const struct intel_pinctrl_soc_data **table;
1451 struct acpi_device *adev;
1452 unsigned int i;
1453
1454 adev = ACPI_COMPANION(&pdev->dev);
1455 if (adev) {
1456 const void *match = device_get_match_data(&pdev->dev);
1457
1458 table = (const struct intel_pinctrl_soc_data **)match;
1459 for (i = 0; table[i]; i++) {
1460 if (!strcmp(adev->pnp.unique_id, table[i]->uid)) {
1461 data = table[i];
1462 break;
1463 }
1464 }
1465 } else {
1466 const struct platform_device_id *id;
1467
1468 id = platform_get_device_id(pdev);
1469 if (!id)
1470 return -ENODEV;
1471
1472 table = (const struct intel_pinctrl_soc_data **)id->driver_data;
1473 data = table[pdev->id];
1474 }
Andy Shevchenko924cf802018-08-30 19:27:36 +03001475
1476 return intel_pinctrl_probe(pdev, data);
1477}
1478EXPORT_SYMBOL_GPL(intel_pinctrl_probe_by_uid);
1479
Mika Westerberg7981c0012015-03-30 17:31:49 +03001480#ifdef CONFIG_PM_SLEEP
Andy Shevchenko04035f72018-09-26 17:50:26 +03001481static bool intel_pinctrl_should_save(struct intel_pinctrl *pctrl, unsigned int pin)
Mika Westerbergc538b942016-10-10 16:39:31 +03001482{
1483 const struct pin_desc *pd = pin_desc_get(pctrl->pctldev, pin);
1484
1485 if (!pd || !intel_pad_usable(pctrl, pin))
1486 return false;
1487
1488 /*
1489 * Only restore the pin if it is actually in use by the kernel (or
1490 * by userspace). It is possible that some pins are used by the
1491 * BIOS during resume and those are not always locked down so leave
1492 * them alone.
1493 */
1494 if (pd->mux_owner || pd->gpio_owner ||
Chris Chiu6cb08802019-08-16 17:38:38 +08001495 gpiochip_line_is_irq(&pctrl->chip, intel_pin_to_gpio(pctrl, pin)))
Mika Westerbergc538b942016-10-10 16:39:31 +03001496 return true;
1497
1498 return false;
1499}
1500
Binbin Wu2fef3272019-04-08 18:49:26 +08001501int intel_pinctrl_suspend_noirq(struct device *dev)
Mika Westerberg7981c0012015-03-30 17:31:49 +03001502{
Wolfram Sangcb035d72018-10-21 22:00:29 +02001503 struct intel_pinctrl *pctrl = dev_get_drvdata(dev);
Mika Westerberg7981c0012015-03-30 17:31:49 +03001504 struct intel_community_context *communities;
1505 struct intel_pad_context *pads;
1506 int i;
1507
1508 pads = pctrl->context.pads;
1509 for (i = 0; i < pctrl->soc->npins; i++) {
1510 const struct pinctrl_pin_desc *desc = &pctrl->soc->pins[i];
Mika Westerberge57725e2017-01-27 13:07:14 +03001511 void __iomem *padcfg;
Mika Westerberg7981c0012015-03-30 17:31:49 +03001512 u32 val;
1513
Mika Westerbergc538b942016-10-10 16:39:31 +03001514 if (!intel_pinctrl_should_save(pctrl, desc->number))
Mika Westerberg7981c0012015-03-30 17:31:49 +03001515 continue;
1516
1517 val = readl(intel_get_padcfg(pctrl, desc->number, PADCFG0));
1518 pads[i].padcfg0 = val & ~PADCFG0_GPIORXSTATE;
1519 val = readl(intel_get_padcfg(pctrl, desc->number, PADCFG1));
1520 pads[i].padcfg1 = val;
Mika Westerberge57725e2017-01-27 13:07:14 +03001521
1522 padcfg = intel_get_padcfg(pctrl, desc->number, PADCFG2);
1523 if (padcfg)
1524 pads[i].padcfg2 = readl(padcfg);
Mika Westerberg7981c0012015-03-30 17:31:49 +03001525 }
1526
1527 communities = pctrl->context.communities;
1528 for (i = 0; i < pctrl->ncommunities; i++) {
1529 struct intel_community *community = &pctrl->communities[i];
1530 void __iomem *base;
Andy Shevchenko04035f72018-09-26 17:50:26 +03001531 unsigned int gpp;
Mika Westerberg7981c0012015-03-30 17:31:49 +03001532
1533 base = community->regs + community->ie_offset;
1534 for (gpp = 0; gpp < community->ngpps; gpp++)
1535 communities[i].intmask[gpp] = readl(base + gpp * 4);
Chris Chiua0a5f762019-04-15 13:53:58 +08001536
1537 base = community->regs + community->hostown_offset;
1538 for (gpp = 0; gpp < community->ngpps; gpp++)
1539 communities[i].hostown[gpp] = readl(base + gpp * 4);
Mika Westerberg7981c0012015-03-30 17:31:49 +03001540 }
1541
1542 return 0;
1543}
Binbin Wu2fef3272019-04-08 18:49:26 +08001544EXPORT_SYMBOL_GPL(intel_pinctrl_suspend_noirq);
Mika Westerberg7981c0012015-03-30 17:31:49 +03001545
Mika Westerbergf487bbf2015-10-13 17:51:25 +03001546static void intel_gpio_irq_init(struct intel_pinctrl *pctrl)
1547{
1548 size_t i;
1549
1550 for (i = 0; i < pctrl->ncommunities; i++) {
1551 const struct intel_community *community;
1552 void __iomem *base;
Andy Shevchenko04035f72018-09-26 17:50:26 +03001553 unsigned int gpp;
Mika Westerbergf487bbf2015-10-13 17:51:25 +03001554
1555 community = &pctrl->communities[i];
1556 base = community->regs;
1557
1558 for (gpp = 0; gpp < community->ngpps; gpp++) {
1559 /* Mask and clear all interrupts */
1560 writel(0, base + community->ie_offset + gpp * 4);
Mika Westerbergcf769bd2017-10-23 15:40:25 +03001561 writel(0xffff, base + community->is_offset + gpp * 4);
Mika Westerbergf487bbf2015-10-13 17:51:25 +03001562 }
1563 }
1564}
1565
Chris Chiua0a5f762019-04-15 13:53:58 +08001566static u32
1567intel_gpio_is_requested(struct gpio_chip *chip, int base, unsigned int size)
1568{
1569 u32 requested = 0;
1570 unsigned int i;
1571
1572 for (i = 0; i < size; i++)
1573 if (gpiochip_is_requested(chip, base + i))
1574 requested |= BIT(i);
1575
1576 return requested;
1577}
1578
1579static u32
1580intel_gpio_update_pad_mode(void __iomem *hostown, u32 mask, u32 value)
1581{
Andy Shevchenko5f61d952019-04-28 20:19:06 +03001582 u32 curr, updated;
Chris Chiua0a5f762019-04-15 13:53:58 +08001583
Andy Shevchenko5f61d952019-04-28 20:19:06 +03001584 curr = readl(hostown);
1585 updated = (curr & ~mask) | (value & mask);
Chris Chiua0a5f762019-04-15 13:53:58 +08001586 writel(updated, hostown);
Andy Shevchenko5f61d952019-04-28 20:19:06 +03001587
Chris Chiua0a5f762019-04-15 13:53:58 +08001588 return curr;
1589}
1590
Binbin Wu2fef3272019-04-08 18:49:26 +08001591int intel_pinctrl_resume_noirq(struct device *dev)
Mika Westerberg7981c0012015-03-30 17:31:49 +03001592{
Wolfram Sangcb035d72018-10-21 22:00:29 +02001593 struct intel_pinctrl *pctrl = dev_get_drvdata(dev);
Mika Westerberg7981c0012015-03-30 17:31:49 +03001594 const struct intel_community_context *communities;
1595 const struct intel_pad_context *pads;
1596 int i;
1597
1598 /* Mask all interrupts */
1599 intel_gpio_irq_init(pctrl);
1600
1601 pads = pctrl->context.pads;
1602 for (i = 0; i < pctrl->soc->npins; i++) {
1603 const struct pinctrl_pin_desc *desc = &pctrl->soc->pins[i];
1604 void __iomem *padcfg;
1605 u32 val;
1606
Mika Westerbergc538b942016-10-10 16:39:31 +03001607 if (!intel_pinctrl_should_save(pctrl, desc->number))
Mika Westerberg7981c0012015-03-30 17:31:49 +03001608 continue;
1609
1610 padcfg = intel_get_padcfg(pctrl, desc->number, PADCFG0);
1611 val = readl(padcfg) & ~PADCFG0_GPIORXSTATE;
1612 if (val != pads[i].padcfg0) {
1613 writel(pads[i].padcfg0, padcfg);
1614 dev_dbg(dev, "restored pin %u padcfg0 %#08x\n",
1615 desc->number, readl(padcfg));
1616 }
1617
1618 padcfg = intel_get_padcfg(pctrl, desc->number, PADCFG1);
1619 val = readl(padcfg);
1620 if (val != pads[i].padcfg1) {
1621 writel(pads[i].padcfg1, padcfg);
1622 dev_dbg(dev, "restored pin %u padcfg1 %#08x\n",
1623 desc->number, readl(padcfg));
1624 }
Mika Westerberge57725e2017-01-27 13:07:14 +03001625
1626 padcfg = intel_get_padcfg(pctrl, desc->number, PADCFG2);
1627 if (padcfg) {
1628 val = readl(padcfg);
1629 if (val != pads[i].padcfg2) {
1630 writel(pads[i].padcfg2, padcfg);
1631 dev_dbg(dev, "restored pin %u padcfg2 %#08x\n",
1632 desc->number, readl(padcfg));
1633 }
1634 }
Mika Westerberg7981c0012015-03-30 17:31:49 +03001635 }
1636
1637 communities = pctrl->context.communities;
1638 for (i = 0; i < pctrl->ncommunities; i++) {
1639 struct intel_community *community = &pctrl->communities[i];
1640 void __iomem *base;
Andy Shevchenko04035f72018-09-26 17:50:26 +03001641 unsigned int gpp;
Mika Westerberg7981c0012015-03-30 17:31:49 +03001642
1643 base = community->regs + community->ie_offset;
1644 for (gpp = 0; gpp < community->ngpps; gpp++) {
1645 writel(communities[i].intmask[gpp], base + gpp * 4);
1646 dev_dbg(dev, "restored mask %d/%u %#08x\n", i, gpp,
1647 readl(base + gpp * 4));
1648 }
Chris Chiua0a5f762019-04-15 13:53:58 +08001649
1650 base = community->regs + community->hostown_offset;
1651 for (gpp = 0; gpp < community->ngpps; gpp++) {
1652 const struct intel_padgroup *padgrp = &community->gpps[gpp];
1653 u32 requested = 0, value = 0;
1654 u32 saved = communities[i].hostown[gpp];
1655
1656 if (padgrp->gpio_base < 0)
1657 continue;
1658
1659 requested = intel_gpio_is_requested(&pctrl->chip,
1660 padgrp->gpio_base, padgrp->size);
1661 value = intel_gpio_update_pad_mode(base + gpp * 4,
1662 requested, saved);
1663 if ((value ^ saved) & requested) {
1664 dev_warn(dev, "restore hostown %d/%u %#8x->%#8x\n",
1665 i, gpp, value, saved);
1666 }
1667 }
Mika Westerberg7981c0012015-03-30 17:31:49 +03001668 }
1669
1670 return 0;
1671}
Binbin Wu2fef3272019-04-08 18:49:26 +08001672EXPORT_SYMBOL_GPL(intel_pinctrl_resume_noirq);
Mika Westerberg7981c0012015-03-30 17:31:49 +03001673#endif
1674
1675MODULE_AUTHOR("Mathias Nyman <mathias.nyman@linux.intel.com>");
1676MODULE_AUTHOR("Mika Westerberg <mika.westerberg@linux.intel.com>");
1677MODULE_DESCRIPTION("Intel pinctrl/GPIO core driver");
1678MODULE_LICENSE("GPL v2");