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-tps65910.c (4889B)


      1// SPDX-License-Identifier: GPL-2.0+
      2/*
      3 * TI TPS6591x GPIO driver
      4 *
      5 * Copyright 2010 Texas Instruments Inc.
      6 *
      7 * Author: Graeme Gregory <gg@slimlogic.co.uk>
      8 * Author: Jorge Eduardo Candelaria <jedu@slimlogic.co.uk>
      9 */
     10
     11#include <linux/kernel.h>
     12#include <linux/init.h>
     13#include <linux/errno.h>
     14#include <linux/gpio/driver.h>
     15#include <linux/i2c.h>
     16#include <linux/platform_device.h>
     17#include <linux/mfd/tps65910.h>
     18#include <linux/of_device.h>
     19
     20struct tps65910_gpio {
     21	struct gpio_chip gpio_chip;
     22	struct tps65910 *tps65910;
     23};
     24
     25static int tps65910_gpio_get(struct gpio_chip *gc, unsigned offset)
     26{
     27	struct tps65910_gpio *tps65910_gpio = gpiochip_get_data(gc);
     28	struct tps65910 *tps65910 = tps65910_gpio->tps65910;
     29	unsigned int val;
     30
     31	regmap_read(tps65910->regmap, TPS65910_GPIO0 + offset, &val);
     32
     33	if (val & GPIO_STS_MASK)
     34		return 1;
     35
     36	return 0;
     37}
     38
     39static void tps65910_gpio_set(struct gpio_chip *gc, unsigned offset,
     40			      int value)
     41{
     42	struct tps65910_gpio *tps65910_gpio = gpiochip_get_data(gc);
     43	struct tps65910 *tps65910 = tps65910_gpio->tps65910;
     44
     45	if (value)
     46		regmap_set_bits(tps65910->regmap, TPS65910_GPIO0 + offset,
     47						GPIO_SET_MASK);
     48	else
     49		regmap_clear_bits(tps65910->regmap, TPS65910_GPIO0 + offset,
     50						GPIO_SET_MASK);
     51}
     52
     53static int tps65910_gpio_output(struct gpio_chip *gc, unsigned offset,
     54				int value)
     55{
     56	struct tps65910_gpio *tps65910_gpio = gpiochip_get_data(gc);
     57	struct tps65910 *tps65910 = tps65910_gpio->tps65910;
     58
     59	/* Set the initial value */
     60	tps65910_gpio_set(gc, offset, value);
     61
     62	return regmap_set_bits(tps65910->regmap, TPS65910_GPIO0 + offset,
     63						GPIO_CFG_MASK);
     64}
     65
     66static int tps65910_gpio_input(struct gpio_chip *gc, unsigned offset)
     67{
     68	struct tps65910_gpio *tps65910_gpio = gpiochip_get_data(gc);
     69	struct tps65910 *tps65910 = tps65910_gpio->tps65910;
     70
     71	return regmap_clear_bits(tps65910->regmap, TPS65910_GPIO0 + offset,
     72						GPIO_CFG_MASK);
     73}
     74
     75#ifdef CONFIG_OF
     76static struct tps65910_board *tps65910_parse_dt_for_gpio(struct device *dev,
     77		struct tps65910 *tps65910, int chip_ngpio)
     78{
     79	struct tps65910_board *tps65910_board = tps65910->of_plat_data;
     80	unsigned int prop_array[TPS6591X_MAX_NUM_GPIO];
     81	int ngpio = min(chip_ngpio, TPS6591X_MAX_NUM_GPIO);
     82	int ret;
     83	int idx;
     84
     85	tps65910_board->gpio_base = -1;
     86	ret = of_property_read_u32_array(tps65910->dev->of_node,
     87			"ti,en-gpio-sleep", prop_array, ngpio);
     88	if (ret < 0) {
     89		dev_dbg(dev, "ti,en-gpio-sleep not specified\n");
     90		return tps65910_board;
     91	}
     92
     93	for (idx = 0; idx < ngpio; idx++)
     94		tps65910_board->en_gpio_sleep[idx] = (prop_array[idx] != 0);
     95
     96	return tps65910_board;
     97}
     98#else
     99static struct tps65910_board *tps65910_parse_dt_for_gpio(struct device *dev,
    100		struct tps65910 *tps65910, int chip_ngpio)
    101{
    102	return NULL;
    103}
    104#endif
    105
    106static int tps65910_gpio_probe(struct platform_device *pdev)
    107{
    108	struct tps65910 *tps65910 = dev_get_drvdata(pdev->dev.parent);
    109	struct tps65910_board *pdata = dev_get_platdata(tps65910->dev);
    110	struct tps65910_gpio *tps65910_gpio;
    111	int ret;
    112	int i;
    113
    114	device_set_node(&pdev->dev, dev_fwnode(pdev->dev.parent));
    115
    116	tps65910_gpio = devm_kzalloc(&pdev->dev,
    117				sizeof(*tps65910_gpio), GFP_KERNEL);
    118	if (!tps65910_gpio)
    119		return -ENOMEM;
    120
    121	tps65910_gpio->tps65910 = tps65910;
    122
    123	tps65910_gpio->gpio_chip.owner = THIS_MODULE;
    124	tps65910_gpio->gpio_chip.label = tps65910->i2c_client->name;
    125
    126	switch (tps65910_chip_id(tps65910)) {
    127	case TPS65910:
    128		tps65910_gpio->gpio_chip.ngpio = TPS65910_NUM_GPIO;
    129		break;
    130	case TPS65911:
    131		tps65910_gpio->gpio_chip.ngpio = TPS65911_NUM_GPIO;
    132		break;
    133	default:
    134		return -EINVAL;
    135	}
    136	tps65910_gpio->gpio_chip.can_sleep = true;
    137	tps65910_gpio->gpio_chip.direction_input = tps65910_gpio_input;
    138	tps65910_gpio->gpio_chip.direction_output = tps65910_gpio_output;
    139	tps65910_gpio->gpio_chip.set	= tps65910_gpio_set;
    140	tps65910_gpio->gpio_chip.get	= tps65910_gpio_get;
    141	tps65910_gpio->gpio_chip.parent = &pdev->dev;
    142
    143	if (pdata && pdata->gpio_base)
    144		tps65910_gpio->gpio_chip.base = pdata->gpio_base;
    145	else
    146		tps65910_gpio->gpio_chip.base = -1;
    147
    148	if (!pdata && tps65910->dev->of_node)
    149		pdata = tps65910_parse_dt_for_gpio(&pdev->dev, tps65910,
    150			tps65910_gpio->gpio_chip.ngpio);
    151
    152	if (!pdata)
    153		goto skip_init;
    154
    155	/* Configure sleep control for gpios if provided */
    156	for (i = 0; i < tps65910_gpio->gpio_chip.ngpio; ++i) {
    157		if (!pdata->en_gpio_sleep[i])
    158			continue;
    159
    160		ret = regmap_set_bits(tps65910->regmap,
    161			TPS65910_GPIO0 + i, GPIO_SLEEP_MASK);
    162		if (ret < 0)
    163			dev_warn(tps65910->dev,
    164				"GPIO Sleep setting failed with err %d\n", ret);
    165	}
    166
    167skip_init:
    168	return devm_gpiochip_add_data(&pdev->dev, &tps65910_gpio->gpio_chip,
    169				      tps65910_gpio);
    170}
    171
    172static struct platform_driver tps65910_gpio_driver = {
    173	.driver.name    = "tps65910-gpio",
    174	.probe		= tps65910_gpio_probe,
    175};
    176
    177static int __init tps65910_gpio_init(void)
    178{
    179	return platform_driver_register(&tps65910_gpio_driver);
    180}
    181subsys_initcall(tps65910_gpio_init);