diff options
Diffstat (limited to 'drivers/soc/fsl/qe/gpio.c')
| -rw-r--r-- | drivers/soc/fsl/qe/gpio.c | 246 |
1 files changed, 127 insertions, 119 deletions
diff --git a/drivers/soc/fsl/qe/gpio.c b/drivers/soc/fsl/qe/gpio.c index ed75198ed254..c54154b404df 100644 --- a/drivers/soc/fsl/qe/gpio.c +++ b/drivers/soc/fsl/qe/gpio.c @@ -12,22 +12,21 @@ #include <linux/spinlock.h> #include <linux/err.h> #include <linux/io.h> -#include <linux/of.h> -#include <linux/of_gpio.h> +#include <linux/gpio/consumer.h> #include <linux/gpio/driver.h> -/* FIXME: needed for gpio_to_chip() get rid of this */ -#include <linux/gpio.h> #include <linux/slab.h> #include <linux/export.h> +#include <linux/platform_device.h> + #include <soc/fsl/qe/qe.h> +#define PIN_MASK(gpio) (1UL << (QE_PIO_PINS - 1 - (gpio))) + struct qe_gpio_chip { - struct of_mm_gpio_chip mm_gc; + struct gpio_chip gc; + void __iomem *regs; spinlock_t lock; - unsigned long pin_flags[QE_PIO_PINS]; -#define QE_PIN_REQUESTED 0 - /* shadowed data register to clear/set bits safely */ u32 cpdata; @@ -35,37 +34,34 @@ struct qe_gpio_chip { struct qe_pio_regs saved_regs; }; -static void qe_gpio_save_regs(struct of_mm_gpio_chip *mm_gc) +static void qe_gpio_save_regs(struct qe_gpio_chip *qe_gc) { - struct qe_gpio_chip *qe_gc = - container_of(mm_gc, struct qe_gpio_chip, mm_gc); - struct qe_pio_regs __iomem *regs = mm_gc->regs; + struct qe_pio_regs __iomem *regs = qe_gc->regs; - qe_gc->cpdata = qe_ioread32be(®s->cpdata); + qe_gc->cpdata = ioread32be(®s->cpdata); qe_gc->saved_regs.cpdata = qe_gc->cpdata; - qe_gc->saved_regs.cpdir1 = qe_ioread32be(®s->cpdir1); - qe_gc->saved_regs.cpdir2 = qe_ioread32be(®s->cpdir2); - qe_gc->saved_regs.cppar1 = qe_ioread32be(®s->cppar1); - qe_gc->saved_regs.cppar2 = qe_ioread32be(®s->cppar2); - qe_gc->saved_regs.cpodr = qe_ioread32be(®s->cpodr); + qe_gc->saved_regs.cpdir1 = ioread32be(®s->cpdir1); + qe_gc->saved_regs.cpdir2 = ioread32be(®s->cpdir2); + qe_gc->saved_regs.cppar1 = ioread32be(®s->cppar1); + qe_gc->saved_regs.cppar2 = ioread32be(®s->cppar2); + qe_gc->saved_regs.cpodr = ioread32be(®s->cpodr); } static int qe_gpio_get(struct gpio_chip *gc, unsigned int gpio) { - struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); - struct qe_pio_regs __iomem *regs = mm_gc->regs; - u32 pin_mask = 1 << (QE_PIO_PINS - 1 - gpio); + struct qe_gpio_chip *qe_gc = gpiochip_get_data(gc); + struct qe_pio_regs __iomem *regs = qe_gc->regs; + u32 pin_mask = PIN_MASK(gpio); - return !!(qe_ioread32be(®s->cpdata) & pin_mask); + return !!(ioread32be(®s->cpdata) & pin_mask); } -static void qe_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val) +static int qe_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val) { - struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); struct qe_gpio_chip *qe_gc = gpiochip_get_data(gc); - struct qe_pio_regs __iomem *regs = mm_gc->regs; + struct qe_pio_regs __iomem *regs = qe_gc->regs; unsigned long flags; - u32 pin_mask = 1 << (QE_PIO_PINS - 1 - gpio); + u32 pin_mask = PIN_MASK(gpio); spin_lock_irqsave(&qe_gc->lock, flags); @@ -74,17 +70,18 @@ static void qe_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val) else qe_gc->cpdata &= ~pin_mask; - qe_iowrite32be(qe_gc->cpdata, ®s->cpdata); + iowrite32be(qe_gc->cpdata, ®s->cpdata); spin_unlock_irqrestore(&qe_gc->lock, flags); + + return 0; } -static void qe_gpio_set_multiple(struct gpio_chip *gc, - unsigned long *mask, unsigned long *bits) +static int qe_gpio_set_multiple(struct gpio_chip *gc, + unsigned long *mask, unsigned long *bits) { - struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); struct qe_gpio_chip *qe_gc = gpiochip_get_data(gc); - struct qe_pio_regs __iomem *regs = mm_gc->regs; + struct qe_pio_regs __iomem *regs = qe_gc->regs; unsigned long flags; int i; @@ -95,26 +92,27 @@ static void qe_gpio_set_multiple(struct gpio_chip *gc, break; if (__test_and_clear_bit(i, mask)) { if (test_bit(i, bits)) - qe_gc->cpdata |= (1U << (QE_PIO_PINS - 1 - i)); + qe_gc->cpdata |= PIN_MASK(i); else - qe_gc->cpdata &= ~(1U << (QE_PIO_PINS - 1 - i)); + qe_gc->cpdata &= ~PIN_MASK(i); } } - qe_iowrite32be(qe_gc->cpdata, ®s->cpdata); + iowrite32be(qe_gc->cpdata, ®s->cpdata); spin_unlock_irqrestore(&qe_gc->lock, flags); + + return 0; } static int qe_gpio_dir_in(struct gpio_chip *gc, unsigned int gpio) { - struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); struct qe_gpio_chip *qe_gc = gpiochip_get_data(gc); unsigned long flags; spin_lock_irqsave(&qe_gc->lock, flags); - __par_io_config_pin(mm_gc->regs, gpio, QE_PIO_DIR_IN, 0, 0, 0); + __par_io_config_pin(qe_gc->regs, gpio, QE_PIO_DIR_IN, 0, 0, 0); spin_unlock_irqrestore(&qe_gc->lock, flags); @@ -123,7 +121,6 @@ static int qe_gpio_dir_in(struct gpio_chip *gc, unsigned int gpio) static int qe_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) { - struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); struct qe_gpio_chip *qe_gc = gpiochip_get_data(gc); unsigned long flags; @@ -131,7 +128,7 @@ static int qe_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) spin_lock_irqsave(&qe_gc->lock, flags); - __par_io_config_pin(mm_gc->regs, gpio, QE_PIO_DIR_OUT, 0, 0, 0); + __par_io_config_pin(qe_gc->regs, gpio, QE_PIO_DIR_OUT, 0, 0, 0); spin_unlock_irqrestore(&qe_gc->lock, flags); @@ -149,62 +146,65 @@ struct qe_pin { /** * qe_pin_request - Request a QE pin - * @np: device node to get a pin from - * @index: index of a pin in the device tree + * @dev: device to get the pin from + * @index: index of the pin in the device tree * Context: non-atomic * * This function return qe_pin so that you could use it with the rest of * the QE Pin Multiplexing API. */ -struct qe_pin *qe_pin_request(struct device_node *np, int index) +struct qe_pin *qe_pin_request(struct device *dev, int index) { struct qe_pin *qe_pin; struct gpio_chip *gc; - struct qe_gpio_chip *qe_gc; + struct gpio_desc *gpiod; + int gpio_num; int err; - unsigned long flags; qe_pin = kzalloc(sizeof(*qe_pin), GFP_KERNEL); if (!qe_pin) { - pr_debug("%s: can't allocate memory\n", __func__); + dev_dbg(dev, "%s: can't allocate memory\n", __func__); return ERR_PTR(-ENOMEM); } - err = of_get_gpio(np, index); - if (err < 0) + /* + * Request gpio as nonexclusive as it was likely reserved by the + * caller, and we are not planning on controlling it, we only need + * the descriptor to the to the gpio chip structure. + */ + gpiod = gpiod_get_index(dev, NULL, index, + GPIOD_ASIS | GPIOD_FLAGS_BIT_NONEXCLUSIVE); + err = PTR_ERR_OR_ZERO(gpiod); + if (err) goto err0; - gc = gpio_to_chip(err); + + gc = gpiod_to_chip(gpiod); + gpio_num = desc_to_gpio(gpiod); + /* We no longer need this descriptor */ + gpiod_put(gpiod); + if (WARN_ON(!gc)) { err = -ENODEV; goto err0; } - if (!of_device_is_compatible(gc->of_node, "fsl,mpc8323-qe-pario-bank")) { - pr_debug("%s: tried to get a non-qe pin\n", __func__); + qe_pin->controller = gpiochip_get_data(gc); + /* + * FIXME: this gets the local offset on the gpio_chip so that the driver + * can manipulate pin control settings through its custom API. The real + * solution is to create a real pin control driver for this. + */ + qe_pin->num = gpio_num - gc->base; + + if (!fwnode_device_is_compatible(gc->fwnode, "fsl,mpc8323-qe-pario-bank")) { + dev_dbg(dev, "%s: tried to get a non-qe pin\n", __func__); err = -EINVAL; goto err0; } - - qe_gc = gpiochip_get_data(gc); - - spin_lock_irqsave(&qe_gc->lock, flags); - - err -= gc->base; - if (test_and_set_bit(QE_PIN_REQUESTED, &qe_gc->pin_flags[err]) == 0) { - qe_pin->controller = qe_gc; - qe_pin->num = err; - err = 0; - } else { - err = -EBUSY; - } - - spin_unlock_irqrestore(&qe_gc->lock, flags); - - if (!err) - return qe_pin; + return qe_pin; err0: kfree(qe_pin); - pr_debug("%s failed with status %d\n", __func__, err); + dev_dbg(dev, "%s failed with status %d\n", __func__, err); return ERR_PTR(err); } EXPORT_SYMBOL(qe_pin_request); @@ -219,14 +219,6 @@ EXPORT_SYMBOL(qe_pin_request); */ void qe_pin_free(struct qe_pin *qe_pin) { - struct qe_gpio_chip *qe_gc = qe_pin->controller; - unsigned long flags; - const int pin = qe_pin->num; - - spin_lock_irqsave(&qe_gc->lock, flags); - test_and_clear_bit(QE_PIN_REQUESTED, &qe_gc->pin_flags[pin]); - spin_unlock_irqrestore(&qe_gc->lock, flags); - kfree(qe_pin); } EXPORT_SYMBOL(qe_pin_free); @@ -242,7 +234,7 @@ EXPORT_SYMBOL(qe_pin_free); void qe_pin_set_dedicated(struct qe_pin *qe_pin) { struct qe_gpio_chip *qe_gc = qe_pin->controller; - struct qe_pio_regs __iomem *regs = qe_gc->mm_gc.regs; + struct qe_pio_regs __iomem *regs = qe_gc->regs; struct qe_pio_regs *sregs = &qe_gc->saved_regs; int pin = qe_pin->num; u32 mask1 = 1 << (QE_PIO_PINS - (pin + 1)); @@ -269,9 +261,8 @@ void qe_pin_set_dedicated(struct qe_pin *qe_pin) else qe_gc->cpdata &= ~mask1; - qe_iowrite32be(qe_gc->cpdata, ®s->cpdata); + iowrite32be(qe_gc->cpdata, ®s->cpdata); qe_clrsetbits_be32(®s->cpodr, mask1, sregs->cpodr & mask1); - spin_unlock_irqrestore(&qe_gc->lock, flags); } EXPORT_SYMBOL(qe_pin_set_dedicated); @@ -286,7 +277,7 @@ EXPORT_SYMBOL(qe_pin_set_dedicated); void qe_pin_set_gpio(struct qe_pin *qe_pin) { struct qe_gpio_chip *qe_gc = qe_pin->controller; - struct qe_pio_regs __iomem *regs = qe_gc->mm_gc.regs; + struct qe_pio_regs __iomem *regs = qe_gc->regs; unsigned long flags; spin_lock_irqsave(&qe_gc->lock, flags); @@ -298,45 +289,62 @@ void qe_pin_set_gpio(struct qe_pin *qe_pin) } EXPORT_SYMBOL(qe_pin_set_gpio); -static int __init qe_add_gpiochips(void) +static int qe_gpio_probe(struct platform_device *ofdev) { - struct device_node *np; - - for_each_compatible_node(np, NULL, "fsl,mpc8323-qe-pario-bank") { - int ret; - struct qe_gpio_chip *qe_gc; - struct of_mm_gpio_chip *mm_gc; - struct gpio_chip *gc; - - qe_gc = kzalloc(sizeof(*qe_gc), GFP_KERNEL); - if (!qe_gc) { - ret = -ENOMEM; - goto err; - } + struct device *dev = &ofdev->dev; + struct device_node *np = dev->of_node; + struct qe_gpio_chip *qe_gc; + struct gpio_chip *gc; - spin_lock_init(&qe_gc->lock); - - mm_gc = &qe_gc->mm_gc; - gc = &mm_gc->gc; - - mm_gc->save_regs = qe_gpio_save_regs; - gc->ngpio = QE_PIO_PINS; - gc->direction_input = qe_gpio_dir_in; - gc->direction_output = qe_gpio_dir_out; - gc->get = qe_gpio_get; - gc->set = qe_gpio_set; - gc->set_multiple = qe_gpio_set_multiple; - - ret = of_mm_gpiochip_add_data(np, mm_gc, qe_gc); - if (ret) - goto err; - continue; -err: - pr_err("%pOF: registration failed with status %d\n", - np, ret); - kfree(qe_gc); - /* try others anyway */ - } - return 0; + qe_gc = devm_kzalloc(dev, sizeof(*qe_gc), GFP_KERNEL); + if (!qe_gc) + return -ENOMEM; + + spin_lock_init(&qe_gc->lock); + + gc = &qe_gc->gc; + + gc->base = -1; + gc->ngpio = QE_PIO_PINS; + gc->direction_input = qe_gpio_dir_in; + gc->direction_output = qe_gpio_dir_out; + gc->get = qe_gpio_get; + gc->set = qe_gpio_set; + gc->set_multiple = qe_gpio_set_multiple; + gc->parent = dev; + gc->owner = THIS_MODULE; + + gc->label = devm_kasprintf(dev, GFP_KERNEL, "%pOF", np); + if (!gc->label) + return -ENOMEM; + + qe_gc->regs = devm_of_iomap(dev, np, 0, NULL); + if (IS_ERR(qe_gc->regs)) + return PTR_ERR(qe_gc->regs); + + qe_gpio_save_regs(qe_gc); + + return devm_gpiochip_add_data(dev, gc, qe_gc); +} + +static const struct of_device_id qe_gpio_match[] = { + { + .compatible = "fsl,mpc8323-qe-pario-bank", + }, + {}, +}; +MODULE_DEVICE_TABLE(of, qe_gpio_match); + +static struct platform_driver qe_gpio_driver = { + .probe = qe_gpio_probe, + .driver = { + .name = "qe-gpio", + .of_match_table = qe_gpio_match, + }, +}; + +static int __init qe_gpio_init(void) +{ + return platform_driver_register(&qe_gpio_driver); } -arch_initcall(qe_add_gpiochips); +arch_initcall(qe_gpio_init); |
