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