Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v6.17-rc3 368 lines 9.2 kB view raw
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * MPC52xx gpio driver 4 * 5 * Copyright (c) 2008 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix 6 */ 7 8#include <linux/of.h> 9#include <linux/kernel.h> 10#include <linux/slab.h> 11#include <linux/gpio/legacy-of-mm-gpiochip.h> 12#include <linux/io.h> 13#include <linux/platform_device.h> 14#include <linux/module.h> 15 16#include <asm/mpc52xx.h> 17#include <sysdev/fsl_soc.h> 18 19static DEFINE_SPINLOCK(gpio_lock); 20 21struct mpc52xx_gpiochip { 22 struct of_mm_gpio_chip mmchip; 23 unsigned int shadow_dvo; 24 unsigned int shadow_gpioe; 25 unsigned int shadow_ddr; 26}; 27 28/* 29 * GPIO LIB API implementation for wakeup GPIOs. 30 * 31 * There's a maximum of 8 wakeup GPIOs. Which of these are available 32 * for use depends on your board setup. 33 * 34 * 0 -> GPIO_WKUP_7 35 * 1 -> GPIO_WKUP_6 36 * 2 -> PSC6_1 37 * 3 -> PSC6_0 38 * 4 -> ETH_17 39 * 5 -> PSC3_9 40 * 6 -> PSC2_4 41 * 7 -> PSC1_4 42 * 43 */ 44static int mpc52xx_wkup_gpio_get(struct gpio_chip *gc, unsigned int gpio) 45{ 46 struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); 47 struct mpc52xx_gpio_wkup __iomem *regs = mm_gc->regs; 48 unsigned int ret; 49 50 ret = (in_8(&regs->wkup_ival) >> (7 - gpio)) & 1; 51 52 pr_debug("%s: gpio: %d ret: %d\n", __func__, gpio, ret); 53 54 return ret; 55} 56 57static inline void 58__mpc52xx_wkup_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val) 59{ 60 struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); 61 struct mpc52xx_gpiochip *chip = gpiochip_get_data(gc); 62 struct mpc52xx_gpio_wkup __iomem *regs = mm_gc->regs; 63 64 if (val) 65 chip->shadow_dvo |= 1 << (7 - gpio); 66 else 67 chip->shadow_dvo &= ~(1 << (7 - gpio)); 68 69 out_8(&regs->wkup_dvo, chip->shadow_dvo); 70} 71 72static int 73mpc52xx_wkup_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val) 74{ 75 unsigned long flags; 76 77 spin_lock_irqsave(&gpio_lock, flags); 78 79 __mpc52xx_wkup_gpio_set(gc, gpio, val); 80 81 spin_unlock_irqrestore(&gpio_lock, flags); 82 83 pr_debug("%s: gpio: %d val: %d\n", __func__, gpio, val); 84 85 return 0; 86} 87 88static int mpc52xx_wkup_gpio_dir_in(struct gpio_chip *gc, unsigned int gpio) 89{ 90 struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); 91 struct mpc52xx_gpiochip *chip = gpiochip_get_data(gc); 92 struct mpc52xx_gpio_wkup __iomem *regs = mm_gc->regs; 93 unsigned long flags; 94 95 spin_lock_irqsave(&gpio_lock, flags); 96 97 /* set the direction */ 98 chip->shadow_ddr &= ~(1 << (7 - gpio)); 99 out_8(&regs->wkup_ddr, chip->shadow_ddr); 100 101 /* and enable the pin */ 102 chip->shadow_gpioe |= 1 << (7 - gpio); 103 out_8(&regs->wkup_gpioe, chip->shadow_gpioe); 104 105 spin_unlock_irqrestore(&gpio_lock, flags); 106 107 return 0; 108} 109 110static int 111mpc52xx_wkup_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) 112{ 113 struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); 114 struct mpc52xx_gpio_wkup __iomem *regs = mm_gc->regs; 115 struct mpc52xx_gpiochip *chip = gpiochip_get_data(gc); 116 unsigned long flags; 117 118 spin_lock_irqsave(&gpio_lock, flags); 119 120 __mpc52xx_wkup_gpio_set(gc, gpio, val); 121 122 /* Then set direction */ 123 chip->shadow_ddr |= 1 << (7 - gpio); 124 out_8(&regs->wkup_ddr, chip->shadow_ddr); 125 126 /* Finally enable the pin */ 127 chip->shadow_gpioe |= 1 << (7 - gpio); 128 out_8(&regs->wkup_gpioe, chip->shadow_gpioe); 129 130 spin_unlock_irqrestore(&gpio_lock, flags); 131 132 pr_debug("%s: gpio: %d val: %d\n", __func__, gpio, val); 133 134 return 0; 135} 136 137static int mpc52xx_wkup_gpiochip_probe(struct platform_device *ofdev) 138{ 139 struct mpc52xx_gpiochip *chip; 140 struct mpc52xx_gpio_wkup __iomem *regs; 141 struct gpio_chip *gc; 142 int ret; 143 144 chip = devm_kzalloc(&ofdev->dev, sizeof(*chip), GFP_KERNEL); 145 if (!chip) 146 return -ENOMEM; 147 148 platform_set_drvdata(ofdev, chip); 149 150 gc = &chip->mmchip.gc; 151 152 gc->ngpio = 8; 153 gc->direction_input = mpc52xx_wkup_gpio_dir_in; 154 gc->direction_output = mpc52xx_wkup_gpio_dir_out; 155 gc->get = mpc52xx_wkup_gpio_get; 156 gc->set = mpc52xx_wkup_gpio_set; 157 158 ret = of_mm_gpiochip_add_data(ofdev->dev.of_node, &chip->mmchip, chip); 159 if (ret) 160 return ret; 161 162 regs = chip->mmchip.regs; 163 chip->shadow_gpioe = in_8(&regs->wkup_gpioe); 164 chip->shadow_ddr = in_8(&regs->wkup_ddr); 165 chip->shadow_dvo = in_8(&regs->wkup_dvo); 166 167 return 0; 168} 169 170static void mpc52xx_gpiochip_remove(struct platform_device *ofdev) 171{ 172 struct mpc52xx_gpiochip *chip = platform_get_drvdata(ofdev); 173 174 of_mm_gpiochip_remove(&chip->mmchip); 175} 176 177static const struct of_device_id mpc52xx_wkup_gpiochip_match[] = { 178 { .compatible = "fsl,mpc5200-gpio-wkup", }, 179 {} 180}; 181 182static struct platform_driver mpc52xx_wkup_gpiochip_driver = { 183 .driver = { 184 .name = "mpc5200-gpio-wkup", 185 .of_match_table = mpc52xx_wkup_gpiochip_match, 186 }, 187 .probe = mpc52xx_wkup_gpiochip_probe, 188 .remove = mpc52xx_gpiochip_remove, 189}; 190 191/* 192 * GPIO LIB API implementation for simple GPIOs 193 * 194 * There's a maximum of 32 simple GPIOs. Which of these are available 195 * for use depends on your board setup. 196 * The numbering reflects the bit numbering in the port registers: 197 * 198 * 0..1 > reserved 199 * 2..3 > IRDA 200 * 4..7 > ETHR 201 * 8..11 > reserved 202 * 12..15 > USB 203 * 16..17 > reserved 204 * 18..23 > PSC3 205 * 24..27 > PSC2 206 * 28..31 > PSC1 207 */ 208static int mpc52xx_simple_gpio_get(struct gpio_chip *gc, unsigned int gpio) 209{ 210 struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); 211 struct mpc52xx_gpio __iomem *regs = mm_gc->regs; 212 unsigned int ret; 213 214 ret = (in_be32(&regs->simple_ival) >> (31 - gpio)) & 1; 215 216 return ret; 217} 218 219static inline void 220__mpc52xx_simple_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val) 221{ 222 struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); 223 struct mpc52xx_gpiochip *chip = gpiochip_get_data(gc); 224 struct mpc52xx_gpio __iomem *regs = mm_gc->regs; 225 226 if (val) 227 chip->shadow_dvo |= 1 << (31 - gpio); 228 else 229 chip->shadow_dvo &= ~(1 << (31 - gpio)); 230 out_be32(&regs->simple_dvo, chip->shadow_dvo); 231} 232 233static int 234mpc52xx_simple_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val) 235{ 236 unsigned long flags; 237 238 spin_lock_irqsave(&gpio_lock, flags); 239 240 __mpc52xx_simple_gpio_set(gc, gpio, val); 241 242 spin_unlock_irqrestore(&gpio_lock, flags); 243 244 pr_debug("%s: gpio: %d val: %d\n", __func__, gpio, val); 245 246 return 0; 247} 248 249static int mpc52xx_simple_gpio_dir_in(struct gpio_chip *gc, unsigned int gpio) 250{ 251 struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); 252 struct mpc52xx_gpiochip *chip = gpiochip_get_data(gc); 253 struct mpc52xx_gpio __iomem *regs = mm_gc->regs; 254 unsigned long flags; 255 256 spin_lock_irqsave(&gpio_lock, flags); 257 258 /* set the direction */ 259 chip->shadow_ddr &= ~(1 << (31 - gpio)); 260 out_be32(&regs->simple_ddr, chip->shadow_ddr); 261 262 /* and enable the pin */ 263 chip->shadow_gpioe |= 1 << (31 - gpio); 264 out_be32(&regs->simple_gpioe, chip->shadow_gpioe); 265 266 spin_unlock_irqrestore(&gpio_lock, flags); 267 268 return 0; 269} 270 271static int 272mpc52xx_simple_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) 273{ 274 struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); 275 struct mpc52xx_gpiochip *chip = gpiochip_get_data(gc); 276 struct mpc52xx_gpio __iomem *regs = mm_gc->regs; 277 unsigned long flags; 278 279 spin_lock_irqsave(&gpio_lock, flags); 280 281 /* First set initial value */ 282 __mpc52xx_simple_gpio_set(gc, gpio, val); 283 284 /* Then set direction */ 285 chip->shadow_ddr |= 1 << (31 - gpio); 286 out_be32(&regs->simple_ddr, chip->shadow_ddr); 287 288 /* Finally enable the pin */ 289 chip->shadow_gpioe |= 1 << (31 - gpio); 290 out_be32(&regs->simple_gpioe, chip->shadow_gpioe); 291 292 spin_unlock_irqrestore(&gpio_lock, flags); 293 294 pr_debug("%s: gpio: %d val: %d\n", __func__, gpio, val); 295 296 return 0; 297} 298 299static int mpc52xx_simple_gpiochip_probe(struct platform_device *ofdev) 300{ 301 struct mpc52xx_gpiochip *chip; 302 struct gpio_chip *gc; 303 struct mpc52xx_gpio __iomem *regs; 304 int ret; 305 306 chip = devm_kzalloc(&ofdev->dev, sizeof(*chip), GFP_KERNEL); 307 if (!chip) 308 return -ENOMEM; 309 310 platform_set_drvdata(ofdev, chip); 311 312 gc = &chip->mmchip.gc; 313 314 gc->ngpio = 32; 315 gc->direction_input = mpc52xx_simple_gpio_dir_in; 316 gc->direction_output = mpc52xx_simple_gpio_dir_out; 317 gc->get = mpc52xx_simple_gpio_get; 318 gc->set = mpc52xx_simple_gpio_set; 319 320 ret = of_mm_gpiochip_add_data(ofdev->dev.of_node, &chip->mmchip, chip); 321 if (ret) 322 return ret; 323 324 regs = chip->mmchip.regs; 325 chip->shadow_gpioe = in_be32(&regs->simple_gpioe); 326 chip->shadow_ddr = in_be32(&regs->simple_ddr); 327 chip->shadow_dvo = in_be32(&regs->simple_dvo); 328 329 return 0; 330} 331 332static const struct of_device_id mpc52xx_simple_gpiochip_match[] = { 333 { .compatible = "fsl,mpc5200-gpio", }, 334 {} 335}; 336 337static struct platform_driver mpc52xx_simple_gpiochip_driver = { 338 .driver = { 339 .name = "mpc5200-gpio", 340 .of_match_table = mpc52xx_simple_gpiochip_match, 341 }, 342 .probe = mpc52xx_simple_gpiochip_probe, 343 .remove = mpc52xx_gpiochip_remove, 344}; 345 346static struct platform_driver * const drivers[] = { 347 &mpc52xx_wkup_gpiochip_driver, 348 &mpc52xx_simple_gpiochip_driver, 349}; 350 351static int __init mpc52xx_gpio_init(void) 352{ 353 return platform_register_drivers(drivers, ARRAY_SIZE(drivers)); 354} 355 356/* Make sure we get initialised before anyone else tries to use us */ 357subsys_initcall(mpc52xx_gpio_init); 358 359static void __exit mpc52xx_gpio_exit(void) 360{ 361 platform_unregister_drivers(drivers, ARRAY_SIZE(drivers)); 362} 363module_exit(mpc52xx_gpio_exit); 364 365MODULE_DESCRIPTION("Freescale MPC52xx gpio driver"); 366MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de"); 367MODULE_LICENSE("GPL v2"); 368