linux/drivers/usb/gadget/udc/renesas_usbf.c

// SPDX-License-Identifier: GPL-2.0
/*
 * Renesas USBF USB Function driver
 *
 * Copyright 2022 Schneider Electric
 * Author: Herve Codina <[email protected]>
 */

#include <linux/delay.h>
#include <linux/dma-mapping.h>
#include <linux/interrupt.h>
#include <linux/iopoll.h>
#include <linux/kernel.h>
#include <linux/kfifo.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/types.h>
#include <linux/usb/composite.h>
#include <linux/usb/gadget.h>
#include <linux/usb/role.h>

#define USBF_NUM_ENDPOINTS
#define USBF_EP0_MAX_PCKT_SIZE

/* EPC registers */
#define USBF_REG_USB_CONTROL
#define USBF_USB_PUE2
#define USBF_USB_CONNECTB
#define USBF_USB_DEFAULT
#define USBF_USB_CONF
#define USBF_USB_SUSPEND
#define USBF_USB_RSUM_IN
#define USBF_USB_SOF_RCV
#define USBF_USB_FORCEFS
#define USBF_USB_INT_SEL
#define USBF_USB_SOF_CLK_MODE

#define USBF_REG_USB_STATUS
#define USBF_USB_RSUM_OUT
#define USBF_USB_SPND_OUT
#define USBF_USB_USB_RST
#define USBF_USB_DEFAULT_ST
#define USBF_USB_CONF_ST
#define USBF_USB_SPEED_MODE
#define USBF_USB_SOF_DELAY_STATUS

#define USBF_REG_USB_ADDRESS
#define USBF_USB_SOF_STATUS
#define USBF_USB_SET_USB_ADDR(_a)
#define USBF_USB_GET_FRAME(_r)

#define USBF_REG_SETUP_DATA0
#define USBF_REG_SETUP_DATA1
#define USBF_REG_USB_INT_STA
#define USBF_USB_RSUM_INT
#define USBF_USB_SPND_INT
#define USBF_USB_USB_RST_INT
#define USBF_USB_SOF_INT
#define USBF_USB_SOF_ERROR_INT
#define USBF_USB_SPEED_MODE_INT
#define USBF_USB_EPN_INT(_n)

#define USBF_REG_USB_INT_ENA
#define USBF_USB_RSUM_EN
#define USBF_USB_SPND_EN
#define USBF_USB_USB_RST_EN
#define USBF_USB_SOF_EN
#define USBF_USB_SOF_ERROR_EN
#define USBF_USB_SPEED_MODE_EN
#define USBF_USB_EPN_EN(_n)

#define USBF_BASE_EP0
/* EP0 registers offsets from Base + USBF_BASE_EP0 (EP0 regs area) */
#define USBF_REG_EP0_CONTROL
#define USBF_EP0_ONAK
#define USBF_EP0_INAK
#define USBF_EP0_STL
#define USBF_EP0_PERR_NAK_CLR
#define USBF_EP0_INAK_EN
#define USBF_EP0_DW_MASK
#define USBF_EP0_DW(_s)
#define USBF_EP0_DEND
#define USBF_EP0_BCLR
#define USBF_EP0_PIDCLR
#define USBF_EP0_AUTO
#define USBF_EP0_OVERSEL
#define USBF_EP0_STGSEL

#define USBF_REG_EP0_STATUS
#define USBF_EP0_SETUP_INT
#define USBF_EP0_STG_START_INT
#define USBF_EP0_STG_END_INT
#define USBF_EP0_STALL_INT
#define USBF_EP0_IN_INT
#define USBF_EP0_OUT_INT
#define USBF_EP0_OUT_OR_INT
#define USBF_EP0_OUT_NULL_INT
#define USBF_EP0_IN_EMPTY
#define USBF_EP0_IN_FULL
#define USBF_EP0_IN_DATA
#define USBF_EP0_IN_NAK_INT
#define USBF_EP0_OUT_EMPTY
#define USBF_EP0_OUT_FULL
#define USBF_EP0_OUT_NULL
#define USBF_EP0_OUT_NAK_INT
#define USBF_EP0_PERR_NAK_INT
#define USBF_EP0_PERR_NAK
#define USBF_EP0_PID

