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