xref: /netbsd/sys/arch/hpcarm/dev/wzero3_usb.c (revision 6550d01e)
1 /*	$NetBSD: wzero3_usb.c,v 1.1 2010/04/17 13:36:21 nonaka Exp $	*/
2 
3 /*
4  * Copyright (c) 2009 NONAKA Kimihiro <nonaka@netbsd.org>
5  * All rights reserved.
6  *
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
14  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
15  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
16  * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
17  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
19  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23  * SUCH DAMAGE.
24  */
25 
26 #include <sys/cdefs.h>
27 __KERNEL_RCSID(0, "$NetBSD: wzero3_usb.c,v 1.1 2010/04/17 13:36:21 nonaka Exp $");
28 
29 #include <sys/param.h>
30 #include <sys/device.h>
31 #include <sys/kernel.h>
32 
33 #include <arm/xscale/pxa2x0reg.h>
34 #include <arm/xscale/pxa2x0var.h>
35 #include <arm/xscale/pxa2x0_gpio.h>
36 
37 #include <machine/bus.h>
38 #include <machine/bootinfo.h>
39 #include <machine/config_hook.h>
40 #include <machine/platid.h>
41 #include <machine/platid_mask.h>
42 
43 #include <hpcarm/dev/wzero3_reg.h>
44 
45 #if defined(WZERO3USB_DEBUG)
46 #define	DPRINTF(s)	printf s
47 #else
48 #define	DPRINTF(s)
49 #endif
50 
51 struct wzero3usb_softc {
52 	device_t sc_dev;
53 
54 	bus_space_tag_t sc_iot;
55 	bus_space_handle_t sc_ioh;
56 
57 	int sc_client_pin;
58 	int sc_host_pin;
59 	int sc_host_power_pin;
60 
61 	void *sc_client_ih;
62 	void *sc_host_ih;
63 };
64 
65 static int wzero3usb_match(device_t, cfdata_t, void *);
66 static void wzero3usb_attach(device_t, device_t, void *);
67 
68 CFATTACH_DECL_NEW(wzero3usb, sizeof(struct wzero3usb_softc),
69     wzero3usb_match, wzero3usb_attach, NULL, NULL);
70 
71 static int wzero3usb_client_intr(void *);
72 static int wzero3usb_host_intr(void *);
73 static void wzero3usb_host_power(struct wzero3usb_softc *);
74 
75 static const struct wzero3usb_model {
76 	platid_mask_t *platid;
77 	int client_pin;
78 	int host_pin;
79 	int host_power_pin;
80 } wzero3usb_table[] = {
81 	/* WS003SH */
82 	{
83 		&platid_mask_MACH_SHARP_WZERO3_WS003SH,
84 		GPIO_WS003SH_USB_CLIENT_DETECT,
85 		-1,	/* None */
86 		-1,	/* None */
87 	},
88 	/* WS004SH */
89 	{
90 		&platid_mask_MACH_SHARP_WZERO3_WS004SH,
91 		GPIO_WS003SH_USB_CLIENT_DETECT,
92 		-1,	/* None */
93 		-1,	/* None */
94 	},
95 	/* WS007SH */
96 	{
97 		&platid_mask_MACH_SHARP_WZERO3_WS007SH,
98 		GPIO_WS007SH_USB_CLIENT_DETECT,
99 		GPIO_WS007SH_USB_HOST_DETECT,
100 		GPIO_WS007SH_USB_HOST_POWER,
101 	},
102 	/* WS011SH */
103 	{
104 		&platid_mask_MACH_SHARP_WZERO3_WS011SH,
105 		GPIO_WS011SH_USB_CLIENT_DETECT,
106 		GPIO_WS011SH_USB_HOST_DETECT,
107 		GPIO_WS011SH_USB_HOST_POWER,
108 	},
109 	/* XXX: WS020SH */
110 
111 	{ NULL, -1, -1, -1, }
112 };
113 
114 static const struct wzero3usb_model *
115 wzero3usb_lookup(void)
116 {
117 	const struct wzero3usb_model *model;
118 
119 	for (model = wzero3usb_table; model->platid != NULL; model++) {
120 		if (platid_match(&platid, model->platid)) {
121 			return model;
122 		}
123 	}
124 	return NULL;
125 }
126 
127 static int
128 wzero3usb_match(device_t parent, cfdata_t cf, void *aux)
129 {
130 
131 	if (strcmp(cf->cf_name, "wzero3usb") != 0)
132 		return 0;
133 	if (wzero3usb_lookup() == NULL)
134 		return 0;
135 	return 1;
136 }
137 
138 static void
139 wzero3usb_attach(device_t parent, device_t self, void *aux)
140 {
141 	struct wzero3usb_softc *sc = device_private(self);
142 	struct pxaip_attach_args *pxa = aux;
143 	const struct wzero3usb_model *model;
144 
145 	sc->sc_dev = self;
146 	sc->sc_iot = pxa->pxa_iot;
147 
148 	aprint_normal(": USB Mode detection\n");
149 
150 	model = wzero3usb_lookup();
151 	if (model == NULL) {
152 		aprint_error_dev(self, "unknown model\n");
153 		return;
154 	}
155 	sc->sc_client_pin = model->client_pin;
156 	sc->sc_host_pin = model->host_pin;
157 	sc->sc_host_power_pin = model->host_power_pin;
158 
159 	if (bus_space_map(sc->sc_iot, PXA2X0_USBDC_BASE, PXA270_USBDC_SIZE, 0,
160 				&sc->sc_ioh)) {
161 		aprint_error_dev(self, "couldn't map memory space\n");
162 		return;
163 	}
164 
165 	if (sc->sc_client_pin >= 0) {
166 		sc->sc_client_ih = pxa2x0_gpio_intr_establish(sc->sc_client_pin,
167 		    IST_EDGE_BOTH, IPL_BIO, wzero3usb_client_intr, sc);
168 	}
169 	if (sc->sc_host_pin >= 0) {
170 		sc->sc_host_ih = pxa2x0_gpio_intr_establish(sc->sc_host_pin,
171 		    IST_EDGE_BOTH, IPL_BIO, wzero3usb_host_intr, sc);
172 	}
173 
174 	/* configure port 2 for input */
175 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, USBDC_UP2OCR,
176 			USBDC_UP2OCR_HXS | USBDC_UP2OCR_HXOE |
177 			USBDC_UP2OCR_DPPDE | USBDC_UP2OCR_DMPDE);
178 
179 	wzero3usb_host_power(sc);
180 }
181 
182 static int
183 wzero3usb_host_intr(void *v)
184 {
185 	struct wzero3usb_softc *sc = (struct wzero3usb_softc *)v;
186 
187 	DPRINTF(("%s: USB host cable changed: level = %s\n",
188 	    device_xname(sc->sc_dev),
189 	    pxa2x0_gpio_get_bit(sc->sc_host_pin) ? "H" : "L"));
190 
191 	wzero3usb_host_power(sc);
192 
193 	return 1;
194 }
195 
196 static int
197 wzero3usb_client_intr(void *v)
198 {
199 	struct wzero3usb_softc *sc = (struct wzero3usb_softc *)v;
200 
201 	DPRINTF(("%s: USB client cable changed: level = %s\n",
202 	    device_xname(sc->sc_dev),
203 	    pxa2x0_gpio_get_bit(sc->sc_client_pin) ? "H" : "L"));
204 
205 	(void)sc; /*XXX*/
206 
207 	return 1;
208 }
209 
210 static void
211 wzero3usb_host_power(struct wzero3usb_softc *sc)
212 {
213 	int host_cable;
214 
215 	if (sc->sc_host_pin >= 0 && sc->sc_host_power_pin >= 0) {
216 		host_cable = pxa2x0_gpio_get_bit(sc->sc_host_pin);
217 
218 		if (!host_cable) {
219 			DPRINTF(("%s: enable USB host power\n",
220 			    device_xname(sc->sc_dev)));
221 			pxa2x0_gpio_set_bit(sc->sc_host_power_pin);
222 		} else {
223 			DPRINTF(("%s: disable USB host power\n",
224 			    device_xname(sc->sc_dev)));
225 			pxa2x0_gpio_clear_bit(sc->sc_host_power_pin);
226 		}
227 	}
228 }
229