forked from Qortal/Brooklyn
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
113 lines
2.9 KiB
113 lines
2.9 KiB
// SPDX-License-Identifier: GPL-2.0-only |
|
/* |
|
* Copyright Intel Corporation (C) 2014-2016. All Rights Reserved |
|
* |
|
* GPIO driver for Altera Arria10 MAX5 System Resource Chip |
|
* |
|
* Adapted from gpio-tps65910.c |
|
*/ |
|
|
|
#include <linux/gpio/driver.h> |
|
#include <linux/mfd/altera-a10sr.h> |
|
#include <linux/module.h> |
|
|
|
/** |
|
* struct altr_a10sr_gpio - Altera Max5 GPIO device private data structure |
|
* @gp: : instance of the gpio_chip |
|
* @regmap: the regmap from the parent device. |
|
*/ |
|
struct altr_a10sr_gpio { |
|
struct gpio_chip gp; |
|
struct regmap *regmap; |
|
}; |
|
|
|
static int altr_a10sr_gpio_get(struct gpio_chip *chip, unsigned int offset) |
|
{ |
|
struct altr_a10sr_gpio *gpio = gpiochip_get_data(chip); |
|
int ret, val; |
|
|
|
ret = regmap_read(gpio->regmap, ALTR_A10SR_PBDSW_REG, &val); |
|
if (ret < 0) |
|
return ret; |
|
|
|
return !!(val & BIT(offset - ALTR_A10SR_LED_VALID_SHIFT)); |
|
} |
|
|
|
static void altr_a10sr_gpio_set(struct gpio_chip *chip, unsigned int offset, |
|
int value) |
|
{ |
|
struct altr_a10sr_gpio *gpio = gpiochip_get_data(chip); |
|
|
|
regmap_update_bits(gpio->regmap, ALTR_A10SR_LED_REG, |
|
BIT(ALTR_A10SR_LED_VALID_SHIFT + offset), |
|
value ? BIT(ALTR_A10SR_LED_VALID_SHIFT + offset) |
|
: 0); |
|
} |
|
|
|
static int altr_a10sr_gpio_direction_input(struct gpio_chip *gc, |
|
unsigned int nr) |
|
{ |
|
if (nr < (ALTR_A10SR_IN_VALID_RANGE_LO - ALTR_A10SR_LED_VALID_SHIFT)) |
|
return -EINVAL; |
|
|
|
return 0; |
|
} |
|
|
|
static int altr_a10sr_gpio_direction_output(struct gpio_chip *gc, |
|
unsigned int nr, int value) |
|
{ |
|
if (nr > (ALTR_A10SR_OUT_VALID_RANGE_HI - ALTR_A10SR_LED_VALID_SHIFT)) |
|
return -EINVAL; |
|
|
|
altr_a10sr_gpio_set(gc, nr, value); |
|
return 0; |
|
} |
|
|
|
static const struct gpio_chip altr_a10sr_gc = { |
|
.label = "altr_a10sr_gpio", |
|
.owner = THIS_MODULE, |
|
.get = altr_a10sr_gpio_get, |
|
.set = altr_a10sr_gpio_set, |
|
.direction_input = altr_a10sr_gpio_direction_input, |
|
.direction_output = altr_a10sr_gpio_direction_output, |
|
.can_sleep = true, |
|
.ngpio = 12, |
|
.base = -1, |
|
}; |
|
|
|
static int altr_a10sr_gpio_probe(struct platform_device *pdev) |
|
{ |
|
struct altr_a10sr_gpio *gpio; |
|
struct altr_a10sr *a10sr = dev_get_drvdata(pdev->dev.parent); |
|
|
|
gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL); |
|
if (!gpio) |
|
return -ENOMEM; |
|
|
|
gpio->regmap = a10sr->regmap; |
|
|
|
gpio->gp = altr_a10sr_gc; |
|
gpio->gp.parent = pdev->dev.parent; |
|
gpio->gp.of_node = pdev->dev.of_node; |
|
|
|
return devm_gpiochip_add_data(&pdev->dev, &gpio->gp, gpio); |
|
} |
|
|
|
static const struct of_device_id altr_a10sr_gpio_of_match[] = { |
|
{ .compatible = "altr,a10sr-gpio" }, |
|
{ }, |
|
}; |
|
MODULE_DEVICE_TABLE(of, altr_a10sr_gpio_of_match); |
|
|
|
static struct platform_driver altr_a10sr_gpio_driver = { |
|
.probe = altr_a10sr_gpio_probe, |
|
.driver = { |
|
.name = "altr_a10sr_gpio", |
|
.of_match_table = of_match_ptr(altr_a10sr_gpio_of_match), |
|
}, |
|
}; |
|
module_platform_driver(altr_a10sr_gpio_driver); |
|
|
|
MODULE_LICENSE("GPL v2"); |
|
MODULE_AUTHOR("Thor Thayer <[email protected]>"); |
|
MODULE_DESCRIPTION("Altera Arria10 System Resource Chip GPIO");
|
|
|