cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

gpio-tps68470.c (4654B)


      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 void 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	regmap_update_bits(regmap, reg, BIT(offset), value ? BIT(offset) : 0);
     86}
     87
     88static int tps68470_gpio_output(struct gpio_chip *gc, unsigned int offset,
     89				int value)
     90{
     91	struct tps68470_gpio_data *tps68470_gpio = gpiochip_get_data(gc);
     92	struct regmap *regmap = tps68470_gpio->tps68470_regmap;
     93
     94	/* rest are always outputs */
     95	if (offset >= TPS68470_N_REGULAR_GPIO)
     96		return 0;
     97
     98	/* Set the initial value */
     99	tps68470_gpio_set(gc, offset, value);
    100
    101	return regmap_update_bits(regmap, TPS68470_GPIO_CTL_REG_A(offset),
    102				 TPS68470_GPIO_MODE_MASK,
    103				 TPS68470_GPIO_MODE_OUT_CMOS);
    104}
    105
    106static int tps68470_gpio_input(struct gpio_chip *gc, unsigned int offset)
    107{
    108	struct tps68470_gpio_data *tps68470_gpio = gpiochip_get_data(gc);
    109	struct regmap *regmap = tps68470_gpio->tps68470_regmap;
    110
    111	/* rest are always outputs */
    112	if (offset >= TPS68470_N_REGULAR_GPIO)
    113		return -EINVAL;
    114
    115	return regmap_update_bits(regmap, TPS68470_GPIO_CTL_REG_A(offset),
    116				   TPS68470_GPIO_MODE_MASK, 0x00);
    117}
    118
    119static const char *tps68470_names[TPS68470_N_GPIO] = {
    120	"gpio.0", "gpio.1", "gpio.2", "gpio.3",
    121	"gpio.4", "gpio.5", "gpio.6",
    122	"s_enable", "s_idle", "s_resetn",
    123};
    124
    125static int tps68470_gpio_probe(struct platform_device *pdev)
    126{
    127	struct tps68470_gpio_data *tps68470_gpio;
    128
    129	tps68470_gpio = devm_kzalloc(&pdev->dev, sizeof(*tps68470_gpio),
    130				     GFP_KERNEL);
    131	if (!tps68470_gpio)
    132		return -ENOMEM;
    133
    134	tps68470_gpio->tps68470_regmap = dev_get_drvdata(pdev->dev.parent);
    135	tps68470_gpio->gc.label = "tps68470-gpio";
    136	tps68470_gpio->gc.owner = THIS_MODULE;
    137	tps68470_gpio->gc.direction_input = tps68470_gpio_input;
    138	tps68470_gpio->gc.direction_output = tps68470_gpio_output;
    139	tps68470_gpio->gc.get = tps68470_gpio_get;
    140	tps68470_gpio->gc.get_direction = tps68470_gpio_get_direction;
    141	tps68470_gpio->gc.set = tps68470_gpio_set;
    142	tps68470_gpio->gc.can_sleep = true;
    143	tps68470_gpio->gc.names = tps68470_names;
    144	tps68470_gpio->gc.ngpio = TPS68470_N_GPIO;
    145	tps68470_gpio->gc.base = -1;
    146	tps68470_gpio->gc.parent = &pdev->dev;
    147
    148	return devm_gpiochip_add_data(&pdev->dev, &tps68470_gpio->gc, tps68470_gpio);
    149}
    150
    151static struct platform_driver tps68470_gpio_driver = {
    152	.driver = {
    153		   .name = "tps68470-gpio",
    154	},
    155	.probe = tps68470_gpio_probe,
    156};
    157module_platform_driver(tps68470_gpio_driver);
    158
    159MODULE_ALIAS("platform:tps68470-gpio");
    160MODULE_DESCRIPTION("GPIO driver for TPS68470 PMIC");
    161MODULE_LICENSE("GPL v2");