gpio-intel-mid.c 10.5 KB
Newer Older
Grant Likely's avatar
Grant Likely committed
1
/*
2
 * Intel MID GPIO driver
Grant Likely's avatar
Grant Likely committed
3
 *
4
 * Copyright (c) 2008-2014,2016 Intel Corporation.
5 6 7 8 9 10 11 12 13 14 15 16 17
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

/* Supports:
 * Moorestown platform Langwell chip.
Alek Du's avatar
Alek Du committed
18
 * Medfield platform Penwell chip.
19
 * Clovertrail platform Cloverview chip.
20 21 22 23
 */

#include <linux/delay.h>
#include <linux/init.h>
24
#include <linux/interrupt.h>
25
#include <linux/io.h>
26
#include <linux/gpio/driver.h>
27 28 29 30
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/platform_device.h>
31
#include <linux/pm_runtime.h>
32 33
#include <linux/slab.h>
#include <linux/stddef.h>
34

35 36
#define INTEL_MID_IRQ_TYPE_EDGE		(1 << 0)
#define INTEL_MID_IRQ_TYPE_LEVEL	(1 << 1)
37

Alek Du's avatar
Alek Du committed
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
/*
 * Langwell chip has 64 pins and thus there are 2 32bit registers to control
 * each feature, while Penwell chip has 96 pins for each block, and need 3 32bit
 * registers to control them, so we only define the order here instead of a
 * structure, to get a bit offset for a pin (use GPDR as an example):
 *
 * nreg = ngpio / 32;
 * reg = offset / 32;
 * bit = offset % 32;
 * reg_addr = reg_base + GPDR * nreg * 4 + reg * 4;
 *
 * so the bit of reg_addr is to control pin offset's GPDR feature
*/

enum GPIO_REG {
	GPLR = 0,	/* pin level read-only */
	GPDR,		/* pin direction */
	GPSR,		/* pin set */
	GPCR,		/* pin clear */
	GRER,		/* rising edge detect */
	GFER,		/* falling edge detect */
	GEDR,		/* edge detect result */
60
	GAFR,		/* alt function */
61 62
};

63 64
/* intel_mid gpio driver data */
struct intel_mid_gpio_ddata {
65 66 67 68
	u16 ngpio;		/* number of gpio pins */
	u32 chip_irq_type;	/* chip interrupt type */
};

69
struct intel_mid_gpio {
70
	struct gpio_chip		chip;
71
	void __iomem			*reg_base;
72
	spinlock_t			lock;
73
	struct pci_dev			*pdev;
74 75
};

Alek Du's avatar
Alek Du committed
76
static void __iomem *gpio_reg(struct gpio_chip *chip, unsigned offset,
77
			      enum GPIO_REG reg_type)
78
{
79
	struct intel_mid_gpio *priv = gpiochip_get_data(chip);
Alek Du's avatar
Alek Du committed
80
	unsigned nreg = chip->ngpio / 32;
81
	u8 reg = offset / 32;
Alek Du's avatar
Alek Du committed
82

83
	return priv->reg_base + reg_type * nreg * 4 + reg * 4;
Alek Du's avatar
Alek Du committed
84 85
}

86 87 88
static void __iomem *gpio_reg_2bit(struct gpio_chip *chip, unsigned offset,
				   enum GPIO_REG reg_type)
{
89
	struct intel_mid_gpio *priv = gpiochip_get_data(chip);
90 91 92
	unsigned nreg = chip->ngpio / 32;
	u8 reg = offset / 16;

93
	return priv->reg_base + reg_type * nreg * 4 + reg * 4;
94 95
}

96
static int intel_gpio_request(struct gpio_chip *chip, unsigned offset)
97 98 99 100 101 102 103 104 105 106 107 108
{
	void __iomem *gafr = gpio_reg_2bit(chip, offset, GAFR);
	u32 value = readl(gafr);
	int shift = (offset % 16) << 1, af = (value >> shift) & 3;

	if (af) {
		value &= ~(3 << shift);
		writel(value, gafr);
	}
	return 0;
}

