1e9fe32bcSLaxman Dewangan /* 2e9fe32bcSLaxman Dewangan * GPIO driver for RICOH583 power management chip. 3e9fe32bcSLaxman Dewangan * 4e9fe32bcSLaxman Dewangan * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. 5e9fe32bcSLaxman Dewangan * Author: Laxman dewangan <ldewangan@nvidia.com> 6e9fe32bcSLaxman Dewangan * 7e9fe32bcSLaxman Dewangan * Based on code 8e9fe32bcSLaxman Dewangan * Copyright (C) 2011 RICOH COMPANY,LTD 9e9fe32bcSLaxman Dewangan * 10e9fe32bcSLaxman Dewangan * This program is free software; you can redistribute it and/or modify it 11e9fe32bcSLaxman Dewangan * under the terms and conditions of the GNU General Public License, 12e9fe32bcSLaxman Dewangan * version 2, as published by the Free Software Foundation. 13e9fe32bcSLaxman Dewangan * 14e9fe32bcSLaxman Dewangan * This program is distributed in the hope it will be useful, but WITHOUT 15e9fe32bcSLaxman Dewangan * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 16e9fe32bcSLaxman Dewangan * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 17e9fe32bcSLaxman Dewangan * more details. 18e9fe32bcSLaxman Dewangan * 19e9fe32bcSLaxman Dewangan * You should have received a copy of the GNU General Public License 20e9fe32bcSLaxman Dewangan * along with this program. If not, see <http://www.gnu.org/licenses/>. 21e9fe32bcSLaxman Dewangan * 22e9fe32bcSLaxman Dewangan */ 23e9fe32bcSLaxman Dewangan #include <linux/init.h> 24e9fe32bcSLaxman Dewangan #include <linux/kernel.h> 25e9fe32bcSLaxman Dewangan #include <linux/slab.h> 26e9fe32bcSLaxman Dewangan #include <linux/module.h> 27e9fe32bcSLaxman Dewangan #include <linux/platform_device.h> 28e9fe32bcSLaxman Dewangan #include <linux/device.h> 29e9fe32bcSLaxman Dewangan #include <linux/gpio.h> 30e9fe32bcSLaxman Dewangan #include <linux/mfd/rc5t583.h> 31e9fe32bcSLaxman Dewangan 32e9fe32bcSLaxman Dewangan struct rc5t583_gpio { 33e9fe32bcSLaxman Dewangan struct gpio_chip gpio_chip; 34e9fe32bcSLaxman Dewangan struct rc5t583 *rc5t583; 35e9fe32bcSLaxman Dewangan }; 36e9fe32bcSLaxman Dewangan 37e9fe32bcSLaxman Dewangan static inline struct rc5t583_gpio *to_rc5t583_gpio(struct gpio_chip *chip) 38e9fe32bcSLaxman Dewangan { 39e9fe32bcSLaxman Dewangan return container_of(chip, struct rc5t583_gpio, gpio_chip); 40e9fe32bcSLaxman Dewangan } 41e9fe32bcSLaxman Dewangan 42e9fe32bcSLaxman Dewangan static int rc5t583_gpio_get(struct gpio_chip *gc, unsigned int offset) 43e9fe32bcSLaxman Dewangan { 44e9fe32bcSLaxman Dewangan struct rc5t583_gpio *rc5t583_gpio = to_rc5t583_gpio(gc); 45e9fe32bcSLaxman Dewangan struct device *parent = rc5t583_gpio->rc5t583->dev; 46e9fe32bcSLaxman Dewangan uint8_t val = 0; 47e9fe32bcSLaxman Dewangan int ret; 48e9fe32bcSLaxman Dewangan 49e9fe32bcSLaxman Dewangan ret = rc5t583_read(parent, RC5T583_GPIO_MON_IOIN, &val); 50e9fe32bcSLaxman Dewangan if (ret < 0) 51e9fe32bcSLaxman Dewangan return ret; 52e9fe32bcSLaxman Dewangan 53e9fe32bcSLaxman Dewangan return !!(val & BIT(offset)); 54e9fe32bcSLaxman Dewangan } 55e9fe32bcSLaxman Dewangan 56e9fe32bcSLaxman Dewangan static void rc5t583_gpio_set(struct gpio_chip *gc, unsigned int offset, int val) 57e9fe32bcSLaxman Dewangan { 58e9fe32bcSLaxman Dewangan struct rc5t583_gpio *rc5t583_gpio = to_rc5t583_gpio(gc); 59e9fe32bcSLaxman Dewangan struct device *parent = rc5t583_gpio->rc5t583->dev; 60e9fe32bcSLaxman Dewangan if (val) 61e9fe32bcSLaxman Dewangan rc5t583_set_bits(parent, RC5T583_GPIO_IOOUT, BIT(offset)); 62e9fe32bcSLaxman Dewangan else 63e9fe32bcSLaxman Dewangan rc5t583_clear_bits(parent, RC5T583_GPIO_IOOUT, BIT(offset)); 64e9fe32bcSLaxman Dewangan } 65e9fe32bcSLaxman Dewangan 66e9fe32bcSLaxman Dewangan static int rc5t583_gpio_dir_input(struct gpio_chip *gc, unsigned int offset) 67e9fe32bcSLaxman Dewangan { 68e9fe32bcSLaxman Dewangan struct rc5t583_gpio *rc5t583_gpio = to_rc5t583_gpio(gc); 69e9fe32bcSLaxman Dewangan struct device *parent = rc5t583_gpio->rc5t583->dev; 70e9fe32bcSLaxman Dewangan int ret; 71e9fe32bcSLaxman Dewangan 72e9fe32bcSLaxman Dewangan ret = rc5t583_clear_bits(parent, RC5T583_GPIO_IOSEL, BIT(offset)); 73e9fe32bcSLaxman Dewangan if (ret < 0) 74e9fe32bcSLaxman Dewangan return ret; 75e9fe32bcSLaxman Dewangan 76e9fe32bcSLaxman Dewangan /* Set pin to gpio mode */ 77e9fe32bcSLaxman Dewangan return rc5t583_clear_bits(parent, RC5T583_GPIO_PGSEL, BIT(offset)); 78e9fe32bcSLaxman Dewangan } 79e9fe32bcSLaxman Dewangan 80e9fe32bcSLaxman Dewangan static int rc5t583_gpio_dir_output(struct gpio_chip *gc, unsigned offset, 81e9fe32bcSLaxman Dewangan int value) 82e9fe32bcSLaxman Dewangan { 83e9fe32bcSLaxman Dewangan struct rc5t583_gpio *rc5t583_gpio = to_rc5t583_gpio(gc); 84e9fe32bcSLaxman Dewangan struct device *parent = rc5t583_gpio->rc5t583->dev; 85e9fe32bcSLaxman Dewangan int ret; 86e9fe32bcSLaxman Dewangan 87e9fe32bcSLaxman Dewangan rc5t583_gpio_set(gc, offset, value); 88e9fe32bcSLaxman Dewangan ret = rc5t583_set_bits(parent, RC5T583_GPIO_IOSEL, BIT(offset)); 89e9fe32bcSLaxman Dewangan if (ret < 0) 90e9fe32bcSLaxman Dewangan return ret; 91e9fe32bcSLaxman Dewangan 92e9fe32bcSLaxman Dewangan /* Set pin to gpio mode */ 93e9fe32bcSLaxman Dewangan return rc5t583_clear_bits(parent, RC5T583_GPIO_PGSEL, BIT(offset)); 94e9fe32bcSLaxman Dewangan } 95e9fe32bcSLaxman Dewangan 96e9fe32bcSLaxman Dewangan static int rc5t583_gpio_to_irq(struct gpio_chip *gc, unsigned offset) 97e9fe32bcSLaxman Dewangan { 98e9fe32bcSLaxman Dewangan struct rc5t583_gpio *rc5t583_gpio = to_rc5t583_gpio(gc); 99e9fe32bcSLaxman Dewangan 100e9fe32bcSLaxman Dewangan if ((offset >= 0) && (offset < 8)) 101e9fe32bcSLaxman Dewangan return rc5t583_gpio->rc5t583->irq_base + 102e9fe32bcSLaxman Dewangan RC5T583_IRQ_GPIO0 + offset; 103e9fe32bcSLaxman Dewangan return -EINVAL; 104e9fe32bcSLaxman Dewangan } 105e9fe32bcSLaxman Dewangan 106e9fe32bcSLaxman Dewangan static void rc5t583_gpio_free(struct gpio_chip *gc, unsigned offset) 107e9fe32bcSLaxman Dewangan { 108e9fe32bcSLaxman Dewangan struct rc5t583_gpio *rc5t583_gpio = to_rc5t583_gpio(gc); 109e9fe32bcSLaxman Dewangan struct device *parent = rc5t583_gpio->rc5t583->dev; 110e9fe32bcSLaxman Dewangan 111e9fe32bcSLaxman Dewangan rc5t583_set_bits(parent, RC5T583_GPIO_PGSEL, BIT(offset)); 112e9fe32bcSLaxman Dewangan } 113e9fe32bcSLaxman Dewangan 114e9fe32bcSLaxman Dewangan static int __devinit rc5t583_gpio_probe(struct platform_device *pdev) 115e9fe32bcSLaxman Dewangan { 116e9fe32bcSLaxman Dewangan struct rc5t583 *rc5t583 = dev_get_drvdata(pdev->dev.parent); 117e9fe32bcSLaxman Dewangan struct rc5t583_platform_data *pdata = dev_get_platdata(rc5t583->dev); 118e9fe32bcSLaxman Dewangan struct rc5t583_gpio *rc5t583_gpio; 119e9fe32bcSLaxman Dewangan 120e9fe32bcSLaxman Dewangan rc5t583_gpio = devm_kzalloc(&pdev->dev, sizeof(*rc5t583_gpio), 121e9fe32bcSLaxman Dewangan GFP_KERNEL); 122e9fe32bcSLaxman Dewangan if (!rc5t583_gpio) { 123e9fe32bcSLaxman Dewangan dev_warn(&pdev->dev, "Mem allocation for rc5t583_gpio failed"); 124e9fe32bcSLaxman Dewangan return -ENOMEM; 125e9fe32bcSLaxman Dewangan } 126e9fe32bcSLaxman Dewangan 127e9fe32bcSLaxman Dewangan rc5t583_gpio->gpio_chip.label = "gpio-rc5t583", 128e9fe32bcSLaxman Dewangan rc5t583_gpio->gpio_chip.owner = THIS_MODULE, 129e9fe32bcSLaxman Dewangan rc5t583_gpio->gpio_chip.free = rc5t583_gpio_free, 130e9fe32bcSLaxman Dewangan rc5t583_gpio->gpio_chip.direction_input = rc5t583_gpio_dir_input, 131e9fe32bcSLaxman Dewangan rc5t583_gpio->gpio_chip.direction_output = rc5t583_gpio_dir_output, 132e9fe32bcSLaxman Dewangan rc5t583_gpio->gpio_chip.set = rc5t583_gpio_set, 133e9fe32bcSLaxman Dewangan rc5t583_gpio->gpio_chip.get = rc5t583_gpio_get, 134e9fe32bcSLaxman Dewangan rc5t583_gpio->gpio_chip.to_irq = rc5t583_gpio_to_irq, 135e9fe32bcSLaxman Dewangan rc5t583_gpio->gpio_chip.ngpio = RC5T583_MAX_GPIO, 136e9fe32bcSLaxman Dewangan rc5t583_gpio->gpio_chip.can_sleep = 1, 137e9fe32bcSLaxman Dewangan rc5t583_gpio->gpio_chip.dev = &pdev->dev; 138e9fe32bcSLaxman Dewangan rc5t583_gpio->gpio_chip.base = -1; 139e9fe32bcSLaxman Dewangan rc5t583_gpio->rc5t583 = rc5t583; 140e9fe32bcSLaxman Dewangan 141e9fe32bcSLaxman Dewangan if (pdata && pdata->gpio_base) 142e9fe32bcSLaxman Dewangan rc5t583_gpio->gpio_chip.base = pdata->gpio_base; 143e9fe32bcSLaxman Dewangan 144e9fe32bcSLaxman Dewangan platform_set_drvdata(pdev, rc5t583_gpio); 145e9fe32bcSLaxman Dewangan 146e9fe32bcSLaxman Dewangan return gpiochip_add(&rc5t583_gpio->gpio_chip); 147e9fe32bcSLaxman Dewangan } 148e9fe32bcSLaxman Dewangan 149e9fe32bcSLaxman Dewangan static int __devexit rc5t583_gpio_remove(struct platform_device *pdev) 150e9fe32bcSLaxman Dewangan { 151e9fe32bcSLaxman Dewangan struct rc5t583_gpio *rc5t583_gpio = platform_get_drvdata(pdev); 152e9fe32bcSLaxman Dewangan 153e9fe32bcSLaxman Dewangan return gpiochip_remove(&rc5t583_gpio->gpio_chip); 154e9fe32bcSLaxman Dewangan } 155e9fe32bcSLaxman Dewangan 156e9fe32bcSLaxman Dewangan static struct platform_driver rc5t583_gpio_driver = { 157e9fe32bcSLaxman Dewangan .driver = { 158e9fe32bcSLaxman Dewangan .name = "rc5t583-gpio", 159e9fe32bcSLaxman Dewangan .owner = THIS_MODULE, 160e9fe32bcSLaxman Dewangan }, 161e9fe32bcSLaxman Dewangan .probe = rc5t583_gpio_probe, 162e9fe32bcSLaxman Dewangan .remove = __devexit_p(rc5t583_gpio_remove), 163e9fe32bcSLaxman Dewangan }; 164e9fe32bcSLaxman Dewangan 165e9fe32bcSLaxman Dewangan static int __init rc5t583_gpio_init(void) 166e9fe32bcSLaxman Dewangan { 167e9fe32bcSLaxman Dewangan return platform_driver_register(&rc5t583_gpio_driver); 168e9fe32bcSLaxman Dewangan } 169e9fe32bcSLaxman Dewangan subsys_initcall(rc5t583_gpio_init); 170e9fe32bcSLaxman Dewangan 171e9fe32bcSLaxman Dewangan static void __exit rc5t583_gpio_exit(void) 172e9fe32bcSLaxman Dewangan { 173e9fe32bcSLaxman Dewangan platform_driver_unregister(&rc5t583_gpio_driver); 174e9fe32bcSLaxman Dewangan } 175e9fe32bcSLaxman Dewangan module_exit(rc5t583_gpio_exit); 176e9fe32bcSLaxman Dewangan 177e9fe32bcSLaxman Dewangan MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>"); 178e9fe32bcSLaxman Dewangan MODULE_DESCRIPTION("GPIO interface for RC5T583"); 179e9fe32bcSLaxman Dewangan MODULE_LICENSE("GPL v2"); 180e9fe32bcSLaxman Dewangan MODULE_ALIAS("platform:rc5t583-gpio"); 181