1/* $NetBSD: zusb.c,v 1.5 2011/06/19 16:20:09 nonaka Exp $ */ 2 3/* 4 * Copyright (c) 2008 Christopher Gilbert 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 * 3. The name of the company nor the name of the author may be used to 13 * endorse or promote products derived from this software without specific 14 * prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 20 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29#include <sys/cdefs.h> 30__KERNEL_RCSID(0, "$NetBSD: zusb.c,v 1.5 2011/06/19 16:20:09 nonaka Exp $"); 31 32#include <sys/param.h> 33#include <sys/device.h> 34#include <sys/kernel.h> 35#include <sys/bus.h> 36 37#include <arm/xscale/pxa2x0reg.h> 38#include <arm/xscale/pxa2x0var.h> 39#include <arm/xscale/pxa2x0_gpio.h> 40 41#include <machine/intr.h> 42 43#include <zaurus/zaurus/zaurus_reg.h> 44#include <zaurus/zaurus/zaurus_var.h> 45 46 47#ifdef ZUSB_DEBUG 48#define DPRINTF(s) printf s 49#else 50#define DPRINTF(s) 51#endif 52 53 54struct zusb_softc { 55 device_t sc_dev; 56 57 bus_space_tag_t sc_iot; 58 bus_space_handle_t sc_ioh; 59 60 void *sc_client_ih; 61 void *sc_host_ih; 62}; 63 64static int zusb_match(device_t, cfdata_t, void *); 65static void zusb_attach(device_t, device_t, void *); 66 67CFATTACH_DECL_NEW(zusb, sizeof(struct zusb_softc), 68 zusb_match, zusb_attach, NULL, NULL); 69 70static int zusb_client_intr(void *); 71static int zusb_host_intr(void *); 72static void zusb_test_and_enabled_host_port(struct zusb_softc *); 73 74static int 75zusb_match(device_t parent, cfdata_t cf, void *aux) 76{ 77 78 if (ZAURUS_ISC1000 || ZAURUS_ISC3000) 79 return 1; 80 return 0; 81} 82 83static void 84zusb_attach(device_t parent, device_t self, void *aux) 85{ 86 struct zusb_softc *sc = device_private(self); 87 struct pxaip_attach_args *pxa = aux; 88 89 aprint_normal(": USB Mode detection\n"); 90 aprint_naive("\n"); 91 92 sc->sc_dev = self; 93 sc->sc_iot = pxa->pxa_iot; 94 95 /* Map I/O space */ 96 if (bus_space_map(sc->sc_iot, PXA2X0_USBDC_BASE, PXA270_USBDC_SIZE, 0, 97 &sc->sc_ioh)) { 98 aprint_error_dev(sc->sc_dev, "couldn't map memory space\n"); 99 return; 100 } 101 102 pxa2x0_gpio_set_function(C3000_USB_DEVICE_PIN, GPIO_IN); 103 sc->sc_client_ih = pxa2x0_gpio_intr_establish(C3000_USB_DEVICE_PIN, 104 IST_EDGE_BOTH, IPL_BIO, zusb_client_intr, sc); 105 106 pxa2x0_gpio_set_function(C3000_USB_HOST_PIN, GPIO_IN); 107 sc->sc_host_ih = pxa2x0_gpio_intr_establish(C3000_USB_HOST_PIN, 108 IST_EDGE_BOTH, IPL_BIO, zusb_host_intr, sc); 109 110 /* configure port 2 for input */ 111 bus_space_write_4(sc->sc_iot, sc->sc_ioh, USBDC_UP2OCR, 112 USBDC_UP2OCR_HXS | USBDC_UP2OCR_HXOE | 113 USBDC_UP2OCR_DPPDE | USBDC_UP2OCR_DMPDE); 114 115 zusb_test_and_enabled_host_port(sc); 116} 117 118static int 119zusb_client_intr(void *v) 120{ 121 struct zusb_softc *sc = v; 122 123 DPRINTF(("%s: USB client cable changed\n", device_xname(sc->sc_dev))); 124 zusb_test_and_enabled_host_port(sc); 125 126 return 1; 127} 128 129static int 130zusb_host_intr(void *v) 131{ 132 struct zusb_softc *sc = v; 133 134 DPRINTF(("%s: USB host cable changed\n", device_xname(sc->sc_dev))); 135 zusb_test_and_enabled_host_port(sc); 136 137 return 1; 138} 139 140static void 141zusb_test_and_enabled_host_port(struct zusb_softc *sc) 142{ 143 int host_cable = pxa2x0_gpio_get_bit(C3000_USB_HOST_PIN); 144#ifdef ZUSB_DEBUG 145 int client_cable = pxa2x0_gpio_get_bit(C3000_USB_DEVICE_PIN); 146#endif 147 148 DPRINTF(("%s: USB cable: host %d, client %d\n", 149 device_xname(sc->sc_dev), host_cable, client_cable)); 150 151 if (!host_cable) { 152 pxa2x0_gpio_set_function(C3000_USB_HOST_POWER_PIN, 153 GPIO_OUT | GPIO_SET); 154 DPRINTF(("%s: USB host power enabled\n", 155 device_xname(sc->sc_dev))); 156 } else { 157 pxa2x0_gpio_set_function(C3000_USB_HOST_POWER_PIN, 158 GPIO_OUT | GPIO_CLR); 159 DPRINTF(("%s: USB host power disabled\n", 160 device_xname(sc->sc_dev))); 161 } 162} 163