109
static int intel_gpio_get(struct gpio_chip *chip, unsigned offset)
Alek Du's avatar
Alek Du committed
110 111
{
	void __iomem *gplr = gpio_reg(chip, offset, GPLR);
112

113
	return !!(readl(gplr) & BIT(offset % 32));
114 115
}

116
static void intel_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
117 118 119 120
{
	void __iomem *gpsr, *gpcr;

	if (value) {
Alek Du's avatar
Alek Du committed
121
		gpsr = gpio_reg(chip, offset, GPSR);
122 123
		writel(BIT(offset % 32), gpsr);
	} else {
Alek Du's avatar
Alek Du committed
124
		gpcr = gpio_reg(chip, offset, GPCR);
125 126 127 128
		writel(BIT(offset % 32), gpcr);
	}
}

129
static int intel_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
130
{
131
	struct intel_mid_gpio *priv = gpiochip_get_data(chip);
Alek Du's avatar
Alek Du committed
132
	void __iomem *gpdr = gpio_reg(chip, offset, GPDR);
133 134 135
	u32 value;
	unsigned long flags;

136 137
	if (priv->pdev)
		pm_runtime_get(&priv->pdev->dev);
138

139
	spin_lock_irqsave(&priv->lock, flags);
140 141 142
	value = readl(gpdr);
	value &= ~BIT(offset % 32);
	writel(value, gpdr);
143
	spin_unlock_irqrestore(&priv->lock, flags);
144

145 146
	if (priv->pdev)
		pm_runtime_put(&priv->pdev->dev);
147

148 149 150
	return 0;
}

151
static int intel_gpio_direction_output(struct gpio_chip *chip,
152 153
			unsigned offset, int value)
{
154
	struct intel_mid_gpio *priv = gpiochip_get_data(chip);
Alek Du's avatar
Alek Du committed
155
	void __iomem *gpdr = gpio_reg(chip, offset, GPDR);
156 157
	unsigned long flags;

158
	intel_gpio_set(chip, offset, value);
159

160 161
	if (priv->pdev)
		pm_runtime_get(&priv->pdev->dev);
162

163
	spin_lock_irqsave(&priv->lock, flags);
164
	value = readl(gpdr);
165
	value |= BIT(offset % 32);
166
	writel(value, gpdr);
167
	spin_unlock_irqrestore(&priv->lock, flags);
168

169 170
	if (priv->pdev)
		pm_runtime_put(&priv->pdev->dev);
171

172 173 174
	return 0;
}

175
static int intel_mid_irq_type(struct irq_data *d, unsigned type)
176
{
177
	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
178
	struct intel_mid_gpio *priv = gpiochip_get_data(gc);
179
	u32 gpio = irqd_to_hwirq(d);
180 181
	unsigned long flags;
	u32 value;
182 183
	void __iomem *grer = gpio_reg(&priv->chip, gpio, GRER);
	void __iomem *gfer = gpio_reg(&priv->chip, gpio, GFER);
184

185
	if (gpio >= priv->chip.ngpio)
186
		return -EINVAL;
187

188 189
	if (priv->pdev)
		pm_runtime_get(&priv->pdev->dev);
190

191
	spin_lock_irqsave(&priv->lock, flags);
192 193 194 195 196 197 198 199 200 201 202
	if (type & IRQ_TYPE_EDGE_RISING)
		value = readl(grer) | BIT(gpio % 32);
	else
		value = readl(grer) & (~BIT(gpio % 32));
	writel(value, grer);

	if (type & IRQ_TYPE_EDGE_FALLING)
		value = readl(gfer) | BIT(gpio % 32);
	else
		value = readl(gfer) & (~BIT(gpio % 32));
	writel(value, gfer);
203
	spin_unlock_irqrestore(&priv->lock, flags);
204

205 206
	if (priv->pdev)
		pm_runtime_put(&priv->pdev->dev);
207

208
	return 0;
209
}
210

211
static void intel_mid_irq_unmask(struct irq_data *d)
212
{
213
}
214

