Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * GPIO driver for RICOH583 power management chip.
0004  *
0005  * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
0006  * Author: Laxman dewangan <ldewangan@nvidia.com>
0007  *
0008  * Based on code
0009  *  Copyright (C) 2011 RICOH COMPANY,LTD
0010  */
0011 #include <linux/init.h>
0012 #include <linux/kernel.h>
0013 #include <linux/slab.h>
0014 #include <linux/platform_device.h>
0015 #include <linux/device.h>
0016 #include <linux/gpio/driver.h>
0017 #include <linux/mfd/rc5t583.h>
0018 
0019 struct rc5t583_gpio {
0020     struct gpio_chip gpio_chip;
0021     struct rc5t583 *rc5t583;
0022 };
0023 
0024 static int rc5t583_gpio_get(struct gpio_chip *gc, unsigned int offset)
0025 {
0026     struct rc5t583_gpio *rc5t583_gpio = gpiochip_get_data(gc);
0027     struct device *parent = rc5t583_gpio->rc5t583->dev;
0028     uint8_t val = 0;
0029     int ret;
0030 
0031     ret = rc5t583_read(parent, RC5T583_GPIO_MON_IOIN, &val);
0032     if (ret < 0)
0033         return ret;
0034 
0035     return !!(val & BIT(offset));
0036 }
0037 
0038 static void rc5t583_gpio_set(struct gpio_chip *gc, unsigned int offset, int val)
0039 {
0040     struct rc5t583_gpio *rc5t583_gpio = gpiochip_get_data(gc);
0041     struct device *parent = rc5t583_gpio->rc5t583->dev;
0042     if (val)
0043         rc5t583_set_bits(parent, RC5T583_GPIO_IOOUT, BIT(offset));
0044     else
0045         rc5t583_clear_bits(parent, RC5T583_GPIO_IOOUT, BIT(offset));
0046 }
0047 
0048 static int rc5t583_gpio_dir_input(struct gpio_chip *gc, unsigned int offset)
0049 {
0050     struct rc5t583_gpio *rc5t583_gpio = gpiochip_get_data(gc);
0051     struct device *parent = rc5t583_gpio->rc5t583->dev;
0052     int ret;
0053 
0054     ret = rc5t583_clear_bits(parent, RC5T583_GPIO_IOSEL, BIT(offset));
0055     if (ret < 0)
0056         return ret;
0057 
0058     /* Set pin to gpio mode */
0059     return rc5t583_clear_bits(parent, RC5T583_GPIO_PGSEL, BIT(offset));
0060 }
0061 
0062 static int rc5t583_gpio_dir_output(struct gpio_chip *gc, unsigned offset,
0063             int value)
0064 {
0065     struct rc5t583_gpio *rc5t583_gpio = gpiochip_get_data(gc);
0066     struct device *parent = rc5t583_gpio->rc5t583->dev;
0067     int ret;
0068 
0069     rc5t583_gpio_set(gc, offset, value);
0070     ret = rc5t583_set_bits(parent, RC5T583_GPIO_IOSEL, BIT(offset));
0071     if (ret < 0)
0072         return ret;
0073 
0074     /* Set pin to gpio mode */
0075     return rc5t583_clear_bits(parent, RC5T583_GPIO_PGSEL, BIT(offset));
0076 }
0077 
0078 static int rc5t583_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
0079 {
0080     struct rc5t583_gpio *rc5t583_gpio = gpiochip_get_data(gc);
0081 
0082     if (offset < RC5T583_MAX_GPIO)
0083         return rc5t583_gpio->rc5t583->irq_base +
0084                 RC5T583_IRQ_GPIO0 + offset;
0085     return -EINVAL;
0086 }
0087 
0088 static void rc5t583_gpio_free(struct gpio_chip *gc, unsigned offset)
0089 {
0090     struct rc5t583_gpio *rc5t583_gpio = gpiochip_get_data(gc);
0091     struct device *parent = rc5t583_gpio->rc5t583->dev;
0092 
0093     rc5t583_set_bits(parent, RC5T583_GPIO_PGSEL, BIT(offset));
0094 }
0095 
0096 static int rc5t583_gpio_probe(struct platform_device *pdev)
0097 {
0098     struct rc5t583 *rc5t583 = dev_get_drvdata(pdev->dev.parent);
0099     struct rc5t583_platform_data *pdata = dev_get_platdata(rc5t583->dev);
0100     struct rc5t583_gpio *rc5t583_gpio;
0101 
0102     rc5t583_gpio = devm_kzalloc(&pdev->dev, sizeof(*rc5t583_gpio),
0103                     GFP_KERNEL);
0104     if (!rc5t583_gpio)
0105         return -ENOMEM;
0106 
0107     rc5t583_gpio->gpio_chip.label = "gpio-rc5t583",
0108     rc5t583_gpio->gpio_chip.owner = THIS_MODULE,
0109     rc5t583_gpio->gpio_chip.free = rc5t583_gpio_free,
0110     rc5t583_gpio->gpio_chip.direction_input = rc5t583_gpio_dir_input,
0111     rc5t583_gpio->gpio_chip.direction_output = rc5t583_gpio_dir_output,
0112     rc5t583_gpio->gpio_chip.set = rc5t583_gpio_set,
0113     rc5t583_gpio->gpio_chip.get = rc5t583_gpio_get,
0114     rc5t583_gpio->gpio_chip.to_irq = rc5t583_gpio_to_irq,
0115     rc5t583_gpio->gpio_chip.ngpio = RC5T583_MAX_GPIO,
0116     rc5t583_gpio->gpio_chip.can_sleep = true,
0117     rc5t583_gpio->gpio_chip.parent = &pdev->dev;
0118     rc5t583_gpio->gpio_chip.base = -1;
0119     rc5t583_gpio->rc5t583 = rc5t583;
0120 
0121     if (pdata && pdata->gpio_base)
0122         rc5t583_gpio->gpio_chip.base = pdata->gpio_base;
0123 
0124     platform_set_drvdata(pdev, rc5t583_gpio);
0125 
0126     return devm_gpiochip_add_data(&pdev->dev, &rc5t583_gpio->gpio_chip,
0127                       rc5t583_gpio);
0128 }
0129 
0130 static struct platform_driver rc5t583_gpio_driver = {
0131     .driver = {
0132         .name    = "rc5t583-gpio",
0133     },
0134     .probe      = rc5t583_gpio_probe,
0135 };
0136 
0137 static int __init rc5t583_gpio_init(void)
0138 {
0139     return platform_driver_register(&rc5t583_gpio_driver);
0140 }
0141 subsys_initcall(rc5t583_gpio_init);