| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * GPIO driver for LPC32xx SoC |
|---|
| 3 | 4 | * |
|---|
| 4 | 5 | * Author: Kevin Wells <kevin.wells@nxp.com> |
|---|
| 5 | 6 | * |
|---|
| 6 | 7 | * Copyright (C) 2010 NXP Semiconductors |
|---|
| 7 | | - * |
|---|
| 8 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 9 | | - * it under the terms of the GNU General Public License as published by |
|---|
| 10 | | - * the Free Software Foundation; either version 2 of the License, or |
|---|
| 11 | | - * (at your option) any later version. |
|---|
| 12 | | - * |
|---|
| 13 | | - * This program is distributed in the hope that it will be useful, |
|---|
| 14 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 15 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 16 | | - * GNU General Public License for more details. |
|---|
| 17 | 8 | */ |
|---|
| 18 | 9 | |
|---|
| 19 | 10 | #include <linux/kernel.h> |
|---|
| .. | .. |
|---|
| 25 | 16 | #include <linux/platform_device.h> |
|---|
| 26 | 17 | #include <linux/module.h> |
|---|
| 27 | 18 | |
|---|
| 28 | | -#include <mach/hardware.h> |
|---|
| 29 | | -#include <mach/platform.h> |
|---|
| 30 | | - |
|---|
| 31 | | -#define LPC32XX_GPIO_P3_INP_STATE _GPREG(0x000) |
|---|
| 32 | | -#define LPC32XX_GPIO_P3_OUTP_SET _GPREG(0x004) |
|---|
| 33 | | -#define LPC32XX_GPIO_P3_OUTP_CLR _GPREG(0x008) |
|---|
| 34 | | -#define LPC32XX_GPIO_P3_OUTP_STATE _GPREG(0x00C) |
|---|
| 35 | | -#define LPC32XX_GPIO_P2_DIR_SET _GPREG(0x010) |
|---|
| 36 | | -#define LPC32XX_GPIO_P2_DIR_CLR _GPREG(0x014) |
|---|
| 37 | | -#define LPC32XX_GPIO_P2_DIR_STATE _GPREG(0x018) |
|---|
| 38 | | -#define LPC32XX_GPIO_P2_INP_STATE _GPREG(0x01C) |
|---|
| 39 | | -#define LPC32XX_GPIO_P2_OUTP_SET _GPREG(0x020) |
|---|
| 40 | | -#define LPC32XX_GPIO_P2_OUTP_CLR _GPREG(0x024) |
|---|
| 41 | | -#define LPC32XX_GPIO_P2_MUX_SET _GPREG(0x028) |
|---|
| 42 | | -#define LPC32XX_GPIO_P2_MUX_CLR _GPREG(0x02C) |
|---|
| 43 | | -#define LPC32XX_GPIO_P2_MUX_STATE _GPREG(0x030) |
|---|
| 44 | | -#define LPC32XX_GPIO_P0_INP_STATE _GPREG(0x040) |
|---|
| 45 | | -#define LPC32XX_GPIO_P0_OUTP_SET _GPREG(0x044) |
|---|
| 46 | | -#define LPC32XX_GPIO_P0_OUTP_CLR _GPREG(0x048) |
|---|
| 47 | | -#define LPC32XX_GPIO_P0_OUTP_STATE _GPREG(0x04C) |
|---|
| 48 | | -#define LPC32XX_GPIO_P0_DIR_SET _GPREG(0x050) |
|---|
| 49 | | -#define LPC32XX_GPIO_P0_DIR_CLR _GPREG(0x054) |
|---|
| 50 | | -#define LPC32XX_GPIO_P0_DIR_STATE _GPREG(0x058) |
|---|
| 51 | | -#define LPC32XX_GPIO_P1_INP_STATE _GPREG(0x060) |
|---|
| 52 | | -#define LPC32XX_GPIO_P1_OUTP_SET _GPREG(0x064) |
|---|
| 53 | | -#define LPC32XX_GPIO_P1_OUTP_CLR _GPREG(0x068) |
|---|
| 54 | | -#define LPC32XX_GPIO_P1_OUTP_STATE _GPREG(0x06C) |
|---|
| 55 | | -#define LPC32XX_GPIO_P1_DIR_SET _GPREG(0x070) |
|---|
| 56 | | -#define LPC32XX_GPIO_P1_DIR_CLR _GPREG(0x074) |
|---|
| 57 | | -#define LPC32XX_GPIO_P1_DIR_STATE _GPREG(0x078) |
|---|
| 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) |
|---|
| 58 | 46 | |
|---|
| 59 | 47 | #define GPIO012_PIN_TO_BIT(x) (1 << (x)) |
|---|
| 60 | 48 | #define GPIO3_PIN_TO_BIT(x) (1 << ((x) + 25)) |
|---|
| .. | .. |
|---|
| 81 | 69 | #define LPC32XX_GPO_P3_GRP (LPC32XX_GPI_P3_GRP + LPC32XX_GPI_P3_MAX) |
|---|
| 82 | 70 | |
|---|
| 83 | 71 | struct gpio_regs { |
|---|
| 84 | | - void __iomem *inp_state; |
|---|
| 85 | | - void __iomem *outp_state; |
|---|
| 86 | | - void __iomem *outp_set; |
|---|
| 87 | | - void __iomem *outp_clr; |
|---|
| 88 | | - void __iomem *dir_set; |
|---|
| 89 | | - void __iomem *dir_clr; |
|---|
| 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; |
|---|
| 90 | 78 | }; |
|---|
| 91 | 79 | |
|---|
| 92 | 80 | /* |
|---|
| .. | .. |
|---|
| 174 | 162 | struct lpc32xx_gpio_chip { |
|---|
| 175 | 163 | struct gpio_chip chip; |
|---|
| 176 | 164 | struct gpio_regs *gpio_grp; |
|---|
| 165 | + void __iomem *reg_base; |
|---|
| 177 | 166 | }; |
|---|
| 167 | + |
|---|
| 168 | +static inline u32 gpreg_read(struct lpc32xx_gpio_chip *group, unsigned long offset) |
|---|
| 169 | +{ |
|---|
| 170 | + return __raw_readl(group->reg_base + offset); |
|---|
| 171 | +} |
|---|
| 172 | + |
|---|
| 173 | +static inline void gpreg_write(struct lpc32xx_gpio_chip *group, u32 val, unsigned long offset) |
|---|
| 174 | +{ |
|---|
| 175 | + __raw_writel(val, group->reg_base + offset); |
|---|
| 176 | +} |
|---|
| 178 | 177 | |
|---|
| 179 | 178 | static void __set_gpio_dir_p012(struct lpc32xx_gpio_chip *group, |
|---|
| 180 | 179 | unsigned pin, int input) |
|---|
| 181 | 180 | { |
|---|
| 182 | 181 | if (input) |
|---|
| 183 | | - __raw_writel(GPIO012_PIN_TO_BIT(pin), |
|---|
| 182 | + gpreg_write(group, GPIO012_PIN_TO_BIT(pin), |
|---|
| 184 | 183 | group->gpio_grp->dir_clr); |
|---|
| 185 | 184 | else |
|---|
| 186 | | - __raw_writel(GPIO012_PIN_TO_BIT(pin), |
|---|
| 185 | + gpreg_write(group, GPIO012_PIN_TO_BIT(pin), |
|---|
| 187 | 186 | group->gpio_grp->dir_set); |
|---|
| 188 | 187 | } |
|---|
| 189 | 188 | |
|---|
| .. | .. |
|---|
| 193 | 192 | u32 u = GPIO3_PIN_TO_BIT(pin); |
|---|
| 194 | 193 | |
|---|
| 195 | 194 | if (input) |
|---|
| 196 | | - __raw_writel(u, group->gpio_grp->dir_clr); |
|---|
| 195 | + gpreg_write(group, u, group->gpio_grp->dir_clr); |
|---|
| 197 | 196 | else |
|---|
| 198 | | - __raw_writel(u, group->gpio_grp->dir_set); |
|---|
| 197 | + gpreg_write(group, u, group->gpio_grp->dir_set); |
|---|
| 199 | 198 | } |
|---|
| 200 | 199 | |
|---|
| 201 | 200 | static void __set_gpio_level_p012(struct lpc32xx_gpio_chip *group, |
|---|
| 202 | 201 | unsigned pin, int high) |
|---|
| 203 | 202 | { |
|---|
| 204 | 203 | if (high) |
|---|
| 205 | | - __raw_writel(GPIO012_PIN_TO_BIT(pin), |
|---|
| 204 | + gpreg_write(group, GPIO012_PIN_TO_BIT(pin), |
|---|
| 206 | 205 | group->gpio_grp->outp_set); |
|---|
| 207 | 206 | else |
|---|
| 208 | | - __raw_writel(GPIO012_PIN_TO_BIT(pin), |
|---|
| 207 | + gpreg_write(group, GPIO012_PIN_TO_BIT(pin), |
|---|
| 209 | 208 | group->gpio_grp->outp_clr); |
|---|
| 210 | 209 | } |
|---|
| 211 | 210 | |
|---|
| .. | .. |
|---|
| 215 | 214 | u32 u = GPIO3_PIN_TO_BIT(pin); |
|---|
| 216 | 215 | |
|---|
| 217 | 216 | if (high) |
|---|
| 218 | | - __raw_writel(u, group->gpio_grp->outp_set); |
|---|
| 217 | + gpreg_write(group, u, group->gpio_grp->outp_set); |
|---|
| 219 | 218 | else |
|---|
| 220 | | - __raw_writel(u, group->gpio_grp->outp_clr); |
|---|
| 219 | + gpreg_write(group, u, group->gpio_grp->outp_clr); |
|---|
| 221 | 220 | } |
|---|
| 222 | 221 | |
|---|
| 223 | 222 | static void __set_gpo_level_p3(struct lpc32xx_gpio_chip *group, |
|---|
| 224 | 223 | unsigned pin, int high) |
|---|
| 225 | 224 | { |
|---|
| 226 | 225 | if (high) |
|---|
| 227 | | - __raw_writel(GPO3_PIN_TO_BIT(pin), group->gpio_grp->outp_set); |
|---|
| 226 | + gpreg_write(group, GPO3_PIN_TO_BIT(pin), group->gpio_grp->outp_set); |
|---|
| 228 | 227 | else |
|---|
| 229 | | - __raw_writel(GPO3_PIN_TO_BIT(pin), group->gpio_grp->outp_clr); |
|---|
| 228 | + gpreg_write(group, GPO3_PIN_TO_BIT(pin), group->gpio_grp->outp_clr); |
|---|
| 230 | 229 | } |
|---|
| 231 | 230 | |
|---|
| 232 | 231 | static int __get_gpio_state_p012(struct lpc32xx_gpio_chip *group, |
|---|
| 233 | 232 | unsigned pin) |
|---|
| 234 | 233 | { |
|---|
| 235 | | - return GPIO012_PIN_IN_SEL(__raw_readl(group->gpio_grp->inp_state), |
|---|
| 234 | + return GPIO012_PIN_IN_SEL(gpreg_read(group, group->gpio_grp->inp_state), |
|---|
| 236 | 235 | pin); |
|---|
| 237 | 236 | } |
|---|
| 238 | 237 | |
|---|
| 239 | 238 | static int __get_gpio_state_p3(struct lpc32xx_gpio_chip *group, |
|---|
| 240 | 239 | unsigned pin) |
|---|
| 241 | 240 | { |
|---|
| 242 | | - int state = __raw_readl(group->gpio_grp->inp_state); |
|---|
| 241 | + int state = gpreg_read(group, group->gpio_grp->inp_state); |
|---|
| 243 | 242 | |
|---|
| 244 | 243 | /* |
|---|
| 245 | 244 | * P3 GPIO pin input mapping is not contiguous, GPIOP3-0..4 is mapped |
|---|
| .. | .. |
|---|
| 251 | 250 | static int __get_gpi_state_p3(struct lpc32xx_gpio_chip *group, |
|---|
| 252 | 251 | unsigned pin) |
|---|
| 253 | 252 | { |
|---|
| 254 | | - return GPI3_PIN_IN_SEL(__raw_readl(group->gpio_grp->inp_state), pin); |
|---|
| 253 | + return GPI3_PIN_IN_SEL(gpreg_read(group, group->gpio_grp->inp_state), pin); |
|---|
| 255 | 254 | } |
|---|
| 256 | 255 | |
|---|
| 257 | 256 | static int __get_gpo_state_p3(struct lpc32xx_gpio_chip *group, |
|---|
| 258 | 257 | unsigned pin) |
|---|
| 259 | 258 | { |
|---|
| 260 | | - return GPO3_PIN_IN_SEL(__raw_readl(group->gpio_grp->outp_state), pin); |
|---|
| 259 | + return GPO3_PIN_IN_SEL(gpreg_read(group, group->gpio_grp->outp_state), pin); |
|---|
| 261 | 260 | } |
|---|
| 262 | 261 | |
|---|
| 263 | 262 | /* |
|---|
| .. | .. |
|---|
| 506 | 505 | static int lpc32xx_gpio_probe(struct platform_device *pdev) |
|---|
| 507 | 506 | { |
|---|
| 508 | 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); |
|---|
| 509 | 513 | |
|---|
| 510 | 514 | for (i = 0; i < ARRAY_SIZE(lpc32xx_gpiochip); i++) { |
|---|
| 511 | 515 | if (pdev->dev.of_node) { |
|---|
| 512 | 516 | lpc32xx_gpiochip[i].chip.of_xlate = lpc32xx_of_xlate; |
|---|
| 513 | 517 | lpc32xx_gpiochip[i].chip.of_gpio_n_cells = 3; |
|---|
| 514 | 518 | lpc32xx_gpiochip[i].chip.of_node = pdev->dev.of_node; |
|---|
| 519 | + lpc32xx_gpiochip[i].reg_base = reg_base; |
|---|
| 515 | 520 | } |
|---|
| 516 | 521 | devm_gpiochip_add_data(&pdev->dev, &lpc32xx_gpiochip[i].chip, |
|---|
| 517 | 522 | &lpc32xx_gpiochip[i]); |
|---|
| .. | .. |
|---|
| 536 | 541 | }; |
|---|
| 537 | 542 | |
|---|
| 538 | 543 | module_platform_driver(lpc32xx_gpio_driver); |
|---|
| 544 | + |
|---|
| 545 | +MODULE_AUTHOR("Kevin Wells <kevin.wells@nxp.com>"); |
|---|
| 546 | +MODULE_LICENSE("GPL"); |
|---|
| 547 | +MODULE_DESCRIPTION("GPIO driver for LPC32xx SoC"); |
|---|