215
static void intel_mid_irq_mask(struct irq_data *d)
216
{
217
}
218

219 220 221 222 223
static struct irq_chip intel_mid_irqchip = {
	.name		= "INTEL_MID-GPIO",
	.irq_mask	= intel_mid_irq_mask,
	.irq_unmask	= intel_mid_irq_unmask,
	.irq_set_type	= intel_mid_irq_type,
224 225
};

226
static const struct intel_mid_gpio_ddata gpio_lincroft = {
227 228 229
	.ngpio = 64,
};

230
static const struct intel_mid_gpio_ddata gpio_penwell_aon = {
231
	.ngpio = 96,
232
	.chip_irq_type = INTEL_MID_IRQ_TYPE_EDGE,
233 234
};

235
static const struct intel_mid_gpio_ddata gpio_penwell_core = {
236
	.ngpio = 96,
237
	.chip_irq_type = INTEL_MID_IRQ_TYPE_EDGE,
238 239
};

240
static const struct intel_mid_gpio_ddata gpio_cloverview_aon = {
241
	.ngpio = 96,
242
	.chip_irq_type = INTEL_MID_IRQ_TYPE_EDGE | INTEL_MID_IRQ_TYPE_LEVEL,
243 244
};

245
static const struct intel_mid_gpio_ddata gpio_cloverview_core = {
246
	.ngpio = 96,
247
	.chip_irq_type = INTEL_MID_IRQ_TYPE_EDGE,
248 249
};

250
static const struct pci_device_id intel_gpio_ids[] = {
251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276
	{
		/* Lincroft */
		PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x080f),
		.driver_data = (kernel_ulong_t)&gpio_lincroft,
	},
	{
		/* Penwell AON */
		PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081f),
		.driver_data = (kernel_ulong_t)&gpio_penwell_aon,
	},
	{
		/* Penwell Core */
		PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081a),
		.driver_data = (kernel_ulong_t)&gpio_penwell_core,
	},
	{
		/* Cloverview Aon */
		PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x08eb),
		.driver_data = (kernel_ulong_t)&gpio_cloverview_aon,
	},
	{
		/* Cloverview Core */
		PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x08f7),
		.driver_data = (kernel_ulong_t)&gpio_cloverview_core,
	},
	{ 0 }
277
};
278
MODULE_DEVICE_TABLE(pci, intel_gpio_ids);
279

280
static void intel_mid_irq_handler(struct irq_desc *desc)
281
{
282
	struct gpio_chip *gc = irq_desc_get_handler_data(desc);
283
	struct intel_mid_gpio *priv = gpiochip_get_data(gc);
284 285
	struct irq_data *data = irq_desc_get_irq_data(desc);
	struct irq_chip *chip = irq_data_get_irq_chip(data);
286
	u32 base, gpio, mask;
287
	unsigned long pending;
288 289 290
	void __iomem *gedr;

	/* check GPIO controller to check which pin triggered the interrupt */
291 292
	for (base = 0; base < priv->chip.ngpio; base += 32) {
		gedr = gpio_reg(&priv->chip, base, GEDR);
293
		while ((pending = readl(gedr))) {
294
			gpio = __ffs(pending);
295 296 297
			mask = BIT(gpio);
			/* Clear before handling so we can't lose an edge */
			writel(mask, gedr);
298
			generic_handle_irq(irq_find_mapping(gc->irq.domain,
299
							    base + gpio));
300
		}
301
	}
302

303
	chip->irq_eoi(data);
304 305
}

306
static void intel_mid_irq_init_hw(struct intel_mid_gpio *priv)
307 308 309 310
{
	void __iomem *reg;
	unsigned base;

311
	for (base = 0; base < priv->chip.ngpio; base += 32) {
312
		/* Clear the rising-edge detect register */
313
		reg = gpio_reg(&priv->chip, base, GRER);
314 315
		writel(0, reg);
		/* Clear the falling-edge detect register */
316
		reg = gpio_reg(&priv->chip, base, GFER);
317 318
		writel(0, reg);
		/* Clear the edge detect status register */
319
		reg = gpio_reg(&priv->chip, base, GEDR);
320 321 322 323
		writel(~0, reg);
	}
}

