547 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * GPIO driver for LPC32xx SoC4 *5 * Author: Kevin Wells <kevin.wells@nxp.com>6 *7 * Copyright (C) 2010 NXP Semiconductors8 */9 10#include <linux/kernel.h>11#include <linux/init.h>12#include <linux/io.h>13#include <linux/errno.h>14#include <linux/gpio/driver.h>15#include <linux/of.h>16#include <linux/platform_device.h>17#include <linux/module.h>18 19#define LPC32XX_GPIO_P3_INP_STATE (0x000)20#define LPC32XX_GPIO_P3_OUTP_SET (0x004)21#define LPC32XX_GPIO_P3_OUTP_CLR (0x008)22#define LPC32XX_GPIO_P3_OUTP_STATE (0x00C)23#define LPC32XX_GPIO_P2_DIR_SET (0x010)24#define LPC32XX_GPIO_P2_DIR_CLR (0x014)25#define LPC32XX_GPIO_P2_DIR_STATE (0x018)26#define LPC32XX_GPIO_P2_INP_STATE (0x01C)27#define LPC32XX_GPIO_P2_OUTP_SET (0x020)28#define LPC32XX_GPIO_P2_OUTP_CLR (0x024)29#define LPC32XX_GPIO_P2_MUX_SET (0x028)30#define LPC32XX_GPIO_P2_MUX_CLR (0x02C)31#define LPC32XX_GPIO_P2_MUX_STATE (0x030)32#define LPC32XX_GPIO_P0_INP_STATE (0x040)33#define LPC32XX_GPIO_P0_OUTP_SET (0x044)34#define LPC32XX_GPIO_P0_OUTP_CLR (0x048)35#define LPC32XX_GPIO_P0_OUTP_STATE (0x04C)36#define LPC32XX_GPIO_P0_DIR_SET (0x050)37#define LPC32XX_GPIO_P0_DIR_CLR (0x054)38#define LPC32XX_GPIO_P0_DIR_STATE (0x058)39#define LPC32XX_GPIO_P1_INP_STATE (0x060)40#define LPC32XX_GPIO_P1_OUTP_SET (0x064)41#define LPC32XX_GPIO_P1_OUTP_CLR (0x068)42#define LPC32XX_GPIO_P1_OUTP_STATE (0x06C)43#define LPC32XX_GPIO_P1_DIR_SET (0x070)44#define LPC32XX_GPIO_P1_DIR_CLR (0x074)45#define LPC32XX_GPIO_P1_DIR_STATE (0x078)46 47#define GPIO012_PIN_TO_BIT(x) (1 << (x))48#define GPIO3_PIN_TO_BIT(x) (1 << ((x) + 25))49#define GPO3_PIN_TO_BIT(x) (1 << (x))50#define GPIO012_PIN_IN_SEL(x, y) (((x) >> (y)) & 1)51#define GPIO3_PIN_IN_SHIFT(x) ((x) == 5 ? 24 : 10 + (x))52#define GPIO3_PIN_IN_SEL(x, y) (((x) >> GPIO3_PIN_IN_SHIFT(y)) & 1)53#define GPIO3_PIN5_IN_SEL(x) (((x) >> 24) & 1)54#define GPI3_PIN_IN_SEL(x, y) (((x) >> (y)) & 1)55#define GPO3_PIN_IN_SEL(x, y) (((x) >> (y)) & 1)56 57#define LPC32XX_GPIO_P0_MAX 858#define LPC32XX_GPIO_P1_MAX 2459#define LPC32XX_GPIO_P2_MAX 1360#define LPC32XX_GPIO_P3_MAX 661#define LPC32XX_GPI_P3_MAX 2962#define LPC32XX_GPO_P3_MAX 2463 64#define LPC32XX_GPIO_P0_GRP 065#define LPC32XX_GPIO_P1_GRP (LPC32XX_GPIO_P0_GRP + LPC32XX_GPIO_P0_MAX)66#define LPC32XX_GPIO_P2_GRP (LPC32XX_GPIO_P1_GRP + LPC32XX_GPIO_P1_MAX)67#define LPC32XX_GPIO_P3_GRP (LPC32XX_GPIO_P2_GRP + LPC32XX_GPIO_P2_MAX)68#define LPC32XX_GPI_P3_GRP (LPC32XX_GPIO_P3_GRP + LPC32XX_GPIO_P3_MAX)69#define LPC32XX_GPO_P3_GRP (LPC32XX_GPI_P3_GRP + LPC32XX_GPI_P3_MAX)70 71struct gpio_regs {72 unsigned long inp_state;73 unsigned long outp_state;74 unsigned long outp_set;75 unsigned long outp_clr;76 unsigned long dir_set;77 unsigned long dir_clr;78};79 80/*81 * GPIO names82 */83static const char *gpio_p0_names[LPC32XX_GPIO_P0_MAX] = {84 "p0.0", "p0.1", "p0.2", "p0.3",85 "p0.4", "p0.5", "p0.6", "p0.7"86};87 88static const char *gpio_p1_names[LPC32XX_GPIO_P1_MAX] = {89 "p1.0", "p1.1", "p1.2", "p1.3",90 "p1.4", "p1.5", "p1.6", "p1.7",91 "p1.8", "p1.9", "p1.10", "p1.11",92 "p1.12", "p1.13", "p1.14", "p1.15",93 "p1.16", "p1.17", "p1.18", "p1.19",94 "p1.20", "p1.21", "p1.22", "p1.23",95};96 97static const char *gpio_p2_names[LPC32XX_GPIO_P2_MAX] = {98 "p2.0", "p2.1", "p2.2", "p2.3",99 "p2.4", "p2.5", "p2.6", "p2.7",100 "p2.8", "p2.9", "p2.10", "p2.11",101 "p2.12"102};103 104static const char *gpio_p3_names[LPC32XX_GPIO_P3_MAX] = {105 "gpio00", "gpio01", "gpio02", "gpio03",106 "gpio04", "gpio05"107};108 109static const char *gpi_p3_names[LPC32XX_GPI_P3_MAX] = {110 "gpi00", "gpi01", "gpi02", "gpi03",111 "gpi04", "gpi05", "gpi06", "gpi07",112 "gpi08", "gpi09", NULL, NULL,113 NULL, NULL, NULL, "gpi15",114 "gpi16", "gpi17", "gpi18", "gpi19",115 "gpi20", "gpi21", "gpi22", "gpi23",116 "gpi24", "gpi25", "gpi26", "gpi27",117 "gpi28"118};119 120static const char *gpo_p3_names[LPC32XX_GPO_P3_MAX] = {121 "gpo00", "gpo01", "gpo02", "gpo03",122 "gpo04", "gpo05", "gpo06", "gpo07",123 "gpo08", "gpo09", "gpo10", "gpo11",124 "gpo12", "gpo13", "gpo14", "gpo15",125 "gpo16", "gpo17", "gpo18", "gpo19",126 "gpo20", "gpo21", "gpo22", "gpo23"127};128 129static struct gpio_regs gpio_grp_regs_p0 = {130 .inp_state = LPC32XX_GPIO_P0_INP_STATE,131 .outp_set = LPC32XX_GPIO_P0_OUTP_SET,132 .outp_clr = LPC32XX_GPIO_P0_OUTP_CLR,133 .dir_set = LPC32XX_GPIO_P0_DIR_SET,134 .dir_clr = LPC32XX_GPIO_P0_DIR_CLR,135};136 137static struct gpio_regs gpio_grp_regs_p1 = {138 .inp_state = LPC32XX_GPIO_P1_INP_STATE,139 .outp_set = LPC32XX_GPIO_P1_OUTP_SET,140 .outp_clr = LPC32XX_GPIO_P1_OUTP_CLR,141 .dir_set = LPC32XX_GPIO_P1_DIR_SET,142 .dir_clr = LPC32XX_GPIO_P1_DIR_CLR,143};144 145static struct gpio_regs gpio_grp_regs_p2 = {146 .inp_state = LPC32XX_GPIO_P2_INP_STATE,147 .outp_set = LPC32XX_GPIO_P2_OUTP_SET,148 .outp_clr = LPC32XX_GPIO_P2_OUTP_CLR,149 .dir_set = LPC32XX_GPIO_P2_DIR_SET,150 .dir_clr = LPC32XX_GPIO_P2_DIR_CLR,151};152 153static struct gpio_regs gpio_grp_regs_p3 = {154 .inp_state = LPC32XX_GPIO_P3_INP_STATE,155 .outp_state = LPC32XX_GPIO_P3_OUTP_STATE,156 .outp_set = LPC32XX_GPIO_P3_OUTP_SET,157 .outp_clr = LPC32XX_GPIO_P3_OUTP_CLR,158 .dir_set = LPC32XX_GPIO_P2_DIR_SET,159 .dir_clr = LPC32XX_GPIO_P2_DIR_CLR,160};161 162struct lpc32xx_gpio_chip {163 struct gpio_chip chip;164 struct gpio_regs *gpio_grp;165 void __iomem *reg_base;166};167 168static inline u32 gpreg_read(struct lpc32xx_gpio_chip *group, unsigned long offset)169{170 return __raw_readl(group->reg_base + offset);171}172 173static inline void gpreg_write(struct lpc32xx_gpio_chip *group, u32 val, unsigned long offset)174{175 __raw_writel(val, group->reg_base + offset);176}177 178static void __set_gpio_dir_p012(struct lpc32xx_gpio_chip *group,179 unsigned pin, int input)180{181 if (input)182 gpreg_write(group, GPIO012_PIN_TO_BIT(pin),183 group->gpio_grp->dir_clr);184 else185 gpreg_write(group, GPIO012_PIN_TO_BIT(pin),186 group->gpio_grp->dir_set);187}188 189static void __set_gpio_dir_p3(struct lpc32xx_gpio_chip *group,190 unsigned pin, int input)191{192 u32 u = GPIO3_PIN_TO_BIT(pin);193 194 if (input)195 gpreg_write(group, u, group->gpio_grp->dir_clr);196 else197 gpreg_write(group, u, group->gpio_grp->dir_set);198}199 200static void __set_gpio_level_p012(struct lpc32xx_gpio_chip *group,201 unsigned pin, int high)202{203 if (high)204 gpreg_write(group, GPIO012_PIN_TO_BIT(pin),205 group->gpio_grp->outp_set);206 else207 gpreg_write(group, GPIO012_PIN_TO_BIT(pin),208 group->gpio_grp->outp_clr);209}210 211static void __set_gpio_level_p3(struct lpc32xx_gpio_chip *group,212 unsigned pin, int high)213{214 u32 u = GPIO3_PIN_TO_BIT(pin);215 216 if (high)217 gpreg_write(group, u, group->gpio_grp->outp_set);218 else219 gpreg_write(group, u, group->gpio_grp->outp_clr);220}221 222static void __set_gpo_level_p3(struct lpc32xx_gpio_chip *group,223 unsigned pin, int high)224{225 if (high)226 gpreg_write(group, GPO3_PIN_TO_BIT(pin), group->gpio_grp->outp_set);227 else228 gpreg_write(group, GPO3_PIN_TO_BIT(pin), group->gpio_grp->outp_clr);229}230 231static int __get_gpio_state_p012(struct lpc32xx_gpio_chip *group,232 unsigned pin)233{234 return GPIO012_PIN_IN_SEL(gpreg_read(group, group->gpio_grp->inp_state),235 pin);236}237 238static int __get_gpio_state_p3(struct lpc32xx_gpio_chip *group,239 unsigned pin)240{241 int state = gpreg_read(group, group->gpio_grp->inp_state);242 243 /*244 * P3 GPIO pin input mapping is not contiguous, GPIOP3-0..4 is mapped245 * to bits 10..14, while GPIOP3-5 is mapped to bit 24.246 */247 return GPIO3_PIN_IN_SEL(state, pin);248}249 250static int __get_gpi_state_p3(struct lpc32xx_gpio_chip *group,251 unsigned pin)252{253 return GPI3_PIN_IN_SEL(gpreg_read(group, group->gpio_grp->inp_state), pin);254}255 256static int __get_gpo_state_p3(struct lpc32xx_gpio_chip *group,257 unsigned pin)258{259 return GPO3_PIN_IN_SEL(gpreg_read(group, group->gpio_grp->outp_state), pin);260}261 262/*263 * GPIO primitives.264 */265static int lpc32xx_gpio_dir_input_p012(struct gpio_chip *chip,266 unsigned pin)267{268 struct lpc32xx_gpio_chip *group = gpiochip_get_data(chip);269 270 __set_gpio_dir_p012(group, pin, 1);271 272 return 0;273}274 275static int lpc32xx_gpio_dir_input_p3(struct gpio_chip *chip,276 unsigned pin)277{278 struct lpc32xx_gpio_chip *group = gpiochip_get_data(chip);279 280 __set_gpio_dir_p3(group, pin, 1);281 282 return 0;283}284 285static int lpc32xx_gpio_dir_in_always(struct gpio_chip *chip,286 unsigned pin)287{288 return 0;289}290 291static int lpc32xx_gpio_get_value_p012(struct gpio_chip *chip, unsigned pin)292{293 struct lpc32xx_gpio_chip *group = gpiochip_get_data(chip);294 295 return !!__get_gpio_state_p012(group, pin);296}297 298static int lpc32xx_gpio_get_value_p3(struct gpio_chip *chip, unsigned pin)299{300 struct lpc32xx_gpio_chip *group = gpiochip_get_data(chip);301 302 return !!__get_gpio_state_p3(group, pin);303}304 305static int lpc32xx_gpi_get_value(struct gpio_chip *chip, unsigned pin)306{307 struct lpc32xx_gpio_chip *group = gpiochip_get_data(chip);308 309 return !!__get_gpi_state_p3(group, pin);310}311 312static int lpc32xx_gpio_dir_output_p012(struct gpio_chip *chip, unsigned pin,313 int value)314{315 struct lpc32xx_gpio_chip *group = gpiochip_get_data(chip);316 317 __set_gpio_level_p012(group, pin, value);318 __set_gpio_dir_p012(group, pin, 0);319 320 return 0;321}322 323static int lpc32xx_gpio_dir_output_p3(struct gpio_chip *chip, unsigned pin,324 int value)325{326 struct lpc32xx_gpio_chip *group = gpiochip_get_data(chip);327 328 __set_gpio_level_p3(group, pin, value);329 __set_gpio_dir_p3(group, pin, 0);330 331 return 0;332}333 334static int lpc32xx_gpio_dir_out_always(struct gpio_chip *chip, unsigned pin,335 int value)336{337 struct lpc32xx_gpio_chip *group = gpiochip_get_data(chip);338 339 __set_gpo_level_p3(group, pin, value);340 return 0;341}342 343static void lpc32xx_gpio_set_value_p012(struct gpio_chip *chip, unsigned pin,344 int value)345{346 struct lpc32xx_gpio_chip *group = gpiochip_get_data(chip);347 348 __set_gpio_level_p012(group, pin, value);349}350 351static void lpc32xx_gpio_set_value_p3(struct gpio_chip *chip, unsigned pin,352 int value)353{354 struct lpc32xx_gpio_chip *group = gpiochip_get_data(chip);355 356 __set_gpio_level_p3(group, pin, value);357}358 359static void lpc32xx_gpo_set_value(struct gpio_chip *chip, unsigned pin,360 int value)361{362 struct lpc32xx_gpio_chip *group = gpiochip_get_data(chip);363 364 __set_gpo_level_p3(group, pin, value);365}366 367static int lpc32xx_gpo_get_value(struct gpio_chip *chip, unsigned pin)368{369 struct lpc32xx_gpio_chip *group = gpiochip_get_data(chip);370 371 return !!__get_gpo_state_p3(group, pin);372}373 374static int lpc32xx_gpio_request(struct gpio_chip *chip, unsigned pin)375{376 if (pin < chip->ngpio)377 return 0;378 379 return -EINVAL;380}381 382static int lpc32xx_gpio_to_irq_p01(struct gpio_chip *chip, unsigned offset)383{384 return -ENXIO;385}386 387static int lpc32xx_gpio_to_irq_gpio_p3(struct gpio_chip *chip, unsigned offset)388{389 return -ENXIO;390}391 392static int lpc32xx_gpio_to_irq_gpi_p3(struct gpio_chip *chip, unsigned offset)393{394 return -ENXIO;395}396 397static struct lpc32xx_gpio_chip lpc32xx_gpiochip[] = {398 {399 .chip = {400 .label = "gpio_p0",401 .direction_input = lpc32xx_gpio_dir_input_p012,402 .get = lpc32xx_gpio_get_value_p012,403 .direction_output = lpc32xx_gpio_dir_output_p012,404 .set = lpc32xx_gpio_set_value_p012,405 .request = lpc32xx_gpio_request,406 .to_irq = lpc32xx_gpio_to_irq_p01,407 .base = LPC32XX_GPIO_P0_GRP,408 .ngpio = LPC32XX_GPIO_P0_MAX,409 .names = gpio_p0_names,410 .can_sleep = false,411 },412 .gpio_grp = &gpio_grp_regs_p0,413 },414 {415 .chip = {416 .label = "gpio_p1",417 .direction_input = lpc32xx_gpio_dir_input_p012,418 .get = lpc32xx_gpio_get_value_p012,419 .direction_output = lpc32xx_gpio_dir_output_p012,420 .set = lpc32xx_gpio_set_value_p012,421 .request = lpc32xx_gpio_request,422 .to_irq = lpc32xx_gpio_to_irq_p01,423 .base = LPC32XX_GPIO_P1_GRP,424 .ngpio = LPC32XX_GPIO_P1_MAX,425 .names = gpio_p1_names,426 .can_sleep = false,427 },428 .gpio_grp = &gpio_grp_regs_p1,429 },430 {431 .chip = {432 .label = "gpio_p2",433 .direction_input = lpc32xx_gpio_dir_input_p012,434 .get = lpc32xx_gpio_get_value_p012,435 .direction_output = lpc32xx_gpio_dir_output_p012,436 .set = lpc32xx_gpio_set_value_p012,437 .request = lpc32xx_gpio_request,438 .base = LPC32XX_GPIO_P2_GRP,439 .ngpio = LPC32XX_GPIO_P2_MAX,440 .names = gpio_p2_names,441 .can_sleep = false,442 },443 .gpio_grp = &gpio_grp_regs_p2,444 },445 {446 .chip = {447 .label = "gpio_p3",448 .direction_input = lpc32xx_gpio_dir_input_p3,449 .get = lpc32xx_gpio_get_value_p3,450 .direction_output = lpc32xx_gpio_dir_output_p3,451 .set = lpc32xx_gpio_set_value_p3,452 .request = lpc32xx_gpio_request,453 .to_irq = lpc32xx_gpio_to_irq_gpio_p3,454 .base = LPC32XX_GPIO_P3_GRP,455 .ngpio = LPC32XX_GPIO_P3_MAX,456 .names = gpio_p3_names,457 .can_sleep = false,458 },459 .gpio_grp = &gpio_grp_regs_p3,460 },461 {462 .chip = {463 .label = "gpi_p3",464 .direction_input = lpc32xx_gpio_dir_in_always,465 .get = lpc32xx_gpi_get_value,466 .request = lpc32xx_gpio_request,467 .to_irq = lpc32xx_gpio_to_irq_gpi_p3,468 .base = LPC32XX_GPI_P3_GRP,469 .ngpio = LPC32XX_GPI_P3_MAX,470 .names = gpi_p3_names,471 .can_sleep = false,472 },473 .gpio_grp = &gpio_grp_regs_p3,474 },475 {476 .chip = {477 .label = "gpo_p3",478 .direction_output = lpc32xx_gpio_dir_out_always,479 .set = lpc32xx_gpo_set_value,480 .get = lpc32xx_gpo_get_value,481 .request = lpc32xx_gpio_request,482 .base = LPC32XX_GPO_P3_GRP,483 .ngpio = LPC32XX_GPO_P3_MAX,484 .names = gpo_p3_names,485 .can_sleep = false,486 },487 .gpio_grp = &gpio_grp_regs_p3,488 },489};490 491static int lpc32xx_of_xlate(struct gpio_chip *gc,492 const struct of_phandle_args *gpiospec, u32 *flags)493{494 /* Is this the correct bank? */495 u32 bank = gpiospec->args[0];496 if ((bank >= ARRAY_SIZE(lpc32xx_gpiochip) ||497 (gc != &lpc32xx_gpiochip[bank].chip)))498 return -EINVAL;499 500 if (flags)501 *flags = gpiospec->args[2];502 return gpiospec->args[1];503}504 505static int lpc32xx_gpio_probe(struct platform_device *pdev)506{507 int i;508 void __iomem *reg_base;509 510 reg_base = devm_platform_ioremap_resource(pdev, 0);511 if (IS_ERR(reg_base))512 return PTR_ERR(reg_base);513 514 for (i = 0; i < ARRAY_SIZE(lpc32xx_gpiochip); i++) {515 lpc32xx_gpiochip[i].chip.parent = &pdev->dev;516 if (pdev->dev.of_node) {517 lpc32xx_gpiochip[i].chip.of_xlate = lpc32xx_of_xlate;518 lpc32xx_gpiochip[i].chip.of_gpio_n_cells = 3;519 lpc32xx_gpiochip[i].reg_base = reg_base;520 }521 devm_gpiochip_add_data(&pdev->dev, &lpc32xx_gpiochip[i].chip,522 &lpc32xx_gpiochip[i]);523 }524 525 return 0;526}527 528static const struct of_device_id lpc32xx_gpio_of_match[] = {529 { .compatible = "nxp,lpc3220-gpio", },530 { },531};532MODULE_DEVICE_TABLE(of, lpc32xx_gpio_of_match);533 534static struct platform_driver lpc32xx_gpio_driver = {535 .driver = {536 .name = "lpc32xx-gpio",537 .of_match_table = lpc32xx_gpio_of_match,538 },539 .probe = lpc32xx_gpio_probe,540};541 542module_platform_driver(lpc32xx_gpio_driver);543 544MODULE_AUTHOR("Kevin Wells <kevin.wells@nxp.com>");545MODULE_LICENSE("GPL");546MODULE_DESCRIPTION("GPIO driver for LPC32xx SoC");547