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-palmas.c (5388B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * TI Palma series PMIC's GPIO driver.
      4 *
      5 * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
      6 *
      7 * Author: Laxman Dewangan <ldewangan@nvidia.com>
      8 */
      9
     10#include <linux/gpio/driver.h>
     11#include <linux/kernel.h>
     12#include <linux/init.h>
     13#include <linux/mfd/palmas.h>
     14#include <linux/of.h>
     15#include <linux/of_device.h>
     16#include <linux/platform_device.h>
     17
     18struct palmas_gpio {
     19	struct gpio_chip gpio_chip;
     20	struct palmas *palmas;
     21};
     22
     23struct palmas_device_data {
     24	int ngpio;
     25};
     26
     27static int palmas_gpio_get(struct gpio_chip *gc, unsigned offset)
     28{
     29	struct palmas_gpio *pg = gpiochip_get_data(gc);
     30	struct palmas *palmas = pg->palmas;
     31	unsigned int val;
     32	int ret;
     33	unsigned int reg;
     34	int gpio16 = (offset/8);
     35
     36	offset %= 8;
     37	reg = (gpio16) ? PALMAS_GPIO_DATA_DIR2 : PALMAS_GPIO_DATA_DIR;
     38
     39	ret = palmas_read(palmas, PALMAS_GPIO_BASE, reg, &val);
     40	if (ret < 0) {
     41		dev_err(gc->parent, "Reg 0x%02x read failed, %d\n", reg, ret);
     42		return ret;
     43	}
     44
     45	if (val & BIT(offset))
     46		reg = (gpio16) ? PALMAS_GPIO_DATA_OUT2 : PALMAS_GPIO_DATA_OUT;
     47	else
     48		reg = (gpio16) ? PALMAS_GPIO_DATA_IN2 : PALMAS_GPIO_DATA_IN;
     49
     50	ret = palmas_read(palmas, PALMAS_GPIO_BASE, reg, &val);
     51	if (ret < 0) {
     52		dev_err(gc->parent, "Reg 0x%02x read failed, %d\n", reg, ret);
     53		return ret;
     54	}
     55	return !!(val & BIT(offset));
     56}
     57
     58static void palmas_gpio_set(struct gpio_chip *gc, unsigned offset,
     59			int value)
     60{
     61	struct palmas_gpio *pg = gpiochip_get_data(gc);
     62	struct palmas *palmas = pg->palmas;
     63	int ret;
     64	unsigned int reg;
     65	int gpio16 = (offset/8);
     66
     67	offset %= 8;
     68	if (gpio16)
     69		reg = (value) ?
     70			PALMAS_GPIO_SET_DATA_OUT2 : PALMAS_GPIO_CLEAR_DATA_OUT2;
     71	else
     72		reg = (value) ?
     73			PALMAS_GPIO_SET_DATA_OUT : PALMAS_GPIO_CLEAR_DATA_OUT;
     74
     75	ret = palmas_write(palmas, PALMAS_GPIO_BASE, reg, BIT(offset));
     76	if (ret < 0)
     77		dev_err(gc->parent, "Reg 0x%02x write failed, %d\n", reg, ret);
     78}
     79
     80static int palmas_gpio_output(struct gpio_chip *gc, unsigned offset,
     81				int value)
     82{
     83	struct palmas_gpio *pg = gpiochip_get_data(gc);
     84	struct palmas *palmas = pg->palmas;
     85	int ret;
     86	unsigned int reg;
     87	int gpio16 = (offset/8);
     88
     89	offset %= 8;
     90	reg = (gpio16) ? PALMAS_GPIO_DATA_DIR2 : PALMAS_GPIO_DATA_DIR;
     91
     92	/* Set the initial value */
     93	palmas_gpio_set(gc, offset, value);
     94
     95	ret = palmas_update_bits(palmas, PALMAS_GPIO_BASE, reg,
     96				BIT(offset), BIT(offset));
     97	if (ret < 0)
     98		dev_err(gc->parent, "Reg 0x%02x update failed, %d\n", reg,
     99			ret);
    100	return ret;
    101}
    102
    103static int palmas_gpio_input(struct gpio_chip *gc, unsigned offset)
    104{
    105	struct palmas_gpio *pg = gpiochip_get_data(gc);
    106	struct palmas *palmas = pg->palmas;
    107	int ret;
    108	unsigned int reg;
    109	int gpio16 = (offset/8);
    110
    111	offset %= 8;
    112	reg = (gpio16) ? PALMAS_GPIO_DATA_DIR2 : PALMAS_GPIO_DATA_DIR;
    113
    114	ret = palmas_update_bits(palmas, PALMAS_GPIO_BASE, reg, BIT(offset), 0);
    115	if (ret < 0)
    116		dev_err(gc->parent, "Reg 0x%02x update failed, %d\n", reg,
    117			ret);
    118	return ret;
    119}
    120
    121static int palmas_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
    122{
    123	struct palmas_gpio *pg = gpiochip_get_data(gc);
    124	struct palmas *palmas = pg->palmas;
    125
    126	return palmas_irq_get_virq(palmas, PALMAS_GPIO_0_IRQ + offset);
    127}
    128
    129static const struct palmas_device_data palmas_dev_data = {
    130	.ngpio = 8,
    131};
    132
    133static const struct palmas_device_data tps80036_dev_data = {
    134	.ngpio = 16,
    135};
    136
    137static const struct of_device_id of_palmas_gpio_match[] = {
    138	{ .compatible = "ti,palmas-gpio", .data = &palmas_dev_data,},
    139	{ .compatible = "ti,tps65913-gpio", .data = &palmas_dev_data,},
    140	{ .compatible = "ti,tps65914-gpio", .data = &palmas_dev_data,},
    141	{ .compatible = "ti,tps80036-gpio", .data = &tps80036_dev_data,},
    142	{ },
    143};
    144
    145static int palmas_gpio_probe(struct platform_device *pdev)
    146{
    147	struct palmas *palmas = dev_get_drvdata(pdev->dev.parent);
    148	struct palmas_platform_data *palmas_pdata;
    149	struct palmas_gpio *palmas_gpio;
    150	int ret;
    151	const struct palmas_device_data *dev_data;
    152
    153	dev_data = of_device_get_match_data(&pdev->dev);
    154	if (!dev_data)
    155		dev_data = &palmas_dev_data;
    156
    157	palmas_gpio = devm_kzalloc(&pdev->dev,
    158				sizeof(*palmas_gpio), GFP_KERNEL);
    159	if (!palmas_gpio)
    160		return -ENOMEM;
    161
    162	palmas_gpio->palmas = palmas;
    163	palmas_gpio->gpio_chip.owner = THIS_MODULE;
    164	palmas_gpio->gpio_chip.label = dev_name(&pdev->dev);
    165	palmas_gpio->gpio_chip.ngpio = dev_data->ngpio;
    166	palmas_gpio->gpio_chip.can_sleep = true;
    167	palmas_gpio->gpio_chip.direction_input = palmas_gpio_input;
    168	palmas_gpio->gpio_chip.direction_output = palmas_gpio_output;
    169	palmas_gpio->gpio_chip.to_irq = palmas_gpio_to_irq;
    170	palmas_gpio->gpio_chip.set	= palmas_gpio_set;
    171	palmas_gpio->gpio_chip.get	= palmas_gpio_get;
    172	palmas_gpio->gpio_chip.parent = &pdev->dev;
    173
    174	palmas_pdata = dev_get_platdata(palmas->dev);
    175	if (palmas_pdata && palmas_pdata->gpio_base)
    176		palmas_gpio->gpio_chip.base = palmas_pdata->gpio_base;
    177	else
    178		palmas_gpio->gpio_chip.base = -1;
    179
    180	ret = devm_gpiochip_add_data(&pdev->dev, &palmas_gpio->gpio_chip,
    181				     palmas_gpio);
    182	if (ret < 0) {
    183		dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret);
    184		return ret;
    185	}
    186
    187	platform_set_drvdata(pdev, palmas_gpio);
    188	return ret;
    189}
    190
    191static struct platform_driver palmas_gpio_driver = {
    192	.driver.name	= "palmas-gpio",
    193	.driver.of_match_table = of_palmas_gpio_match,
    194	.probe		= palmas_gpio_probe,
    195};
    196
    197static int __init palmas_gpio_init(void)
    198{
    199	return platform_driver_register(&palmas_gpio_driver);
    200}
    201subsys_initcall(palmas_gpio_init);