#define USBF_REG_EP0_INT_ENA
#define USBF_EP0_SETUP_EN
#define USBF_EP0_STG_START_EN
#define USBF_EP0_STG_END_EN
#define USBF_EP0_STALL_EN
#define USBF_EP0_IN_EN
#define USBF_EP0_OUT_EN
#define USBF_EP0_OUT_OR_EN
#define USBF_EP0_OUT_NULL_EN
#define USBF_EP0_IN_NAK_EN
#define USBF_EP0_OUT_NAK_EN
#define USBF_EP0_PERR_NAK_EN

#define USBF_REG_EP0_LENGTH
#define USBF_EP0_LDATA
#define USBF_REG_EP0_READ
#define USBF_REG_EP0_WRITE

#define USBF_BASE_EPN(_n)
/* EPn registers offsets from Base + USBF_BASE_EPN(n-1). n=1..15 */
#define USBF_REG_EPN_CONTROL
#define USBF_EPN_ONAK
#define USBF_EPN_OSTL
#define USBF_EPN_ISTL
#define USBF_EPN_OSTL_EN
#define USBF_EPN_DW_MASK
#define USBF_EPN_DW(_s)
#define USBF_EPN_DEND
#define USBF_EPN_CBCLR
#define USBF_EPN_BCLR
#define USBF_EPN_OPIDCLR
#define USBF_EPN_IPIDCLR
#define USBF_EPN_AUTO
#define USBF_EPN_OVERSEL
#define USBF_EPN_MODE_MASK
#define USBF_EPN_MODE_BULK
#define USBF_EPN_MODE_INTR
#define USBF_EPN_MODE_ISO
#define USBF_EPN_DIR0
#define USBF_EPN_BUF_TYPE_DOUBLE
#define USBF_EPN_EN

#define USBF_REG_EPN_STATUS
#define USBF_EPN_IN_EMPTY
#define USBF_EPN_IN_FULL
#define USBF_EPN_IN_DATA
#define USBF_EPN_IN_INT
#define USBF_EPN_IN_STALL_INT
#define USBF_EPN_IN_NAK_ERR_INT
#define USBF_EPN_IN_END_INT
#define USBF_EPN_IPID
#define USBF_EPN_OUT_EMPTY
#define USBF_EPN_OUT_FULL
#define USBF_EPN_OUT_NULL_INT
#define USBF_EPN_OUT_INT
#define USBF_EPN_OUT_STALL_INT
#define USBF_EPN_OUT_NAK_ERR_INT
#define USBF_EPN_OUT_OR_INT
#define USBF_EPN_OUT_END_INT
#define USBF_EPN_ISO_CRC
#define USBF_EPN_ISO_OR
#define USBF_EPN_OUT_NOTKN
#define USBF_EPN_ISO_OPID
#define USBF_EPN_ISO_PIDERR

#define USBF_REG_EPN_INT_ENA
#define USBF_EPN_IN_EN
#define USBF_EPN_IN_STALL_EN
#define USBF_EPN_IN_NAK_ERR_EN
#define USBF_EPN_IN_END_EN
#define USBF_EPN_OUT_NULL_EN
#define USBF_EPN_OUT_EN
#define USBF_EPN_OUT_STALL_EN
#define USBF_EPN_OUT_NAK_ERR_EN
#define USBF_EPN_OUT_OR_EN
#define USBF_EPN_OUT_END_EN

#define USBF_REG_EPN_DMA_CTRL
#define USBF_EPN_DMAMODE0
#define USBF_EPN_DMA_EN
#define USBF_EPN_STOP_SET
#define USBF_EPN_BURST_SET
#define USBF_EPN_DEND_SET
#define USBF_EPN_STOP_MODE

#define USBF_REG_EPN_PCKT_ADRS
#define USBF_EPN_MPKT(_l)
#define USBF_EPN_BASEAD(_a)

