Sat Jan 2 16:50:52 2016 UTC ()
properly initialize the EHCI
from Alexander Kabaev ( kan at freebsd.org )


(macallan)
diff -r1.3 -r1.4 src/sys/arch/mips/ingenic/ingenic_ehci.c

cvs diff -r1.3 -r1.4 src/sys/arch/mips/ingenic/ingenic_ehci.c (expand / switch to unified diff)

--- src/sys/arch/mips/ingenic/ingenic_ehci.c 2015/03/17 09:27:09 1.3
+++ src/sys/arch/mips/ingenic/ingenic_ehci.c 2016/01/02 16:50:52 1.4
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: ingenic_ehci.c,v 1.3 2015/03/17 09:27:09 macallan Exp $ */ 1/* $NetBSD: ingenic_ehci.c,v 1.4 2016/01/02 16:50:52 macallan Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2015 Michael Lorenz 4 * Copyright (c) 2015 Michael Lorenz
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
@@ -17,27 +17,27 @@ @@ -17,27 +17,27 @@
17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE. 26 * POSSIBILITY OF SUCH DAMAGE.
27 */ 27 */
28 28
29#include <sys/cdefs.h> 29#include <sys/cdefs.h>
30__KERNEL_RCSID(0, "$NetBSD: ingenic_ehci.c,v 1.3 2015/03/17 09:27:09 macallan Exp $"); 30__KERNEL_RCSID(0, "$NetBSD: ingenic_ehci.c,v 1.4 2016/01/02 16:50:52 macallan Exp $");
31 31
32#include <sys/param.h> 32#include <sys/param.h>
33#include <sys/systm.h> 33#include <sys/systm.h>
34#include <sys/device.h> 34#include <sys/device.h>
35#include <sys/mutex.h> 35#include <sys/mutex.h>
36#include <sys/bus.h> 36#include <sys/bus.h>
37#include <sys/workqueue.h> 37#include <sys/workqueue.h>
38 38
39#include <mips/ingenic/ingenic_var.h> 39#include <mips/ingenic/ingenic_var.h>
40#include <mips/ingenic/ingenic_regs.h> 40#include <mips/ingenic/ingenic_regs.h>
41 41
42#include <dev/usb/usb.h> 42#include <dev/usb/usb.h>
43#include <dev/usb/usbdi.h> 43#include <dev/usb/usbdi.h>
@@ -64,26 +64,99 @@ extern device_t ingenic_ohci; @@ -64,26 +64,99 @@ extern device_t ingenic_ohci;
64 64
65/* ARGSUSED */ 65/* ARGSUSED */
66static int 66static int
67ingenic_ehci_match(device_t parent, struct cfdata *match, void *aux) 67ingenic_ehci_match(device_t parent, struct cfdata *match, void *aux)
68{ 68{
69 struct apbus_attach_args *aa = aux; 69 struct apbus_attach_args *aa = aux;
70 70
71 if (strcmp(aa->aa_name, "ehci") != 0) 71 if (strcmp(aa->aa_name, "ehci") != 0)
72 return 0; 72 return 0;
73 73
74 return 1; 74 return 1;
75} 75}
76 76
 77static int
 78ingenic_ehci_enable(struct ehci_softc *sc)
 79{
 80 uint32_t reg;
 81
 82 /* Togle VBUS pin */
 83 gpio_set(5, 15, 0);
 84 delay(250000);
 85 gpio_set(5, 15, 1);
 86 delay(250000);
 87
 88 /* Enable OTG, should not be necessary since we use PLL clock */
 89 reg = readreg(JZ_USBPCR);
 90 reg &= ~(PCR_OTG_DISABLE);
 91 writereg(JZ_USBPCR, reg);
 92
 93 /* Select CORE as PLL reference */
 94 reg = readreg(JZ_USBPCR1);
 95 reg |= PCR_REFCLK_CORE;
 96 writereg(JZ_USBPCR1, reg);
 97
 98 /* Configure OTG PHY clock frequency */
 99 reg = readreg(JZ_USBPCR1);
 100 reg &= ~PCR_CLK_M;
 101 reg |= PCR_CLK_48;
 102 writereg(JZ_USBPCR1, reg);
 103
 104 /* Do not force port1 to suspend mode */
 105 reg = readreg(JZ_OPCR);
 106 reg |= OPCR_SPENDN1;
 107 writereg(JZ_OPCR, reg);
 108
 109 /* D- pulldown */
 110 reg = readreg(JZ_USBPCR1);
 111 reg |= PCR_DMPD1;
 112 writereg(JZ_USBPCR1, reg);
 113
 114 /* D+ pulldown */
 115 reg = readreg(JZ_USBPCR1);
 116 reg |= PCR_DPPD1;
 117 writereg(JZ_USBPCR1, reg);
 118
 119 /* 16 bit bus witdth for port 1 (and 0) */
 120 reg = readreg(JZ_USBPCR1);
 121 reg |= PCR_WORD_I_F1 | PCR_WORD_I_F0;
 122 writereg(JZ_USBPCR1, reg);
 123
 124 /* Reset USB */
 125 reg = readreg(JZ_USBPCR);
 126 reg |= PCR_POR;
 127 writereg(JZ_USBPCR, reg);
 128 delay(1);
 129 reg = readreg(JZ_USBPCR);
 130 reg &= ~(PCR_POR);
 131 writereg(JZ_USBPCR, reg);
 132
 133 /* Soft-reset USB */
 134 reg = readreg(JZ_SRBC);
 135 reg |= (1 << 14);
 136 writereg(JZ_SRBC, reg);
 137 /* 300ms */
 138 delay(300000);
 139
 140 reg = readreg(JZ_SRBC);
 141 reg &= ~(1 << 14);
 142 writereg(JZ_SRBC, reg);
 143
 144 /* 300ms */
 145 delay(300000);
 146
 147 return (0);
 148}
 149
