1ef72af40SMichael Hennerich /* 2ef72af40SMichael Hennerich * GPIO driver for Analog Devices ADP5520 MFD PMICs 3ef72af40SMichael Hennerich * 4ef72af40SMichael Hennerich * Copyright 2009 Analog Devices Inc. 5ef72af40SMichael Hennerich * 6ef72af40SMichael Hennerich * Licensed under the GPL-2 or later. 7ef72af40SMichael Hennerich */ 8ef72af40SMichael Hennerich 9ef72af40SMichael Hennerich #include <linux/module.h> 105a0e3ad6STejun Heo #include <linux/slab.h> 11ef72af40SMichael Hennerich #include <linux/kernel.h> 12ef72af40SMichael Hennerich #include <linux/init.h> 13ef72af40SMichael Hennerich #include <linux/platform_device.h> 14ef72af40SMichael Hennerich #include <linux/mfd/adp5520.h> 15ef72af40SMichael Hennerich 16ef72af40SMichael Hennerich #include <linux/gpio.h> 17ef72af40SMichael Hennerich 18ef72af40SMichael Hennerich struct adp5520_gpio { 19ef72af40SMichael Hennerich struct device *master; 20ef72af40SMichael Hennerich struct gpio_chip gpio_chip; 21ef72af40SMichael Hennerich unsigned char lut[ADP5520_MAXGPIOS]; 22ef72af40SMichael Hennerich unsigned long output; 23ef72af40SMichael Hennerich }; 24ef72af40SMichael Hennerich 25ef72af40SMichael Hennerich static int adp5520_gpio_get_value(struct gpio_chip *chip, unsigned off) 26ef72af40SMichael Hennerich { 27ef72af40SMichael Hennerich struct adp5520_gpio *dev; 28ef72af40SMichael Hennerich uint8_t reg_val; 29ef72af40SMichael Hennerich 30ef72af40SMichael Hennerich dev = container_of(chip, struct adp5520_gpio, gpio_chip); 31ef72af40SMichael Hennerich 32ef72af40SMichael Hennerich /* 33ef72af40SMichael Hennerich * There are dedicated registers for GPIO IN/OUT. 34ef72af40SMichael Hennerich * Make sure we return the right value, even when configured as output 35ef72af40SMichael Hennerich */ 36ef72af40SMichael Hennerich 37ef72af40SMichael Hennerich if (test_bit(off, &dev->output)) 387c29a476SMichael Hennerich adp5520_read(dev->master, ADP5520_GPIO_OUT, ®_val); 39ef72af40SMichael Hennerich else 407c29a476SMichael Hennerich adp5520_read(dev->master, ADP5520_GPIO_IN, ®_val); 41ef72af40SMichael Hennerich 42ef72af40SMichael Hennerich return !!(reg_val & dev->lut[off]); 43ef72af40SMichael Hennerich } 44ef72af40SMichael Hennerich 45ef72af40SMichael Hennerich static void adp5520_gpio_set_value(struct gpio_chip *chip, 46ef72af40SMichael Hennerich unsigned off, int val) 47ef72af40SMichael Hennerich { 48ef72af40SMichael Hennerich struct adp5520_gpio *dev; 49ef72af40SMichael Hennerich dev = container_of(chip, struct adp5520_gpio, gpio_chip); 50ef72af40SMichael Hennerich 51ef72af40SMichael Hennerich if (val) 527c29a476SMichael Hennerich adp5520_set_bits(dev->master, ADP5520_GPIO_OUT, dev->lut[off]); 53ef72af40SMichael Hennerich else 547c29a476SMichael Hennerich adp5520_clr_bits(dev->master, ADP5520_GPIO_OUT, dev->lut[off]); 55ef72af40SMichael Hennerich } 56ef72af40SMichael Hennerich 57ef72af40SMichael Hennerich static int adp5520_gpio_direction_input(struct gpio_chip *chip, unsigned off) 58ef72af40SMichael Hennerich { 59ef72af40SMichael Hennerich struct adp5520_gpio *dev; 60ef72af40SMichael Hennerich dev = container_of(chip, struct adp5520_gpio, gpio_chip); 61ef72af40SMichael Hennerich 62ef72af40SMichael Hennerich clear_bit(off, &dev->output); 63ef72af40SMichael Hennerich 647c29a476SMichael Hennerich return adp5520_clr_bits(dev->master, ADP5520_GPIO_CFG_2, 657c29a476SMichael Hennerich dev->lut[off]); 66ef72af40SMichael Hennerich } 67ef72af40SMichael Hennerich 68ef72af40SMichael Hennerich static int adp5520_gpio_direction_output(struct gpio_chip *chip, 69ef72af40SMichael Hennerich unsigned off, int val) 70ef72af40SMichael Hennerich { 71ef72af40SMichael Hennerich struct adp5520_gpio *dev; 72ef72af40SMichael Hennerich int ret = 0; 73ef72af40SMichael Hennerich dev = container_of(chip, struct adp5520_gpio, gpio_chip); 74ef72af40SMichael Hennerich 75ef72af40SMichael Hennerich set_bit(off, &dev->output); 76ef72af40SMichael Hennerich 77ef72af40SMichael Hennerich if (val) 787c29a476SMichael Hennerich ret |= adp5520_set_bits(dev->master, ADP5520_GPIO_OUT, 797c29a476SMichael Hennerich dev->lut[off]); 80ef72af40SMichael Hennerich else 817c29a476SMichael Hennerich ret |= adp5520_clr_bits(dev->master, ADP5520_GPIO_OUT, 827c29a476SMichael Hennerich dev->lut[off]); 83ef72af40SMichael Hennerich 847c29a476SMichael Hennerich ret |= adp5520_set_bits(dev->master, ADP5520_GPIO_CFG_2, 857c29a476SMichael Hennerich dev->lut[off]); 86ef72af40SMichael Hennerich 87ef72af40SMichael Hennerich return ret; 88ef72af40SMichael Hennerich } 89ef72af40SMichael Hennerich 903836309dSBill Pemberton static int adp5520_gpio_probe(struct platform_device *pdev) 91ef72af40SMichael Hennerich { 92*e56aee18SJingoo Han struct adp5520_gpio_platform_data *pdata = dev_get_platdata(&pdev->dev); 93ef72af40SMichael Hennerich struct adp5520_gpio *dev; 94ef72af40SMichael Hennerich struct gpio_chip *gc; 95ef72af40SMichael Hennerich int ret, i, gpios; 96ef72af40SMichael Hennerich unsigned char ctl_mask = 0; 97ef72af40SMichael Hennerich 98ef72af40SMichael Hennerich if (pdata == NULL) { 99ef72af40SMichael Hennerich dev_err(&pdev->dev, "missing platform data\n"); 100ef72af40SMichael Hennerich return -ENODEV; 101ef72af40SMichael Hennerich } 102ef72af40SMichael Hennerich 103ef72af40SMichael Hennerich if (pdev->id != ID_ADP5520) { 104ef72af40SMichael Hennerich dev_err(&pdev->dev, "only ADP5520 supports GPIO\n"); 105ef72af40SMichael Hennerich return -ENODEV; 106ef72af40SMichael Hennerich } 107ef72af40SMichael Hennerich 10824bb3813SJingoo Han dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL); 109ef72af40SMichael Hennerich if (dev == NULL) { 110ef72af40SMichael Hennerich dev_err(&pdev->dev, "failed to alloc memory\n"); 111ef72af40SMichael Hennerich return -ENOMEM; 112ef72af40SMichael Hennerich } 113ef72af40SMichael Hennerich 114ef72af40SMichael Hennerich dev->master = pdev->dev.parent; 115ef72af40SMichael Hennerich 116ef72af40SMichael Hennerich for (gpios = 0, i = 0; i < ADP5520_MAXGPIOS; i++) 117ef72af40SMichael Hennerich if (pdata->gpio_en_mask & (1 << i)) 118ef72af40SMichael Hennerich dev->lut[gpios++] = 1 << i; 119ef72af40SMichael Hennerich 120ef72af40SMichael Hennerich if (gpios < 1) { 121ef72af40SMichael Hennerich ret = -EINVAL; 122ef72af40SMichael Hennerich goto err; 123ef72af40SMichael Hennerich } 124ef72af40SMichael Hennerich 125ef72af40SMichael Hennerich gc = &dev->gpio_chip; 126ef72af40SMichael Hennerich gc->direction_input = adp5520_gpio_direction_input; 127ef72af40SMichael Hennerich gc->direction_output = adp5520_gpio_direction_output; 128ef72af40SMichael Hennerich gc->get = adp5520_gpio_get_value; 129ef72af40SMichael Hennerich gc->set = adp5520_gpio_set_value; 130ef72af40SMichael Hennerich gc->can_sleep = 1; 131ef72af40SMichael Hennerich 132ef72af40SMichael Hennerich gc->base = pdata->gpio_start; 133ef72af40SMichael Hennerich gc->ngpio = gpios; 134ef72af40SMichael Hennerich gc->label = pdev->name; 135ef72af40SMichael Hennerich gc->owner = THIS_MODULE; 136ef72af40SMichael Hennerich 1377c29a476SMichael Hennerich ret = adp5520_clr_bits(dev->master, ADP5520_GPIO_CFG_1, 138ef72af40SMichael Hennerich pdata->gpio_en_mask); 139ef72af40SMichael Hennerich 1407c29a476SMichael Hennerich if (pdata->gpio_en_mask & ADP5520_GPIO_C3) 1417c29a476SMichael Hennerich ctl_mask |= ADP5520_C3_MODE; 142ef72af40SMichael Hennerich 1437c29a476SMichael Hennerich if (pdata->gpio_en_mask & ADP5520_GPIO_R3) 1447c29a476SMichael Hennerich ctl_mask |= ADP5520_R3_MODE; 145ef72af40SMichael Hennerich 146ef72af40SMichael Hennerich if (ctl_mask) 1477c29a476SMichael Hennerich ret = adp5520_set_bits(dev->master, ADP5520_LED_CONTROL, 148ef72af40SMichael Hennerich ctl_mask); 149ef72af40SMichael Hennerich 1507c29a476SMichael Hennerich ret |= adp5520_set_bits(dev->master, ADP5520_GPIO_PULLUP, 151ef72af40SMichael Hennerich pdata->gpio_pullup_mask); 152ef72af40SMichael Hennerich 153ef72af40SMichael Hennerich if (ret) { 154ef72af40SMichael Hennerich dev_err(&pdev->dev, "failed to write\n"); 155ef72af40SMichael Hennerich goto err; 156ef72af40SMichael Hennerich } 157ef72af40SMichael Hennerich 158ef72af40SMichael Hennerich ret = gpiochip_add(&dev->gpio_chip); 159ef72af40SMichael Hennerich if (ret) 160ef72af40SMichael Hennerich goto err; 161ef72af40SMichael Hennerich 162ef72af40SMichael Hennerich platform_set_drvdata(pdev, dev); 163ef72af40SMichael Hennerich return 0; 164ef72af40SMichael Hennerich 165ef72af40SMichael Hennerich err: 166ef72af40SMichael Hennerich return ret; 167ef72af40SMichael Hennerich } 168ef72af40SMichael Hennerich 169206210ceSBill Pemberton static int adp5520_gpio_remove(struct platform_device *pdev) 170ef72af40SMichael Hennerich { 171ef72af40SMichael Hennerich struct adp5520_gpio *dev; 172ef72af40SMichael Hennerich int ret; 173ef72af40SMichael Hennerich 174ef72af40SMichael Hennerich dev = platform_get_drvdata(pdev); 175ef72af40SMichael Hennerich ret = gpiochip_remove(&dev->gpio_chip); 176ef72af40SMichael Hennerich if (ret) { 177ef72af40SMichael Hennerich dev_err(&pdev->dev, "%s failed, %d\n", 178ef72af40SMichael Hennerich "gpiochip_remove()", ret); 179ef72af40SMichael Hennerich return ret; 180ef72af40SMichael Hennerich } 181ef72af40SMichael Hennerich 182ef72af40SMichael Hennerich return 0; 183ef72af40SMichael Hennerich } 184ef72af40SMichael Hennerich 185ef72af40SMichael Hennerich static struct platform_driver adp5520_gpio_driver = { 186ef72af40SMichael Hennerich .driver = { 187ef72af40SMichael Hennerich .name = "adp5520-gpio", 188ef72af40SMichael Hennerich .owner = THIS_MODULE, 189ef72af40SMichael Hennerich }, 190ef72af40SMichael Hennerich .probe = adp5520_gpio_probe, 1918283c4ffSBill Pemberton .remove = adp5520_gpio_remove, 192ef72af40SMichael Hennerich }; 193ef72af40SMichael Hennerich 1946f61415eSMark Brown module_platform_driver(adp5520_gpio_driver); 195ef72af40SMichael Hennerich 196ef72af40SMichael Hennerich MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); 197ef72af40SMichael Hennerich MODULE_DESCRIPTION("GPIO ADP5520 Driver"); 198ef72af40SMichael Hennerich MODULE_LICENSE("GPL"); 199ef72af40SMichael Hennerich MODULE_ALIAS("platform:adp5520-gpio"); 200