Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

gpio/rc5t583: add gpio driver for RICOH PMIC RC5T583

The PMIC device RC5T583 from RICOH supports 8 gpios.
Adding gpio driver for this device to access the pins
control through gpio library.

Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com>
[grant.likely: slight cosmetic changes]
Signed-off-by: Grant Likely <grant.likely@secretlab.ca>

authored by

Laxman Dewangan and committed by
Grant Likely
e9fe32bc ee1c1e7d

+192
+9
drivers/gpio/Kconfig
··· 301 301 This driver provides an in-kernel interface to those GPIOs using 302 302 platform-neutral GPIO calls. 303 303 304 + config GPIO_RC5T583 305 + bool "RICOH RC5T583 GPIO" 306 + depends on MFD_RC5T583 307 + help 308 + Select this option to enable GPIO driver for the Ricoh RC5T583 309 + chip family. 310 + This driver provides the support for driving/reading the gpio pins 311 + of RC5T583 device through standard gpio library. 312 + 304 313 config GPIO_SX150X 305 314 bool "Semtech SX150x I2C GPIO expander" 306 315 depends on I2C=y
+1
drivers/gpio/Makefile
··· 45 45 obj-$(CONFIG_GPIO_PCH) += gpio-pch.o 46 46 obj-$(CONFIG_GPIO_PL061) += gpio-pl061.o 47 47 obj-$(CONFIG_GPIO_PXA) += gpio-pxa.o 48 + obj-$(CONFIG_GPIO_RC5T583) += gpio-rc5t583.o 48 49 obj-$(CONFIG_GPIO_RDC321X) += gpio-rdc321x.o 49 50 obj-$(CONFIG_PLAT_SAMSUNG) += gpio-samsung.o 50 51 obj-$(CONFIG_ARCH_SA1100) += gpio-sa1100.o
+180
drivers/gpio/gpio-rc5t583.c
··· 1 + /* 2 + * GPIO driver for RICOH583 power management chip. 3 + * 4 + * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. 5 + * Author: Laxman dewangan <ldewangan@nvidia.com> 6 + * 7 + * Based on code 8 + * Copyright (C) 2011 RICOH COMPANY,LTD 9 + * 10 + * This program is free software; you can redistribute it and/or modify it 11 + * under the terms and conditions of the GNU General Public License, 12 + * version 2, as published by the Free Software Foundation. 13 + * 14 + * This program is distributed in the hope it will be useful, but WITHOUT 15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 17 + * more details. 18 + * 19 + * You should have received a copy of the GNU General Public License 20 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 21 + * 22 + */ 23 + #include <linux/init.h> 24 + #include <linux/kernel.h> 25 + #include <linux/slab.h> 26 + #include <linux/module.h> 27 + #include <linux/platform_device.h> 28 + #include <linux/device.h> 29 + #include <linux/gpio.h> 30 + #include <linux/mfd/rc5t583.h> 31 + 32 + struct rc5t583_gpio { 33 + struct gpio_chip gpio_chip; 34 + struct rc5t583 *rc5t583; 35 + }; 36 + 37 + static inline struct rc5t583_gpio *to_rc5t583_gpio(struct gpio_chip *chip) 38 + { 39 + return container_of(chip, struct rc5t583_gpio, gpio_chip); 40 + } 41 + 42 + static int rc5t583_gpio_get(struct gpio_chip *gc, unsigned int offset) 43 + { 44 + struct rc5t583_gpio *rc5t583_gpio = to_rc5t583_gpio(gc); 45 + struct device *parent = rc5t583_gpio->rc5t583->dev; 46 + uint8_t val = 0; 47 + int ret; 48 + 49 + ret = rc5t583_read(parent, RC5T583_GPIO_MON_IOIN, &val); 50 + if (ret < 0) 51 + return ret; 52 + 53 + return !!(val & BIT(offset)); 54 + } 55 + 56 + static void rc5t583_gpio_set(struct gpio_chip *gc, unsigned int offset, int val) 57 + { 58 + struct rc5t583_gpio *rc5t583_gpio = to_rc5t583_gpio(gc); 59 + struct device *parent = rc5t583_gpio->rc5t583->dev; 60 + if (val) 61 + rc5t583_set_bits(parent, RC5T583_GPIO_IOOUT, BIT(offset)); 62 + else 63 + rc5t583_clear_bits(parent, RC5T583_GPIO_IOOUT, BIT(offset)); 64 + } 65 + 66 + static int rc5t583_gpio_dir_input(struct gpio_chip *gc, unsigned int offset) 67 + { 68 + struct rc5t583_gpio *rc5t583_gpio = to_rc5t583_gpio(gc); 69 + struct device *parent = rc5t583_gpio->rc5t583->dev; 70 + int ret; 71 + 72 + ret = rc5t583_clear_bits(parent, RC5T583_GPIO_IOSEL, BIT(offset)); 73 + if (ret < 0) 74 + return ret; 75 + 76 + /* Set pin to gpio mode */ 77 + return rc5t583_clear_bits(parent, RC5T583_GPIO_PGSEL, BIT(offset)); 78 + } 79 + 80 + static int rc5t583_gpio_dir_output(struct gpio_chip *gc, unsigned offset, 81 + int value) 82 + { 83 + struct rc5t583_gpio *rc5t583_gpio = to_rc5t583_gpio(gc); 84 + struct device *parent = rc5t583_gpio->rc5t583->dev; 85 + int ret; 86 + 87 + rc5t583_gpio_set(gc, offset, value); 88 + ret = rc5t583_set_bits(parent, RC5T583_GPIO_IOSEL, BIT(offset)); 89 + if (ret < 0) 90 + return ret; 91 + 92 + /* Set pin to gpio mode */ 93 + return rc5t583_clear_bits(parent, RC5T583_GPIO_PGSEL, BIT(offset)); 94 + } 95 + 96 + static int rc5t583_gpio_to_irq(struct gpio_chip *gc, unsigned offset) 97 + { 98 + struct rc5t583_gpio *rc5t583_gpio = to_rc5t583_gpio(gc); 99 + 100 + if ((offset >= 0) && (offset < 8)) 101 + return rc5t583_gpio->rc5t583->irq_base + 102 + RC5T583_IRQ_GPIO0 + offset; 103 + return -EINVAL; 104 + } 105 + 106 + static void rc5t583_gpio_free(struct gpio_chip *gc, unsigned offset) 107 + { 108 + struct rc5t583_gpio *rc5t583_gpio = to_rc5t583_gpio(gc); 109 + struct device *parent = rc5t583_gpio->rc5t583->dev; 110 + 111 + rc5t583_set_bits(parent, RC5T583_GPIO_PGSEL, BIT(offset)); 112 + } 113 + 114 + static int __devinit rc5t583_gpio_probe(struct platform_device *pdev) 115 + { 116 + struct rc5t583 *rc5t583 = dev_get_drvdata(pdev->dev.parent); 117 + struct rc5t583_platform_data *pdata = dev_get_platdata(rc5t583->dev); 118 + struct rc5t583_gpio *rc5t583_gpio; 119 + 120 + rc5t583_gpio = devm_kzalloc(&pdev->dev, sizeof(*rc5t583_gpio), 121 + GFP_KERNEL); 122 + if (!rc5t583_gpio) { 123 + dev_warn(&pdev->dev, "Mem allocation for rc5t583_gpio failed"); 124 + return -ENOMEM; 125 + } 126 + 127 + rc5t583_gpio->gpio_chip.label = "gpio-rc5t583", 128 + rc5t583_gpio->gpio_chip.owner = THIS_MODULE, 129 + rc5t583_gpio->gpio_chip.free = rc5t583_gpio_free, 130 + rc5t583_gpio->gpio_chip.direction_input = rc5t583_gpio_dir_input, 131 + rc5t583_gpio->gpio_chip.direction_output = rc5t583_gpio_dir_output, 132 + rc5t583_gpio->gpio_chip.set = rc5t583_gpio_set, 133 + rc5t583_gpio->gpio_chip.get = rc5t583_gpio_get, 134 + rc5t583_gpio->gpio_chip.to_irq = rc5t583_gpio_to_irq, 135 + rc5t583_gpio->gpio_chip.ngpio = RC5T583_MAX_GPIO, 136 + rc5t583_gpio->gpio_chip.can_sleep = 1, 137 + rc5t583_gpio->gpio_chip.dev = &pdev->dev; 138 + rc5t583_gpio->gpio_chip.base = -1; 139 + rc5t583_gpio->rc5t583 = rc5t583; 140 + 141 + if (pdata && pdata->gpio_base) 142 + rc5t583_gpio->gpio_chip.base = pdata->gpio_base; 143 + 144 + platform_set_drvdata(pdev, rc5t583_gpio); 145 + 146 + return gpiochip_add(&rc5t583_gpio->gpio_chip); 147 + } 148 + 149 + static int __devexit rc5t583_gpio_remove(struct platform_device *pdev) 150 + { 151 + struct rc5t583_gpio *rc5t583_gpio = platform_get_drvdata(pdev); 152 + 153 + return gpiochip_remove(&rc5t583_gpio->gpio_chip); 154 + } 155 + 156 + static struct platform_driver rc5t583_gpio_driver = { 157 + .driver = { 158 + .name = "rc5t583-gpio", 159 + .owner = THIS_MODULE, 160 + }, 161 + .probe = rc5t583_gpio_probe, 162 + .remove = __devexit_p(rc5t583_gpio_remove), 163 + }; 164 + 165 + static int __init rc5t583_gpio_init(void) 166 + { 167 + return platform_driver_register(&rc5t583_gpio_driver); 168 + } 169 + subsys_initcall(rc5t583_gpio_init); 170 + 171 + static void __exit rc5t583_gpio_exit(void) 172 + { 173 + platform_driver_unregister(&rc5t583_gpio_driver); 174 + } 175 + module_exit(rc5t583_gpio_exit); 176 + 177 + MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>"); 178 + MODULE_DESCRIPTION("GPIO interface for RC5T583"); 179 + MODULE_LICENSE("GPL v2"); 180 + MODULE_ALIAS("platform:rc5t583-gpio");
+2
include/linux/mfd/rc5t583.h
··· 272 272 * rc5t583_platform_data: Platform data for ricoh rc5t583 pmu. 273 273 * The board specific data is provided through this structure. 274 274 * @irq_base: Irq base number on which this device registers their interrupts. 275 + * @gpio_base: GPIO base from which gpio of this device will start. 275 276 * @enable_shutdown: Enable shutdown through the input pin "shutdown". 276 277 */ 277 278 278 279 struct rc5t583_platform_data { 279 280 int irq_base; 281 + int gpio_base; 280 282 bool enable_shutdown; 281 283 }; 282 284