1275b13a6SRajmohan Mani /* 2275b13a6SRajmohan Mani * GPIO driver for TPS68470 PMIC 3275b13a6SRajmohan Mani * 4275b13a6SRajmohan Mani * Copyright (C) 2017 Intel Corporation 5275b13a6SRajmohan Mani * 6275b13a6SRajmohan Mani * Authors: 7275b13a6SRajmohan Mani * Antti Laakso <antti.laakso@intel.com> 8275b13a6SRajmohan Mani * Tianshu Qiu <tian.shu.qiu@intel.com> 9275b13a6SRajmohan Mani * Jian Xu Zheng <jian.xu.zheng@intel.com> 10275b13a6SRajmohan Mani * Yuning Pu <yuning.pu@intel.com> 11275b13a6SRajmohan Mani * 12275b13a6SRajmohan Mani * This program is free software; you can redistribute it and/or 13275b13a6SRajmohan Mani * modify it under the terms of the GNU General Public License as 14275b13a6SRajmohan Mani * published by the Free Software Foundation version 2. 15275b13a6SRajmohan Mani * 16275b13a6SRajmohan Mani * This program is distributed "as is" WITHOUT ANY WARRANTY of any 17275b13a6SRajmohan Mani * kind, whether express or implied; without even the implied warranty 18275b13a6SRajmohan Mani * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19275b13a6SRajmohan Mani * GNU General Public License for more details. 20275b13a6SRajmohan Mani */ 21275b13a6SRajmohan Mani 22275b13a6SRajmohan Mani #include <linux/gpio/driver.h> 23275b13a6SRajmohan Mani #include <linux/mfd/tps68470.h> 24275b13a6SRajmohan Mani #include <linux/module.h> 25275b13a6SRajmohan Mani #include <linux/platform_device.h> 26275b13a6SRajmohan Mani #include <linux/regmap.h> 27275b13a6SRajmohan Mani 28275b13a6SRajmohan Mani #define TPS68470_N_LOGIC_OUTPUT 3 29275b13a6SRajmohan Mani #define TPS68470_N_REGULAR_GPIO 7 30275b13a6SRajmohan Mani #define TPS68470_N_GPIO (TPS68470_N_LOGIC_OUTPUT + TPS68470_N_REGULAR_GPIO) 31275b13a6SRajmohan Mani 32275b13a6SRajmohan Mani struct tps68470_gpio_data { 33275b13a6SRajmohan Mani struct regmap *tps68470_regmap; 34275b13a6SRajmohan Mani struct gpio_chip gc; 35275b13a6SRajmohan Mani }; 36275b13a6SRajmohan Mani 37275b13a6SRajmohan Mani static int tps68470_gpio_get(struct gpio_chip *gc, unsigned int offset) 38275b13a6SRajmohan Mani { 39275b13a6SRajmohan Mani struct tps68470_gpio_data *tps68470_gpio = gpiochip_get_data(gc); 40275b13a6SRajmohan Mani struct regmap *regmap = tps68470_gpio->tps68470_regmap; 41275b13a6SRajmohan Mani unsigned int reg = TPS68470_REG_GPDO; 42275b13a6SRajmohan Mani int val, ret; 43275b13a6SRajmohan Mani 44275b13a6SRajmohan Mani if (offset >= TPS68470_N_REGULAR_GPIO) { 45275b13a6SRajmohan Mani offset -= TPS68470_N_REGULAR_GPIO; 46275b13a6SRajmohan Mani reg = TPS68470_REG_SGPO; 47275b13a6SRajmohan Mani } 48275b13a6SRajmohan Mani 49275b13a6SRajmohan Mani ret = regmap_read(regmap, reg, &val); 50275b13a6SRajmohan Mani if (ret) { 51275b13a6SRajmohan Mani dev_err(tps68470_gpio->gc.parent, "reg 0x%x read failed\n", 52275b13a6SRajmohan Mani TPS68470_REG_SGPO); 53275b13a6SRajmohan Mani return ret; 54275b13a6SRajmohan Mani } 55275b13a6SRajmohan Mani return !!(val & BIT(offset)); 56275b13a6SRajmohan Mani } 57275b13a6SRajmohan Mani 58275b13a6SRajmohan Mani /* Return 0 if output, 1 if input */ 59275b13a6SRajmohan Mani static int tps68470_gpio_get_direction(struct gpio_chip *gc, 60275b13a6SRajmohan Mani unsigned int offset) 61275b13a6SRajmohan Mani { 62275b13a6SRajmohan Mani struct tps68470_gpio_data *tps68470_gpio = gpiochip_get_data(gc); 63275b13a6SRajmohan Mani struct regmap *regmap = tps68470_gpio->tps68470_regmap; 64275b13a6SRajmohan Mani int val, ret; 65275b13a6SRajmohan Mani 66275b13a6SRajmohan Mani /* rest are always outputs */ 67275b13a6SRajmohan Mani if (offset >= TPS68470_N_REGULAR_GPIO) 68275b13a6SRajmohan Mani return 0; 69275b13a6SRajmohan Mani 70275b13a6SRajmohan Mani ret = regmap_read(regmap, TPS68470_GPIO_CTL_REG_A(offset), &val); 71275b13a6SRajmohan Mani if (ret) { 72275b13a6SRajmohan Mani dev_err(tps68470_gpio->gc.parent, "reg 0x%x read failed\n", 73275b13a6SRajmohan Mani TPS68470_GPIO_CTL_REG_A(offset)); 74275b13a6SRajmohan Mani return ret; 75275b13a6SRajmohan Mani } 76275b13a6SRajmohan Mani 77275b13a6SRajmohan Mani val &= TPS68470_GPIO_MODE_MASK; 78275b13a6SRajmohan Mani return val >= TPS68470_GPIO_MODE_OUT_CMOS ? 0 : 1; 79275b13a6SRajmohan Mani } 80275b13a6SRajmohan Mani 81275b13a6SRajmohan Mani static void tps68470_gpio_set(struct gpio_chip *gc, unsigned int offset, 82275b13a6SRajmohan Mani int value) 83275b13a6SRajmohan Mani { 84275b13a6SRajmohan Mani struct tps68470_gpio_data *tps68470_gpio = gpiochip_get_data(gc); 85275b13a6SRajmohan Mani struct regmap *regmap = tps68470_gpio->tps68470_regmap; 86275b13a6SRajmohan Mani unsigned int reg = TPS68470_REG_GPDO; 87275b13a6SRajmohan Mani 88275b13a6SRajmohan Mani if (offset >= TPS68470_N_REGULAR_GPIO) { 89275b13a6SRajmohan Mani reg = TPS68470_REG_SGPO; 90275b13a6SRajmohan Mani offset -= TPS68470_N_REGULAR_GPIO; 91275b13a6SRajmohan Mani } 92275b13a6SRajmohan Mani 93275b13a6SRajmohan Mani regmap_update_bits(regmap, reg, BIT(offset), value ? BIT(offset) : 0); 94275b13a6SRajmohan Mani } 95275b13a6SRajmohan Mani 96275b13a6SRajmohan Mani static int tps68470_gpio_output(struct gpio_chip *gc, unsigned int offset, 97275b13a6SRajmohan Mani int value) 98275b13a6SRajmohan Mani { 99275b13a6SRajmohan Mani struct tps68470_gpio_data *tps68470_gpio = gpiochip_get_data(gc); 100275b13a6SRajmohan Mani struct regmap *regmap = tps68470_gpio->tps68470_regmap; 101275b13a6SRajmohan Mani 102275b13a6SRajmohan Mani /* rest are always outputs */ 103275b13a6SRajmohan Mani if (offset >= TPS68470_N_REGULAR_GPIO) 104275b13a6SRajmohan Mani return 0; 105275b13a6SRajmohan Mani 106275b13a6SRajmohan Mani /* Set the initial value */ 107275b13a6SRajmohan Mani tps68470_gpio_set(gc, offset, value); 108275b13a6SRajmohan Mani 109275b13a6SRajmohan Mani return regmap_update_bits(regmap, TPS68470_GPIO_CTL_REG_A(offset), 110275b13a6SRajmohan Mani TPS68470_GPIO_MODE_MASK, 111275b13a6SRajmohan Mani TPS68470_GPIO_MODE_OUT_CMOS); 112275b13a6SRajmohan Mani } 113275b13a6SRajmohan Mani 114275b13a6SRajmohan Mani static int tps68470_gpio_input(struct gpio_chip *gc, unsigned int offset) 115275b13a6SRajmohan Mani { 116275b13a6SRajmohan Mani struct tps68470_gpio_data *tps68470_gpio = gpiochip_get_data(gc); 117275b13a6SRajmohan Mani struct regmap *regmap = tps68470_gpio->tps68470_regmap; 118275b13a6SRajmohan Mani 119275b13a6SRajmohan Mani /* rest are always outputs */ 120275b13a6SRajmohan Mani if (offset >= TPS68470_N_REGULAR_GPIO) 121275b13a6SRajmohan Mani return -EINVAL; 122275b13a6SRajmohan Mani 123275b13a6SRajmohan Mani return regmap_update_bits(regmap, TPS68470_GPIO_CTL_REG_A(offset), 124275b13a6SRajmohan Mani TPS68470_GPIO_MODE_MASK, 0x00); 125275b13a6SRajmohan Mani } 126275b13a6SRajmohan Mani 127275b13a6SRajmohan Mani static const char *tps68470_names[TPS68470_N_GPIO] = { 128275b13a6SRajmohan Mani "gpio.0", "gpio.1", "gpio.2", "gpio.3", 129275b13a6SRajmohan Mani "gpio.4", "gpio.5", "gpio.6", 130275b13a6SRajmohan Mani "s_enable", "s_idle", "s_resetn", 131275b13a6SRajmohan Mani }; 132275b13a6SRajmohan Mani 133275b13a6SRajmohan Mani static int tps68470_gpio_probe(struct platform_device *pdev) 134275b13a6SRajmohan Mani { 135275b13a6SRajmohan Mani struct tps68470_gpio_data *tps68470_gpio; 136275b13a6SRajmohan Mani int ret; 137275b13a6SRajmohan Mani 138275b13a6SRajmohan Mani tps68470_gpio = devm_kzalloc(&pdev->dev, sizeof(*tps68470_gpio), 139275b13a6SRajmohan Mani GFP_KERNEL); 140275b13a6SRajmohan Mani if (!tps68470_gpio) 141275b13a6SRajmohan Mani return -ENOMEM; 142275b13a6SRajmohan Mani 143275b13a6SRajmohan Mani tps68470_gpio->tps68470_regmap = dev_get_drvdata(pdev->dev.parent); 144275b13a6SRajmohan Mani tps68470_gpio->gc.label = "tps68470-gpio"; 145275b13a6SRajmohan Mani tps68470_gpio->gc.owner = THIS_MODULE; 146275b13a6SRajmohan Mani tps68470_gpio->gc.direction_input = tps68470_gpio_input; 147275b13a6SRajmohan Mani tps68470_gpio->gc.direction_output = tps68470_gpio_output; 148275b13a6SRajmohan Mani tps68470_gpio->gc.get = tps68470_gpio_get; 149275b13a6SRajmohan Mani tps68470_gpio->gc.get_direction = tps68470_gpio_get_direction; 150275b13a6SRajmohan Mani tps68470_gpio->gc.set = tps68470_gpio_set; 151275b13a6SRajmohan Mani tps68470_gpio->gc.can_sleep = true; 152275b13a6SRajmohan Mani tps68470_gpio->gc.names = tps68470_names; 153275b13a6SRajmohan Mani tps68470_gpio->gc.ngpio = TPS68470_N_GPIO; 154275b13a6SRajmohan Mani tps68470_gpio->gc.base = -1; 155275b13a6SRajmohan Mani tps68470_gpio->gc.parent = &pdev->dev; 156275b13a6SRajmohan Mani 157275b13a6SRajmohan Mani ret = devm_gpiochip_add_data(&pdev->dev, &tps68470_gpio->gc, 158275b13a6SRajmohan Mani tps68470_gpio); 159275b13a6SRajmohan Mani if (ret < 0) { 160275b13a6SRajmohan Mani dev_err(&pdev->dev, "Failed to register gpio_chip: %d\n", ret); 161275b13a6SRajmohan Mani return ret; 162275b13a6SRajmohan Mani } 163275b13a6SRajmohan Mani 164275b13a6SRajmohan Mani platform_set_drvdata(pdev, tps68470_gpio); 165275b13a6SRajmohan Mani 166275b13a6SRajmohan Mani return ret; 167275b13a6SRajmohan Mani } 168275b13a6SRajmohan Mani 169275b13a6SRajmohan Mani static struct platform_driver tps68470_gpio_driver = { 170275b13a6SRajmohan Mani .driver = { 171275b13a6SRajmohan Mani .name = "tps68470-gpio", 172275b13a6SRajmohan Mani }, 173275b13a6SRajmohan Mani .probe = tps68470_gpio_probe, 174275b13a6SRajmohan Mani }; 175275b13a6SRajmohan Mani 176275b13a6SRajmohan Mani builtin_platform_driver(tps68470_gpio_driver) 177