diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 7a15031..0f924d1 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -67,6 +67,14 @@ additional drivers must be enabled in order to use the functionality of the device. +config GPIO_MPC8XXX + bool "MPC512x/MPC8xxx/QorIQ GPIO support" + depends on ARCH_LAYERSCAPE + select GPIO_GENERIC + help + Say Y here if you're going to use hardware that connects to the + MPC512x/831x/834x/837x/8572/8610/QorIQ GPIOs. + config GPIO_OMAP def_bool ARCH_OMAP diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 990df01..bc5c500 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -11,6 +11,7 @@ obj-$(CONFIG_GPIO_MXS) += gpio-mxs.o obj-$(CONFIG_GPIO_JZ4740) += gpio-jz4740.o obj-$(CONFIG_GPIO_MALTA_FPGA_I2C) += gpio-malta-fpga-i2c.o +obj-$(CONFIG_GPIO_MPC8XXX) += gpio-mpc8xxx.o obj-$(CONFIG_GPIO_ORION) += gpio-orion.o obj-$(CONFIG_GPIO_OMAP) += gpio-omap.o obj-$(CONFIG_GPIO_PCA953X) += gpio-pca953x.o diff --git a/drivers/gpio/gpio-mpc8xxx.c b/drivers/gpio/gpio-mpc8xxx.c new file mode 100644 index 0000000..979f92a --- /dev/null +++ b/drivers/gpio/gpio-mpc8xxx.c @@ -0,0 +1,122 @@ +/* + * GPIOs on MPC512x/8349/8572/8610/QorIQ and compatible + * + * Copyright (C) 2008 Peter Korsgaard + * Copyright (C) 2016 Freescale Semiconductor Inc. + * + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed "as is" without any warranty of any + * kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MPC8XXX_GPIO_PINS 32 + +#define GPIO_DIR 0x00 +#define GPIO_ODR 0x04 +#define GPIO_DAT 0x08 +#define GPIO_IER 0x0c +#define GPIO_IMR 0x10 + +struct mpc8xxx_gpio_chip { + struct bgpio_chip bgc; + void __iomem *regs; +}; + +struct mpc8xxx_gpio_devtype { + int (*gpio_dir_out)(struct bgpio_chip *, unsigned int, int); + int (*gpio_get)(struct bgpio_chip *, unsigned int); +}; + +static int mpc8xxx_probe(struct device_d *dev) +{ + struct device_node *np; + struct resource *iores; + struct mpc8xxx_gpio_chip *mpc8xxx_gc; + struct bgpio_chip *bgc; + int ret; + + mpc8xxx_gc = xzalloc(sizeof(*mpc8xxx_gc)); + + if (dev->device_node) { + np = dev->device_node; + } else { + dev_err(dev, "no device_node\n"); + return -ENODEV; + } + + iores = dev_request_mem_resource(dev, 0); + if (IS_ERR(iores)) + return PTR_ERR(iores); + + mpc8xxx_gc->regs = IOMEM(iores->start); + if (!mpc8xxx_gc->regs) + return -ENOMEM; + + bgc = &mpc8xxx_gc->bgc; + + if (of_property_read_bool(np, "little-endian")) { + ret = bgpio_init(bgc, dev, 4, + mpc8xxx_gc->regs + GPIO_DAT, + NULL, NULL, + mpc8xxx_gc->regs + GPIO_DIR, NULL, 0); + if (ret) + goto err; + dev_dbg(dev, "GPIO registers are LITTLE endian\n"); + } else { + ret = bgpio_init(bgc, dev, 4, + mpc8xxx_gc->regs + GPIO_DAT, + NULL, NULL, + mpc8xxx_gc->regs + GPIO_DIR, NULL, + BGPIOF_BIG_ENDIAN); + if (ret) + goto err; + dev_dbg(dev, "GPIO registers are BIG endian\n"); + } + + ret = gpiochip_add(&mpc8xxx_gc->bgc.gc); + if (ret) { + pr_err("%pOF: GPIO chip registration failed with status %d\n", + np, ret); + goto err; + } + + /* ack and mask all irqs */ + bgc->write_reg(mpc8xxx_gc->regs + GPIO_IER, 0xffffffff); + bgc->write_reg(mpc8xxx_gc->regs + GPIO_IMR, 0); + + return 0; + +err: + return ret; +} + +static __maybe_unused struct of_device_id mpc8xxx_gpio_ids[] = { + { + .compatible = "fsl,qoriq-gpio", + }, + { + /* sentinel */ + }, +}; + +static struct driver_d mpc8xxx_driver = { + .name = "mpc8xxx-gpio", + .probe = mpc8xxx_probe, + .of_compatible = DRV_OF_COMPAT(mpc8xxx_gpio_ids), +}; + +static int __init mpc8xxx_init(void) +{ + return platform_driver_register(&mpc8xxx_driver); +} +postcore_initcall(mpc8xxx_init);