epohci.c revision 1.8
11.8Sskrll/* $NetBSD: epohci.c,v 1.8 2016/04/23 10:15:28 skrll Exp $ */ 21.1Sjoff 31.1Sjoff/*- 41.1Sjoff * Copyright (c) 2004 Jesse Off 51.1Sjoff * All rights reserved. 61.1Sjoff * 71.1Sjoff * Redistribution and use in source and binary forms, with or without 81.1Sjoff * modification, are permitted provided that the following conditions 91.1Sjoff * are met: 101.1Sjoff * 1. Redistributions of source code must retain the above copyright 111.1Sjoff * notice, this list of conditions and the following disclaimer. 121.1Sjoff * 2. Redistributions in binary form must reproduce the above copyright 131.1Sjoff * notice, this list of conditions and the following disclaimer in the 141.1Sjoff * documentation and/or other materials provided with the distribution. 151.1Sjoff * 161.1Sjoff * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 171.1Sjoff * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 181.1Sjoff * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 191.1Sjoff * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 201.1Sjoff * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 211.1Sjoff * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 221.1Sjoff * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 231.1Sjoff * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 241.1Sjoff * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 251.1Sjoff * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 261.1Sjoff * SUCH DAMAGE. 271.1Sjoff */ 281.1Sjoff 291.1Sjoff/* 301.1Sjoff * USB Open Host Controller driver. 311.1Sjoff * 321.1Sjoff * OHCI spec: ftp://ftp.compaq.com/pub/supportinformation/papers/hcir1_0a.exe 331.1Sjoff * USB spec: http://www.usb.org/developers/data/usb11.pdf 341.1Sjoff */ 351.1Sjoff 361.1Sjoff#include <sys/cdefs.h> 371.8Sskrll__KERNEL_RCSID(0, "$NetBSD: epohci.c,v 1.8 2016/04/23 10:15:28 skrll Exp $"); 381.1Sjoff 391.1Sjoff#include <sys/param.h> 401.1Sjoff#include <sys/systm.h> 411.1Sjoff#include <sys/kernel.h> 421.1Sjoff#include <sys/device.h> 431.1Sjoff#include <sys/proc.h> 441.1Sjoff#include <sys/queue.h> 451.1Sjoff 461.1Sjoff/* busdma */ 471.1Sjoff#include <sys/mbuf.h> 481.1Sjoff#include <uvm/uvm_extern.h> 491.1Sjoff 501.5Sdyoung#include <sys/bus.h> 511.1Sjoff 521.1Sjoff#include <dev/usb/usb.h> 531.1Sjoff#include <dev/usb/usbdi.h> 541.1Sjoff#include <dev/usb/usbdivar.h> 551.1Sjoff#include <dev/usb/usb_mem.h> 561.1Sjoff 571.1Sjoff#include <dev/usb/ohcireg.h> 581.1Sjoff#include <dev/usb/ohcivar.h> 591.1Sjoff 601.1Sjoff#include <arm/ep93xx/ep93xxreg.h> 611.1Sjoff#include <arm/ep93xx/ep93xxvar.h> 621.1Sjoff#include <arm/ep93xx/epsocvar.h> 631.1Sjoff 641.6Schsint epohci_match(device_t, cfdata_t, void *); 651.6Schsvoid epohci_attach(device_t, device_t, void *); 661.6Schsvoid epohci_callback(device_t); 671.1Sjoff 681.1Sjoffstruct epohci_softc { 691.1Sjoff struct ohci_softc sc; 701.1Sjoff void *sc_ih; 711.1Sjoff int sc_intr; 721.1Sjoff}; 731.1Sjoff 741.3SdrochnerCFATTACH_DECL_NEW(epohci, sizeof(struct epohci_softc), 751.1Sjoff epohci_match, epohci_attach, NULL, NULL); 761.1Sjoff 771.1Sjoffint 781.6Schsepohci_match(device_t parent, cfdata_t match, void *aux) 791.1Sjoff{ 801.1Sjoff /* EP93xx builtin OHCI module */ 811.1Sjoff 821.8Sskrll return 1; 831.1Sjoff} 841.1Sjoff 851.1Sjoffvoid 861.6Schsepohci_attach(device_t parent, device_t self, void *aux) 871.1Sjoff{ 881.3Sdrochner struct epohci_softc *sc = device_private(self); 891.1Sjoff struct epsoc_attach_args *sa = aux; 901.7Sskrll uint32_t i; 911.1Sjoff bus_space_handle_t syscon_ioh; 921.1Sjoff 931.3Sdrochner sc->sc.sc_dev = self; 941.8Sskrll sc->sc.sc_bus.ub_hcpriv = sc; 951.3Sdrochner 961.1Sjoff sc->sc.iot = sa->sa_iot; 971.8Sskrll sc->sc.sc_bus.ub_dmatag = sa->sa_dmat; 981.1Sjoff sc->sc_intr = sa->sa_intr; 991.1Sjoff 1001.1Sjoff /* Map I/O space */ 1011.8Sskrll if (bus_space_map(sc->sc.iot, sa->sa_addr, sa->sa_size, 1021.1Sjoff 0, &sc->sc.ioh)) { 1031.1Sjoff printf(": cannot map mem space\n"); 1041.1Sjoff return; 1051.1Sjoff } 1061.1Sjoff 1071.1Sjoff /* Enable hclk clock gating to the USB block. */ 1081.1Sjoff 1091.1Sjoff bus_space_map(sc->sc.iot, EP93XX_APB_HWBASE + EP93XX_APB_SYSCON, 1101.1Sjoff EP93XX_APB_SYSCON_SIZE, 0, &syscon_ioh); 1111.1Sjoff i = bus_space_read_4(sc->sc.iot, syscon_ioh, EP93XX_SYSCON_PwrCnt); 1121.1Sjoff i |= 0x10000000; 1131.1Sjoff bus_space_write_4(sc->sc.iot, syscon_ioh, EP93XX_SYSCON_PwrCnt, i); 1141.1Sjoff 1151.1Sjoff /* 1161.1Sjoff * Not sure if I understand the datasheet here, but we must wait a 1171.1Sjoff * few instructions and also make certain PLL2 is stable before 1181.1Sjoff * continuing. Hopefully, the check for PLL2 is enough, as the 1191.1Sjoff * datasheet is elusive to actually how many insns we need. 1201.1Sjoff */ 1211.1Sjoff 1221.1Sjoff do { 1231.8Sskrll i = bus_space_read_4(sc->sc.iot, syscon_ioh, 1241.1Sjoff EP93XX_SYSCON_PwrSts); 1251.1Sjoff } while ((i & 0x100) == 0); 1261.1Sjoff bus_space_unmap(sc->sc.iot, syscon_ioh, EP93XX_APB_SYSCON_SIZE); 1271.1Sjoff 1281.1Sjoff printf("\n"); 1291.1Sjoff 1301.1Sjoff /* Defer the rest until later */ 1311.1Sjoff config_defer(self, epohci_callback); 1321.1Sjoff} 1331.1Sjoff 1341.1Sjoffvoid 1351.6Schsepohci_callback(device_t self) 1361.1Sjoff{ 1371.3Sdrochner struct epohci_softc *sc = device_private(self); 1381.1Sjoff 1391.1Sjoff /* Disable interrupts, so we don't get any spurious ones. */ 1401.1Sjoff bus_space_write_4(sc->sc.iot, sc->sc.ioh, OHCI_INTERRUPT_DISABLE, 1411.1Sjoff OHCI_ALL_INTRS); 1421.1Sjoff 1431.1Sjoff strlcpy(sc->sc.sc_vendor, "Cirrus Logic", sizeof sc->sc.sc_vendor); 1441.1Sjoff 1451.8Sskrll sc->sc_ih = ep93xx_intr_establish(sc->sc_intr, IPL_USB, 1461.1Sjoff ohci_intr, sc); 1471.8Sskrll int err = ohci_init(&sc->sc); 1481.1Sjoff 1491.8Sskrll if (err) { 1501.8Sskrll printf("%s: init failed, error=%d\n", device_xname(self), err); 1511.1Sjoff 1521.1Sjoff ep93xx_intr_disestablish(sc->sc_ih); 1531.1Sjoff return; 1541.1Sjoff } 1551.1Sjoff 1561.1Sjoff /* Attach usb device. */ 1571.3Sdrochner sc->sc.sc_child = config_found(self, &sc->sc.sc_bus, usbctlprint); 1581.1Sjoff 1591.1Sjoff} 160