#define USBF_REG_EPN_LEN_DCNT
#define USBF_EPN_GET_LDATA(_r)
#define USBF_EPN_SET_DMACNT(_c)
#define USBF_EPN_GET_DMACNT(_r)

#define USBF_REG_EPN_READ
#define USBF_REG_EPN_WRITE

/* AHB-EPC Bridge registers */
#define USBF_REG_AHBSCTR
#define USBF_REG_AHBMCTR
#define USBF_SYS_WBURST_TYPE
#define USBF_SYS_ARBITER_CTR

#define USBF_REG_AHBBINT
#define USBF_SYS_ERR_MASTER
#define USBF_SYS_SBUS_ERRINT0
#define USBF_SYS_SBUS_ERRINT1
#define USBF_SYS_MBUS_ERRINT
#define USBF_SYS_VBUS_INT
#define USBF_SYS_DMA_ENDINT_EPN(_n)

#define USBF_REG_AHBBINTEN
#define USBF_SYS_SBUS_ERRINT0EN
#define USBF_SYS_SBUS_ERRINT1EN
#define USBF_SYS_MBUS_ERRINTEN
#define USBF_SYS_VBUS_INTEN
#define USBF_SYS_DMA_ENDINTEN_EPN(_n)

#define USBF_REG_EPCTR
#define USBF_SYS_EPC_RST
#define USBF_SYS_PLL_RST
#define USBF_SYS_PLL_LOCK
#define USBF_SYS_PLL_RESUME
#define USBF_SYS_VBUS_LEVEL
#define USBF_SYS_DIRPD

#define USBF_REG_USBSSVER
#define USBF_REG_USBSSCONF
#define USBF_SYS_DMA_AVAILABLE(_n)
#define USBF_SYS_EP_AVAILABLE(_n)

#define USBF_BASE_DMA_EPN(_n)
/* EPn DMA registers offsets from Base USBF_BASE_DMA_EPN(n-1). n=1..15*/
#define USBF_REG_DMA_EPN_DCR1
#define USBF_SYS_EPN_REQEN
#define USBF_SYS_EPN_DIR0
#define USBF_SYS_EPN_SET_DMACNT(_c)
#define USBF_SYS_EPN_GET_DMACNT(_r)

#define USBF_REG_DMA_EPN_DCR2
#define USBF_SYS_EPN_MPKT(_s)
#define USBF_SYS_EPN_LMPKT(_l)

#define USBF_REG_DMA_EPN_TADR

/* USB request */
struct usbf_req {};

/* USB Endpoint */
struct usbf_ep {};

enum usbf_ep0state {};

struct usbf_udc {};

struct usbf_ep_info {};

#define USBF_SINGLE_BUFFER
#define USBF_DOUBLE_BUFFER
#define USBF_EP_INFO(_name, _caps, _base_addr, _is_double, _maxpacket_limit)

/* This table is computed from the recommended values provided in the SOC
 * datasheet. The buffer type (single/double) and the endpoint type cannot
 * be changed. The mapping in internal RAM (base_addr and number of words)
 * for each endpoints depends on the max packet size and the buffer type.
 */
static const struct usbf_ep_info usbf_ep_info[USBF_NUM_ENDPOINTS] =;

static inline u32 usbf_reg_readl(struct usbf_udc *udc, uint offset)
{}

static inline void usbf_reg_writel(struct usbf_udc *udc, uint offset, u32 val)
{}

static inline void usbf_reg_bitset(struct usbf_udc *udc, uint offset, u32 set)
{}

static inline void usbf_reg_bitclr(struct usbf_udc *udc, uint offset, u32 clr)
{}

static inline void usbf_reg_clrset(struct usbf_udc *udc, uint offset,
				   u32 clr, u32 set)
{}

static inline u32 usbf_ep_reg_readl(struct usbf_ep *ep, uint offset)
{}

static inline void usbf_ep_reg_read_rep(struct usbf_ep *ep, uint offset,
				       void *dst, uint count)
{}

static inline void usbf_ep_reg_writel(struct usbf_ep *ep, uint offset, u32 val)
{}