77/* ARGSUSED */ 150/* ARGSUSED */
78static void 151static void
79ingenic_ehci_attach(device_t parent, device_t self, void *aux) 152ingenic_ehci_attach(device_t parent, device_t self, void *aux)
80{ 153{
81 struct ehci_softc *sc = device_private(self); 154 struct ehci_softc *sc = device_private(self);
82 struct apbus_attach_args *aa = aux; 155 struct apbus_attach_args *aa = aux;
83 void *ih; 156 void *ih;
84 int error, status; 157 int error, status;
85 uint32_t reg; 158 uint32_t reg;
86 159
87 sc->sc_dev = self; 160 sc->sc_dev = self;
88 161
89 sc->iot = aa->aa_bst; 162 sc->iot = aa->aa_bst;
@@ -95,61 +168,64 @@ ingenic_ehci_attach(device_t parent, dev @@ -95,61 +168,64 @@ ingenic_ehci_attach(device_t parent, dev
95 if (aa->aa_addr == 0) 168 if (aa->aa_addr == 0)
96 aa->aa_addr = JZ_EHCI_BASE; 169 aa->aa_addr = JZ_EHCI_BASE;
97 170
98 error = bus_space_map(aa->aa_bst, aa->aa_addr, 0x1000, 0, &sc->ioh); 171 error = bus_space_map(aa->aa_bst, aa->aa_addr, 0x1000, 0, &sc->ioh);
99 if (error) { 172 if (error) {
100 aprint_error_dev(self, 173 aprint_error_dev(self,
101 "can't map registers for %s: %d\n", aa->aa_name, error); 174 "can't map registers for %s: %d\n", aa->aa_name, error);
102 return; 175 return;
103 } 176 }
104 177
105 aprint_naive(": EHCI USB controller\n"); 178 aprint_naive(": EHCI USB controller\n");
106 aprint_normal(": EHCI USB controller\n"); 179 aprint_normal(": EHCI USB controller\n");
107 180
108 /* 181 ingenic_ehci_enable(sc);
109 * voodoo from the linux driver: 
110 * select utmi data bus width of controller to 16bit 
111 */ 
112 reg = bus_space_read_4(sc->iot, sc->ioh, 0xb0); 
113 reg |= 1 << 6; 
114 bus_space_write_4(sc->iot, sc->ioh, 0xb0, reg); 
115 182
116 /* Disable EHCI interrupts */ 183 /* Disable EHCI interrupts */
117 bus_space_write_4(sc->iot, sc->ioh, EHCI_USBINTR, 0); 184 bus_space_write_4(sc->iot, sc->ioh, EHCI_USBINTR, 0);
118 185
119 ih = evbmips_intr_establish(aa->aa_irq, ehci_intr, sc); 186 ih = evbmips_intr_establish(aa->aa_irq, ehci_intr, sc);
120  187
121 if (ih == NULL) { 188 if (ih == NULL) {
122 aprint_error_dev(self, "failed to establish interrupt %d\n", 189 aprint_error_dev(self, "failed to establish interrupt %d\n",
123 aa->aa_irq); 190 aa->aa_irq);
124 goto fail; 191 goto fail;
125 } 192 }
126 193
127#if NOHCI > 0 194#if NOHCI > 0
128 if (ingenic_ohci != NULL) { 195 if (ingenic_ohci != NULL) {
129 sc->sc_ncomp = 1; 196 sc->sc_ncomp = 1;
130 sc->sc_comps[0] = ingenic_ohci; 197 sc->sc_comps[0] = ingenic_ohci;
131 } else 198 } else
132 sc->sc_ncomp = 0; 199 sc->sc_ncomp = 0;
133#else 200#else
134 sc->sc_ncomp = 0; 201 sc->sc_ncomp = 0;
 202 sc->sc_npcomp = 0;
135#endif 203#endif
136 sc->sc_id_vendor = USB_VENDOR_INGENIC; 204 sc->sc_id_vendor = USB_VENDOR_INGENIC;
137 strlcpy(sc->sc_vendor, "Ingenic", sizeof(sc->sc_vendor)); 205 strlcpy(sc->sc_vendor, "Ingenic", sizeof(sc->sc_vendor));
138 206
139 status = ehci_init(sc); 207 status = ehci_init(sc);
140 if (status != USBD_NORMAL_COMPLETION) { 208 if (status != USBD_NORMAL_COMPLETION) {
141 aprint_error_dev(self, "init failed, error=%d\n", status); 209 aprint_error_dev(self, "init failed, error=%d\n", status);
142 goto fail; 210 goto fail;
143 } 211 }
144 212
 213 /*
 214 * voodoo from the linux driver:
 215 * select utmi data bus width of controller to 16bit
 216 */
 217 reg = bus_space_read_4(sc->iot, sc->ioh, 0xb0);
 218 reg |= 1 << 6;
 219 bus_space_write_4(sc->iot, sc->ioh, 0xb0, reg);
 220
145 /* Attach USB device */ 221 /* Attach USB device */
146 sc->sc_child = config_found(self, &sc->sc_bus, usbctlprint); 222 sc->sc_child = config_found(self, &sc->sc_bus, usbctlprint);
147 223
148 return; 224 return;
149 225
150fail: 226fail:
151 if (ih) { 227 if (ih) {
152 evbmips_intr_disestablish(ih); 228 evbmips_intr_disestablish(ih);
153 } 229 }
154 bus_space_unmap(sc->iot, sc->ioh, 0x1000); 230 bus_space_unmap(sc->iot, sc->ioh, 0x1000);
155} 231}