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

Configure Feed

Select the types of activity you want to include in your feed.

at master 184 lines 5.1 kB view raw
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * GPIO driver for TPS68470 PMIC 4 * 5 * Copyright (C) 2017 Intel Corporation 6 * 7 * Authors: 8 * Antti Laakso <antti.laakso@intel.com> 9 * Tianshu Qiu <tian.shu.qiu@intel.com> 10 * Jian Xu Zheng <jian.xu.zheng@intel.com> 11 * Yuning Pu <yuning.pu@intel.com> 12 */ 13 14#include <linux/gpio/driver.h> 15#include <linux/mfd/tps68470.h> 16#include <linux/module.h> 17#include <linux/platform_device.h> 18#include <linux/regmap.h> 19 20#define TPS68470_N_LOGIC_OUTPUT 3 21#define TPS68470_N_REGULAR_GPIO 7 22#define TPS68470_N_GPIO (TPS68470_N_LOGIC_OUTPUT + TPS68470_N_REGULAR_GPIO) 23 24struct tps68470_gpio_data { 25 struct regmap *tps68470_regmap; 26 struct gpio_chip gc; 27}; 28 29static int tps68470_gpio_get(struct gpio_chip *gc, unsigned int offset) 30{ 31 struct tps68470_gpio_data *tps68470_gpio = gpiochip_get_data(gc); 32 struct regmap *regmap = tps68470_gpio->tps68470_regmap; 33 unsigned int reg = TPS68470_REG_GPDO; 34 int val, ret; 35 36 if (offset >= TPS68470_N_REGULAR_GPIO) { 37 offset -= TPS68470_N_REGULAR_GPIO; 38 reg = TPS68470_REG_SGPO; 39 } 40 41 ret = regmap_read(regmap, reg, &val); 42 if (ret) { 43 dev_err(tps68470_gpio->gc.parent, "reg 0x%x read failed\n", 44 TPS68470_REG_SGPO); 45 return ret; 46 } 47 return !!(val & BIT(offset)); 48} 49 50static int tps68470_gpio_get_direction(struct gpio_chip *gc, 51 unsigned int offset) 52{ 53 struct tps68470_gpio_data *tps68470_gpio = gpiochip_get_data(gc); 54 struct regmap *regmap = tps68470_gpio->tps68470_regmap; 55 int val, ret; 56 57 /* rest are always outputs */ 58 if (offset >= TPS68470_N_REGULAR_GPIO) 59 return GPIO_LINE_DIRECTION_OUT; 60 61 ret = regmap_read(regmap, TPS68470_GPIO_CTL_REG_A(offset), &val); 62 if (ret) { 63 dev_err(tps68470_gpio->gc.parent, "reg 0x%x read failed\n", 64 TPS68470_GPIO_CTL_REG_A(offset)); 65 return ret; 66 } 67 68 val &= TPS68470_GPIO_MODE_MASK; 69 return val >= TPS68470_GPIO_MODE_OUT_CMOS ? GPIO_LINE_DIRECTION_OUT : 70 GPIO_LINE_DIRECTION_IN; 71} 72 73static int tps68470_gpio_set(struct gpio_chip *gc, unsigned int offset, 74 int value) 75{ 76 struct tps68470_gpio_data *tps68470_gpio = gpiochip_get_data(gc); 77 struct regmap *regmap = tps68470_gpio->tps68470_regmap; 78 unsigned int reg = TPS68470_REG_GPDO; 79 80 if (offset >= TPS68470_N_REGULAR_GPIO) { 81 reg = TPS68470_REG_SGPO; 82 offset -= TPS68470_N_REGULAR_GPIO; 83 } 84 85 return regmap_update_bits(regmap, reg, BIT(offset), 86 value ? BIT(offset) : 0); 87} 88 89static int tps68470_gpio_output(struct gpio_chip *gc, unsigned int offset, 90 int value) 91{ 92 struct tps68470_gpio_data *tps68470_gpio = gpiochip_get_data(gc); 93 struct regmap *regmap = tps68470_gpio->tps68470_regmap; 94 int ret; 95 96 /* Set the initial value */ 97 ret = tps68470_gpio_set(gc, offset, value); 98 if (ret) 99 return ret; 100 101 /* rest are always outputs */ 102 if (offset >= TPS68470_N_REGULAR_GPIO) 103 return 0; 104 105 return regmap_update_bits(regmap, TPS68470_GPIO_CTL_REG_A(offset), 106 TPS68470_GPIO_MODE_MASK, 107 TPS68470_GPIO_MODE_OUT_CMOS); 108} 109 110static int tps68470_gpio_input(struct gpio_chip *gc, unsigned int offset) 111{ 112 struct tps68470_gpio_data *tps68470_gpio = gpiochip_get_data(gc); 113 struct regmap *regmap = tps68470_gpio->tps68470_regmap; 114 115 /* rest are always outputs */ 116 if (offset >= TPS68470_N_REGULAR_GPIO) 117 return -EINVAL; 118 119 return regmap_update_bits(regmap, TPS68470_GPIO_CTL_REG_A(offset), 120 TPS68470_GPIO_MODE_MASK, 0x00); 121} 122 123static int tps68470_enable_i2c_daisy_chain(struct gpio_chip *gc) 124{ 125 int ret; 126 127 ret = tps68470_gpio_input(gc, 1); 128 if (ret) 129 return ret; 130 131 return tps68470_gpio_input(gc, 2); 132} 133 134static const char *tps68470_names[TPS68470_N_GPIO] = { 135 "gpio.0", "gpio.1", "gpio.2", "gpio.3", 136 "gpio.4", "gpio.5", "gpio.6", 137 "s_enable", "s_idle", "s_resetn", 138}; 139 140static int tps68470_gpio_probe(struct platform_device *pdev) 141{ 142 struct tps68470_gpio_data *tps68470_gpio; 143 int ret; 144 145 tps68470_gpio = devm_kzalloc(&pdev->dev, sizeof(*tps68470_gpio), 146 GFP_KERNEL); 147 if (!tps68470_gpio) 148 return -ENOMEM; 149 150 tps68470_gpio->tps68470_regmap = dev_get_drvdata(pdev->dev.parent); 151 tps68470_gpio->gc.label = "tps68470-gpio"; 152 tps68470_gpio->gc.owner = THIS_MODULE; 153 tps68470_gpio->gc.direction_input = tps68470_gpio_input; 154 tps68470_gpio->gc.direction_output = tps68470_gpio_output; 155 tps68470_gpio->gc.get = tps68470_gpio_get; 156 tps68470_gpio->gc.get_direction = tps68470_gpio_get_direction; 157 tps68470_gpio->gc.set = tps68470_gpio_set; 158 tps68470_gpio->gc.can_sleep = true; 159 tps68470_gpio->gc.names = tps68470_names; 160 tps68470_gpio->gc.ngpio = TPS68470_N_GPIO; 161 tps68470_gpio->gc.base = -1; 162 tps68470_gpio->gc.parent = &pdev->dev; 163 164 ret = devm_gpiochip_add_data(&pdev->dev, &tps68470_gpio->gc, tps68470_gpio); 165 if (ret) 166 return ret; 167 168 if (device_property_present(&pdev->dev, "daisy-chain-enable")) 169 ret = tps68470_enable_i2c_daisy_chain(&tps68470_gpio->gc); 170 171 return ret; 172} 173 174static struct platform_driver tps68470_gpio_driver = { 175 .driver = { 176 .name = "tps68470-gpio", 177 }, 178 .probe = tps68470_gpio_probe, 179}; 180module_platform_driver(tps68470_gpio_driver); 181 182MODULE_ALIAS("platform:tps68470-gpio"); 183MODULE_DESCRIPTION("GPIO driver for TPS68470 PMIC"); 184MODULE_LICENSE("GPL v2");