root/drivers/staging/greybus/usb.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. to_gb_usb_device
  2. gb_usb_device_to_hcd
  3. hcd_stop
  4. hcd_start
  5. urb_enqueue
  6. urb_dequeue
  7. get_frame_number
  8. hub_status_data
  9. hub_control
  10. gb_usb_probe
  11. gb_usb_remove

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * USB host driver for the Greybus "generic" USB module.
   4  *
   5  * Copyright 2014 Google Inc.
   6  * Copyright 2014 Linaro Ltd.
   7  */
   8 #include <linux/kernel.h>
   9 #include <linux/module.h>
  10 #include <linux/slab.h>
  11 #include <linux/usb.h>
  12 #include <linux/usb/hcd.h>
  13 #include <linux/greybus.h>
  14 
  15 #include "gbphy.h"
  16 
  17 /* Greybus USB request types */
  18 #define GB_USB_TYPE_HCD_START           0x02
  19 #define GB_USB_TYPE_HCD_STOP            0x03
  20 #define GB_USB_TYPE_HUB_CONTROL         0x04
  21 
  22 struct gb_usb_hub_control_request {
  23         __le16 typeReq;
  24         __le16 wValue;
  25         __le16 wIndex;
  26         __le16 wLength;
  27 };
  28 
  29 struct gb_usb_hub_control_response {
  30         u8 buf[0];
  31 };
  32 
  33 struct gb_usb_device {
  34         struct gb_connection *connection;
  35         struct gbphy_device *gbphy_dev;
  36 };
  37 
  38 static inline struct gb_usb_device *to_gb_usb_device(struct usb_hcd *hcd)
  39 {
  40         return (struct gb_usb_device *)hcd->hcd_priv;
  41 }
  42 
  43 static inline struct usb_hcd *gb_usb_device_to_hcd(struct gb_usb_device *dev)
  44 {
  45         return container_of((void *)dev, struct usb_hcd, hcd_priv);
  46 }
  47 
  48 static void hcd_stop(struct usb_hcd *hcd)
  49 {
  50         struct gb_usb_device *dev = to_gb_usb_device(hcd);
  51         int ret;
  52 
  53         ret = gb_operation_sync(dev->connection, GB_USB_TYPE_HCD_STOP,
  54                                 NULL, 0, NULL, 0);
  55         if (ret)
  56                 dev_err(&dev->gbphy_dev->dev, "HCD stop failed '%d'\n", ret);
  57 }
  58 
  59 static int hcd_start(struct usb_hcd *hcd)
  60 {
  61         struct usb_bus *bus = hcd_to_bus(hcd);
  62         struct gb_usb_device *dev = to_gb_usb_device(hcd);
  63         int ret;
  64 
  65         ret = gb_operation_sync(dev->connection, GB_USB_TYPE_HCD_START,
  66                                 NULL, 0, NULL, 0);
  67         if (ret) {
  68                 dev_err(&dev->gbphy_dev->dev, "HCD start failed '%d'\n", ret);
  69                 return ret;
  70         }
  71 
  72         hcd->state = HC_STATE_RUNNING;
  73         if (bus->root_hub)
  74                 usb_hcd_resume_root_hub(hcd);
  75         return 0;
  76 }
  77 
  78 static int urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags)
  79 {
  80         return -ENXIO;
  81 }
  82 
  83 static int urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
  84 {
  85         return -ENXIO;
  86 }
  87 
  88 static int get_frame_number(struct usb_hcd *hcd)
  89 {
  90         return 0;
  91 }
  92 
  93 static int hub_status_data(struct usb_hcd *hcd, char *buf)
  94 {
  95         return 0;
  96 }
  97 
  98 static int hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex,
  99                        char *buf, u16 wLength)
 100 {
 101         struct gb_usb_device *dev = to_gb_usb_device(hcd);
 102         struct gb_operation *operation;
 103         struct gb_usb_hub_control_request *request;
 104         struct gb_usb_hub_control_response *response;
 105         size_t response_size;
 106         int ret;
 107 
 108         /* FIXME: handle unspecified lengths */
 109         response_size = sizeof(*response) + wLength;
 110 
 111         operation = gb_operation_create(dev->connection,
 112                                         GB_USB_TYPE_HUB_CONTROL,
 113                                         sizeof(*request),
 114                                         response_size,
 115                                         GFP_KERNEL);
 116         if (!operation)
 117                 return -ENOMEM;
 118 
 119         request = operation->request->payload;
 120         request->typeReq = cpu_to_le16(typeReq);
 121         request->wValue = cpu_to_le16(wValue);
 122         request->wIndex = cpu_to_le16(wIndex);
 123         request->wLength = cpu_to_le16(wLength);
 124 
 125         ret = gb_operation_request_send_sync(operation);
 126         if (ret)
 127                 goto out;
 128 
 129         if (wLength) {
 130                 /* Greybus core has verified response size */
 131                 response = operation->response->payload;
 132                 memcpy(buf, response->buf, wLength);
 133         }
 134 out:
 135         gb_operation_put(operation);
 136 
 137         return ret;
 138 }
 139 
 140 static const struct hc_driver usb_gb_hc_driver = {
 141         .description = "greybus-hcd",
 142         .product_desc = "Greybus USB Host Controller",
 143         .hcd_priv_size = sizeof(struct gb_usb_device),
 144 
 145         .flags = HCD_USB2,
 146 
 147         .start = hcd_start,
 148         .stop = hcd_stop,
 149 
 150         .urb_enqueue = urb_enqueue,
 151         .urb_dequeue = urb_dequeue,
 152 
 153         .get_frame_number = get_frame_number,
 154         .hub_status_data = hub_status_data,
 155         .hub_control = hub_control,
 156 };
 157 
 158 static int gb_usb_probe(struct gbphy_device *gbphy_dev,
 159                         const struct gbphy_device_id *id)
 160 {
 161         struct gb_connection *connection;
 162         struct device *dev = &gbphy_dev->dev;
 163         struct gb_usb_device *gb_usb_dev;
 164         struct usb_hcd *hcd;
 165         int retval;
 166 
 167         hcd = usb_create_hcd(&usb_gb_hc_driver, dev, dev_name(dev));
 168         if (!hcd)
 169                 return -ENOMEM;
 170 
 171         connection = gb_connection_create(gbphy_dev->bundle,
 172                                           le16_to_cpu(gbphy_dev->cport_desc->id),
 173                                           NULL);
 174         if (IS_ERR(connection)) {
 175                 retval = PTR_ERR(connection);
 176                 goto exit_usb_put;
 177         }
 178 
 179         gb_usb_dev = to_gb_usb_device(hcd);
 180         gb_usb_dev->connection = connection;
 181         gb_connection_set_data(connection, gb_usb_dev);
 182         gb_usb_dev->gbphy_dev = gbphy_dev;
 183         gb_gbphy_set_data(gbphy_dev, gb_usb_dev);
 184 
 185         hcd->has_tt = 1;
 186 
 187         retval = gb_connection_enable(connection);
 188         if (retval)
 189                 goto exit_connection_destroy;
 190 
 191         /*
 192          * FIXME: The USB bridged-PHY protocol driver depends on changes to
 193          *        USB core which are not yet upstream.
 194          *
 195          *        Disable for now.
 196          */
 197         if (1) {
 198                 dev_warn(dev, "USB protocol disabled\n");
 199                 retval = -EPROTONOSUPPORT;
 200                 goto exit_connection_disable;
 201         }
 202 
 203         retval = usb_add_hcd(hcd, 0, 0);
 204         if (retval)
 205                 goto exit_connection_disable;
 206 
 207         return 0;
 208 
 209 exit_connection_disable:
 210         gb_connection_disable(connection);
 211 exit_connection_destroy:
 212         gb_connection_destroy(connection);
 213 exit_usb_put:
 214         usb_put_hcd(hcd);
 215 
 216         return retval;
 217 }
 218 
 219 static void gb_usb_remove(struct gbphy_device *gbphy_dev)
 220 {
 221         struct gb_usb_device *gb_usb_dev = gb_gbphy_get_data(gbphy_dev);
 222         struct gb_connection *connection = gb_usb_dev->connection;
 223         struct usb_hcd *hcd = gb_usb_device_to_hcd(gb_usb_dev);
 224 
 225         usb_remove_hcd(hcd);
 226         gb_connection_disable(connection);
 227         gb_connection_destroy(connection);
 228         usb_put_hcd(hcd);
 229 }
 230 
 231 static const struct gbphy_device_id gb_usb_id_table[] = {
 232         { GBPHY_PROTOCOL(GREYBUS_PROTOCOL_USB) },
 233         { },
 234 };
 235 MODULE_DEVICE_TABLE(gbphy, gb_usb_id_table);
 236 
 237 static struct gbphy_driver usb_driver = {
 238         .name           = "usb",
 239         .probe          = gb_usb_probe,
 240         .remove         = gb_usb_remove,
 241         .id_table       = gb_usb_id_table,
 242 };
 243 
 244 module_gbphy_driver(usb_driver);
 245 MODULE_LICENSE("GPL v2");

/* [<][>][^][v][top][bottom][index][help] */