0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/module.h>
0009 #include <linux/slab.h>
0010 #include <linux/kernel.h>
0011 #include <linux/init.h>
0012 #include <linux/platform_device.h>
0013 #include <linux/mfd/adp5520.h>
0014 #include <linux/gpio/driver.h>
0015
0016 struct adp5520_gpio {
0017 struct device *master;
0018 struct gpio_chip gpio_chip;
0019 unsigned char lut[ADP5520_MAXGPIOS];
0020 unsigned long output;
0021 };
0022
0023 static int adp5520_gpio_get_value(struct gpio_chip *chip, unsigned off)
0024 {
0025 struct adp5520_gpio *dev;
0026 uint8_t reg_val;
0027
0028 dev = gpiochip_get_data(chip);
0029
0030
0031
0032
0033
0034
0035 if (test_bit(off, &dev->output))
0036 adp5520_read(dev->master, ADP5520_GPIO_OUT, ®_val);
0037 else
0038 adp5520_read(dev->master, ADP5520_GPIO_IN, ®_val);
0039
0040 return !!(reg_val & dev->lut[off]);
0041 }
0042
0043 static void adp5520_gpio_set_value(struct gpio_chip *chip,
0044 unsigned off, int val)
0045 {
0046 struct adp5520_gpio *dev;
0047 dev = gpiochip_get_data(chip);
0048
0049 if (val)
0050 adp5520_set_bits(dev->master, ADP5520_GPIO_OUT, dev->lut[off]);
0051 else
0052 adp5520_clr_bits(dev->master, ADP5520_GPIO_OUT, dev->lut[off]);
0053 }
0054
0055 static int adp5520_gpio_direction_input(struct gpio_chip *chip, unsigned off)
0056 {
0057 struct adp5520_gpio *dev;
0058 dev = gpiochip_get_data(chip);
0059
0060 clear_bit(off, &dev->output);
0061
0062 return adp5520_clr_bits(dev->master, ADP5520_GPIO_CFG_2,
0063 dev->lut[off]);
0064 }
0065
0066 static int adp5520_gpio_direction_output(struct gpio_chip *chip,
0067 unsigned off, int val)
0068 {
0069 struct adp5520_gpio *dev;
0070 int ret = 0;
0071 dev = gpiochip_get_data(chip);
0072
0073 set_bit(off, &dev->output);
0074
0075 if (val)
0076 ret |= adp5520_set_bits(dev->master, ADP5520_GPIO_OUT,
0077 dev->lut[off]);
0078 else
0079 ret |= adp5520_clr_bits(dev->master, ADP5520_GPIO_OUT,
0080 dev->lut[off]);
0081
0082 ret |= adp5520_set_bits(dev->master, ADP5520_GPIO_CFG_2,
0083 dev->lut[off]);
0084
0085 return ret;
0086 }
0087
0088 static int adp5520_gpio_probe(struct platform_device *pdev)
0089 {
0090 struct adp5520_gpio_platform_data *pdata = dev_get_platdata(&pdev->dev);
0091 struct adp5520_gpio *dev;
0092 struct gpio_chip *gc;
0093 int ret, i, gpios;
0094 unsigned char ctl_mask = 0;
0095
0096 if (pdata == NULL) {
0097 dev_err(&pdev->dev, "missing platform data\n");
0098 return -ENODEV;
0099 }
0100
0101 if (pdev->id != ID_ADP5520) {
0102 dev_err(&pdev->dev, "only ADP5520 supports GPIO\n");
0103 return -ENODEV;
0104 }
0105
0106 dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
0107 if (dev == NULL)
0108 return -ENOMEM;
0109
0110 dev->master = pdev->dev.parent;
0111
0112 for (gpios = 0, i = 0; i < ADP5520_MAXGPIOS; i++)
0113 if (pdata->gpio_en_mask & (1 << i))
0114 dev->lut[gpios++] = 1 << i;
0115
0116 if (gpios < 1)
0117 return -EINVAL;
0118
0119 gc = &dev->gpio_chip;
0120 gc->direction_input = adp5520_gpio_direction_input;
0121 gc->direction_output = adp5520_gpio_direction_output;
0122 gc->get = adp5520_gpio_get_value;
0123 gc->set = adp5520_gpio_set_value;
0124 gc->can_sleep = true;
0125
0126 gc->base = pdata->gpio_start;
0127 gc->ngpio = gpios;
0128 gc->label = pdev->name;
0129 gc->owner = THIS_MODULE;
0130
0131 ret = adp5520_clr_bits(dev->master, ADP5520_GPIO_CFG_1,
0132 pdata->gpio_en_mask);
0133
0134 if (pdata->gpio_en_mask & ADP5520_GPIO_C3)
0135 ctl_mask |= ADP5520_C3_MODE;
0136
0137 if (pdata->gpio_en_mask & ADP5520_GPIO_R3)
0138 ctl_mask |= ADP5520_R3_MODE;
0139
0140 if (ctl_mask)
0141 ret = adp5520_set_bits(dev->master, ADP5520_LED_CONTROL,
0142 ctl_mask);
0143
0144 ret |= adp5520_set_bits(dev->master, ADP5520_GPIO_PULLUP,
0145 pdata->gpio_pullup_mask);
0146
0147 if (ret) {
0148 dev_err(&pdev->dev, "failed to write\n");
0149 return ret;
0150 }
0151
0152 return devm_gpiochip_add_data(&pdev->dev, &dev->gpio_chip, dev);
0153 }
0154
0155 static struct platform_driver adp5520_gpio_driver = {
0156 .driver = {
0157 .name = "adp5520-gpio",
0158 },
0159 .probe = adp5520_gpio_probe,
0160 };
0161
0162 module_platform_driver(adp5520_gpio_driver);
0163
0164 MODULE_AUTHOR("Michael Hennerich <michael.hennerich@analog.com>");
0165 MODULE_DESCRIPTION("GPIO ADP5520 Driver");
0166 MODULE_LICENSE("GPL");
0167 MODULE_ALIAS("platform:adp5520-gpio");