11.9Sthorpej/*	$Id: at91ohci.c,v 1.9 2021/08/07 16:18:43 thorpej Exp $	*/
21.9Sthorpej/*	$NetBSD: at91ohci.c,v 1.9 2021/08/07 16:18:43 thorpej Exp $	*/
31.2Smatt
41.2Smatt/*-
51.2Smatt * Copyright (c) 2007 Embedtronics Oy.
61.2Smatt * All rights reserved.
71.2Smatt *
81.6Sskrll * Based on arch/arm/ep93xx/epohci.c,
91.2Smatt * Copyright (c) 2004 Jesse Off
101.2Smatt * All rights reserved.
111.2Smatt *
121.2Smatt * Redistribution and use in source and binary forms, with or without
131.2Smatt * modification, are permitted provided that the following conditions
141.2Smatt * are met:
151.2Smatt * 1. Redistributions of source code must retain the above copyright
161.2Smatt *    notice, this list of conditions and the following disclaimer.
171.2Smatt * 2. Redistributions in binary form must reproduce the above copyright
181.2Smatt *    notice, this list of conditions and the following disclaimer in the
191.2Smatt *    documentation and/or other materials provided with the distribution.
201.2Smatt *
211.2Smatt * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
221.2Smatt * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
231.2Smatt * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
241.2Smatt * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
251.2Smatt * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
261.2Smatt * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
271.2Smatt * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
281.2Smatt * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
291.2Smatt * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
301.2Smatt * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
311.2Smatt * SUCH DAMAGE.
321.2Smatt */
331.2Smatt
341.2Smatt/*
351.2Smatt * USB Open Host Controller driver.
361.2Smatt *
371.2Smatt * OHCI spec: ftp://ftp.compaq.com/pub/supportinformation/papers/hcir1_0a.exe
381.2Smatt * USB spec: http://www.usb.org/developers/data/usb11.pdf
391.2Smatt */
401.2Smatt
411.2Smatt#include <sys/cdefs.h>
421.9Sthorpej__KERNEL_RCSID(0, "$NetBSD: at91ohci.c,v 1.9 2021/08/07 16:18:43 thorpej Exp $");
431.2Smatt
441.2Smatt#include <sys/param.h>
451.2Smatt#include <sys/systm.h>
461.2Smatt#include <sys/kernel.h>
471.2Smatt#include <sys/device.h>
481.2Smatt#include <sys/proc.h>
491.2Smatt#include <sys/queue.h>
501.2Smatt
511.2Smatt/* busdma */
521.2Smatt#include <sys/mbuf.h>
531.2Smatt#include <uvm/uvm_extern.h>
541.2Smatt
551.4Sdyoung#include <sys/bus.h>
561.2Smatt
571.2Smatt#include <dev/usb/usb.h>
581.2Smatt#include <dev/usb/usbdi.h>
591.2Smatt#include <dev/usb/usbdivar.h>
601.2Smatt#include <dev/usb/usb_mem.h>
611.2Smatt
621.2Smatt#include <dev/usb/ohcireg.h>
631.2Smatt#include <dev/usb/ohcivar.h>
641.2Smatt
651.2Smatt#include <arm/at91/at91reg.h>
661.2Smatt#include <arm/at91/at91var.h>
671.2Smatt
681.2Smattint at91ohci_match(device_t, cfdata_t, void *);
691.2Smattvoid at91ohci_attach(device_t, device_t, void *);
701.2Smattvoid at91ohci_callback(device_t );
711.2Smatt
721.2Smattstruct at91ohci_softc {
731.2Smatt	struct ohci_softc sc;
741.2Smatt	void	*sc_ih;
751.2Smatt	int	sc_pid;
761.2Smatt};
771.2Smatt
781.5SaymericCFATTACH_DECL_NEW(at91ohci, sizeof(struct at91ohci_softc),
791.2Smatt    at91ohci_match, at91ohci_attach, NULL, NULL);
801.2Smatt
811.2Smattint
821.2Smattat91ohci_match(device_t parent, cfdata_t match, void *aux)
831.2Smatt{
841.2Smatt	/* AT91X builtin OHCI module */
851.2Smatt	if (strcmp(match->cf_name, "ohci") == 0 && strcmp(match->cf_atname, "at91ohci") == 0)
861.6Sskrll		return 2;
871.2Smatt	return(0);
881.2Smatt}
891.2Smatt
901.2Smattvoid
911.2Smattat91ohci_attach(device_t parent, device_t self, void *aux)
921.2Smatt{
931.5Saymeric	struct at91ohci_softc *sc = device_private(self);
941.2Smatt	struct at91bus_attach_args *sa = aux;
951.2Smatt
961.5Saymeric	sc->sc.sc_dev = self;
971.6Sskrll	sc->sc.sc_bus.ub_hcpriv = sc;
981.6Sskrll	sc->sc.sc_bus.ub_dmatag = sa->sa_dmat;
991.2Smatt	sc->sc.iot = sa->sa_iot;
1001.2Smatt	sc->sc_pid = sa->sa_pid;
1011.2Smatt
1021.2Smatt	/* Map I/O space */
1031.6Sskrll	if (bus_space_map(sc->sc.iot, sa->sa_addr, sa->sa_size,
1041.2Smatt			  0, &sc->sc.ioh)) {
1051.2Smatt		printf(": cannot map mem space\n");
1061.2Smatt		return;
1071.2Smatt	}
1081.2Smatt
1091.5Saymeric	sc->sc.sc_size = sa->sa_size;
1101.5Saymeric
1111.2Smatt	/* enable peripheral clock */
1121.2Smatt	at91_peripheral_clock(sc->sc_pid, 1);
1131.2Smatt
1141.2Smatt	printf("\n");
1151.2Smatt
1161.2Smatt        /* Defer the rest until later */
1171.2Smatt        config_defer(self, at91ohci_callback);
1181.2Smatt}
1191.2Smatt
1201.2Smattvoid
1211.3Sdslat91ohci_callback(device_t self)
1221.2Smatt{
1231.5Saymeric	struct at91ohci_softc *sc = device_private(self);
1241.2Smatt
1251.2Smatt	/* Disable interrupts, so we don't get any spurious ones. */
1261.2Smatt	bus_space_write_4(sc->sc.iot, sc->sc.ioh, OHCI_INTERRUPT_DISABLE,
1271.2Smatt			  OHCI_ALL_INTRS);
1281.2Smatt
1291.2Smatt	sc->sc_ih = at91_intr_establish(sc->sc_pid, IPL_USB, INTR_HIGH_LEVEL, ohci_intr, sc);
1301.6Sskrll	int err = ohci_init(&sc->sc);
1311.2Smatt
1321.6Sskrll	if (err) {
1331.6Sskrll		printf("%s: init failed, error=%d\n", device_xname(self), err);
1341.2Smatt
1351.2Smatt		at91_intr_disestablish(sc->sc_ih);
1361.2Smatt		return;
1371.2Smatt	}
1381.2Smatt
1391.2Smatt	/* Attach usb device. */
1401.8Sthorpej	sc->sc.sc_child = config_found(self, &sc->sc.sc_bus, usbctlprint,
1411.9Sthorpej	    CFARGS_NONE);
1421.2Smatt}
143