blob: b73973d92013b65e3ecbd12e8b5619e50980d6d6 [file] [log] [blame]
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) 2019 - 2021 DisplayLink (UK) Ltd.
*/
#ifndef __MAUSB_HCD_H__
#define __MAUSB_HCD_H__
#include <linux/slab.h>
#include <linux/usb.h>
#include <linux/usb/hcd.h>
#include "hpal.h"
#define DRIVER_NAME "mausb_host"
#define DEVICE_NAME "mausb_host_hcd"
#define NUMBER_OF_PORTS 15
/* Response Timeout in ms (MA-USB v1.0a, Table 43) */
#define RESPONSE_TIMEOUT_MS 5000
/* MA-USB v1.0a, Table 12 */
enum mausb_device_type {
USBDEVICE = 0,
USB20HUB = 1,
USB30HUB = 2,
};
/* MA-USB v1.0a, Table 15 */
enum mausb_device_speed {
LOW_SPEED = 0,
FULL_SPEED = 1,
HIGH_SPEED = 2,
SUPER_SPEED = 3,
SUPER_SPEED_PLUS = 4,
};
struct mausb_hcd {
spinlock_t lock; /* Protect HCD during URB processing */
u8 connected_ports;
struct rb_root mausb_urbs;
struct hub_ctx *hcd_ss_ctx;
struct hub_ctx *hcd_hs_ctx;
struct notifier_block power_state_listener;
};
struct mausb_dev {
u32 port_status;
struct rb_root usb_devices;
u8 dev_speed;
void *ma_dev;
};
struct hub_ctx {
struct usb_hcd *hcd;
struct mausb_dev ma_devs[NUMBER_OF_PORTS];
};
int mausb_host_driver_init(void);
void mausb_host_driver_deinit(void);
void mausb_port_has_changed(const enum mausb_device_type device_type,
const enum mausb_device_speed device_speed,
void *ma_dev);
void mausb_hcd_disconnect(const u8 port_number,
const enum mausb_device_type device_type,
const enum mausb_device_speed device_speed);
#define PORT_C_MASK \
((USB_PORT_STAT_C_CONNECTION \
| USB_PORT_STAT_C_ENABLE \
| USB_PORT_STAT_C_SUSPEND \
| USB_PORT_STAT_C_OVERCURRENT \
| USB_PORT_STAT_C_RESET) << 16)
/* USB 2.0 specification chapter 11.24.2.7.1 table 11-21 page 427 */
#define MAUSB_PORT_20_STATUS_CONNECT 0x0001
#define MAUSB_PORT_20_STATUS_ENABLE 0x0002
#define MAUSB_PORT_20_STATUS_SUSPEND 0x0004
#define MAUSB_PORT_20_STATUS_OVER_CURRENT 0x0008
#define MAUSB_PORT_20_STATUS_RESET 0x0010
#define MAUSB_PORT_20_STATUS_POWER 0x0100
#define MAUSB_PORT_20_STATUS_LOW_SPEED 0x0200
#define MAUSB_PORT_20_STATUS_HIGH_SPEED 0x0400
/* USB 3.2 specification chapter 10.16.2.6.1 table 10-13 page 440 */
#define MAUSB_PORT_30_STATUS_CONNECT 0x0001
#define MAUSB_PORT_30_STATUS_ENABLE 0x0002
#define MAUSB_PORT_30_STATUS_OVER_CURRENT 0x0008
#define MAUSB_PORT_30_STATUS_RESET 0x0010
#define MAUSB_PORT_30_LINK_STATE_U0 0x0000
#define MAUSB_PORT_30_LINK_STATE_U1 0x0020
#define MAUSB_PORT_30_LINK_STATE_U2 0x0040
#define MAUSB_PORT_30_LINK_STATE_U3 0x0060
#define MAUSB_PORT_30_LINK_STATE_DISABLED 0x0080
#define MAUSB_PORT_30_LINK_STATE_RX_DETECT 0x00A0
#define MAUSB_PORT_30_LINK_STATE_INACTIVE 0x00C0
#define MAUSB_PORT_30_LINK_STATE_POLLING 0x00E0
#define MAUSB_PORT_30_LINK_STATE_RECOVERY 0x0100
#define MAUSB_PORT_30_LINK_STATE_HOT_RESET 0x0120
#define MAUSB_PORT_30_LINK_STATE_COMPLIANCE_MODE 0x0140
#define MAUSB_PORT_30_LINK_STATE_LOOPBACK 0x0160
#define MAUSB_PORT_30_STATUS_POWER 0x0200
#define MAUSB_PORT_30_STATUS_SUPER_SPEED 0x0400
#define MAUSB_PORT_30_CLEAR_LINK_STATE 0xFE1F
/* USB 3.2 specification chapter 10.16.2.6.2 table 10-14 page 443 */
#define MAUSB_CHANGE_PORT_30_STATUS_CONNECT 0x010000
#define MAUSB_CHANGE_PORT_30_STATUS_OVER_CURRENT 0x080000
#define MAUSB_CHANGE_PORT_30_STATUS_RESET 0x100000
#define MAUSB_CHANGE_PORT_30_BH_STATUS_RESET 0x200000
#define MAUSB_CHANGE_PORT_30_LINK_STATE 0x400000
#define MAUSB_CHANGE_PORT_30_CONFIG_ERROR 0x800000
/* USB 3.2 specification chapter 10.16.2.4 table 10-10 page 438 */
#define MAUSB_HUB_30_POWER_GOOD 0x00
#define MAUSB_HUB_30_LOCAL_POWER_SOURCE_LOST 0x01
#define MAUSB_HUB_30_OVER_CURRENT 0x02
/* USB 3.2 specification chapter 10.16.2.4 table 10-11 page 438 */
#define MAUSB_CHANGE_HUB_30_LOCAL_POWER_SOURCE_LOST 0x10000
#define MAUSB_CHANGE_HUB_30_OVER_CURRENT 0x20000
#define DEV_HANDLE_NOT_ASSIGNED -1
struct mausb_usb_device_ctx {
s32 dev_handle;
bool addressed;
void *dev_addr;
struct rb_node rb_node;
};
struct mausb_endpoint_ctx {
u16 ep_handle;
u16 dev_handle;
void *ma_dev;
struct mausb_usb_device_ctx *usb_device_ctx;
};
struct mausb_urb_ctx {
struct urb *urb;
struct mausb_data_iter iterator;
struct rb_node rb_node;
struct work_struct work;
};
int mausb_hcd_create_and_add(struct device *dev);
void mausb_hcd_urb_complete(struct urb *urb, u32 actual_length, int status);
void mausb_clear_hcd_madev(u8 port_number);
#endif /* __MAUSB_HCD_H__ */