Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1485039
| From | Greg KH <gregkh@linuxfoundation.org> |
|---|---|
| Newsgroups | linux.kernel |
| Subject | [patch 29/32] greybus: bridged phy usb driver |
| Date | 2016-09-16 16:30 +0200 |
| Message-ID | <si2jo-5SZ-19@gated-at.bofh.it> (permalink) |
| References | <shfsm-830-21@gated-at.bofh.it> <shV8d-14L-5@gated-at.bofh.it> |
| Organization | linux.* mail to news gateway |
This driver implements the Greybus bridged phy USB class protocol.
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/greybus/usb.c | 247 ++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 247 insertions(+)
--- /dev/null
+++ b/drivers/greybus/usb.c
@@ -0,0 +1,247 @@
+/*
+ * USB host driver for the Greybus "generic" USB module.
+ *
+ * Copyright 2014 Google Inc.
+ * Copyright 2014 Linaro Ltd.
+ *
+ * Released under the GPLv2 only.
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/usb.h>
+#include <linux/usb/hcd.h>
+
+#include "greybus.h"
+#include "gbphy.h"
+
+/* Greybus USB request types */
+#define GB_USB_TYPE_HCD_START 0x02
+#define GB_USB_TYPE_HCD_STOP 0x03
+#define GB_USB_TYPE_HUB_CONTROL 0x04
+
+struct gb_usb_hub_control_request {
+ __le16 typeReq;
+ __le16 wValue;
+ __le16 wIndex;
+ __le16 wLength;
+};
+
+struct gb_usb_hub_control_response {
+ u8 buf[0];
+};
+
+struct gb_usb_device {
+ struct gb_connection *connection;
+ struct gbphy_device *gbphy_dev;
+};
+
+static inline struct gb_usb_device *to_gb_usb_device(struct usb_hcd *hcd)
+{
+ return (struct gb_usb_device *)hcd->hcd_priv;
+}
+
+static inline struct usb_hcd *gb_usb_device_to_hcd(struct gb_usb_device *dev)
+{
+ return container_of((void *)dev, struct usb_hcd, hcd_priv);
+}
+
+static void hcd_stop(struct usb_hcd *hcd)
+{
+ struct gb_usb_device *dev = to_gb_usb_device(hcd);
+ int ret;
+
+ ret = gb_operation_sync(dev->connection, GB_USB_TYPE_HCD_STOP,
+ NULL, 0, NULL, 0);
+ if (ret)
+ dev_err(&dev->gbphy_dev->dev, "HCD stop failed '%d'\n", ret);
+}
+
+static int hcd_start(struct usb_hcd *hcd)
+{
+ struct usb_bus *bus = hcd_to_bus(hcd);
+ struct gb_usb_device *dev = to_gb_usb_device(hcd);
+ int ret;
+
+ ret = gb_operation_sync(dev->connection, GB_USB_TYPE_HCD_START,
+ NULL, 0, NULL, 0);
+ if (ret) {
+ dev_err(&dev->gbphy_dev->dev, "HCD start failed '%d'\n", ret);
+ return ret;
+ }
+
+ hcd->state = HC_STATE_RUNNING;
+ if (bus->root_hub)
+ usb_hcd_resume_root_hub(hcd);
+ return 0;
+}
+
+static int urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags)
+{
+ return -ENXIO;
+}
+
+static int urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
+{
+ return -ENXIO;
+}
+
+static int get_frame_number(struct usb_hcd *hcd)
+{
+ return 0;
+}
+
+static int hub_status_data(struct usb_hcd *hcd, char *buf)
+{
+ return 0;
+}
+
+static int hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex,
+ char *buf, u16 wLength)
+{
+ struct gb_usb_device *dev = to_gb_usb_device(hcd);
+ struct gb_operation *operation;
+ struct gb_usb_hub_control_request *request;
+ struct gb_usb_hub_control_response *response;
+ size_t response_size;
+ int ret;
+
+ /* FIXME: handle unspecified lengths */
+ response_size = sizeof(*response) + wLength;
+
+ operation = gb_operation_create(dev->connection,
+ GB_USB_TYPE_HUB_CONTROL,
+ sizeof(*request),
+ response_size,
+ GFP_KERNEL);
+ if (!operation)
+ return -ENOMEM;
+
+ request = operation->request->payload;
+ request->typeReq = cpu_to_le16(typeReq);
+ request->wValue = cpu_to_le16(wValue);
+ request->wIndex = cpu_to_le16(wIndex);
+ request->wLength = cpu_to_le16(wLength);
+
+ ret = gb_operation_request_send_sync(operation);
+ if (ret)
+ goto out;
+
+ if (wLength) {
+ /* Greybus core has verified response size */
+ response = operation->response->payload;
+ memcpy(buf, response->buf, wLength);
+ }
+out:
+ gb_operation_put(operation);
+
+ return ret;
+}
+
+static struct hc_driver usb_gb_hc_driver = {
+ .description = "greybus-hcd",
+ .product_desc = "Greybus USB Host Controller",
+ .hcd_priv_size = sizeof(struct gb_usb_device),
+
+ .flags = HCD_USB2,
+
+ .start = hcd_start,
+ .stop = hcd_stop,
+
+ .urb_enqueue = urb_enqueue,
+ .urb_dequeue = urb_dequeue,
+
+ .get_frame_number = get_frame_number,
+ .hub_status_data = hub_status_data,
+ .hub_control = hub_control,
+};
+
+static int gb_usb_probe(struct gbphy_device *gbphy_dev,
+ const struct gbphy_device_id *id)
+{
+ struct gb_connection *connection;
+ struct device *dev = &gbphy_dev->dev;
+ struct gb_usb_device *gb_usb_dev;
+ struct usb_hcd *hcd;
+ int retval;
+
+ hcd = usb_create_hcd(&usb_gb_hc_driver, dev, dev_name(dev));
+ if (!hcd)
+ return -ENOMEM;
+
+ connection = gb_connection_create(gbphy_dev->bundle,
+ le16_to_cpu(gbphy_dev->cport_desc->id),
+ NULL);
+ if (IS_ERR(connection)) {
+ retval = PTR_ERR(connection);
+ goto exit_usb_put;
+ }
+
+ gb_usb_dev = to_gb_usb_device(hcd);
+ gb_usb_dev->connection = connection;
+ gb_connection_set_data(connection, gb_usb_dev);
+ gb_usb_dev->gbphy_dev = gbphy_dev;
+ gb_gbphy_set_data(gbphy_dev, gb_usb_dev);
+
+ hcd->has_tt = 1;
+
+ retval = gb_connection_enable(connection);
+ if (retval)
+ goto exit_connection_destroy;
+
+ /*
+ * FIXME: The USB bridged-PHY protocol driver depends on changes to
+ * USB core which are not yet upstream.
+ *
+ * Disable for now.
+ */
+ if (1) {
+ dev_warn(dev, "USB protocol disabled\n");
+ retval = -EPROTONOSUPPORT;
+ goto exit_connection_disable;
+ }
+
+ retval = usb_add_hcd(hcd, 0, 0);
+ if (retval)
+ goto exit_connection_disable;
+
+ return 0;
+
+exit_connection_disable:
+ gb_connection_disable(connection);
+exit_connection_destroy:
+ gb_connection_destroy(connection);
+exit_usb_put:
+ usb_put_hcd(hcd);
+
+ return retval;
+}
+
+static void gb_usb_remove(struct gbphy_device *gbphy_dev)
+{
+ struct gb_usb_device *gb_usb_dev = gb_gbphy_get_data(gbphy_dev);
+ struct gb_connection *connection = gb_usb_dev->connection;
+ struct usb_hcd *hcd = gb_usb_device_to_hcd(gb_usb_dev);
+
+ usb_remove_hcd(hcd);
+ gb_connection_disable(connection);
+ gb_connection_destroy(connection);
+ usb_put_hcd(hcd);
+}
+
+static const struct gbphy_device_id gb_usb_id_table[] = {
+ { GBPHY_PROTOCOL(GREYBUS_PROTOCOL_USB) },
+ { },
+};
+MODULE_DEVICE_TABLE(gbphy, gb_usb_id_table);
+
+static struct gbphy_driver usb_driver = {
+ .name = "usb",
+ .probe = gb_usb_probe,
+ .remove = gb_usb_remove,
+ .id_table = gb_usb_id_table,
+};
+
+module_gbphy_driver(usb_driver);
+MODULE_LICENSE("GPL v2");
Back to linux.kernel | Previous | Next — Previous in thread | Next in thread | Find similar | Unroll thread
[patch 00/32] Greybus driver subsystem Greg KH <gregkh@linuxfoundation.org> - 2016-09-16 08:50 +0200 [patch 02/32] greybus: interface control logic Greg KH <gregkh@linuxfoundation.org> - 2016-09-16 08:50 +0200 [patch 08/32] greybus: bootrom driver Greg KH <gregkh@linuxfoundation.org> - 2016-09-16 15:30 +0200 [patch 05/32] greybus: trace.h Greg KH <gregkh@linuxfoundation.org> - 2016-09-16 15:30 +0200 [patch 04/32] greybus: host driver framework Greg KH <gregkh@linuxfoundation.org> - 2016-09-16 15:30 +0200 [patch 13/32] greybus: HID driver Greg KH <gregkh@linuxfoundation.org> - 2016-09-16 16:20 +0200 [patch 18/32] greybus: raw driver Greg KH <gregkh@linuxfoundation.org> - 2016-09-16 16:20 +0200 [patch 14/32] greybus: LED driver Greg KH <gregkh@linuxfoundation.org> - 2016-09-16 16:20 +0200 [patch 15/32] greybus: logging driver Greg KH <gregkh@linuxfoundation.org> - 2016-09-16 16:20 +0200 [patch 17/32] greybus: power supply driver Greg KH <gregkh@linuxfoundation.org> - 2016-09-16 16:20 +0200 [patch 16/32] greybus: loopback driver Greg KH <gregkh@linuxfoundation.org> - 2016-09-16 16:20 +0200 [patch 20/32] greybus: vibrator driver Greg KH <gregkh@linuxfoundation.org> - 2016-09-16 16:20 +0200 [patch 25/32] greybus: bridged phy pwm driver Greg KH <gregkh@linuxfoundation.org> - 2016-09-16 16:30 +0200 [patch 23/32] greybus: bridged phy gpio driver Greg KH <gregkh@linuxfoundation.org> - 2016-09-16 16:30 +0200 [patch 24/32] greybus: bridged phy i2c driver Greg KH <gregkh@linuxfoundation.org> - 2016-09-16 16:30 +0200 [patch 29/32] greybus: bridged phy usb driver Greg KH <gregkh@linuxfoundation.org> - 2016-09-16 16:30 +0200 [patch 32/32] greybus: add to the build Greg KH <gregkh@linuxfoundation.org> - 2016-09-16 16:30 +0200 [patch 26/32] greybus: bridged phy sdio driver Greg KH <gregkh@linuxfoundation.org> - 2016-09-16 16:30 +0200 [patch 28/32] greybus: bridged phy uart driver Greg KH <gregkh@linuxfoundation.org> - 2016-09-16 16:30 +0200 [patch 27/32] greybus: bridged phy spi driver Greg KH <gregkh@linuxfoundation.org> - 2016-09-16 16:30 +0200 [patch 22/32] greybus: bridged phy bus code Greg KH <gregkh@linuxfoundation.org> - 2016-09-16 16:30 +0200 [patch 31/32] greybus: documentation Greg KH <gregkh@linuxfoundation.org> - 2016-09-16 16:30 +0200
csiph-web