+/* SPDX-License-Identifier: GPL-2.0+ */
/*
* (C) Copyright 2001
* Denis Peter, MPL AG Switzerland
*
* Adapted for U-Boot driver model
* (C) Copyright 2015 Google, Inc
- *
- * SPDX-License-Identifier: GPL-2.0+
* Note: Part of this code has been derived from linux
*
*/
*/
struct usb_device {
int devnum; /* Device number on USB bus */
- int speed; /* full/low/high */
+ enum usb_device_speed speed; /* full/low/high */
char mf[32]; /* manufacturer */
char prod[32]; /* product */
char serial[32]; /* serial number */
int act_len; /* transferred bytes */
int maxchild; /* Number of ports if hub */
int portnr; /* Port number, 1=first */
-#ifndef CONFIG_DM_USB
+#if !CONFIG_IS_ENABLED(DM_USB)
/* parent hub, or NULL if this is the root hub */
struct usb_device *parent;
struct usb_device *children[USB_MAXCHILDREN];
#endif
/* slot_id - for xHCI enabled devices */
unsigned int slot_id;
-#ifdef CONFIG_DM_USB
+#if CONFIG_IS_ENABLED(DM_USB)
struct udevice *dev; /* Pointer to associated device */
struct udevice *controller_dev; /* Pointer to associated controller */
#endif
*/
enum usb_init_type {
USB_INIT_HOST,
- USB_INIT_DEVICE
+ USB_INIT_DEVICE,
+ USB_INIT_UNKNOWN,
};
/**********************************************************************
int usb_lowlevel_init(int index, enum usb_init_type init, void **controller);
int usb_lowlevel_stop(int index);
-#if defined(CONFIG_USB_MUSB_HOST) || defined(CONFIG_DM_USB)
+#if defined(CONFIG_USB_MUSB_HOST) || CONFIG_IS_ENABLED(DM_USB)
int usb_reset_root_port(struct usb_device *dev);
#else
#define usb_reset_root_port(dev)
int submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
int transfer_len, struct devrequest *setup);
int submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
- int transfer_len, int interval);
+ int transfer_len, int interval, bool nonblock);
#if defined CONFIG_USB_EHCI_HCD || defined CONFIG_USB_MUSB_HOST \
- || defined(CONFIG_DM_USB)
+ || CONFIG_IS_ENABLED(DM_USB)
struct int_queue *create_int_queue(struct usb_device *dev, unsigned long pipe,
int queuesize, int elementsize, void *buffer, int interval);
int destroy_int_queue(struct usb_device *dev, struct int_queue *queue);
#ifdef CONFIG_USB_KEYBOARD
+/*
+ * USB Keyboard reports are 8 bytes in boot protocol.
+ * Appendix B of HID Device Class Definition 1.11
+ */
+#define USB_KBD_BOOT_REPORT_SIZE 8
+
int drv_usb_kbd_init(void);
int usb_kbd_deregister(int force);
void *data, unsigned short size, int timeout);
int usb_bulk_msg(struct usb_device *dev, unsigned int pipe,
void *data, int len, int *actual_length, int timeout);
-int usb_submit_int_msg(struct usb_device *dev, unsigned long pipe,
- void *buffer, int transfer_len, int interval);
+int usb_int_msg(struct usb_device *dev, unsigned long pipe,
+ void *buffer, int transfer_len, int interval, bool nonblock);
+int usb_lock_async(struct usb_device *dev, int lock);
int usb_disable_asynch(int disable);
int usb_maxpacket(struct usb_device *dev, unsigned long pipe);
int usb_get_configuration_no(struct usb_device *dev, int cfgno,
unsigned short wHubChange;
} __attribute__ ((packed));
+/*
+ * Hub Device descriptor
+ * USB Hub class device protocols
+ */
+#define USB_HUB_PR_FS 0 /* Full speed hub */
+#define USB_HUB_PR_HS_NO_TT 0 /* Hi-speed hub without TT */
+#define USB_HUB_PR_HS_SINGLE_TT 1 /* Hi-speed hub with single TT */
+#define USB_HUB_PR_HS_MULTI_TT 2 /* Hi-speed hub with multiple TT */
+#define USB_HUB_PR_SS 3 /* Super speed hub */
+
+/* Transaction Translator Think Times, in bits */
+#define HUB_TTTT_8_BITS 0x00
+#define HUB_TTTT_16_BITS 0x20
+#define HUB_TTTT_24_BITS 0x40
+#define HUB_TTTT_32_BITS 0x60
/* Hub descriptor */
struct usb_hub_descriptor {
unsigned short wHubCharacteristics;
unsigned char bPwrOn2PwrGood;
unsigned char bHubContrCurrent;
- unsigned char DeviceRemovable[(USB_MAXCHILDREN+1+7)/8];
- unsigned char PortPowerCtrlMask[(USB_MAXCHILDREN+1+7)/8];
- /* DeviceRemovable and PortPwrCtrlMask want to be variable-length
- bitmaps that hold max 255 entries. (bit0 is ignored) */
+ /* 2.0 and 3.0 hubs differ here */
+ union {
+ struct {
+ /* add 1 bit for hub status change; round to bytes */
+ __u8 DeviceRemovable[(USB_MAXCHILDREN + 1 + 7) / 8];
+ __u8 PortPowerCtrlMask[(USB_MAXCHILDREN + 1 + 7) / 8];
+ } __attribute__ ((packed)) hs;
+
+ struct {
+ __u8 bHubHdrDecLat;
+ __le16 wHubDelay;
+ __le16 DeviceRemovable;
+ } __attribute__ ((packed)) ss;
+ } u;
} __attribute__ ((packed));
ulong connect_timeout; /* Device connection timeout in ms */
ulong query_delay; /* Device query delay in ms */
int overcurrent_count[USB_MAXCHILDREN]; /* Over-current counter */
+ int hub_depth; /* USB 3.0 hub depth */
+ struct usb_tt tt; /* Transaction Translator */
};
-#ifdef CONFIG_DM_USB
+#if CONFIG_IS_ENABLED(DM_USB)
/**
- * struct usb_platdata - Platform data about a USB controller
+ * struct usb_plat - Platform data about a USB controller
*
- * Given a USB controller (UCLASS_USB) dev this is dev_get_platdata(dev)
+ * Given a USB controller (UCLASS_USB) dev this is dev_get_plat(dev)
*/
-struct usb_platdata {
+struct usb_plat {
enum usb_init_type init_type;
};
/**
- * struct usb_dev_platdata - Platform data about a USB device
+ * struct usb_dev_plat - Platform data about a USB device
*
- * Given a USB device dev this structure is dev_get_parent_platdata(dev).
+ * Given a USB device dev this structure is dev_get_parent_plat(dev).
* This is used by sandbox to provide emulation data also.
*
* @id: ID used to match this device
* @strings: List of descriptor strings (for sandbox emulation purposes)
* @desc_list: List of descriptors (for sandbox emulation purposes)
*/
-struct usb_dev_platdata {
+struct usb_dev_plat {
struct usb_device_id id;
int devnum;
/*
};
/**
+ * struct usb_emul_plat - platform data about the USB emulator
+ *
+ * Given a USB emulator (UCLASS_USB_EMUL) 'dev', this is
+ * dev_get_uclass_plat(dev).
+ *
+ * @port1: USB emulator device port number on the parent hub
+ */
+struct usb_emul_plat {
+ int port1; /* Port number (numbered from 1) */
+};
+
+/**
* struct dm_usb_ops - USB controller operations
*
* This defines the operations supoorted on a USB controller. Common
*/
int (*interrupt)(struct udevice *bus, struct usb_device *udev,
unsigned long pipe, void *buffer, int length,
- int interval);
+ int interval, bool nonblock);
/**
* create_int_queue() - Create and queue interrupt packets
* reset_root_port() - Reset usb root port
*/
int (*reset_root_port)(struct udevice *bus, struct usb_device *udev);
+
+ /**
+ * update_hub_device() - Update HCD's internal representation of hub
+ *
+ * After a hub descriptor is fetched, notify HCD so that its internal
+ * representation of this hub can be updated (xHCI)
+ */
+ int (*update_hub_device)(struct udevice *bus, struct usb_device *udev);
+
+ /**
+ * get_max_xfer_size() - Get HCD's maximum transfer bytes
+ *
+ * The HCD may have limitation on the maximum bytes to be transferred
+ * in a USB transfer. USB class driver needs to be aware of this.
+ */
+ int (*get_max_xfer_size)(struct udevice *bus, size_t *size);
+
+ /**
+ * lock_async() - Keep async schedule after a transfer
+ *
+ * It may be desired to keep the asynchronous schedule running even
+ * after a transfer finishes, usually when doing multiple transfers
+ * back-to-back. This callback allows signalling the USB controller
+ * driver to do just that.
+ */
+ int (*lock_async)(struct udevice *udev, int lock);
};
#define usb_get_ops(dev) ((struct dm_usb_ops *)(dev)->driver->ops)
* @do_read: true to read the device descriptor before an address is set
* (should be false for XHCI buses, true otherwise)
* @parent: Parent device (either UCLASS_USB or UCLASS_USB_HUB)
- * @return 0 if OK, -ve on error */
+ * Return: 0 if OK, -ve on error */
int usb_setup_device(struct usb_device *dev, bool do_read,
struct usb_device *parent);
/**
+ * usb_hub_is_root_hub() - Test whether a hub device is root hub or not
+ *
+ * @hub: USB hub device to test
+ * @return: true if the hub device is root hub, false otherwise.
+ */
+bool usb_hub_is_root_hub(struct udevice *hub);
+
+/**
* usb_hub_scan() - Scan a hub and find its devices
*
* @hub: Hub device to scan
* @port: Hub port number (numbered from 1)
* @speed: USB speed to use for this device
* @devp: Returns pointer to device if all is well
- * @return 0 if OK, -ve on error
+ * Return: 0 if OK, -ve on error
*/
int usb_scan_device(struct udevice *parent, int port,
enum usb_device_speed speed, struct udevice **devp);
* will be a device with uclass UCLASS_USB.
*
* @dev: Device to check
- * @return The bus, or NULL if not found (this indicates a critical error in
+ * Return: The bus, or NULL if not found (this indicates a critical error in
* the USB stack
*/
struct udevice *usb_get_bus(struct udevice *dev);
int usb_setup_ehci_gadget(struct ehci_ctrl **ctlrp);
/**
+ * usb_remove_ehci_gadget() - Remove a gadget USB device
+ *
+ * TODO(sjg@chromium.org): Tidy this up when USB gadgets can use driver model
+ *
+ * This provides a way to tell a controller to remove a USB device
+ */
+int usb_remove_ehci_gadget(struct ehci_ctrl **ctlrp);
+
+/**
* usb_stor_reset() - Prepare to scan USB storage devices
*
* Empty the list of USB storage devices in preparation for scanning them.
*/
void usb_stor_reset(void);
-#else /* !CONFIG_DM_USB */
+#else /* !CONFIG_IS_ENABLED(DM_USB) */
struct usb_device *usb_get_dev_index(int index);
int usb_hub_probe(struct usb_device *dev, int ifnum);
void usb_hub_reset(void);
-/**
- * legacy_hub_port_reset() - reset a port given its usb_device pointer
- *
- * Reset a hub port and see if a device is present on that port, providing
- * sufficient time for it to show itself. The port status is returned.
- *
- * With driver model this moves to hub_port_reset() and is passed a struct
- * udevice.
- *
- * @dev: USB device to reset
- * @port: Port number to reset (note ports are numbered from 0 here)
- * @portstat: Returns port status
- */
-int legacy_hub_port_reset(struct usb_device *dev, int port,
- unsigned short *portstat);
-
-int hub_port_reset(struct udevice *dev, int port, unsigned short *portstat);
-
/*
* usb_find_usb2_hub_address_port() - Get hub address and port for TT setting
*
* @devp: returns a pointer of a new device structure. With driver model this
* is a device pointer, but with legacy USB this pointer is
* driver-specific.
- * @return 0 if OK, -ENOSPC if we have found out of room for new devices
+ * Return: 0 if OK, -ENOSPC if we have found out of room for new devices
*/
int usb_alloc_new_device(struct udevice *controller, struct usb_device **devp);
int usb_alloc_device(struct usb_device *dev);
/**
+ * usb_update_hub_device() - Update HCD's internal representation of hub
+ *
+ * After a hub descriptor is fetched, notify HCD so that its internal
+ * representation of this hub can be updated.
+ *
+ * @dev: Hub device
+ * Return: 0 if OK, -ve on error
+ */
+int usb_update_hub_device(struct usb_device *dev);
+
+/**
+ * usb_get_max_xfer_size() - Get HCD's maximum transfer bytes
+ *
+ * The HCD may have limitation on the maximum bytes to be transferred
+ * in a USB transfer. USB class driver needs to be aware of this.
+ *
+ * @dev: USB device
+ * @size: maximum transfer bytes
+ * Return: 0 if OK, -ve on error
+ */
+int usb_get_max_xfer_size(struct usb_device *dev, size_t *size);
+
+/**
* usb_emul_setup_device() - Set up a new USB device emulation
*
* This is normally called when a new emulation device is bound. It tells
* the USB emulation uclass about the features of the emulator.
*
* @dev: Emulation device
- * @maxpacketsize: Maximum packet size (e.g. PACKET_SIZE_64)
* @strings: List of USB string descriptors, terminated by a NULL
* entry
* @desc_list: List of points or USB descriptors, terminated by NULL.
* The first entry must be struct usb_device_descriptor,
* and others follow on after that.
- * @return 0 if OK, -ve on error
+ * Return: 0 if OK, -ENOSYS if not implemented, other -ve on error
*/
-int usb_emul_setup_device(struct udevice *dev, int maxpacketsize,
- struct usb_string *strings, void **desc_list);
+int usb_emul_setup_device(struct udevice *dev, struct usb_string *strings,
+ void **desc_list);
/**
* usb_emul_control() - Send a control packet to an emulator
* @emul: Emulator device
* @udev: USB device (which the emulator is causing to appear)
* See struct dm_usb_ops for details on other parameters
- * @return 0 if OK, -ve on error
+ * Return: 0 if OK, -ve on error
*/
int usb_emul_control(struct udevice *emul, struct usb_device *udev,
unsigned long pipe, void *buffer, int length,
* @emul: Emulator device
* @udev: USB device (which the emulator is causing to appear)
* See struct dm_usb_ops for details on other parameters
- * @return 0 if OK, -ve on error
+ * Return: 0 if OK, -ve on error
*/
int usb_emul_bulk(struct udevice *emul, struct usb_device *udev,
unsigned long pipe, void *buffer, int length);
* @emul: Emulator device
* @udev: USB device (which the emulator is causing to appear)
* See struct dm_usb_ops for details on other parameters
- * @return 0 if OK, -ve on error
+ * Return: 0 if OK, -ve on error
*/
int usb_emul_int(struct udevice *emul, struct usb_device *udev,
- unsigned long pipe, void *buffer, int length, int interval);
+ unsigned long pipe, void *buffer, int length, int interval,
+ bool nonblock);
/**
* usb_emul_find() - Find an emulator for a particular device
*
- * Check @pipe to find a device number on bus @bus and return it.
+ * Check @pipe and @port1 to find a device number on bus @bus and return it.
*
* @bus: USB bus (controller)
* @pipe: Describes pipe being used, and includes the device number
+ * @port1: Describes port number on the parent hub
* @emulp: Returns pointer to emulator, or NULL if not found
- * @return 0 if found, -ve on error
+ * Return: 0 if found, -ve on error
*/
-int usb_emul_find(struct udevice *bus, ulong pipe, struct udevice **emulp);
+int usb_emul_find(struct udevice *bus, ulong pipe, int port1,
+ struct udevice **emulp);
/**
* usb_emul_find_for_dev() - Find an emulator for a particular device
*
- * @bus: USB bus (controller)
* @dev: USB device to check
* @emulp: Returns pointer to emulator, or NULL if not found
- * @return 0 if found, -ve on error
+ * Return: 0 if found, -ve on error
*/
int usb_emul_find_for_dev(struct udevice *dev, struct udevice **emulp);
/**
- * usb_emul_reset() - Reset all emulators ready for use
+ * usb_emul_find_descriptor() - Find a USB descriptor of a particular device
*
- * Clear out any address information in the emulators and make then ready for
- * a new USB scan
+ * @ptr: a pointer to a list of USB descriptor pointers
+ * @type: type of USB descriptor to find
+ * @index: if @type is USB_DT_CONFIG, this is the configuration value
+ * Return: a pointer to the USB descriptor found, NULL if not found
*/
-void usb_emul_reset(struct udevice *dev);
+struct usb_generic_descriptor **usb_emul_find_descriptor(
+ struct usb_generic_descriptor **ptr, int type, int index);
/**
* usb_show_tree() - show the USB device tree