443 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright (C) 2008, 2009 Provigent Ltd.4 *5 * Author: Baruch Siach <baruch@tkos.co.il>6 *7 * Driver for the ARM PrimeCell(tm) General Purpose Input/Output (PL061)8 *9 * Data sheet: ARM DDI 0190B, September 200010 */11#include <linux/amba/bus.h>12#include <linux/bitops.h>13#include <linux/device.h>14#include <linux/errno.h>15#include <linux/gpio/driver.h>16#include <linux/init.h>17#include <linux/interrupt.h>18#include <linux/io.h>19#include <linux/ioport.h>20#include <linux/irq.h>21#include <linux/irqchip/chained_irq.h>22#include <linux/module.h>23#include <linux/pinctrl/consumer.h>24#include <linux/pm.h>25#include <linux/seq_file.h>26#include <linux/slab.h>27#include <linux/spinlock.h>28 29#define GPIODIR 0x40030#define GPIOIS 0x40431#define GPIOIBE 0x40832#define GPIOIEV 0x40C33#define GPIOIE 0x41034#define GPIORIS 0x41435#define GPIOMIS 0x41836#define GPIOIC 0x41C37 38#define PL061_GPIO_NR 839 40#ifdef CONFIG_PM41struct pl061_context_save_regs {42 u8 gpio_data;43 u8 gpio_dir;44 u8 gpio_is;45 u8 gpio_ibe;46 u8 gpio_iev;47 u8 gpio_ie;48};49#endif50 51struct pl061 {52 raw_spinlock_t lock;53 54 void __iomem *base;55 struct gpio_chip gc;56 int parent_irq;57 58#ifdef CONFIG_PM59 struct pl061_context_save_regs csave_regs;60#endif61};62 63static int pl061_get_direction(struct gpio_chip *gc, unsigned offset)64{65 struct pl061 *pl061 = gpiochip_get_data(gc);66 67 if (readb(pl061->base + GPIODIR) & BIT(offset))68 return GPIO_LINE_DIRECTION_OUT;69 70 return GPIO_LINE_DIRECTION_IN;71}72 73static int pl061_direction_input(struct gpio_chip *gc, unsigned offset)74{75 struct pl061 *pl061 = gpiochip_get_data(gc);76 unsigned long flags;77 unsigned char gpiodir;78 79 raw_spin_lock_irqsave(&pl061->lock, flags);80 gpiodir = readb(pl061->base + GPIODIR);81 gpiodir &= ~(BIT(offset));82 writeb(gpiodir, pl061->base + GPIODIR);83 raw_spin_unlock_irqrestore(&pl061->lock, flags);84 85 return 0;86}87 88static int pl061_direction_output(struct gpio_chip *gc, unsigned offset,89 int value)90{91 struct pl061 *pl061 = gpiochip_get_data(gc);92 unsigned long flags;93 unsigned char gpiodir;94 95 raw_spin_lock_irqsave(&pl061->lock, flags);96 writeb(!!value << offset, pl061->base + (BIT(offset + 2)));97 gpiodir = readb(pl061->base + GPIODIR);98 gpiodir |= BIT(offset);99 writeb(gpiodir, pl061->base + GPIODIR);100 101 /*102 * gpio value is set again, because pl061 doesn't allow to set value of103 * a gpio pin before configuring it in OUT mode.104 */105 writeb(!!value << offset, pl061->base + (BIT(offset + 2)));106 raw_spin_unlock_irqrestore(&pl061->lock, flags);107 108 return 0;109}110 111static int pl061_get_value(struct gpio_chip *gc, unsigned offset)112{113 struct pl061 *pl061 = gpiochip_get_data(gc);114 115 return !!readb(pl061->base + (BIT(offset + 2)));116}117 118static void pl061_set_value(struct gpio_chip *gc, unsigned offset, int value)119{120 struct pl061 *pl061 = gpiochip_get_data(gc);121 122 writeb(!!value << offset, pl061->base + (BIT(offset + 2)));123}124 125static int pl061_irq_type(struct irq_data *d, unsigned trigger)126{127 struct gpio_chip *gc = irq_data_get_irq_chip_data(d);128 struct pl061 *pl061 = gpiochip_get_data(gc);129 int offset = irqd_to_hwirq(d);130 unsigned long flags;131 u8 gpiois, gpioibe, gpioiev;132 u8 bit = BIT(offset);133 134 if (offset < 0 || offset >= PL061_GPIO_NR)135 return -EINVAL;136 137 if ((trigger & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) &&138 (trigger & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)))139 {140 dev_err(gc->parent,141 "trying to configure line %d for both level and edge "142 "detection, choose one!\n",143 offset);144 return -EINVAL;145 }146 147 148 raw_spin_lock_irqsave(&pl061->lock, flags);149 150 gpioiev = readb(pl061->base + GPIOIEV);151 gpiois = readb(pl061->base + GPIOIS);152 gpioibe = readb(pl061->base + GPIOIBE);153 154 if (trigger & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) {155 bool polarity = trigger & IRQ_TYPE_LEVEL_HIGH;156 157 /* Disable edge detection */158 gpioibe &= ~bit;159 /* Enable level detection */160 gpiois |= bit;161 /* Select polarity */162 if (polarity)163 gpioiev |= bit;164 else165 gpioiev &= ~bit;166 irq_set_handler_locked(d, handle_level_irq);167 dev_dbg(gc->parent, "line %d: IRQ on %s level\n",168 offset,169 polarity ? "HIGH" : "LOW");170 } else if ((trigger & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH) {171 /* Disable level detection */172 gpiois &= ~bit;173 /* Select both edges, setting this makes GPIOEV be ignored */174 gpioibe |= bit;175 irq_set_handler_locked(d, handle_edge_irq);176 dev_dbg(gc->parent, "line %d: IRQ on both edges\n", offset);177 } else if ((trigger & IRQ_TYPE_EDGE_RISING) ||178 (trigger & IRQ_TYPE_EDGE_FALLING)) {179 bool rising = trigger & IRQ_TYPE_EDGE_RISING;180 181 /* Disable level detection */182 gpiois &= ~bit;183 /* Clear detection on both edges */184 gpioibe &= ~bit;185 /* Select edge */186 if (rising)187 gpioiev |= bit;188 else189 gpioiev &= ~bit;190 irq_set_handler_locked(d, handle_edge_irq);191 dev_dbg(gc->parent, "line %d: IRQ on %s edge\n",192 offset,193 rising ? "RISING" : "FALLING");194 } else {195 /* No trigger: disable everything */196 gpiois &= ~bit;197 gpioibe &= ~bit;198 gpioiev &= ~bit;199 irq_set_handler_locked(d, handle_bad_irq);200 dev_warn(gc->parent, "no trigger selected for line %d\n",201 offset);202 }203 204 writeb(gpiois, pl061->base + GPIOIS);205 writeb(gpioibe, pl061->base + GPIOIBE);206 writeb(gpioiev, pl061->base + GPIOIEV);207 208 raw_spin_unlock_irqrestore(&pl061->lock, flags);209 210 return 0;211}212 213static void pl061_irq_handler(struct irq_desc *desc)214{215 unsigned long pending;216 int offset;217 struct gpio_chip *gc = irq_desc_get_handler_data(desc);218 struct pl061 *pl061 = gpiochip_get_data(gc);219 struct irq_chip *irqchip = irq_desc_get_chip(desc);220 221 chained_irq_enter(irqchip, desc);222 223 pending = readb(pl061->base + GPIOMIS);224 if (pending) {225 for_each_set_bit(offset, &pending, PL061_GPIO_NR)226 generic_handle_domain_irq(gc->irq.domain,227 offset);228 }229 230 chained_irq_exit(irqchip, desc);231}232 233static void pl061_irq_mask(struct irq_data *d)234{235 struct gpio_chip *gc = irq_data_get_irq_chip_data(d);236 struct pl061 *pl061 = gpiochip_get_data(gc);237 u8 mask = BIT(irqd_to_hwirq(d) % PL061_GPIO_NR);238 u8 gpioie;239 240 raw_spin_lock(&pl061->lock);241 gpioie = readb(pl061->base + GPIOIE) & ~mask;242 writeb(gpioie, pl061->base + GPIOIE);243 raw_spin_unlock(&pl061->lock);244 245 gpiochip_disable_irq(gc, d->hwirq);246}247 248static void pl061_irq_unmask(struct irq_data *d)249{250 struct gpio_chip *gc = irq_data_get_irq_chip_data(d);251 struct pl061 *pl061 = gpiochip_get_data(gc);252 u8 mask = BIT(irqd_to_hwirq(d) % PL061_GPIO_NR);253 u8 gpioie;254 255 gpiochip_enable_irq(gc, d->hwirq);256 257 raw_spin_lock(&pl061->lock);258 gpioie = readb(pl061->base + GPIOIE) | mask;259 writeb(gpioie, pl061->base + GPIOIE);260 raw_spin_unlock(&pl061->lock);261}262 263/**264 * pl061_irq_ack() - ACK an edge IRQ265 * @d: IRQ data for this IRQ266 *267 * This gets called from the edge IRQ handler to ACK the edge IRQ268 * in the GPIOIC (interrupt-clear) register. For level IRQs this is269 * not needed: these go away when the level signal goes away.270 */271static void pl061_irq_ack(struct irq_data *d)272{273 struct gpio_chip *gc = irq_data_get_irq_chip_data(d);274 struct pl061 *pl061 = gpiochip_get_data(gc);275 u8 mask = BIT(irqd_to_hwirq(d) % PL061_GPIO_NR);276 277 raw_spin_lock(&pl061->lock);278 writeb(mask, pl061->base + GPIOIC);279 raw_spin_unlock(&pl061->lock);280}281 282static int pl061_irq_set_wake(struct irq_data *d, unsigned int state)283{284 struct gpio_chip *gc = irq_data_get_irq_chip_data(d);285 struct pl061 *pl061 = gpiochip_get_data(gc);286 287 return irq_set_irq_wake(pl061->parent_irq, state);288}289 290static void pl061_irq_print_chip(struct irq_data *data, struct seq_file *p)291{292 struct gpio_chip *gc = irq_data_get_irq_chip_data(data);293 294 seq_printf(p, dev_name(gc->parent));295}296 297static const struct irq_chip pl061_irq_chip = {298 .irq_ack = pl061_irq_ack,299 .irq_mask = pl061_irq_mask,300 .irq_unmask = pl061_irq_unmask,301 .irq_set_type = pl061_irq_type,302 .irq_set_wake = pl061_irq_set_wake,303 .irq_print_chip = pl061_irq_print_chip,304 .flags = IRQCHIP_IMMUTABLE,305 GPIOCHIP_IRQ_RESOURCE_HELPERS,306};307 308static int pl061_probe(struct amba_device *adev, const struct amba_id *id)309{310 struct device *dev = &adev->dev;311 struct pl061 *pl061;312 struct gpio_irq_chip *girq;313 int ret, irq;314 315 pl061 = devm_kzalloc(dev, sizeof(*pl061), GFP_KERNEL);316 if (pl061 == NULL)317 return -ENOMEM;318 319 pl061->base = devm_ioremap_resource(dev, &adev->res);320 if (IS_ERR(pl061->base))321 return PTR_ERR(pl061->base);322 323 raw_spin_lock_init(&pl061->lock);324 pl061->gc.request = gpiochip_generic_request;325 pl061->gc.free = gpiochip_generic_free;326 pl061->gc.base = -1;327 pl061->gc.get_direction = pl061_get_direction;328 pl061->gc.direction_input = pl061_direction_input;329 pl061->gc.direction_output = pl061_direction_output;330 pl061->gc.get = pl061_get_value;331 pl061->gc.set = pl061_set_value;332 pl061->gc.ngpio = PL061_GPIO_NR;333 pl061->gc.label = dev_name(dev);334 pl061->gc.parent = dev;335 pl061->gc.owner = THIS_MODULE;336 337 /*338 * irq_chip support339 */340 writeb(0, pl061->base + GPIOIE); /* disable irqs */341 irq = adev->irq[0];342 if (!irq)343 dev_warn(&adev->dev, "IRQ support disabled\n");344 pl061->parent_irq = irq;345 346 girq = &pl061->gc.irq;347 gpio_irq_chip_set_chip(girq, &pl061_irq_chip);348 girq->parent_handler = pl061_irq_handler;349 girq->num_parents = 1;350 girq->parents = devm_kcalloc(dev, 1, sizeof(*girq->parents),351 GFP_KERNEL);352 if (!girq->parents)353 return -ENOMEM;354 girq->parents[0] = irq;355 girq->default_type = IRQ_TYPE_NONE;356 girq->handler = handle_bad_irq;357 358 ret = devm_gpiochip_add_data(dev, &pl061->gc, pl061);359 if (ret)360 return ret;361 362 amba_set_drvdata(adev, pl061);363 dev_info(dev, "PL061 GPIO chip registered\n");364 365 return 0;366}367 368#ifdef CONFIG_PM369static int pl061_suspend(struct device *dev)370{371 struct pl061 *pl061 = dev_get_drvdata(dev);372 int offset;373 374 pl061->csave_regs.gpio_data = 0;375 pl061->csave_regs.gpio_dir = readb(pl061->base + GPIODIR);376 pl061->csave_regs.gpio_is = readb(pl061->base + GPIOIS);377 pl061->csave_regs.gpio_ibe = readb(pl061->base + GPIOIBE);378 pl061->csave_regs.gpio_iev = readb(pl061->base + GPIOIEV);379 pl061->csave_regs.gpio_ie = readb(pl061->base + GPIOIE);380 381 for (offset = 0; offset < PL061_GPIO_NR; offset++) {382 if (pl061->csave_regs.gpio_dir & (BIT(offset)))383 pl061->csave_regs.gpio_data |=384 pl061_get_value(&pl061->gc, offset) << offset;385 }386 387 return 0;388}389 390static int pl061_resume(struct device *dev)391{392 struct pl061 *pl061 = dev_get_drvdata(dev);393 int offset;394 395 for (offset = 0; offset < PL061_GPIO_NR; offset++) {396 if (pl061->csave_regs.gpio_dir & (BIT(offset)))397 pl061_direction_output(&pl061->gc, offset,398 pl061->csave_regs.gpio_data &399 (BIT(offset)));400 else401 pl061_direction_input(&pl061->gc, offset);402 }403 404 writeb(pl061->csave_regs.gpio_is, pl061->base + GPIOIS);405 writeb(pl061->csave_regs.gpio_ibe, pl061->base + GPIOIBE);406 writeb(pl061->csave_regs.gpio_iev, pl061->base + GPIOIEV);407 writeb(pl061->csave_regs.gpio_ie, pl061->base + GPIOIE);408 409 return 0;410}411 412static const struct dev_pm_ops pl061_dev_pm_ops = {413 .suspend = pl061_suspend,414 .resume = pl061_resume,415 .freeze = pl061_suspend,416 .restore = pl061_resume,417};418#endif419 420static const struct amba_id pl061_ids[] = {421 {422 .id = 0x00041061,423 .mask = 0x000fffff,424 },425 { 0, 0 },426};427MODULE_DEVICE_TABLE(amba, pl061_ids);428 429static struct amba_driver pl061_gpio_driver = {430 .drv = {431 .name = "pl061_gpio",432#ifdef CONFIG_PM433 .pm = &pl061_dev_pm_ops,434#endif435 },436 .id_table = pl061_ids,437 .probe = pl061_probe,438};439module_amba_driver(pl061_gpio_driver);440 441MODULE_DESCRIPTION("Driver for the ARM PrimeCell(tm) General Purpose Input/Output (PL061)");442MODULE_LICENSE("GPL v2");443