Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * TI Palma series PMIC's GPIO driver.
0004  *
0005  * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
0006  *
0007  * Author: Laxman Dewangan <ldewangan@nvidia.com>
0008  */
0009 
0010 #include <linux/gpio/driver.h>
0011 #include <linux/kernel.h>
0012 #include <linux/init.h>
0013 #include <linux/mfd/palmas.h>
0014 #include <linux/of.h>
0015 #include <linux/of_device.h>
0016 #include <linux/platform_device.h>
0017 
0018 struct palmas_gpio {
0019     struct gpio_chip gpio_chip;
0020     struct palmas *palmas;
0021 };
0022 
0023 struct palmas_device_data {
0024     int ngpio;
0025 };
0026 
0027 static int palmas_gpio_get(struct gpio_chip *gc, unsigned offset)
0028 {
0029     struct palmas_gpio *pg = gpiochip_get_data(gc);
0030     struct palmas *palmas = pg->palmas;
0031     unsigned int val;
0032     int ret;
0033     unsigned int reg;
0034     int gpio16 = (offset/8);
0035 
0036     offset %= 8;
0037     reg = (gpio16) ? PALMAS_GPIO_DATA_DIR2 : PALMAS_GPIO_DATA_DIR;
0038 
0039     ret = palmas_read(palmas, PALMAS_GPIO_BASE, reg, &val);
0040     if (ret < 0) {
0041         dev_err(gc->parent, "Reg 0x%02x read failed, %d\n", reg, ret);
0042         return ret;
0043     }
0044 
0045     if (val & BIT(offset))
0046         reg = (gpio16) ? PALMAS_GPIO_DATA_OUT2 : PALMAS_GPIO_DATA_OUT;
0047     else
0048         reg = (gpio16) ? PALMAS_GPIO_DATA_IN2 : PALMAS_GPIO_DATA_IN;
0049 
0050     ret = palmas_read(palmas, PALMAS_GPIO_BASE, reg, &val);
0051     if (ret < 0) {
0052         dev_err(gc->parent, "Reg 0x%02x read failed, %d\n", reg, ret);
0053         return ret;
0054     }
0055     return !!(val & BIT(offset));
0056 }
0057 
0058 static void palmas_gpio_set(struct gpio_chip *gc, unsigned offset,
0059             int value)
0060 {
0061     struct palmas_gpio *pg = gpiochip_get_data(gc);
0062     struct palmas *palmas = pg->palmas;
0063     int ret;
0064     unsigned int reg;
0065     int gpio16 = (offset/8);
0066 
0067     offset %= 8;
0068     if (gpio16)
0069         reg = (value) ?
0070             PALMAS_GPIO_SET_DATA_OUT2 : PALMAS_GPIO_CLEAR_DATA_OUT2;
0071     else
0072         reg = (value) ?
0073             PALMAS_GPIO_SET_DATA_OUT : PALMAS_GPIO_CLEAR_DATA_OUT;
0074 
0075     ret = palmas_write(palmas, PALMAS_GPIO_BASE, reg, BIT(offset));
0076     if (ret < 0)
0077         dev_err(gc->parent, "Reg 0x%02x write failed, %d\n", reg, ret);
0078 }
0079 
0080 static int palmas_gpio_output(struct gpio_chip *gc, unsigned offset,
0081                 int value)
0082 {
0083     struct palmas_gpio *pg = gpiochip_get_data(gc);
0084     struct palmas *palmas = pg->palmas;
0085     int ret;
0086     unsigned int reg;
0087     int gpio16 = (offset/8);
0088 
0089     offset %= 8;
0090     reg = (gpio16) ? PALMAS_GPIO_DATA_DIR2 : PALMAS_GPIO_DATA_DIR;
0091 
0092     /* Set the initial value */
0093     palmas_gpio_set(gc, offset, value);
0094 
0095     ret = palmas_update_bits(palmas, PALMAS_GPIO_BASE, reg,
0096                 BIT(offset), BIT(offset));
0097     if (ret < 0)
0098         dev_err(gc->parent, "Reg 0x%02x update failed, %d\n", reg,
0099             ret);
0100     return ret;
0101 }
0102 
0103 static int palmas_gpio_input(struct gpio_chip *gc, unsigned offset)
0104 {
0105     struct palmas_gpio *pg = gpiochip_get_data(gc);
0106     struct palmas *palmas = pg->palmas;
0107     int ret;
0108     unsigned int reg;
0109     int gpio16 = (offset/8);
0110 
0111     offset %= 8;
0112     reg = (gpio16) ? PALMAS_GPIO_DATA_DIR2 : PALMAS_GPIO_DATA_DIR;
0113 
0114     ret = palmas_update_bits(palmas, PALMAS_GPIO_BASE, reg, BIT(offset), 0);
0115     if (ret < 0)
0116         dev_err(gc->parent, "Reg 0x%02x update failed, %d\n", reg,
0117             ret);
0118     return ret;
0119 }
0120 
0121 static int palmas_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
0122 {
0123     struct palmas_gpio *pg = gpiochip_get_data(gc);
0124     struct palmas *palmas = pg->palmas;
0125 
0126     return palmas_irq_get_virq(palmas, PALMAS_GPIO_0_IRQ + offset);
0127 }
0128 
0129 static const struct palmas_device_data palmas_dev_data = {
0130     .ngpio = 8,
0131 };
0132 
0133 static const struct palmas_device_data tps80036_dev_data = {
0134     .ngpio = 16,
0135 };
0136 
0137 static const struct of_device_id of_palmas_gpio_match[] = {
0138     { .compatible = "ti,palmas-gpio", .data = &palmas_dev_data,},
0139     { .compatible = "ti,tps65913-gpio", .data = &palmas_dev_data,},
0140     { .compatible = "ti,tps65914-gpio", .data = &palmas_dev_data,},
0141     { .compatible = "ti,tps80036-gpio", .data = &tps80036_dev_data,},
0142     { },
0143 };
0144 
0145 static int palmas_gpio_probe(struct platform_device *pdev)
0146 {
0147     struct palmas *palmas = dev_get_drvdata(pdev->dev.parent);
0148     struct palmas_platform_data *palmas_pdata;
0149     struct palmas_gpio *palmas_gpio;
0150     int ret;
0151     const struct palmas_device_data *dev_data;
0152 
0153     dev_data = of_device_get_match_data(&pdev->dev);
0154     if (!dev_data)
0155         dev_data = &palmas_dev_data;
0156 
0157     palmas_gpio = devm_kzalloc(&pdev->dev,
0158                 sizeof(*palmas_gpio), GFP_KERNEL);
0159     if (!palmas_gpio)
0160         return -ENOMEM;
0161 
0162     palmas_gpio->palmas = palmas;
0163     palmas_gpio->gpio_chip.owner = THIS_MODULE;
0164     palmas_gpio->gpio_chip.label = dev_name(&pdev->dev);
0165     palmas_gpio->gpio_chip.ngpio = dev_data->ngpio;
0166     palmas_gpio->gpio_chip.can_sleep = true;
0167     palmas_gpio->gpio_chip.direction_input = palmas_gpio_input;
0168     palmas_gpio->gpio_chip.direction_output = palmas_gpio_output;
0169     palmas_gpio->gpio_chip.to_irq = palmas_gpio_to_irq;
0170     palmas_gpio->gpio_chip.set  = palmas_gpio_set;
0171     palmas_gpio->gpio_chip.get  = palmas_gpio_get;
0172     palmas_gpio->gpio_chip.parent = &pdev->dev;
0173 
0174     palmas_pdata = dev_get_platdata(palmas->dev);
0175     if (palmas_pdata && palmas_pdata->gpio_base)
0176         palmas_gpio->gpio_chip.base = palmas_pdata->gpio_base;
0177     else
0178         palmas_gpio->gpio_chip.base = -1;
0179 
0180     ret = devm_gpiochip_add_data(&pdev->dev, &palmas_gpio->gpio_chip,
0181                      palmas_gpio);
0182     if (ret < 0) {
0183         dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret);
0184         return ret;
0185     }
0186 
0187     platform_set_drvdata(pdev, palmas_gpio);
0188     return ret;
0189 }
0190 
0191 static struct platform_driver palmas_gpio_driver = {
0192     .driver.name    = "palmas-gpio",
0193     .driver.of_match_table = of_palmas_gpio_match,
0194     .probe      = palmas_gpio_probe,
0195 };
0196 
0197 static int __init palmas_gpio_init(void)
0198 {
0199     return platform_driver_register(&palmas_gpio_driver);
0200 }
0201 subsys_initcall(palmas_gpio_init);