[patch 23/32] greybus: bridged phy gpio driver

2016-09-16 Thread Greg KH
This driver implements the Greybus bridged phy gpio class protocol.

Signed-off-by: Greg Kroah-Hartman 
---
 drivers/greybus/gpio.c |  767 +
 1 file changed, 767 insertions(+)

--- /dev/null
+++ b/drivers/greybus/gpio.c
@@ -0,0 +1,767 @@
+/*
+ * GPIO Greybus driver.
+ *
+ * Copyright 2014 Google Inc.
+ * Copyright 2014 Linaro Ltd.
+ *
+ * Released under the GPLv2 only.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "greybus.h"
+#include "gbphy.h"
+
+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;
+   boolirq_type_pending;
+   boolmasked;
+   boolmasked_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_chipchip;
+   struct irq_chip irqc;
+   struct irq_chip *irqchip;
+   struct irq_domain   *irqdomain;
+   unsigned intirq_base;
+   irq_flow_handler_t  irq_handler;
+   unsigned intirq_default_type;
+   struct mutexirq_lock;
+};
+#define gpio_chip_to_gb_gpio_controller(chip) \
+   container_of(chip, struct gb_gpio_controller, chip)
+#define irq_data_to_gpio_chip(d) (d->domain->host_data)
+
+static int gb_gpio_line_count_operation(struct gb_gpio_controller *ggc)
+{
+   struct gb_gpio_line_count_response response;
+   int ret;
+
+   ret = gb_operation_sync(ggc->connection, GB_GPIO_TYPE_LINE_COUNT,
+   NULL, 0, , 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,
+, 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 = _dev->dev;
+   struct gb_gpio_deactivate_request request;
+   int ret;
+
+   request.which = which;
+   ret = gb_operation_sync(ggc->connection, GB_GPIO_TYPE_DEACTIVATE,
+, 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 = >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,
+   , sizeof(request),
+   , 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,
+   , sizeof(request), NULL, 0);
+   if (!ret)
+   ggc->lines[which].direction = 1;
+   return ret;
+}
+
+static int 

[patch 23/32] greybus: bridged phy gpio driver

2016-09-16 Thread Greg KH
This driver implements the Greybus bridged phy gpio class protocol.

Signed-off-by: Greg Kroah-Hartman 
---
 drivers/greybus/gpio.c |  767 +
 1 file changed, 767 insertions(+)

--- /dev/null
+++ b/drivers/greybus/gpio.c
@@ -0,0 +1,767 @@
+/*
+ * GPIO Greybus driver.
+ *
+ * Copyright 2014 Google Inc.
+ * Copyright 2014 Linaro Ltd.
+ *
+ * Released under the GPLv2 only.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "greybus.h"
+#include "gbphy.h"
+
+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;
+   boolirq_type_pending;
+   boolmasked;
+   boolmasked_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_chipchip;
+   struct irq_chip irqc;
+   struct irq_chip *irqchip;
+   struct irq_domain   *irqdomain;
+   unsigned intirq_base;
+   irq_flow_handler_t  irq_handler;
+   unsigned intirq_default_type;
+   struct mutexirq_lock;
+};
+#define gpio_chip_to_gb_gpio_controller(chip) \
+   container_of(chip, struct gb_gpio_controller, chip)
+#define irq_data_to_gpio_chip(d) (d->domain->host_data)
+
+static int gb_gpio_line_count_operation(struct gb_gpio_controller *ggc)
+{
+   struct gb_gpio_line_count_response response;
+   int ret;
+
+   ret = gb_operation_sync(ggc->connection, GB_GPIO_TYPE_LINE_COUNT,
+   NULL, 0, , 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,
+, 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 = _dev->dev;
+   struct gb_gpio_deactivate_request request;
+   int ret;
+
+   request.which = which;
+   ret = gb_operation_sync(ggc->connection, GB_GPIO_TYPE_DEACTIVATE,
+, 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 = >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,
+   , sizeof(request),
+   , 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,
+   , sizeof(request), NULL, 0);
+   if (!ret)
+   ggc->lines[which].direction = 1;
+   return ret;
+}
+
+static int gb_gpio_direction_out_operation(struct