182c29810SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 2c103de24SGrant Likely /* 3c103de24SGrant Likely * Timberdale FPGA GPIO driver 452ad9053SPaul Gortmaker * Author: Mocean Laboratories 5c103de24SGrant Likely * Copyright (c) 2009 Intel Corporation 6c103de24SGrant Likely */ 7c103de24SGrant Likely 8c103de24SGrant Likely /* Supports: 9c103de24SGrant Likely * Timberdale FPGA GPIO 10c103de24SGrant Likely */ 11c103de24SGrant Likely 1252ad9053SPaul Gortmaker #include <linux/init.h> 1350fe83a3SLinus Walleij #include <linux/gpio/driver.h> 14c103de24SGrant Likely #include <linux/platform_device.h> 15c103de24SGrant Likely #include <linux/irq.h> 16c103de24SGrant Likely #include <linux/io.h> 17c103de24SGrant Likely #include <linux/timb_gpio.h> 18c103de24SGrant Likely #include <linux/interrupt.h> 19c103de24SGrant Likely #include <linux/slab.h> 20c103de24SGrant Likely 21c103de24SGrant Likely #define DRIVER_NAME "timb-gpio" 22c103de24SGrant Likely 23c103de24SGrant Likely #define TGPIOVAL 0x00 24c103de24SGrant Likely #define TGPIODIR 0x04 25c103de24SGrant Likely #define TGPIO_IER 0x08 26c103de24SGrant Likely #define TGPIO_ISR 0x0c 27c103de24SGrant Likely #define TGPIO_IPR 0x10 28c103de24SGrant Likely #define TGPIO_ICR 0x14 29c103de24SGrant Likely #define TGPIO_FLR 0x18 30c103de24SGrant Likely #define TGPIO_LVR 0x1c 31c103de24SGrant Likely #define TGPIO_VER 0x20 32c103de24SGrant Likely #define TGPIO_BFLR 0x24 33c103de24SGrant Likely 34c103de24SGrant Likely struct timbgpio { 35c103de24SGrant Likely void __iomem *membase; 36c103de24SGrant Likely spinlock_t lock; /* mutual exclusion */ 37c103de24SGrant Likely struct gpio_chip gpio; 38c103de24SGrant Likely int irq_base; 39c103de24SGrant Likely unsigned long last_ier; 40c103de24SGrant Likely }; 41c103de24SGrant Likely 42c103de24SGrant Likely static int timbgpio_update_bit(struct gpio_chip *gpio, unsigned index, 43c103de24SGrant Likely unsigned offset, bool enabled) 44c103de24SGrant Likely { 4592a41e2fSLinus Walleij struct timbgpio *tgpio = gpiochip_get_data(gpio); 46*9e8bc2ddSChengfeng Ye unsigned long flags; 47c103de24SGrant Likely u32 reg; 48c103de24SGrant Likely 49*9e8bc2ddSChengfeng Ye spin_lock_irqsave(&tgpio->lock, flags); 50c103de24SGrant Likely reg = ioread32(tgpio->membase + offset); 51c103de24SGrant Likely 52c103de24SGrant Likely if (enabled) 53c103de24SGrant Likely reg |= (1 << index); 54c103de24SGrant Likely else 55c103de24SGrant Likely reg &= ~(1 << index); 56c103de24SGrant Likely 57c103de24SGrant Likely iowrite32(reg, tgpio->membase + offset); 58*9e8bc2ddSChengfeng Ye spin_unlock_irqrestore(&tgpio->lock, flags); 59c103de24SGrant Likely 60c103de24SGrant Likely return 0; 61c103de24SGrant Likely } 62c103de24SGrant Likely 63c103de24SGrant Likely static int timbgpio_gpio_direction_input(struct gpio_chip *gpio, unsigned nr) 64c103de24SGrant Likely { 65c103de24SGrant Likely return timbgpio_update_bit(gpio, nr, TGPIODIR, true); 66c103de24SGrant Likely } 67c103de24SGrant Likely 68c103de24SGrant Likely static int timbgpio_gpio_get(struct gpio_chip *gpio, unsigned nr) 69c103de24SGrant Likely { 7092a41e2fSLinus Walleij struct timbgpio *tgpio = gpiochip_get_data(gpio); 71c103de24SGrant Likely u32 value; 72c103de24SGrant Likely 73c103de24SGrant Likely value = ioread32(tgpio->membase + TGPIOVAL); 74c103de24SGrant Likely return (value & (1 << nr)) ? 1 : 0; 75c103de24SGrant Likely } 76c103de24SGrant Likely 77c103de24SGrant Likely static int timbgpio_gpio_direction_output(struct gpio_chip *gpio, 78c103de24SGrant Likely unsigned nr, int val) 79c103de24SGrant Likely { 80c103de24SGrant Likely return timbgpio_update_bit(gpio, nr, TGPIODIR, false); 81c103de24SGrant Likely } 82c103de24SGrant Likely 83c103de24SGrant Likely static void timbgpio_gpio_set(struct gpio_chip *gpio, 84c103de24SGrant Likely unsigned nr, int val) 85c103de24SGrant Likely { 86c103de24SGrant Likely timbgpio_update_bit(gpio, nr, TGPIOVAL, val != 0); 87c103de24SGrant Likely } 88c103de24SGrant Likely 89c103de24SGrant Likely static int timbgpio_to_irq(struct gpio_chip *gpio, unsigned offset) 90c103de24SGrant Likely { 9192a41e2fSLinus Walleij struct timbgpio *tgpio = gpiochip_get_data(gpio); 92c103de24SGrant Likely 93c103de24SGrant Likely if (tgpio->irq_base <= 0) 94c103de24SGrant Likely return -EINVAL; 95c103de24SGrant Likely 96c103de24SGrant Likely return tgpio->irq_base + offset; 97c103de24SGrant Likely } 98c103de24SGrant Likely 99c103de24SGrant Likely /* 100c103de24SGrant Likely * GPIO IRQ 101c103de24SGrant Likely */ 102c103de24SGrant Likely static void timbgpio_irq_disable(struct irq_data *d) 103c103de24SGrant Likely { 104c103de24SGrant Likely struct timbgpio *tgpio = irq_data_get_irq_chip_data(d); 105c103de24SGrant Likely int offset = d->irq - tgpio->irq_base; 106c103de24SGrant Likely unsigned long flags; 107c103de24SGrant Likely 108c103de24SGrant Likely spin_lock_irqsave(&tgpio->lock, flags); 109d79550a7SDan Carpenter tgpio->last_ier &= ~(1UL << offset); 110c103de24SGrant Likely iowrite32(tgpio->last_ier, tgpio->membase + TGPIO_IER); 111c103de24SGrant Likely spin_unlock_irqrestore(&tgpio->lock, flags); 112c103de24SGrant Likely } 113c103de24SGrant Likely 114c103de24SGrant Likely static void timbgpio_irq_enable(struct irq_data *d) 115c103de24SGrant Likely { 116c103de24SGrant Likely struct timbgpio *tgpio = irq_data_get_irq_chip_data(d); 117c103de24SGrant Likely int offset = d->irq - tgpio->irq_base; 118c103de24SGrant Likely unsigned long flags; 119c103de24SGrant Likely 120c103de24SGrant Likely spin_lock_irqsave(&tgpio->lock, flags); 121d79550a7SDan Carpenter tgpio->last_ier |= 1UL << offset; 122c103de24SGrant Likely iowrite32(tgpio->last_ier, tgpio->membase + TGPIO_IER); 123c103de24SGrant Likely spin_unlock_irqrestore(&tgpio->lock, flags); 124c103de24SGrant Likely } 125c103de24SGrant Likely 126c103de24SGrant Likely static int timbgpio_irq_type(struct irq_data *d, unsigned trigger) 127c103de24SGrant Likely { 128c103de24SGrant Likely struct timbgpio *tgpio = irq_data_get_irq_chip_data(d); 129c103de24SGrant Likely int offset = d->irq - tgpio->irq_base; 130c103de24SGrant Likely unsigned long flags; 131c103de24SGrant Likely u32 lvr, flr, bflr = 0; 132c103de24SGrant Likely u32 ver; 133c103de24SGrant Likely int ret = 0; 134c103de24SGrant Likely 135c103de24SGrant Likely if (offset < 0 || offset > tgpio->gpio.ngpio) 136c103de24SGrant Likely return -EINVAL; 137c103de24SGrant Likely 138c103de24SGrant Likely ver = ioread32(tgpio->membase + TGPIO_VER); 139c103de24SGrant Likely 140c103de24SGrant Likely spin_lock_irqsave(&tgpio->lock, flags); 141c103de24SGrant Likely 142c103de24SGrant Likely lvr = ioread32(tgpio->membase + TGPIO_LVR); 143c103de24SGrant Likely flr = ioread32(tgpio->membase + TGPIO_FLR); 144c103de24SGrant Likely if (ver > 2) 145c103de24SGrant Likely bflr = ioread32(tgpio->membase + TGPIO_BFLR); 146c103de24SGrant Likely 147c103de24SGrant Likely if (trigger & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) { 148c103de24SGrant Likely bflr &= ~(1 << offset); 149c103de24SGrant Likely flr &= ~(1 << offset); 150c103de24SGrant Likely if (trigger & IRQ_TYPE_LEVEL_HIGH) 151c103de24SGrant Likely lvr |= 1 << offset; 152c103de24SGrant Likely else 153c103de24SGrant Likely lvr &= ~(1 << offset); 154c103de24SGrant Likely } 155c103de24SGrant Likely 156c103de24SGrant Likely if ((trigger & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH) { 157c103de24SGrant Likely if (ver < 3) { 158c103de24SGrant Likely ret = -EINVAL; 159c103de24SGrant Likely goto out; 1608a29a409SLaurent Navet } else { 161c103de24SGrant Likely flr |= 1 << offset; 162c103de24SGrant Likely bflr |= 1 << offset; 163c103de24SGrant Likely } 164c103de24SGrant Likely } else { 165c103de24SGrant Likely bflr &= ~(1 << offset); 166c103de24SGrant Likely flr |= 1 << offset; 167c103de24SGrant Likely if (trigger & IRQ_TYPE_EDGE_FALLING) 168c103de24SGrant Likely lvr &= ~(1 << offset); 169c103de24SGrant Likely else 170c103de24SGrant Likely lvr |= 1 << offset; 171c103de24SGrant Likely } 172c103de24SGrant Likely 173c103de24SGrant Likely iowrite32(lvr, tgpio->membase + TGPIO_LVR); 174c103de24SGrant Likely iowrite32(flr, tgpio->membase + TGPIO_FLR); 175c103de24SGrant Likely if (ver > 2) 176c103de24SGrant Likely iowrite32(bflr, tgpio->membase + TGPIO_BFLR); 177c103de24SGrant Likely 178c103de24SGrant Likely iowrite32(1 << offset, tgpio->membase + TGPIO_ICR); 179c103de24SGrant Likely 180c103de24SGrant Likely out: 181c103de24SGrant Likely spin_unlock_irqrestore(&tgpio->lock, flags); 182c103de24SGrant Likely return ret; 183c103de24SGrant Likely } 184c103de24SGrant Likely 185bd0b9ac4SThomas Gleixner static void timbgpio_irq(struct irq_desc *desc) 186c103de24SGrant Likely { 187476f8b4cSJiang Liu struct timbgpio *tgpio = irq_desc_get_handler_data(desc); 188476f8b4cSJiang Liu struct irq_data *data = irq_desc_get_irq_data(desc); 189c103de24SGrant Likely unsigned long ipr; 190c103de24SGrant Likely int offset; 191c103de24SGrant Likely 192476f8b4cSJiang Liu data->chip->irq_ack(data); 193c103de24SGrant Likely ipr = ioread32(tgpio->membase + TGPIO_IPR); 194c103de24SGrant Likely iowrite32(ipr, tgpio->membase + TGPIO_ICR); 195c103de24SGrant Likely 196c103de24SGrant Likely /* 197c103de24SGrant Likely * Some versions of the hardware trash the IER register if more than 198c103de24SGrant Likely * one interrupt is received simultaneously. 199c103de24SGrant Likely */ 200c103de24SGrant Likely iowrite32(0, tgpio->membase + TGPIO_IER); 201c103de24SGrant Likely 202c103de24SGrant Likely for_each_set_bit(offset, &ipr, tgpio->gpio.ngpio) 203c103de24SGrant Likely generic_handle_irq(timbgpio_to_irq(&tgpio->gpio, offset)); 204c103de24SGrant Likely 205c103de24SGrant Likely iowrite32(tgpio->last_ier, tgpio->membase + TGPIO_IER); 206c103de24SGrant Likely } 207c103de24SGrant Likely 208c103de24SGrant Likely static struct irq_chip timbgpio_irqchip = { 209c103de24SGrant Likely .name = "GPIO", 210c103de24SGrant Likely .irq_enable = timbgpio_irq_enable, 211c103de24SGrant Likely .irq_disable = timbgpio_irq_disable, 212c103de24SGrant Likely .irq_set_type = timbgpio_irq_type, 213c103de24SGrant Likely }; 214c103de24SGrant Likely 2153836309dSBill Pemberton static int timbgpio_probe(struct platform_device *pdev) 216c103de24SGrant Likely { 217c103de24SGrant Likely int err, i; 2180ed3398eSabdoulaye berthe struct device *dev = &pdev->dev; 219c103de24SGrant Likely struct gpio_chip *gc; 220c103de24SGrant Likely struct timbgpio *tgpio; 221e56aee18SJingoo Han struct timbgpio_platform_data *pdata = dev_get_platdata(&pdev->dev); 222c103de24SGrant Likely int irq = platform_get_irq(pdev, 0); 223c103de24SGrant Likely 224c103de24SGrant Likely if (!pdata || pdata->nr_pins > 32) { 2250ed3398eSabdoulaye berthe dev_err(dev, "Invalid platform data\n"); 2260ed3398eSabdoulaye berthe return -EINVAL; 227c103de24SGrant Likely } 228c103de24SGrant Likely 2292c3087e1SMarkus Elfring tgpio = devm_kzalloc(dev, sizeof(*tgpio), GFP_KERNEL); 230587ca5edSMarkus Elfring if (!tgpio) 2310ed3398eSabdoulaye berthe return -EINVAL; 232587ca5edSMarkus Elfring 233c103de24SGrant Likely tgpio->irq_base = pdata->irq_base; 234c103de24SGrant Likely 235c103de24SGrant Likely spin_lock_init(&tgpio->lock); 236c103de24SGrant Likely 237aa6c9b91SEnrico Weigelt, metux IT consult tgpio->membase = devm_platform_ioremap_resource(pdev, 0); 238fa283db7SAmitoj Kaur Chawla if (IS_ERR(tgpio->membase)) 239fa283db7SAmitoj Kaur Chawla return PTR_ERR(tgpio->membase); 240c103de24SGrant Likely 241c103de24SGrant Likely gc = &tgpio->gpio; 242c103de24SGrant Likely 243c103de24SGrant Likely gc->label = dev_name(&pdev->dev); 244c103de24SGrant Likely gc->owner = THIS_MODULE; 24558383c78SLinus Walleij gc->parent = &pdev->dev; 246c103de24SGrant Likely gc->direction_input = timbgpio_gpio_direction_input; 247c103de24SGrant Likely gc->get = timbgpio_gpio_get; 248c103de24SGrant Likely gc->direction_output = timbgpio_gpio_direction_output; 249c103de24SGrant Likely gc->set = timbgpio_gpio_set; 250c103de24SGrant Likely gc->to_irq = (irq >= 0 && tgpio->irq_base > 0) ? timbgpio_to_irq : NULL; 251c103de24SGrant Likely gc->dbg_show = NULL; 252c103de24SGrant Likely gc->base = pdata->gpio_base; 253c103de24SGrant Likely gc->ngpio = pdata->nr_pins; 2549fb1f39eSLinus Walleij gc->can_sleep = false; 255c103de24SGrant Likely 25643fad832SLaxman Dewangan err = devm_gpiochip_add_data(&pdev->dev, gc, tgpio); 257c103de24SGrant Likely if (err) 2580ed3398eSabdoulaye berthe return err; 259c103de24SGrant Likely 260c103de24SGrant Likely /* make sure to disable interrupts */ 261c103de24SGrant Likely iowrite32(0x0, tgpio->membase + TGPIO_IER); 262c103de24SGrant Likely 263c103de24SGrant Likely if (irq < 0 || tgpio->irq_base <= 0) 264c103de24SGrant Likely return 0; 265c103de24SGrant Likely 266c103de24SGrant Likely for (i = 0; i < pdata->nr_pins; i++) { 267e5428a68SLinus Walleij irq_set_chip_and_handler(tgpio->irq_base + i, 268e5428a68SLinus Walleij &timbgpio_irqchip, handle_simple_irq); 269c103de24SGrant Likely irq_set_chip_data(tgpio->irq_base + i, tgpio); 27023393d49SRob Herring irq_clear_status_flags(tgpio->irq_base + i, IRQ_NOREQUEST | IRQ_NOPROBE); 271c103de24SGrant Likely } 272c103de24SGrant Likely 2738a52211aSThomas Gleixner irq_set_chained_handler_and_data(irq, timbgpio_irq, tgpio); 274c103de24SGrant Likely 275c103de24SGrant Likely return 0; 276c103de24SGrant Likely } 277c103de24SGrant Likely 278c103de24SGrant Likely static struct platform_driver timbgpio_platform_driver = { 279c103de24SGrant Likely .driver = { 280c103de24SGrant Likely .name = DRIVER_NAME, 28152ad9053SPaul Gortmaker .suppress_bind_attrs = true, 282c103de24SGrant Likely }, 283c103de24SGrant Likely .probe = timbgpio_probe, 284c103de24SGrant Likely }; 285c103de24SGrant Likely 286c103de24SGrant Likely /*--------------------------------------------------------------------------*/ 287c103de24SGrant Likely 28852ad9053SPaul Gortmaker builtin_platform_driver(timbgpio_platform_driver); 289