18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Renesas USB3.0 Peripheral driver (USB gadget) 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2015-2017 Renesas Electronics Corporation 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#include <linux/debugfs.h> 98c2ecf20Sopenharmony_ci#include <linux/delay.h> 108c2ecf20Sopenharmony_ci#include <linux/dma-mapping.h> 118c2ecf20Sopenharmony_ci#include <linux/err.h> 128c2ecf20Sopenharmony_ci#include <linux/extcon-provider.h> 138c2ecf20Sopenharmony_ci#include <linux/interrupt.h> 148c2ecf20Sopenharmony_ci#include <linux/io.h> 158c2ecf20Sopenharmony_ci#include <linux/module.h> 168c2ecf20Sopenharmony_ci#include <linux/of_device.h> 178c2ecf20Sopenharmony_ci#include <linux/phy/phy.h> 188c2ecf20Sopenharmony_ci#include <linux/platform_device.h> 198c2ecf20Sopenharmony_ci#include <linux/pm_runtime.h> 208c2ecf20Sopenharmony_ci#include <linux/sizes.h> 218c2ecf20Sopenharmony_ci#include <linux/slab.h> 228c2ecf20Sopenharmony_ci#include <linux/string.h> 238c2ecf20Sopenharmony_ci#include <linux/sys_soc.h> 248c2ecf20Sopenharmony_ci#include <linux/uaccess.h> 258c2ecf20Sopenharmony_ci#include <linux/usb/ch9.h> 268c2ecf20Sopenharmony_ci#include <linux/usb/gadget.h> 278c2ecf20Sopenharmony_ci#include <linux/usb/of.h> 288c2ecf20Sopenharmony_ci#include <linux/usb/role.h> 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci/* register definitions */ 318c2ecf20Sopenharmony_ci#define USB3_AXI_INT_STA 0x008 328c2ecf20Sopenharmony_ci#define USB3_AXI_INT_ENA 0x00c 338c2ecf20Sopenharmony_ci#define USB3_DMA_INT_STA 0x010 348c2ecf20Sopenharmony_ci#define USB3_DMA_INT_ENA 0x014 358c2ecf20Sopenharmony_ci#define USB3_DMA_CH0_CON(n) (0x030 + ((n) - 1) * 0x10) /* n = 1 to 4 */ 368c2ecf20Sopenharmony_ci#define USB3_DMA_CH0_PRD_ADR(n) (0x034 + ((n) - 1) * 0x10) /* n = 1 to 4 */ 378c2ecf20Sopenharmony_ci#define USB3_USB_COM_CON 0x200 388c2ecf20Sopenharmony_ci#define USB3_USB20_CON 0x204 398c2ecf20Sopenharmony_ci#define USB3_USB30_CON 0x208 408c2ecf20Sopenharmony_ci#define USB3_USB_STA 0x210 418c2ecf20Sopenharmony_ci#define USB3_DRD_CON 0x218 428c2ecf20Sopenharmony_ci#define USB3_USB_INT_STA_1 0x220 438c2ecf20Sopenharmony_ci#define USB3_USB_INT_STA_2 0x224 448c2ecf20Sopenharmony_ci#define USB3_USB_INT_ENA_1 0x228 458c2ecf20Sopenharmony_ci#define USB3_USB_INT_ENA_2 0x22c 468c2ecf20Sopenharmony_ci#define USB3_STUP_DAT_0 0x230 478c2ecf20Sopenharmony_ci#define USB3_STUP_DAT_1 0x234 488c2ecf20Sopenharmony_ci#define USB3_USB_OTG_STA 0x268 498c2ecf20Sopenharmony_ci#define USB3_USB_OTG_INT_STA 0x26c 508c2ecf20Sopenharmony_ci#define USB3_USB_OTG_INT_ENA 0x270 518c2ecf20Sopenharmony_ci#define USB3_P0_MOD 0x280 528c2ecf20Sopenharmony_ci#define USB3_P0_CON 0x288 538c2ecf20Sopenharmony_ci#define USB3_P0_STA 0x28c 548c2ecf20Sopenharmony_ci#define USB3_P0_INT_STA 0x290 558c2ecf20Sopenharmony_ci#define USB3_P0_INT_ENA 0x294 568c2ecf20Sopenharmony_ci#define USB3_P0_LNG 0x2a0 578c2ecf20Sopenharmony_ci#define USB3_P0_READ 0x2a4 588c2ecf20Sopenharmony_ci#define USB3_P0_WRITE 0x2a8 598c2ecf20Sopenharmony_ci#define USB3_PIPE_COM 0x2b0 608c2ecf20Sopenharmony_ci#define USB3_PN_MOD 0x2c0 618c2ecf20Sopenharmony_ci#define USB3_PN_RAMMAP 0x2c4 628c2ecf20Sopenharmony_ci#define USB3_PN_CON 0x2c8 638c2ecf20Sopenharmony_ci#define USB3_PN_STA 0x2cc 648c2ecf20Sopenharmony_ci#define USB3_PN_INT_STA 0x2d0 658c2ecf20Sopenharmony_ci#define USB3_PN_INT_ENA 0x2d4 668c2ecf20Sopenharmony_ci#define USB3_PN_LNG 0x2e0 678c2ecf20Sopenharmony_ci#define USB3_PN_READ 0x2e4 688c2ecf20Sopenharmony_ci#define USB3_PN_WRITE 0x2e8 698c2ecf20Sopenharmony_ci#define USB3_SSIFCMD 0x340 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ci/* AXI_INT_ENA and AXI_INT_STA */ 728c2ecf20Sopenharmony_ci#define AXI_INT_DMAINT BIT(31) 738c2ecf20Sopenharmony_ci#define AXI_INT_EPCINT BIT(30) 748c2ecf20Sopenharmony_ci/* PRD's n = from 1 to 4 */ 758c2ecf20Sopenharmony_ci#define AXI_INT_PRDEN_CLR_STA_SHIFT(n) (16 + (n) - 1) 768c2ecf20Sopenharmony_ci#define AXI_INT_PRDERR_STA_SHIFT(n) (0 + (n) - 1) 778c2ecf20Sopenharmony_ci#define AXI_INT_PRDEN_CLR_STA(n) (1 << AXI_INT_PRDEN_CLR_STA_SHIFT(n)) 788c2ecf20Sopenharmony_ci#define AXI_INT_PRDERR_STA(n) (1 << AXI_INT_PRDERR_STA_SHIFT(n)) 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ci/* DMA_INT_ENA and DMA_INT_STA */ 818c2ecf20Sopenharmony_ci#define DMA_INT(n) BIT(n) 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci/* DMA_CH0_CONn */ 848c2ecf20Sopenharmony_ci#define DMA_CON_PIPE_DIR BIT(15) /* 1: In Transfer */ 858c2ecf20Sopenharmony_ci#define DMA_CON_PIPE_NO_SHIFT 8 868c2ecf20Sopenharmony_ci#define DMA_CON_PIPE_NO_MASK GENMASK(12, DMA_CON_PIPE_NO_SHIFT) 878c2ecf20Sopenharmony_ci#define DMA_COM_PIPE_NO(n) (((n) << DMA_CON_PIPE_NO_SHIFT) & \ 888c2ecf20Sopenharmony_ci DMA_CON_PIPE_NO_MASK) 898c2ecf20Sopenharmony_ci#define DMA_CON_PRD_EN BIT(0) 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_ci/* LCLKSEL */ 928c2ecf20Sopenharmony_ci#define LCLKSEL_LSEL BIT(18) 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_ci/* USB_COM_CON */ 958c2ecf20Sopenharmony_ci#define USB_COM_CON_CONF BIT(24) 968c2ecf20Sopenharmony_ci#define USB_COM_CON_PN_WDATAIF_NL BIT(23) 978c2ecf20Sopenharmony_ci#define USB_COM_CON_PN_RDATAIF_NL BIT(22) 988c2ecf20Sopenharmony_ci#define USB_COM_CON_PN_LSTTR_PP BIT(21) 998c2ecf20Sopenharmony_ci#define USB_COM_CON_SPD_MODE BIT(17) 1008c2ecf20Sopenharmony_ci#define USB_COM_CON_EP0_EN BIT(16) 1018c2ecf20Sopenharmony_ci#define USB_COM_CON_DEV_ADDR_SHIFT 8 1028c2ecf20Sopenharmony_ci#define USB_COM_CON_DEV_ADDR_MASK GENMASK(14, USB_COM_CON_DEV_ADDR_SHIFT) 1038c2ecf20Sopenharmony_ci#define USB_COM_CON_DEV_ADDR(n) (((n) << USB_COM_CON_DEV_ADDR_SHIFT) & \ 1048c2ecf20Sopenharmony_ci USB_COM_CON_DEV_ADDR_MASK) 1058c2ecf20Sopenharmony_ci#define USB_COM_CON_RX_DETECTION BIT(1) 1068c2ecf20Sopenharmony_ci#define USB_COM_CON_PIPE_CLR BIT(0) 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ci/* USB20_CON */ 1098c2ecf20Sopenharmony_ci#define USB20_CON_B2_PUE BIT(31) 1108c2ecf20Sopenharmony_ci#define USB20_CON_B2_SUSPEND BIT(24) 1118c2ecf20Sopenharmony_ci#define USB20_CON_B2_CONNECT BIT(17) 1128c2ecf20Sopenharmony_ci#define USB20_CON_B2_TSTMOD_SHIFT 8 1138c2ecf20Sopenharmony_ci#define USB20_CON_B2_TSTMOD_MASK GENMASK(10, USB20_CON_B2_TSTMOD_SHIFT) 1148c2ecf20Sopenharmony_ci#define USB20_CON_B2_TSTMOD(n) (((n) << USB20_CON_B2_TSTMOD_SHIFT) & \ 1158c2ecf20Sopenharmony_ci USB20_CON_B2_TSTMOD_MASK) 1168c2ecf20Sopenharmony_ci#define USB20_CON_B2_TSTMOD_EN BIT(0) 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci/* USB30_CON */ 1198c2ecf20Sopenharmony_ci#define USB30_CON_POW_SEL_SHIFT 24 1208c2ecf20Sopenharmony_ci#define USB30_CON_POW_SEL_MASK GENMASK(26, USB30_CON_POW_SEL_SHIFT) 1218c2ecf20Sopenharmony_ci#define USB30_CON_POW_SEL_IN_U3 BIT(26) 1228c2ecf20Sopenharmony_ci#define USB30_CON_POW_SEL_IN_DISCON 0 1238c2ecf20Sopenharmony_ci#define USB30_CON_POW_SEL_P2_TO_P0 BIT(25) 1248c2ecf20Sopenharmony_ci#define USB30_CON_POW_SEL_P0_TO_P3 BIT(24) 1258c2ecf20Sopenharmony_ci#define USB30_CON_POW_SEL_P0_TO_P2 0 1268c2ecf20Sopenharmony_ci#define USB30_CON_B3_PLLWAKE BIT(23) 1278c2ecf20Sopenharmony_ci#define USB30_CON_B3_CONNECT BIT(17) 1288c2ecf20Sopenharmony_ci#define USB30_CON_B3_HOTRST_CMP BIT(1) 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ci/* USB_STA */ 1318c2ecf20Sopenharmony_ci#define USB_STA_SPEED_MASK (BIT(2) | BIT(1)) 1328c2ecf20Sopenharmony_ci#define USB_STA_SPEED_HS BIT(2) 1338c2ecf20Sopenharmony_ci#define USB_STA_SPEED_FS BIT(1) 1348c2ecf20Sopenharmony_ci#define USB_STA_SPEED_SS 0 1358c2ecf20Sopenharmony_ci#define USB_STA_VBUS_STA BIT(0) 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ci/* DRD_CON */ 1388c2ecf20Sopenharmony_ci#define DRD_CON_PERI_CON BIT(24) 1398c2ecf20Sopenharmony_ci#define DRD_CON_VBOUT BIT(0) 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_ci/* USB_INT_ENA_1 and USB_INT_STA_1 */ 1428c2ecf20Sopenharmony_ci#define USB_INT_1_B3_PLLWKUP BIT(31) 1438c2ecf20Sopenharmony_ci#define USB_INT_1_B3_LUPSUCS BIT(30) 1448c2ecf20Sopenharmony_ci#define USB_INT_1_B3_DISABLE BIT(27) 1458c2ecf20Sopenharmony_ci#define USB_INT_1_B3_WRMRST BIT(21) 1468c2ecf20Sopenharmony_ci#define USB_INT_1_B3_HOTRST BIT(20) 1478c2ecf20Sopenharmony_ci#define USB_INT_1_B2_USBRST BIT(12) 1488c2ecf20Sopenharmony_ci#define USB_INT_1_B2_L1SPND BIT(11) 1498c2ecf20Sopenharmony_ci#define USB_INT_1_B2_SPND BIT(9) 1508c2ecf20Sopenharmony_ci#define USB_INT_1_B2_RSUM BIT(8) 1518c2ecf20Sopenharmony_ci#define USB_INT_1_SPEED BIT(1) 1528c2ecf20Sopenharmony_ci#define USB_INT_1_VBUS_CNG BIT(0) 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ci/* USB_INT_ENA_2 and USB_INT_STA_2 */ 1558c2ecf20Sopenharmony_ci#define USB_INT_2_PIPE(n) BIT(n) 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_ci/* USB_OTG_STA, USB_OTG_INT_STA and USB_OTG_INT_ENA */ 1588c2ecf20Sopenharmony_ci#define USB_OTG_IDMON BIT(4) 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ci/* P0_MOD */ 1618c2ecf20Sopenharmony_ci#define P0_MOD_DIR BIT(6) 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci/* P0_CON and PN_CON */ 1648c2ecf20Sopenharmony_ci#define PX_CON_BYTE_EN_MASK (BIT(10) | BIT(9)) 1658c2ecf20Sopenharmony_ci#define PX_CON_BYTE_EN_SHIFT 9 1668c2ecf20Sopenharmony_ci#define PX_CON_BYTE_EN_BYTES(n) (((n) << PX_CON_BYTE_EN_SHIFT) & \ 1678c2ecf20Sopenharmony_ci PX_CON_BYTE_EN_MASK) 1688c2ecf20Sopenharmony_ci#define PX_CON_SEND BIT(8) 1698c2ecf20Sopenharmony_ci 1708c2ecf20Sopenharmony_ci/* P0_CON */ 1718c2ecf20Sopenharmony_ci#define P0_CON_ST_RES_MASK (BIT(27) | BIT(26)) 1728c2ecf20Sopenharmony_ci#define P0_CON_ST_RES_FORCE_STALL BIT(27) 1738c2ecf20Sopenharmony_ci#define P0_CON_ST_RES_NORMAL BIT(26) 1748c2ecf20Sopenharmony_ci#define P0_CON_ST_RES_FORCE_NRDY 0 1758c2ecf20Sopenharmony_ci#define P0_CON_OT_RES_MASK (BIT(25) | BIT(24)) 1768c2ecf20Sopenharmony_ci#define P0_CON_OT_RES_FORCE_STALL BIT(25) 1778c2ecf20Sopenharmony_ci#define P0_CON_OT_RES_NORMAL BIT(24) 1788c2ecf20Sopenharmony_ci#define P0_CON_OT_RES_FORCE_NRDY 0 1798c2ecf20Sopenharmony_ci#define P0_CON_IN_RES_MASK (BIT(17) | BIT(16)) 1808c2ecf20Sopenharmony_ci#define P0_CON_IN_RES_FORCE_STALL BIT(17) 1818c2ecf20Sopenharmony_ci#define P0_CON_IN_RES_NORMAL BIT(16) 1828c2ecf20Sopenharmony_ci#define P0_CON_IN_RES_FORCE_NRDY 0 1838c2ecf20Sopenharmony_ci#define P0_CON_RES_WEN BIT(7) 1848c2ecf20Sopenharmony_ci#define P0_CON_BCLR BIT(1) 1858c2ecf20Sopenharmony_ci 1868c2ecf20Sopenharmony_ci/* P0_STA and PN_STA */ 1878c2ecf20Sopenharmony_ci#define PX_STA_BUFSTS BIT(0) 1888c2ecf20Sopenharmony_ci 1898c2ecf20Sopenharmony_ci/* P0_INT_ENA and P0_INT_STA */ 1908c2ecf20Sopenharmony_ci#define P0_INT_STSED BIT(18) 1918c2ecf20Sopenharmony_ci#define P0_INT_STSST BIT(17) 1928c2ecf20Sopenharmony_ci#define P0_INT_SETUP BIT(16) 1938c2ecf20Sopenharmony_ci#define P0_INT_RCVNL BIT(8) 1948c2ecf20Sopenharmony_ci#define P0_INT_ERDY BIT(7) 1958c2ecf20Sopenharmony_ci#define P0_INT_FLOW BIT(6) 1968c2ecf20Sopenharmony_ci#define P0_INT_STALL BIT(2) 1978c2ecf20Sopenharmony_ci#define P0_INT_NRDY BIT(1) 1988c2ecf20Sopenharmony_ci#define P0_INT_BFRDY BIT(0) 1998c2ecf20Sopenharmony_ci#define P0_INT_ALL_BITS (P0_INT_STSED | P0_INT_SETUP | P0_INT_BFRDY) 2008c2ecf20Sopenharmony_ci 2018c2ecf20Sopenharmony_ci/* PN_MOD */ 2028c2ecf20Sopenharmony_ci#define PN_MOD_DIR BIT(6) 2038c2ecf20Sopenharmony_ci#define PN_MOD_TYPE_SHIFT 4 2048c2ecf20Sopenharmony_ci#define PN_MOD_TYPE_MASK GENMASK(5, PN_MOD_TYPE_SHIFT) 2058c2ecf20Sopenharmony_ci#define PN_MOD_TYPE(n) (((n) << PN_MOD_TYPE_SHIFT) & \ 2068c2ecf20Sopenharmony_ci PN_MOD_TYPE_MASK) 2078c2ecf20Sopenharmony_ci#define PN_MOD_EPNUM_MASK GENMASK(3, 0) 2088c2ecf20Sopenharmony_ci#define PN_MOD_EPNUM(n) ((n) & PN_MOD_EPNUM_MASK) 2098c2ecf20Sopenharmony_ci 2108c2ecf20Sopenharmony_ci/* PN_RAMMAP */ 2118c2ecf20Sopenharmony_ci#define PN_RAMMAP_RAMAREA_SHIFT 29 2128c2ecf20Sopenharmony_ci#define PN_RAMMAP_RAMAREA_MASK GENMASK(31, PN_RAMMAP_RAMAREA_SHIFT) 2138c2ecf20Sopenharmony_ci#define PN_RAMMAP_RAMAREA_16KB BIT(31) 2148c2ecf20Sopenharmony_ci#define PN_RAMMAP_RAMAREA_8KB (BIT(30) | BIT(29)) 2158c2ecf20Sopenharmony_ci#define PN_RAMMAP_RAMAREA_4KB BIT(30) 2168c2ecf20Sopenharmony_ci#define PN_RAMMAP_RAMAREA_2KB BIT(29) 2178c2ecf20Sopenharmony_ci#define PN_RAMMAP_RAMAREA_1KB 0 2188c2ecf20Sopenharmony_ci#define PN_RAMMAP_MPKT_SHIFT 16 2198c2ecf20Sopenharmony_ci#define PN_RAMMAP_MPKT_MASK GENMASK(26, PN_RAMMAP_MPKT_SHIFT) 2208c2ecf20Sopenharmony_ci#define PN_RAMMAP_MPKT(n) (((n) << PN_RAMMAP_MPKT_SHIFT) & \ 2218c2ecf20Sopenharmony_ci PN_RAMMAP_MPKT_MASK) 2228c2ecf20Sopenharmony_ci#define PN_RAMMAP_RAMIF_SHIFT 14 2238c2ecf20Sopenharmony_ci#define PN_RAMMAP_RAMIF_MASK GENMASK(15, PN_RAMMAP_RAMIF_SHIFT) 2248c2ecf20Sopenharmony_ci#define PN_RAMMAP_RAMIF(n) (((n) << PN_RAMMAP_RAMIF_SHIFT) & \ 2258c2ecf20Sopenharmony_ci PN_RAMMAP_RAMIF_MASK) 2268c2ecf20Sopenharmony_ci#define PN_RAMMAP_BASEAD_MASK GENMASK(13, 0) 2278c2ecf20Sopenharmony_ci#define PN_RAMMAP_BASEAD(offs) (((offs) >> 3) & PN_RAMMAP_BASEAD_MASK) 2288c2ecf20Sopenharmony_ci#define PN_RAMMAP_DATA(area, ramif, basead) ((PN_RAMMAP_##area) | \ 2298c2ecf20Sopenharmony_ci (PN_RAMMAP_RAMIF(ramif)) | \ 2308c2ecf20Sopenharmony_ci (PN_RAMMAP_BASEAD(basead))) 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_ci/* PN_CON */ 2338c2ecf20Sopenharmony_ci#define PN_CON_EN BIT(31) 2348c2ecf20Sopenharmony_ci#define PN_CON_DATAIF_EN BIT(30) 2358c2ecf20Sopenharmony_ci#define PN_CON_RES_MASK (BIT(17) | BIT(16)) 2368c2ecf20Sopenharmony_ci#define PN_CON_RES_FORCE_STALL BIT(17) 2378c2ecf20Sopenharmony_ci#define PN_CON_RES_NORMAL BIT(16) 2388c2ecf20Sopenharmony_ci#define PN_CON_RES_FORCE_NRDY 0 2398c2ecf20Sopenharmony_ci#define PN_CON_LAST BIT(11) 2408c2ecf20Sopenharmony_ci#define PN_CON_RES_WEN BIT(7) 2418c2ecf20Sopenharmony_ci#define PN_CON_CLR BIT(0) 2428c2ecf20Sopenharmony_ci 2438c2ecf20Sopenharmony_ci/* PN_INT_STA and PN_INT_ENA */ 2448c2ecf20Sopenharmony_ci#define PN_INT_LSTTR BIT(4) 2458c2ecf20Sopenharmony_ci#define PN_INT_BFRDY BIT(0) 2468c2ecf20Sopenharmony_ci 2478c2ecf20Sopenharmony_ci/* USB3_SSIFCMD */ 2488c2ecf20Sopenharmony_ci#define SSIFCMD_URES_U2 BIT(9) 2498c2ecf20Sopenharmony_ci#define SSIFCMD_URES_U1 BIT(8) 2508c2ecf20Sopenharmony_ci#define SSIFCMD_UDIR_U2 BIT(7) 2518c2ecf20Sopenharmony_ci#define SSIFCMD_UDIR_U1 BIT(6) 2528c2ecf20Sopenharmony_ci#define SSIFCMD_UREQ_U2 BIT(5) 2538c2ecf20Sopenharmony_ci#define SSIFCMD_UREQ_U1 BIT(4) 2548c2ecf20Sopenharmony_ci 2558c2ecf20Sopenharmony_ci#define USB3_EP0_SS_MAX_PACKET_SIZE 512 2568c2ecf20Sopenharmony_ci#define USB3_EP0_HSFS_MAX_PACKET_SIZE 64 2578c2ecf20Sopenharmony_ci#define USB3_EP0_BUF_SIZE 8 2588c2ecf20Sopenharmony_ci#define USB3_MAX_NUM_PIPES 6 /* This includes PIPE 0 */ 2598c2ecf20Sopenharmony_ci#define USB3_WAIT_US 3 2608c2ecf20Sopenharmony_ci#define USB3_DMA_NUM_SETTING_AREA 4 2618c2ecf20Sopenharmony_ci/* 2628c2ecf20Sopenharmony_ci * To avoid double-meaning of "0" (xferred 65536 bytes or received zlp if 2638c2ecf20Sopenharmony_ci * buffer size is 65536), this driver uses the maximum size per a entry is 2648c2ecf20Sopenharmony_ci * 32768 bytes. 2658c2ecf20Sopenharmony_ci */ 2668c2ecf20Sopenharmony_ci#define USB3_DMA_MAX_XFER_SIZE 32768 2678c2ecf20Sopenharmony_ci#define USB3_DMA_PRD_SIZE 4096 2688c2ecf20Sopenharmony_ci 2698c2ecf20Sopenharmony_cistruct renesas_usb3; 2708c2ecf20Sopenharmony_ci 2718c2ecf20Sopenharmony_ci/* Physical Region Descriptor Table */ 2728c2ecf20Sopenharmony_cistruct renesas_usb3_prd { 2738c2ecf20Sopenharmony_ci u32 word1; 2748c2ecf20Sopenharmony_ci#define USB3_PRD1_E BIT(30) /* the end of chain */ 2758c2ecf20Sopenharmony_ci#define USB3_PRD1_U BIT(29) /* completion of transfer */ 2768c2ecf20Sopenharmony_ci#define USB3_PRD1_D BIT(28) /* Error occurred */ 2778c2ecf20Sopenharmony_ci#define USB3_PRD1_INT BIT(27) /* Interrupt occurred */ 2788c2ecf20Sopenharmony_ci#define USB3_PRD1_LST BIT(26) /* Last Packet */ 2798c2ecf20Sopenharmony_ci#define USB3_PRD1_B_INC BIT(24) 2808c2ecf20Sopenharmony_ci#define USB3_PRD1_MPS_8 0 2818c2ecf20Sopenharmony_ci#define USB3_PRD1_MPS_16 BIT(21) 2828c2ecf20Sopenharmony_ci#define USB3_PRD1_MPS_32 BIT(22) 2838c2ecf20Sopenharmony_ci#define USB3_PRD1_MPS_64 (BIT(22) | BIT(21)) 2848c2ecf20Sopenharmony_ci#define USB3_PRD1_MPS_512 BIT(23) 2858c2ecf20Sopenharmony_ci#define USB3_PRD1_MPS_1024 (BIT(23) | BIT(21)) 2868c2ecf20Sopenharmony_ci#define USB3_PRD1_MPS_RESERVED (BIT(23) | BIT(22) | BIT(21)) 2878c2ecf20Sopenharmony_ci#define USB3_PRD1_SIZE_MASK GENMASK(15, 0) 2888c2ecf20Sopenharmony_ci 2898c2ecf20Sopenharmony_ci u32 bap; 2908c2ecf20Sopenharmony_ci}; 2918c2ecf20Sopenharmony_ci#define USB3_DMA_NUM_PRD_ENTRIES (USB3_DMA_PRD_SIZE / \ 2928c2ecf20Sopenharmony_ci sizeof(struct renesas_usb3_prd)) 2938c2ecf20Sopenharmony_ci#define USB3_DMA_MAX_XFER_SIZE_ALL_PRDS (USB3_DMA_PRD_SIZE / \ 2948c2ecf20Sopenharmony_ci sizeof(struct renesas_usb3_prd) * \ 2958c2ecf20Sopenharmony_ci USB3_DMA_MAX_XFER_SIZE) 2968c2ecf20Sopenharmony_ci 2978c2ecf20Sopenharmony_cistruct renesas_usb3_dma { 2988c2ecf20Sopenharmony_ci struct renesas_usb3_prd *prd; 2998c2ecf20Sopenharmony_ci dma_addr_t prd_dma; 3008c2ecf20Sopenharmony_ci int num; /* Setting area number (from 1 to 4) */ 3018c2ecf20Sopenharmony_ci bool used; 3028c2ecf20Sopenharmony_ci}; 3038c2ecf20Sopenharmony_ci 3048c2ecf20Sopenharmony_cistruct renesas_usb3_request { 3058c2ecf20Sopenharmony_ci struct usb_request req; 3068c2ecf20Sopenharmony_ci struct list_head queue; 3078c2ecf20Sopenharmony_ci}; 3088c2ecf20Sopenharmony_ci 3098c2ecf20Sopenharmony_ci#define USB3_EP_NAME_SIZE 8 3108c2ecf20Sopenharmony_cistruct renesas_usb3_ep { 3118c2ecf20Sopenharmony_ci struct usb_ep ep; 3128c2ecf20Sopenharmony_ci struct renesas_usb3 *usb3; 3138c2ecf20Sopenharmony_ci struct renesas_usb3_dma *dma; 3148c2ecf20Sopenharmony_ci int num; 3158c2ecf20Sopenharmony_ci char ep_name[USB3_EP_NAME_SIZE]; 3168c2ecf20Sopenharmony_ci struct list_head queue; 3178c2ecf20Sopenharmony_ci u32 rammap_val; 3188c2ecf20Sopenharmony_ci bool dir_in; 3198c2ecf20Sopenharmony_ci bool halt; 3208c2ecf20Sopenharmony_ci bool wedge; 3218c2ecf20Sopenharmony_ci bool started; 3228c2ecf20Sopenharmony_ci}; 3238c2ecf20Sopenharmony_ci 3248c2ecf20Sopenharmony_cistruct renesas_usb3_priv { 3258c2ecf20Sopenharmony_ci int ramsize_per_ramif; /* unit = bytes */ 3268c2ecf20Sopenharmony_ci int num_ramif; 3278c2ecf20Sopenharmony_ci int ramsize_per_pipe; /* unit = bytes */ 3288c2ecf20Sopenharmony_ci bool workaround_for_vbus; /* if true, don't check vbus signal */ 3298c2ecf20Sopenharmony_ci}; 3308c2ecf20Sopenharmony_ci 3318c2ecf20Sopenharmony_cistruct renesas_usb3 { 3328c2ecf20Sopenharmony_ci void __iomem *reg; 3338c2ecf20Sopenharmony_ci 3348c2ecf20Sopenharmony_ci struct usb_gadget gadget; 3358c2ecf20Sopenharmony_ci struct usb_gadget_driver *driver; 3368c2ecf20Sopenharmony_ci struct extcon_dev *extcon; 3378c2ecf20Sopenharmony_ci struct work_struct extcon_work; 3388c2ecf20Sopenharmony_ci struct phy *phy; 3398c2ecf20Sopenharmony_ci struct dentry *dentry; 3408c2ecf20Sopenharmony_ci 3418c2ecf20Sopenharmony_ci struct usb_role_switch *role_sw; 3428c2ecf20Sopenharmony_ci struct device *host_dev; 3438c2ecf20Sopenharmony_ci struct work_struct role_work; 3448c2ecf20Sopenharmony_ci enum usb_role role; 3458c2ecf20Sopenharmony_ci 3468c2ecf20Sopenharmony_ci struct renesas_usb3_ep *usb3_ep; 3478c2ecf20Sopenharmony_ci int num_usb3_eps; 3488c2ecf20Sopenharmony_ci 3498c2ecf20Sopenharmony_ci struct renesas_usb3_dma dma[USB3_DMA_NUM_SETTING_AREA]; 3508c2ecf20Sopenharmony_ci 3518c2ecf20Sopenharmony_ci spinlock_t lock; 3528c2ecf20Sopenharmony_ci int disabled_count; 3538c2ecf20Sopenharmony_ci 3548c2ecf20Sopenharmony_ci struct usb_request *ep0_req; 3558c2ecf20Sopenharmony_ci 3568c2ecf20Sopenharmony_ci enum usb_role connection_state; 3578c2ecf20Sopenharmony_ci u16 test_mode; 3588c2ecf20Sopenharmony_ci u8 ep0_buf[USB3_EP0_BUF_SIZE]; 3598c2ecf20Sopenharmony_ci bool softconnect; 3608c2ecf20Sopenharmony_ci bool workaround_for_vbus; 3618c2ecf20Sopenharmony_ci bool extcon_host; /* check id and set EXTCON_USB_HOST */ 3628c2ecf20Sopenharmony_ci bool extcon_usb; /* check vbus and set EXTCON_USB */ 3638c2ecf20Sopenharmony_ci bool forced_b_device; 3648c2ecf20Sopenharmony_ci bool start_to_connect; 3658c2ecf20Sopenharmony_ci bool role_sw_by_connector; 3668c2ecf20Sopenharmony_ci}; 3678c2ecf20Sopenharmony_ci 3688c2ecf20Sopenharmony_ci#define gadget_to_renesas_usb3(_gadget) \ 3698c2ecf20Sopenharmony_ci container_of(_gadget, struct renesas_usb3, gadget) 3708c2ecf20Sopenharmony_ci#define renesas_usb3_to_gadget(renesas_usb3) (&renesas_usb3->gadget) 3718c2ecf20Sopenharmony_ci#define usb3_to_dev(_usb3) (_usb3->gadget.dev.parent) 3728c2ecf20Sopenharmony_ci 3738c2ecf20Sopenharmony_ci#define usb_ep_to_usb3_ep(_ep) container_of(_ep, struct renesas_usb3_ep, ep) 3748c2ecf20Sopenharmony_ci#define usb3_ep_to_usb3(_usb3_ep) (_usb3_ep->usb3) 3758c2ecf20Sopenharmony_ci#define usb_req_to_usb3_req(_req) container_of(_req, \ 3768c2ecf20Sopenharmony_ci struct renesas_usb3_request, req) 3778c2ecf20Sopenharmony_ci 3788c2ecf20Sopenharmony_ci#define usb3_get_ep(usb3, n) ((usb3)->usb3_ep + (n)) 3798c2ecf20Sopenharmony_ci#define usb3_for_each_ep(usb3_ep, usb3, i) \ 3808c2ecf20Sopenharmony_ci for ((i) = 0, usb3_ep = usb3_get_ep(usb3, (i)); \ 3818c2ecf20Sopenharmony_ci (i) < (usb3)->num_usb3_eps; \ 3828c2ecf20Sopenharmony_ci (i)++, usb3_ep = usb3_get_ep(usb3, (i))) 3838c2ecf20Sopenharmony_ci 3848c2ecf20Sopenharmony_ci#define usb3_get_dma(usb3, i) (&(usb3)->dma[i]) 3858c2ecf20Sopenharmony_ci#define usb3_for_each_dma(usb3, dma, i) \ 3868c2ecf20Sopenharmony_ci for ((i) = 0, dma = usb3_get_dma((usb3), (i)); \ 3878c2ecf20Sopenharmony_ci (i) < USB3_DMA_NUM_SETTING_AREA; \ 3888c2ecf20Sopenharmony_ci (i)++, dma = usb3_get_dma((usb3), (i))) 3898c2ecf20Sopenharmony_ci 3908c2ecf20Sopenharmony_cistatic const char udc_name[] = "renesas_usb3"; 3918c2ecf20Sopenharmony_ci 3928c2ecf20Sopenharmony_cistatic bool use_dma = 1; 3938c2ecf20Sopenharmony_cimodule_param(use_dma, bool, 0644); 3948c2ecf20Sopenharmony_ciMODULE_PARM_DESC(use_dma, "use dedicated DMAC"); 3958c2ecf20Sopenharmony_ci 3968c2ecf20Sopenharmony_cistatic void usb3_write(struct renesas_usb3 *usb3, u32 data, u32 offs) 3978c2ecf20Sopenharmony_ci{ 3988c2ecf20Sopenharmony_ci iowrite32(data, usb3->reg + offs); 3998c2ecf20Sopenharmony_ci} 4008c2ecf20Sopenharmony_ci 4018c2ecf20Sopenharmony_cistatic u32 usb3_read(struct renesas_usb3 *usb3, u32 offs) 4028c2ecf20Sopenharmony_ci{ 4038c2ecf20Sopenharmony_ci return ioread32(usb3->reg + offs); 4048c2ecf20Sopenharmony_ci} 4058c2ecf20Sopenharmony_ci 4068c2ecf20Sopenharmony_cistatic void usb3_set_bit(struct renesas_usb3 *usb3, u32 bits, u32 offs) 4078c2ecf20Sopenharmony_ci{ 4088c2ecf20Sopenharmony_ci u32 val = usb3_read(usb3, offs); 4098c2ecf20Sopenharmony_ci 4108c2ecf20Sopenharmony_ci val |= bits; 4118c2ecf20Sopenharmony_ci usb3_write(usb3, val, offs); 4128c2ecf20Sopenharmony_ci} 4138c2ecf20Sopenharmony_ci 4148c2ecf20Sopenharmony_cistatic void usb3_clear_bit(struct renesas_usb3 *usb3, u32 bits, u32 offs) 4158c2ecf20Sopenharmony_ci{ 4168c2ecf20Sopenharmony_ci u32 val = usb3_read(usb3, offs); 4178c2ecf20Sopenharmony_ci 4188c2ecf20Sopenharmony_ci val &= ~bits; 4198c2ecf20Sopenharmony_ci usb3_write(usb3, val, offs); 4208c2ecf20Sopenharmony_ci} 4218c2ecf20Sopenharmony_ci 4228c2ecf20Sopenharmony_cistatic int usb3_wait(struct renesas_usb3 *usb3, u32 reg, u32 mask, 4238c2ecf20Sopenharmony_ci u32 expected) 4248c2ecf20Sopenharmony_ci{ 4258c2ecf20Sopenharmony_ci int i; 4268c2ecf20Sopenharmony_ci 4278c2ecf20Sopenharmony_ci for (i = 0; i < USB3_WAIT_US; i++) { 4288c2ecf20Sopenharmony_ci if ((usb3_read(usb3, reg) & mask) == expected) 4298c2ecf20Sopenharmony_ci return 0; 4308c2ecf20Sopenharmony_ci udelay(1); 4318c2ecf20Sopenharmony_ci } 4328c2ecf20Sopenharmony_ci 4338c2ecf20Sopenharmony_ci dev_dbg(usb3_to_dev(usb3), "%s: timed out (%8x, %08x, %08x)\n", 4348c2ecf20Sopenharmony_ci __func__, reg, mask, expected); 4358c2ecf20Sopenharmony_ci 4368c2ecf20Sopenharmony_ci return -EBUSY; 4378c2ecf20Sopenharmony_ci} 4388c2ecf20Sopenharmony_ci 4398c2ecf20Sopenharmony_cistatic void renesas_usb3_extcon_work(struct work_struct *work) 4408c2ecf20Sopenharmony_ci{ 4418c2ecf20Sopenharmony_ci struct renesas_usb3 *usb3 = container_of(work, struct renesas_usb3, 4428c2ecf20Sopenharmony_ci extcon_work); 4438c2ecf20Sopenharmony_ci 4448c2ecf20Sopenharmony_ci extcon_set_state_sync(usb3->extcon, EXTCON_USB_HOST, usb3->extcon_host); 4458c2ecf20Sopenharmony_ci extcon_set_state_sync(usb3->extcon, EXTCON_USB, usb3->extcon_usb); 4468c2ecf20Sopenharmony_ci} 4478c2ecf20Sopenharmony_ci 4488c2ecf20Sopenharmony_cistatic void usb3_enable_irq_1(struct renesas_usb3 *usb3, u32 bits) 4498c2ecf20Sopenharmony_ci{ 4508c2ecf20Sopenharmony_ci usb3_set_bit(usb3, bits, USB3_USB_INT_ENA_1); 4518c2ecf20Sopenharmony_ci} 4528c2ecf20Sopenharmony_ci 4538c2ecf20Sopenharmony_cistatic void usb3_disable_irq_1(struct renesas_usb3 *usb3, u32 bits) 4548c2ecf20Sopenharmony_ci{ 4558c2ecf20Sopenharmony_ci usb3_clear_bit(usb3, bits, USB3_USB_INT_ENA_1); 4568c2ecf20Sopenharmony_ci} 4578c2ecf20Sopenharmony_ci 4588c2ecf20Sopenharmony_cistatic void usb3_enable_pipe_irq(struct renesas_usb3 *usb3, int num) 4598c2ecf20Sopenharmony_ci{ 4608c2ecf20Sopenharmony_ci usb3_set_bit(usb3, USB_INT_2_PIPE(num), USB3_USB_INT_ENA_2); 4618c2ecf20Sopenharmony_ci} 4628c2ecf20Sopenharmony_ci 4638c2ecf20Sopenharmony_cistatic void usb3_disable_pipe_irq(struct renesas_usb3 *usb3, int num) 4648c2ecf20Sopenharmony_ci{ 4658c2ecf20Sopenharmony_ci usb3_clear_bit(usb3, USB_INT_2_PIPE(num), USB3_USB_INT_ENA_2); 4668c2ecf20Sopenharmony_ci} 4678c2ecf20Sopenharmony_ci 4688c2ecf20Sopenharmony_cistatic bool usb3_is_host(struct renesas_usb3 *usb3) 4698c2ecf20Sopenharmony_ci{ 4708c2ecf20Sopenharmony_ci return !(usb3_read(usb3, USB3_DRD_CON) & DRD_CON_PERI_CON); 4718c2ecf20Sopenharmony_ci} 4728c2ecf20Sopenharmony_ci 4738c2ecf20Sopenharmony_cistatic void usb3_init_axi_bridge(struct renesas_usb3 *usb3) 4748c2ecf20Sopenharmony_ci{ 4758c2ecf20Sopenharmony_ci /* Set AXI_INT */ 4768c2ecf20Sopenharmony_ci usb3_write(usb3, ~0, USB3_DMA_INT_STA); 4778c2ecf20Sopenharmony_ci usb3_write(usb3, 0, USB3_DMA_INT_ENA); 4788c2ecf20Sopenharmony_ci usb3_set_bit(usb3, AXI_INT_DMAINT | AXI_INT_EPCINT, USB3_AXI_INT_ENA); 4798c2ecf20Sopenharmony_ci} 4808c2ecf20Sopenharmony_ci 4818c2ecf20Sopenharmony_cistatic void usb3_init_epc_registers(struct renesas_usb3 *usb3) 4828c2ecf20Sopenharmony_ci{ 4838c2ecf20Sopenharmony_ci usb3_write(usb3, ~0, USB3_USB_INT_STA_1); 4848c2ecf20Sopenharmony_ci if (!usb3->workaround_for_vbus) 4858c2ecf20Sopenharmony_ci usb3_enable_irq_1(usb3, USB_INT_1_VBUS_CNG); 4868c2ecf20Sopenharmony_ci} 4878c2ecf20Sopenharmony_ci 4888c2ecf20Sopenharmony_cistatic bool usb3_wakeup_usb2_phy(struct renesas_usb3 *usb3) 4898c2ecf20Sopenharmony_ci{ 4908c2ecf20Sopenharmony_ci if (!(usb3_read(usb3, USB3_USB20_CON) & USB20_CON_B2_SUSPEND)) 4918c2ecf20Sopenharmony_ci return true; /* already waked it up */ 4928c2ecf20Sopenharmony_ci 4938c2ecf20Sopenharmony_ci usb3_clear_bit(usb3, USB20_CON_B2_SUSPEND, USB3_USB20_CON); 4948c2ecf20Sopenharmony_ci usb3_enable_irq_1(usb3, USB_INT_1_B2_RSUM); 4958c2ecf20Sopenharmony_ci 4968c2ecf20Sopenharmony_ci return false; 4978c2ecf20Sopenharmony_ci} 4988c2ecf20Sopenharmony_ci 4998c2ecf20Sopenharmony_cistatic void usb3_usb2_pullup(struct renesas_usb3 *usb3, int pullup) 5008c2ecf20Sopenharmony_ci{ 5018c2ecf20Sopenharmony_ci u32 bits = USB20_CON_B2_PUE | USB20_CON_B2_CONNECT; 5028c2ecf20Sopenharmony_ci 5038c2ecf20Sopenharmony_ci if (usb3->softconnect && pullup) 5048c2ecf20Sopenharmony_ci usb3_set_bit(usb3, bits, USB3_USB20_CON); 5058c2ecf20Sopenharmony_ci else 5068c2ecf20Sopenharmony_ci usb3_clear_bit(usb3, bits, USB3_USB20_CON); 5078c2ecf20Sopenharmony_ci} 5088c2ecf20Sopenharmony_ci 5098c2ecf20Sopenharmony_cistatic void usb3_set_test_mode(struct renesas_usb3 *usb3) 5108c2ecf20Sopenharmony_ci{ 5118c2ecf20Sopenharmony_ci u32 val = usb3_read(usb3, USB3_USB20_CON); 5128c2ecf20Sopenharmony_ci 5138c2ecf20Sopenharmony_ci val &= ~USB20_CON_B2_TSTMOD_MASK; 5148c2ecf20Sopenharmony_ci val |= USB20_CON_B2_TSTMOD(usb3->test_mode); 5158c2ecf20Sopenharmony_ci usb3_write(usb3, val | USB20_CON_B2_TSTMOD_EN, USB3_USB20_CON); 5168c2ecf20Sopenharmony_ci if (!usb3->test_mode) 5178c2ecf20Sopenharmony_ci usb3_clear_bit(usb3, USB20_CON_B2_TSTMOD_EN, USB3_USB20_CON); 5188c2ecf20Sopenharmony_ci} 5198c2ecf20Sopenharmony_ci 5208c2ecf20Sopenharmony_cistatic void usb3_start_usb2_connection(struct renesas_usb3 *usb3) 5218c2ecf20Sopenharmony_ci{ 5228c2ecf20Sopenharmony_ci usb3->disabled_count++; 5238c2ecf20Sopenharmony_ci usb3_set_bit(usb3, USB_COM_CON_EP0_EN, USB3_USB_COM_CON); 5248c2ecf20Sopenharmony_ci usb3_set_bit(usb3, USB_COM_CON_SPD_MODE, USB3_USB_COM_CON); 5258c2ecf20Sopenharmony_ci usb3_usb2_pullup(usb3, 1); 5268c2ecf20Sopenharmony_ci} 5278c2ecf20Sopenharmony_ci 5288c2ecf20Sopenharmony_cistatic int usb3_is_usb3_phy_in_u3(struct renesas_usb3 *usb3) 5298c2ecf20Sopenharmony_ci{ 5308c2ecf20Sopenharmony_ci return usb3_read(usb3, USB3_USB30_CON) & USB30_CON_POW_SEL_IN_U3; 5318c2ecf20Sopenharmony_ci} 5328c2ecf20Sopenharmony_ci 5338c2ecf20Sopenharmony_cistatic bool usb3_wakeup_usb3_phy(struct renesas_usb3 *usb3) 5348c2ecf20Sopenharmony_ci{ 5358c2ecf20Sopenharmony_ci if (!usb3_is_usb3_phy_in_u3(usb3)) 5368c2ecf20Sopenharmony_ci return true; /* already waked it up */ 5378c2ecf20Sopenharmony_ci 5388c2ecf20Sopenharmony_ci usb3_set_bit(usb3, USB30_CON_B3_PLLWAKE, USB3_USB30_CON); 5398c2ecf20Sopenharmony_ci usb3_enable_irq_1(usb3, USB_INT_1_B3_PLLWKUP); 5408c2ecf20Sopenharmony_ci 5418c2ecf20Sopenharmony_ci return false; 5428c2ecf20Sopenharmony_ci} 5438c2ecf20Sopenharmony_ci 5448c2ecf20Sopenharmony_cistatic u16 usb3_feature_get_un_enabled(struct renesas_usb3 *usb3) 5458c2ecf20Sopenharmony_ci{ 5468c2ecf20Sopenharmony_ci u32 mask_u2 = SSIFCMD_UDIR_U2 | SSIFCMD_UREQ_U2; 5478c2ecf20Sopenharmony_ci u32 mask_u1 = SSIFCMD_UDIR_U1 | SSIFCMD_UREQ_U1; 5488c2ecf20Sopenharmony_ci u32 val = usb3_read(usb3, USB3_SSIFCMD); 5498c2ecf20Sopenharmony_ci u16 ret = 0; 5508c2ecf20Sopenharmony_ci 5518c2ecf20Sopenharmony_ci /* Enables {U2,U1} if the bits of UDIR and UREQ are set to 0 */ 5528c2ecf20Sopenharmony_ci if (!(val & mask_u2)) 5538c2ecf20Sopenharmony_ci ret |= 1 << USB_DEV_STAT_U2_ENABLED; 5548c2ecf20Sopenharmony_ci if (!(val & mask_u1)) 5558c2ecf20Sopenharmony_ci ret |= 1 << USB_DEV_STAT_U1_ENABLED; 5568c2ecf20Sopenharmony_ci 5578c2ecf20Sopenharmony_ci return ret; 5588c2ecf20Sopenharmony_ci} 5598c2ecf20Sopenharmony_ci 5608c2ecf20Sopenharmony_cistatic void usb3_feature_u2_enable(struct renesas_usb3 *usb3, bool enable) 5618c2ecf20Sopenharmony_ci{ 5628c2ecf20Sopenharmony_ci u32 bits = SSIFCMD_UDIR_U2 | SSIFCMD_UREQ_U2; 5638c2ecf20Sopenharmony_ci 5648c2ecf20Sopenharmony_ci /* Enables U2 if the bits of UDIR and UREQ are set to 0 */ 5658c2ecf20Sopenharmony_ci if (enable) 5668c2ecf20Sopenharmony_ci usb3_clear_bit(usb3, bits, USB3_SSIFCMD); 5678c2ecf20Sopenharmony_ci else 5688c2ecf20Sopenharmony_ci usb3_set_bit(usb3, bits, USB3_SSIFCMD); 5698c2ecf20Sopenharmony_ci} 5708c2ecf20Sopenharmony_ci 5718c2ecf20Sopenharmony_cistatic void usb3_feature_u1_enable(struct renesas_usb3 *usb3, bool enable) 5728c2ecf20Sopenharmony_ci{ 5738c2ecf20Sopenharmony_ci u32 bits = SSIFCMD_UDIR_U1 | SSIFCMD_UREQ_U1; 5748c2ecf20Sopenharmony_ci 5758c2ecf20Sopenharmony_ci /* Enables U1 if the bits of UDIR and UREQ are set to 0 */ 5768c2ecf20Sopenharmony_ci if (enable) 5778c2ecf20Sopenharmony_ci usb3_clear_bit(usb3, bits, USB3_SSIFCMD); 5788c2ecf20Sopenharmony_ci else 5798c2ecf20Sopenharmony_ci usb3_set_bit(usb3, bits, USB3_SSIFCMD); 5808c2ecf20Sopenharmony_ci} 5818c2ecf20Sopenharmony_ci 5828c2ecf20Sopenharmony_cistatic void usb3_start_operation_for_usb3(struct renesas_usb3 *usb3) 5838c2ecf20Sopenharmony_ci{ 5848c2ecf20Sopenharmony_ci usb3_set_bit(usb3, USB_COM_CON_EP0_EN, USB3_USB_COM_CON); 5858c2ecf20Sopenharmony_ci usb3_clear_bit(usb3, USB_COM_CON_SPD_MODE, USB3_USB_COM_CON); 5868c2ecf20Sopenharmony_ci usb3_set_bit(usb3, USB30_CON_B3_CONNECT, USB3_USB30_CON); 5878c2ecf20Sopenharmony_ci} 5888c2ecf20Sopenharmony_ci 5898c2ecf20Sopenharmony_cistatic void usb3_start_usb3_connection(struct renesas_usb3 *usb3) 5908c2ecf20Sopenharmony_ci{ 5918c2ecf20Sopenharmony_ci usb3_start_operation_for_usb3(usb3); 5928c2ecf20Sopenharmony_ci usb3_set_bit(usb3, USB_COM_CON_RX_DETECTION, USB3_USB_COM_CON); 5938c2ecf20Sopenharmony_ci 5948c2ecf20Sopenharmony_ci usb3_enable_irq_1(usb3, USB_INT_1_B3_LUPSUCS | USB_INT_1_B3_DISABLE | 5958c2ecf20Sopenharmony_ci USB_INT_1_SPEED); 5968c2ecf20Sopenharmony_ci} 5978c2ecf20Sopenharmony_ci 5988c2ecf20Sopenharmony_cistatic void usb3_stop_usb3_connection(struct renesas_usb3 *usb3) 5998c2ecf20Sopenharmony_ci{ 6008c2ecf20Sopenharmony_ci usb3_clear_bit(usb3, USB30_CON_B3_CONNECT, USB3_USB30_CON); 6018c2ecf20Sopenharmony_ci} 6028c2ecf20Sopenharmony_ci 6038c2ecf20Sopenharmony_cistatic void usb3_transition_to_default_state(struct renesas_usb3 *usb3, 6048c2ecf20Sopenharmony_ci bool is_usb3) 6058c2ecf20Sopenharmony_ci{ 6068c2ecf20Sopenharmony_ci usb3_set_bit(usb3, USB_INT_2_PIPE(0), USB3_USB_INT_ENA_2); 6078c2ecf20Sopenharmony_ci usb3_write(usb3, P0_INT_ALL_BITS, USB3_P0_INT_STA); 6088c2ecf20Sopenharmony_ci usb3_set_bit(usb3, P0_INT_ALL_BITS, USB3_P0_INT_ENA); 6098c2ecf20Sopenharmony_ci 6108c2ecf20Sopenharmony_ci if (is_usb3) 6118c2ecf20Sopenharmony_ci usb3_enable_irq_1(usb3, USB_INT_1_B3_WRMRST | 6128c2ecf20Sopenharmony_ci USB_INT_1_B3_HOTRST); 6138c2ecf20Sopenharmony_ci else 6148c2ecf20Sopenharmony_ci usb3_enable_irq_1(usb3, USB_INT_1_B2_SPND | 6158c2ecf20Sopenharmony_ci USB_INT_1_B2_L1SPND | USB_INT_1_B2_USBRST); 6168c2ecf20Sopenharmony_ci} 6178c2ecf20Sopenharmony_ci 6188c2ecf20Sopenharmony_cistatic void usb3_connect(struct renesas_usb3 *usb3) 6198c2ecf20Sopenharmony_ci{ 6208c2ecf20Sopenharmony_ci if (usb3_wakeup_usb3_phy(usb3)) 6218c2ecf20Sopenharmony_ci usb3_start_usb3_connection(usb3); 6228c2ecf20Sopenharmony_ci} 6238c2ecf20Sopenharmony_ci 6248c2ecf20Sopenharmony_cistatic void usb3_reset_epc(struct renesas_usb3 *usb3) 6258c2ecf20Sopenharmony_ci{ 6268c2ecf20Sopenharmony_ci usb3_clear_bit(usb3, USB_COM_CON_CONF, USB3_USB_COM_CON); 6278c2ecf20Sopenharmony_ci usb3_clear_bit(usb3, USB_COM_CON_EP0_EN, USB3_USB_COM_CON); 6288c2ecf20Sopenharmony_ci usb3_set_bit(usb3, USB_COM_CON_PIPE_CLR, USB3_USB_COM_CON); 6298c2ecf20Sopenharmony_ci usb3->test_mode = 0; 6308c2ecf20Sopenharmony_ci usb3_set_test_mode(usb3); 6318c2ecf20Sopenharmony_ci} 6328c2ecf20Sopenharmony_ci 6338c2ecf20Sopenharmony_cistatic void usb3_disconnect(struct renesas_usb3 *usb3) 6348c2ecf20Sopenharmony_ci{ 6358c2ecf20Sopenharmony_ci usb3->disabled_count = 0; 6368c2ecf20Sopenharmony_ci usb3_usb2_pullup(usb3, 0); 6378c2ecf20Sopenharmony_ci usb3_clear_bit(usb3, USB30_CON_B3_CONNECT, USB3_USB30_CON); 6388c2ecf20Sopenharmony_ci usb3_reset_epc(usb3); 6398c2ecf20Sopenharmony_ci usb3_disable_irq_1(usb3, USB_INT_1_B2_RSUM | USB_INT_1_B3_PLLWKUP | 6408c2ecf20Sopenharmony_ci USB_INT_1_B3_LUPSUCS | USB_INT_1_B3_DISABLE | 6418c2ecf20Sopenharmony_ci USB_INT_1_SPEED | USB_INT_1_B3_WRMRST | 6428c2ecf20Sopenharmony_ci USB_INT_1_B3_HOTRST | USB_INT_1_B2_SPND | 6438c2ecf20Sopenharmony_ci USB_INT_1_B2_L1SPND | USB_INT_1_B2_USBRST); 6448c2ecf20Sopenharmony_ci usb3_clear_bit(usb3, USB_COM_CON_SPD_MODE, USB3_USB_COM_CON); 6458c2ecf20Sopenharmony_ci usb3_init_epc_registers(usb3); 6468c2ecf20Sopenharmony_ci 6478c2ecf20Sopenharmony_ci if (usb3->driver) 6488c2ecf20Sopenharmony_ci usb3->driver->disconnect(&usb3->gadget); 6498c2ecf20Sopenharmony_ci} 6508c2ecf20Sopenharmony_ci 6518c2ecf20Sopenharmony_cistatic void usb3_check_vbus(struct renesas_usb3 *usb3) 6528c2ecf20Sopenharmony_ci{ 6538c2ecf20Sopenharmony_ci if (usb3->workaround_for_vbus) { 6548c2ecf20Sopenharmony_ci usb3_connect(usb3); 6558c2ecf20Sopenharmony_ci } else { 6568c2ecf20Sopenharmony_ci usb3->extcon_usb = !!(usb3_read(usb3, USB3_USB_STA) & 6578c2ecf20Sopenharmony_ci USB_STA_VBUS_STA); 6588c2ecf20Sopenharmony_ci if (usb3->extcon_usb) 6598c2ecf20Sopenharmony_ci usb3_connect(usb3); 6608c2ecf20Sopenharmony_ci else 6618c2ecf20Sopenharmony_ci usb3_disconnect(usb3); 6628c2ecf20Sopenharmony_ci 6638c2ecf20Sopenharmony_ci schedule_work(&usb3->extcon_work); 6648c2ecf20Sopenharmony_ci } 6658c2ecf20Sopenharmony_ci} 6668c2ecf20Sopenharmony_ci 6678c2ecf20Sopenharmony_cistatic void renesas_usb3_role_work(struct work_struct *work) 6688c2ecf20Sopenharmony_ci{ 6698c2ecf20Sopenharmony_ci struct renesas_usb3 *usb3 = 6708c2ecf20Sopenharmony_ci container_of(work, struct renesas_usb3, role_work); 6718c2ecf20Sopenharmony_ci 6728c2ecf20Sopenharmony_ci usb_role_switch_set_role(usb3->role_sw, usb3->role); 6738c2ecf20Sopenharmony_ci} 6748c2ecf20Sopenharmony_ci 6758c2ecf20Sopenharmony_cistatic void usb3_set_mode(struct renesas_usb3 *usb3, bool host) 6768c2ecf20Sopenharmony_ci{ 6778c2ecf20Sopenharmony_ci if (host) 6788c2ecf20Sopenharmony_ci usb3_clear_bit(usb3, DRD_CON_PERI_CON, USB3_DRD_CON); 6798c2ecf20Sopenharmony_ci else 6808c2ecf20Sopenharmony_ci usb3_set_bit(usb3, DRD_CON_PERI_CON, USB3_DRD_CON); 6818c2ecf20Sopenharmony_ci} 6828c2ecf20Sopenharmony_ci 6838c2ecf20Sopenharmony_cistatic void usb3_set_mode_by_role_sw(struct renesas_usb3 *usb3, bool host) 6848c2ecf20Sopenharmony_ci{ 6858c2ecf20Sopenharmony_ci if (usb3->role_sw) { 6868c2ecf20Sopenharmony_ci usb3->role = host ? USB_ROLE_HOST : USB_ROLE_DEVICE; 6878c2ecf20Sopenharmony_ci schedule_work(&usb3->role_work); 6888c2ecf20Sopenharmony_ci } else { 6898c2ecf20Sopenharmony_ci usb3_set_mode(usb3, host); 6908c2ecf20Sopenharmony_ci } 6918c2ecf20Sopenharmony_ci} 6928c2ecf20Sopenharmony_ci 6938c2ecf20Sopenharmony_cistatic void usb3_vbus_out(struct renesas_usb3 *usb3, bool enable) 6948c2ecf20Sopenharmony_ci{ 6958c2ecf20Sopenharmony_ci if (enable) 6968c2ecf20Sopenharmony_ci usb3_set_bit(usb3, DRD_CON_VBOUT, USB3_DRD_CON); 6978c2ecf20Sopenharmony_ci else 6988c2ecf20Sopenharmony_ci usb3_clear_bit(usb3, DRD_CON_VBOUT, USB3_DRD_CON); 6998c2ecf20Sopenharmony_ci} 7008c2ecf20Sopenharmony_ci 7018c2ecf20Sopenharmony_cistatic void usb3_mode_config(struct renesas_usb3 *usb3, bool host, bool a_dev) 7028c2ecf20Sopenharmony_ci{ 7038c2ecf20Sopenharmony_ci unsigned long flags; 7048c2ecf20Sopenharmony_ci 7058c2ecf20Sopenharmony_ci spin_lock_irqsave(&usb3->lock, flags); 7068c2ecf20Sopenharmony_ci if (!usb3->role_sw_by_connector || 7078c2ecf20Sopenharmony_ci usb3->connection_state != USB_ROLE_NONE) { 7088c2ecf20Sopenharmony_ci usb3_set_mode_by_role_sw(usb3, host); 7098c2ecf20Sopenharmony_ci usb3_vbus_out(usb3, a_dev); 7108c2ecf20Sopenharmony_ci } 7118c2ecf20Sopenharmony_ci /* for A-Peripheral or forced B-device mode */ 7128c2ecf20Sopenharmony_ci if ((!host && a_dev) || usb3->start_to_connect) 7138c2ecf20Sopenharmony_ci usb3_connect(usb3); 7148c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&usb3->lock, flags); 7158c2ecf20Sopenharmony_ci} 7168c2ecf20Sopenharmony_ci 7178c2ecf20Sopenharmony_cistatic bool usb3_is_a_device(struct renesas_usb3 *usb3) 7188c2ecf20Sopenharmony_ci{ 7198c2ecf20Sopenharmony_ci return !(usb3_read(usb3, USB3_USB_OTG_STA) & USB_OTG_IDMON); 7208c2ecf20Sopenharmony_ci} 7218c2ecf20Sopenharmony_ci 7228c2ecf20Sopenharmony_cistatic void usb3_check_id(struct renesas_usb3 *usb3) 7238c2ecf20Sopenharmony_ci{ 7248c2ecf20Sopenharmony_ci usb3->extcon_host = usb3_is_a_device(usb3); 7258c2ecf20Sopenharmony_ci 7268c2ecf20Sopenharmony_ci if ((!usb3->role_sw_by_connector && usb3->extcon_host && 7278c2ecf20Sopenharmony_ci !usb3->forced_b_device) || usb3->connection_state == USB_ROLE_HOST) 7288c2ecf20Sopenharmony_ci usb3_mode_config(usb3, true, true); 7298c2ecf20Sopenharmony_ci else 7308c2ecf20Sopenharmony_ci usb3_mode_config(usb3, false, false); 7318c2ecf20Sopenharmony_ci 7328c2ecf20Sopenharmony_ci schedule_work(&usb3->extcon_work); 7338c2ecf20Sopenharmony_ci} 7348c2ecf20Sopenharmony_ci 7358c2ecf20Sopenharmony_cistatic void renesas_usb3_init_controller(struct renesas_usb3 *usb3) 7368c2ecf20Sopenharmony_ci{ 7378c2ecf20Sopenharmony_ci usb3_init_axi_bridge(usb3); 7388c2ecf20Sopenharmony_ci usb3_init_epc_registers(usb3); 7398c2ecf20Sopenharmony_ci usb3_set_bit(usb3, USB_COM_CON_PN_WDATAIF_NL | 7408c2ecf20Sopenharmony_ci USB_COM_CON_PN_RDATAIF_NL | USB_COM_CON_PN_LSTTR_PP, 7418c2ecf20Sopenharmony_ci USB3_USB_COM_CON); 7428c2ecf20Sopenharmony_ci usb3_write(usb3, USB_OTG_IDMON, USB3_USB_OTG_INT_STA); 7438c2ecf20Sopenharmony_ci usb3_write(usb3, USB_OTG_IDMON, USB3_USB_OTG_INT_ENA); 7448c2ecf20Sopenharmony_ci 7458c2ecf20Sopenharmony_ci usb3_check_id(usb3); 7468c2ecf20Sopenharmony_ci usb3_check_vbus(usb3); 7478c2ecf20Sopenharmony_ci} 7488c2ecf20Sopenharmony_ci 7498c2ecf20Sopenharmony_cistatic void renesas_usb3_stop_controller(struct renesas_usb3 *usb3) 7508c2ecf20Sopenharmony_ci{ 7518c2ecf20Sopenharmony_ci usb3_disconnect(usb3); 7528c2ecf20Sopenharmony_ci usb3_write(usb3, 0, USB3_P0_INT_ENA); 7538c2ecf20Sopenharmony_ci usb3_write(usb3, 0, USB3_USB_OTG_INT_ENA); 7548c2ecf20Sopenharmony_ci usb3_write(usb3, 0, USB3_USB_INT_ENA_1); 7558c2ecf20Sopenharmony_ci usb3_write(usb3, 0, USB3_USB_INT_ENA_2); 7568c2ecf20Sopenharmony_ci usb3_write(usb3, 0, USB3_AXI_INT_ENA); 7578c2ecf20Sopenharmony_ci} 7588c2ecf20Sopenharmony_ci 7598c2ecf20Sopenharmony_cistatic void usb3_irq_epc_int_1_pll_wakeup(struct renesas_usb3 *usb3) 7608c2ecf20Sopenharmony_ci{ 7618c2ecf20Sopenharmony_ci usb3_disable_irq_1(usb3, USB_INT_1_B3_PLLWKUP); 7628c2ecf20Sopenharmony_ci usb3_clear_bit(usb3, USB30_CON_B3_PLLWAKE, USB3_USB30_CON); 7638c2ecf20Sopenharmony_ci usb3_start_usb3_connection(usb3); 7648c2ecf20Sopenharmony_ci} 7658c2ecf20Sopenharmony_ci 7668c2ecf20Sopenharmony_cistatic void usb3_irq_epc_int_1_linkup_success(struct renesas_usb3 *usb3) 7678c2ecf20Sopenharmony_ci{ 7688c2ecf20Sopenharmony_ci usb3_transition_to_default_state(usb3, true); 7698c2ecf20Sopenharmony_ci} 7708c2ecf20Sopenharmony_ci 7718c2ecf20Sopenharmony_cistatic void usb3_irq_epc_int_1_resume(struct renesas_usb3 *usb3) 7728c2ecf20Sopenharmony_ci{ 7738c2ecf20Sopenharmony_ci usb3_disable_irq_1(usb3, USB_INT_1_B2_RSUM); 7748c2ecf20Sopenharmony_ci usb3_start_usb2_connection(usb3); 7758c2ecf20Sopenharmony_ci usb3_transition_to_default_state(usb3, false); 7768c2ecf20Sopenharmony_ci} 7778c2ecf20Sopenharmony_ci 7788c2ecf20Sopenharmony_cistatic void usb3_irq_epc_int_1_suspend(struct renesas_usb3 *usb3) 7798c2ecf20Sopenharmony_ci{ 7808c2ecf20Sopenharmony_ci usb3_disable_irq_1(usb3, USB_INT_1_B2_SPND); 7818c2ecf20Sopenharmony_ci 7828c2ecf20Sopenharmony_ci if (usb3->gadget.speed != USB_SPEED_UNKNOWN && 7838c2ecf20Sopenharmony_ci usb3->gadget.state != USB_STATE_NOTATTACHED) { 7848c2ecf20Sopenharmony_ci if (usb3->driver && usb3->driver->suspend) 7858c2ecf20Sopenharmony_ci usb3->driver->suspend(&usb3->gadget); 7868c2ecf20Sopenharmony_ci usb_gadget_set_state(&usb3->gadget, USB_STATE_SUSPENDED); 7878c2ecf20Sopenharmony_ci } 7888c2ecf20Sopenharmony_ci} 7898c2ecf20Sopenharmony_ci 7908c2ecf20Sopenharmony_cistatic void usb3_irq_epc_int_1_disable(struct renesas_usb3 *usb3) 7918c2ecf20Sopenharmony_ci{ 7928c2ecf20Sopenharmony_ci usb3_stop_usb3_connection(usb3); 7938c2ecf20Sopenharmony_ci if (usb3_wakeup_usb2_phy(usb3)) 7948c2ecf20Sopenharmony_ci usb3_irq_epc_int_1_resume(usb3); 7958c2ecf20Sopenharmony_ci} 7968c2ecf20Sopenharmony_ci 7978c2ecf20Sopenharmony_cistatic void usb3_irq_epc_int_1_bus_reset(struct renesas_usb3 *usb3) 7988c2ecf20Sopenharmony_ci{ 7998c2ecf20Sopenharmony_ci usb3_reset_epc(usb3); 8008c2ecf20Sopenharmony_ci if (usb3->disabled_count < 3) 8018c2ecf20Sopenharmony_ci usb3_start_usb3_connection(usb3); 8028c2ecf20Sopenharmony_ci else 8038c2ecf20Sopenharmony_ci usb3_start_usb2_connection(usb3); 8048c2ecf20Sopenharmony_ci} 8058c2ecf20Sopenharmony_ci 8068c2ecf20Sopenharmony_cistatic void usb3_irq_epc_int_1_vbus_change(struct renesas_usb3 *usb3) 8078c2ecf20Sopenharmony_ci{ 8088c2ecf20Sopenharmony_ci usb3_check_vbus(usb3); 8098c2ecf20Sopenharmony_ci} 8108c2ecf20Sopenharmony_ci 8118c2ecf20Sopenharmony_cistatic void usb3_irq_epc_int_1_hot_reset(struct renesas_usb3 *usb3) 8128c2ecf20Sopenharmony_ci{ 8138c2ecf20Sopenharmony_ci usb3_reset_epc(usb3); 8148c2ecf20Sopenharmony_ci usb3_set_bit(usb3, USB_COM_CON_EP0_EN, USB3_USB_COM_CON); 8158c2ecf20Sopenharmony_ci 8168c2ecf20Sopenharmony_ci /* This bit shall be set within 12ms from the start of HotReset */ 8178c2ecf20Sopenharmony_ci usb3_set_bit(usb3, USB30_CON_B3_HOTRST_CMP, USB3_USB30_CON); 8188c2ecf20Sopenharmony_ci} 8198c2ecf20Sopenharmony_ci 8208c2ecf20Sopenharmony_cistatic void usb3_irq_epc_int_1_warm_reset(struct renesas_usb3 *usb3) 8218c2ecf20Sopenharmony_ci{ 8228c2ecf20Sopenharmony_ci usb3_reset_epc(usb3); 8238c2ecf20Sopenharmony_ci usb3_set_bit(usb3, USB_COM_CON_EP0_EN, USB3_USB_COM_CON); 8248c2ecf20Sopenharmony_ci 8258c2ecf20Sopenharmony_ci usb3_start_operation_for_usb3(usb3); 8268c2ecf20Sopenharmony_ci usb3_enable_irq_1(usb3, USB_INT_1_SPEED); 8278c2ecf20Sopenharmony_ci} 8288c2ecf20Sopenharmony_ci 8298c2ecf20Sopenharmony_cistatic void usb3_irq_epc_int_1_speed(struct renesas_usb3 *usb3) 8308c2ecf20Sopenharmony_ci{ 8318c2ecf20Sopenharmony_ci u32 speed = usb3_read(usb3, USB3_USB_STA) & USB_STA_SPEED_MASK; 8328c2ecf20Sopenharmony_ci 8338c2ecf20Sopenharmony_ci switch (speed) { 8348c2ecf20Sopenharmony_ci case USB_STA_SPEED_SS: 8358c2ecf20Sopenharmony_ci usb3->gadget.speed = USB_SPEED_SUPER; 8368c2ecf20Sopenharmony_ci usb3->gadget.ep0->maxpacket = USB3_EP0_SS_MAX_PACKET_SIZE; 8378c2ecf20Sopenharmony_ci break; 8388c2ecf20Sopenharmony_ci case USB_STA_SPEED_HS: 8398c2ecf20Sopenharmony_ci usb3->gadget.speed = USB_SPEED_HIGH; 8408c2ecf20Sopenharmony_ci usb3->gadget.ep0->maxpacket = USB3_EP0_HSFS_MAX_PACKET_SIZE; 8418c2ecf20Sopenharmony_ci break; 8428c2ecf20Sopenharmony_ci case USB_STA_SPEED_FS: 8438c2ecf20Sopenharmony_ci usb3->gadget.speed = USB_SPEED_FULL; 8448c2ecf20Sopenharmony_ci usb3->gadget.ep0->maxpacket = USB3_EP0_HSFS_MAX_PACKET_SIZE; 8458c2ecf20Sopenharmony_ci break; 8468c2ecf20Sopenharmony_ci default: 8478c2ecf20Sopenharmony_ci usb3->gadget.speed = USB_SPEED_UNKNOWN; 8488c2ecf20Sopenharmony_ci break; 8498c2ecf20Sopenharmony_ci } 8508c2ecf20Sopenharmony_ci} 8518c2ecf20Sopenharmony_ci 8528c2ecf20Sopenharmony_cistatic void usb3_irq_epc_int_1(struct renesas_usb3 *usb3, u32 int_sta_1) 8538c2ecf20Sopenharmony_ci{ 8548c2ecf20Sopenharmony_ci if (int_sta_1 & USB_INT_1_B3_PLLWKUP) 8558c2ecf20Sopenharmony_ci usb3_irq_epc_int_1_pll_wakeup(usb3); 8568c2ecf20Sopenharmony_ci 8578c2ecf20Sopenharmony_ci if (int_sta_1 & USB_INT_1_B3_LUPSUCS) 8588c2ecf20Sopenharmony_ci usb3_irq_epc_int_1_linkup_success(usb3); 8598c2ecf20Sopenharmony_ci 8608c2ecf20Sopenharmony_ci if (int_sta_1 & USB_INT_1_B3_HOTRST) 8618c2ecf20Sopenharmony_ci usb3_irq_epc_int_1_hot_reset(usb3); 8628c2ecf20Sopenharmony_ci 8638c2ecf20Sopenharmony_ci if (int_sta_1 & USB_INT_1_B3_WRMRST) 8648c2ecf20Sopenharmony_ci usb3_irq_epc_int_1_warm_reset(usb3); 8658c2ecf20Sopenharmony_ci 8668c2ecf20Sopenharmony_ci if (int_sta_1 & USB_INT_1_B3_DISABLE) 8678c2ecf20Sopenharmony_ci usb3_irq_epc_int_1_disable(usb3); 8688c2ecf20Sopenharmony_ci 8698c2ecf20Sopenharmony_ci if (int_sta_1 & USB_INT_1_B2_USBRST) 8708c2ecf20Sopenharmony_ci usb3_irq_epc_int_1_bus_reset(usb3); 8718c2ecf20Sopenharmony_ci 8728c2ecf20Sopenharmony_ci if (int_sta_1 & USB_INT_1_B2_RSUM) 8738c2ecf20Sopenharmony_ci usb3_irq_epc_int_1_resume(usb3); 8748c2ecf20Sopenharmony_ci 8758c2ecf20Sopenharmony_ci if (int_sta_1 & USB_INT_1_B2_SPND) 8768c2ecf20Sopenharmony_ci usb3_irq_epc_int_1_suspend(usb3); 8778c2ecf20Sopenharmony_ci 8788c2ecf20Sopenharmony_ci if (int_sta_1 & USB_INT_1_SPEED) 8798c2ecf20Sopenharmony_ci usb3_irq_epc_int_1_speed(usb3); 8808c2ecf20Sopenharmony_ci 8818c2ecf20Sopenharmony_ci if (int_sta_1 & USB_INT_1_VBUS_CNG) 8828c2ecf20Sopenharmony_ci usb3_irq_epc_int_1_vbus_change(usb3); 8838c2ecf20Sopenharmony_ci} 8848c2ecf20Sopenharmony_ci 8858c2ecf20Sopenharmony_cistatic struct renesas_usb3_request *__usb3_get_request(struct renesas_usb3_ep 8868c2ecf20Sopenharmony_ci *usb3_ep) 8878c2ecf20Sopenharmony_ci{ 8888c2ecf20Sopenharmony_ci return list_first_entry_or_null(&usb3_ep->queue, 8898c2ecf20Sopenharmony_ci struct renesas_usb3_request, queue); 8908c2ecf20Sopenharmony_ci} 8918c2ecf20Sopenharmony_ci 8928c2ecf20Sopenharmony_cistatic struct renesas_usb3_request *usb3_get_request(struct renesas_usb3_ep 8938c2ecf20Sopenharmony_ci *usb3_ep) 8948c2ecf20Sopenharmony_ci{ 8958c2ecf20Sopenharmony_ci struct renesas_usb3 *usb3 = usb3_ep_to_usb3(usb3_ep); 8968c2ecf20Sopenharmony_ci struct renesas_usb3_request *usb3_req; 8978c2ecf20Sopenharmony_ci unsigned long flags; 8988c2ecf20Sopenharmony_ci 8998c2ecf20Sopenharmony_ci spin_lock_irqsave(&usb3->lock, flags); 9008c2ecf20Sopenharmony_ci usb3_req = __usb3_get_request(usb3_ep); 9018c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&usb3->lock, flags); 9028c2ecf20Sopenharmony_ci 9038c2ecf20Sopenharmony_ci return usb3_req; 9048c2ecf20Sopenharmony_ci} 9058c2ecf20Sopenharmony_ci 9068c2ecf20Sopenharmony_cistatic void __usb3_request_done(struct renesas_usb3_ep *usb3_ep, 9078c2ecf20Sopenharmony_ci struct renesas_usb3_request *usb3_req, 9088c2ecf20Sopenharmony_ci int status) 9098c2ecf20Sopenharmony_ci{ 9108c2ecf20Sopenharmony_ci struct renesas_usb3 *usb3 = usb3_ep_to_usb3(usb3_ep); 9118c2ecf20Sopenharmony_ci 9128c2ecf20Sopenharmony_ci dev_dbg(usb3_to_dev(usb3), "giveback: ep%2d, %u, %u, %d\n", 9138c2ecf20Sopenharmony_ci usb3_ep->num, usb3_req->req.length, usb3_req->req.actual, 9148c2ecf20Sopenharmony_ci status); 9158c2ecf20Sopenharmony_ci usb3_req->req.status = status; 9168c2ecf20Sopenharmony_ci usb3_ep->started = false; 9178c2ecf20Sopenharmony_ci list_del_init(&usb3_req->queue); 9188c2ecf20Sopenharmony_ci spin_unlock(&usb3->lock); 9198c2ecf20Sopenharmony_ci usb_gadget_giveback_request(&usb3_ep->ep, &usb3_req->req); 9208c2ecf20Sopenharmony_ci spin_lock(&usb3->lock); 9218c2ecf20Sopenharmony_ci} 9228c2ecf20Sopenharmony_ci 9238c2ecf20Sopenharmony_cistatic void usb3_request_done(struct renesas_usb3_ep *usb3_ep, 9248c2ecf20Sopenharmony_ci struct renesas_usb3_request *usb3_req, int status) 9258c2ecf20Sopenharmony_ci{ 9268c2ecf20Sopenharmony_ci struct renesas_usb3 *usb3 = usb3_ep_to_usb3(usb3_ep); 9278c2ecf20Sopenharmony_ci unsigned long flags; 9288c2ecf20Sopenharmony_ci 9298c2ecf20Sopenharmony_ci spin_lock_irqsave(&usb3->lock, flags); 9308c2ecf20Sopenharmony_ci __usb3_request_done(usb3_ep, usb3_req, status); 9318c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&usb3->lock, flags); 9328c2ecf20Sopenharmony_ci} 9338c2ecf20Sopenharmony_ci 9348c2ecf20Sopenharmony_cistatic void usb3_irq_epc_pipe0_status_end(struct renesas_usb3 *usb3) 9358c2ecf20Sopenharmony_ci{ 9368c2ecf20Sopenharmony_ci struct renesas_usb3_ep *usb3_ep = usb3_get_ep(usb3, 0); 9378c2ecf20Sopenharmony_ci struct renesas_usb3_request *usb3_req = usb3_get_request(usb3_ep); 9388c2ecf20Sopenharmony_ci 9398c2ecf20Sopenharmony_ci if (usb3_req) 9408c2ecf20Sopenharmony_ci usb3_request_done(usb3_ep, usb3_req, 0); 9418c2ecf20Sopenharmony_ci if (usb3->test_mode) 9428c2ecf20Sopenharmony_ci usb3_set_test_mode(usb3); 9438c2ecf20Sopenharmony_ci} 9448c2ecf20Sopenharmony_ci 9458c2ecf20Sopenharmony_cistatic void usb3_get_setup_data(struct renesas_usb3 *usb3, 9468c2ecf20Sopenharmony_ci struct usb_ctrlrequest *ctrl) 9478c2ecf20Sopenharmony_ci{ 9488c2ecf20Sopenharmony_ci struct renesas_usb3_ep *usb3_ep = usb3_get_ep(usb3, 0); 9498c2ecf20Sopenharmony_ci u32 *data = (u32 *)ctrl; 9508c2ecf20Sopenharmony_ci 9518c2ecf20Sopenharmony_ci *data++ = usb3_read(usb3, USB3_STUP_DAT_0); 9528c2ecf20Sopenharmony_ci *data = usb3_read(usb3, USB3_STUP_DAT_1); 9538c2ecf20Sopenharmony_ci 9548c2ecf20Sopenharmony_ci /* update this driver's flag */ 9558c2ecf20Sopenharmony_ci usb3_ep->dir_in = !!(ctrl->bRequestType & USB_DIR_IN); 9568c2ecf20Sopenharmony_ci} 9578c2ecf20Sopenharmony_ci 9588c2ecf20Sopenharmony_cistatic void usb3_set_p0_con_update_res(struct renesas_usb3 *usb3, u32 res) 9598c2ecf20Sopenharmony_ci{ 9608c2ecf20Sopenharmony_ci u32 val = usb3_read(usb3, USB3_P0_CON); 9618c2ecf20Sopenharmony_ci 9628c2ecf20Sopenharmony_ci val &= ~(P0_CON_ST_RES_MASK | P0_CON_OT_RES_MASK | P0_CON_IN_RES_MASK); 9638c2ecf20Sopenharmony_ci val |= res | P0_CON_RES_WEN; 9648c2ecf20Sopenharmony_ci usb3_write(usb3, val, USB3_P0_CON); 9658c2ecf20Sopenharmony_ci} 9668c2ecf20Sopenharmony_ci 9678c2ecf20Sopenharmony_cistatic void usb3_set_p0_con_for_ctrl_read_data(struct renesas_usb3 *usb3) 9688c2ecf20Sopenharmony_ci{ 9698c2ecf20Sopenharmony_ci usb3_set_p0_con_update_res(usb3, P0_CON_ST_RES_FORCE_NRDY | 9708c2ecf20Sopenharmony_ci P0_CON_OT_RES_FORCE_STALL | 9718c2ecf20Sopenharmony_ci P0_CON_IN_RES_NORMAL); 9728c2ecf20Sopenharmony_ci} 9738c2ecf20Sopenharmony_ci 9748c2ecf20Sopenharmony_cistatic void usb3_set_p0_con_for_ctrl_read_status(struct renesas_usb3 *usb3) 9758c2ecf20Sopenharmony_ci{ 9768c2ecf20Sopenharmony_ci usb3_set_p0_con_update_res(usb3, P0_CON_ST_RES_NORMAL | 9778c2ecf20Sopenharmony_ci P0_CON_OT_RES_FORCE_STALL | 9788c2ecf20Sopenharmony_ci P0_CON_IN_RES_NORMAL); 9798c2ecf20Sopenharmony_ci} 9808c2ecf20Sopenharmony_ci 9818c2ecf20Sopenharmony_cistatic void usb3_set_p0_con_for_ctrl_write_data(struct renesas_usb3 *usb3) 9828c2ecf20Sopenharmony_ci{ 9838c2ecf20Sopenharmony_ci usb3_set_p0_con_update_res(usb3, P0_CON_ST_RES_FORCE_NRDY | 9848c2ecf20Sopenharmony_ci P0_CON_OT_RES_NORMAL | 9858c2ecf20Sopenharmony_ci P0_CON_IN_RES_FORCE_STALL); 9868c2ecf20Sopenharmony_ci} 9878c2ecf20Sopenharmony_ci 9888c2ecf20Sopenharmony_cistatic void usb3_set_p0_con_for_ctrl_write_status(struct renesas_usb3 *usb3) 9898c2ecf20Sopenharmony_ci{ 9908c2ecf20Sopenharmony_ci usb3_set_p0_con_update_res(usb3, P0_CON_ST_RES_NORMAL | 9918c2ecf20Sopenharmony_ci P0_CON_OT_RES_NORMAL | 9928c2ecf20Sopenharmony_ci P0_CON_IN_RES_FORCE_STALL); 9938c2ecf20Sopenharmony_ci} 9948c2ecf20Sopenharmony_ci 9958c2ecf20Sopenharmony_cistatic void usb3_set_p0_con_for_no_data(struct renesas_usb3 *usb3) 9968c2ecf20Sopenharmony_ci{ 9978c2ecf20Sopenharmony_ci usb3_set_p0_con_update_res(usb3, P0_CON_ST_RES_NORMAL | 9988c2ecf20Sopenharmony_ci P0_CON_OT_RES_FORCE_STALL | 9998c2ecf20Sopenharmony_ci P0_CON_IN_RES_FORCE_STALL); 10008c2ecf20Sopenharmony_ci} 10018c2ecf20Sopenharmony_ci 10028c2ecf20Sopenharmony_cistatic void usb3_set_p0_con_stall(struct renesas_usb3 *usb3) 10038c2ecf20Sopenharmony_ci{ 10048c2ecf20Sopenharmony_ci usb3_set_p0_con_update_res(usb3, P0_CON_ST_RES_FORCE_STALL | 10058c2ecf20Sopenharmony_ci P0_CON_OT_RES_FORCE_STALL | 10068c2ecf20Sopenharmony_ci P0_CON_IN_RES_FORCE_STALL); 10078c2ecf20Sopenharmony_ci} 10088c2ecf20Sopenharmony_ci 10098c2ecf20Sopenharmony_cistatic void usb3_set_p0_con_stop(struct renesas_usb3 *usb3) 10108c2ecf20Sopenharmony_ci{ 10118c2ecf20Sopenharmony_ci usb3_set_p0_con_update_res(usb3, P0_CON_ST_RES_FORCE_NRDY | 10128c2ecf20Sopenharmony_ci P0_CON_OT_RES_FORCE_NRDY | 10138c2ecf20Sopenharmony_ci P0_CON_IN_RES_FORCE_NRDY); 10148c2ecf20Sopenharmony_ci} 10158c2ecf20Sopenharmony_ci 10168c2ecf20Sopenharmony_cistatic int usb3_pn_change(struct renesas_usb3 *usb3, int num) 10178c2ecf20Sopenharmony_ci{ 10188c2ecf20Sopenharmony_ci if (num == 0 || num > usb3->num_usb3_eps) 10198c2ecf20Sopenharmony_ci return -ENXIO; 10208c2ecf20Sopenharmony_ci 10218c2ecf20Sopenharmony_ci usb3_write(usb3, num, USB3_PIPE_COM); 10228c2ecf20Sopenharmony_ci 10238c2ecf20Sopenharmony_ci return 0; 10248c2ecf20Sopenharmony_ci} 10258c2ecf20Sopenharmony_ci 10268c2ecf20Sopenharmony_cistatic void usb3_set_pn_con_update_res(struct renesas_usb3 *usb3, u32 res) 10278c2ecf20Sopenharmony_ci{ 10288c2ecf20Sopenharmony_ci u32 val = usb3_read(usb3, USB3_PN_CON); 10298c2ecf20Sopenharmony_ci 10308c2ecf20Sopenharmony_ci val &= ~PN_CON_RES_MASK; 10318c2ecf20Sopenharmony_ci val |= res & PN_CON_RES_MASK; 10328c2ecf20Sopenharmony_ci val |= PN_CON_RES_WEN; 10338c2ecf20Sopenharmony_ci usb3_write(usb3, val, USB3_PN_CON); 10348c2ecf20Sopenharmony_ci} 10358c2ecf20Sopenharmony_ci 10368c2ecf20Sopenharmony_cistatic void usb3_pn_start(struct renesas_usb3 *usb3) 10378c2ecf20Sopenharmony_ci{ 10388c2ecf20Sopenharmony_ci usb3_set_pn_con_update_res(usb3, PN_CON_RES_NORMAL); 10398c2ecf20Sopenharmony_ci} 10408c2ecf20Sopenharmony_ci 10418c2ecf20Sopenharmony_cistatic void usb3_pn_stop(struct renesas_usb3 *usb3) 10428c2ecf20Sopenharmony_ci{ 10438c2ecf20Sopenharmony_ci usb3_set_pn_con_update_res(usb3, PN_CON_RES_FORCE_NRDY); 10448c2ecf20Sopenharmony_ci} 10458c2ecf20Sopenharmony_ci 10468c2ecf20Sopenharmony_cistatic void usb3_pn_stall(struct renesas_usb3 *usb3) 10478c2ecf20Sopenharmony_ci{ 10488c2ecf20Sopenharmony_ci usb3_set_pn_con_update_res(usb3, PN_CON_RES_FORCE_STALL); 10498c2ecf20Sopenharmony_ci} 10508c2ecf20Sopenharmony_ci 10518c2ecf20Sopenharmony_cistatic int usb3_pn_con_clear(struct renesas_usb3 *usb3) 10528c2ecf20Sopenharmony_ci{ 10538c2ecf20Sopenharmony_ci usb3_set_bit(usb3, PN_CON_CLR, USB3_PN_CON); 10548c2ecf20Sopenharmony_ci 10558c2ecf20Sopenharmony_ci return usb3_wait(usb3, USB3_PN_CON, PN_CON_CLR, 0); 10568c2ecf20Sopenharmony_ci} 10578c2ecf20Sopenharmony_ci 10588c2ecf20Sopenharmony_cistatic bool usb3_is_transfer_complete(struct renesas_usb3_ep *usb3_ep, 10598c2ecf20Sopenharmony_ci struct renesas_usb3_request *usb3_req) 10608c2ecf20Sopenharmony_ci{ 10618c2ecf20Sopenharmony_ci struct usb_request *req = &usb3_req->req; 10628c2ecf20Sopenharmony_ci 10638c2ecf20Sopenharmony_ci if ((!req->zero && req->actual == req->length) || 10648c2ecf20Sopenharmony_ci (req->actual % usb3_ep->ep.maxpacket) || (req->length == 0)) 10658c2ecf20Sopenharmony_ci return true; 10668c2ecf20Sopenharmony_ci else 10678c2ecf20Sopenharmony_ci return false; 10688c2ecf20Sopenharmony_ci} 10698c2ecf20Sopenharmony_ci 10708c2ecf20Sopenharmony_cistatic int usb3_wait_pipe_status(struct renesas_usb3_ep *usb3_ep, u32 mask) 10718c2ecf20Sopenharmony_ci{ 10728c2ecf20Sopenharmony_ci struct renesas_usb3 *usb3 = usb3_ep_to_usb3(usb3_ep); 10738c2ecf20Sopenharmony_ci u32 sta_reg = usb3_ep->num ? USB3_PN_STA : USB3_P0_STA; 10748c2ecf20Sopenharmony_ci 10758c2ecf20Sopenharmony_ci return usb3_wait(usb3, sta_reg, mask, mask); 10768c2ecf20Sopenharmony_ci} 10778c2ecf20Sopenharmony_ci 10788c2ecf20Sopenharmony_cistatic void usb3_set_px_con_send(struct renesas_usb3_ep *usb3_ep, int bytes, 10798c2ecf20Sopenharmony_ci bool last) 10808c2ecf20Sopenharmony_ci{ 10818c2ecf20Sopenharmony_ci struct renesas_usb3 *usb3 = usb3_ep_to_usb3(usb3_ep); 10828c2ecf20Sopenharmony_ci u32 con_reg = usb3_ep->num ? USB3_PN_CON : USB3_P0_CON; 10838c2ecf20Sopenharmony_ci u32 val = usb3_read(usb3, con_reg); 10848c2ecf20Sopenharmony_ci 10858c2ecf20Sopenharmony_ci val |= PX_CON_SEND | PX_CON_BYTE_EN_BYTES(bytes); 10868c2ecf20Sopenharmony_ci val |= (usb3_ep->num && last) ? PN_CON_LAST : 0; 10878c2ecf20Sopenharmony_ci usb3_write(usb3, val, con_reg); 10888c2ecf20Sopenharmony_ci} 10898c2ecf20Sopenharmony_ci 10908c2ecf20Sopenharmony_cistatic int usb3_write_pipe(struct renesas_usb3_ep *usb3_ep, 10918c2ecf20Sopenharmony_ci struct renesas_usb3_request *usb3_req, 10928c2ecf20Sopenharmony_ci u32 fifo_reg) 10938c2ecf20Sopenharmony_ci{ 10948c2ecf20Sopenharmony_ci struct renesas_usb3 *usb3 = usb3_ep_to_usb3(usb3_ep); 10958c2ecf20Sopenharmony_ci int i; 10968c2ecf20Sopenharmony_ci int len = min_t(unsigned, usb3_req->req.length - usb3_req->req.actual, 10978c2ecf20Sopenharmony_ci usb3_ep->ep.maxpacket); 10988c2ecf20Sopenharmony_ci u8 *buf = usb3_req->req.buf + usb3_req->req.actual; 10998c2ecf20Sopenharmony_ci u32 tmp = 0; 11008c2ecf20Sopenharmony_ci bool is_last = !len ? true : false; 11018c2ecf20Sopenharmony_ci 11028c2ecf20Sopenharmony_ci if (usb3_wait_pipe_status(usb3_ep, PX_STA_BUFSTS) < 0) 11038c2ecf20Sopenharmony_ci return -EBUSY; 11048c2ecf20Sopenharmony_ci 11058c2ecf20Sopenharmony_ci /* Update gadget driver parameter */ 11068c2ecf20Sopenharmony_ci usb3_req->req.actual += len; 11078c2ecf20Sopenharmony_ci 11088c2ecf20Sopenharmony_ci /* Write data to the register */ 11098c2ecf20Sopenharmony_ci if (len >= 4) { 11108c2ecf20Sopenharmony_ci iowrite32_rep(usb3->reg + fifo_reg, buf, len / 4); 11118c2ecf20Sopenharmony_ci buf += (len / 4) * 4; 11128c2ecf20Sopenharmony_ci len %= 4; /* update len to use usb3_set_pX_con_send() */ 11138c2ecf20Sopenharmony_ci } 11148c2ecf20Sopenharmony_ci 11158c2ecf20Sopenharmony_ci if (len) { 11168c2ecf20Sopenharmony_ci for (i = 0; i < len; i++) 11178c2ecf20Sopenharmony_ci tmp |= buf[i] << (8 * i); 11188c2ecf20Sopenharmony_ci usb3_write(usb3, tmp, fifo_reg); 11198c2ecf20Sopenharmony_ci } 11208c2ecf20Sopenharmony_ci 11218c2ecf20Sopenharmony_ci if (!is_last) 11228c2ecf20Sopenharmony_ci is_last = usb3_is_transfer_complete(usb3_ep, usb3_req); 11238c2ecf20Sopenharmony_ci /* Send the data */ 11248c2ecf20Sopenharmony_ci usb3_set_px_con_send(usb3_ep, len, is_last); 11258c2ecf20Sopenharmony_ci 11268c2ecf20Sopenharmony_ci return is_last ? 0 : -EAGAIN; 11278c2ecf20Sopenharmony_ci} 11288c2ecf20Sopenharmony_ci 11298c2ecf20Sopenharmony_cistatic u32 usb3_get_received_length(struct renesas_usb3_ep *usb3_ep) 11308c2ecf20Sopenharmony_ci{ 11318c2ecf20Sopenharmony_ci struct renesas_usb3 *usb3 = usb3_ep_to_usb3(usb3_ep); 11328c2ecf20Sopenharmony_ci u32 lng_reg = usb3_ep->num ? USB3_PN_LNG : USB3_P0_LNG; 11338c2ecf20Sopenharmony_ci 11348c2ecf20Sopenharmony_ci return usb3_read(usb3, lng_reg); 11358c2ecf20Sopenharmony_ci} 11368c2ecf20Sopenharmony_ci 11378c2ecf20Sopenharmony_cistatic int usb3_read_pipe(struct renesas_usb3_ep *usb3_ep, 11388c2ecf20Sopenharmony_ci struct renesas_usb3_request *usb3_req, u32 fifo_reg) 11398c2ecf20Sopenharmony_ci{ 11408c2ecf20Sopenharmony_ci struct renesas_usb3 *usb3 = usb3_ep_to_usb3(usb3_ep); 11418c2ecf20Sopenharmony_ci int i; 11428c2ecf20Sopenharmony_ci int len = min_t(unsigned, usb3_req->req.length - usb3_req->req.actual, 11438c2ecf20Sopenharmony_ci usb3_get_received_length(usb3_ep)); 11448c2ecf20Sopenharmony_ci u8 *buf = usb3_req->req.buf + usb3_req->req.actual; 11458c2ecf20Sopenharmony_ci u32 tmp = 0; 11468c2ecf20Sopenharmony_ci 11478c2ecf20Sopenharmony_ci if (!len) 11488c2ecf20Sopenharmony_ci return 0; 11498c2ecf20Sopenharmony_ci 11508c2ecf20Sopenharmony_ci /* Update gadget driver parameter */ 11518c2ecf20Sopenharmony_ci usb3_req->req.actual += len; 11528c2ecf20Sopenharmony_ci 11538c2ecf20Sopenharmony_ci /* Read data from the register */ 11548c2ecf20Sopenharmony_ci if (len >= 4) { 11558c2ecf20Sopenharmony_ci ioread32_rep(usb3->reg + fifo_reg, buf, len / 4); 11568c2ecf20Sopenharmony_ci buf += (len / 4) * 4; 11578c2ecf20Sopenharmony_ci len %= 4; 11588c2ecf20Sopenharmony_ci } 11598c2ecf20Sopenharmony_ci 11608c2ecf20Sopenharmony_ci if (len) { 11618c2ecf20Sopenharmony_ci tmp = usb3_read(usb3, fifo_reg); 11628c2ecf20Sopenharmony_ci for (i = 0; i < len; i++) 11638c2ecf20Sopenharmony_ci buf[i] = (tmp >> (8 * i)) & 0xff; 11648c2ecf20Sopenharmony_ci } 11658c2ecf20Sopenharmony_ci 11668c2ecf20Sopenharmony_ci return usb3_is_transfer_complete(usb3_ep, usb3_req) ? 0 : -EAGAIN; 11678c2ecf20Sopenharmony_ci} 11688c2ecf20Sopenharmony_ci 11698c2ecf20Sopenharmony_cistatic void usb3_set_status_stage(struct renesas_usb3_ep *usb3_ep, 11708c2ecf20Sopenharmony_ci struct renesas_usb3_request *usb3_req) 11718c2ecf20Sopenharmony_ci{ 11728c2ecf20Sopenharmony_ci struct renesas_usb3 *usb3 = usb3_ep_to_usb3(usb3_ep); 11738c2ecf20Sopenharmony_ci 11748c2ecf20Sopenharmony_ci if (usb3_ep->dir_in) { 11758c2ecf20Sopenharmony_ci usb3_set_p0_con_for_ctrl_read_status(usb3); 11768c2ecf20Sopenharmony_ci } else { 11778c2ecf20Sopenharmony_ci if (!usb3_req->req.length) 11788c2ecf20Sopenharmony_ci usb3_set_p0_con_for_no_data(usb3); 11798c2ecf20Sopenharmony_ci else 11808c2ecf20Sopenharmony_ci usb3_set_p0_con_for_ctrl_write_status(usb3); 11818c2ecf20Sopenharmony_ci } 11828c2ecf20Sopenharmony_ci} 11838c2ecf20Sopenharmony_ci 11848c2ecf20Sopenharmony_cistatic void usb3_p0_xfer(struct renesas_usb3_ep *usb3_ep, 11858c2ecf20Sopenharmony_ci struct renesas_usb3_request *usb3_req) 11868c2ecf20Sopenharmony_ci{ 11878c2ecf20Sopenharmony_ci int ret; 11888c2ecf20Sopenharmony_ci 11898c2ecf20Sopenharmony_ci if (usb3_ep->dir_in) 11908c2ecf20Sopenharmony_ci ret = usb3_write_pipe(usb3_ep, usb3_req, USB3_P0_WRITE); 11918c2ecf20Sopenharmony_ci else 11928c2ecf20Sopenharmony_ci ret = usb3_read_pipe(usb3_ep, usb3_req, USB3_P0_READ); 11938c2ecf20Sopenharmony_ci 11948c2ecf20Sopenharmony_ci if (!ret) 11958c2ecf20Sopenharmony_ci usb3_set_status_stage(usb3_ep, usb3_req); 11968c2ecf20Sopenharmony_ci} 11978c2ecf20Sopenharmony_ci 11988c2ecf20Sopenharmony_cistatic void usb3_start_pipe0(struct renesas_usb3_ep *usb3_ep, 11998c2ecf20Sopenharmony_ci struct renesas_usb3_request *usb3_req) 12008c2ecf20Sopenharmony_ci{ 12018c2ecf20Sopenharmony_ci struct renesas_usb3 *usb3 = usb3_ep_to_usb3(usb3_ep); 12028c2ecf20Sopenharmony_ci 12038c2ecf20Sopenharmony_ci if (usb3_ep->started) 12048c2ecf20Sopenharmony_ci return; 12058c2ecf20Sopenharmony_ci 12068c2ecf20Sopenharmony_ci usb3_ep->started = true; 12078c2ecf20Sopenharmony_ci 12088c2ecf20Sopenharmony_ci if (usb3_ep->dir_in) { 12098c2ecf20Sopenharmony_ci usb3_set_bit(usb3, P0_MOD_DIR, USB3_P0_MOD); 12108c2ecf20Sopenharmony_ci usb3_set_p0_con_for_ctrl_read_data(usb3); 12118c2ecf20Sopenharmony_ci } else { 12128c2ecf20Sopenharmony_ci usb3_clear_bit(usb3, P0_MOD_DIR, USB3_P0_MOD); 12138c2ecf20Sopenharmony_ci if (usb3_req->req.length) 12148c2ecf20Sopenharmony_ci usb3_set_p0_con_for_ctrl_write_data(usb3); 12158c2ecf20Sopenharmony_ci } 12168c2ecf20Sopenharmony_ci 12178c2ecf20Sopenharmony_ci usb3_p0_xfer(usb3_ep, usb3_req); 12188c2ecf20Sopenharmony_ci} 12198c2ecf20Sopenharmony_ci 12208c2ecf20Sopenharmony_cistatic void usb3_enable_dma_pipen(struct renesas_usb3 *usb3) 12218c2ecf20Sopenharmony_ci{ 12228c2ecf20Sopenharmony_ci usb3_set_bit(usb3, PN_CON_DATAIF_EN, USB3_PN_CON); 12238c2ecf20Sopenharmony_ci} 12248c2ecf20Sopenharmony_ci 12258c2ecf20Sopenharmony_cistatic void usb3_disable_dma_pipen(struct renesas_usb3 *usb3) 12268c2ecf20Sopenharmony_ci{ 12278c2ecf20Sopenharmony_ci usb3_clear_bit(usb3, PN_CON_DATAIF_EN, USB3_PN_CON); 12288c2ecf20Sopenharmony_ci} 12298c2ecf20Sopenharmony_ci 12308c2ecf20Sopenharmony_cistatic void usb3_enable_dma_irq(struct renesas_usb3 *usb3, int num) 12318c2ecf20Sopenharmony_ci{ 12328c2ecf20Sopenharmony_ci usb3_set_bit(usb3, DMA_INT(num), USB3_DMA_INT_ENA); 12338c2ecf20Sopenharmony_ci} 12348c2ecf20Sopenharmony_ci 12358c2ecf20Sopenharmony_cistatic void usb3_disable_dma_irq(struct renesas_usb3 *usb3, int num) 12368c2ecf20Sopenharmony_ci{ 12378c2ecf20Sopenharmony_ci usb3_clear_bit(usb3, DMA_INT(num), USB3_DMA_INT_ENA); 12388c2ecf20Sopenharmony_ci} 12398c2ecf20Sopenharmony_ci 12408c2ecf20Sopenharmony_cistatic u32 usb3_dma_mps_to_prd_word1(struct renesas_usb3_ep *usb3_ep) 12418c2ecf20Sopenharmony_ci{ 12428c2ecf20Sopenharmony_ci switch (usb3_ep->ep.maxpacket) { 12438c2ecf20Sopenharmony_ci case 8: 12448c2ecf20Sopenharmony_ci return USB3_PRD1_MPS_8; 12458c2ecf20Sopenharmony_ci case 16: 12468c2ecf20Sopenharmony_ci return USB3_PRD1_MPS_16; 12478c2ecf20Sopenharmony_ci case 32: 12488c2ecf20Sopenharmony_ci return USB3_PRD1_MPS_32; 12498c2ecf20Sopenharmony_ci case 64: 12508c2ecf20Sopenharmony_ci return USB3_PRD1_MPS_64; 12518c2ecf20Sopenharmony_ci case 512: 12528c2ecf20Sopenharmony_ci return USB3_PRD1_MPS_512; 12538c2ecf20Sopenharmony_ci case 1024: 12548c2ecf20Sopenharmony_ci return USB3_PRD1_MPS_1024; 12558c2ecf20Sopenharmony_ci default: 12568c2ecf20Sopenharmony_ci return USB3_PRD1_MPS_RESERVED; 12578c2ecf20Sopenharmony_ci } 12588c2ecf20Sopenharmony_ci} 12598c2ecf20Sopenharmony_ci 12608c2ecf20Sopenharmony_cistatic bool usb3_dma_get_setting_area(struct renesas_usb3_ep *usb3_ep, 12618c2ecf20Sopenharmony_ci struct renesas_usb3_request *usb3_req) 12628c2ecf20Sopenharmony_ci{ 12638c2ecf20Sopenharmony_ci struct renesas_usb3 *usb3 = usb3_ep_to_usb3(usb3_ep); 12648c2ecf20Sopenharmony_ci struct renesas_usb3_dma *dma; 12658c2ecf20Sopenharmony_ci int i; 12668c2ecf20Sopenharmony_ci bool ret = false; 12678c2ecf20Sopenharmony_ci 12688c2ecf20Sopenharmony_ci if (usb3_req->req.length > USB3_DMA_MAX_XFER_SIZE_ALL_PRDS) { 12698c2ecf20Sopenharmony_ci dev_dbg(usb3_to_dev(usb3), "%s: the length is too big (%d)\n", 12708c2ecf20Sopenharmony_ci __func__, usb3_req->req.length); 12718c2ecf20Sopenharmony_ci return false; 12728c2ecf20Sopenharmony_ci } 12738c2ecf20Sopenharmony_ci 12748c2ecf20Sopenharmony_ci /* The driver doesn't handle zero-length packet via dmac */ 12758c2ecf20Sopenharmony_ci if (!usb3_req->req.length) 12768c2ecf20Sopenharmony_ci return false; 12778c2ecf20Sopenharmony_ci 12788c2ecf20Sopenharmony_ci if (usb3_dma_mps_to_prd_word1(usb3_ep) == USB3_PRD1_MPS_RESERVED) 12798c2ecf20Sopenharmony_ci return false; 12808c2ecf20Sopenharmony_ci 12818c2ecf20Sopenharmony_ci usb3_for_each_dma(usb3, dma, i) { 12828c2ecf20Sopenharmony_ci if (dma->used) 12838c2ecf20Sopenharmony_ci continue; 12848c2ecf20Sopenharmony_ci 12858c2ecf20Sopenharmony_ci if (usb_gadget_map_request(&usb3->gadget, &usb3_req->req, 12868c2ecf20Sopenharmony_ci usb3_ep->dir_in) < 0) 12878c2ecf20Sopenharmony_ci break; 12888c2ecf20Sopenharmony_ci 12898c2ecf20Sopenharmony_ci dma->used = true; 12908c2ecf20Sopenharmony_ci usb3_ep->dma = dma; 12918c2ecf20Sopenharmony_ci ret = true; 12928c2ecf20Sopenharmony_ci break; 12938c2ecf20Sopenharmony_ci } 12948c2ecf20Sopenharmony_ci 12958c2ecf20Sopenharmony_ci return ret; 12968c2ecf20Sopenharmony_ci} 12978c2ecf20Sopenharmony_ci 12988c2ecf20Sopenharmony_cistatic void usb3_dma_put_setting_area(struct renesas_usb3_ep *usb3_ep, 12998c2ecf20Sopenharmony_ci struct renesas_usb3_request *usb3_req) 13008c2ecf20Sopenharmony_ci{ 13018c2ecf20Sopenharmony_ci struct renesas_usb3 *usb3 = usb3_ep_to_usb3(usb3_ep); 13028c2ecf20Sopenharmony_ci int i; 13038c2ecf20Sopenharmony_ci struct renesas_usb3_dma *dma; 13048c2ecf20Sopenharmony_ci 13058c2ecf20Sopenharmony_ci usb3_for_each_dma(usb3, dma, i) { 13068c2ecf20Sopenharmony_ci if (usb3_ep->dma == dma) { 13078c2ecf20Sopenharmony_ci usb_gadget_unmap_request(&usb3->gadget, &usb3_req->req, 13088c2ecf20Sopenharmony_ci usb3_ep->dir_in); 13098c2ecf20Sopenharmony_ci dma->used = false; 13108c2ecf20Sopenharmony_ci usb3_ep->dma = NULL; 13118c2ecf20Sopenharmony_ci break; 13128c2ecf20Sopenharmony_ci } 13138c2ecf20Sopenharmony_ci } 13148c2ecf20Sopenharmony_ci} 13158c2ecf20Sopenharmony_ci 13168c2ecf20Sopenharmony_cistatic void usb3_dma_fill_prd(struct renesas_usb3_ep *usb3_ep, 13178c2ecf20Sopenharmony_ci struct renesas_usb3_request *usb3_req) 13188c2ecf20Sopenharmony_ci{ 13198c2ecf20Sopenharmony_ci struct renesas_usb3_prd *cur_prd = usb3_ep->dma->prd; 13208c2ecf20Sopenharmony_ci u32 remain = usb3_req->req.length; 13218c2ecf20Sopenharmony_ci u32 dma = usb3_req->req.dma; 13228c2ecf20Sopenharmony_ci u32 len; 13238c2ecf20Sopenharmony_ci int i = 0; 13248c2ecf20Sopenharmony_ci 13258c2ecf20Sopenharmony_ci do { 13268c2ecf20Sopenharmony_ci len = min_t(u32, remain, USB3_DMA_MAX_XFER_SIZE) & 13278c2ecf20Sopenharmony_ci USB3_PRD1_SIZE_MASK; 13288c2ecf20Sopenharmony_ci cur_prd->word1 = usb3_dma_mps_to_prd_word1(usb3_ep) | 13298c2ecf20Sopenharmony_ci USB3_PRD1_B_INC | len; 13308c2ecf20Sopenharmony_ci cur_prd->bap = dma; 13318c2ecf20Sopenharmony_ci remain -= len; 13328c2ecf20Sopenharmony_ci dma += len; 13338c2ecf20Sopenharmony_ci if (!remain || (i + 1) < USB3_DMA_NUM_PRD_ENTRIES) 13348c2ecf20Sopenharmony_ci break; 13358c2ecf20Sopenharmony_ci 13368c2ecf20Sopenharmony_ci cur_prd++; 13378c2ecf20Sopenharmony_ci i++; 13388c2ecf20Sopenharmony_ci } while (1); 13398c2ecf20Sopenharmony_ci 13408c2ecf20Sopenharmony_ci cur_prd->word1 |= USB3_PRD1_E | USB3_PRD1_INT; 13418c2ecf20Sopenharmony_ci if (usb3_ep->dir_in) 13428c2ecf20Sopenharmony_ci cur_prd->word1 |= USB3_PRD1_LST; 13438c2ecf20Sopenharmony_ci} 13448c2ecf20Sopenharmony_ci 13458c2ecf20Sopenharmony_cistatic void usb3_dma_kick_prd(struct renesas_usb3_ep *usb3_ep) 13468c2ecf20Sopenharmony_ci{ 13478c2ecf20Sopenharmony_ci struct renesas_usb3_dma *dma = usb3_ep->dma; 13488c2ecf20Sopenharmony_ci struct renesas_usb3 *usb3 = usb3_ep_to_usb3(usb3_ep); 13498c2ecf20Sopenharmony_ci u32 dma_con = DMA_COM_PIPE_NO(usb3_ep->num) | DMA_CON_PRD_EN; 13508c2ecf20Sopenharmony_ci 13518c2ecf20Sopenharmony_ci if (usb3_ep->dir_in) 13528c2ecf20Sopenharmony_ci dma_con |= DMA_CON_PIPE_DIR; 13538c2ecf20Sopenharmony_ci 13548c2ecf20Sopenharmony_ci wmb(); /* prd entries should be in system memory here */ 13558c2ecf20Sopenharmony_ci 13568c2ecf20Sopenharmony_ci usb3_write(usb3, 1 << usb3_ep->num, USB3_DMA_INT_STA); 13578c2ecf20Sopenharmony_ci usb3_write(usb3, AXI_INT_PRDEN_CLR_STA(dma->num) | 13588c2ecf20Sopenharmony_ci AXI_INT_PRDERR_STA(dma->num), USB3_AXI_INT_STA); 13598c2ecf20Sopenharmony_ci 13608c2ecf20Sopenharmony_ci usb3_write(usb3, dma->prd_dma, USB3_DMA_CH0_PRD_ADR(dma->num)); 13618c2ecf20Sopenharmony_ci usb3_write(usb3, dma_con, USB3_DMA_CH0_CON(dma->num)); 13628c2ecf20Sopenharmony_ci usb3_enable_dma_irq(usb3, usb3_ep->num); 13638c2ecf20Sopenharmony_ci} 13648c2ecf20Sopenharmony_ci 13658c2ecf20Sopenharmony_cistatic void usb3_dma_stop_prd(struct renesas_usb3_ep *usb3_ep) 13668c2ecf20Sopenharmony_ci{ 13678c2ecf20Sopenharmony_ci struct renesas_usb3 *usb3 = usb3_ep_to_usb3(usb3_ep); 13688c2ecf20Sopenharmony_ci struct renesas_usb3_dma *dma = usb3_ep->dma; 13698c2ecf20Sopenharmony_ci 13708c2ecf20Sopenharmony_ci usb3_disable_dma_irq(usb3, usb3_ep->num); 13718c2ecf20Sopenharmony_ci usb3_write(usb3, 0, USB3_DMA_CH0_CON(dma->num)); 13728c2ecf20Sopenharmony_ci} 13738c2ecf20Sopenharmony_ci 13748c2ecf20Sopenharmony_cistatic int usb3_dma_update_status(struct renesas_usb3_ep *usb3_ep, 13758c2ecf20Sopenharmony_ci struct renesas_usb3_request *usb3_req) 13768c2ecf20Sopenharmony_ci{ 13778c2ecf20Sopenharmony_ci struct renesas_usb3_prd *cur_prd = usb3_ep->dma->prd; 13788c2ecf20Sopenharmony_ci struct usb_request *req = &usb3_req->req; 13798c2ecf20Sopenharmony_ci u32 remain, len; 13808c2ecf20Sopenharmony_ci int i = 0; 13818c2ecf20Sopenharmony_ci int status = 0; 13828c2ecf20Sopenharmony_ci 13838c2ecf20Sopenharmony_ci rmb(); /* The controller updated prd entries */ 13848c2ecf20Sopenharmony_ci 13858c2ecf20Sopenharmony_ci do { 13868c2ecf20Sopenharmony_ci if (cur_prd->word1 & USB3_PRD1_D) 13878c2ecf20Sopenharmony_ci status = -EIO; 13888c2ecf20Sopenharmony_ci if (cur_prd->word1 & USB3_PRD1_E) 13898c2ecf20Sopenharmony_ci len = req->length % USB3_DMA_MAX_XFER_SIZE; 13908c2ecf20Sopenharmony_ci else 13918c2ecf20Sopenharmony_ci len = USB3_DMA_MAX_XFER_SIZE; 13928c2ecf20Sopenharmony_ci remain = cur_prd->word1 & USB3_PRD1_SIZE_MASK; 13938c2ecf20Sopenharmony_ci req->actual += len - remain; 13948c2ecf20Sopenharmony_ci 13958c2ecf20Sopenharmony_ci if (cur_prd->word1 & USB3_PRD1_E || 13968c2ecf20Sopenharmony_ci (i + 1) < USB3_DMA_NUM_PRD_ENTRIES) 13978c2ecf20Sopenharmony_ci break; 13988c2ecf20Sopenharmony_ci 13998c2ecf20Sopenharmony_ci cur_prd++; 14008c2ecf20Sopenharmony_ci i++; 14018c2ecf20Sopenharmony_ci } while (1); 14028c2ecf20Sopenharmony_ci 14038c2ecf20Sopenharmony_ci return status; 14048c2ecf20Sopenharmony_ci} 14058c2ecf20Sopenharmony_ci 14068c2ecf20Sopenharmony_cistatic bool usb3_dma_try_start(struct renesas_usb3_ep *usb3_ep, 14078c2ecf20Sopenharmony_ci struct renesas_usb3_request *usb3_req) 14088c2ecf20Sopenharmony_ci{ 14098c2ecf20Sopenharmony_ci struct renesas_usb3 *usb3 = usb3_ep_to_usb3(usb3_ep); 14108c2ecf20Sopenharmony_ci 14118c2ecf20Sopenharmony_ci if (!use_dma) 14128c2ecf20Sopenharmony_ci return false; 14138c2ecf20Sopenharmony_ci 14148c2ecf20Sopenharmony_ci if (usb3_dma_get_setting_area(usb3_ep, usb3_req)) { 14158c2ecf20Sopenharmony_ci usb3_pn_stop(usb3); 14168c2ecf20Sopenharmony_ci usb3_enable_dma_pipen(usb3); 14178c2ecf20Sopenharmony_ci usb3_dma_fill_prd(usb3_ep, usb3_req); 14188c2ecf20Sopenharmony_ci usb3_dma_kick_prd(usb3_ep); 14198c2ecf20Sopenharmony_ci usb3_pn_start(usb3); 14208c2ecf20Sopenharmony_ci return true; 14218c2ecf20Sopenharmony_ci } 14228c2ecf20Sopenharmony_ci 14238c2ecf20Sopenharmony_ci return false; 14248c2ecf20Sopenharmony_ci} 14258c2ecf20Sopenharmony_ci 14268c2ecf20Sopenharmony_cistatic int usb3_dma_try_stop(struct renesas_usb3_ep *usb3_ep, 14278c2ecf20Sopenharmony_ci struct renesas_usb3_request *usb3_req) 14288c2ecf20Sopenharmony_ci{ 14298c2ecf20Sopenharmony_ci struct renesas_usb3 *usb3 = usb3_ep_to_usb3(usb3_ep); 14308c2ecf20Sopenharmony_ci unsigned long flags; 14318c2ecf20Sopenharmony_ci int status = 0; 14328c2ecf20Sopenharmony_ci 14338c2ecf20Sopenharmony_ci spin_lock_irqsave(&usb3->lock, flags); 14348c2ecf20Sopenharmony_ci if (!usb3_ep->dma) 14358c2ecf20Sopenharmony_ci goto out; 14368c2ecf20Sopenharmony_ci 14378c2ecf20Sopenharmony_ci if (!usb3_pn_change(usb3, usb3_ep->num)) 14388c2ecf20Sopenharmony_ci usb3_disable_dma_pipen(usb3); 14398c2ecf20Sopenharmony_ci usb3_dma_stop_prd(usb3_ep); 14408c2ecf20Sopenharmony_ci status = usb3_dma_update_status(usb3_ep, usb3_req); 14418c2ecf20Sopenharmony_ci usb3_dma_put_setting_area(usb3_ep, usb3_req); 14428c2ecf20Sopenharmony_ci 14438c2ecf20Sopenharmony_ciout: 14448c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&usb3->lock, flags); 14458c2ecf20Sopenharmony_ci return status; 14468c2ecf20Sopenharmony_ci} 14478c2ecf20Sopenharmony_ci 14488c2ecf20Sopenharmony_cistatic int renesas_usb3_dma_free_prd(struct renesas_usb3 *usb3, 14498c2ecf20Sopenharmony_ci struct device *dev) 14508c2ecf20Sopenharmony_ci{ 14518c2ecf20Sopenharmony_ci int i; 14528c2ecf20Sopenharmony_ci struct renesas_usb3_dma *dma; 14538c2ecf20Sopenharmony_ci 14548c2ecf20Sopenharmony_ci usb3_for_each_dma(usb3, dma, i) { 14558c2ecf20Sopenharmony_ci if (dma->prd) { 14568c2ecf20Sopenharmony_ci dma_free_coherent(dev, USB3_DMA_PRD_SIZE, 14578c2ecf20Sopenharmony_ci dma->prd, dma->prd_dma); 14588c2ecf20Sopenharmony_ci dma->prd = NULL; 14598c2ecf20Sopenharmony_ci } 14608c2ecf20Sopenharmony_ci } 14618c2ecf20Sopenharmony_ci 14628c2ecf20Sopenharmony_ci return 0; 14638c2ecf20Sopenharmony_ci} 14648c2ecf20Sopenharmony_ci 14658c2ecf20Sopenharmony_cistatic int renesas_usb3_dma_alloc_prd(struct renesas_usb3 *usb3, 14668c2ecf20Sopenharmony_ci struct device *dev) 14678c2ecf20Sopenharmony_ci{ 14688c2ecf20Sopenharmony_ci int i; 14698c2ecf20Sopenharmony_ci struct renesas_usb3_dma *dma; 14708c2ecf20Sopenharmony_ci 14718c2ecf20Sopenharmony_ci if (!use_dma) 14728c2ecf20Sopenharmony_ci return 0; 14738c2ecf20Sopenharmony_ci 14748c2ecf20Sopenharmony_ci usb3_for_each_dma(usb3, dma, i) { 14758c2ecf20Sopenharmony_ci dma->prd = dma_alloc_coherent(dev, USB3_DMA_PRD_SIZE, 14768c2ecf20Sopenharmony_ci &dma->prd_dma, GFP_KERNEL); 14778c2ecf20Sopenharmony_ci if (!dma->prd) { 14788c2ecf20Sopenharmony_ci renesas_usb3_dma_free_prd(usb3, dev); 14798c2ecf20Sopenharmony_ci return -ENOMEM; 14808c2ecf20Sopenharmony_ci } 14818c2ecf20Sopenharmony_ci dma->num = i + 1; 14828c2ecf20Sopenharmony_ci } 14838c2ecf20Sopenharmony_ci 14848c2ecf20Sopenharmony_ci return 0; 14858c2ecf20Sopenharmony_ci} 14868c2ecf20Sopenharmony_ci 14878c2ecf20Sopenharmony_cistatic void usb3_start_pipen(struct renesas_usb3_ep *usb3_ep, 14888c2ecf20Sopenharmony_ci struct renesas_usb3_request *usb3_req) 14898c2ecf20Sopenharmony_ci{ 14908c2ecf20Sopenharmony_ci struct renesas_usb3 *usb3 = usb3_ep_to_usb3(usb3_ep); 14918c2ecf20Sopenharmony_ci struct renesas_usb3_request *usb3_req_first; 14928c2ecf20Sopenharmony_ci unsigned long flags; 14938c2ecf20Sopenharmony_ci int ret = -EAGAIN; 14948c2ecf20Sopenharmony_ci u32 enable_bits = 0; 14958c2ecf20Sopenharmony_ci 14968c2ecf20Sopenharmony_ci spin_lock_irqsave(&usb3->lock, flags); 14978c2ecf20Sopenharmony_ci if (usb3_ep->halt || usb3_ep->started) 14988c2ecf20Sopenharmony_ci goto out; 14998c2ecf20Sopenharmony_ci usb3_req_first = __usb3_get_request(usb3_ep); 15008c2ecf20Sopenharmony_ci if (!usb3_req_first || usb3_req != usb3_req_first) 15018c2ecf20Sopenharmony_ci goto out; 15028c2ecf20Sopenharmony_ci 15038c2ecf20Sopenharmony_ci if (usb3_pn_change(usb3, usb3_ep->num) < 0) 15048c2ecf20Sopenharmony_ci goto out; 15058c2ecf20Sopenharmony_ci 15068c2ecf20Sopenharmony_ci usb3_ep->started = true; 15078c2ecf20Sopenharmony_ci 15088c2ecf20Sopenharmony_ci if (usb3_dma_try_start(usb3_ep, usb3_req)) 15098c2ecf20Sopenharmony_ci goto out; 15108c2ecf20Sopenharmony_ci 15118c2ecf20Sopenharmony_ci usb3_pn_start(usb3); 15128c2ecf20Sopenharmony_ci 15138c2ecf20Sopenharmony_ci if (usb3_ep->dir_in) { 15148c2ecf20Sopenharmony_ci ret = usb3_write_pipe(usb3_ep, usb3_req, USB3_PN_WRITE); 15158c2ecf20Sopenharmony_ci enable_bits |= PN_INT_LSTTR; 15168c2ecf20Sopenharmony_ci } 15178c2ecf20Sopenharmony_ci 15188c2ecf20Sopenharmony_ci if (ret < 0) 15198c2ecf20Sopenharmony_ci enable_bits |= PN_INT_BFRDY; 15208c2ecf20Sopenharmony_ci 15218c2ecf20Sopenharmony_ci if (enable_bits) { 15228c2ecf20Sopenharmony_ci usb3_set_bit(usb3, enable_bits, USB3_PN_INT_ENA); 15238c2ecf20Sopenharmony_ci usb3_enable_pipe_irq(usb3, usb3_ep->num); 15248c2ecf20Sopenharmony_ci } 15258c2ecf20Sopenharmony_ciout: 15268c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&usb3->lock, flags); 15278c2ecf20Sopenharmony_ci} 15288c2ecf20Sopenharmony_ci 15298c2ecf20Sopenharmony_cistatic int renesas_usb3_ep_queue(struct usb_ep *_ep, struct usb_request *_req, 15308c2ecf20Sopenharmony_ci gfp_t gfp_flags) 15318c2ecf20Sopenharmony_ci{ 15328c2ecf20Sopenharmony_ci struct renesas_usb3_ep *usb3_ep = usb_ep_to_usb3_ep(_ep); 15338c2ecf20Sopenharmony_ci struct renesas_usb3_request *usb3_req = usb_req_to_usb3_req(_req); 15348c2ecf20Sopenharmony_ci struct renesas_usb3 *usb3 = usb3_ep_to_usb3(usb3_ep); 15358c2ecf20Sopenharmony_ci unsigned long flags; 15368c2ecf20Sopenharmony_ci 15378c2ecf20Sopenharmony_ci dev_dbg(usb3_to_dev(usb3), "ep_queue: ep%2d, %u\n", usb3_ep->num, 15388c2ecf20Sopenharmony_ci _req->length); 15398c2ecf20Sopenharmony_ci 15408c2ecf20Sopenharmony_ci _req->status = -EINPROGRESS; 15418c2ecf20Sopenharmony_ci _req->actual = 0; 15428c2ecf20Sopenharmony_ci spin_lock_irqsave(&usb3->lock, flags); 15438c2ecf20Sopenharmony_ci list_add_tail(&usb3_req->queue, &usb3_ep->queue); 15448c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&usb3->lock, flags); 15458c2ecf20Sopenharmony_ci 15468c2ecf20Sopenharmony_ci if (!usb3_ep->num) 15478c2ecf20Sopenharmony_ci usb3_start_pipe0(usb3_ep, usb3_req); 15488c2ecf20Sopenharmony_ci else 15498c2ecf20Sopenharmony_ci usb3_start_pipen(usb3_ep, usb3_req); 15508c2ecf20Sopenharmony_ci 15518c2ecf20Sopenharmony_ci return 0; 15528c2ecf20Sopenharmony_ci} 15538c2ecf20Sopenharmony_ci 15548c2ecf20Sopenharmony_cistatic void usb3_set_device_address(struct renesas_usb3 *usb3, u16 addr) 15558c2ecf20Sopenharmony_ci{ 15568c2ecf20Sopenharmony_ci /* DEV_ADDR bit field is cleared by WarmReset, HotReset and BusReset */ 15578c2ecf20Sopenharmony_ci usb3_set_bit(usb3, USB_COM_CON_DEV_ADDR(addr), USB3_USB_COM_CON); 15588c2ecf20Sopenharmony_ci} 15598c2ecf20Sopenharmony_ci 15608c2ecf20Sopenharmony_cistatic bool usb3_std_req_set_address(struct renesas_usb3 *usb3, 15618c2ecf20Sopenharmony_ci struct usb_ctrlrequest *ctrl) 15628c2ecf20Sopenharmony_ci{ 15638c2ecf20Sopenharmony_ci if (le16_to_cpu(ctrl->wValue) >= 128) 15648c2ecf20Sopenharmony_ci return true; /* stall */ 15658c2ecf20Sopenharmony_ci 15668c2ecf20Sopenharmony_ci usb3_set_device_address(usb3, le16_to_cpu(ctrl->wValue)); 15678c2ecf20Sopenharmony_ci usb3_set_p0_con_for_no_data(usb3); 15688c2ecf20Sopenharmony_ci 15698c2ecf20Sopenharmony_ci return false; 15708c2ecf20Sopenharmony_ci} 15718c2ecf20Sopenharmony_ci 15728c2ecf20Sopenharmony_cistatic void usb3_pipe0_internal_xfer(struct renesas_usb3 *usb3, 15738c2ecf20Sopenharmony_ci void *tx_data, size_t len, 15748c2ecf20Sopenharmony_ci void (*complete)(struct usb_ep *ep, 15758c2ecf20Sopenharmony_ci struct usb_request *req)) 15768c2ecf20Sopenharmony_ci{ 15778c2ecf20Sopenharmony_ci struct renesas_usb3_ep *usb3_ep = usb3_get_ep(usb3, 0); 15788c2ecf20Sopenharmony_ci 15798c2ecf20Sopenharmony_ci if (tx_data) 15808c2ecf20Sopenharmony_ci memcpy(usb3->ep0_buf, tx_data, 15818c2ecf20Sopenharmony_ci min_t(size_t, len, USB3_EP0_BUF_SIZE)); 15828c2ecf20Sopenharmony_ci 15838c2ecf20Sopenharmony_ci usb3->ep0_req->buf = &usb3->ep0_buf; 15848c2ecf20Sopenharmony_ci usb3->ep0_req->length = len; 15858c2ecf20Sopenharmony_ci usb3->ep0_req->complete = complete; 15868c2ecf20Sopenharmony_ci renesas_usb3_ep_queue(&usb3_ep->ep, usb3->ep0_req, GFP_ATOMIC); 15878c2ecf20Sopenharmony_ci} 15888c2ecf20Sopenharmony_ci 15898c2ecf20Sopenharmony_cistatic void usb3_pipe0_get_status_completion(struct usb_ep *ep, 15908c2ecf20Sopenharmony_ci struct usb_request *req) 15918c2ecf20Sopenharmony_ci{ 15928c2ecf20Sopenharmony_ci} 15938c2ecf20Sopenharmony_ci 15948c2ecf20Sopenharmony_cistatic bool usb3_std_req_get_status(struct renesas_usb3 *usb3, 15958c2ecf20Sopenharmony_ci struct usb_ctrlrequest *ctrl) 15968c2ecf20Sopenharmony_ci{ 15978c2ecf20Sopenharmony_ci bool stall = false; 15988c2ecf20Sopenharmony_ci struct renesas_usb3_ep *usb3_ep; 15998c2ecf20Sopenharmony_ci int num; 16008c2ecf20Sopenharmony_ci u16 status = 0; 16018c2ecf20Sopenharmony_ci __le16 tx_data; 16028c2ecf20Sopenharmony_ci 16038c2ecf20Sopenharmony_ci switch (ctrl->bRequestType & USB_RECIP_MASK) { 16048c2ecf20Sopenharmony_ci case USB_RECIP_DEVICE: 16058c2ecf20Sopenharmony_ci if (usb3->gadget.is_selfpowered) 16068c2ecf20Sopenharmony_ci status |= 1 << USB_DEVICE_SELF_POWERED; 16078c2ecf20Sopenharmony_ci if (usb3->gadget.speed == USB_SPEED_SUPER) 16088c2ecf20Sopenharmony_ci status |= usb3_feature_get_un_enabled(usb3); 16098c2ecf20Sopenharmony_ci break; 16108c2ecf20Sopenharmony_ci case USB_RECIP_INTERFACE: 16118c2ecf20Sopenharmony_ci break; 16128c2ecf20Sopenharmony_ci case USB_RECIP_ENDPOINT: 16138c2ecf20Sopenharmony_ci num = le16_to_cpu(ctrl->wIndex) & USB_ENDPOINT_NUMBER_MASK; 16148c2ecf20Sopenharmony_ci usb3_ep = usb3_get_ep(usb3, num); 16158c2ecf20Sopenharmony_ci if (usb3_ep->halt) 16168c2ecf20Sopenharmony_ci status |= 1 << USB_ENDPOINT_HALT; 16178c2ecf20Sopenharmony_ci break; 16188c2ecf20Sopenharmony_ci default: 16198c2ecf20Sopenharmony_ci stall = true; 16208c2ecf20Sopenharmony_ci break; 16218c2ecf20Sopenharmony_ci } 16228c2ecf20Sopenharmony_ci 16238c2ecf20Sopenharmony_ci if (!stall) { 16248c2ecf20Sopenharmony_ci tx_data = cpu_to_le16(status); 16258c2ecf20Sopenharmony_ci dev_dbg(usb3_to_dev(usb3), "get_status: req = %p\n", 16268c2ecf20Sopenharmony_ci usb_req_to_usb3_req(usb3->ep0_req)); 16278c2ecf20Sopenharmony_ci usb3_pipe0_internal_xfer(usb3, &tx_data, sizeof(tx_data), 16288c2ecf20Sopenharmony_ci usb3_pipe0_get_status_completion); 16298c2ecf20Sopenharmony_ci } 16308c2ecf20Sopenharmony_ci 16318c2ecf20Sopenharmony_ci return stall; 16328c2ecf20Sopenharmony_ci} 16338c2ecf20Sopenharmony_ci 16348c2ecf20Sopenharmony_cistatic bool usb3_std_req_feature_device(struct renesas_usb3 *usb3, 16358c2ecf20Sopenharmony_ci struct usb_ctrlrequest *ctrl, bool set) 16368c2ecf20Sopenharmony_ci{ 16378c2ecf20Sopenharmony_ci bool stall = true; 16388c2ecf20Sopenharmony_ci u16 w_value = le16_to_cpu(ctrl->wValue); 16398c2ecf20Sopenharmony_ci 16408c2ecf20Sopenharmony_ci switch (w_value) { 16418c2ecf20Sopenharmony_ci case USB_DEVICE_TEST_MODE: 16428c2ecf20Sopenharmony_ci if (!set) 16438c2ecf20Sopenharmony_ci break; 16448c2ecf20Sopenharmony_ci usb3->test_mode = le16_to_cpu(ctrl->wIndex) >> 8; 16458c2ecf20Sopenharmony_ci stall = false; 16468c2ecf20Sopenharmony_ci break; 16478c2ecf20Sopenharmony_ci case USB_DEVICE_U1_ENABLE: 16488c2ecf20Sopenharmony_ci case USB_DEVICE_U2_ENABLE: 16498c2ecf20Sopenharmony_ci if (usb3->gadget.speed != USB_SPEED_SUPER) 16508c2ecf20Sopenharmony_ci break; 16518c2ecf20Sopenharmony_ci if (w_value == USB_DEVICE_U1_ENABLE) 16528c2ecf20Sopenharmony_ci usb3_feature_u1_enable(usb3, set); 16538c2ecf20Sopenharmony_ci if (w_value == USB_DEVICE_U2_ENABLE) 16548c2ecf20Sopenharmony_ci usb3_feature_u2_enable(usb3, set); 16558c2ecf20Sopenharmony_ci stall = false; 16568c2ecf20Sopenharmony_ci break; 16578c2ecf20Sopenharmony_ci default: 16588c2ecf20Sopenharmony_ci break; 16598c2ecf20Sopenharmony_ci } 16608c2ecf20Sopenharmony_ci 16618c2ecf20Sopenharmony_ci return stall; 16628c2ecf20Sopenharmony_ci} 16638c2ecf20Sopenharmony_ci 16648c2ecf20Sopenharmony_cistatic int usb3_set_halt_p0(struct renesas_usb3_ep *usb3_ep, bool halt) 16658c2ecf20Sopenharmony_ci{ 16668c2ecf20Sopenharmony_ci struct renesas_usb3 *usb3 = usb3_ep_to_usb3(usb3_ep); 16678c2ecf20Sopenharmony_ci 16688c2ecf20Sopenharmony_ci if (unlikely(usb3_ep->num)) 16698c2ecf20Sopenharmony_ci return -EINVAL; 16708c2ecf20Sopenharmony_ci 16718c2ecf20Sopenharmony_ci usb3_ep->halt = halt; 16728c2ecf20Sopenharmony_ci if (halt) 16738c2ecf20Sopenharmony_ci usb3_set_p0_con_stall(usb3); 16748c2ecf20Sopenharmony_ci else 16758c2ecf20Sopenharmony_ci usb3_set_p0_con_stop(usb3); 16768c2ecf20Sopenharmony_ci 16778c2ecf20Sopenharmony_ci return 0; 16788c2ecf20Sopenharmony_ci} 16798c2ecf20Sopenharmony_ci 16808c2ecf20Sopenharmony_cistatic int usb3_set_halt_pn(struct renesas_usb3_ep *usb3_ep, bool halt, 16818c2ecf20Sopenharmony_ci bool is_clear_feature) 16828c2ecf20Sopenharmony_ci{ 16838c2ecf20Sopenharmony_ci struct renesas_usb3 *usb3 = usb3_ep_to_usb3(usb3_ep); 16848c2ecf20Sopenharmony_ci unsigned long flags; 16858c2ecf20Sopenharmony_ci 16868c2ecf20Sopenharmony_ci spin_lock_irqsave(&usb3->lock, flags); 16878c2ecf20Sopenharmony_ci if (!usb3_pn_change(usb3, usb3_ep->num)) { 16888c2ecf20Sopenharmony_ci usb3_ep->halt = halt; 16898c2ecf20Sopenharmony_ci if (halt) { 16908c2ecf20Sopenharmony_ci usb3_pn_stall(usb3); 16918c2ecf20Sopenharmony_ci } else if (!is_clear_feature || !usb3_ep->wedge) { 16928c2ecf20Sopenharmony_ci usb3_pn_con_clear(usb3); 16938c2ecf20Sopenharmony_ci usb3_set_bit(usb3, PN_CON_EN, USB3_PN_CON); 16948c2ecf20Sopenharmony_ci usb3_pn_stop(usb3); 16958c2ecf20Sopenharmony_ci } 16968c2ecf20Sopenharmony_ci } 16978c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&usb3->lock, flags); 16988c2ecf20Sopenharmony_ci 16998c2ecf20Sopenharmony_ci return 0; 17008c2ecf20Sopenharmony_ci} 17018c2ecf20Sopenharmony_ci 17028c2ecf20Sopenharmony_cistatic int usb3_set_halt(struct renesas_usb3_ep *usb3_ep, bool halt, 17038c2ecf20Sopenharmony_ci bool is_clear_feature) 17048c2ecf20Sopenharmony_ci{ 17058c2ecf20Sopenharmony_ci int ret = 0; 17068c2ecf20Sopenharmony_ci 17078c2ecf20Sopenharmony_ci if (halt && usb3_ep->started) 17088c2ecf20Sopenharmony_ci return -EAGAIN; 17098c2ecf20Sopenharmony_ci 17108c2ecf20Sopenharmony_ci if (usb3_ep->num) 17118c2ecf20Sopenharmony_ci ret = usb3_set_halt_pn(usb3_ep, halt, is_clear_feature); 17128c2ecf20Sopenharmony_ci else 17138c2ecf20Sopenharmony_ci ret = usb3_set_halt_p0(usb3_ep, halt); 17148c2ecf20Sopenharmony_ci 17158c2ecf20Sopenharmony_ci return ret; 17168c2ecf20Sopenharmony_ci} 17178c2ecf20Sopenharmony_ci 17188c2ecf20Sopenharmony_cistatic bool usb3_std_req_feature_endpoint(struct renesas_usb3 *usb3, 17198c2ecf20Sopenharmony_ci struct usb_ctrlrequest *ctrl, 17208c2ecf20Sopenharmony_ci bool set) 17218c2ecf20Sopenharmony_ci{ 17228c2ecf20Sopenharmony_ci int num = le16_to_cpu(ctrl->wIndex) & USB_ENDPOINT_NUMBER_MASK; 17238c2ecf20Sopenharmony_ci struct renesas_usb3_ep *usb3_ep; 17248c2ecf20Sopenharmony_ci struct renesas_usb3_request *usb3_req; 17258c2ecf20Sopenharmony_ci 17268c2ecf20Sopenharmony_ci if (le16_to_cpu(ctrl->wValue) != USB_ENDPOINT_HALT) 17278c2ecf20Sopenharmony_ci return true; /* stall */ 17288c2ecf20Sopenharmony_ci 17298c2ecf20Sopenharmony_ci usb3_ep = usb3_get_ep(usb3, num); 17308c2ecf20Sopenharmony_ci usb3_set_halt(usb3_ep, set, true); 17318c2ecf20Sopenharmony_ci 17328c2ecf20Sopenharmony_ci /* Restarts a queue if clear feature */ 17338c2ecf20Sopenharmony_ci if (!set) { 17348c2ecf20Sopenharmony_ci usb3_ep->started = false; 17358c2ecf20Sopenharmony_ci usb3_req = usb3_get_request(usb3_ep); 17368c2ecf20Sopenharmony_ci if (usb3_req) 17378c2ecf20Sopenharmony_ci usb3_start_pipen(usb3_ep, usb3_req); 17388c2ecf20Sopenharmony_ci } 17398c2ecf20Sopenharmony_ci 17408c2ecf20Sopenharmony_ci return false; 17418c2ecf20Sopenharmony_ci} 17428c2ecf20Sopenharmony_ci 17438c2ecf20Sopenharmony_cistatic bool usb3_std_req_feature(struct renesas_usb3 *usb3, 17448c2ecf20Sopenharmony_ci struct usb_ctrlrequest *ctrl, bool set) 17458c2ecf20Sopenharmony_ci{ 17468c2ecf20Sopenharmony_ci bool stall = false; 17478c2ecf20Sopenharmony_ci 17488c2ecf20Sopenharmony_ci switch (ctrl->bRequestType & USB_RECIP_MASK) { 17498c2ecf20Sopenharmony_ci case USB_RECIP_DEVICE: 17508c2ecf20Sopenharmony_ci stall = usb3_std_req_feature_device(usb3, ctrl, set); 17518c2ecf20Sopenharmony_ci break; 17528c2ecf20Sopenharmony_ci case USB_RECIP_INTERFACE: 17538c2ecf20Sopenharmony_ci break; 17548c2ecf20Sopenharmony_ci case USB_RECIP_ENDPOINT: 17558c2ecf20Sopenharmony_ci stall = usb3_std_req_feature_endpoint(usb3, ctrl, set); 17568c2ecf20Sopenharmony_ci break; 17578c2ecf20Sopenharmony_ci default: 17588c2ecf20Sopenharmony_ci stall = true; 17598c2ecf20Sopenharmony_ci break; 17608c2ecf20Sopenharmony_ci } 17618c2ecf20Sopenharmony_ci 17628c2ecf20Sopenharmony_ci if (!stall) 17638c2ecf20Sopenharmony_ci usb3_set_p0_con_for_no_data(usb3); 17648c2ecf20Sopenharmony_ci 17658c2ecf20Sopenharmony_ci return stall; 17668c2ecf20Sopenharmony_ci} 17678c2ecf20Sopenharmony_ci 17688c2ecf20Sopenharmony_cistatic void usb3_pipe0_set_sel_completion(struct usb_ep *ep, 17698c2ecf20Sopenharmony_ci struct usb_request *req) 17708c2ecf20Sopenharmony_ci{ 17718c2ecf20Sopenharmony_ci /* TODO */ 17728c2ecf20Sopenharmony_ci} 17738c2ecf20Sopenharmony_ci 17748c2ecf20Sopenharmony_cistatic bool usb3_std_req_set_sel(struct renesas_usb3 *usb3, 17758c2ecf20Sopenharmony_ci struct usb_ctrlrequest *ctrl) 17768c2ecf20Sopenharmony_ci{ 17778c2ecf20Sopenharmony_ci u16 w_length = le16_to_cpu(ctrl->wLength); 17788c2ecf20Sopenharmony_ci 17798c2ecf20Sopenharmony_ci if (w_length != 6) 17808c2ecf20Sopenharmony_ci return true; /* stall */ 17818c2ecf20Sopenharmony_ci 17828c2ecf20Sopenharmony_ci dev_dbg(usb3_to_dev(usb3), "set_sel: req = %p\n", 17838c2ecf20Sopenharmony_ci usb_req_to_usb3_req(usb3->ep0_req)); 17848c2ecf20Sopenharmony_ci usb3_pipe0_internal_xfer(usb3, NULL, 6, usb3_pipe0_set_sel_completion); 17858c2ecf20Sopenharmony_ci 17868c2ecf20Sopenharmony_ci return false; 17878c2ecf20Sopenharmony_ci} 17888c2ecf20Sopenharmony_ci 17898c2ecf20Sopenharmony_cistatic bool usb3_std_req_set_configuration(struct renesas_usb3 *usb3, 17908c2ecf20Sopenharmony_ci struct usb_ctrlrequest *ctrl) 17918c2ecf20Sopenharmony_ci{ 17928c2ecf20Sopenharmony_ci if (le16_to_cpu(ctrl->wValue) > 0) 17938c2ecf20Sopenharmony_ci usb3_set_bit(usb3, USB_COM_CON_CONF, USB3_USB_COM_CON); 17948c2ecf20Sopenharmony_ci else 17958c2ecf20Sopenharmony_ci usb3_clear_bit(usb3, USB_COM_CON_CONF, USB3_USB_COM_CON); 17968c2ecf20Sopenharmony_ci 17978c2ecf20Sopenharmony_ci return false; 17988c2ecf20Sopenharmony_ci} 17998c2ecf20Sopenharmony_ci 18008c2ecf20Sopenharmony_ci/** 18018c2ecf20Sopenharmony_ci * usb3_handle_standard_request - handle some standard requests 18028c2ecf20Sopenharmony_ci * @usb3: the renesas_usb3 pointer 18038c2ecf20Sopenharmony_ci * @ctrl: a pointer of setup data 18048c2ecf20Sopenharmony_ci * 18058c2ecf20Sopenharmony_ci * Returns true if this function handled a standard request 18068c2ecf20Sopenharmony_ci */ 18078c2ecf20Sopenharmony_cistatic bool usb3_handle_standard_request(struct renesas_usb3 *usb3, 18088c2ecf20Sopenharmony_ci struct usb_ctrlrequest *ctrl) 18098c2ecf20Sopenharmony_ci{ 18108c2ecf20Sopenharmony_ci bool ret = false; 18118c2ecf20Sopenharmony_ci bool stall = false; 18128c2ecf20Sopenharmony_ci 18138c2ecf20Sopenharmony_ci if ((ctrl->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) { 18148c2ecf20Sopenharmony_ci switch (ctrl->bRequest) { 18158c2ecf20Sopenharmony_ci case USB_REQ_SET_ADDRESS: 18168c2ecf20Sopenharmony_ci stall = usb3_std_req_set_address(usb3, ctrl); 18178c2ecf20Sopenharmony_ci ret = true; 18188c2ecf20Sopenharmony_ci break; 18198c2ecf20Sopenharmony_ci case USB_REQ_GET_STATUS: 18208c2ecf20Sopenharmony_ci stall = usb3_std_req_get_status(usb3, ctrl); 18218c2ecf20Sopenharmony_ci ret = true; 18228c2ecf20Sopenharmony_ci break; 18238c2ecf20Sopenharmony_ci case USB_REQ_CLEAR_FEATURE: 18248c2ecf20Sopenharmony_ci stall = usb3_std_req_feature(usb3, ctrl, false); 18258c2ecf20Sopenharmony_ci ret = true; 18268c2ecf20Sopenharmony_ci break; 18278c2ecf20Sopenharmony_ci case USB_REQ_SET_FEATURE: 18288c2ecf20Sopenharmony_ci stall = usb3_std_req_feature(usb3, ctrl, true); 18298c2ecf20Sopenharmony_ci ret = true; 18308c2ecf20Sopenharmony_ci break; 18318c2ecf20Sopenharmony_ci case USB_REQ_SET_SEL: 18328c2ecf20Sopenharmony_ci stall = usb3_std_req_set_sel(usb3, ctrl); 18338c2ecf20Sopenharmony_ci ret = true; 18348c2ecf20Sopenharmony_ci break; 18358c2ecf20Sopenharmony_ci case USB_REQ_SET_ISOCH_DELAY: 18368c2ecf20Sopenharmony_ci /* This hardware doesn't support Isochronous xfer */ 18378c2ecf20Sopenharmony_ci stall = true; 18388c2ecf20Sopenharmony_ci ret = true; 18398c2ecf20Sopenharmony_ci break; 18408c2ecf20Sopenharmony_ci case USB_REQ_SET_CONFIGURATION: 18418c2ecf20Sopenharmony_ci usb3_std_req_set_configuration(usb3, ctrl); 18428c2ecf20Sopenharmony_ci break; 18438c2ecf20Sopenharmony_ci default: 18448c2ecf20Sopenharmony_ci break; 18458c2ecf20Sopenharmony_ci } 18468c2ecf20Sopenharmony_ci } 18478c2ecf20Sopenharmony_ci 18488c2ecf20Sopenharmony_ci if (stall) 18498c2ecf20Sopenharmony_ci usb3_set_p0_con_stall(usb3); 18508c2ecf20Sopenharmony_ci 18518c2ecf20Sopenharmony_ci return ret; 18528c2ecf20Sopenharmony_ci} 18538c2ecf20Sopenharmony_ci 18548c2ecf20Sopenharmony_cistatic int usb3_p0_con_clear_buffer(struct renesas_usb3 *usb3) 18558c2ecf20Sopenharmony_ci{ 18568c2ecf20Sopenharmony_ci usb3_set_bit(usb3, P0_CON_BCLR, USB3_P0_CON); 18578c2ecf20Sopenharmony_ci 18588c2ecf20Sopenharmony_ci return usb3_wait(usb3, USB3_P0_CON, P0_CON_BCLR, 0); 18598c2ecf20Sopenharmony_ci} 18608c2ecf20Sopenharmony_ci 18618c2ecf20Sopenharmony_cistatic void usb3_irq_epc_pipe0_setup(struct renesas_usb3 *usb3) 18628c2ecf20Sopenharmony_ci{ 18638c2ecf20Sopenharmony_ci struct usb_ctrlrequest ctrl; 18648c2ecf20Sopenharmony_ci struct renesas_usb3_ep *usb3_ep = usb3_get_ep(usb3, 0); 18658c2ecf20Sopenharmony_ci 18668c2ecf20Sopenharmony_ci /* Call giveback function if previous transfer is not completed */ 18678c2ecf20Sopenharmony_ci if (usb3_ep->started) 18688c2ecf20Sopenharmony_ci usb3_request_done(usb3_ep, usb3_get_request(usb3_ep), 18698c2ecf20Sopenharmony_ci -ECONNRESET); 18708c2ecf20Sopenharmony_ci 18718c2ecf20Sopenharmony_ci usb3_p0_con_clear_buffer(usb3); 18728c2ecf20Sopenharmony_ci usb3_get_setup_data(usb3, &ctrl); 18738c2ecf20Sopenharmony_ci if (!usb3_handle_standard_request(usb3, &ctrl)) 18748c2ecf20Sopenharmony_ci if (usb3->driver->setup(&usb3->gadget, &ctrl) < 0) 18758c2ecf20Sopenharmony_ci usb3_set_p0_con_stall(usb3); 18768c2ecf20Sopenharmony_ci} 18778c2ecf20Sopenharmony_ci 18788c2ecf20Sopenharmony_cistatic void usb3_irq_epc_pipe0_bfrdy(struct renesas_usb3 *usb3) 18798c2ecf20Sopenharmony_ci{ 18808c2ecf20Sopenharmony_ci struct renesas_usb3_ep *usb3_ep = usb3_get_ep(usb3, 0); 18818c2ecf20Sopenharmony_ci struct renesas_usb3_request *usb3_req = usb3_get_request(usb3_ep); 18828c2ecf20Sopenharmony_ci 18838c2ecf20Sopenharmony_ci if (!usb3_req) 18848c2ecf20Sopenharmony_ci return; 18858c2ecf20Sopenharmony_ci 18868c2ecf20Sopenharmony_ci usb3_p0_xfer(usb3_ep, usb3_req); 18878c2ecf20Sopenharmony_ci} 18888c2ecf20Sopenharmony_ci 18898c2ecf20Sopenharmony_cistatic void usb3_irq_epc_pipe0(struct renesas_usb3 *usb3) 18908c2ecf20Sopenharmony_ci{ 18918c2ecf20Sopenharmony_ci u32 p0_int_sta = usb3_read(usb3, USB3_P0_INT_STA); 18928c2ecf20Sopenharmony_ci 18938c2ecf20Sopenharmony_ci p0_int_sta &= usb3_read(usb3, USB3_P0_INT_ENA); 18948c2ecf20Sopenharmony_ci usb3_write(usb3, p0_int_sta, USB3_P0_INT_STA); 18958c2ecf20Sopenharmony_ci if (p0_int_sta & P0_INT_STSED) 18968c2ecf20Sopenharmony_ci usb3_irq_epc_pipe0_status_end(usb3); 18978c2ecf20Sopenharmony_ci if (p0_int_sta & P0_INT_SETUP) 18988c2ecf20Sopenharmony_ci usb3_irq_epc_pipe0_setup(usb3); 18998c2ecf20Sopenharmony_ci if (p0_int_sta & P0_INT_BFRDY) 19008c2ecf20Sopenharmony_ci usb3_irq_epc_pipe0_bfrdy(usb3); 19018c2ecf20Sopenharmony_ci} 19028c2ecf20Sopenharmony_ci 19038c2ecf20Sopenharmony_cistatic void usb3_request_done_pipen(struct renesas_usb3 *usb3, 19048c2ecf20Sopenharmony_ci struct renesas_usb3_ep *usb3_ep, 19058c2ecf20Sopenharmony_ci struct renesas_usb3_request *usb3_req, 19068c2ecf20Sopenharmony_ci int status) 19078c2ecf20Sopenharmony_ci{ 19088c2ecf20Sopenharmony_ci unsigned long flags; 19098c2ecf20Sopenharmony_ci 19108c2ecf20Sopenharmony_ci spin_lock_irqsave(&usb3->lock, flags); 19118c2ecf20Sopenharmony_ci if (usb3_pn_change(usb3, usb3_ep->num)) 19128c2ecf20Sopenharmony_ci usb3_pn_stop(usb3); 19138c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&usb3->lock, flags); 19148c2ecf20Sopenharmony_ci 19158c2ecf20Sopenharmony_ci usb3_disable_pipe_irq(usb3, usb3_ep->num); 19168c2ecf20Sopenharmony_ci usb3_request_done(usb3_ep, usb3_req, status); 19178c2ecf20Sopenharmony_ci 19188c2ecf20Sopenharmony_ci /* get next usb3_req */ 19198c2ecf20Sopenharmony_ci usb3_req = usb3_get_request(usb3_ep); 19208c2ecf20Sopenharmony_ci if (usb3_req) 19218c2ecf20Sopenharmony_ci usb3_start_pipen(usb3_ep, usb3_req); 19228c2ecf20Sopenharmony_ci} 19238c2ecf20Sopenharmony_ci 19248c2ecf20Sopenharmony_cistatic void usb3_irq_epc_pipen_lsttr(struct renesas_usb3 *usb3, int num) 19258c2ecf20Sopenharmony_ci{ 19268c2ecf20Sopenharmony_ci struct renesas_usb3_ep *usb3_ep = usb3_get_ep(usb3, num); 19278c2ecf20Sopenharmony_ci struct renesas_usb3_request *usb3_req = usb3_get_request(usb3_ep); 19288c2ecf20Sopenharmony_ci 19298c2ecf20Sopenharmony_ci if (!usb3_req) 19308c2ecf20Sopenharmony_ci return; 19318c2ecf20Sopenharmony_ci 19328c2ecf20Sopenharmony_ci if (usb3_ep->dir_in) { 19338c2ecf20Sopenharmony_ci dev_dbg(usb3_to_dev(usb3), "%s: len = %u, actual = %u\n", 19348c2ecf20Sopenharmony_ci __func__, usb3_req->req.length, usb3_req->req.actual); 19358c2ecf20Sopenharmony_ci usb3_request_done_pipen(usb3, usb3_ep, usb3_req, 0); 19368c2ecf20Sopenharmony_ci } 19378c2ecf20Sopenharmony_ci} 19388c2ecf20Sopenharmony_ci 19398c2ecf20Sopenharmony_cistatic void usb3_irq_epc_pipen_bfrdy(struct renesas_usb3 *usb3, int num) 19408c2ecf20Sopenharmony_ci{ 19418c2ecf20Sopenharmony_ci struct renesas_usb3_ep *usb3_ep = usb3_get_ep(usb3, num); 19428c2ecf20Sopenharmony_ci struct renesas_usb3_request *usb3_req = usb3_get_request(usb3_ep); 19438c2ecf20Sopenharmony_ci bool done = false; 19448c2ecf20Sopenharmony_ci 19458c2ecf20Sopenharmony_ci if (!usb3_req) 19468c2ecf20Sopenharmony_ci return; 19478c2ecf20Sopenharmony_ci 19488c2ecf20Sopenharmony_ci spin_lock(&usb3->lock); 19498c2ecf20Sopenharmony_ci if (usb3_pn_change(usb3, num)) 19508c2ecf20Sopenharmony_ci goto out; 19518c2ecf20Sopenharmony_ci 19528c2ecf20Sopenharmony_ci if (usb3_ep->dir_in) { 19538c2ecf20Sopenharmony_ci /* Do not stop the IN pipe here to detect LSTTR interrupt */ 19548c2ecf20Sopenharmony_ci if (!usb3_write_pipe(usb3_ep, usb3_req, USB3_PN_WRITE)) 19558c2ecf20Sopenharmony_ci usb3_clear_bit(usb3, PN_INT_BFRDY, USB3_PN_INT_ENA); 19568c2ecf20Sopenharmony_ci } else { 19578c2ecf20Sopenharmony_ci if (!usb3_read_pipe(usb3_ep, usb3_req, USB3_PN_READ)) 19588c2ecf20Sopenharmony_ci done = true; 19598c2ecf20Sopenharmony_ci } 19608c2ecf20Sopenharmony_ci 19618c2ecf20Sopenharmony_ciout: 19628c2ecf20Sopenharmony_ci /* need to unlock because usb3_request_done_pipen() locks it */ 19638c2ecf20Sopenharmony_ci spin_unlock(&usb3->lock); 19648c2ecf20Sopenharmony_ci 19658c2ecf20Sopenharmony_ci if (done) 19668c2ecf20Sopenharmony_ci usb3_request_done_pipen(usb3, usb3_ep, usb3_req, 0); 19678c2ecf20Sopenharmony_ci} 19688c2ecf20Sopenharmony_ci 19698c2ecf20Sopenharmony_cistatic void usb3_irq_epc_pipen(struct renesas_usb3 *usb3, int num) 19708c2ecf20Sopenharmony_ci{ 19718c2ecf20Sopenharmony_ci u32 pn_int_sta; 19728c2ecf20Sopenharmony_ci 19738c2ecf20Sopenharmony_ci spin_lock(&usb3->lock); 19748c2ecf20Sopenharmony_ci if (usb3_pn_change(usb3, num) < 0) { 19758c2ecf20Sopenharmony_ci spin_unlock(&usb3->lock); 19768c2ecf20Sopenharmony_ci return; 19778c2ecf20Sopenharmony_ci } 19788c2ecf20Sopenharmony_ci 19798c2ecf20Sopenharmony_ci pn_int_sta = usb3_read(usb3, USB3_PN_INT_STA); 19808c2ecf20Sopenharmony_ci pn_int_sta &= usb3_read(usb3, USB3_PN_INT_ENA); 19818c2ecf20Sopenharmony_ci usb3_write(usb3, pn_int_sta, USB3_PN_INT_STA); 19828c2ecf20Sopenharmony_ci spin_unlock(&usb3->lock); 19838c2ecf20Sopenharmony_ci if (pn_int_sta & PN_INT_LSTTR) 19848c2ecf20Sopenharmony_ci usb3_irq_epc_pipen_lsttr(usb3, num); 19858c2ecf20Sopenharmony_ci if (pn_int_sta & PN_INT_BFRDY) 19868c2ecf20Sopenharmony_ci usb3_irq_epc_pipen_bfrdy(usb3, num); 19878c2ecf20Sopenharmony_ci} 19888c2ecf20Sopenharmony_ci 19898c2ecf20Sopenharmony_cistatic void usb3_irq_epc_int_2(struct renesas_usb3 *usb3, u32 int_sta_2) 19908c2ecf20Sopenharmony_ci{ 19918c2ecf20Sopenharmony_ci int i; 19928c2ecf20Sopenharmony_ci 19938c2ecf20Sopenharmony_ci for (i = 0; i < usb3->num_usb3_eps; i++) { 19948c2ecf20Sopenharmony_ci if (int_sta_2 & USB_INT_2_PIPE(i)) { 19958c2ecf20Sopenharmony_ci if (!i) 19968c2ecf20Sopenharmony_ci usb3_irq_epc_pipe0(usb3); 19978c2ecf20Sopenharmony_ci else 19988c2ecf20Sopenharmony_ci usb3_irq_epc_pipen(usb3, i); 19998c2ecf20Sopenharmony_ci } 20008c2ecf20Sopenharmony_ci } 20018c2ecf20Sopenharmony_ci} 20028c2ecf20Sopenharmony_ci 20038c2ecf20Sopenharmony_cistatic void usb3_irq_idmon_change(struct renesas_usb3 *usb3) 20048c2ecf20Sopenharmony_ci{ 20058c2ecf20Sopenharmony_ci usb3_check_id(usb3); 20068c2ecf20Sopenharmony_ci} 20078c2ecf20Sopenharmony_ci 20088c2ecf20Sopenharmony_cistatic void usb3_irq_otg_int(struct renesas_usb3 *usb3, u32 otg_int_sta) 20098c2ecf20Sopenharmony_ci{ 20108c2ecf20Sopenharmony_ci if (otg_int_sta & USB_OTG_IDMON) 20118c2ecf20Sopenharmony_ci usb3_irq_idmon_change(usb3); 20128c2ecf20Sopenharmony_ci} 20138c2ecf20Sopenharmony_ci 20148c2ecf20Sopenharmony_cistatic void usb3_irq_epc(struct renesas_usb3 *usb3) 20158c2ecf20Sopenharmony_ci{ 20168c2ecf20Sopenharmony_ci u32 int_sta_1 = usb3_read(usb3, USB3_USB_INT_STA_1); 20178c2ecf20Sopenharmony_ci u32 int_sta_2 = usb3_read(usb3, USB3_USB_INT_STA_2); 20188c2ecf20Sopenharmony_ci u32 otg_int_sta = usb3_read(usb3, USB3_USB_OTG_INT_STA); 20198c2ecf20Sopenharmony_ci 20208c2ecf20Sopenharmony_ci int_sta_1 &= usb3_read(usb3, USB3_USB_INT_ENA_1); 20218c2ecf20Sopenharmony_ci if (int_sta_1) { 20228c2ecf20Sopenharmony_ci usb3_write(usb3, int_sta_1, USB3_USB_INT_STA_1); 20238c2ecf20Sopenharmony_ci usb3_irq_epc_int_1(usb3, int_sta_1); 20248c2ecf20Sopenharmony_ci } 20258c2ecf20Sopenharmony_ci 20268c2ecf20Sopenharmony_ci int_sta_2 &= usb3_read(usb3, USB3_USB_INT_ENA_2); 20278c2ecf20Sopenharmony_ci if (int_sta_2) 20288c2ecf20Sopenharmony_ci usb3_irq_epc_int_2(usb3, int_sta_2); 20298c2ecf20Sopenharmony_ci 20308c2ecf20Sopenharmony_ci otg_int_sta &= usb3_read(usb3, USB3_USB_OTG_INT_ENA); 20318c2ecf20Sopenharmony_ci if (otg_int_sta) { 20328c2ecf20Sopenharmony_ci usb3_write(usb3, otg_int_sta, USB3_USB_OTG_INT_STA); 20338c2ecf20Sopenharmony_ci usb3_irq_otg_int(usb3, otg_int_sta); 20348c2ecf20Sopenharmony_ci } 20358c2ecf20Sopenharmony_ci} 20368c2ecf20Sopenharmony_ci 20378c2ecf20Sopenharmony_cistatic void usb3_irq_dma_int(struct renesas_usb3 *usb3, u32 dma_sta) 20388c2ecf20Sopenharmony_ci{ 20398c2ecf20Sopenharmony_ci struct renesas_usb3_ep *usb3_ep; 20408c2ecf20Sopenharmony_ci struct renesas_usb3_request *usb3_req; 20418c2ecf20Sopenharmony_ci int i, status; 20428c2ecf20Sopenharmony_ci 20438c2ecf20Sopenharmony_ci for (i = 0; i < usb3->num_usb3_eps; i++) { 20448c2ecf20Sopenharmony_ci if (!(dma_sta & DMA_INT(i))) 20458c2ecf20Sopenharmony_ci continue; 20468c2ecf20Sopenharmony_ci 20478c2ecf20Sopenharmony_ci usb3_ep = usb3_get_ep(usb3, i); 20488c2ecf20Sopenharmony_ci if (!(usb3_read(usb3, USB3_AXI_INT_STA) & 20498c2ecf20Sopenharmony_ci AXI_INT_PRDEN_CLR_STA(usb3_ep->dma->num))) 20508c2ecf20Sopenharmony_ci continue; 20518c2ecf20Sopenharmony_ci 20528c2ecf20Sopenharmony_ci usb3_req = usb3_get_request(usb3_ep); 20538c2ecf20Sopenharmony_ci status = usb3_dma_try_stop(usb3_ep, usb3_req); 20548c2ecf20Sopenharmony_ci usb3_request_done_pipen(usb3, usb3_ep, usb3_req, status); 20558c2ecf20Sopenharmony_ci } 20568c2ecf20Sopenharmony_ci} 20578c2ecf20Sopenharmony_ci 20588c2ecf20Sopenharmony_cistatic void usb3_irq_dma(struct renesas_usb3 *usb3) 20598c2ecf20Sopenharmony_ci{ 20608c2ecf20Sopenharmony_ci u32 dma_sta = usb3_read(usb3, USB3_DMA_INT_STA); 20618c2ecf20Sopenharmony_ci 20628c2ecf20Sopenharmony_ci dma_sta &= usb3_read(usb3, USB3_DMA_INT_ENA); 20638c2ecf20Sopenharmony_ci if (dma_sta) { 20648c2ecf20Sopenharmony_ci usb3_write(usb3, dma_sta, USB3_DMA_INT_STA); 20658c2ecf20Sopenharmony_ci usb3_irq_dma_int(usb3, dma_sta); 20668c2ecf20Sopenharmony_ci } 20678c2ecf20Sopenharmony_ci} 20688c2ecf20Sopenharmony_ci 20698c2ecf20Sopenharmony_cistatic irqreturn_t renesas_usb3_irq(int irq, void *_usb3) 20708c2ecf20Sopenharmony_ci{ 20718c2ecf20Sopenharmony_ci struct renesas_usb3 *usb3 = _usb3; 20728c2ecf20Sopenharmony_ci irqreturn_t ret = IRQ_NONE; 20738c2ecf20Sopenharmony_ci u32 axi_int_sta = usb3_read(usb3, USB3_AXI_INT_STA); 20748c2ecf20Sopenharmony_ci 20758c2ecf20Sopenharmony_ci if (axi_int_sta & AXI_INT_DMAINT) { 20768c2ecf20Sopenharmony_ci usb3_irq_dma(usb3); 20778c2ecf20Sopenharmony_ci ret = IRQ_HANDLED; 20788c2ecf20Sopenharmony_ci } 20798c2ecf20Sopenharmony_ci 20808c2ecf20Sopenharmony_ci if (axi_int_sta & AXI_INT_EPCINT) { 20818c2ecf20Sopenharmony_ci usb3_irq_epc(usb3); 20828c2ecf20Sopenharmony_ci ret = IRQ_HANDLED; 20838c2ecf20Sopenharmony_ci } 20848c2ecf20Sopenharmony_ci 20858c2ecf20Sopenharmony_ci return ret; 20868c2ecf20Sopenharmony_ci} 20878c2ecf20Sopenharmony_ci 20888c2ecf20Sopenharmony_cistatic void usb3_write_pn_mod(struct renesas_usb3_ep *usb3_ep, 20898c2ecf20Sopenharmony_ci const struct usb_endpoint_descriptor *desc) 20908c2ecf20Sopenharmony_ci{ 20918c2ecf20Sopenharmony_ci struct renesas_usb3 *usb3 = usb3_ep_to_usb3(usb3_ep); 20928c2ecf20Sopenharmony_ci u32 val = 0; 20938c2ecf20Sopenharmony_ci 20948c2ecf20Sopenharmony_ci val |= usb3_ep->dir_in ? PN_MOD_DIR : 0; 20958c2ecf20Sopenharmony_ci val |= PN_MOD_TYPE(usb_endpoint_type(desc)); 20968c2ecf20Sopenharmony_ci val |= PN_MOD_EPNUM(usb_endpoint_num(desc)); 20978c2ecf20Sopenharmony_ci usb3_write(usb3, val, USB3_PN_MOD); 20988c2ecf20Sopenharmony_ci} 20998c2ecf20Sopenharmony_ci 21008c2ecf20Sopenharmony_cistatic u32 usb3_calc_ramarea(int ram_size) 21018c2ecf20Sopenharmony_ci{ 21028c2ecf20Sopenharmony_ci WARN_ON(ram_size > SZ_16K); 21038c2ecf20Sopenharmony_ci 21048c2ecf20Sopenharmony_ci if (ram_size <= SZ_1K) 21058c2ecf20Sopenharmony_ci return PN_RAMMAP_RAMAREA_1KB; 21068c2ecf20Sopenharmony_ci else if (ram_size <= SZ_2K) 21078c2ecf20Sopenharmony_ci return PN_RAMMAP_RAMAREA_2KB; 21088c2ecf20Sopenharmony_ci else if (ram_size <= SZ_4K) 21098c2ecf20Sopenharmony_ci return PN_RAMMAP_RAMAREA_4KB; 21108c2ecf20Sopenharmony_ci else if (ram_size <= SZ_8K) 21118c2ecf20Sopenharmony_ci return PN_RAMMAP_RAMAREA_8KB; 21128c2ecf20Sopenharmony_ci else 21138c2ecf20Sopenharmony_ci return PN_RAMMAP_RAMAREA_16KB; 21148c2ecf20Sopenharmony_ci} 21158c2ecf20Sopenharmony_ci 21168c2ecf20Sopenharmony_cistatic u32 usb3_calc_rammap_val(struct renesas_usb3_ep *usb3_ep, 21178c2ecf20Sopenharmony_ci const struct usb_endpoint_descriptor *desc) 21188c2ecf20Sopenharmony_ci{ 21198c2ecf20Sopenharmony_ci int i; 21208c2ecf20Sopenharmony_ci static const u32 max_packet_array[] = {8, 16, 32, 64, 512}; 21218c2ecf20Sopenharmony_ci u32 mpkt = PN_RAMMAP_MPKT(1024); 21228c2ecf20Sopenharmony_ci 21238c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(max_packet_array); i++) { 21248c2ecf20Sopenharmony_ci if (usb_endpoint_maxp(desc) <= max_packet_array[i]) 21258c2ecf20Sopenharmony_ci mpkt = PN_RAMMAP_MPKT(max_packet_array[i]); 21268c2ecf20Sopenharmony_ci } 21278c2ecf20Sopenharmony_ci 21288c2ecf20Sopenharmony_ci return usb3_ep->rammap_val | mpkt; 21298c2ecf20Sopenharmony_ci} 21308c2ecf20Sopenharmony_ci 21318c2ecf20Sopenharmony_cistatic int usb3_enable_pipe_n(struct renesas_usb3_ep *usb3_ep, 21328c2ecf20Sopenharmony_ci const struct usb_endpoint_descriptor *desc) 21338c2ecf20Sopenharmony_ci{ 21348c2ecf20Sopenharmony_ci struct renesas_usb3 *usb3 = usb3_ep_to_usb3(usb3_ep); 21358c2ecf20Sopenharmony_ci unsigned long flags; 21368c2ecf20Sopenharmony_ci 21378c2ecf20Sopenharmony_ci usb3_ep->dir_in = usb_endpoint_dir_in(desc); 21388c2ecf20Sopenharmony_ci 21398c2ecf20Sopenharmony_ci spin_lock_irqsave(&usb3->lock, flags); 21408c2ecf20Sopenharmony_ci if (!usb3_pn_change(usb3, usb3_ep->num)) { 21418c2ecf20Sopenharmony_ci usb3_write_pn_mod(usb3_ep, desc); 21428c2ecf20Sopenharmony_ci usb3_write(usb3, usb3_calc_rammap_val(usb3_ep, desc), 21438c2ecf20Sopenharmony_ci USB3_PN_RAMMAP); 21448c2ecf20Sopenharmony_ci usb3_pn_con_clear(usb3); 21458c2ecf20Sopenharmony_ci usb3_set_bit(usb3, PN_CON_EN, USB3_PN_CON); 21468c2ecf20Sopenharmony_ci } 21478c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&usb3->lock, flags); 21488c2ecf20Sopenharmony_ci 21498c2ecf20Sopenharmony_ci return 0; 21508c2ecf20Sopenharmony_ci} 21518c2ecf20Sopenharmony_ci 21528c2ecf20Sopenharmony_cistatic int usb3_disable_pipe_n(struct renesas_usb3_ep *usb3_ep) 21538c2ecf20Sopenharmony_ci{ 21548c2ecf20Sopenharmony_ci struct renesas_usb3 *usb3 = usb3_ep_to_usb3(usb3_ep); 21558c2ecf20Sopenharmony_ci unsigned long flags; 21568c2ecf20Sopenharmony_ci 21578c2ecf20Sopenharmony_ci usb3_ep->halt = false; 21588c2ecf20Sopenharmony_ci 21598c2ecf20Sopenharmony_ci spin_lock_irqsave(&usb3->lock, flags); 21608c2ecf20Sopenharmony_ci if (!usb3_pn_change(usb3, usb3_ep->num)) { 21618c2ecf20Sopenharmony_ci usb3_write(usb3, 0, USB3_PN_INT_ENA); 21628c2ecf20Sopenharmony_ci usb3_write(usb3, 0, USB3_PN_RAMMAP); 21638c2ecf20Sopenharmony_ci usb3_clear_bit(usb3, PN_CON_EN, USB3_PN_CON); 21648c2ecf20Sopenharmony_ci } 21658c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&usb3->lock, flags); 21668c2ecf20Sopenharmony_ci 21678c2ecf20Sopenharmony_ci return 0; 21688c2ecf20Sopenharmony_ci} 21698c2ecf20Sopenharmony_ci 21708c2ecf20Sopenharmony_ci/*------- usb_ep_ops -----------------------------------------------------*/ 21718c2ecf20Sopenharmony_cistatic int renesas_usb3_ep_enable(struct usb_ep *_ep, 21728c2ecf20Sopenharmony_ci const struct usb_endpoint_descriptor *desc) 21738c2ecf20Sopenharmony_ci{ 21748c2ecf20Sopenharmony_ci struct renesas_usb3_ep *usb3_ep = usb_ep_to_usb3_ep(_ep); 21758c2ecf20Sopenharmony_ci 21768c2ecf20Sopenharmony_ci return usb3_enable_pipe_n(usb3_ep, desc); 21778c2ecf20Sopenharmony_ci} 21788c2ecf20Sopenharmony_ci 21798c2ecf20Sopenharmony_cistatic int renesas_usb3_ep_disable(struct usb_ep *_ep) 21808c2ecf20Sopenharmony_ci{ 21818c2ecf20Sopenharmony_ci struct renesas_usb3_ep *usb3_ep = usb_ep_to_usb3_ep(_ep); 21828c2ecf20Sopenharmony_ci struct renesas_usb3_request *usb3_req; 21838c2ecf20Sopenharmony_ci 21848c2ecf20Sopenharmony_ci do { 21858c2ecf20Sopenharmony_ci usb3_req = usb3_get_request(usb3_ep); 21868c2ecf20Sopenharmony_ci if (!usb3_req) 21878c2ecf20Sopenharmony_ci break; 21888c2ecf20Sopenharmony_ci usb3_dma_try_stop(usb3_ep, usb3_req); 21898c2ecf20Sopenharmony_ci usb3_request_done(usb3_ep, usb3_req, -ESHUTDOWN); 21908c2ecf20Sopenharmony_ci } while (1); 21918c2ecf20Sopenharmony_ci 21928c2ecf20Sopenharmony_ci return usb3_disable_pipe_n(usb3_ep); 21938c2ecf20Sopenharmony_ci} 21948c2ecf20Sopenharmony_ci 21958c2ecf20Sopenharmony_cistatic struct usb_request *__renesas_usb3_ep_alloc_request(gfp_t gfp_flags) 21968c2ecf20Sopenharmony_ci{ 21978c2ecf20Sopenharmony_ci struct renesas_usb3_request *usb3_req; 21988c2ecf20Sopenharmony_ci 21998c2ecf20Sopenharmony_ci usb3_req = kzalloc(sizeof(struct renesas_usb3_request), gfp_flags); 22008c2ecf20Sopenharmony_ci if (!usb3_req) 22018c2ecf20Sopenharmony_ci return NULL; 22028c2ecf20Sopenharmony_ci 22038c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&usb3_req->queue); 22048c2ecf20Sopenharmony_ci 22058c2ecf20Sopenharmony_ci return &usb3_req->req; 22068c2ecf20Sopenharmony_ci} 22078c2ecf20Sopenharmony_ci 22088c2ecf20Sopenharmony_cistatic void __renesas_usb3_ep_free_request(struct usb_request *_req) 22098c2ecf20Sopenharmony_ci{ 22108c2ecf20Sopenharmony_ci struct renesas_usb3_request *usb3_req = usb_req_to_usb3_req(_req); 22118c2ecf20Sopenharmony_ci 22128c2ecf20Sopenharmony_ci kfree(usb3_req); 22138c2ecf20Sopenharmony_ci} 22148c2ecf20Sopenharmony_ci 22158c2ecf20Sopenharmony_cistatic struct usb_request *renesas_usb3_ep_alloc_request(struct usb_ep *_ep, 22168c2ecf20Sopenharmony_ci gfp_t gfp_flags) 22178c2ecf20Sopenharmony_ci{ 22188c2ecf20Sopenharmony_ci return __renesas_usb3_ep_alloc_request(gfp_flags); 22198c2ecf20Sopenharmony_ci} 22208c2ecf20Sopenharmony_ci 22218c2ecf20Sopenharmony_cistatic void renesas_usb3_ep_free_request(struct usb_ep *_ep, 22228c2ecf20Sopenharmony_ci struct usb_request *_req) 22238c2ecf20Sopenharmony_ci{ 22248c2ecf20Sopenharmony_ci __renesas_usb3_ep_free_request(_req); 22258c2ecf20Sopenharmony_ci} 22268c2ecf20Sopenharmony_ci 22278c2ecf20Sopenharmony_cistatic int renesas_usb3_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req) 22288c2ecf20Sopenharmony_ci{ 22298c2ecf20Sopenharmony_ci struct renesas_usb3_ep *usb3_ep = usb_ep_to_usb3_ep(_ep); 22308c2ecf20Sopenharmony_ci struct renesas_usb3_request *usb3_req = usb_req_to_usb3_req(_req); 22318c2ecf20Sopenharmony_ci struct renesas_usb3 *usb3 = usb3_ep_to_usb3(usb3_ep); 22328c2ecf20Sopenharmony_ci 22338c2ecf20Sopenharmony_ci dev_dbg(usb3_to_dev(usb3), "ep_dequeue: ep%2d, %u\n", usb3_ep->num, 22348c2ecf20Sopenharmony_ci _req->length); 22358c2ecf20Sopenharmony_ci 22368c2ecf20Sopenharmony_ci usb3_dma_try_stop(usb3_ep, usb3_req); 22378c2ecf20Sopenharmony_ci usb3_request_done_pipen(usb3, usb3_ep, usb3_req, -ECONNRESET); 22388c2ecf20Sopenharmony_ci 22398c2ecf20Sopenharmony_ci return 0; 22408c2ecf20Sopenharmony_ci} 22418c2ecf20Sopenharmony_ci 22428c2ecf20Sopenharmony_cistatic int renesas_usb3_ep_set_halt(struct usb_ep *_ep, int value) 22438c2ecf20Sopenharmony_ci{ 22448c2ecf20Sopenharmony_ci return usb3_set_halt(usb_ep_to_usb3_ep(_ep), !!value, false); 22458c2ecf20Sopenharmony_ci} 22468c2ecf20Sopenharmony_ci 22478c2ecf20Sopenharmony_cistatic int renesas_usb3_ep_set_wedge(struct usb_ep *_ep) 22488c2ecf20Sopenharmony_ci{ 22498c2ecf20Sopenharmony_ci struct renesas_usb3_ep *usb3_ep = usb_ep_to_usb3_ep(_ep); 22508c2ecf20Sopenharmony_ci 22518c2ecf20Sopenharmony_ci usb3_ep->wedge = true; 22528c2ecf20Sopenharmony_ci return usb3_set_halt(usb3_ep, true, false); 22538c2ecf20Sopenharmony_ci} 22548c2ecf20Sopenharmony_ci 22558c2ecf20Sopenharmony_cistatic void renesas_usb3_ep_fifo_flush(struct usb_ep *_ep) 22568c2ecf20Sopenharmony_ci{ 22578c2ecf20Sopenharmony_ci struct renesas_usb3_ep *usb3_ep = usb_ep_to_usb3_ep(_ep); 22588c2ecf20Sopenharmony_ci struct renesas_usb3 *usb3 = usb3_ep_to_usb3(usb3_ep); 22598c2ecf20Sopenharmony_ci unsigned long flags; 22608c2ecf20Sopenharmony_ci 22618c2ecf20Sopenharmony_ci if (usb3_ep->num) { 22628c2ecf20Sopenharmony_ci spin_lock_irqsave(&usb3->lock, flags); 22638c2ecf20Sopenharmony_ci if (!usb3_pn_change(usb3, usb3_ep->num)) { 22648c2ecf20Sopenharmony_ci usb3_pn_con_clear(usb3); 22658c2ecf20Sopenharmony_ci usb3_set_bit(usb3, PN_CON_EN, USB3_PN_CON); 22668c2ecf20Sopenharmony_ci } 22678c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&usb3->lock, flags); 22688c2ecf20Sopenharmony_ci } else { 22698c2ecf20Sopenharmony_ci usb3_p0_con_clear_buffer(usb3); 22708c2ecf20Sopenharmony_ci } 22718c2ecf20Sopenharmony_ci} 22728c2ecf20Sopenharmony_ci 22738c2ecf20Sopenharmony_cistatic const struct usb_ep_ops renesas_usb3_ep_ops = { 22748c2ecf20Sopenharmony_ci .enable = renesas_usb3_ep_enable, 22758c2ecf20Sopenharmony_ci .disable = renesas_usb3_ep_disable, 22768c2ecf20Sopenharmony_ci 22778c2ecf20Sopenharmony_ci .alloc_request = renesas_usb3_ep_alloc_request, 22788c2ecf20Sopenharmony_ci .free_request = renesas_usb3_ep_free_request, 22798c2ecf20Sopenharmony_ci 22808c2ecf20Sopenharmony_ci .queue = renesas_usb3_ep_queue, 22818c2ecf20Sopenharmony_ci .dequeue = renesas_usb3_ep_dequeue, 22828c2ecf20Sopenharmony_ci 22838c2ecf20Sopenharmony_ci .set_halt = renesas_usb3_ep_set_halt, 22848c2ecf20Sopenharmony_ci .set_wedge = renesas_usb3_ep_set_wedge, 22858c2ecf20Sopenharmony_ci .fifo_flush = renesas_usb3_ep_fifo_flush, 22868c2ecf20Sopenharmony_ci}; 22878c2ecf20Sopenharmony_ci 22888c2ecf20Sopenharmony_ci/*------- usb_gadget_ops -------------------------------------------------*/ 22898c2ecf20Sopenharmony_cistatic int renesas_usb3_start(struct usb_gadget *gadget, 22908c2ecf20Sopenharmony_ci struct usb_gadget_driver *driver) 22918c2ecf20Sopenharmony_ci{ 22928c2ecf20Sopenharmony_ci struct renesas_usb3 *usb3; 22938c2ecf20Sopenharmony_ci 22948c2ecf20Sopenharmony_ci if (!driver || driver->max_speed < USB_SPEED_FULL || 22958c2ecf20Sopenharmony_ci !driver->setup) 22968c2ecf20Sopenharmony_ci return -EINVAL; 22978c2ecf20Sopenharmony_ci 22988c2ecf20Sopenharmony_ci usb3 = gadget_to_renesas_usb3(gadget); 22998c2ecf20Sopenharmony_ci 23008c2ecf20Sopenharmony_ci /* hook up the driver */ 23018c2ecf20Sopenharmony_ci usb3->driver = driver; 23028c2ecf20Sopenharmony_ci 23038c2ecf20Sopenharmony_ci if (usb3->phy) 23048c2ecf20Sopenharmony_ci phy_init(usb3->phy); 23058c2ecf20Sopenharmony_ci 23068c2ecf20Sopenharmony_ci pm_runtime_get_sync(usb3_to_dev(usb3)); 23078c2ecf20Sopenharmony_ci 23088c2ecf20Sopenharmony_ci renesas_usb3_init_controller(usb3); 23098c2ecf20Sopenharmony_ci 23108c2ecf20Sopenharmony_ci return 0; 23118c2ecf20Sopenharmony_ci} 23128c2ecf20Sopenharmony_ci 23138c2ecf20Sopenharmony_cistatic int renesas_usb3_stop(struct usb_gadget *gadget) 23148c2ecf20Sopenharmony_ci{ 23158c2ecf20Sopenharmony_ci struct renesas_usb3 *usb3 = gadget_to_renesas_usb3(gadget); 23168c2ecf20Sopenharmony_ci 23178c2ecf20Sopenharmony_ci usb3->softconnect = false; 23188c2ecf20Sopenharmony_ci usb3->gadget.speed = USB_SPEED_UNKNOWN; 23198c2ecf20Sopenharmony_ci usb3->driver = NULL; 23208c2ecf20Sopenharmony_ci renesas_usb3_stop_controller(usb3); 23218c2ecf20Sopenharmony_ci 23228c2ecf20Sopenharmony_ci if (usb3->phy) 23238c2ecf20Sopenharmony_ci phy_exit(usb3->phy); 23248c2ecf20Sopenharmony_ci 23258c2ecf20Sopenharmony_ci pm_runtime_put(usb3_to_dev(usb3)); 23268c2ecf20Sopenharmony_ci 23278c2ecf20Sopenharmony_ci return 0; 23288c2ecf20Sopenharmony_ci} 23298c2ecf20Sopenharmony_ci 23308c2ecf20Sopenharmony_cistatic int renesas_usb3_get_frame(struct usb_gadget *_gadget) 23318c2ecf20Sopenharmony_ci{ 23328c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 23338c2ecf20Sopenharmony_ci} 23348c2ecf20Sopenharmony_ci 23358c2ecf20Sopenharmony_cistatic int renesas_usb3_pullup(struct usb_gadget *gadget, int is_on) 23368c2ecf20Sopenharmony_ci{ 23378c2ecf20Sopenharmony_ci struct renesas_usb3 *usb3 = gadget_to_renesas_usb3(gadget); 23388c2ecf20Sopenharmony_ci 23398c2ecf20Sopenharmony_ci usb3->softconnect = !!is_on; 23408c2ecf20Sopenharmony_ci 23418c2ecf20Sopenharmony_ci return 0; 23428c2ecf20Sopenharmony_ci} 23438c2ecf20Sopenharmony_ci 23448c2ecf20Sopenharmony_cistatic int renesas_usb3_set_selfpowered(struct usb_gadget *gadget, int is_self) 23458c2ecf20Sopenharmony_ci{ 23468c2ecf20Sopenharmony_ci gadget->is_selfpowered = !!is_self; 23478c2ecf20Sopenharmony_ci 23488c2ecf20Sopenharmony_ci return 0; 23498c2ecf20Sopenharmony_ci} 23508c2ecf20Sopenharmony_ci 23518c2ecf20Sopenharmony_cistatic const struct usb_gadget_ops renesas_usb3_gadget_ops = { 23528c2ecf20Sopenharmony_ci .get_frame = renesas_usb3_get_frame, 23538c2ecf20Sopenharmony_ci .udc_start = renesas_usb3_start, 23548c2ecf20Sopenharmony_ci .udc_stop = renesas_usb3_stop, 23558c2ecf20Sopenharmony_ci .pullup = renesas_usb3_pullup, 23568c2ecf20Sopenharmony_ci .set_selfpowered = renesas_usb3_set_selfpowered, 23578c2ecf20Sopenharmony_ci}; 23588c2ecf20Sopenharmony_ci 23598c2ecf20Sopenharmony_cistatic enum usb_role renesas_usb3_role_switch_get(struct usb_role_switch *sw) 23608c2ecf20Sopenharmony_ci{ 23618c2ecf20Sopenharmony_ci struct renesas_usb3 *usb3 = usb_role_switch_get_drvdata(sw); 23628c2ecf20Sopenharmony_ci enum usb_role cur_role; 23638c2ecf20Sopenharmony_ci 23648c2ecf20Sopenharmony_ci pm_runtime_get_sync(usb3_to_dev(usb3)); 23658c2ecf20Sopenharmony_ci cur_role = usb3_is_host(usb3) ? USB_ROLE_HOST : USB_ROLE_DEVICE; 23668c2ecf20Sopenharmony_ci pm_runtime_put(usb3_to_dev(usb3)); 23678c2ecf20Sopenharmony_ci 23688c2ecf20Sopenharmony_ci return cur_role; 23698c2ecf20Sopenharmony_ci} 23708c2ecf20Sopenharmony_ci 23718c2ecf20Sopenharmony_cistatic void handle_ext_role_switch_states(struct device *dev, 23728c2ecf20Sopenharmony_ci enum usb_role role) 23738c2ecf20Sopenharmony_ci{ 23748c2ecf20Sopenharmony_ci struct renesas_usb3 *usb3 = dev_get_drvdata(dev); 23758c2ecf20Sopenharmony_ci struct device *host = usb3->host_dev; 23768c2ecf20Sopenharmony_ci enum usb_role cur_role = renesas_usb3_role_switch_get(usb3->role_sw); 23778c2ecf20Sopenharmony_ci 23788c2ecf20Sopenharmony_ci switch (role) { 23798c2ecf20Sopenharmony_ci case USB_ROLE_NONE: 23808c2ecf20Sopenharmony_ci usb3->connection_state = USB_ROLE_NONE; 23818c2ecf20Sopenharmony_ci if (cur_role == USB_ROLE_HOST) 23828c2ecf20Sopenharmony_ci device_release_driver(host); 23838c2ecf20Sopenharmony_ci if (usb3->driver) 23848c2ecf20Sopenharmony_ci usb3_disconnect(usb3); 23858c2ecf20Sopenharmony_ci usb3_vbus_out(usb3, false); 23868c2ecf20Sopenharmony_ci break; 23878c2ecf20Sopenharmony_ci case USB_ROLE_DEVICE: 23888c2ecf20Sopenharmony_ci if (usb3->connection_state == USB_ROLE_NONE) { 23898c2ecf20Sopenharmony_ci usb3->connection_state = USB_ROLE_DEVICE; 23908c2ecf20Sopenharmony_ci usb3_set_mode(usb3, false); 23918c2ecf20Sopenharmony_ci if (usb3->driver) 23928c2ecf20Sopenharmony_ci usb3_connect(usb3); 23938c2ecf20Sopenharmony_ci } else if (cur_role == USB_ROLE_HOST) { 23948c2ecf20Sopenharmony_ci device_release_driver(host); 23958c2ecf20Sopenharmony_ci usb3_set_mode(usb3, false); 23968c2ecf20Sopenharmony_ci if (usb3->driver) 23978c2ecf20Sopenharmony_ci usb3_connect(usb3); 23988c2ecf20Sopenharmony_ci } 23998c2ecf20Sopenharmony_ci usb3_vbus_out(usb3, false); 24008c2ecf20Sopenharmony_ci break; 24018c2ecf20Sopenharmony_ci case USB_ROLE_HOST: 24028c2ecf20Sopenharmony_ci if (usb3->connection_state == USB_ROLE_NONE) { 24038c2ecf20Sopenharmony_ci if (usb3->driver) 24048c2ecf20Sopenharmony_ci usb3_disconnect(usb3); 24058c2ecf20Sopenharmony_ci 24068c2ecf20Sopenharmony_ci usb3->connection_state = USB_ROLE_HOST; 24078c2ecf20Sopenharmony_ci usb3_set_mode(usb3, true); 24088c2ecf20Sopenharmony_ci usb3_vbus_out(usb3, true); 24098c2ecf20Sopenharmony_ci if (device_attach(host) < 0) 24108c2ecf20Sopenharmony_ci dev_err(dev, "device_attach(host) failed\n"); 24118c2ecf20Sopenharmony_ci } else if (cur_role == USB_ROLE_DEVICE) { 24128c2ecf20Sopenharmony_ci usb3_disconnect(usb3); 24138c2ecf20Sopenharmony_ci /* Must set the mode before device_attach of the host */ 24148c2ecf20Sopenharmony_ci usb3_set_mode(usb3, true); 24158c2ecf20Sopenharmony_ci /* This device_attach() might sleep */ 24168c2ecf20Sopenharmony_ci if (device_attach(host) < 0) 24178c2ecf20Sopenharmony_ci dev_err(dev, "device_attach(host) failed\n"); 24188c2ecf20Sopenharmony_ci } 24198c2ecf20Sopenharmony_ci break; 24208c2ecf20Sopenharmony_ci default: 24218c2ecf20Sopenharmony_ci break; 24228c2ecf20Sopenharmony_ci } 24238c2ecf20Sopenharmony_ci} 24248c2ecf20Sopenharmony_ci 24258c2ecf20Sopenharmony_cistatic void handle_role_switch_states(struct device *dev, 24268c2ecf20Sopenharmony_ci enum usb_role role) 24278c2ecf20Sopenharmony_ci{ 24288c2ecf20Sopenharmony_ci struct renesas_usb3 *usb3 = dev_get_drvdata(dev); 24298c2ecf20Sopenharmony_ci struct device *host = usb3->host_dev; 24308c2ecf20Sopenharmony_ci enum usb_role cur_role = renesas_usb3_role_switch_get(usb3->role_sw); 24318c2ecf20Sopenharmony_ci 24328c2ecf20Sopenharmony_ci if (cur_role == USB_ROLE_HOST && role == USB_ROLE_DEVICE) { 24338c2ecf20Sopenharmony_ci device_release_driver(host); 24348c2ecf20Sopenharmony_ci usb3_set_mode(usb3, false); 24358c2ecf20Sopenharmony_ci } else if (cur_role == USB_ROLE_DEVICE && role == USB_ROLE_HOST) { 24368c2ecf20Sopenharmony_ci /* Must set the mode before device_attach of the host */ 24378c2ecf20Sopenharmony_ci usb3_set_mode(usb3, true); 24388c2ecf20Sopenharmony_ci /* This device_attach() might sleep */ 24398c2ecf20Sopenharmony_ci if (device_attach(host) < 0) 24408c2ecf20Sopenharmony_ci dev_err(dev, "device_attach(host) failed\n"); 24418c2ecf20Sopenharmony_ci } 24428c2ecf20Sopenharmony_ci} 24438c2ecf20Sopenharmony_ci 24448c2ecf20Sopenharmony_cistatic int renesas_usb3_role_switch_set(struct usb_role_switch *sw, 24458c2ecf20Sopenharmony_ci enum usb_role role) 24468c2ecf20Sopenharmony_ci{ 24478c2ecf20Sopenharmony_ci struct renesas_usb3 *usb3 = usb_role_switch_get_drvdata(sw); 24488c2ecf20Sopenharmony_ci 24498c2ecf20Sopenharmony_ci pm_runtime_get_sync(usb3_to_dev(usb3)); 24508c2ecf20Sopenharmony_ci 24518c2ecf20Sopenharmony_ci if (usb3->role_sw_by_connector) 24528c2ecf20Sopenharmony_ci handle_ext_role_switch_states(usb3_to_dev(usb3), role); 24538c2ecf20Sopenharmony_ci else 24548c2ecf20Sopenharmony_ci handle_role_switch_states(usb3_to_dev(usb3), role); 24558c2ecf20Sopenharmony_ci 24568c2ecf20Sopenharmony_ci pm_runtime_put(usb3_to_dev(usb3)); 24578c2ecf20Sopenharmony_ci 24588c2ecf20Sopenharmony_ci return 0; 24598c2ecf20Sopenharmony_ci} 24608c2ecf20Sopenharmony_ci 24618c2ecf20Sopenharmony_cistatic ssize_t role_store(struct device *dev, struct device_attribute *attr, 24628c2ecf20Sopenharmony_ci const char *buf, size_t count) 24638c2ecf20Sopenharmony_ci{ 24648c2ecf20Sopenharmony_ci struct renesas_usb3 *usb3 = dev_get_drvdata(dev); 24658c2ecf20Sopenharmony_ci bool new_mode_is_host; 24668c2ecf20Sopenharmony_ci 24678c2ecf20Sopenharmony_ci if (!usb3->driver) 24688c2ecf20Sopenharmony_ci return -ENODEV; 24698c2ecf20Sopenharmony_ci 24708c2ecf20Sopenharmony_ci if (usb3->forced_b_device) 24718c2ecf20Sopenharmony_ci return -EBUSY; 24728c2ecf20Sopenharmony_ci 24738c2ecf20Sopenharmony_ci if (sysfs_streq(buf, "host")) 24748c2ecf20Sopenharmony_ci new_mode_is_host = true; 24758c2ecf20Sopenharmony_ci else if (sysfs_streq(buf, "peripheral")) 24768c2ecf20Sopenharmony_ci new_mode_is_host = false; 24778c2ecf20Sopenharmony_ci else 24788c2ecf20Sopenharmony_ci return -EINVAL; 24798c2ecf20Sopenharmony_ci 24808c2ecf20Sopenharmony_ci if (new_mode_is_host == usb3_is_host(usb3)) 24818c2ecf20Sopenharmony_ci return -EINVAL; 24828c2ecf20Sopenharmony_ci 24838c2ecf20Sopenharmony_ci usb3_mode_config(usb3, new_mode_is_host, usb3_is_a_device(usb3)); 24848c2ecf20Sopenharmony_ci 24858c2ecf20Sopenharmony_ci return count; 24868c2ecf20Sopenharmony_ci} 24878c2ecf20Sopenharmony_ci 24888c2ecf20Sopenharmony_cistatic ssize_t role_show(struct device *dev, struct device_attribute *attr, 24898c2ecf20Sopenharmony_ci char *buf) 24908c2ecf20Sopenharmony_ci{ 24918c2ecf20Sopenharmony_ci struct renesas_usb3 *usb3 = dev_get_drvdata(dev); 24928c2ecf20Sopenharmony_ci 24938c2ecf20Sopenharmony_ci if (!usb3->driver) 24948c2ecf20Sopenharmony_ci return -ENODEV; 24958c2ecf20Sopenharmony_ci 24968c2ecf20Sopenharmony_ci return sprintf(buf, "%s\n", usb3_is_host(usb3) ? "host" : "peripheral"); 24978c2ecf20Sopenharmony_ci} 24988c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RW(role); 24998c2ecf20Sopenharmony_ci 25008c2ecf20Sopenharmony_cistatic int renesas_usb3_b_device_show(struct seq_file *s, void *unused) 25018c2ecf20Sopenharmony_ci{ 25028c2ecf20Sopenharmony_ci struct renesas_usb3 *usb3 = s->private; 25038c2ecf20Sopenharmony_ci 25048c2ecf20Sopenharmony_ci seq_printf(s, "%d\n", usb3->forced_b_device); 25058c2ecf20Sopenharmony_ci 25068c2ecf20Sopenharmony_ci return 0; 25078c2ecf20Sopenharmony_ci} 25088c2ecf20Sopenharmony_ci 25098c2ecf20Sopenharmony_cistatic int renesas_usb3_b_device_open(struct inode *inode, struct file *file) 25108c2ecf20Sopenharmony_ci{ 25118c2ecf20Sopenharmony_ci return single_open(file, renesas_usb3_b_device_show, inode->i_private); 25128c2ecf20Sopenharmony_ci} 25138c2ecf20Sopenharmony_ci 25148c2ecf20Sopenharmony_cistatic ssize_t renesas_usb3_b_device_write(struct file *file, 25158c2ecf20Sopenharmony_ci const char __user *ubuf, 25168c2ecf20Sopenharmony_ci size_t count, loff_t *ppos) 25178c2ecf20Sopenharmony_ci{ 25188c2ecf20Sopenharmony_ci struct seq_file *s = file->private_data; 25198c2ecf20Sopenharmony_ci struct renesas_usb3 *usb3 = s->private; 25208c2ecf20Sopenharmony_ci char buf[32]; 25218c2ecf20Sopenharmony_ci 25228c2ecf20Sopenharmony_ci if (!usb3->driver) 25238c2ecf20Sopenharmony_ci return -ENODEV; 25248c2ecf20Sopenharmony_ci 25258c2ecf20Sopenharmony_ci if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count))) 25268c2ecf20Sopenharmony_ci return -EFAULT; 25278c2ecf20Sopenharmony_ci 25288c2ecf20Sopenharmony_ci usb3->start_to_connect = false; 25298c2ecf20Sopenharmony_ci if (usb3->workaround_for_vbus && usb3->forced_b_device && 25308c2ecf20Sopenharmony_ci !strncmp(buf, "2", 1)) 25318c2ecf20Sopenharmony_ci usb3->start_to_connect = true; 25328c2ecf20Sopenharmony_ci else if (!strncmp(buf, "1", 1)) 25338c2ecf20Sopenharmony_ci usb3->forced_b_device = true; 25348c2ecf20Sopenharmony_ci else 25358c2ecf20Sopenharmony_ci usb3->forced_b_device = false; 25368c2ecf20Sopenharmony_ci 25378c2ecf20Sopenharmony_ci if (usb3->workaround_for_vbus) 25388c2ecf20Sopenharmony_ci usb3_disconnect(usb3); 25398c2ecf20Sopenharmony_ci 25408c2ecf20Sopenharmony_ci /* Let this driver call usb3_connect() if needed */ 25418c2ecf20Sopenharmony_ci usb3_check_id(usb3); 25428c2ecf20Sopenharmony_ci 25438c2ecf20Sopenharmony_ci return count; 25448c2ecf20Sopenharmony_ci} 25458c2ecf20Sopenharmony_ci 25468c2ecf20Sopenharmony_cistatic const struct file_operations renesas_usb3_b_device_fops = { 25478c2ecf20Sopenharmony_ci .open = renesas_usb3_b_device_open, 25488c2ecf20Sopenharmony_ci .write = renesas_usb3_b_device_write, 25498c2ecf20Sopenharmony_ci .read = seq_read, 25508c2ecf20Sopenharmony_ci .llseek = seq_lseek, 25518c2ecf20Sopenharmony_ci .release = single_release, 25528c2ecf20Sopenharmony_ci}; 25538c2ecf20Sopenharmony_ci 25548c2ecf20Sopenharmony_cistatic void renesas_usb3_debugfs_init(struct renesas_usb3 *usb3, 25558c2ecf20Sopenharmony_ci struct device *dev) 25568c2ecf20Sopenharmony_ci{ 25578c2ecf20Sopenharmony_ci usb3->dentry = debugfs_create_dir(dev_name(dev), usb_debug_root); 25588c2ecf20Sopenharmony_ci 25598c2ecf20Sopenharmony_ci debugfs_create_file("b_device", 0644, usb3->dentry, usb3, 25608c2ecf20Sopenharmony_ci &renesas_usb3_b_device_fops); 25618c2ecf20Sopenharmony_ci} 25628c2ecf20Sopenharmony_ci 25638c2ecf20Sopenharmony_ci/*------- platform_driver ------------------------------------------------*/ 25648c2ecf20Sopenharmony_cistatic int renesas_usb3_remove(struct platform_device *pdev) 25658c2ecf20Sopenharmony_ci{ 25668c2ecf20Sopenharmony_ci struct renesas_usb3 *usb3 = platform_get_drvdata(pdev); 25678c2ecf20Sopenharmony_ci 25688c2ecf20Sopenharmony_ci debugfs_remove_recursive(usb3->dentry); 25698c2ecf20Sopenharmony_ci device_remove_file(&pdev->dev, &dev_attr_role); 25708c2ecf20Sopenharmony_ci 25718c2ecf20Sopenharmony_ci cancel_work_sync(&usb3->role_work); 25728c2ecf20Sopenharmony_ci usb_role_switch_unregister(usb3->role_sw); 25738c2ecf20Sopenharmony_ci 25748c2ecf20Sopenharmony_ci usb_del_gadget_udc(&usb3->gadget); 25758c2ecf20Sopenharmony_ci renesas_usb3_dma_free_prd(usb3, &pdev->dev); 25768c2ecf20Sopenharmony_ci 25778c2ecf20Sopenharmony_ci __renesas_usb3_ep_free_request(usb3->ep0_req); 25788c2ecf20Sopenharmony_ci pm_runtime_disable(&pdev->dev); 25798c2ecf20Sopenharmony_ci 25808c2ecf20Sopenharmony_ci return 0; 25818c2ecf20Sopenharmony_ci} 25828c2ecf20Sopenharmony_ci 25838c2ecf20Sopenharmony_cistatic int renesas_usb3_init_ep(struct renesas_usb3 *usb3, struct device *dev, 25848c2ecf20Sopenharmony_ci const struct renesas_usb3_priv *priv) 25858c2ecf20Sopenharmony_ci{ 25868c2ecf20Sopenharmony_ci struct renesas_usb3_ep *usb3_ep; 25878c2ecf20Sopenharmony_ci int i; 25888c2ecf20Sopenharmony_ci 25898c2ecf20Sopenharmony_ci /* calculate num_usb3_eps from renesas_usb3_priv */ 25908c2ecf20Sopenharmony_ci usb3->num_usb3_eps = priv->ramsize_per_ramif * priv->num_ramif * 2 / 25918c2ecf20Sopenharmony_ci priv->ramsize_per_pipe + 1; 25928c2ecf20Sopenharmony_ci 25938c2ecf20Sopenharmony_ci if (usb3->num_usb3_eps > USB3_MAX_NUM_PIPES) 25948c2ecf20Sopenharmony_ci usb3->num_usb3_eps = USB3_MAX_NUM_PIPES; 25958c2ecf20Sopenharmony_ci 25968c2ecf20Sopenharmony_ci usb3->usb3_ep = devm_kcalloc(dev, 25978c2ecf20Sopenharmony_ci usb3->num_usb3_eps, sizeof(*usb3_ep), 25988c2ecf20Sopenharmony_ci GFP_KERNEL); 25998c2ecf20Sopenharmony_ci if (!usb3->usb3_ep) 26008c2ecf20Sopenharmony_ci return -ENOMEM; 26018c2ecf20Sopenharmony_ci 26028c2ecf20Sopenharmony_ci dev_dbg(dev, "%s: num_usb3_eps = %d\n", __func__, usb3->num_usb3_eps); 26038c2ecf20Sopenharmony_ci /* 26048c2ecf20Sopenharmony_ci * This driver prepares pipes as follows: 26058c2ecf20Sopenharmony_ci * - odd pipes = IN pipe 26068c2ecf20Sopenharmony_ci * - even pipes = OUT pipe (except pipe 0) 26078c2ecf20Sopenharmony_ci */ 26088c2ecf20Sopenharmony_ci usb3_for_each_ep(usb3_ep, usb3, i) { 26098c2ecf20Sopenharmony_ci snprintf(usb3_ep->ep_name, sizeof(usb3_ep->ep_name), "ep%d", i); 26108c2ecf20Sopenharmony_ci usb3_ep->usb3 = usb3; 26118c2ecf20Sopenharmony_ci usb3_ep->num = i; 26128c2ecf20Sopenharmony_ci usb3_ep->ep.name = usb3_ep->ep_name; 26138c2ecf20Sopenharmony_ci usb3_ep->ep.ops = &renesas_usb3_ep_ops; 26148c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&usb3_ep->queue); 26158c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&usb3_ep->ep.ep_list); 26168c2ecf20Sopenharmony_ci if (!i) { 26178c2ecf20Sopenharmony_ci /* for control pipe */ 26188c2ecf20Sopenharmony_ci usb3->gadget.ep0 = &usb3_ep->ep; 26198c2ecf20Sopenharmony_ci usb_ep_set_maxpacket_limit(&usb3_ep->ep, 26208c2ecf20Sopenharmony_ci USB3_EP0_SS_MAX_PACKET_SIZE); 26218c2ecf20Sopenharmony_ci usb3_ep->ep.caps.type_control = true; 26228c2ecf20Sopenharmony_ci usb3_ep->ep.caps.dir_in = true; 26238c2ecf20Sopenharmony_ci usb3_ep->ep.caps.dir_out = true; 26248c2ecf20Sopenharmony_ci continue; 26258c2ecf20Sopenharmony_ci } 26268c2ecf20Sopenharmony_ci 26278c2ecf20Sopenharmony_ci /* for bulk or interrupt pipe */ 26288c2ecf20Sopenharmony_ci usb_ep_set_maxpacket_limit(&usb3_ep->ep, ~0); 26298c2ecf20Sopenharmony_ci list_add_tail(&usb3_ep->ep.ep_list, &usb3->gadget.ep_list); 26308c2ecf20Sopenharmony_ci usb3_ep->ep.caps.type_bulk = true; 26318c2ecf20Sopenharmony_ci usb3_ep->ep.caps.type_int = true; 26328c2ecf20Sopenharmony_ci if (i & 1) 26338c2ecf20Sopenharmony_ci usb3_ep->ep.caps.dir_in = true; 26348c2ecf20Sopenharmony_ci else 26358c2ecf20Sopenharmony_ci usb3_ep->ep.caps.dir_out = true; 26368c2ecf20Sopenharmony_ci } 26378c2ecf20Sopenharmony_ci 26388c2ecf20Sopenharmony_ci return 0; 26398c2ecf20Sopenharmony_ci} 26408c2ecf20Sopenharmony_ci 26418c2ecf20Sopenharmony_cistatic void renesas_usb3_init_ram(struct renesas_usb3 *usb3, struct device *dev, 26428c2ecf20Sopenharmony_ci const struct renesas_usb3_priv *priv) 26438c2ecf20Sopenharmony_ci{ 26448c2ecf20Sopenharmony_ci struct renesas_usb3_ep *usb3_ep; 26458c2ecf20Sopenharmony_ci int i; 26468c2ecf20Sopenharmony_ci u32 ramif[2], basead[2]; /* index 0 = for IN pipes */ 26478c2ecf20Sopenharmony_ci u32 *cur_ramif, *cur_basead; 26488c2ecf20Sopenharmony_ci u32 val; 26498c2ecf20Sopenharmony_ci 26508c2ecf20Sopenharmony_ci memset(ramif, 0, sizeof(ramif)); 26518c2ecf20Sopenharmony_ci memset(basead, 0, sizeof(basead)); 26528c2ecf20Sopenharmony_ci 26538c2ecf20Sopenharmony_ci /* 26548c2ecf20Sopenharmony_ci * This driver prepares pipes as follows: 26558c2ecf20Sopenharmony_ci * - all pipes = the same size as "ramsize_per_pipe" 26568c2ecf20Sopenharmony_ci * Please refer to the "Method of Specifying RAM Mapping" 26578c2ecf20Sopenharmony_ci */ 26588c2ecf20Sopenharmony_ci usb3_for_each_ep(usb3_ep, usb3, i) { 26598c2ecf20Sopenharmony_ci if (!i) 26608c2ecf20Sopenharmony_ci continue; /* out of scope if ep num = 0 */ 26618c2ecf20Sopenharmony_ci if (usb3_ep->ep.caps.dir_in) { 26628c2ecf20Sopenharmony_ci cur_ramif = &ramif[0]; 26638c2ecf20Sopenharmony_ci cur_basead = &basead[0]; 26648c2ecf20Sopenharmony_ci } else { 26658c2ecf20Sopenharmony_ci cur_ramif = &ramif[1]; 26668c2ecf20Sopenharmony_ci cur_basead = &basead[1]; 26678c2ecf20Sopenharmony_ci } 26688c2ecf20Sopenharmony_ci 26698c2ecf20Sopenharmony_ci if (*cur_basead > priv->ramsize_per_ramif) 26708c2ecf20Sopenharmony_ci continue; /* out of memory for IN or OUT pipe */ 26718c2ecf20Sopenharmony_ci 26728c2ecf20Sopenharmony_ci /* calculate rammap_val */ 26738c2ecf20Sopenharmony_ci val = PN_RAMMAP_RAMIF(*cur_ramif); 26748c2ecf20Sopenharmony_ci val |= usb3_calc_ramarea(priv->ramsize_per_pipe); 26758c2ecf20Sopenharmony_ci val |= PN_RAMMAP_BASEAD(*cur_basead); 26768c2ecf20Sopenharmony_ci usb3_ep->rammap_val = val; 26778c2ecf20Sopenharmony_ci 26788c2ecf20Sopenharmony_ci dev_dbg(dev, "ep%2d: val = %08x, ramif = %d, base = %x\n", 26798c2ecf20Sopenharmony_ci i, val, *cur_ramif, *cur_basead); 26808c2ecf20Sopenharmony_ci 26818c2ecf20Sopenharmony_ci /* update current ramif */ 26828c2ecf20Sopenharmony_ci if (*cur_ramif + 1 == priv->num_ramif) { 26838c2ecf20Sopenharmony_ci *cur_ramif = 0; 26848c2ecf20Sopenharmony_ci *cur_basead += priv->ramsize_per_pipe; 26858c2ecf20Sopenharmony_ci } else { 26868c2ecf20Sopenharmony_ci (*cur_ramif)++; 26878c2ecf20Sopenharmony_ci } 26888c2ecf20Sopenharmony_ci } 26898c2ecf20Sopenharmony_ci} 26908c2ecf20Sopenharmony_ci 26918c2ecf20Sopenharmony_cistatic const struct renesas_usb3_priv renesas_usb3_priv_r8a7795_es1 = { 26928c2ecf20Sopenharmony_ci .ramsize_per_ramif = SZ_16K, 26938c2ecf20Sopenharmony_ci .num_ramif = 2, 26948c2ecf20Sopenharmony_ci .ramsize_per_pipe = SZ_4K, 26958c2ecf20Sopenharmony_ci .workaround_for_vbus = true, 26968c2ecf20Sopenharmony_ci}; 26978c2ecf20Sopenharmony_ci 26988c2ecf20Sopenharmony_cistatic const struct renesas_usb3_priv renesas_usb3_priv_gen3 = { 26998c2ecf20Sopenharmony_ci .ramsize_per_ramif = SZ_16K, 27008c2ecf20Sopenharmony_ci .num_ramif = 4, 27018c2ecf20Sopenharmony_ci .ramsize_per_pipe = SZ_4K, 27028c2ecf20Sopenharmony_ci}; 27038c2ecf20Sopenharmony_ci 27048c2ecf20Sopenharmony_cistatic const struct renesas_usb3_priv renesas_usb3_priv_r8a77990 = { 27058c2ecf20Sopenharmony_ci .ramsize_per_ramif = SZ_16K, 27068c2ecf20Sopenharmony_ci .num_ramif = 4, 27078c2ecf20Sopenharmony_ci .ramsize_per_pipe = SZ_4K, 27088c2ecf20Sopenharmony_ci .workaround_for_vbus = true, 27098c2ecf20Sopenharmony_ci}; 27108c2ecf20Sopenharmony_ci 27118c2ecf20Sopenharmony_cistatic const struct of_device_id usb3_of_match[] = { 27128c2ecf20Sopenharmony_ci { 27138c2ecf20Sopenharmony_ci .compatible = "renesas,r8a774c0-usb3-peri", 27148c2ecf20Sopenharmony_ci .data = &renesas_usb3_priv_r8a77990, 27158c2ecf20Sopenharmony_ci }, { 27168c2ecf20Sopenharmony_ci .compatible = "renesas,r8a7795-usb3-peri", 27178c2ecf20Sopenharmony_ci .data = &renesas_usb3_priv_gen3, 27188c2ecf20Sopenharmony_ci }, { 27198c2ecf20Sopenharmony_ci .compatible = "renesas,r8a77990-usb3-peri", 27208c2ecf20Sopenharmony_ci .data = &renesas_usb3_priv_r8a77990, 27218c2ecf20Sopenharmony_ci }, { 27228c2ecf20Sopenharmony_ci .compatible = "renesas,rcar-gen3-usb3-peri", 27238c2ecf20Sopenharmony_ci .data = &renesas_usb3_priv_gen3, 27248c2ecf20Sopenharmony_ci }, 27258c2ecf20Sopenharmony_ci { }, 27268c2ecf20Sopenharmony_ci}; 27278c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, usb3_of_match); 27288c2ecf20Sopenharmony_ci 27298c2ecf20Sopenharmony_cistatic const struct soc_device_attribute renesas_usb3_quirks_match[] = { 27308c2ecf20Sopenharmony_ci { 27318c2ecf20Sopenharmony_ci .soc_id = "r8a7795", .revision = "ES1.*", 27328c2ecf20Sopenharmony_ci .data = &renesas_usb3_priv_r8a7795_es1, 27338c2ecf20Sopenharmony_ci }, 27348c2ecf20Sopenharmony_ci { /* sentinel */ }, 27358c2ecf20Sopenharmony_ci}; 27368c2ecf20Sopenharmony_ci 27378c2ecf20Sopenharmony_cistatic const unsigned int renesas_usb3_cable[] = { 27388c2ecf20Sopenharmony_ci EXTCON_USB, 27398c2ecf20Sopenharmony_ci EXTCON_USB_HOST, 27408c2ecf20Sopenharmony_ci EXTCON_NONE, 27418c2ecf20Sopenharmony_ci}; 27428c2ecf20Sopenharmony_ci 27438c2ecf20Sopenharmony_cistatic struct usb_role_switch_desc renesas_usb3_role_switch_desc = { 27448c2ecf20Sopenharmony_ci .set = renesas_usb3_role_switch_set, 27458c2ecf20Sopenharmony_ci .get = renesas_usb3_role_switch_get, 27468c2ecf20Sopenharmony_ci .allow_userspace_control = true, 27478c2ecf20Sopenharmony_ci}; 27488c2ecf20Sopenharmony_ci 27498c2ecf20Sopenharmony_cistatic int renesas_usb3_probe(struct platform_device *pdev) 27508c2ecf20Sopenharmony_ci{ 27518c2ecf20Sopenharmony_ci struct renesas_usb3 *usb3; 27528c2ecf20Sopenharmony_ci int irq, ret; 27538c2ecf20Sopenharmony_ci const struct renesas_usb3_priv *priv; 27548c2ecf20Sopenharmony_ci const struct soc_device_attribute *attr; 27558c2ecf20Sopenharmony_ci 27568c2ecf20Sopenharmony_ci attr = soc_device_match(renesas_usb3_quirks_match); 27578c2ecf20Sopenharmony_ci if (attr) 27588c2ecf20Sopenharmony_ci priv = attr->data; 27598c2ecf20Sopenharmony_ci else 27608c2ecf20Sopenharmony_ci priv = of_device_get_match_data(&pdev->dev); 27618c2ecf20Sopenharmony_ci 27628c2ecf20Sopenharmony_ci irq = platform_get_irq(pdev, 0); 27638c2ecf20Sopenharmony_ci if (irq < 0) 27648c2ecf20Sopenharmony_ci return irq; 27658c2ecf20Sopenharmony_ci 27668c2ecf20Sopenharmony_ci usb3 = devm_kzalloc(&pdev->dev, sizeof(*usb3), GFP_KERNEL); 27678c2ecf20Sopenharmony_ci if (!usb3) 27688c2ecf20Sopenharmony_ci return -ENOMEM; 27698c2ecf20Sopenharmony_ci 27708c2ecf20Sopenharmony_ci usb3->reg = devm_platform_ioremap_resource(pdev, 0); 27718c2ecf20Sopenharmony_ci if (IS_ERR(usb3->reg)) 27728c2ecf20Sopenharmony_ci return PTR_ERR(usb3->reg); 27738c2ecf20Sopenharmony_ci 27748c2ecf20Sopenharmony_ci platform_set_drvdata(pdev, usb3); 27758c2ecf20Sopenharmony_ci spin_lock_init(&usb3->lock); 27768c2ecf20Sopenharmony_ci 27778c2ecf20Sopenharmony_ci usb3->gadget.ops = &renesas_usb3_gadget_ops; 27788c2ecf20Sopenharmony_ci usb3->gadget.name = udc_name; 27798c2ecf20Sopenharmony_ci usb3->gadget.max_speed = USB_SPEED_SUPER; 27808c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&usb3->gadget.ep_list); 27818c2ecf20Sopenharmony_ci ret = renesas_usb3_init_ep(usb3, &pdev->dev, priv); 27828c2ecf20Sopenharmony_ci if (ret < 0) 27838c2ecf20Sopenharmony_ci return ret; 27848c2ecf20Sopenharmony_ci renesas_usb3_init_ram(usb3, &pdev->dev, priv); 27858c2ecf20Sopenharmony_ci 27868c2ecf20Sopenharmony_ci ret = devm_request_irq(&pdev->dev, irq, renesas_usb3_irq, 0, 27878c2ecf20Sopenharmony_ci dev_name(&pdev->dev), usb3); 27888c2ecf20Sopenharmony_ci if (ret < 0) 27898c2ecf20Sopenharmony_ci return ret; 27908c2ecf20Sopenharmony_ci 27918c2ecf20Sopenharmony_ci INIT_WORK(&usb3->extcon_work, renesas_usb3_extcon_work); 27928c2ecf20Sopenharmony_ci usb3->extcon = devm_extcon_dev_allocate(&pdev->dev, renesas_usb3_cable); 27938c2ecf20Sopenharmony_ci if (IS_ERR(usb3->extcon)) 27948c2ecf20Sopenharmony_ci return PTR_ERR(usb3->extcon); 27958c2ecf20Sopenharmony_ci 27968c2ecf20Sopenharmony_ci ret = devm_extcon_dev_register(&pdev->dev, usb3->extcon); 27978c2ecf20Sopenharmony_ci if (ret < 0) { 27988c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "Failed to register extcon\n"); 27998c2ecf20Sopenharmony_ci return ret; 28008c2ecf20Sopenharmony_ci } 28018c2ecf20Sopenharmony_ci 28028c2ecf20Sopenharmony_ci /* for ep0 handling */ 28038c2ecf20Sopenharmony_ci usb3->ep0_req = __renesas_usb3_ep_alloc_request(GFP_KERNEL); 28048c2ecf20Sopenharmony_ci if (!usb3->ep0_req) 28058c2ecf20Sopenharmony_ci return -ENOMEM; 28068c2ecf20Sopenharmony_ci 28078c2ecf20Sopenharmony_ci ret = renesas_usb3_dma_alloc_prd(usb3, &pdev->dev); 28088c2ecf20Sopenharmony_ci if (ret < 0) 28098c2ecf20Sopenharmony_ci goto err_alloc_prd; 28108c2ecf20Sopenharmony_ci 28118c2ecf20Sopenharmony_ci /* 28128c2ecf20Sopenharmony_ci * This is optional. So, if this driver cannot get a phy, 28138c2ecf20Sopenharmony_ci * this driver will not handle a phy anymore. 28148c2ecf20Sopenharmony_ci */ 28158c2ecf20Sopenharmony_ci usb3->phy = devm_phy_optional_get(&pdev->dev, "usb"); 28168c2ecf20Sopenharmony_ci if (IS_ERR(usb3->phy)) { 28178c2ecf20Sopenharmony_ci ret = PTR_ERR(usb3->phy); 28188c2ecf20Sopenharmony_ci goto err_add_udc; 28198c2ecf20Sopenharmony_ci } 28208c2ecf20Sopenharmony_ci 28218c2ecf20Sopenharmony_ci pm_runtime_enable(&pdev->dev); 28228c2ecf20Sopenharmony_ci ret = usb_add_gadget_udc(&pdev->dev, &usb3->gadget); 28238c2ecf20Sopenharmony_ci if (ret < 0) 28248c2ecf20Sopenharmony_ci goto err_add_udc; 28258c2ecf20Sopenharmony_ci 28268c2ecf20Sopenharmony_ci ret = device_create_file(&pdev->dev, &dev_attr_role); 28278c2ecf20Sopenharmony_ci if (ret < 0) 28288c2ecf20Sopenharmony_ci goto err_dev_create; 28298c2ecf20Sopenharmony_ci 28308c2ecf20Sopenharmony_ci if (device_property_read_bool(&pdev->dev, "usb-role-switch")) { 28318c2ecf20Sopenharmony_ci usb3->role_sw_by_connector = true; 28328c2ecf20Sopenharmony_ci renesas_usb3_role_switch_desc.fwnode = dev_fwnode(&pdev->dev); 28338c2ecf20Sopenharmony_ci } 28348c2ecf20Sopenharmony_ci 28358c2ecf20Sopenharmony_ci renesas_usb3_role_switch_desc.driver_data = usb3; 28368c2ecf20Sopenharmony_ci 28378c2ecf20Sopenharmony_ci INIT_WORK(&usb3->role_work, renesas_usb3_role_work); 28388c2ecf20Sopenharmony_ci usb3->role_sw = usb_role_switch_register(&pdev->dev, 28398c2ecf20Sopenharmony_ci &renesas_usb3_role_switch_desc); 28408c2ecf20Sopenharmony_ci if (!IS_ERR(usb3->role_sw)) { 28418c2ecf20Sopenharmony_ci usb3->host_dev = usb_of_get_companion_dev(&pdev->dev); 28428c2ecf20Sopenharmony_ci if (!usb3->host_dev) { 28438c2ecf20Sopenharmony_ci /* If not found, this driver will not use a role sw */ 28448c2ecf20Sopenharmony_ci usb_role_switch_unregister(usb3->role_sw); 28458c2ecf20Sopenharmony_ci usb3->role_sw = NULL; 28468c2ecf20Sopenharmony_ci } 28478c2ecf20Sopenharmony_ci } else { 28488c2ecf20Sopenharmony_ci usb3->role_sw = NULL; 28498c2ecf20Sopenharmony_ci } 28508c2ecf20Sopenharmony_ci 28518c2ecf20Sopenharmony_ci usb3->workaround_for_vbus = priv->workaround_for_vbus; 28528c2ecf20Sopenharmony_ci 28538c2ecf20Sopenharmony_ci renesas_usb3_debugfs_init(usb3, &pdev->dev); 28548c2ecf20Sopenharmony_ci 28558c2ecf20Sopenharmony_ci dev_info(&pdev->dev, "probed%s\n", usb3->phy ? " with phy" : ""); 28568c2ecf20Sopenharmony_ci 28578c2ecf20Sopenharmony_ci return 0; 28588c2ecf20Sopenharmony_ci 28598c2ecf20Sopenharmony_cierr_dev_create: 28608c2ecf20Sopenharmony_ci usb_del_gadget_udc(&usb3->gadget); 28618c2ecf20Sopenharmony_ci 28628c2ecf20Sopenharmony_cierr_add_udc: 28638c2ecf20Sopenharmony_ci renesas_usb3_dma_free_prd(usb3, &pdev->dev); 28648c2ecf20Sopenharmony_ci 28658c2ecf20Sopenharmony_cierr_alloc_prd: 28668c2ecf20Sopenharmony_ci __renesas_usb3_ep_free_request(usb3->ep0_req); 28678c2ecf20Sopenharmony_ci 28688c2ecf20Sopenharmony_ci return ret; 28698c2ecf20Sopenharmony_ci} 28708c2ecf20Sopenharmony_ci 28718c2ecf20Sopenharmony_ci#ifdef CONFIG_PM_SLEEP 28728c2ecf20Sopenharmony_cistatic int renesas_usb3_suspend(struct device *dev) 28738c2ecf20Sopenharmony_ci{ 28748c2ecf20Sopenharmony_ci struct renesas_usb3 *usb3 = dev_get_drvdata(dev); 28758c2ecf20Sopenharmony_ci 28768c2ecf20Sopenharmony_ci /* Not started */ 28778c2ecf20Sopenharmony_ci if (!usb3->driver) 28788c2ecf20Sopenharmony_ci return 0; 28798c2ecf20Sopenharmony_ci 28808c2ecf20Sopenharmony_ci renesas_usb3_stop_controller(usb3); 28818c2ecf20Sopenharmony_ci if (usb3->phy) 28828c2ecf20Sopenharmony_ci phy_exit(usb3->phy); 28838c2ecf20Sopenharmony_ci pm_runtime_put(dev); 28848c2ecf20Sopenharmony_ci 28858c2ecf20Sopenharmony_ci return 0; 28868c2ecf20Sopenharmony_ci} 28878c2ecf20Sopenharmony_ci 28888c2ecf20Sopenharmony_cistatic int renesas_usb3_resume(struct device *dev) 28898c2ecf20Sopenharmony_ci{ 28908c2ecf20Sopenharmony_ci struct renesas_usb3 *usb3 = dev_get_drvdata(dev); 28918c2ecf20Sopenharmony_ci 28928c2ecf20Sopenharmony_ci /* Not started */ 28938c2ecf20Sopenharmony_ci if (!usb3->driver) 28948c2ecf20Sopenharmony_ci return 0; 28958c2ecf20Sopenharmony_ci 28968c2ecf20Sopenharmony_ci if (usb3->phy) 28978c2ecf20Sopenharmony_ci phy_init(usb3->phy); 28988c2ecf20Sopenharmony_ci pm_runtime_get_sync(dev); 28998c2ecf20Sopenharmony_ci renesas_usb3_init_controller(usb3); 29008c2ecf20Sopenharmony_ci 29018c2ecf20Sopenharmony_ci return 0; 29028c2ecf20Sopenharmony_ci} 29038c2ecf20Sopenharmony_ci#endif 29048c2ecf20Sopenharmony_ci 29058c2ecf20Sopenharmony_cistatic SIMPLE_DEV_PM_OPS(renesas_usb3_pm_ops, renesas_usb3_suspend, 29068c2ecf20Sopenharmony_ci renesas_usb3_resume); 29078c2ecf20Sopenharmony_ci 29088c2ecf20Sopenharmony_cistatic struct platform_driver renesas_usb3_driver = { 29098c2ecf20Sopenharmony_ci .probe = renesas_usb3_probe, 29108c2ecf20Sopenharmony_ci .remove = renesas_usb3_remove, 29118c2ecf20Sopenharmony_ci .driver = { 29128c2ecf20Sopenharmony_ci .name = udc_name, 29138c2ecf20Sopenharmony_ci .pm = &renesas_usb3_pm_ops, 29148c2ecf20Sopenharmony_ci .of_match_table = of_match_ptr(usb3_of_match), 29158c2ecf20Sopenharmony_ci }, 29168c2ecf20Sopenharmony_ci}; 29178c2ecf20Sopenharmony_cimodule_platform_driver(renesas_usb3_driver); 29188c2ecf20Sopenharmony_ci 29198c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Renesas USB3.0 Peripheral driver"); 29208c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2"); 29218c2ecf20Sopenharmony_ciMODULE_AUTHOR("Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>"); 29228c2ecf20Sopenharmony_ciMODULE_ALIAS("platform:renesas_usb3"); 2923