linux-stable/drivers/staging/greybus/gpio.c

635 lines
16 KiB
C
Raw Normal View History

// SPDX-License-Identifier: GPL-2.0
2014-08-12 04:00:16 +00:00
/*
* GPIO Greybus driver.
*
* Copyright 2014 Google Inc.
* Copyright 2014 Linaro Ltd.
2014-08-12 04:00:16 +00:00
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/irq.h>
#include <linux/irqdomain.h>
#include <linux/gpio/driver.h>
#include <linux/mutex.h>
#include <linux/greybus.h>
#include "gbphy.h"
2014-08-12 04:00:16 +00:00
struct gb_gpio_line {
/* The following has to be an array of line_max entries */
/* --> make them just a flags field */
u8 active: 1,
direction: 1, /* 0 = output, 1 = input */
value: 1; /* 0 = low, 1 = high */
u16 debounce_usec;
u8 irq_type;
bool irq_type_pending;
bool masked;
bool masked_pending;
};
struct gb_gpio_controller {
struct gbphy_device *gbphy_dev;
struct gb_connection *connection;
u8 line_max; /* max line number */
struct gb_gpio_line *lines;
struct gpio_chip chip;
struct irq_chip irqc;
struct mutex irq_lock;
};
static inline struct gb_gpio_controller *gpio_chip_to_gb_gpio_controller(struct gpio_chip *chip)
{
return container_of(chip, struct gb_gpio_controller, chip);
}
static struct gpio_chip *irq_data_to_gpio_chip(struct irq_data *d)
{
return d->domain->host_data;
}
static int gb_gpio_line_count_operation(struct gb_gpio_controller *ggc)
2014-08-12 04:00:16 +00:00
{
struct gb_gpio_line_count_response response;
int ret;
ret = gb_operation_sync(ggc->connection, GB_GPIO_TYPE_LINE_COUNT,
NULL, 0, &response, sizeof(response));
if (!ret)
ggc->line_max = response.count;
return ret;
}
static int gb_gpio_activate_operation(struct gb_gpio_controller *ggc, u8 which)
{
struct gb_gpio_activate_request request;
struct gbphy_device *gbphy_dev = ggc->gbphy_dev;
int ret;
ret = gbphy_runtime_get_sync(gbphy_dev);
if (ret)
return ret;
request.which = which;
ret = gb_operation_sync(ggc->connection, GB_GPIO_TYPE_ACTIVATE,
&request, sizeof(request), NULL, 0);
if (ret) {
gbphy_runtime_put_autosuspend(gbphy_dev);
return ret;
}
ggc->lines[which].active = true;
return 0;
}
static void gb_gpio_deactivate_operation(struct gb_gpio_controller *ggc,
u8 which)
{
struct gbphy_device *gbphy_dev = ggc->gbphy_dev;
struct device *dev = &gbphy_dev->dev;
struct gb_gpio_deactivate_request request;
int ret;
request.which = which;
ret = gb_operation_sync(ggc->connection, GB_GPIO_TYPE_DEACTIVATE,
&request, sizeof(request), NULL, 0);
if (ret) {
dev_err(dev, "failed to deactivate gpio %u\n", which);
goto out_pm_put;
}
ggc->lines[which].active = false;
out_pm_put:
gbphy_runtime_put_autosuspend(gbphy_dev);
}
static int gb_gpio_get_direction_operation(struct gb_gpio_controller *ggc,
u8 which)
{
struct device *dev = &ggc->gbphy_dev->dev;
struct gb_gpio_get_direction_request request;
struct gb_gpio_get_direction_response response;
int ret;
u8 direction;
request.which = which;
ret = gb_operation_sync(ggc->connection, GB_GPIO_TYPE_GET_DIRECTION,
&request, sizeof(request),
&response, sizeof(response));
if (ret)
return ret;
direction = response.direction;
if (direction && direction != 1) {
dev_warn(dev, "gpio %u direction was %u (should be 0 or 1)\n",
which, direction);
}
ggc->lines[which].direction = direction ? 1 : 0;
return 0;
}
static int gb_gpio_direction_in_operation(struct gb_gpio_controller *ggc,
u8 which)
{
struct gb_gpio_direction_in_request request;
int ret;
request.which = which;
ret = gb_operation_sync(ggc->connection, GB_GPIO_TYPE_DIRECTION_IN,
&request, sizeof(request), NULL, 0);
if (!ret)
ggc->lines[which].direction = 1;
return ret;
}
static int gb_gpio_direction_out_operation(struct gb_gpio_controller *ggc,
u8 which, bool value_high)
{
struct gb_gpio_direction_out_request request;
int ret;
request.which = which;
request.value = value_high ? 1 : 0;
ret = gb_operation_sync(ggc->connection, GB_GPIO_TYPE_DIRECTION_OUT,
&request, sizeof(request), NULL, 0);
if (!ret)
ggc->lines[which].direction = 0;
return ret;
}
static int gb_gpio_get_value_operation(struct gb_gpio_controller *ggc,
u8 which)
{
struct device *dev = &ggc->gbphy_dev->dev;
struct gb_gpio_get_value_request request;
struct gb_gpio_get_value_response response;
int ret;
u8 value;
request.which = which;
ret = gb_operation_sync(ggc->connection, GB_GPIO_TYPE_GET_VALUE,
&request, sizeof(request),
&response, sizeof(response));
if (ret) {
dev_err(dev, "failed to get value of gpio %u\n", which);
return ret;
}
value = response.value;
if (value && value != 1) {
dev_warn(dev, "gpio %u value was %u (should be 0 or 1)\n",
which, value);
}
ggc->lines[which].value = value ? 1 : 0;
return 0;
}
static void gb_gpio_set_value_operation(struct gb_gpio_controller *ggc,
u8 which, bool value_high)
{
struct device *dev = &ggc->gbphy_dev->dev;
struct gb_gpio_set_value_request request;
int ret;
if (ggc->lines[which].direction == 1) {
dev_warn(dev, "refusing to set value of input gpio %u\n",
which);
return;
}
request.which = which;
request.value = value_high ? 1 : 0;
ret = gb_operation_sync(ggc->connection, GB_GPIO_TYPE_SET_VALUE,
&request, sizeof(request), NULL, 0);
if (ret) {
dev_err(dev, "failed to set value of gpio %u\n", which);
return;
}
ggc->lines[which].value = request.value;
}
static int gb_gpio_set_debounce_operation(struct gb_gpio_controller *ggc,
u8 which, u16 debounce_usec)
{
struct gb_gpio_set_debounce_request request;
int ret;
request.which = which;
request.usec = cpu_to_le16(debounce_usec);
ret = gb_operation_sync(ggc->connection, GB_GPIO_TYPE_SET_DEBOUNCE,
&request, sizeof(request), NULL, 0);
if (!ret)
ggc->lines[which].debounce_usec = debounce_usec;
return ret;
}
static void _gb_gpio_irq_mask(struct gb_gpio_controller *ggc, u8 hwirq)
{
struct device *dev = &ggc->gbphy_dev->dev;
struct gb_gpio_irq_mask_request request;
int ret;
request.which = hwirq;
ret = gb_operation_sync(ggc->connection,
GB_GPIO_TYPE_IRQ_MASK,
&request, sizeof(request), NULL, 0);
if (ret)
dev_err(dev, "failed to mask irq: %d\n", ret);
}
static void _gb_gpio_irq_unmask(struct gb_gpio_controller *ggc, u8 hwirq)
{
struct device *dev = &ggc->gbphy_dev->dev;
struct gb_gpio_irq_unmask_request request;
int ret;
request.which = hwirq;
ret = gb_operation_sync(ggc->connection,
GB_GPIO_TYPE_IRQ_UNMASK,
&request, sizeof(request), NULL, 0);
if (ret)
dev_err(dev, "failed to unmask irq: %d\n", ret);
}
static void _gb_gpio_irq_set_type(struct gb_gpio_controller *ggc,
u8 hwirq, u8 type)
{
struct device *dev = &ggc->gbphy_dev->dev;
struct gb_gpio_irq_type_request request;
int ret;
request.which = hwirq;
request.type = type;
ret = gb_operation_sync(ggc->connection,
GB_GPIO_TYPE_IRQ_TYPE,
&request, sizeof(request), NULL, 0);
if (ret)
dev_err(dev, "failed to set irq type: %d\n", ret);
}
static void gb_gpio_irq_mask(struct irq_data *d)
{
struct gpio_chip *chip = irq_data_to_gpio_chip(d);
struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip);
struct gb_gpio_line *line = &ggc->lines[d->hwirq];
line->masked = true;
line->masked_pending = true;
}
static void gb_gpio_irq_unmask(struct irq_data *d)
{
struct gpio_chip *chip = irq_data_to_gpio_chip(d);
struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip);
struct gb_gpio_line *line = &ggc->lines[d->hwirq];
line->masked = false;
line->masked_pending = true;
}
static int gb_gpio_irq_set_type(struct irq_data *d, unsigned int type)
{
struct gpio_chip *chip = irq_data_to_gpio_chip(d);
struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip);
struct gb_gpio_line *line = &ggc->lines[d->hwirq];
struct device *dev = &ggc->gbphy_dev->dev;
u8 irq_type;
switch (type) {
case IRQ_TYPE_NONE:
irq_type = GB_GPIO_IRQ_TYPE_NONE;
break;
case IRQ_TYPE_EDGE_RISING:
irq_type = GB_GPIO_IRQ_TYPE_EDGE_RISING;
break;
case IRQ_TYPE_EDGE_FALLING:
irq_type = GB_GPIO_IRQ_TYPE_EDGE_FALLING;
break;
case IRQ_TYPE_EDGE_BOTH:
irq_type = GB_GPIO_IRQ_TYPE_EDGE_BOTH;
break;
case IRQ_TYPE_LEVEL_LOW:
irq_type = GB_GPIO_IRQ_TYPE_LEVEL_LOW;
break;
case IRQ_TYPE_LEVEL_HIGH:
irq_type = GB_GPIO_IRQ_TYPE_LEVEL_HIGH;
break;
default:
dev_err(dev, "unsupported irq type: %u\n", type);
return -EINVAL;
}
line->irq_type = irq_type;
line->irq_type_pending = true;
return 0;
}
static void gb_gpio_irq_bus_lock(struct irq_data *d)
{
struct gpio_chip *chip = irq_data_to_gpio_chip(d);
struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip);
mutex_lock(&ggc->irq_lock);
}
static void gb_gpio_irq_bus_sync_unlock(struct irq_data *d)
{
struct gpio_chip *chip = irq_data_to_gpio_chip(d);
struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip);
struct gb_gpio_line *line = &ggc->lines[d->hwirq];
if (line->irq_type_pending) {
_gb_gpio_irq_set_type(ggc, d->hwirq, line->irq_type);
line->irq_type_pending = false;
}
if (line->masked_pending) {
if (line->masked)
_gb_gpio_irq_mask(ggc, d->hwirq);
else
_gb_gpio_irq_unmask(ggc, d->hwirq);
line->masked_pending = false;
}
mutex_unlock(&ggc->irq_lock);
}
static int gb_gpio_request_handler(struct gb_operation *op)
{
struct gb_connection *connection = op->connection;
struct gb_gpio_controller *ggc = gb_connection_get_data(connection);
struct device *dev = &ggc->gbphy_dev->dev;
struct gb_message *request;
struct gb_gpio_irq_event_request *event;
u8 type = op->type;
int irq, ret;
if (type != GB_GPIO_TYPE_IRQ_EVENT) {
dev_err(dev, "unsupported unsolicited request: %u\n", type);
return -EINVAL;
}
request = op->request;
if (request->payload_size < sizeof(*event)) {
dev_err(dev, "short event received (%zu < %zu)\n",
request->payload_size, sizeof(*event));
return -EINVAL;
}
event = request->payload;
if (event->which > ggc->line_max) {
dev_err(dev, "invalid hw irq: %d\n", event->which);
return -EINVAL;
}
irq = irq_find_mapping(ggc->chip.irq.domain, event->which);
if (!irq) {
dev_err(dev, "failed to find IRQ\n");
return -EINVAL;
}
ret = generic_handle_irq_safe(irq);
if (ret)
dev_err(dev, "failed to invoke irq handler\n");
return ret;
}
static int gb_gpio_request(struct gpio_chip *chip, unsigned int offset)
{
struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip);
return gb_gpio_activate_operation(ggc, (u8)offset);
2014-08-12 04:00:16 +00:00
}
static void gb_gpio_free(struct gpio_chip *chip, unsigned int offset)
{
struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip);
gb_gpio_deactivate_operation(ggc, (u8)offset);
}
static int gb_gpio_get_direction(struct gpio_chip *chip, unsigned int offset)
{
struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip);
u8 which;
int ret;
which = (u8)offset;
ret = gb_gpio_get_direction_operation(ggc, which);
if (ret)
return ret;
return ggc->lines[which].direction ? 1 : 0;
}
static int gb_gpio_direction_input(struct gpio_chip *chip, unsigned int offset)
2014-08-12 04:00:16 +00:00
{
struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip);
return gb_gpio_direction_in_operation(ggc, (u8)offset);
2014-08-12 04:00:16 +00:00
}
static int gb_gpio_direction_output(struct gpio_chip *chip, unsigned int offset,
int value)
2014-08-12 04:00:16 +00:00
{
struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip);
return gb_gpio_direction_out_operation(ggc, (u8)offset, !!value);
2014-08-12 04:00:16 +00:00
}
static int gb_gpio_get(struct gpio_chip *chip, unsigned int offset)
{
struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip);
u8 which;
int ret;
which = (u8)offset;
ret = gb_gpio_get_value_operation(ggc, which);
if (ret)
return ret;
return ggc->lines[which].value;
}
static void gb_gpio_set(struct gpio_chip *chip, unsigned int offset, int value)
2014-08-12 04:00:16 +00:00
{
struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip);
gb_gpio_set_value_operation(ggc, (u8)offset, !!value);
2014-08-12 04:00:16 +00:00
}
staging/iio driver patches for 4.11-rc1 Here is the big staging and iio driver patchsets for 4.11-rc1. We almost broke even this time around, with only a few thousand lines added overall, as we removed the old and obsolete i4l code, but added some new drivers for the RPi platform, as well as adding some new IIO drivers. All of these have been in linux-next for a while with no reported issues. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> -----BEGIN PGP SIGNATURE----- iG0EABECAC0WIQT0tgzFv3jCIUoxPcsxR9QN2y37KQUCWK2j/w8cZ3JlZ0Brcm9h aC5jb20ACgkQMUfUDdst+ymZ1ACdFR4o6xYrWEizmao4a/u+lUZE1aIAnRmcGcIc J+leO1n9bE5iadQvKYUW =sKVA -----END PGP SIGNATURE----- Merge tag 'staging-4.11-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging Pull staging/iio driver updates from Greg KH: "Here is the big staging and iio driver patchsets for 4.11-rc1. We almost broke even this time around, with only a few thousand lines added overall, as we removed the old and obsolete i4l code, but added some new drivers for the RPi platform, as well as adding some new IIO drivers. All of these have been in linux-next for a while with no reported issues" * tag 'staging-4.11-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging: (669 commits) Staging: vc04_services: Fix the "space prohibited" code style errors Staging: vc04_services: Fix the "wrong indent" code style errors staging: octeon: Use net_device_stats from struct net_device Staging: rtl8192u: ieee80211: ieee80211.h - style fix Staging: rtl8192u: ieee80211: ieee80211_tx.c - style fix Staging: rtl8192u: ieee80211: rtl819x_BAProc.c - style fix Staging: rtl8192u: ieee80211: ieee80211_module.c - style fix Staging: rtl8192u: ieee80211: rtl819x_TSProc.c - style fix Staging: rtl8192u: r8192U.h - style fix Staging: rtl8192u: r8192U_core.c - style fix Staging: rtl8192u: r819xU_cmdpkt.c - style fix staging: rtl8192u: blank lines aren't necessary before a close brace '}' staging: rtl8192u: Adding space after enum and struct definition staging: rtl8192u: Adding space after struct definition Staging: ks7010: Add required and preferred spaces around operators Staging: ks7010: ks*: Remove redundant blank lines Staging: ks7010: ks*: Add missing blank lines after declarations staging: visorbus, replace init_timer with setup_timer staging: vt6656: rxtx.c Removed multiple dereferencing staging: vt6656: Alignment match open parenthesis ...
2017-02-22 20:14:01 +00:00
static int gb_gpio_set_config(struct gpio_chip *chip, unsigned int offset,
unsigned long config)
2014-08-12 04:00:16 +00:00
{
struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip);
u32 debounce;
if (pinconf_to_config_param(config) != PIN_CONFIG_INPUT_DEBOUNCE)
return -ENOTSUPP;
debounce = pinconf_to_config_argument(config);
if (debounce > U16_MAX)
return -EINVAL;
return gb_gpio_set_debounce_operation(ggc, (u8)offset, (u16)debounce);
}
static int gb_gpio_controller_setup(struct gb_gpio_controller *ggc)
{
int ret;
/* Now find out how many lines there are */
ret = gb_gpio_line_count_operation(ggc);
if (ret)
return ret;
ggc->lines = kcalloc(ggc->line_max + 1, sizeof(*ggc->lines),
GFP_KERNEL);
if (!ggc->lines)
return -ENOMEM;
return ret;
}
static int gb_gpio_probe(struct gbphy_device *gbphy_dev,
const struct gbphy_device_id *id)
{
struct gb_connection *connection;
struct gb_gpio_controller *ggc;
2014-08-12 04:00:16 +00:00
struct gpio_chip *gpio;
struct gpio_irq_chip *girq;
struct irq_chip *irqc;
int ret;
2014-08-12 04:00:16 +00:00
ggc = kzalloc(sizeof(*ggc), GFP_KERNEL);
if (!ggc)
2014-08-12 04:00:16 +00:00
return -ENOMEM;
connection =
gb_connection_create(gbphy_dev->bundle,
le16_to_cpu(gbphy_dev->cport_desc->id),
gb_gpio_request_handler);
if (IS_ERR(connection)) {
ret = PTR_ERR(connection);
goto exit_ggc_free;
}
ggc->connection = connection;
gb_connection_set_data(connection, ggc);
ggc->gbphy_dev = gbphy_dev;
gb_gbphy_set_data(gbphy_dev, ggc);
ret = gb_connection_enable_tx(connection);
if (ret)
goto exit_connection_destroy;
ret = gb_gpio_controller_setup(ggc);
if (ret)
goto exit_connection_disable;
2014-08-12 04:00:16 +00:00
irqc = &ggc->irqc;
irqc->irq_mask = gb_gpio_irq_mask;
irqc->irq_unmask = gb_gpio_irq_unmask;
irqc->irq_set_type = gb_gpio_irq_set_type;
irqc->irq_bus_lock = gb_gpio_irq_bus_lock;
irqc->irq_bus_sync_unlock = gb_gpio_irq_bus_sync_unlock;
irqc->name = "greybus_gpio";
mutex_init(&ggc->irq_lock);
gpio = &ggc->chip;
2014-08-12 04:00:16 +00:00
gpio->label = "greybus_gpio";
gpio->parent = &gbphy_dev->dev;
gpio->owner = THIS_MODULE;
gpio->request = gb_gpio_request;
gpio->free = gb_gpio_free;
gpio->get_direction = gb_gpio_get_direction;
gpio->direction_input = gb_gpio_direction_input;
gpio->direction_output = gb_gpio_direction_output;
gpio->get = gb_gpio_get;
gpio->set = gb_gpio_set;
gpio->set_config = gb_gpio_set_config;
gpio->base = -1; /* Allocate base dynamically */
gpio->ngpio = ggc->line_max + 1;
gpio->can_sleep = true;
2014-08-12 04:00:16 +00:00
girq = &gpio->irq;
girq->chip = irqc;
/* The event comes from the outside so no parent handler */
girq->parent_handler = NULL;
girq->num_parents = 0;
girq->parents = NULL;
girq->default_type = IRQ_TYPE_NONE;
girq->handler = handle_level_irq;
ret = gb_connection_enable(connection);
if (ret)
goto exit_line_free;
ret = gpiochip_add(gpio);
if (ret) {
dev_err(&gbphy_dev->dev, "failed to add gpio chip: %d\n", ret);
goto exit_line_free;
}
gbphy_runtime_put_autosuspend(gbphy_dev);
2014-08-12 04:00:16 +00:00
return 0;
exit_line_free:
kfree(ggc->lines);
exit_connection_disable:
gb_connection_disable(connection);
exit_connection_destroy:
gb_connection_destroy(connection);
exit_ggc_free:
kfree(ggc);
return ret;
2014-08-12 04:00:16 +00:00
}
static void gb_gpio_remove(struct gbphy_device *gbphy_dev)
2014-08-12 04:00:16 +00:00
{
struct gb_gpio_controller *ggc = gb_gbphy_get_data(gbphy_dev);
struct gb_connection *connection = ggc->connection;
int ret;
ret = gbphy_runtime_get_sync(gbphy_dev);
if (ret)
gbphy_runtime_get_noresume(gbphy_dev);
2014-08-12 04:00:16 +00:00
gb_connection_disable_rx(connection);
gpiochip_remove(&ggc->chip);
gb_connection_disable(connection);
gb_connection_destroy(connection);
kfree(ggc->lines);
kfree(ggc);
2014-08-12 04:00:16 +00:00
}
static const struct gbphy_device_id gb_gpio_id_table[] = {
{ GBPHY_PROTOCOL(GREYBUS_PROTOCOL_GPIO) },
{ },
};
MODULE_DEVICE_TABLE(gbphy, gb_gpio_id_table);
static struct gbphy_driver gpio_driver = {
.name = "gpio",
.probe = gb_gpio_probe,
.remove = gb_gpio_remove,
.id_table = gb_gpio_id_table,
};
module_gbphy_driver(gpio_driver);
MODULE_LICENSE("GPL v2");