Module Name: src Committed By: kiyohara Date: Sat Oct 2 05:53:37 UTC 2010
Modified Files: src/sys/dev/marvell: files.discovery Added Files: src/sys/dev/marvell: ehci_mv.c Log Message: Add Marvell EHCI Controller wrapper. However, because this driver has some problems now, it will not work the way things are going. To generate a diff of this commit: cvs rdiff -u -r0 -r1.1 src/sys/dev/marvell/ehci_mv.c cvs rdiff -u -r1.17 -r1.18 src/sys/dev/marvell/files.discovery Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/dev/marvell/files.discovery diff -u src/sys/dev/marvell/files.discovery:1.17 src/sys/dev/marvell/files.discovery:1.18 --- src/sys/dev/marvell/files.discovery:1.17 Thu Sep 23 12:36:01 2010 +++ src/sys/dev/marvell/files.discovery Sat Oct 2 05:53:37 2010 @@ -1,4 +1,4 @@ -# $NetBSD: files.discovery,v 1.17 2010/09/23 12:36:01 kiyohara Exp $ +# $NetBSD: files.discovery,v 1.18 2010/10/02 05:53:37 kiyohara Exp $ # # Config file and device description for machine-independent support for # the Marvell (formerly Galileo Technology) Discovery system controllers. @@ -68,8 +68,8 @@ file dev/marvell/if_mvgbe.c mvgbec | mvgbe # USB 2.0 Interface -#attach ehci at gt with mvusb_gt -#file dev/marvell/ehci_mv.c mvusb_gt | mvusb_mbus +attach ehci at gt with mvusb_gt +file dev/marvell/ehci_mv.c mvusb_gt | mvusb_mbus # Cryptographic Engines and Security Accelerator #device mvcesa: opencrypto Added files: Index: src/sys/dev/marvell/ehci_mv.c diff -u /dev/null src/sys/dev/marvell/ehci_mv.c:1.1 --- /dev/null Sat Oct 2 05:53:37 2010 +++ src/sys/dev/marvell/ehci_mv.c Sat Oct 2 05:53:37 2010 @@ -0,0 +1,374 @@ +/* $NetBSD: ehci_mv.c,v 1.1 2010/10/02 05:53:37 kiyohara Exp $ */ +/* + * Copyright (c) 2008 KIYOHARA Takashi + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__KERNEL_RCSID(0, "$NetBSD: ehci_mv.c,v 1.1 2010/10/02 05:53:37 kiyohara Exp $"); + +#include <sys/param.h> +#include <sys/bus.h> +#include <sys/device.h> +#include <sys/errno.h> +#include <sys/systm.h> + +#include <dev/marvell/marvellreg.h> +#include <dev/marvell/marvellvar.h> + +#include <dev/usb/usb.h> +#include <dev/usb/usbdi.h> +#include <dev/usb/usbdivar.h> +#include <dev/usb/usb_mem.h> + +#include <dev/usb/ehcireg.h> +#include <dev/usb/ehcivar.h> + +#include "locators.h" + +#ifdef EHCI_DEBUG +#define DPRINTF(x) if (ehcidebug) printf x +extern int ehcidebug; +#else +#define DPRINTF(x) +#endif + + +#define MARVELL_USB_SIZE 0x2000 + +#define MARVELL_USB_NWINDOW 4 + +#define MARVELL_USB_ID 0x000 +#define MARVELL_USB_HWGENERAL 0x004 +#define MARVELL_USB_HWHOST 0x008 +#define MARVELL_USB_HWDEVICE 0x00c +#define MARVELL_USB_HWTXBUF 0x010 +#define MARVELL_USB_HWRXBUF 0x014 +#define MARVELL_USB_HWTTTXBUF 0x018 +#define MARVELL_USB_HWTTRXBUF 0x01c + +/* ehci generic registers */ +#define MARVELL_USB_EHCI_BASE 0x100 +#define MARVELL_USB_EHCI_SIZE 0x1000 + +#define MARVELL_USB_DCIVERSION 0x120 +#define MARVELL_USB_DCCPARAMS 0x124 +#define MARVELL_USB_TTCTRL 0x15c +#define MARVELL_USB_BURSTSIZE 0x160 +#define MARVELL_USB_TXFILLTUNING 0x164 +#define MARVELL_USB_TXTTFILLTUNING 0x168 +#define MARVELL_USB_OTGSC 0x1a4 +#define MARVELL_USB_USBMODE 0x1a8 +#define MARVELL_USB_USBMODE_MASK (3 << 0) +#define MARVELL_USB_USBMODE_HOST (3 << 0) +#define MARVELL_USB_USBMODE_DEVICE (2 << 0) +#define MARVELL_USB_USBMODE_STREAMDISABLE (1 << 4) +#define MARVELL_USB_ENPDTSETUPSTAT 0x1ac +#define MARVELL_USB_ENDPTPRIME 0x1b0 +#define MARVELL_USB_ENDPTFLUSH 0x1b4 +#define MARVELL_USB_ENDPTSTATS 0x1b8 +#define MARVELL_USB_ENDPTCOMPLETE 0x1bc +#define MARVELL_USB_ENDPTCTRL0 0x1c0 +#define MARVELL_USB_ENDPTCTRL1 0x1c1 +#define MARVELL_USB_ENDPTCTRL2 0x1c2 +#define MARVELL_USB_ENDPTCTRL3 0x1c3 +/* Bridge Control And Status Registers */ +#define MARVELL_USB_BCR 0x300 /* Control */ +/* Bridge Interrupt and Error Registers */ +#define MARVELL_USB_BICR 0x310 /* Interrupt Cause */ +#define MARVELL_USB_BIMR 0x314 /* Interrupt Mask */ +#define MARVELL_USB_BIR_ADDRDECERR (1 << 0) +#define MARVELL_USB_BEAR 0x31c /* Error Address */ +/* Bridge Address Decoding Registers */ +#define MARVELL_USB_WCR(n) (0x320 + (n) * 0x10) /* WinN Control */ +#define MARVELL_USB_WCR_WINEN (1 << 0) +#define MARVELL_USB_WCR_TARGET(t) (((t) & 0xf) << 4) +#define MARVELL_USB_WCR_ATTR(a) (((a) & 0xff) << 8) +#define MARVELL_USB_WCR_SIZE(s) (((s) - 1) & 0xffff0000) +#define MARVELL_USB_WBR(n) (0x324 + (n) * 0x10) /* WinN Base */ +#define MARVELL_USB_WBR_BASE(b) ((b) & 0xffff0000) +/* IPG Metal Fix Register ??? */ +#define MARVELL_USB_IPGR 0x360 +/* USB 2.0 PHY Register Map */ +#define MARVELL_USB_PCR 0x400 /* Power Control */ +#define MARVELL_USB_PCR_PU (1 << 0) /* Power Up */ +#define MARVELL_USB_PCR_PUPLL (1 << 1) /*Power Up PLL*/ +#define MARVELL_USB_PCR_SUSPENDM (1 << 2) +#define MARVELL_USB_PCR_VBUSPWRFAULT (1 << 3) +#define MARVELL_USB_PCR_PWRCTLWAKEUP (1 << 4) +#define MARVELL_USB_PCR_PUREF (1 << 5) +#define MARVELL_USB_PCR_BGVSEL_MASK (3 << 6) +#define MARVELL_USB_PCR_BGVSEL_CONNECT_ANAGRP (1 << 6) +#define MARVELL_USB_PCR_REGARCDPDMMODE (1 << 8) +#define MARVELL_USB_PCR_REGDPPULLDOWN (1 << 9) +#define MARVELL_USB_PCR_REGDMPULLDOWN (1 << 10) +#define MARVELL_USB_PCR_UTMISESSION (1 << 23) +#define MARVELL_USB_PCR_UTMIVBUSVALID (1 << 24) +#define MARVELL_USB_PCR_UTMIAVALID (1 << 25) +#define MARVELL_USB_PCR_UTMIBVALID (1 << 26) +#define MARVELL_USB_PCR_TXBITSTUFF (1 << 27) +/* USB PHY Tx Control Register */ +#define MARVELL_USB_PTCR 0x420 +/* USB PHY Rx Control Register */ +#define MARVELL_USB_PRCR 0x430 +/* USB PHY IVREFF Control Register */ +#define MARVELL_USB_PIVREFFCR 0x440 +/* USB PHY Test Group Control Register */ +#define MARVELL_USB_PTGCR 0x450 + + +struct mvusb_softc { + ehci_softc_t sc; + + int sc_model; + int sc_rev; + + bus_space_tag_t sc_iot; + bus_space_handle_t sc_ioh; +}; + +static int mvusb_match(device_t, cfdata_t, void *); +static void mvusb_attach(device_t, device_t, void *); + +static void mvusb_init(struct mvusb_softc *); +static void mvusb_wininit(struct mvusb_softc *); + +CFATTACH_DECL2_NEW(mvusb_gt, sizeof(struct mvusb_softc), + mvusb_match, mvusb_attach, NULL, ehci_activate, NULL, ehci_childdet); +CFATTACH_DECL2_NEW(mvusb_mbus, sizeof(struct mvusb_softc), + mvusb_match, mvusb_attach, NULL, ehci_activate, NULL, ehci_childdet); + + +/* ARGSUSED */ +static int +mvusb_match(device_t parent, cfdata_t match, void *aux) +{ + struct marvell_attach_args *mva = aux; + + if (strcmp(mva->mva_name, match->cf_name) != 0) + return 0; + if (mva->mva_offset == MVA_OFFSET_DEFAULT || + mva->mva_irq == MVA_IRQ_DEFAULT) + return 0; + + mva->mva_size = MARVELL_USB_SIZE; + return 1; +} + +/* ARGSUSED */ +static void +mvusb_attach(device_t parent, device_t self, void *aux) +{ + struct mvusb_softc *sc = device_private(self); + struct marvell_attach_args *mva = aux; + usbd_status r; + + aprint_normal(": Marvell USB 2.0 Interface\n"); + aprint_naive("\n"); + + sc->sc.sc_dev = self; + sc->sc.sc_bus.hci_private = sc; + + sc->sc_model = mva->mva_model; + sc->sc_rev = mva->mva_revision; + sc->sc_iot = mva->mva_iot; + + /* Map I/O registers for marvell usb */ + if (bus_space_subregion(mva->mva_iot, mva->mva_ioh, mva->mva_offset, + mva->mva_size, &sc->sc_ioh)) { + aprint_error_dev(self, "can't map registers\n"); + return; + } + mvusb_init(sc); + + /* Map I/O registers for ehci */ + sc->sc.sc_size = MARVELL_USB_EHCI_SIZE; + if (bus_space_subregion(sc->sc_iot, sc->sc_ioh, MARVELL_USB_EHCI_BASE, + sc->sc.sc_size, &sc->sc.ioh)) { + aprint_error_dev(self, "can't subregion registers\n"); + return; + } + sc->sc.iot = sc->sc_iot; + sc->sc.sc_bus.dmatag = mva->mva_dmat; + + /* Disable interrupts, so we don't get any spurious ones. */ + sc->sc.sc_offs = EREAD1(&sc->sc, EHCI_CAPLENGTH); + DPRINTF(("%s: offs=%d\n", device_xname(self), sc->sc.sc_offs)); + EOWRITE2(&sc->sc, EHCI_USBINTR, 0); + + marvell_intr_establish(mva->mva_irq, IPL_USB, ehci_intr, sc); + + sc->sc.sc_bus.usbrev = USBREV_2_0; + /* Figure out vendor for root hub descriptor. */ + sc->sc.sc_id_vendor = 0x0000; /* XXXXX */ + strcpy(sc->sc.sc_vendor, "Marvell"); + + r = ehci_init(&sc->sc); + if (r != USBD_NORMAL_COMPLETION) { + aprint_error_dev(self, "init failed, error=%d\n", r); + return; + } + + /* Attach usb device. */ + sc->sc.sc_child = config_found(self, &sc->sc.sc_bus, usbctlprint); +} + +static void +mvusb_init(struct mvusb_softc *sc) +{ + uint32_t reg; + int opr_offs; + + /* Clear Interrupt Cause and Mask registers */ + bus_space_write_4(sc->sc_iot, sc->sc_ioh, MARVELL_USB_BICR, 0); + bus_space_write_4(sc->sc_iot, sc->sc_ioh, MARVELL_USB_BIMR, 0); + + opr_offs = bus_space_read_1(sc->sc_iot, sc->sc_ioh, + MARVELL_USB_EHCI_BASE + EHCI_CAPLENGTH); + + /* Reset controller */ + reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh, + MARVELL_USB_EHCI_BASE + opr_offs + EHCI_USBCMD); + reg |= EHCI_CMD_HCRESET; + bus_space_write_4(sc->sc_iot, sc->sc_ioh, + MARVELL_USB_EHCI_BASE + opr_offs + EHCI_USBCMD, reg); + while (bus_space_read_4(sc->sc_iot, sc->sc_ioh, + MARVELL_USB_EHCI_BASE + opr_offs + EHCI_USBCMD) & EHCI_CMD_HCRESET); + + if (!((sc->sc_model == MARVELL_ORION_1_88F5181 && + (sc->sc_rev <= 3 || sc->sc_rev == 8)) || + (sc->sc_model == MARVELL_ORION_1_88F5182 && sc->sc_rev <= 1) || + (sc->sc_model == MARVELL_ORION_2_88F5281 && sc->sc_rev <= 1))) { + reg = + bus_space_read_4(sc->sc_iot, sc->sc_ioh, MARVELL_USB_IPGR); + /* + * Change bits[14:8] - IPG for non Start of Frame Packets + * from 0x9(default) to 0xc + */ + reg &= ~(0x7f << 8); + reg |= (0x0c << 8); + bus_space_write_4(sc->sc_iot, sc->sc_ioh, MARVELL_USB_IPGR, + reg); + } + + reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh, MARVELL_USB_PCR); + reg &= ~MARVELL_USB_PCR_BGVSEL_MASK; + reg |= MARVELL_USB_PCR_BGVSEL_CONNECT_ANAGRP; + bus_space_write_4(sc->sc_iot, sc->sc_ioh, MARVELL_USB_PCR, reg); + + reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh, MARVELL_USB_PTCR); + if (sc->sc_model == MARVELL_ORION_1_88F5181 && sc->sc_rev <= 1) + /* For OrionI A1/A0 rev: bit[21]=0 (TXDATA_BLOCK_EN=0) */ + reg &= ~(1 << 21); + else + reg |= (1 << 21); + /* bit[13]=1, (REG_EXT_RCAL_EN=1) */ + reg |= (1 << 13); + /* bits[6:3]=8 (IMP_CAL=8) */ + reg &= ~(0xf << 3); + reg |= (8 << 3); + bus_space_write_4(sc->sc_iot, sc->sc_ioh, MARVELL_USB_PTCR, reg); + + reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh, MARVELL_USB_PRCR); + /* bits[8:9] - (DISCON_THRESHOLD ) */ + /* Orion1-A0/A1/B0=11, Orion2-A0=10, Orion1-B1 and Orion2-B0 later=00 */ + reg &= ~(3 << 8); + if (sc->sc_model == MARVELL_ORION_1_88F5181 && sc->sc_rev <= 2) + reg |= (3 << 8); + else if (sc->sc_model == MARVELL_ORION_2_88F5281 && sc->sc_rev == 0) + reg |= (2 << 8); + /* bit[21]=0 (CDR_FASTLOCK_EN=0) */ + reg &= ~(1 << 21); + /* bits[27:26]=0 (EDGE_DET_SEL=0) */ + reg &= ~(3 << 26); + /* bits[31:30]=3 (RXDATA_BLOCK_LENGHT=3) */ + reg |= (3 << 30); + /* bits[7:4]=1 (SQ_THRESH=1) */ + reg &= ~(0xf << 4); + reg |= (1 << 4); + bus_space_write_4(sc->sc_iot, sc->sc_ioh, MARVELL_USB_PRCR, reg); + + reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh, MARVELL_USB_PIVREFFCR); + /* bits[1:0]=2 (PLLVDD12=2)*/ + reg &= ~(3 << 0); + reg |= (2 << 0); + /* bits[5:4]=3 (RXVDD=3) */ + reg &= ~(3 << 4); + reg |= (3 << 4); + /* bit[19] (Reserved) */ + reg &= ~(1 << 19); + bus_space_write_4(sc->sc_iot, sc->sc_ioh, MARVELL_USB_PIVREFFCR, reg); + + reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh, MARVELL_USB_PTGCR); + /* bit[15]=0 (REG_FIFO_SQ_RST=0) */ + reg &= ~(1 << 15); + bus_space_write_4(sc->sc_iot, sc->sc_ioh, MARVELL_USB_PTGCR, reg); + + mvusb_wininit(sc); +} + +static void +mvusb_wininit(struct mvusb_softc *sc) +{ + device_t pdev = device_parent(sc->sc.sc_dev); + uint64_t base; + uint32_t size; + int window, target, attr, rv, i; + static int tags[] = { + MARVELL_TAG_SDRAM_CS0, + MARVELL_TAG_SDRAM_CS1, + MARVELL_TAG_SDRAM_CS2, + MARVELL_TAG_SDRAM_CS3, + + MARVELL_TAG_UNDEFINED, + }; + + for (window = 0, i = 0; + tags[i] != MARVELL_TAG_UNDEFINED && window < MARVELL_USB_NWINDOW; + i++) { + rv = marvell_winparams_by_tag(pdev, tags[i], + &target, &attr, &base, &size); + if (rv != 0 || size == 0) + continue; + if (base > 0xffffffffULL) { + aprint_error_dev(sc->sc.sc_dev, + "tag %d address 0x%llx not support\n", + tags[i], base); + continue; + } + + bus_space_write_4(sc->sc_iot, sc->sc_ioh, + MARVELL_USB_WCR(window), + MARVELL_USB_WCR_WINEN | + MARVELL_USB_WCR_TARGET(target) | + MARVELL_USB_WCR_ATTR(attr) | + MARVELL_USB_WCR_SIZE(size)); + bus_space_write_4(sc->sc_iot, sc->sc_ioh, + MARVELL_USB_WBR(window), MARVELL_USB_WBR_BASE(base)); + window++; + } + for (; window < MARVELL_USB_NWINDOW; window++) + bus_space_write_4(sc->sc_iot, sc->sc_ioh, + MARVELL_USB_WCR(window), 0); +}