1 /*        $NetBSD: ehci_mv.c,v 1.10 2021/08/07 16:19:13 thorpej Exp $ */
2 /*
3  * Copyright (c) 2008 KIYOHARA Takashi
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
19  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
23  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
24  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25  * POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 #include <sys/cdefs.h>
29 __KERNEL_RCSID(0, "$NetBSD: ehci_mv.c,v 1.10 2021/08/07 16:19:13 thorpej Exp $");
30 
31 #include <sys/param.h>
32 #include <sys/bus.h>
33 #include <sys/device.h>
34 #include <sys/errno.h>
35 #include <sys/systm.h>
36 
37 #include <dev/marvell/marvellreg.h>
38 #include <dev/marvell/marvellvar.h>
39 
40 #include <dev/usb/usb.h>
41 #include <dev/usb/usbdi.h>
42 #include <dev/usb/usbdivar.h>
43 #include <dev/usb/usb_mem.h>
44 
45 #include <dev/usb/ehcireg.h>
46 #include <dev/usb/ehcivar.h>
47 
48 #include "locators.h"
49 
50 #ifdef EHCI_DEBUG
51 #define DPRINTF(x)  if (ehcidebug) printf x
52 extern int ehcidebug;
53 #else
54 #define DPRINTF(x)
55 #endif
56 
57 
58 #define MARVELL_USB_SIZE                0x1000
59 
60 #define MARVELL_USB_NWINDOW             4
61 
62 #define MARVELL_USB_ID                            0x000
63 #define MARVELL_USB_HWGENERAL           0x004
64 #define MARVELL_USB_HWHOST              0x008
65 #define MARVELL_USB_HWDEVICE            0x00c
66 #define MARVELL_USB_HWTXBUF             0x010
67 #define MARVELL_USB_HWRXBUF             0x014
68 #define MARVELL_USB_HWTTTXBUF           0x018
69 #define MARVELL_USB_HWTTRXBUF           0x01c
70 
71 /* ehci generic registers */
72 #define MARVELL_USB_EHCI_BASE           0x100
73 #define MARVELL_USB_EHCI_SIZE           0x100
74 
75 /* ehci vendor extension registers */
76 #define MARVELL_USB_EHCI_PS_PSPD        0x0c000000          /* Port speed */
77 #define MARVELL_USB_EHCI_PS_PSPD_FS     0x00000000          /*  Full speed */
78 #define MARVELL_USB_EHCI_PS_PSPD_LS     0x04000000          /*  Low speed */
79 #define MARVELL_USB_EHCI_PS_PSPD_HS     0x08000000          /*  High speed */
80 
81 #define MARVELL_USB_EHCI_USBMODE        0x68
82 #define MARVELL_USB_EHCI_MODE_STRMDIS   0x00000008 /* RW straming disable */
83 #define MARVELL_USB_EHCI_MODE_BE        0x00000004 /* RW B/L endianness select*/
84 #define MARVELL_USB_EHCI_MODE_HDMASK    0x00000003 /* RW host/device Mask */
85 #define MARVELL_USB_EHCI_MODE_HOST      0x00000003 /* RW mode host */
86 #define MARVELL_USB_EHCI_MODE_DEVICE    0x00000002 /* RW mode device */
87 
88 #define MARVELL_USB_DCIVERSION                    0x120
89 #define MARVELL_USB_DCCPARAMS           0x124
90 #define MARVELL_USB_TTCTRL              0x15c
91 #define MARVELL_USB_BURSTSIZE           0x160
92 #define MARVELL_USB_TXFILLTUNING        0x164
93 #define MARVELL_USB_TXTTFILLTUNING      0x168
94 #define MARVELL_USB_OTGSC               0x1a4
95 #define MARVELL_USB_USBMODE             0x1a8
96 #define MARVELL_USB_USBMODE_MASK                  (3 << 0)
97 #define MARVELL_USB_USBMODE_HOST                  (3 << 0)
98 #define MARVELL_USB_USBMODE_DEVICE                (2 << 0)
99 #define MARVELL_USB_USBMODE_STREAMDISABLE         (1 << 4)
100 #define MARVELL_USB_ENPDTSETUPSTAT      0x1ac
101 #define MARVELL_USB_ENDPTPRIME                    0x1b0
102 #define MARVELL_USB_ENDPTFLUSH                    0x1b4
103 #define MARVELL_USB_ENDPTSTATS                    0x1b8
104 #define MARVELL_USB_ENDPTCOMPLETE       0x1bc
105 #define MARVELL_USB_ENDPTCTRL0                    0x1c0
106 #define MARVELL_USB_ENDPTCTRL1                    0x1c1
107 #define MARVELL_USB_ENDPTCTRL2                    0x1c2
108 #define MARVELL_USB_ENDPTCTRL3                    0x1c3
109 /* Bridge Control And Status Registers */
110 #define MARVELL_USB_BCR                           0x300 /* Control */
111 /* Bridge Interrupt and Error Registers */
112 #define MARVELL_USB_BICR                0x310 /* Interrupt Cause */
113 #define MARVELL_USB_BIMR                0x314 /* Interrupt Mask */
114 #define MARVELL_USB_BIR_ADDRDECERR                (1 << 0)
115 #define MARVELL_USB_BEAR                0x31c /* Error Address */
116 /* Bridge Address Decoding Registers */
117 #define MARVELL_USB_WCR(n)              (0x320 + (n) * 0x10) /* WinN Control */
118 #define MARVELL_USB_WCR_WINEN                     (1 << 0)
119 #define MARVELL_USB_WCR_TARGET(t)                 (((t) & 0xf) << 4)
120 #define MARVELL_USB_WCR_ATTR(a)                             (((a) & 0xff) << 8)
121 #define MARVELL_USB_WCR_SIZE(s)                             (((s) - 1) & 0xffff0000)
122 #define MARVELL_USB_WBR(n)              (0x324 + (n) * 0x10) /* WinN Base */
123 #define MARVELL_USB_WBR_BASE(b)                             ((b) & 0xffff0000)
124 /* IPG Metal Fix Register ??? */
125 #define MARVELL_USB_IPGR                0x360
126 /* USB 2.0 PHY Register Map */
127 #define MARVELL_USB_PCR                           0x400 /* Power Control */
128 #define MARVELL_USB_PCR_PU                        (1 << 0)        /* Power Up */
129 #define MARVELL_USB_PCR_PUPLL                     (1 << 1)        /*Power Up PLL*/
130 #define MARVELL_USB_PCR_SUSPENDM                  (1 << 2)
131 #define MARVELL_USB_PCR_VBUSPWRFAULT              (1 << 3)
132 #define MARVELL_USB_PCR_PWRCTLWAKEUP              (1 << 4)
133 #define MARVELL_USB_PCR_PUREF                     (1 << 5)
134 #define MARVELL_USB_PCR_BGVSEL_MASK               (3 << 6)
135 #define MARVELL_USB_PCR_BGVSEL_CONNECT_ANAGRP     (1 << 6)
136 #define MARVELL_USB_PCR_REGARCDPDMMODE            (1 << 8)
137 #define MARVELL_USB_PCR_REGDPPULLDOWN             (1 << 9)
138 #define MARVELL_USB_PCR_REGDMPULLDOWN             (1 << 10)
139 #define MARVELL_USB_PCR_UTMISESSION               (1 << 23)
140 #define MARVELL_USB_PCR_UTMIVBUSVALID             (1 << 24)
141 #define MARVELL_USB_PCR_UTMIAVALID                (1 << 25)
142 #define MARVELL_USB_PCR_UTMIBVALID                (1 << 26)
143 #define MARVELL_USB_PCR_TXBITSTUFF                (1 << 27)
144 /* USB PHY Tx Control Register */
145 #define MARVELL_USB_PTCR                0x420
146 /* USB PHY Rx Control Register */
147 #define MARVELL_USB_PRCR                0x430
148 /* USB PHY IVREFF Control Register */
149 #define MARVELL_USB_PIVREFFCR           0x440
150 /* USB PHY Test Group Control Register */
151 #define MARVELL_USB_PTGCR               0x450
152 
153 
154 struct mvusb_softc {
155           ehci_softc_t sc;
156 
157           int sc_model;
158           int sc_rev;
159 
160           bus_space_tag_t sc_iot;
161           bus_space_handle_t sc_ioh;
162 };
163 
164 static int mvusb_match(device_t, cfdata_t, void *);
165 static void mvusb_attach(device_t, device_t, void *);
166 
167 static void mvusb_init(struct mvusb_softc *, enum marvell_tags *);
168 static void mvusb_wininit(struct mvusb_softc *, enum marvell_tags *);
169 
170 static void mvusb_vendor_init(struct ehci_softc *);
171 static int mvusb_vendor_port_status(struct ehci_softc *, uint32_t, int);
172 
173 CFATTACH_DECL2_NEW(mvusb_gt, sizeof(struct mvusb_softc),
174     mvusb_match, mvusb_attach, NULL, ehci_activate, NULL, ehci_childdet);
175 CFATTACH_DECL2_NEW(mvusb_mbus, sizeof(struct mvusb_softc),
176     mvusb_match, mvusb_attach, NULL, ehci_activate, NULL, ehci_childdet);
177 
178 
179 /* ARGSUSED */
180 static int
mvusb_match(device_t parent,cfdata_t match,void * aux)181 mvusb_match(device_t parent, cfdata_t match, void *aux)
182 {
183           struct marvell_attach_args *mva = aux;
184 
185           if (strcmp(mva->mva_name, match->cf_name) != 0)
186                     return 0;
187           if (mva->mva_offset == MVA_OFFSET_DEFAULT ||
188               mva->mva_irq == MVA_IRQ_DEFAULT)
189                     return 0;
190 
191           mva->mva_size = MARVELL_USB_SIZE;
192           return 1;
193 }
194 
195 /* ARGSUSED */
196 static void
mvusb_attach(device_t parent,device_t self,void * aux)197 mvusb_attach(device_t parent, device_t self, void *aux)
198 {
199           struct mvusb_softc *sc = device_private(self);
200           struct marvell_attach_args *mva = aux;
201 
202           aprint_normal(": Marvell USB 2.0 Interface\n");
203           aprint_naive("\n");
204 
205           sc->sc.sc_dev = self;
206           sc->sc.sc_bus.ub_hcpriv = sc;
207 
208           sc->sc_model = mva->mva_model;
209           sc->sc_rev = mva->mva_revision;
210           sc->sc_iot = mva->mva_iot;
211 
212           /* Map I/O registers for marvell usb */
213           if (bus_space_subregion(mva->mva_iot, mva->mva_ioh, mva->mva_offset,
214               mva->mva_size, &sc->sc_ioh)) {
215                     aprint_error_dev(self, "can't map registers\n");
216                     return;
217           }
218           mvusb_init(sc, mva->mva_tags);
219 
220           /* Map I/O registers for ehci */
221           sc->sc.sc_size = MARVELL_USB_EHCI_SIZE;
222           if (bus_space_subregion(sc->sc_iot, sc->sc_ioh, MARVELL_USB_EHCI_BASE,
223               sc->sc.sc_size, &sc->sc.ioh)) {
224                     aprint_error_dev(self, "can't subregion registers\n");
225                     return;
226           }
227           sc->sc.iot = sc->sc_iot;
228           sc->sc.sc_bus.ub_dmatag = mva->mva_dmat;
229 
230           /* Disable interrupts, so we don't get any spurious ones. */
231           sc->sc.sc_offs = EREAD1(&sc->sc, EHCI_CAPLENGTH);
232           DPRINTF(("%s: offs=%d\n", device_xname(self), sc->sc.sc_offs));
233           EOWRITE2(&sc->sc, EHCI_USBINTR, 0);
234 
235           marvell_intr_establish(mva->mva_irq, IPL_USB, ehci_intr, sc);
236 
237           sc->sc.sc_bus.ub_revision = USBREV_2_0;
238 
239           sc->sc.sc_vendor_init = mvusb_vendor_init;
240           sc->sc.sc_vendor_port_status = mvusb_vendor_port_status;
241 
242           int err = ehci_init(&sc->sc);
243           if (err) {
244                     aprint_error_dev(self, "init failed, error=%d\n", err);
245                     return;
246           }
247 
248           /* Attach usb device. */
249           sc->sc.sc_child = config_found(self, &sc->sc.sc_bus, usbctlprint,
250               CFARGS_NONE);
251 }
252 
253 static void
mvusb_init(struct mvusb_softc * sc,enum marvell_tags * tags)254 mvusb_init(struct mvusb_softc *sc, enum marvell_tags *tags)
255 {
256           uint32_t reg;
257           int opr_offs;
258 
259           /* Clear Interrupt Cause and Mask registers */
260           bus_space_write_4(sc->sc_iot, sc->sc_ioh, MARVELL_USB_BICR, 0);
261           bus_space_write_4(sc->sc_iot, sc->sc_ioh, MARVELL_USB_BIMR, 0);
262 
263           opr_offs = bus_space_read_1(sc->sc_iot, sc->sc_ioh,
264               MARVELL_USB_EHCI_BASE + EHCI_CAPLENGTH);
265 
266           /* Reset controller */
267           reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
268               MARVELL_USB_EHCI_BASE + opr_offs + EHCI_USBCMD);
269           reg |= EHCI_CMD_HCRESET;
270           bus_space_write_4(sc->sc_iot, sc->sc_ioh,
271               MARVELL_USB_EHCI_BASE + opr_offs + EHCI_USBCMD, reg);
272           while (bus_space_read_4(sc->sc_iot, sc->sc_ioh,
273               MARVELL_USB_EHCI_BASE + opr_offs + EHCI_USBCMD) & EHCI_CMD_HCRESET);
274 
275           if (!((sc->sc_model == MARVELL_ORION_1_88F5181 &&
276                                                   (sc->sc_rev <= 3 || sc->sc_rev == 8)) ||
277               (sc->sc_model == MARVELL_ORION_1_88F5182 && sc->sc_rev <= 1) ||
278               (sc->sc_model == MARVELL_ORION_2_88F5281 && sc->sc_rev <= 1))) {
279                     reg =
280                         bus_space_read_4(sc->sc_iot, sc->sc_ioh, MARVELL_USB_IPGR);
281                     /*
282                      * Change bits[14:8] - IPG for non Start of Frame Packets
283                      * from 0x9(default) to 0xc
284                      */
285                     reg &= ~(0x7f << 8);
286                     reg |= (0x0c << 8);
287                     bus_space_write_4(sc->sc_iot, sc->sc_ioh, MARVELL_USB_IPGR,
288                         reg);
289           }
290           if (!(sc->sc_model == MARVELL_ARMADAXP_MV78460)) {
291                     reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh, MARVELL_USB_PCR);
292                     reg &= ~MARVELL_USB_PCR_BGVSEL_MASK;
293                     reg |= MARVELL_USB_PCR_BGVSEL_CONNECT_ANAGRP;
294                     bus_space_write_4(sc->sc_iot, sc->sc_ioh, MARVELL_USB_PCR, reg);
295 
296                     reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
297                         MARVELL_USB_PTCR);
298                     if (sc->sc_model == MARVELL_ORION_1_88F5181 && sc->sc_rev <= 1)
299                               /* For OrionI A1/A0 rev: bit[21]=0 (TXDATA_BLOCK_EN=0) */
300                               reg &= ~(1 << 21);
301                     else
302                               reg |= (1 << 21);
303                     /* bit[13]=1, (REG_EXT_RCAL_EN=1) */
304                     reg |= (1 << 13);
305                     /* bits[6:3]=8 (IMP_CAL=8) */
306                     reg &= ~(0xf << 3);
307                     reg |= (8 << 3);
308                     bus_space_write_4(sc->sc_iot, sc->sc_ioh, MARVELL_USB_PTCR,
309                         reg);
310 
311                     reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
312                         MARVELL_USB_PRCR);
313                     /* bits[8:9] - (DISCON_THRESHOLD ) */
314                     /*
315                      * Orion1-A0/A1/B0=11, Orion2-A0=10,
316                      * Orion1-B1 and Orion2-B0 later=00
317                      */
318                     reg &= ~(3 << 8);
319                     if (sc->sc_model == MARVELL_ORION_1_88F5181 && sc->sc_rev <= 2)
320                               reg |= (3 << 8);
321                     else if (sc->sc_model == MARVELL_ORION_2_88F5281 &&
322                         sc->sc_rev == 0)
323                               reg |= (2 << 8);
324                     /* bit[21]=0 (CDR_FASTLOCK_EN=0) */
325                     reg &= ~(1 << 21);
326                     /* bits[27:26]=0 (EDGE_DET_SEL=0) */
327                     reg &= ~(3 << 26);
328                     /* bits[31:30]=3 (RXDATA_BLOCK_LENGTH=3) */
329                     reg |= (3 << 30);
330                     /* bits[7:4]=1 (SQ_THRESH=1) */
331                     reg &= ~(0xf << 4);
332                     reg |= (1 << 4);
333                     bus_space_write_4(sc->sc_iot, sc->sc_ioh, MARVELL_USB_PRCR,
334                         reg);
335 
336                     reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
337                         MARVELL_USB_PIVREFFCR);
338                     /* bits[1:0]=2 (PLLVDD12=2)*/
339                     reg &= ~(3 << 0);
340                     reg |= (2 << 0);
341                     /* bits[5:4]=3 (RXVDD=3) */
342                     reg &= ~(3 << 4);
343                     reg |= (3 << 4);
344                     /* bit[19] (Reserved) */
345                     reg &= ~(1 << 19);
346                     bus_space_write_4(sc->sc_iot, sc->sc_ioh,
347                         MARVELL_USB_PIVREFFCR, reg);
348 
349                     reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
350                         MARVELL_USB_PTGCR);
351                     /* bit[15]=0 (REG_FIFO_SQ_RST=0) */
352                     reg &= ~(1 << 15);
353                     bus_space_write_4(sc->sc_iot, sc->sc_ioh, MARVELL_USB_PTGCR,
354                         reg);
355           }
356 
357           mvusb_wininit(sc, tags);
358 }
359 
360 static void
mvusb_wininit(struct mvusb_softc * sc,enum marvell_tags * tags)361 mvusb_wininit(struct mvusb_softc *sc, enum marvell_tags *tags)
362 {
363           device_t pdev = device_parent(sc->sc.sc_dev);
364           uint64_t base;
365           uint32_t size;
366           int window, target, attr, rv, i;
367 
368           for (window = 0, i = 0;
369               tags[i] != MARVELL_TAG_UNDEFINED && window < MARVELL_USB_NWINDOW;
370               i++) {
371                     rv = marvell_winparams_by_tag(pdev, tags[i],
372                         &target, &attr, &base, &size);
373                     if (rv != 0 || size == 0)
374                               continue;
375                     if (base > 0xffffffffULL) {
376                               aprint_error_dev(sc->sc.sc_dev,
377                                   "tag %d address 0x%llx not support\n",
378                                   tags[i], base);
379                               continue;
380                     }
381 
382                     bus_space_write_4(sc->sc_iot, sc->sc_ioh,
383                         MARVELL_USB_WCR(window),
384                         MARVELL_USB_WCR_WINEN |
385                         MARVELL_USB_WCR_TARGET(target) |
386                         MARVELL_USB_WCR_ATTR(attr) |
387                         MARVELL_USB_WCR_SIZE(size));
388                     bus_space_write_4(sc->sc_iot, sc->sc_ioh,
389                         MARVELL_USB_WBR(window), MARVELL_USB_WBR_BASE(base));
390                     window++;
391           }
392           for (; window < MARVELL_USB_NWINDOW; window++)
393                     bus_space_write_4(sc->sc_iot, sc->sc_ioh,
394                         MARVELL_USB_WCR(window), 0);
395 }
396 
397 static void
mvusb_vendor_init(struct ehci_softc * sc)398 mvusb_vendor_init(struct ehci_softc *sc)
399 {
400           uint32_t mode;
401 
402           /* put TDI/ARC silicon into EHCI mode */
403           mode = EOREAD4(sc, MARVELL_USB_EHCI_USBMODE);
404           mode &= ~MARVELL_USB_EHCI_MODE_HDMASK;  /* Host/Device Mask */
405           mode |= MARVELL_USB_EHCI_MODE_HOST;
406           mode |= MARVELL_USB_EHCI_MODE_STRMDIS;
407           EOWRITE4(sc, MARVELL_USB_EHCI_USBMODE, mode);
408 }
409 
410 static int
mvusb_vendor_port_status(struct ehci_softc * sc,uint32_t v,int i)411 mvusb_vendor_port_status(struct ehci_softc *sc, uint32_t v, int i)
412 {
413 
414           i &= ~UPS_HIGH_SPEED;
415           if (v & EHCI_PS_CS) {
416                     switch (v & MARVELL_USB_EHCI_PS_PSPD) {
417                     case MARVELL_USB_EHCI_PS_PSPD_FS:
418                               break;
419                     case MARVELL_USB_EHCI_PS_PSPD_LS:
420                               i |= UPS_LOW_SPEED;
421                               break;
422                     case MARVELL_USB_EHCI_PS_PSPD_HS:
423                     default:
424                               i |= UPS_HIGH_SPEED;
425                     }
426           }
427 
428           return i;
429 }
430