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 int rc5t583_gpio_get(struct gpio_chip *gc, unsigned int offset) 38e9fe32bcSLaxman Dewangan { 39d660c68eSLinus Walleij struct rc5t583_gpio *rc5t583_gpio = gpiochip_get_data(gc); 40e9fe32bcSLaxman Dewangan struct device *parent = rc5t583_gpio->rc5t583->dev; 41e9fe32bcSLaxman Dewangan uint8_t val = 0; 42e9fe32bcSLaxman Dewangan int ret; 43e9fe32bcSLaxman Dewangan 44e9fe32bcSLaxman Dewangan ret = rc5t583_read(parent, RC5T583_GPIO_MON_IOIN, &val); 45e9fe32bcSLaxman Dewangan if (ret < 0) 46e9fe32bcSLaxman Dewangan return ret; 47e9fe32bcSLaxman Dewangan 48e9fe32bcSLaxman Dewangan return !!(val & BIT(offset)); 49e9fe32bcSLaxman Dewangan } 50e9fe32bcSLaxman Dewangan 51e9fe32bcSLaxman Dewangan static void rc5t583_gpio_set(struct gpio_chip *gc, unsigned int offset, int val) 52e9fe32bcSLaxman Dewangan { 53d660c68eSLinus Walleij struct rc5t583_gpio *rc5t583_gpio = gpiochip_get_data(gc); 54e9fe32bcSLaxman Dewangan struct device *parent = rc5t583_gpio->rc5t583->dev; 55e9fe32bcSLaxman Dewangan if (val) 56e9fe32bcSLaxman Dewangan rc5t583_set_bits(parent, RC5T583_GPIO_IOOUT, BIT(offset)); 57e9fe32bcSLaxman Dewangan else 58e9fe32bcSLaxman Dewangan rc5t583_clear_bits(parent, RC5T583_GPIO_IOOUT, BIT(offset)); 59e9fe32bcSLaxman Dewangan } 60e9fe32bcSLaxman Dewangan 61e9fe32bcSLaxman Dewangan static int rc5t583_gpio_dir_input(struct gpio_chip *gc, unsigned int offset) 62e9fe32bcSLaxman Dewangan { 63d660c68eSLinus Walleij struct rc5t583_gpio *rc5t583_gpio = gpiochip_get_data(gc); 64e9fe32bcSLaxman Dewangan struct device *parent = rc5t583_gpio->rc5t583->dev; 65e9fe32bcSLaxman Dewangan int ret; 66e9fe32bcSLaxman Dewangan 67e9fe32bcSLaxman Dewangan ret = rc5t583_clear_bits(parent, RC5T583_GPIO_IOSEL, BIT(offset)); 68e9fe32bcSLaxman Dewangan if (ret < 0) 69e9fe32bcSLaxman Dewangan return ret; 70e9fe32bcSLaxman Dewangan 71e9fe32bcSLaxman Dewangan /* Set pin to gpio mode */ 72e9fe32bcSLaxman Dewangan return rc5t583_clear_bits(parent, RC5T583_GPIO_PGSEL, BIT(offset)); 73e9fe32bcSLaxman Dewangan } 74e9fe32bcSLaxman Dewangan 75e9fe32bcSLaxman Dewangan static int rc5t583_gpio_dir_output(struct gpio_chip *gc, unsigned offset, 76e9fe32bcSLaxman Dewangan int value) 77e9fe32bcSLaxman Dewangan { 78d660c68eSLinus Walleij struct rc5t583_gpio *rc5t583_gpio = gpiochip_get_data(gc); 79e9fe32bcSLaxman Dewangan struct device *parent = rc5t583_gpio->rc5t583->dev; 80e9fe32bcSLaxman Dewangan int ret; 81e9fe32bcSLaxman Dewangan 82e9fe32bcSLaxman Dewangan rc5t583_gpio_set(gc, offset, value); 83e9fe32bcSLaxman Dewangan ret = rc5t583_set_bits(parent, RC5T583_GPIO_IOSEL, BIT(offset)); 84e9fe32bcSLaxman Dewangan if (ret < 0) 85e9fe32bcSLaxman Dewangan return ret; 86e9fe32bcSLaxman Dewangan 87e9fe32bcSLaxman Dewangan /* Set pin to gpio mode */ 88e9fe32bcSLaxman Dewangan return rc5t583_clear_bits(parent, RC5T583_GPIO_PGSEL, BIT(offset)); 89e9fe32bcSLaxman Dewangan } 90e9fe32bcSLaxman Dewangan 91e9fe32bcSLaxman Dewangan static int rc5t583_gpio_to_irq(struct gpio_chip *gc, unsigned offset) 92e9fe32bcSLaxman Dewangan { 93d660c68eSLinus Walleij struct rc5t583_gpio *rc5t583_gpio = gpiochip_get_data(gc); 94e9fe32bcSLaxman Dewangan 953bde4d26SAlexander Shiyan if (offset < RC5T583_MAX_GPIO) 96e9fe32bcSLaxman Dewangan return rc5t583_gpio->rc5t583->irq_base + 97e9fe32bcSLaxman Dewangan RC5T583_IRQ_GPIO0 + offset; 98e9fe32bcSLaxman Dewangan return -EINVAL; 99e9fe32bcSLaxman Dewangan } 100e9fe32bcSLaxman Dewangan 101e9fe32bcSLaxman Dewangan static void rc5t583_gpio_free(struct gpio_chip *gc, unsigned offset) 102e9fe32bcSLaxman Dewangan { 103d660c68eSLinus Walleij struct rc5t583_gpio *rc5t583_gpio = gpiochip_get_data(gc); 104e9fe32bcSLaxman Dewangan struct device *parent = rc5t583_gpio->rc5t583->dev; 105e9fe32bcSLaxman Dewangan 106e9fe32bcSLaxman Dewangan rc5t583_set_bits(parent, RC5T583_GPIO_PGSEL, BIT(offset)); 107e9fe32bcSLaxman Dewangan } 108e9fe32bcSLaxman Dewangan 1093836309dSBill Pemberton static int rc5t583_gpio_probe(struct platform_device *pdev) 110e9fe32bcSLaxman Dewangan { 111e9fe32bcSLaxman Dewangan struct rc5t583 *rc5t583 = dev_get_drvdata(pdev->dev.parent); 112e9fe32bcSLaxman Dewangan struct rc5t583_platform_data *pdata = dev_get_platdata(rc5t583->dev); 113e9fe32bcSLaxman Dewangan struct rc5t583_gpio *rc5t583_gpio; 114e9fe32bcSLaxman Dewangan 115e9fe32bcSLaxman Dewangan rc5t583_gpio = devm_kzalloc(&pdev->dev, sizeof(*rc5t583_gpio), 116e9fe32bcSLaxman Dewangan GFP_KERNEL); 1174b7dfd7fSJingoo Han if (!rc5t583_gpio) 118e9fe32bcSLaxman Dewangan return -ENOMEM; 119e9fe32bcSLaxman Dewangan 120e9fe32bcSLaxman Dewangan rc5t583_gpio->gpio_chip.label = "gpio-rc5t583", 121e9fe32bcSLaxman Dewangan rc5t583_gpio->gpio_chip.owner = THIS_MODULE, 122e9fe32bcSLaxman Dewangan rc5t583_gpio->gpio_chip.free = rc5t583_gpio_free, 123e9fe32bcSLaxman Dewangan rc5t583_gpio->gpio_chip.direction_input = rc5t583_gpio_dir_input, 124e9fe32bcSLaxman Dewangan rc5t583_gpio->gpio_chip.direction_output = rc5t583_gpio_dir_output, 125e9fe32bcSLaxman Dewangan rc5t583_gpio->gpio_chip.set = rc5t583_gpio_set, 126e9fe32bcSLaxman Dewangan rc5t583_gpio->gpio_chip.get = rc5t583_gpio_get, 127e9fe32bcSLaxman Dewangan rc5t583_gpio->gpio_chip.to_irq = rc5t583_gpio_to_irq, 128e9fe32bcSLaxman Dewangan rc5t583_gpio->gpio_chip.ngpio = RC5T583_MAX_GPIO, 1299fb1f39eSLinus Walleij rc5t583_gpio->gpio_chip.can_sleep = true, 13058383c78SLinus Walleij rc5t583_gpio->gpio_chip.parent = &pdev->dev; 131e9fe32bcSLaxman Dewangan rc5t583_gpio->gpio_chip.base = -1; 132e9fe32bcSLaxman Dewangan rc5t583_gpio->rc5t583 = rc5t583; 133e9fe32bcSLaxman Dewangan 134e9fe32bcSLaxman Dewangan if (pdata && pdata->gpio_base) 135e9fe32bcSLaxman Dewangan rc5t583_gpio->gpio_chip.base = pdata->gpio_base; 136e9fe32bcSLaxman Dewangan 137e9fe32bcSLaxman Dewangan platform_set_drvdata(pdev, rc5t583_gpio); 138e9fe32bcSLaxman Dewangan 139d660c68eSLinus Walleij return gpiochip_add_data(&rc5t583_gpio->gpio_chip, rc5t583_gpio); 140e9fe32bcSLaxman Dewangan } 141e9fe32bcSLaxman Dewangan 142206210ceSBill Pemberton static int rc5t583_gpio_remove(struct platform_device *pdev) 143e9fe32bcSLaxman Dewangan { 144e9fe32bcSLaxman Dewangan struct rc5t583_gpio *rc5t583_gpio = platform_get_drvdata(pdev); 145e9fe32bcSLaxman Dewangan 1469f5132aeSabdoulaye berthe gpiochip_remove(&rc5t583_gpio->gpio_chip); 1479f5132aeSabdoulaye berthe return 0; 148e9fe32bcSLaxman Dewangan } 149e9fe32bcSLaxman Dewangan 150e9fe32bcSLaxman Dewangan static struct platform_driver rc5t583_gpio_driver = { 151e9fe32bcSLaxman Dewangan .driver = { 152e9fe32bcSLaxman Dewangan .name = "rc5t583-gpio", 153e9fe32bcSLaxman Dewangan }, 154e9fe32bcSLaxman Dewangan .probe = rc5t583_gpio_probe, 1558283c4ffSBill Pemberton .remove = rc5t583_gpio_remove, 156e9fe32bcSLaxman Dewangan }; 157e9fe32bcSLaxman Dewangan 158e9fe32bcSLaxman Dewangan static int __init rc5t583_gpio_init(void) 159e9fe32bcSLaxman Dewangan { 160e9fe32bcSLaxman Dewangan return platform_driver_register(&rc5t583_gpio_driver); 161e9fe32bcSLaxman Dewangan } 162e9fe32bcSLaxman Dewangan subsys_initcall(rc5t583_gpio_init); 163e9fe32bcSLaxman Dewangan 164e9fe32bcSLaxman Dewangan static void __exit rc5t583_gpio_exit(void) 165e9fe32bcSLaxman Dewangan { 166e9fe32bcSLaxman Dewangan platform_driver_unregister(&rc5t583_gpio_driver); 167e9fe32bcSLaxman Dewangan } 168e9fe32bcSLaxman Dewangan module_exit(rc5t583_gpio_exit); 169e9fe32bcSLaxman Dewangan 170e9fe32bcSLaxman Dewangan MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>"); 171e9fe32bcSLaxman Dewangan MODULE_DESCRIPTION("GPIO interface for RC5T583"); 172e9fe32bcSLaxman Dewangan MODULE_LICENSE("GPL v2"); 173e9fe32bcSLaxman Dewangan MODULE_ALIAS("platform:rc5t583-gpio"); 174