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/platform_device.h> 27e9fe32bcSLaxman Dewangan #include <linux/device.h> 2898aef8e7SLinus Walleij #include <linux/gpio/driver.h> 29e9fe32bcSLaxman Dewangan #include <linux/mfd/rc5t583.h> 30e9fe32bcSLaxman Dewangan 31e9fe32bcSLaxman Dewangan struct rc5t583_gpio { 32e9fe32bcSLaxman Dewangan struct gpio_chip gpio_chip; 33e9fe32bcSLaxman Dewangan struct rc5t583 *rc5t583; 34e9fe32bcSLaxman Dewangan }; 35e9fe32bcSLaxman Dewangan 36e9fe32bcSLaxman Dewangan static int rc5t583_gpio_get(struct gpio_chip *gc, unsigned int offset) 37e9fe32bcSLaxman Dewangan { 38d660c68eSLinus Walleij struct rc5t583_gpio *rc5t583_gpio = gpiochip_get_data(gc); 39e9fe32bcSLaxman Dewangan struct device *parent = rc5t583_gpio->rc5t583->dev; 40e9fe32bcSLaxman Dewangan uint8_t val = 0; 41e9fe32bcSLaxman Dewangan int ret; 42e9fe32bcSLaxman Dewangan 43e9fe32bcSLaxman Dewangan ret = rc5t583_read(parent, RC5T583_GPIO_MON_IOIN, &val); 44e9fe32bcSLaxman Dewangan if (ret < 0) 45e9fe32bcSLaxman Dewangan return ret; 46e9fe32bcSLaxman Dewangan 47e9fe32bcSLaxman Dewangan return !!(val & BIT(offset)); 48e9fe32bcSLaxman Dewangan } 49e9fe32bcSLaxman Dewangan 50e9fe32bcSLaxman Dewangan static void rc5t583_gpio_set(struct gpio_chip *gc, unsigned int offset, int val) 51e9fe32bcSLaxman Dewangan { 52d660c68eSLinus Walleij struct rc5t583_gpio *rc5t583_gpio = gpiochip_get_data(gc); 53e9fe32bcSLaxman Dewangan struct device *parent = rc5t583_gpio->rc5t583->dev; 54e9fe32bcSLaxman Dewangan if (val) 55e9fe32bcSLaxman Dewangan rc5t583_set_bits(parent, RC5T583_GPIO_IOOUT, BIT(offset)); 56e9fe32bcSLaxman Dewangan else 57e9fe32bcSLaxman Dewangan rc5t583_clear_bits(parent, RC5T583_GPIO_IOOUT, BIT(offset)); 58e9fe32bcSLaxman Dewangan } 59e9fe32bcSLaxman Dewangan 60e9fe32bcSLaxman Dewangan static int rc5t583_gpio_dir_input(struct gpio_chip *gc, unsigned int offset) 61e9fe32bcSLaxman Dewangan { 62d660c68eSLinus Walleij struct rc5t583_gpio *rc5t583_gpio = gpiochip_get_data(gc); 63e9fe32bcSLaxman Dewangan struct device *parent = rc5t583_gpio->rc5t583->dev; 64e9fe32bcSLaxman Dewangan int ret; 65e9fe32bcSLaxman Dewangan 66e9fe32bcSLaxman Dewangan ret = rc5t583_clear_bits(parent, RC5T583_GPIO_IOSEL, BIT(offset)); 67e9fe32bcSLaxman Dewangan if (ret < 0) 68e9fe32bcSLaxman Dewangan return ret; 69e9fe32bcSLaxman Dewangan 70e9fe32bcSLaxman Dewangan /* Set pin to gpio mode */ 71e9fe32bcSLaxman Dewangan return rc5t583_clear_bits(parent, RC5T583_GPIO_PGSEL, BIT(offset)); 72e9fe32bcSLaxman Dewangan } 73e9fe32bcSLaxman Dewangan 74e9fe32bcSLaxman Dewangan static int rc5t583_gpio_dir_output(struct gpio_chip *gc, unsigned offset, 75e9fe32bcSLaxman Dewangan int value) 76e9fe32bcSLaxman Dewangan { 77d660c68eSLinus Walleij struct rc5t583_gpio *rc5t583_gpio = gpiochip_get_data(gc); 78e9fe32bcSLaxman Dewangan struct device *parent = rc5t583_gpio->rc5t583->dev; 79e9fe32bcSLaxman Dewangan int ret; 80e9fe32bcSLaxman Dewangan 81e9fe32bcSLaxman Dewangan rc5t583_gpio_set(gc, offset, value); 82e9fe32bcSLaxman Dewangan ret = rc5t583_set_bits(parent, RC5T583_GPIO_IOSEL, BIT(offset)); 83e9fe32bcSLaxman Dewangan if (ret < 0) 84e9fe32bcSLaxman Dewangan return ret; 85e9fe32bcSLaxman Dewangan 86e9fe32bcSLaxman Dewangan /* Set pin to gpio mode */ 87e9fe32bcSLaxman Dewangan return rc5t583_clear_bits(parent, RC5T583_GPIO_PGSEL, BIT(offset)); 88e9fe32bcSLaxman Dewangan } 89e9fe32bcSLaxman Dewangan 90e9fe32bcSLaxman Dewangan static int rc5t583_gpio_to_irq(struct gpio_chip *gc, unsigned offset) 91e9fe32bcSLaxman Dewangan { 92d660c68eSLinus Walleij struct rc5t583_gpio *rc5t583_gpio = gpiochip_get_data(gc); 93e9fe32bcSLaxman Dewangan 943bde4d26SAlexander Shiyan if (offset < RC5T583_MAX_GPIO) 95e9fe32bcSLaxman Dewangan return rc5t583_gpio->rc5t583->irq_base + 96e9fe32bcSLaxman Dewangan RC5T583_IRQ_GPIO0 + offset; 97e9fe32bcSLaxman Dewangan return -EINVAL; 98e9fe32bcSLaxman Dewangan } 99e9fe32bcSLaxman Dewangan 100e9fe32bcSLaxman Dewangan static void rc5t583_gpio_free(struct gpio_chip *gc, unsigned offset) 101e9fe32bcSLaxman Dewangan { 102d660c68eSLinus Walleij struct rc5t583_gpio *rc5t583_gpio = gpiochip_get_data(gc); 103e9fe32bcSLaxman Dewangan struct device *parent = rc5t583_gpio->rc5t583->dev; 104e9fe32bcSLaxman Dewangan 105e9fe32bcSLaxman Dewangan rc5t583_set_bits(parent, RC5T583_GPIO_PGSEL, BIT(offset)); 106e9fe32bcSLaxman Dewangan } 107e9fe32bcSLaxman Dewangan 1083836309dSBill Pemberton static int rc5t583_gpio_probe(struct platform_device *pdev) 109e9fe32bcSLaxman Dewangan { 110e9fe32bcSLaxman Dewangan struct rc5t583 *rc5t583 = dev_get_drvdata(pdev->dev.parent); 111e9fe32bcSLaxman Dewangan struct rc5t583_platform_data *pdata = dev_get_platdata(rc5t583->dev); 112e9fe32bcSLaxman Dewangan struct rc5t583_gpio *rc5t583_gpio; 113e9fe32bcSLaxman Dewangan 114e9fe32bcSLaxman Dewangan rc5t583_gpio = devm_kzalloc(&pdev->dev, sizeof(*rc5t583_gpio), 115e9fe32bcSLaxman Dewangan GFP_KERNEL); 1164b7dfd7fSJingoo Han if (!rc5t583_gpio) 117e9fe32bcSLaxman Dewangan return -ENOMEM; 118e9fe32bcSLaxman Dewangan 119e9fe32bcSLaxman Dewangan rc5t583_gpio->gpio_chip.label = "gpio-rc5t583", 120e9fe32bcSLaxman Dewangan rc5t583_gpio->gpio_chip.owner = THIS_MODULE, 121e9fe32bcSLaxman Dewangan rc5t583_gpio->gpio_chip.free = rc5t583_gpio_free, 122e9fe32bcSLaxman Dewangan rc5t583_gpio->gpio_chip.direction_input = rc5t583_gpio_dir_input, 123e9fe32bcSLaxman Dewangan rc5t583_gpio->gpio_chip.direction_output = rc5t583_gpio_dir_output, 124e9fe32bcSLaxman Dewangan rc5t583_gpio->gpio_chip.set = rc5t583_gpio_set, 125e9fe32bcSLaxman Dewangan rc5t583_gpio->gpio_chip.get = rc5t583_gpio_get, 126e9fe32bcSLaxman Dewangan rc5t583_gpio->gpio_chip.to_irq = rc5t583_gpio_to_irq, 127e9fe32bcSLaxman Dewangan rc5t583_gpio->gpio_chip.ngpio = RC5T583_MAX_GPIO, 1289fb1f39eSLinus Walleij rc5t583_gpio->gpio_chip.can_sleep = true, 12958383c78SLinus Walleij rc5t583_gpio->gpio_chip.parent = &pdev->dev; 130e9fe32bcSLaxman Dewangan rc5t583_gpio->gpio_chip.base = -1; 131e9fe32bcSLaxman Dewangan rc5t583_gpio->rc5t583 = rc5t583; 132e9fe32bcSLaxman Dewangan 133e9fe32bcSLaxman Dewangan if (pdata && pdata->gpio_base) 134e9fe32bcSLaxman Dewangan rc5t583_gpio->gpio_chip.base = pdata->gpio_base; 135e9fe32bcSLaxman Dewangan 136e9fe32bcSLaxman Dewangan platform_set_drvdata(pdev, rc5t583_gpio); 137e9fe32bcSLaxman Dewangan 138bc72f7f7SLaxman Dewangan return devm_gpiochip_add_data(&pdev->dev, &rc5t583_gpio->gpio_chip, 139bc72f7f7SLaxman Dewangan rc5t583_gpio); 140e9fe32bcSLaxman Dewangan } 141e9fe32bcSLaxman Dewangan 142e9fe32bcSLaxman Dewangan static struct platform_driver rc5t583_gpio_driver = { 143e9fe32bcSLaxman Dewangan .driver = { 144e9fe32bcSLaxman Dewangan .name = "rc5t583-gpio", 145e9fe32bcSLaxman Dewangan }, 146e9fe32bcSLaxman Dewangan .probe = rc5t583_gpio_probe, 147e9fe32bcSLaxman Dewangan }; 148e9fe32bcSLaxman Dewangan 149e9fe32bcSLaxman Dewangan static int __init rc5t583_gpio_init(void) 150e9fe32bcSLaxman Dewangan { 151e9fe32bcSLaxman Dewangan return platform_driver_register(&rc5t583_gpio_driver); 152e9fe32bcSLaxman Dewangan } 153e9fe32bcSLaxman Dewangan subsys_initcall(rc5t583_gpio_init); 154