1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * Copyright Intel Corporation (C) 2014-2016. All Rights Reserved 4 * 5 * GPIO driver for Altera Arria10 MAX5 System Resource Chip 6 * 7 * Adapted from gpio-tps65910.c 8 */ 9 10#include <linux/gpio/driver.h> 11#include <linux/mfd/altera-a10sr.h> 12#include <linux/mod_devicetable.h> 13#include <linux/module.h> 14#include <linux/property.h> 15 16/** 17 * struct altr_a10sr_gpio - Altera Max5 GPIO device private data structure 18 * @gp: : instance of the gpio_chip 19 * @regmap: the regmap from the parent device. 20 */ 21struct altr_a10sr_gpio { 22 struct gpio_chip gp; 23 struct regmap *regmap; 24}; 25 26static int altr_a10sr_gpio_get(struct gpio_chip *chip, unsigned int offset) 27{ 28 struct altr_a10sr_gpio *gpio = gpiochip_get_data(chip); 29 int ret, val; 30 31 ret = regmap_read(gpio->regmap, ALTR_A10SR_PBDSW_REG, &val); 32 if (ret < 0) 33 return ret; 34 35 return !!(val & BIT(offset - ALTR_A10SR_LED_VALID_SHIFT)); 36} 37 38static void altr_a10sr_gpio_set(struct gpio_chip *chip, unsigned int offset, 39 int value) 40{ 41 struct altr_a10sr_gpio *gpio = gpiochip_get_data(chip); 42 43 regmap_update_bits(gpio->regmap, ALTR_A10SR_LED_REG, 44 BIT(ALTR_A10SR_LED_VALID_SHIFT + offset), 45 value ? BIT(ALTR_A10SR_LED_VALID_SHIFT + offset) 46 : 0); 47} 48 49static int altr_a10sr_gpio_direction_input(struct gpio_chip *gc, 50 unsigned int nr) 51{ 52 if (nr < (ALTR_A10SR_IN_VALID_RANGE_LO - ALTR_A10SR_LED_VALID_SHIFT)) 53 return -EINVAL; 54 55 return 0; 56} 57 58static int altr_a10sr_gpio_direction_output(struct gpio_chip *gc, 59 unsigned int nr, int value) 60{ 61 if (nr > (ALTR_A10SR_OUT_VALID_RANGE_HI - ALTR_A10SR_LED_VALID_SHIFT)) 62 return -EINVAL; 63 64 altr_a10sr_gpio_set(gc, nr, value); 65 return 0; 66} 67 68static const struct gpio_chip altr_a10sr_gc = { 69 .label = "altr_a10sr_gpio", 70 .owner = THIS_MODULE, 71 .get = altr_a10sr_gpio_get, 72 .set = altr_a10sr_gpio_set, 73 .direction_input = altr_a10sr_gpio_direction_input, 74 .direction_output = altr_a10sr_gpio_direction_output, 75 .can_sleep = true, 76 .ngpio = 12, 77 .base = -1, 78}; 79 80static int altr_a10sr_gpio_probe(struct platform_device *pdev) 81{ 82 struct altr_a10sr_gpio *gpio; 83 struct altr_a10sr *a10sr = dev_get_drvdata(pdev->dev.parent); 84 85 gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL); 86 if (!gpio) 87 return -ENOMEM; 88 89 gpio->regmap = a10sr->regmap; 90 91 gpio->gp = altr_a10sr_gc; 92 gpio->gp.parent = pdev->dev.parent; 93 gpio->gp.fwnode = dev_fwnode(&pdev->dev); 94 95 return devm_gpiochip_add_data(&pdev->dev, &gpio->gp, gpio); 96} 97 98static const struct of_device_id altr_a10sr_gpio_of_match[] = { 99 { .compatible = "altr,a10sr-gpio" }, 100 { }, 101}; 102MODULE_DEVICE_TABLE(of, altr_a10sr_gpio_of_match); 103 104static struct platform_driver altr_a10sr_gpio_driver = { 105 .probe = altr_a10sr_gpio_probe, 106 .driver = { 107 .name = "altr_a10sr_gpio", 108 .of_match_table = altr_a10sr_gpio_of_match, 109 }, 110}; 111module_platform_driver(altr_a10sr_gpio_driver); 112 113MODULE_LICENSE("GPL v2"); 114MODULE_AUTHOR("Thor Thayer <tthayer@opensource.altera.com>"); 115MODULE_DESCRIPTION("Altera Arria10 System Resource Chip GPIO"); 116