static inline void usbf_ep_reg_write_rep(struct usbf_ep *ep, uint offset,
					 const void *src, uint count)
{}

static inline void usbf_ep_reg_bitset(struct usbf_ep *ep, uint offset, u32 set)
{}

static inline void usbf_ep_reg_bitclr(struct usbf_ep *ep, uint offset, u32 clr)
{}

static inline void usbf_ep_reg_clrset(struct usbf_ep *ep, uint offset,
				      u32 clr, u32 set)
{}

static inline u32 usbf_ep_dma_reg_readl(struct usbf_ep *ep, uint offset)
{}

static inline void usbf_ep_dma_reg_writel(struct usbf_ep *ep, uint offset,
					  u32 val)
{}

static inline void usbf_ep_dma_reg_bitset(struct usbf_ep *ep, uint offset,
					  u32 set)
{}

static inline void usbf_ep_dma_reg_bitclr(struct usbf_ep *ep, uint offset,
					  u32 clr)
{}

static void usbf_ep0_send_null(struct usbf_ep *ep0, bool is_data1)
{}

static int usbf_ep0_pio_in(struct usbf_ep *ep0, struct usbf_req *req)
{}

static int usbf_ep0_pio_out(struct usbf_ep *ep0, struct usbf_req *req)
{}

static void usbf_ep0_fifo_flush(struct usbf_ep *ep0)
{}

static void usbf_epn_send_null(struct usbf_ep *epn)
{}

static void usbf_epn_send_residue(struct usbf_ep *epn, const void *buf,
				  unsigned int size)
{}

static int usbf_epn_pio_in(struct usbf_ep *epn, struct usbf_req *req)
{}

static void usbf_epn_enable_in_end_int(struct usbf_ep *epn)
{}

static int usbf_epn_dma_in(struct usbf_ep *epn, struct usbf_req *req)
{}

static void usbf_epn_recv_residue(struct usbf_ep *epn, void *buf,
				  unsigned int size)
{}

static int usbf_epn_pio_out(struct usbf_ep *epn, struct usbf_req *req)
{}

static void usbf_epn_enable_out_end_int(struct usbf_ep *epn)
{}

static void usbf_epn_process_queue(struct usbf_ep *epn);

static void usbf_epn_dma_out_send_dma(struct usbf_ep *epn, dma_addr_t addr, u32 npkt, bool is_short)
{}

static size_t usbf_epn_dma_out_complete_dma(struct usbf_ep *epn, bool is_short)
{}

static int usbf_epn_dma_out(struct usbf_ep *epn, struct usbf_req *req)
{}

static void usbf_epn_dma_stop(struct usbf_ep *epn)
{}

static void usbf_epn_dma_abort(struct usbf_ep *epn,  struct usbf_req *req)
{}

static void usbf_epn_fifo_flush(struct usbf_ep *epn)
{}

static void usbf_ep_req_done(struct usbf_ep *ep, struct usbf_req *req,
			     int status)
{}

static void usbf_ep_nuke(struct usbf_ep *ep, int status)
{}

static bool usbf_ep_is_stalled(struct usbf_ep *ep)
{}

static int usbf_epn_start_queue(struct usbf_ep *epn)
{}

static int usbf_ep_process_queue(struct usbf_ep *ep)
{}

static void usbf_ep_stall(struct usbf_ep *ep, bool stall)
{}

static void usbf_ep0_enable(struct usbf_ep *ep0)
{}

static int usbf_epn_enable(struct usbf_ep *epn)
{}

static int usbf_ep_enable(struct usb_ep *_ep,
			  const struct usb_endpoint_descriptor *desc)
{}

static int usbf_epn_disable(struct usbf_ep *epn)
{}

static int usbf_ep_disable(struct usb_ep *_ep)
{}

static int usbf_ep0_queue(struct usbf_ep *ep0, struct usbf_req *req,
			  gfp_t gfp_flags)
{}

static int usbf_epn_queue(struct usbf_ep *ep, struct usbf_req *req,
			  gfp_t gfp_flags)
{}

static int usbf_ep_queue(struct usb_ep *_ep, struct usb_request *_req,
			 gfp_t gfp_flags)
{}

