diff options
author | Chunfeng Yun <chunfeng.yun@mediatek.com> | 2019-03-20 22:53:45 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2019-03-26 03:40:13 -0400 |
commit | 48e0d3735aa557a8adaf94632ca3cf78798e8505 (patch) | |
tree | 8769798ea7b0a5a9410580bd5c15f0ad5b55ca06 | |
parent | 09befc326eea250cf6a3175114e1578d498a21ea (diff) |
usb: mtu3: supports new QMU format
In order to support U3gen2 ISOC transfer upto 96DPs, extend
the data buffer length.
Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r-- | drivers/usb/mtu3/mtu3.h | 11 | ||||
-rw-r--r-- | drivers/usb/mtu3/mtu3_core.c | 5 | ||||
-rw-r--r-- | drivers/usb/mtu3/mtu3_gadget.c | 6 | ||||
-rw-r--r-- | drivers/usb/mtu3/mtu3_hw_regs.h | 1 | ||||
-rw-r--r-- | drivers/usb/mtu3/mtu3_qmu.c | 64 | ||||
-rw-r--r-- | drivers/usb/mtu3/mtu3_qmu.h | 1 |
6 files changed, 66 insertions, 22 deletions
diff --git a/drivers/usb/mtu3/mtu3.h b/drivers/usb/mtu3/mtu3.h index 4dda7ed6e24e..76ecf12fdf62 100644 --- a/drivers/usb/mtu3/mtu3.h +++ b/drivers/usb/mtu3/mtu3.h | |||
@@ -148,22 +148,23 @@ struct mtu3_fifo_info { | |||
148 | * bit0: Hardware Own (HWO) | 148 | * bit0: Hardware Own (HWO) |
149 | * bit1: Buffer Descriptor Present (BDP), always 0, BD is not supported | 149 | * bit1: Buffer Descriptor Present (BDP), always 0, BD is not supported |
150 | * bit2: Bypass (BPS), 1: HW skips this GPD if HWO = 1 | 150 | * bit2: Bypass (BPS), 1: HW skips this GPD if HWO = 1 |
151 | * bit6: [EL] Zero Length Packet (ZLP), moved from @dw3_info[29] | ||
151 | * bit7: Interrupt On Completion (IOC) | 152 | * bit7: Interrupt On Completion (IOC) |
152 | * bit[31:16]: allow data buffer length (RX ONLY), | 153 | * bit[31:16]: ([EL] bit[31:12]) allow data buffer length (RX ONLY), |
153 | * the buffer length of the data to receive | 154 | * the buffer length of the data to receive |
154 | * bit[23:16]: extension address (TX ONLY), | 155 | * bit[23:16]: ([EL] bit[31:24]) extension address (TX ONLY), |
155 | * lower 4 bits are extension bits of @buffer, | 156 | * lower 4 bits are extension bits of @buffer, |
156 | * upper 4 bits are extension bits of @next_gpd | 157 | * upper 4 bits are extension bits of @next_gpd |
157 | * @next_gpd: Physical address of the next GPD | 158 | * @next_gpd: Physical address of the next GPD |
158 | * @buffer: Physical address of the data buffer | 159 | * @buffer: Physical address of the data buffer |
159 | * @dw3_info: | 160 | * @dw3_info: |
160 | * bit[15:0]: data buffer length, | 161 | * bit[15:0]: ([EL] bit[19:0]) data buffer length, |
161 | * (TX): the buffer length of the data to transmit | 162 | * (TX): the buffer length of the data to transmit |
162 | * (RX): The total length of data received | 163 | * (RX): The total length of data received |
163 | * bit[23:16]: extension address (RX ONLY), | 164 | * bit[23:16]: ([EL] bit[31:24]) extension address (RX ONLY), |
164 | * lower 4 bits are extension bits of @buffer, | 165 | * lower 4 bits are extension bits of @buffer, |
165 | * upper 4 bits are extension bits of @next_gpd | 166 | * upper 4 bits are extension bits of @next_gpd |
166 | * bit29: Zero Length Packet (ZLP) (TX ONLY) | 167 | * bit29: ([EL] abandoned) Zero Length Packet (ZLP) (TX ONLY) |
167 | */ | 168 | */ |
168 | struct qmu_gpd { | 169 | struct qmu_gpd { |
169 | __le32 dw0_info; | 170 | __le32 dw0_info; |
diff --git a/drivers/usb/mtu3/mtu3_core.c b/drivers/usb/mtu3/mtu3_core.c index ef27c2052ad6..d354f5c3805a 100644 --- a/drivers/usb/mtu3/mtu3_core.c +++ b/drivers/usb/mtu3/mtu3_core.c | |||
@@ -601,6 +601,10 @@ static void mtu3_regs_init(struct mtu3 *mtu) | |||
601 | mtu3_clrbits(mbase, U3D_MISC_CTRL, VBUS_FRC_EN | VBUS_ON); | 601 | mtu3_clrbits(mbase, U3D_MISC_CTRL, VBUS_FRC_EN | VBUS_ON); |
602 | /* enable automatical HWRW from L1 */ | 602 | /* enable automatical HWRW from L1 */ |
603 | mtu3_setbits(mbase, U3D_POWER_MANAGEMENT, LPM_HRWE); | 603 | mtu3_setbits(mbase, U3D_POWER_MANAGEMENT, LPM_HRWE); |
604 | |||
605 | /* use new QMU format when HW version >= 0x1003 */ | ||
606 | if (mtu->gen2cp) | ||
607 | mtu3_writel(mbase, U3D_QFCR, ~0x0); | ||
604 | } | 608 | } |
605 | 609 | ||
606 | static irqreturn_t mtu3_link_isr(struct mtu3 *mtu) | 610 | static irqreturn_t mtu3_link_isr(struct mtu3 *mtu) |
@@ -755,6 +759,7 @@ static int mtu3_hw_init(struct mtu3 *mtu) | |||
755 | 759 | ||
756 | value = mtu3_readl(mtu->ippc_base, U3D_SSUSB_IP_TRUNK_VERS); | 760 | value = mtu3_readl(mtu->ippc_base, U3D_SSUSB_IP_TRUNK_VERS); |
757 | mtu->hw_version = IP_TRUNK_VERS(value); | 761 | mtu->hw_version = IP_TRUNK_VERS(value); |
762 | mtu->gen2cp = !!(mtu->hw_version >= MTU3_TRUNK_VERS_1003); | ||
758 | 763 | ||
759 | value = mtu3_readl(mtu->ippc_base, U3D_SSUSB_IP_DEV_CAP); | 764 | value = mtu3_readl(mtu->ippc_base, U3D_SSUSB_IP_DEV_CAP); |
760 | mtu->is_u3_ip = !!SSUSB_IP_DEV_U3_PORT_NUM(value); | 765 | mtu->is_u3_ip = !!SSUSB_IP_DEV_U3_PORT_NUM(value); |
diff --git a/drivers/usb/mtu3/mtu3_gadget.c b/drivers/usb/mtu3/mtu3_gadget.c index bbcd3332471d..fe798b94a357 100644 --- a/drivers/usb/mtu3/mtu3_gadget.c +++ b/drivers/usb/mtu3/mtu3_gadget.c | |||
@@ -278,10 +278,12 @@ static int mtu3_gadget_queue(struct usb_ep *ep, | |||
278 | __func__, mep->is_in ? "TX" : "RX", mreq->epnum, ep->name, | 278 | __func__, mep->is_in ? "TX" : "RX", mreq->epnum, ep->name, |
279 | mreq, ep->maxpacket, mreq->request.length); | 279 | mreq, ep->maxpacket, mreq->request.length); |
280 | 280 | ||
281 | if (req->length > GPD_BUF_SIZE) { | 281 | if (req->length > GPD_BUF_SIZE || |
282 | (mtu->gen2cp && req->length > GPD_BUF_SIZE_EL)) { | ||
282 | dev_warn(mtu->dev, | 283 | dev_warn(mtu->dev, |
283 | "req length > supported MAX:%d requested:%d\n", | 284 | "req length > supported MAX:%d requested:%d\n", |
284 | GPD_BUF_SIZE, req->length); | 285 | mtu->gen2cp ? GPD_BUF_SIZE_EL : GPD_BUF_SIZE, |
286 | req->length); | ||
285 | return -EOPNOTSUPP; | 287 | return -EOPNOTSUPP; |
286 | } | 288 | } |
287 | 289 | ||
diff --git a/drivers/usb/mtu3/mtu3_hw_regs.h b/drivers/usb/mtu3/mtu3_hw_regs.h index fae3b8de1092..bf70ea2426a9 100644 --- a/drivers/usb/mtu3/mtu3_hw_regs.h +++ b/drivers/usb/mtu3/mtu3_hw_regs.h | |||
@@ -49,6 +49,7 @@ | |||
49 | #define U3D_QCR1 (SSUSB_DEV_BASE + 0x0404) | 49 | #define U3D_QCR1 (SSUSB_DEV_BASE + 0x0404) |
50 | #define U3D_QCR2 (SSUSB_DEV_BASE + 0x0408) | 50 | #define U3D_QCR2 (SSUSB_DEV_BASE + 0x0408) |
51 | #define U3D_QCR3 (SSUSB_DEV_BASE + 0x040C) | 51 | #define U3D_QCR3 (SSUSB_DEV_BASE + 0x040C) |
52 | #define U3D_QFCR (SSUSB_DEV_BASE + 0x0428) | ||
52 | #define U3D_TXQHIAR1 (SSUSB_DEV_BASE + 0x0484) | 53 | #define U3D_TXQHIAR1 (SSUSB_DEV_BASE + 0x0484) |
53 | #define U3D_RXQHIAR1 (SSUSB_DEV_BASE + 0x04C4) | 54 | #define U3D_RXQHIAR1 (SSUSB_DEV_BASE + 0x04C4) |
54 | 55 | ||
diff --git a/drivers/usb/mtu3/mtu3_qmu.c b/drivers/usb/mtu3/mtu3_qmu.c index 7a1919fc9f9e..9f017aa8fbeb 100644 --- a/drivers/usb/mtu3/mtu3_qmu.c +++ b/drivers/usb/mtu3/mtu3_qmu.c | |||
@@ -28,14 +28,42 @@ | |||
28 | #define GPD_FLAGS_HWO BIT(0) | 28 | #define GPD_FLAGS_HWO BIT(0) |
29 | #define GPD_FLAGS_BDP BIT(1) | 29 | #define GPD_FLAGS_BDP BIT(1) |
30 | #define GPD_FLAGS_BPS BIT(2) | 30 | #define GPD_FLAGS_BPS BIT(2) |
31 | #define GPD_FLAGS_ZLP BIT(6) | ||
31 | #define GPD_FLAGS_IOC BIT(7) | 32 | #define GPD_FLAGS_IOC BIT(7) |
32 | #define GET_GPD_HWO(gpd) (le32_to_cpu((gpd)->dw0_info) & GPD_FLAGS_HWO) | 33 | #define GET_GPD_HWO(gpd) (le32_to_cpu((gpd)->dw0_info) & GPD_FLAGS_HWO) |
33 | 34 | ||
34 | #define GPD_RX_BUF_LEN(x) (((x) & 0xffff) << 16) | 35 | #define GPD_RX_BUF_LEN_OG(x) (((x) & 0xffff) << 16) |
35 | #define GPD_DATA_LEN(x) ((x) & 0xffff) | 36 | #define GPD_RX_BUF_LEN_EL(x) (((x) & 0xfffff) << 12) |
37 | #define GPD_RX_BUF_LEN(mtu, x) \ | ||
38 | ({ \ | ||
39 | typeof(x) x_ = (x); \ | ||
40 | ((mtu)->gen2cp) ? GPD_RX_BUF_LEN_EL(x_) : GPD_RX_BUF_LEN_OG(x_); \ | ||
41 | }) | ||
42 | |||
43 | #define GPD_DATA_LEN_OG(x) ((x) & 0xffff) | ||
44 | #define GPD_DATA_LEN_EL(x) ((x) & 0xfffff) | ||
45 | #define GPD_DATA_LEN(mtu, x) \ | ||
46 | ({ \ | ||
47 | typeof(x) x_ = (x); \ | ||
48 | ((mtu)->gen2cp) ? GPD_DATA_LEN_EL(x_) : GPD_DATA_LEN_OG(x_); \ | ||
49 | }) | ||
50 | |||
36 | #define GPD_EXT_FLAG_ZLP BIT(29) | 51 | #define GPD_EXT_FLAG_ZLP BIT(29) |
37 | #define GPD_EXT_NGP(x) (((x) & 0xf) << 20) | 52 | #define GPD_EXT_NGP_OG(x) (((x) & 0xf) << 20) |
38 | #define GPD_EXT_BUF(x) (((x) & 0xf) << 16) | 53 | #define GPD_EXT_BUF_OG(x) (((x) & 0xf) << 16) |
54 | #define GPD_EXT_NGP_EL(x) (((x) & 0xf) << 28) | ||
55 | #define GPD_EXT_BUF_EL(x) (((x) & 0xf) << 24) | ||
56 | #define GPD_EXT_NGP(mtu, x) \ | ||
57 | ({ \ | ||
58 | typeof(x) x_ = (x); \ | ||
59 | ((mtu)->gen2cp) ? GPD_EXT_NGP_EL(x_) : GPD_EXT_NGP_OG(x_); \ | ||
60 | }) | ||
61 | |||
62 | #define GPD_EXT_BUF(mtu, x) \ | ||
63 | ({ \ | ||
64 | typeof(x) x_ = (x); \ | ||
65 | ((mtu)->gen2cp) ? GPD_EXT_BUF_EL(x_) : GPD_EXT_BUF_OG(x_); \ | ||
66 | }) | ||
39 | 67 | ||
40 | #define HILO_GEN64(hi, lo) (((u64)(hi) << 32) + (lo)) | 68 | #define HILO_GEN64(hi, lo) (((u64)(hi) << 32) + (lo)) |
41 | #define HILO_DMA(hi, lo) \ | 69 | #define HILO_DMA(hi, lo) \ |
@@ -217,13 +245,14 @@ static int mtu3_prepare_tx_gpd(struct mtu3_ep *mep, struct mtu3_request *mreq) | |||
217 | struct mtu3_gpd_ring *ring = &mep->gpd_ring; | 245 | struct mtu3_gpd_ring *ring = &mep->gpd_ring; |
218 | struct qmu_gpd *gpd = ring->enqueue; | 246 | struct qmu_gpd *gpd = ring->enqueue; |
219 | struct usb_request *req = &mreq->request; | 247 | struct usb_request *req = &mreq->request; |
248 | struct mtu3 *mtu = mep->mtu; | ||
220 | dma_addr_t enq_dma; | 249 | dma_addr_t enq_dma; |
221 | u32 ext_addr; | 250 | u32 ext_addr; |
222 | 251 | ||
223 | gpd->dw0_info = 0; /* SW own it */ | 252 | gpd->dw0_info = 0; /* SW own it */ |
224 | gpd->buffer = cpu_to_le32(lower_32_bits(req->dma)); | 253 | gpd->buffer = cpu_to_le32(lower_32_bits(req->dma)); |
225 | ext_addr = GPD_EXT_BUF(upper_32_bits(req->dma)); | 254 | ext_addr = GPD_EXT_BUF(mtu, upper_32_bits(req->dma)); |
226 | gpd->dw3_info = cpu_to_le32(GPD_DATA_LEN(req->length)); | 255 | gpd->dw3_info = cpu_to_le32(GPD_DATA_LEN(mtu, req->length)); |
227 | 256 | ||
228 | /* get the next GPD */ | 257 | /* get the next GPD */ |
229 | enq = advance_enq_gpd(ring); | 258 | enq = advance_enq_gpd(ring); |
@@ -233,11 +262,15 @@ static int mtu3_prepare_tx_gpd(struct mtu3_ep *mep, struct mtu3_request *mreq) | |||
233 | 262 | ||
234 | enq->dw0_info &= cpu_to_le32(~GPD_FLAGS_HWO); | 263 | enq->dw0_info &= cpu_to_le32(~GPD_FLAGS_HWO); |
235 | gpd->next_gpd = cpu_to_le32(lower_32_bits(enq_dma)); | 264 | gpd->next_gpd = cpu_to_le32(lower_32_bits(enq_dma)); |
236 | ext_addr |= GPD_EXT_NGP(upper_32_bits(enq_dma)); | 265 | ext_addr |= GPD_EXT_NGP(mtu, upper_32_bits(enq_dma)); |
237 | gpd->dw0_info = cpu_to_le32(ext_addr); | 266 | gpd->dw0_info = cpu_to_le32(ext_addr); |
238 | 267 | ||
239 | if (req->zero) | 268 | if (req->zero) { |
240 | gpd->dw3_info |= cpu_to_le32(GPD_EXT_FLAG_ZLP); | 269 | if (mtu->gen2cp) |
270 | gpd->dw0_info |= cpu_to_le32(GPD_FLAGS_ZLP); | ||
271 | else | ||
272 | gpd->dw3_info |= cpu_to_le32(GPD_EXT_FLAG_ZLP); | ||
273 | } | ||
241 | 274 | ||
242 | gpd->dw0_info |= cpu_to_le32(GPD_FLAGS_IOC | GPD_FLAGS_HWO); | 275 | gpd->dw0_info |= cpu_to_le32(GPD_FLAGS_IOC | GPD_FLAGS_HWO); |
243 | 276 | ||
@@ -252,13 +285,14 @@ static int mtu3_prepare_rx_gpd(struct mtu3_ep *mep, struct mtu3_request *mreq) | |||
252 | struct mtu3_gpd_ring *ring = &mep->gpd_ring; | 285 | struct mtu3_gpd_ring *ring = &mep->gpd_ring; |
253 | struct qmu_gpd *gpd = ring->enqueue; | 286 | struct qmu_gpd *gpd = ring->enqueue; |
254 | struct usb_request *req = &mreq->request; | 287 | struct usb_request *req = &mreq->request; |
288 | struct mtu3 *mtu = mep->mtu; | ||
255 | dma_addr_t enq_dma; | 289 | dma_addr_t enq_dma; |
256 | u32 ext_addr; | 290 | u32 ext_addr; |
257 | 291 | ||
258 | gpd->dw0_info = 0; /* SW own it */ | 292 | gpd->dw0_info = 0; /* SW own it */ |
259 | gpd->buffer = cpu_to_le32(lower_32_bits(req->dma)); | 293 | gpd->buffer = cpu_to_le32(lower_32_bits(req->dma)); |
260 | ext_addr = GPD_EXT_BUF(upper_32_bits(req->dma)); | 294 | ext_addr = GPD_EXT_BUF(mtu, upper_32_bits(req->dma)); |
261 | gpd->dw0_info = cpu_to_le32(GPD_RX_BUF_LEN(req->length)); | 295 | gpd->dw0_info = cpu_to_le32(GPD_RX_BUF_LEN(mtu, req->length)); |
262 | 296 | ||
263 | /* get the next GPD */ | 297 | /* get the next GPD */ |
264 | enq = advance_enq_gpd(ring); | 298 | enq = advance_enq_gpd(ring); |
@@ -268,7 +302,7 @@ static int mtu3_prepare_rx_gpd(struct mtu3_ep *mep, struct mtu3_request *mreq) | |||
268 | 302 | ||
269 | enq->dw0_info &= cpu_to_le32(~GPD_FLAGS_HWO); | 303 | enq->dw0_info &= cpu_to_le32(~GPD_FLAGS_HWO); |
270 | gpd->next_gpd = cpu_to_le32(lower_32_bits(enq_dma)); | 304 | gpd->next_gpd = cpu_to_le32(lower_32_bits(enq_dma)); |
271 | ext_addr |= GPD_EXT_NGP(upper_32_bits(enq_dma)); | 305 | ext_addr |= GPD_EXT_NGP(mtu, upper_32_bits(enq_dma)); |
272 | gpd->dw3_info = cpu_to_le32(ext_addr); | 306 | gpd->dw3_info = cpu_to_le32(ext_addr); |
273 | gpd->dw0_info |= cpu_to_le32(GPD_FLAGS_IOC | GPD_FLAGS_HWO); | 307 | gpd->dw0_info |= cpu_to_le32(GPD_FLAGS_IOC | GPD_FLAGS_HWO); |
274 | 308 | ||
@@ -391,7 +425,7 @@ static void qmu_tx_zlp_error_handler(struct mtu3 *mtu, u8 epnum) | |||
391 | cur_gpd_dma = read_txq_cur_addr(mbase, epnum); | 425 | cur_gpd_dma = read_txq_cur_addr(mbase, epnum); |
392 | gpd_current = gpd_dma_to_virt(ring, cur_gpd_dma); | 426 | gpd_current = gpd_dma_to_virt(ring, cur_gpd_dma); |
393 | 427 | ||
394 | if (GPD_DATA_LEN(le32_to_cpu(gpd_current->dw3_info)) != 0) { | 428 | if (GPD_DATA_LEN(mtu, le32_to_cpu(gpd_current->dw3_info)) != 0) { |
395 | dev_err(mtu->dev, "TX EP%d buffer length error(!=0)\n", epnum); | 429 | dev_err(mtu->dev, "TX EP%d buffer length error(!=0)\n", epnum); |
396 | return; | 430 | return; |
397 | } | 431 | } |
@@ -451,7 +485,7 @@ static void qmu_done_tx(struct mtu3 *mtu, u8 epnum) | |||
451 | } | 485 | } |
452 | 486 | ||
453 | request = &mreq->request; | 487 | request = &mreq->request; |
454 | request->actual = GPD_DATA_LEN(le32_to_cpu(gpd->dw3_info)); | 488 | request->actual = GPD_DATA_LEN(mtu, le32_to_cpu(gpd->dw3_info)); |
455 | mtu3_req_complete(mep, request, 0); | 489 | mtu3_req_complete(mep, request, 0); |
456 | 490 | ||
457 | gpd = advance_deq_gpd(ring); | 491 | gpd = advance_deq_gpd(ring); |
@@ -489,7 +523,7 @@ static void qmu_done_rx(struct mtu3 *mtu, u8 epnum) | |||
489 | } | 523 | } |
490 | req = &mreq->request; | 524 | req = &mreq->request; |
491 | 525 | ||
492 | req->actual = GPD_DATA_LEN(le32_to_cpu(gpd->dw3_info)); | 526 | req->actual = GPD_DATA_LEN(mtu, le32_to_cpu(gpd->dw3_info)); |
493 | mtu3_req_complete(mep, req, 0); | 527 | mtu3_req_complete(mep, req, 0); |
494 | 528 | ||
495 | gpd = advance_deq_gpd(ring); | 529 | gpd = advance_deq_gpd(ring); |
diff --git a/drivers/usb/mtu3/mtu3_qmu.h b/drivers/usb/mtu3/mtu3_qmu.h index 81f5151a55ed..9cfde201db63 100644 --- a/drivers/usb/mtu3/mtu3_qmu.h +++ b/drivers/usb/mtu3/mtu3_qmu.h | |||
@@ -15,6 +15,7 @@ | |||
15 | #define QMU_GPD_RING_SIZE (MAX_GPD_NUM * QMU_GPD_SIZE) | 15 | #define QMU_GPD_RING_SIZE (MAX_GPD_NUM * QMU_GPD_SIZE) |
16 | 16 | ||
17 | #define GPD_BUF_SIZE 65532 | 17 | #define GPD_BUF_SIZE 65532 |
18 | #define GPD_BUF_SIZE_EL 1048572 | ||
18 | 19 | ||
19 | void mtu3_qmu_stop(struct mtu3_ep *mep); | 20 | void mtu3_qmu_stop(struct mtu3_ep *mep); |
20 | int mtu3_qmu_start(struct mtu3_ep *mep); | 21 | int mtu3_qmu_start(struct mtu3_ep *mep); |