324
static int __maybe_unused intel_gpio_runtime_idle(struct device *dev)
325
{
326 327
	int err = pm_schedule_suspend(dev, 500);
	return err ?: -EBUSY;
328 329
}

330 331
static const struct dev_pm_ops intel_gpio_pm_ops = {
	SET_RUNTIME_PM_OPS(NULL, NULL, intel_gpio_runtime_idle)
332 333
};

334
static int intel_gpio_probe(struct pci_dev *pdev,
335
			  const struct pci_device_id *id)
336
{
337
	void __iomem *base;
338
	struct intel_mid_gpio *priv;
339
	u32 gpio_base;
340
	u32 irq_base;
341
	int retval;
342 343
	struct intel_mid_gpio_ddata *ddata =
				(struct intel_mid_gpio_ddata *)id->driver_data;
344

345
	retval = pcim_enable_device(pdev);
346
	if (retval)
347
		return retval;
348

349
	retval = pcim_iomap_regions(pdev, 1 << 0 | 1 << 1, pci_name(pdev));
350
	if (retval) {
351 352
		dev_err(&pdev->dev, "I/O memory mapping error\n");
		return retval;
353
	}
354

355 356
	base = pcim_iomap_table(pdev)[1];

357 358 359
	irq_base = readl(base);
	gpio_base = readl(sizeof(u32) + base);

360
	/* release the IO mapping, since we already get the info from bar1 */
361
	pcim_iounmap_regions(pdev, 1 << 1);
362

363 364
	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
	if (!priv) {
365
		dev_err(&pdev->dev, "can't allocate chip data\n");
366
		return -ENOMEM;
367
	}
368

369 370
	priv->reg_base = pcim_iomap_table(pdev)[0];
	priv->chip.label = dev_name(&pdev->dev);
371
	priv->chip.parent = &pdev->dev;
372 373 374 375 376 377 378
	priv->chip.request = intel_gpio_request;
	priv->chip.direction_input = intel_gpio_direction_input;
	priv->chip.direction_output = intel_gpio_direction_output;
	priv->chip.get = intel_gpio_get;
	priv->chip.set = intel_gpio_set;
	priv->chip.base = gpio_base;
	priv->chip.ngpio = ddata->ngpio;
379
	priv->chip.can_sleep = false;
380 381 382 383 384
	priv->pdev = pdev;

	spin_lock_init(&priv->lock);

	pci_set_drvdata(pdev, priv);
385
	retval = devm_gpiochip_add_data(&pdev->dev, &priv->chip, priv);
386
	if (retval) {
387
		dev_err(&pdev->dev, "gpiochip_add error %d\n", retval);
388
		return retval;
389
	}
390

391 392 393 394 395 396 397 398 399 400 401
	retval = gpiochip_irqchip_add(&priv->chip,
				      &intel_mid_irqchip,
				      irq_base,
				      handle_simple_irq,
				      IRQ_TYPE_NONE);
	if (retval) {
		dev_err(&pdev->dev,
			"could not connect irqchip to gpiochip\n");
		return retval;
	}

402
	intel_mid_irq_init_hw(priv);
403

404 405 406 407
	gpiochip_set_chained_irqchip(&priv->chip,
				     &intel_mid_irqchip,
				     pdev->irq,
				     intel_mid_irq_handler);
408

409 410 411
	pm_runtime_put_noidle(&pdev->dev);
	pm_runtime_allow(&pdev->dev);

412
	return 0;
413 414
}

415 416 417 418
static struct pci_driver intel_gpio_driver = {
	.name		= "intel_mid_gpio",
	.id_table	= intel_gpio_ids,
	.probe		= intel_gpio_probe,
419
	.driver		= {
420
		.pm	= &intel_gpio_pm_ops,
421
	},
422 423
};

424
builtin_pci_driver(intel_gpio_driver);