Loading drivers/usb/mtu3/mtu3.h +6 −5 Original line number Diff line number Diff line Loading @@ -148,22 +148,23 @@ struct mtu3_fifo_info { * bit0: Hardware Own (HWO) * bit1: Buffer Descriptor Present (BDP), always 0, BD is not supported * bit2: Bypass (BPS), 1: HW skips this GPD if HWO = 1 * bit6: [EL] Zero Length Packet (ZLP), moved from @dw3_info[29] * bit7: Interrupt On Completion (IOC) * bit[31:16]: allow data buffer length (RX ONLY), * bit[31:16]: ([EL] bit[31:12]) allow data buffer length (RX ONLY), * the buffer length of the data to receive * bit[23:16]: extension address (TX ONLY), * bit[23:16]: ([EL] bit[31:24]) extension address (TX ONLY), * lower 4 bits are extension bits of @buffer, * upper 4 bits are extension bits of @next_gpd * @next_gpd: Physical address of the next GPD * @buffer: Physical address of the data buffer * @dw3_info: * bit[15:0]: data buffer length, * bit[15:0]: ([EL] bit[19:0]) data buffer length, * (TX): the buffer length of the data to transmit * (RX): The total length of data received * bit[23:16]: extension address (RX ONLY), * bit[23:16]: ([EL] bit[31:24]) extension address (RX ONLY), * lower 4 bits are extension bits of @buffer, * upper 4 bits are extension bits of @next_gpd * bit29: Zero Length Packet (ZLP) (TX ONLY) * bit29: ([EL] abandoned) Zero Length Packet (ZLP) (TX ONLY) */ struct qmu_gpd { __le32 dw0_info; Loading drivers/usb/mtu3/mtu3_core.c +5 −0 Original line number Diff line number Diff line Loading @@ -601,6 +601,10 @@ static void mtu3_regs_init(struct mtu3 *mtu) mtu3_clrbits(mbase, U3D_MISC_CTRL, VBUS_FRC_EN | VBUS_ON); /* enable automatical HWRW from L1 */ mtu3_setbits(mbase, U3D_POWER_MANAGEMENT, LPM_HRWE); /* use new QMU format when HW version >= 0x1003 */ if (mtu->gen2cp) mtu3_writel(mbase, U3D_QFCR, ~0x0); } static irqreturn_t mtu3_link_isr(struct mtu3 *mtu) Loading Loading @@ -755,6 +759,7 @@ static int mtu3_hw_init(struct mtu3 *mtu) value = mtu3_readl(mtu->ippc_base, U3D_SSUSB_IP_TRUNK_VERS); mtu->hw_version = IP_TRUNK_VERS(value); mtu->gen2cp = !!(mtu->hw_version >= MTU3_TRUNK_VERS_1003); value = mtu3_readl(mtu->ippc_base, U3D_SSUSB_IP_DEV_CAP); mtu->is_u3_ip = !!SSUSB_IP_DEV_U3_PORT_NUM(value); Loading drivers/usb/mtu3/mtu3_gadget.c +4 −2 Original line number Diff line number Diff line Loading @@ -278,10 +278,12 @@ static int mtu3_gadget_queue(struct usb_ep *ep, __func__, mep->is_in ? "TX" : "RX", mreq->epnum, ep->name, mreq, ep->maxpacket, mreq->request.length); if (req->length > GPD_BUF_SIZE) { if (req->length > GPD_BUF_SIZE || (mtu->gen2cp && req->length > GPD_BUF_SIZE_EL)) { dev_warn(mtu->dev, "req length > supported MAX:%d requested:%d\n", GPD_BUF_SIZE, req->length); mtu->gen2cp ? GPD_BUF_SIZE_EL : GPD_BUF_SIZE, req->length); return -EOPNOTSUPP; } Loading drivers/usb/mtu3/mtu3_hw_regs.h +1 −0 Original line number Diff line number Diff line Loading @@ -49,6 +49,7 @@ #define U3D_QCR1 (SSUSB_DEV_BASE + 0x0404) #define U3D_QCR2 (SSUSB_DEV_BASE + 0x0408) #define U3D_QCR3 (SSUSB_DEV_BASE + 0x040C) #define U3D_QFCR (SSUSB_DEV_BASE + 0x0428) #define U3D_TXQHIAR1 (SSUSB_DEV_BASE + 0x0484) #define U3D_RXQHIAR1 (SSUSB_DEV_BASE + 0x04C4) Loading drivers/usb/mtu3/mtu3_qmu.c +49 −15 Original line number Diff line number Diff line Loading @@ -28,14 +28,42 @@ #define GPD_FLAGS_HWO BIT(0) #define GPD_FLAGS_BDP BIT(1) #define GPD_FLAGS_BPS BIT(2) #define GPD_FLAGS_ZLP BIT(6) #define GPD_FLAGS_IOC BIT(7) #define GET_GPD_HWO(gpd) (le32_to_cpu((gpd)->dw0_info) & GPD_FLAGS_HWO) #define GPD_RX_BUF_LEN(x) (((x) & 0xffff) << 16) #define GPD_DATA_LEN(x) ((x) & 0xffff) #define GPD_RX_BUF_LEN_OG(x) (((x) & 0xffff) << 16) #define GPD_RX_BUF_LEN_EL(x) (((x) & 0xfffff) << 12) #define GPD_RX_BUF_LEN(mtu, x) \ ({ \ typeof(x) x_ = (x); \ ((mtu)->gen2cp) ? GPD_RX_BUF_LEN_EL(x_) : GPD_RX_BUF_LEN_OG(x_); \ }) #define GPD_DATA_LEN_OG(x) ((x) & 0xffff) #define GPD_DATA_LEN_EL(x) ((x) & 0xfffff) #define GPD_DATA_LEN(mtu, x) \ ({ \ typeof(x) x_ = (x); \ ((mtu)->gen2cp) ? GPD_DATA_LEN_EL(x_) : GPD_DATA_LEN_OG(x_); \ }) #define GPD_EXT_FLAG_ZLP BIT(29) #define GPD_EXT_NGP(x) (((x) & 0xf) << 20) #define GPD_EXT_BUF(x) (((x) & 0xf) << 16) #define GPD_EXT_NGP_OG(x) (((x) & 0xf) << 20) #define GPD_EXT_BUF_OG(x) (((x) & 0xf) << 16) #define GPD_EXT_NGP_EL(x) (((x) & 0xf) << 28) #define GPD_EXT_BUF_EL(x) (((x) & 0xf) << 24) #define GPD_EXT_NGP(mtu, x) \ ({ \ typeof(x) x_ = (x); \ ((mtu)->gen2cp) ? GPD_EXT_NGP_EL(x_) : GPD_EXT_NGP_OG(x_); \ }) #define GPD_EXT_BUF(mtu, x) \ ({ \ typeof(x) x_ = (x); \ ((mtu)->gen2cp) ? GPD_EXT_BUF_EL(x_) : GPD_EXT_BUF_OG(x_); \ }) #define HILO_GEN64(hi, lo) (((u64)(hi) << 32) + (lo)) #define HILO_DMA(hi, lo) \ Loading Loading @@ -217,13 +245,14 @@ static int mtu3_prepare_tx_gpd(struct mtu3_ep *mep, struct mtu3_request *mreq) struct mtu3_gpd_ring *ring = &mep->gpd_ring; struct qmu_gpd *gpd = ring->enqueue; struct usb_request *req = &mreq->request; struct mtu3 *mtu = mep->mtu; dma_addr_t enq_dma; u32 ext_addr; gpd->dw0_info = 0; /* SW own it */ gpd->buffer = cpu_to_le32(lower_32_bits(req->dma)); ext_addr = GPD_EXT_BUF(upper_32_bits(req->dma)); gpd->dw3_info = cpu_to_le32(GPD_DATA_LEN(req->length)); ext_addr = GPD_EXT_BUF(mtu, upper_32_bits(req->dma)); gpd->dw3_info = cpu_to_le32(GPD_DATA_LEN(mtu, req->length)); /* get the next GPD */ enq = advance_enq_gpd(ring); Loading @@ -233,11 +262,15 @@ static int mtu3_prepare_tx_gpd(struct mtu3_ep *mep, struct mtu3_request *mreq) enq->dw0_info &= cpu_to_le32(~GPD_FLAGS_HWO); gpd->next_gpd = cpu_to_le32(lower_32_bits(enq_dma)); ext_addr |= GPD_EXT_NGP(upper_32_bits(enq_dma)); ext_addr |= GPD_EXT_NGP(mtu, upper_32_bits(enq_dma)); gpd->dw0_info = cpu_to_le32(ext_addr); if (req->zero) if (req->zero) { if (mtu->gen2cp) gpd->dw0_info |= cpu_to_le32(GPD_FLAGS_ZLP); else gpd->dw3_info |= cpu_to_le32(GPD_EXT_FLAG_ZLP); } gpd->dw0_info |= cpu_to_le32(GPD_FLAGS_IOC | GPD_FLAGS_HWO); Loading @@ -252,13 +285,14 @@ static int mtu3_prepare_rx_gpd(struct mtu3_ep *mep, struct mtu3_request *mreq) struct mtu3_gpd_ring *ring = &mep->gpd_ring; struct qmu_gpd *gpd = ring->enqueue; struct usb_request *req = &mreq->request; struct mtu3 *mtu = mep->mtu; dma_addr_t enq_dma; u32 ext_addr; gpd->dw0_info = 0; /* SW own it */ gpd->buffer = cpu_to_le32(lower_32_bits(req->dma)); ext_addr = GPD_EXT_BUF(upper_32_bits(req->dma)); gpd->dw0_info = cpu_to_le32(GPD_RX_BUF_LEN(req->length)); ext_addr = GPD_EXT_BUF(mtu, upper_32_bits(req->dma)); gpd->dw0_info = cpu_to_le32(GPD_RX_BUF_LEN(mtu, req->length)); /* get the next GPD */ enq = advance_enq_gpd(ring); Loading @@ -268,7 +302,7 @@ static int mtu3_prepare_rx_gpd(struct mtu3_ep *mep, struct mtu3_request *mreq) enq->dw0_info &= cpu_to_le32(~GPD_FLAGS_HWO); gpd->next_gpd = cpu_to_le32(lower_32_bits(enq_dma)); ext_addr |= GPD_EXT_NGP(upper_32_bits(enq_dma)); ext_addr |= GPD_EXT_NGP(mtu, upper_32_bits(enq_dma)); gpd->dw3_info = cpu_to_le32(ext_addr); gpd->dw0_info |= cpu_to_le32(GPD_FLAGS_IOC | GPD_FLAGS_HWO); Loading Loading @@ -391,7 +425,7 @@ static void qmu_tx_zlp_error_handler(struct mtu3 *mtu, u8 epnum) cur_gpd_dma = read_txq_cur_addr(mbase, epnum); gpd_current = gpd_dma_to_virt(ring, cur_gpd_dma); if (GPD_DATA_LEN(le32_to_cpu(gpd_current->dw3_info)) != 0) { if (GPD_DATA_LEN(mtu, le32_to_cpu(gpd_current->dw3_info)) != 0) { dev_err(mtu->dev, "TX EP%d buffer length error(!=0)\n", epnum); return; } Loading Loading @@ -451,7 +485,7 @@ static void qmu_done_tx(struct mtu3 *mtu, u8 epnum) } request = &mreq->request; request->actual = GPD_DATA_LEN(le32_to_cpu(gpd->dw3_info)); request->actual = GPD_DATA_LEN(mtu, le32_to_cpu(gpd->dw3_info)); mtu3_req_complete(mep, request, 0); gpd = advance_deq_gpd(ring); Loading Loading @@ -489,7 +523,7 @@ static void qmu_done_rx(struct mtu3 *mtu, u8 epnum) } req = &mreq->request; req->actual = GPD_DATA_LEN(le32_to_cpu(gpd->dw3_info)); req->actual = GPD_DATA_LEN(mtu, le32_to_cpu(gpd->dw3_info)); mtu3_req_complete(mep, req, 0); gpd = advance_deq_gpd(ring); Loading Loading
drivers/usb/mtu3/mtu3.h +6 −5 Original line number Diff line number Diff line Loading @@ -148,22 +148,23 @@ struct mtu3_fifo_info { * bit0: Hardware Own (HWO) * bit1: Buffer Descriptor Present (BDP), always 0, BD is not supported * bit2: Bypass (BPS), 1: HW skips this GPD if HWO = 1 * bit6: [EL] Zero Length Packet (ZLP), moved from @dw3_info[29] * bit7: Interrupt On Completion (IOC) * bit[31:16]: allow data buffer length (RX ONLY), * bit[31:16]: ([EL] bit[31:12]) allow data buffer length (RX ONLY), * the buffer length of the data to receive * bit[23:16]: extension address (TX ONLY), * bit[23:16]: ([EL] bit[31:24]) extension address (TX ONLY), * lower 4 bits are extension bits of @buffer, * upper 4 bits are extension bits of @next_gpd * @next_gpd: Physical address of the next GPD * @buffer: Physical address of the data buffer * @dw3_info: * bit[15:0]: data buffer length, * bit[15:0]: ([EL] bit[19:0]) data buffer length, * (TX): the buffer length of the data to transmit * (RX): The total length of data received * bit[23:16]: extension address (RX ONLY), * bit[23:16]: ([EL] bit[31:24]) extension address (RX ONLY), * lower 4 bits are extension bits of @buffer, * upper 4 bits are extension bits of @next_gpd * bit29: Zero Length Packet (ZLP) (TX ONLY) * bit29: ([EL] abandoned) Zero Length Packet (ZLP) (TX ONLY) */ struct qmu_gpd { __le32 dw0_info; Loading
drivers/usb/mtu3/mtu3_core.c +5 −0 Original line number Diff line number Diff line Loading @@ -601,6 +601,10 @@ static void mtu3_regs_init(struct mtu3 *mtu) mtu3_clrbits(mbase, U3D_MISC_CTRL, VBUS_FRC_EN | VBUS_ON); /* enable automatical HWRW from L1 */ mtu3_setbits(mbase, U3D_POWER_MANAGEMENT, LPM_HRWE); /* use new QMU format when HW version >= 0x1003 */ if (mtu->gen2cp) mtu3_writel(mbase, U3D_QFCR, ~0x0); } static irqreturn_t mtu3_link_isr(struct mtu3 *mtu) Loading Loading @@ -755,6 +759,7 @@ static int mtu3_hw_init(struct mtu3 *mtu) value = mtu3_readl(mtu->ippc_base, U3D_SSUSB_IP_TRUNK_VERS); mtu->hw_version = IP_TRUNK_VERS(value); mtu->gen2cp = !!(mtu->hw_version >= MTU3_TRUNK_VERS_1003); value = mtu3_readl(mtu->ippc_base, U3D_SSUSB_IP_DEV_CAP); mtu->is_u3_ip = !!SSUSB_IP_DEV_U3_PORT_NUM(value); Loading
drivers/usb/mtu3/mtu3_gadget.c +4 −2 Original line number Diff line number Diff line Loading @@ -278,10 +278,12 @@ static int mtu3_gadget_queue(struct usb_ep *ep, __func__, mep->is_in ? "TX" : "RX", mreq->epnum, ep->name, mreq, ep->maxpacket, mreq->request.length); if (req->length > GPD_BUF_SIZE) { if (req->length > GPD_BUF_SIZE || (mtu->gen2cp && req->length > GPD_BUF_SIZE_EL)) { dev_warn(mtu->dev, "req length > supported MAX:%d requested:%d\n", GPD_BUF_SIZE, req->length); mtu->gen2cp ? GPD_BUF_SIZE_EL : GPD_BUF_SIZE, req->length); return -EOPNOTSUPP; } Loading
drivers/usb/mtu3/mtu3_hw_regs.h +1 −0 Original line number Diff line number Diff line Loading @@ -49,6 +49,7 @@ #define U3D_QCR1 (SSUSB_DEV_BASE + 0x0404) #define U3D_QCR2 (SSUSB_DEV_BASE + 0x0408) #define U3D_QCR3 (SSUSB_DEV_BASE + 0x040C) #define U3D_QFCR (SSUSB_DEV_BASE + 0x0428) #define U3D_TXQHIAR1 (SSUSB_DEV_BASE + 0x0484) #define U3D_RXQHIAR1 (SSUSB_DEV_BASE + 0x04C4) Loading
drivers/usb/mtu3/mtu3_qmu.c +49 −15 Original line number Diff line number Diff line Loading @@ -28,14 +28,42 @@ #define GPD_FLAGS_HWO BIT(0) #define GPD_FLAGS_BDP BIT(1) #define GPD_FLAGS_BPS BIT(2) #define GPD_FLAGS_ZLP BIT(6) #define GPD_FLAGS_IOC BIT(7) #define GET_GPD_HWO(gpd) (le32_to_cpu((gpd)->dw0_info) & GPD_FLAGS_HWO) #define GPD_RX_BUF_LEN(x) (((x) & 0xffff) << 16) #define GPD_DATA_LEN(x) ((x) & 0xffff) #define GPD_RX_BUF_LEN_OG(x) (((x) & 0xffff) << 16) #define GPD_RX_BUF_LEN_EL(x) (((x) & 0xfffff) << 12) #define GPD_RX_BUF_LEN(mtu, x) \ ({ \ typeof(x) x_ = (x); \ ((mtu)->gen2cp) ? GPD_RX_BUF_LEN_EL(x_) : GPD_RX_BUF_LEN_OG(x_); \ }) #define GPD_DATA_LEN_OG(x) ((x) & 0xffff) #define GPD_DATA_LEN_EL(x) ((x) & 0xfffff) #define GPD_DATA_LEN(mtu, x) \ ({ \ typeof(x) x_ = (x); \ ((mtu)->gen2cp) ? GPD_DATA_LEN_EL(x_) : GPD_DATA_LEN_OG(x_); \ }) #define GPD_EXT_FLAG_ZLP BIT(29) #define GPD_EXT_NGP(x) (((x) & 0xf) << 20) #define GPD_EXT_BUF(x) (((x) & 0xf) << 16) #define GPD_EXT_NGP_OG(x) (((x) & 0xf) << 20) #define GPD_EXT_BUF_OG(x) (((x) & 0xf) << 16) #define GPD_EXT_NGP_EL(x) (((x) & 0xf) << 28) #define GPD_EXT_BUF_EL(x) (((x) & 0xf) << 24) #define GPD_EXT_NGP(mtu, x) \ ({ \ typeof(x) x_ = (x); \ ((mtu)->gen2cp) ? GPD_EXT_NGP_EL(x_) : GPD_EXT_NGP_OG(x_); \ }) #define GPD_EXT_BUF(mtu, x) \ ({ \ typeof(x) x_ = (x); \ ((mtu)->gen2cp) ? GPD_EXT_BUF_EL(x_) : GPD_EXT_BUF_OG(x_); \ }) #define HILO_GEN64(hi, lo) (((u64)(hi) << 32) + (lo)) #define HILO_DMA(hi, lo) \ Loading Loading @@ -217,13 +245,14 @@ static int mtu3_prepare_tx_gpd(struct mtu3_ep *mep, struct mtu3_request *mreq) struct mtu3_gpd_ring *ring = &mep->gpd_ring; struct qmu_gpd *gpd = ring->enqueue; struct usb_request *req = &mreq->request; struct mtu3 *mtu = mep->mtu; dma_addr_t enq_dma; u32 ext_addr; gpd->dw0_info = 0; /* SW own it */ gpd->buffer = cpu_to_le32(lower_32_bits(req->dma)); ext_addr = GPD_EXT_BUF(upper_32_bits(req->dma)); gpd->dw3_info = cpu_to_le32(GPD_DATA_LEN(req->length)); ext_addr = GPD_EXT_BUF(mtu, upper_32_bits(req->dma)); gpd->dw3_info = cpu_to_le32(GPD_DATA_LEN(mtu, req->length)); /* get the next GPD */ enq = advance_enq_gpd(ring); Loading @@ -233,11 +262,15 @@ static int mtu3_prepare_tx_gpd(struct mtu3_ep *mep, struct mtu3_request *mreq) enq->dw0_info &= cpu_to_le32(~GPD_FLAGS_HWO); gpd->next_gpd = cpu_to_le32(lower_32_bits(enq_dma)); ext_addr |= GPD_EXT_NGP(upper_32_bits(enq_dma)); ext_addr |= GPD_EXT_NGP(mtu, upper_32_bits(enq_dma)); gpd->dw0_info = cpu_to_le32(ext_addr); if (req->zero) if (req->zero) { if (mtu->gen2cp) gpd->dw0_info |= cpu_to_le32(GPD_FLAGS_ZLP); else gpd->dw3_info |= cpu_to_le32(GPD_EXT_FLAG_ZLP); } gpd->dw0_info |= cpu_to_le32(GPD_FLAGS_IOC | GPD_FLAGS_HWO); Loading @@ -252,13 +285,14 @@ static int mtu3_prepare_rx_gpd(struct mtu3_ep *mep, struct mtu3_request *mreq) struct mtu3_gpd_ring *ring = &mep->gpd_ring; struct qmu_gpd *gpd = ring->enqueue; struct usb_request *req = &mreq->request; struct mtu3 *mtu = mep->mtu; dma_addr_t enq_dma; u32 ext_addr; gpd->dw0_info = 0; /* SW own it */ gpd->buffer = cpu_to_le32(lower_32_bits(req->dma)); ext_addr = GPD_EXT_BUF(upper_32_bits(req->dma)); gpd->dw0_info = cpu_to_le32(GPD_RX_BUF_LEN(req->length)); ext_addr = GPD_EXT_BUF(mtu, upper_32_bits(req->dma)); gpd->dw0_info = cpu_to_le32(GPD_RX_BUF_LEN(mtu, req->length)); /* get the next GPD */ enq = advance_enq_gpd(ring); Loading @@ -268,7 +302,7 @@ static int mtu3_prepare_rx_gpd(struct mtu3_ep *mep, struct mtu3_request *mreq) enq->dw0_info &= cpu_to_le32(~GPD_FLAGS_HWO); gpd->next_gpd = cpu_to_le32(lower_32_bits(enq_dma)); ext_addr |= GPD_EXT_NGP(upper_32_bits(enq_dma)); ext_addr |= GPD_EXT_NGP(mtu, upper_32_bits(enq_dma)); gpd->dw3_info = cpu_to_le32(ext_addr); gpd->dw0_info |= cpu_to_le32(GPD_FLAGS_IOC | GPD_FLAGS_HWO); Loading Loading @@ -391,7 +425,7 @@ static void qmu_tx_zlp_error_handler(struct mtu3 *mtu, u8 epnum) cur_gpd_dma = read_txq_cur_addr(mbase, epnum); gpd_current = gpd_dma_to_virt(ring, cur_gpd_dma); if (GPD_DATA_LEN(le32_to_cpu(gpd_current->dw3_info)) != 0) { if (GPD_DATA_LEN(mtu, le32_to_cpu(gpd_current->dw3_info)) != 0) { dev_err(mtu->dev, "TX EP%d buffer length error(!=0)\n", epnum); return; } Loading Loading @@ -451,7 +485,7 @@ static void qmu_done_tx(struct mtu3 *mtu, u8 epnum) } request = &mreq->request; request->actual = GPD_DATA_LEN(le32_to_cpu(gpd->dw3_info)); request->actual = GPD_DATA_LEN(mtu, le32_to_cpu(gpd->dw3_info)); mtu3_req_complete(mep, request, 0); gpd = advance_deq_gpd(ring); Loading Loading @@ -489,7 +523,7 @@ static void qmu_done_rx(struct mtu3 *mtu, u8 epnum) } req = &mreq->request; req->actual = GPD_DATA_LEN(le32_to_cpu(gpd->dw3_info)); req->actual = GPD_DATA_LEN(mtu, le32_to_cpu(gpd->dw3_info)); mtu3_req_complete(mep, req, 0); gpd = advance_deq_gpd(ring); Loading