1135446Strhodes// SPDX-License-Identifier: GPL-2.0-only 2193149Sdougb/* 3135446Strhodes * TI Palma series PMIC's GPIO driver. 4135446Strhodes * 5193149Sdougb * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. 6135446Strhodes * 7135446Strhodes * Author: Laxman Dewangan <ldewangan@nvidia.com> 8135446Strhodes */ 9135446Strhodes 10135446Strhodes#include <linux/gpio/driver.h> 11135446Strhodes#include <linux/kernel.h> 12135446Strhodes#include <linux/init.h> 13135446Strhodes#include <linux/mfd/palmas.h> 14135446Strhodes#include <linux/of.h> 15135446Strhodes#include <linux/platform_device.h> 16135446Strhodes 17135446Strhodesstruct palmas_gpio { 18193149Sdougb struct gpio_chip gpio_chip; 19135446Strhodes struct palmas *palmas; 20135446Strhodes}; 21135446Strhodes 22135446Strhodesstruct palmas_device_data { 23170222Sdougb int ngpio; 24135446Strhodes}; 25135446Strhodes 26135446Strhodesstatic int palmas_gpio_get(struct gpio_chip *gc, unsigned offset) 27135446Strhodes{ 28135446Strhodes struct palmas_gpio *pg = gpiochip_get_data(gc); 29135446Strhodes struct palmas *palmas = pg->palmas; 30193149Sdougb unsigned int val; 31170222Sdougb int ret; 32170222Sdougb unsigned int reg; 33170222Sdougb int gpio16 = (offset/8); 34135446Strhodes 35135446Strhodes offset %= 8; 36135446Strhodes reg = (gpio16) ? PALMAS_GPIO_DATA_DIR2 : PALMAS_GPIO_DATA_DIR; 37135446Strhodes 38135446Strhodes ret = palmas_read(palmas, PALMAS_GPIO_BASE, reg, &val); 39135446Strhodes if (ret < 0) { 40135446Strhodes dev_err(gc->parent, "Reg 0x%02x read failed, %d\n", reg, ret); 41135446Strhodes return ret; 42135446Strhodes } 43135446Strhodes 44135446Strhodes if (val & BIT(offset)) 45170222Sdougb reg = (gpio16) ? PALMAS_GPIO_DATA_OUT2 : PALMAS_GPIO_DATA_OUT; 46170222Sdougb else 47135446Strhodes reg = (gpio16) ? PALMAS_GPIO_DATA_IN2 : PALMAS_GPIO_DATA_IN; 48135446Strhodes 49135446Strhodes ret = palmas_read(palmas, PALMAS_GPIO_BASE, reg, &val); 50135446Strhodes if (ret < 0) { 51135446Strhodes dev_err(gc->parent, "Reg 0x%02x read failed, %d\n", reg, ret); 52135446Strhodes return ret; 53135446Strhodes } 54135446Strhodes return !!(val & BIT(offset)); 55135446Strhodes} 56135446Strhodes 57135446Strhodesstatic void palmas_gpio_set(struct gpio_chip *gc, unsigned offset, 58135446Strhodes int value) 59135446Strhodes{ 60135446Strhodes struct palmas_gpio *pg = gpiochip_get_data(gc); 61135446Strhodes struct palmas *palmas = pg->palmas; 62135446Strhodes int ret; 63135446Strhodes unsigned int reg; 64135446Strhodes int gpio16 = (offset/8); 65135446Strhodes 66135446Strhodes offset %= 8; 67135446Strhodes if (gpio16) 68135446Strhodes reg = (value) ? 69170222Sdougb PALMAS_GPIO_SET_DATA_OUT2 : PALMAS_GPIO_CLEAR_DATA_OUT2; 70135446Strhodes else 71135446Strhodes reg = (value) ? 72170222Sdougb PALMAS_GPIO_SET_DATA_OUT : PALMAS_GPIO_CLEAR_DATA_OUT; 73170222Sdougb 74170222Sdougb ret = palmas_write(palmas, PALMAS_GPIO_BASE, reg, BIT(offset)); 75170222Sdougb if (ret < 0) 76170222Sdougb dev_err(gc->parent, "Reg 0x%02x write failed, %d\n", reg, ret); 77135446Strhodes} 78135446Strhodes 79135446Strhodesstatic int palmas_gpio_output(struct gpio_chip *gc, unsigned offset, 80135446Strhodes int value) 81135446Strhodes{ 82135446Strhodes struct palmas_gpio *pg = gpiochip_get_data(gc); 83135446Strhodes struct palmas *palmas = pg->palmas; 84135446Strhodes int ret; 85135446Strhodes unsigned int reg; 86135446Strhodes int gpio16 = (offset/8); 87135446Strhodes 88135446Strhodes offset %= 8; 89135446Strhodes reg = (gpio16) ? PALMAS_GPIO_DATA_DIR2 : PALMAS_GPIO_DATA_DIR; 90135446Strhodes 91135446Strhodes /* Set the initial value */ 92135446Strhodes palmas_gpio_set(gc, offset, value); 93135446Strhodes 94135446Strhodes ret = palmas_update_bits(palmas, PALMAS_GPIO_BASE, reg, 95135446Strhodes BIT(offset), BIT(offset)); 96135446Strhodes if (ret < 0) 97135446Strhodes dev_err(gc->parent, "Reg 0x%02x update failed, %d\n", reg, 98170222Sdougb ret); 99135446Strhodes return ret; 100170222Sdougb} 101170222Sdougb 102135446Strhodesstatic int palmas_gpio_input(struct gpio_chip *gc, unsigned offset) 103170222Sdougb{ 104170222Sdougb struct palmas_gpio *pg = gpiochip_get_data(gc); 105170222Sdougb struct palmas *palmas = pg->palmas; 106170222Sdougb int ret; 107170222Sdougb unsigned int reg; 108170222Sdougb int gpio16 = (offset/8); 109170222Sdougb 110170222Sdougb offset %= 8; 111170222Sdougb reg = (gpio16) ? PALMAS_GPIO_DATA_DIR2 : PALMAS_GPIO_DATA_DIR; 112170222Sdougb 113170222Sdougb ret = palmas_update_bits(palmas, PALMAS_GPIO_BASE, reg, BIT(offset), 0); 114170222Sdougb if (ret < 0) 115170222Sdougb dev_err(gc->parent, "Reg 0x%02x update failed, %d\n", reg, 116170222Sdougb ret); 117170222Sdougb return ret; 118170222Sdougb} 119170222Sdougb 120170222Sdougbstatic int palmas_gpio_to_irq(struct gpio_chip *gc, unsigned offset) 121170222Sdougb{ 122170222Sdougb struct palmas_gpio *pg = gpiochip_get_data(gc); 123170222Sdougb struct palmas *palmas = pg->palmas; 124170222Sdougb 125170222Sdougb return palmas_irq_get_virq(palmas, PALMAS_GPIO_0_IRQ + offset); 126170222Sdougb} 127170222Sdougb 128170222Sdougbstatic const struct palmas_device_data palmas_dev_data = { 129170222Sdougb .ngpio = 8, 130170222Sdougb}; 131170222Sdougb 132170222Sdougbstatic const struct palmas_device_data tps80036_dev_data = { 133170222Sdougb .ngpio = 16, 134170222Sdougb}; 135170222Sdougb 136170222Sdougbstatic const struct of_device_id of_palmas_gpio_match[] = { 137170222Sdougb { .compatible = "ti,palmas-gpio", .data = &palmas_dev_data,}, 138170222Sdougb { .compatible = "ti,tps65913-gpio", .data = &palmas_dev_data,}, 139170222Sdougb { .compatible = "ti,tps65914-gpio", .data = &palmas_dev_data,}, 140170222Sdougb { .compatible = "ti,tps80036-gpio", .data = &tps80036_dev_data,}, 141135446Strhodes { }, 142135446Strhodes}; 143135446Strhodes 144135446Strhodesstatic int palmas_gpio_probe(struct platform_device *pdev) 145170222Sdougb{ 146135446Strhodes struct palmas *palmas = dev_get_drvdata(pdev->dev.parent); 147135446Strhodes struct palmas_platform_data *palmas_pdata; 148135446Strhodes struct palmas_gpio *palmas_gpio; 149135446Strhodes int ret; 150135446Strhodes const struct palmas_device_data *dev_data; 151135446Strhodes 152135446Strhodes dev_data = of_device_get_match_data(&pdev->dev); 153135446Strhodes if (!dev_data) 154170222Sdougb dev_data = &palmas_dev_data; 155170222Sdougb 156170222Sdougb palmas_gpio = devm_kzalloc(&pdev->dev, 157170222Sdougb sizeof(*palmas_gpio), GFP_KERNEL); 158170222Sdougb if (!palmas_gpio) 159170222Sdougb return -ENOMEM; 160170222Sdougb 161170222Sdougb palmas_gpio->palmas = palmas; 162170222Sdougb palmas_gpio->gpio_chip.owner = THIS_MODULE; 163170222Sdougb palmas_gpio->gpio_chip.label = dev_name(&pdev->dev); 164170222Sdougb palmas_gpio->gpio_chip.ngpio = dev_data->ngpio; 165135446Strhodes palmas_gpio->gpio_chip.can_sleep = true; 166135446Strhodes palmas_gpio->gpio_chip.direction_input = palmas_gpio_input; 167135446Strhodes palmas_gpio->gpio_chip.direction_output = palmas_gpio_output; 168135446Strhodes palmas_gpio->gpio_chip.to_irq = palmas_gpio_to_irq; 169135446Strhodes palmas_gpio->gpio_chip.set = palmas_gpio_set; 170135446Strhodes palmas_gpio->gpio_chip.get = palmas_gpio_get; 171135446Strhodes palmas_gpio->gpio_chip.parent = &pdev->dev; 172135446Strhodes 173135446Strhodes palmas_pdata = dev_get_platdata(palmas->dev); 174135446Strhodes if (palmas_pdata && palmas_pdata->gpio_base) 175135446Strhodes palmas_gpio->gpio_chip.base = palmas_pdata->gpio_base; 176170222Sdougb else 177135446Strhodes palmas_gpio->gpio_chip.base = -1; 178135446Strhodes 179135446Strhodes ret = devm_gpiochip_add_data(&pdev->dev, &palmas_gpio->gpio_chip, 180135446Strhodes palmas_gpio); 181135446Strhodes if (ret < 0) { 182135446Strhodes dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret); 183135446Strhodes return ret; 184135446Strhodes } 185135446Strhodes 186135446Strhodes return ret; 187135446Strhodes} 188170222Sdougb 189170222Sdougbstatic struct platform_driver palmas_gpio_driver = { 190135446Strhodes .driver.name = "palmas-gpio", 191135446Strhodes .driver.of_match_table = of_palmas_gpio_match, 192135446Strhodes .probe = palmas_gpio_probe, 193135446Strhodes}; 194135446Strhodes 195135446Strhodesstatic int __init palmas_gpio_init(void) 196135446Strhodes{ 197135446Strhodes return platform_driver_register(&palmas_gpio_driver); 198170222Sdougb} 199135446Strhodessubsys_initcall(palmas_gpio_init); 200135446Strhodes