162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 262306a36Sopenharmony_ci/** 362306a36Sopenharmony_ci * xhci-dbgcap.h - xHCI debug capability support 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2017 Intel Corporation 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Author: Lu Baolu <baolu.lu@linux.intel.com> 862306a36Sopenharmony_ci */ 962306a36Sopenharmony_ci#ifndef __LINUX_XHCI_DBGCAP_H 1062306a36Sopenharmony_ci#define __LINUX_XHCI_DBGCAP_H 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#include <linux/tty.h> 1362306a36Sopenharmony_ci#include <linux/kfifo.h> 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_cistruct dbc_regs { 1662306a36Sopenharmony_ci __le32 capability; 1762306a36Sopenharmony_ci __le32 doorbell; 1862306a36Sopenharmony_ci __le32 ersts; /* Event Ring Segment Table Size*/ 1962306a36Sopenharmony_ci __le32 __reserved_0; /* 0c~0f reserved bits */ 2062306a36Sopenharmony_ci __le64 erstba; /* Event Ring Segment Table Base Address */ 2162306a36Sopenharmony_ci __le64 erdp; /* Event Ring Dequeue Pointer */ 2262306a36Sopenharmony_ci __le32 control; 2362306a36Sopenharmony_ci __le32 status; 2462306a36Sopenharmony_ci __le32 portsc; /* Port status and control */ 2562306a36Sopenharmony_ci __le32 __reserved_1; /* 2b~28 reserved bits */ 2662306a36Sopenharmony_ci __le64 dccp; /* Debug Capability Context Pointer */ 2762306a36Sopenharmony_ci __le32 devinfo1; /* Device Descriptor Info Register 1 */ 2862306a36Sopenharmony_ci __le32 devinfo2; /* Device Descriptor Info Register 2 */ 2962306a36Sopenharmony_ci}; 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_cistruct dbc_info_context { 3262306a36Sopenharmony_ci __le64 string0; 3362306a36Sopenharmony_ci __le64 manufacturer; 3462306a36Sopenharmony_ci __le64 product; 3562306a36Sopenharmony_ci __le64 serial; 3662306a36Sopenharmony_ci __le32 length; 3762306a36Sopenharmony_ci __le32 __reserved_0[7]; 3862306a36Sopenharmony_ci}; 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci#define DBC_CTRL_DBC_RUN BIT(0) 4162306a36Sopenharmony_ci#define DBC_CTRL_PORT_ENABLE BIT(1) 4262306a36Sopenharmony_ci#define DBC_CTRL_HALT_OUT_TR BIT(2) 4362306a36Sopenharmony_ci#define DBC_CTRL_HALT_IN_TR BIT(3) 4462306a36Sopenharmony_ci#define DBC_CTRL_DBC_RUN_CHANGE BIT(4) 4562306a36Sopenharmony_ci#define DBC_CTRL_DBC_ENABLE BIT(31) 4662306a36Sopenharmony_ci#define DBC_CTRL_MAXBURST(p) (((p) >> 16) & 0xff) 4762306a36Sopenharmony_ci#define DBC_DOOR_BELL_TARGET(p) (((p) & 0xff) << 8) 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ci#define DBC_MAX_PACKET 1024 5062306a36Sopenharmony_ci#define DBC_MAX_STRING_LENGTH 64 5162306a36Sopenharmony_ci#define DBC_STRING_MANUFACTURER "Linux Foundation" 5262306a36Sopenharmony_ci#define DBC_STRING_PRODUCT "Linux USB Debug Target" 5362306a36Sopenharmony_ci#define DBC_STRING_SERIAL "0001" 5462306a36Sopenharmony_ci#define DBC_CONTEXT_SIZE 64 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci/* 5762306a36Sopenharmony_ci * Port status: 5862306a36Sopenharmony_ci */ 5962306a36Sopenharmony_ci#define DBC_PORTSC_CONN_STATUS BIT(0) 6062306a36Sopenharmony_ci#define DBC_PORTSC_PORT_ENABLED BIT(1) 6162306a36Sopenharmony_ci#define DBC_PORTSC_CONN_CHANGE BIT(17) 6262306a36Sopenharmony_ci#define DBC_PORTSC_RESET_CHANGE BIT(21) 6362306a36Sopenharmony_ci#define DBC_PORTSC_LINK_CHANGE BIT(22) 6462306a36Sopenharmony_ci#define DBC_PORTSC_CONFIG_CHANGE BIT(23) 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_cistruct dbc_str_descs { 6762306a36Sopenharmony_ci char string0[DBC_MAX_STRING_LENGTH]; 6862306a36Sopenharmony_ci char manufacturer[DBC_MAX_STRING_LENGTH]; 6962306a36Sopenharmony_ci char product[DBC_MAX_STRING_LENGTH]; 7062306a36Sopenharmony_ci char serial[DBC_MAX_STRING_LENGTH]; 7162306a36Sopenharmony_ci}; 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci#define DBC_PROTOCOL 1 /* GNU Remote Debug Command */ 7462306a36Sopenharmony_ci#define DBC_VENDOR_ID 0x1d6b /* Linux Foundation 0x1d6b */ 7562306a36Sopenharmony_ci#define DBC_PRODUCT_ID 0x0010 /* device 0010 */ 7662306a36Sopenharmony_ci#define DBC_DEVICE_REV 0x0010 /* 0.10 */ 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_cienum dbc_state { 7962306a36Sopenharmony_ci DS_DISABLED = 0, 8062306a36Sopenharmony_ci DS_INITIALIZED, 8162306a36Sopenharmony_ci DS_ENABLED, 8262306a36Sopenharmony_ci DS_CONNECTED, 8362306a36Sopenharmony_ci DS_CONFIGURED, 8462306a36Sopenharmony_ci DS_STALLED, 8562306a36Sopenharmony_ci}; 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_cistruct dbc_ep { 8862306a36Sopenharmony_ci struct xhci_dbc *dbc; 8962306a36Sopenharmony_ci struct list_head list_pending; 9062306a36Sopenharmony_ci struct xhci_ring *ring; 9162306a36Sopenharmony_ci unsigned int direction:1; 9262306a36Sopenharmony_ci}; 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ci#define DBC_QUEUE_SIZE 16 9562306a36Sopenharmony_ci#define DBC_WRITE_BUF_SIZE 8192 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci/* 9862306a36Sopenharmony_ci * Private structure for DbC hardware state: 9962306a36Sopenharmony_ci */ 10062306a36Sopenharmony_cistruct dbc_port { 10162306a36Sopenharmony_ci struct tty_port port; 10262306a36Sopenharmony_ci spinlock_t port_lock; /* port access */ 10362306a36Sopenharmony_ci int minor; 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_ci struct list_head read_pool; 10662306a36Sopenharmony_ci struct list_head read_queue; 10762306a36Sopenharmony_ci unsigned int n_read; 10862306a36Sopenharmony_ci struct tasklet_struct push; 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ci struct list_head write_pool; 11162306a36Sopenharmony_ci struct kfifo write_fifo; 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci bool registered; 11462306a36Sopenharmony_ci}; 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_cistruct dbc_driver { 11762306a36Sopenharmony_ci int (*configure)(struct xhci_dbc *dbc); 11862306a36Sopenharmony_ci void (*disconnect)(struct xhci_dbc *dbc); 11962306a36Sopenharmony_ci}; 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_cistruct xhci_dbc { 12262306a36Sopenharmony_ci spinlock_t lock; /* device access */ 12362306a36Sopenharmony_ci struct device *dev; 12462306a36Sopenharmony_ci struct xhci_hcd *xhci; 12562306a36Sopenharmony_ci struct dbc_regs __iomem *regs; 12662306a36Sopenharmony_ci struct xhci_ring *ring_evt; 12762306a36Sopenharmony_ci struct xhci_ring *ring_in; 12862306a36Sopenharmony_ci struct xhci_ring *ring_out; 12962306a36Sopenharmony_ci struct xhci_erst erst; 13062306a36Sopenharmony_ci struct xhci_container_ctx *ctx; 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_ci struct dbc_str_descs *string; 13362306a36Sopenharmony_ci dma_addr_t string_dma; 13462306a36Sopenharmony_ci size_t string_size; 13562306a36Sopenharmony_ci u16 idVendor; 13662306a36Sopenharmony_ci u16 idProduct; 13762306a36Sopenharmony_ci u16 bcdDevice; 13862306a36Sopenharmony_ci u8 bInterfaceProtocol; 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci enum dbc_state state; 14162306a36Sopenharmony_ci struct delayed_work event_work; 14262306a36Sopenharmony_ci unsigned resume_required:1; 14362306a36Sopenharmony_ci struct dbc_ep eps[2]; 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_ci const struct dbc_driver *driver; 14662306a36Sopenharmony_ci void *priv; 14762306a36Sopenharmony_ci}; 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_cistruct dbc_request { 15062306a36Sopenharmony_ci void *buf; 15162306a36Sopenharmony_ci unsigned int length; 15262306a36Sopenharmony_ci dma_addr_t dma; 15362306a36Sopenharmony_ci void (*complete)(struct xhci_dbc *dbc, 15462306a36Sopenharmony_ci struct dbc_request *req); 15562306a36Sopenharmony_ci struct list_head list_pool; 15662306a36Sopenharmony_ci int status; 15762306a36Sopenharmony_ci unsigned int actual; 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ci struct xhci_dbc *dbc; 16062306a36Sopenharmony_ci struct list_head list_pending; 16162306a36Sopenharmony_ci dma_addr_t trb_dma; 16262306a36Sopenharmony_ci union xhci_trb *trb; 16362306a36Sopenharmony_ci unsigned direction:1; 16462306a36Sopenharmony_ci}; 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_ci#define dbc_bulkout_ctx(d) \ 16762306a36Sopenharmony_ci ((struct xhci_ep_ctx *)((d)->ctx->bytes + DBC_CONTEXT_SIZE)) 16862306a36Sopenharmony_ci#define dbc_bulkin_ctx(d) \ 16962306a36Sopenharmony_ci ((struct xhci_ep_ctx *)((d)->ctx->bytes + DBC_CONTEXT_SIZE * 2)) 17062306a36Sopenharmony_ci#define dbc_bulkout_enq(d) \ 17162306a36Sopenharmony_ci xhci_trb_virt_to_dma((d)->ring_out->enq_seg, (d)->ring_out->enqueue) 17262306a36Sopenharmony_ci#define dbc_bulkin_enq(d) \ 17362306a36Sopenharmony_ci xhci_trb_virt_to_dma((d)->ring_in->enq_seg, (d)->ring_in->enqueue) 17462306a36Sopenharmony_ci#define dbc_epctx_info2(t, p, b) \ 17562306a36Sopenharmony_ci cpu_to_le32(EP_TYPE(t) | MAX_PACKET(p) | MAX_BURST(b)) 17662306a36Sopenharmony_ci#define dbc_ep_dma_direction(d) \ 17762306a36Sopenharmony_ci ((d)->direction ? DMA_FROM_DEVICE : DMA_TO_DEVICE) 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_ci#define BULK_OUT 0 18062306a36Sopenharmony_ci#define BULK_IN 1 18162306a36Sopenharmony_ci#define EPID_OUT 2 18262306a36Sopenharmony_ci#define EPID_IN 3 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_cienum evtreturn { 18562306a36Sopenharmony_ci EVT_ERR = -1, 18662306a36Sopenharmony_ci EVT_DONE, 18762306a36Sopenharmony_ci EVT_GSER, 18862306a36Sopenharmony_ci EVT_DISC, 18962306a36Sopenharmony_ci}; 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_cistatic inline struct dbc_ep *get_in_ep(struct xhci_dbc *dbc) 19262306a36Sopenharmony_ci{ 19362306a36Sopenharmony_ci return &dbc->eps[BULK_IN]; 19462306a36Sopenharmony_ci} 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_cistatic inline struct dbc_ep *get_out_ep(struct xhci_dbc *dbc) 19762306a36Sopenharmony_ci{ 19862306a36Sopenharmony_ci return &dbc->eps[BULK_OUT]; 19962306a36Sopenharmony_ci} 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_ci#ifdef CONFIG_USB_XHCI_DBGCAP 20262306a36Sopenharmony_ciint xhci_create_dbc_dev(struct xhci_hcd *xhci); 20362306a36Sopenharmony_civoid xhci_remove_dbc_dev(struct xhci_hcd *xhci); 20462306a36Sopenharmony_ciint xhci_dbc_init(void); 20562306a36Sopenharmony_civoid xhci_dbc_exit(void); 20662306a36Sopenharmony_ciint dbc_tty_init(void); 20762306a36Sopenharmony_civoid dbc_tty_exit(void); 20862306a36Sopenharmony_ciint xhci_dbc_tty_probe(struct device *dev, void __iomem *res, struct xhci_hcd *xhci); 20962306a36Sopenharmony_civoid xhci_dbc_tty_remove(struct xhci_dbc *dbc); 21062306a36Sopenharmony_cistruct xhci_dbc *xhci_alloc_dbc(struct device *dev, void __iomem *res, 21162306a36Sopenharmony_ci const struct dbc_driver *driver); 21262306a36Sopenharmony_civoid xhci_dbc_remove(struct xhci_dbc *dbc); 21362306a36Sopenharmony_cistruct dbc_request *dbc_alloc_request(struct xhci_dbc *dbc, 21462306a36Sopenharmony_ci unsigned int direction, 21562306a36Sopenharmony_ci gfp_t flags); 21662306a36Sopenharmony_civoid dbc_free_request(struct dbc_request *req); 21762306a36Sopenharmony_ciint dbc_ep_queue(struct dbc_request *req); 21862306a36Sopenharmony_ci#ifdef CONFIG_PM 21962306a36Sopenharmony_ciint xhci_dbc_suspend(struct xhci_hcd *xhci); 22062306a36Sopenharmony_ciint xhci_dbc_resume(struct xhci_hcd *xhci); 22162306a36Sopenharmony_ci#endif /* CONFIG_PM */ 22262306a36Sopenharmony_ci#else 22362306a36Sopenharmony_cistatic inline int xhci_create_dbc_dev(struct xhci_hcd *xhci) 22462306a36Sopenharmony_ci{ 22562306a36Sopenharmony_ci return 0; 22662306a36Sopenharmony_ci} 22762306a36Sopenharmony_ci 22862306a36Sopenharmony_cistatic inline void xhci_remove_dbc_dev(struct xhci_hcd *xhci) 22962306a36Sopenharmony_ci{ 23062306a36Sopenharmony_ci} 23162306a36Sopenharmony_cistatic inline int xhci_dbc_init(void) 23262306a36Sopenharmony_ci{ 23362306a36Sopenharmony_ci return 0; 23462306a36Sopenharmony_ci} 23562306a36Sopenharmony_cistatic inline void xhci_dbc_exit(void) 23662306a36Sopenharmony_ci{ 23762306a36Sopenharmony_ci} 23862306a36Sopenharmony_cistatic inline int xhci_dbc_suspend(struct xhci_hcd *xhci) 23962306a36Sopenharmony_ci{ 24062306a36Sopenharmony_ci return 0; 24162306a36Sopenharmony_ci} 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_cistatic inline int xhci_dbc_resume(struct xhci_hcd *xhci) 24462306a36Sopenharmony_ci{ 24562306a36Sopenharmony_ci return 0; 24662306a36Sopenharmony_ci} 24762306a36Sopenharmony_ci#endif /* CONFIG_USB_XHCI_DBGCAP */ 24862306a36Sopenharmony_ci#endif /* __LINUX_XHCI_DBGCAP_H */ 249