static int usbf_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req)
{}

static struct usb_request *usbf_ep_alloc_request(struct usb_ep *_ep,
						 gfp_t gfp_flags)
{}

static void usbf_ep_free_request(struct usb_ep *_ep, struct usb_request *_req)
{}

static int usbf_ep_set_halt(struct usb_ep *_ep, int halt)
{}

static int usbf_ep_set_wedge(struct usb_ep *_ep)
{}

static struct usb_ep_ops usbf_ep_ops =;

static void usbf_ep0_req_complete(struct usb_ep *_ep, struct usb_request *_req)
{}

static void usbf_ep0_fill_req(struct usbf_ep *ep0, struct usbf_req *req,
			      void *buf, unsigned int length,
			      void (*complete)(struct usb_ep *_ep,
					       struct usb_request *_req))
{}

static struct usbf_ep *usbf_get_ep_by_addr(struct usbf_udc *udc, u8 address)
{}

static int usbf_req_delegate(struct usbf_udc *udc,
			     const struct usb_ctrlrequest *ctrlrequest)
{}

static int usbf_req_get_status(struct usbf_udc *udc,
			       const struct usb_ctrlrequest *ctrlrequest)
{}

static int usbf_req_clear_set_feature(struct usbf_udc *udc,
				      const struct usb_ctrlrequest *ctrlrequest,
				      bool is_set)
{}

static void usbf_ep0_req_set_address_complete(struct usb_ep *_ep,
					      struct usb_request *_req)
{}

static int usbf_req_set_address(struct usbf_udc *udc,
				const struct usb_ctrlrequest *ctrlrequest)
{}

static int usbf_req_set_configuration(struct usbf_udc *udc,
				      const struct usb_ctrlrequest *ctrlrequest)
{}

static int usbf_handle_ep0_setup(struct usbf_ep *ep0)
{}

static int usbf_handle_ep0_data_status(struct usbf_ep *ep0,
				  const char *ep0state_name,
				  enum usbf_ep0state next_ep0state)
{}

static int usbf_handle_ep0_out_status_start(struct usbf_ep *ep0)
{}

static int usbf_handle_ep0_in_status_start(struct usbf_ep *ep0)
{}

static void usbf_ep0_interrupt(struct usbf_ep *ep0)
{}

static void usbf_epn_process_queue(struct usbf_ep *epn)
{}

static void usbf_epn_interrupt(struct usbf_ep *epn)
{}

static void usbf_ep_reset(struct usbf_ep *ep)
{}

static void usbf_reset(struct usbf_udc *udc)
{}

static void usbf_driver_suspend(struct usbf_udc *udc)
{}

static void usbf_driver_resume(struct usbf_udc *udc)
{}

static irqreturn_t usbf_epc_irq(int irq, void *_udc)
{}

static irqreturn_t usbf_ahb_epc_irq(int irq, void *_udc)
{}

static int usbf_udc_start(struct usb_gadget *gadget,
			  struct usb_gadget_driver *driver)
{}

static int usbf_udc_stop(struct usb_gadget *gadget)
{}

static int usbf_get_frame(struct usb_gadget *gadget)
{}

static void usbf_attach(struct usbf_udc *udc)
{}

static void usbf_detach(struct usbf_udc *udc)
{}

static int usbf_pullup(struct usb_gadget *gadget, int is_on)
{}

static int usbf_udc_set_selfpowered(struct usb_gadget *gadget,
				    int is_selfpowered)
{}

static int usbf_udc_wakeup(struct usb_gadget *gadget)
{}

static struct usb_gadget_ops usbf_gadget_ops =;

static int usbf_epn_check(struct usbf_ep *epn)
{}

static int usbf_probe(struct platform_device *pdev)
{}

static void usbf_remove(struct platform_device *pdev)
{}

static const struct of_device_id usbf_match[] =;
MODULE_DEVICE_TABLE(of, usbf_match);

static struct platform_driver udc_driver =;

module_platform_driver();

MODULE_AUTHOR();
MODULE_DESCRIPTION();
MODULE_LICENSE();