Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch/arm/allwinner motg glue (host mode) for allwinner, ...



details:   https://anonhg.NetBSD.org/src/rev/eecbad198b6b
branches:  trunk
changeset: 802417:eecbad198b6b
user:      jmcneill <jmcneill%NetBSD.org@localhost>
date:      Sat Sep 13 17:48:52 2014 +0000

description:
motg glue (host mode) for allwinner, not quite working yet

diffstat:

 sys/arch/arm/allwinner/awin_otg.c    |  252 +++++++++++++++++++++++++++++++++++
 sys/arch/arm/allwinner/awin_otgreg.h |    6 +-
 sys/arch/arm/allwinner/files.awin    |    6 +-
 3 files changed, 262 insertions(+), 2 deletions(-)

diffs (294 lines):

diff -r 3647d2784a7f -r eecbad198b6b sys/arch/arm/allwinner/awin_otg.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/arch/arm/allwinner/awin_otg.c Sat Sep 13 17:48:52 2014 +0000
@@ -0,0 +1,252 @@
+/* $NetBSD: awin_otg.c,v 1.1 2014/09/13 17:48:52 jmcneill Exp $ */
+
+/*-
+ * Copyright (c) 2014 Jared D. McNeill <jmcneill%invisible.ca@localhost>
+ * 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: awin_otg.c,v 1.1 2014/09/13 17:48:52 jmcneill Exp $");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/device.h>
+#include <sys/intr.h>
+#include <sys/systm.h>
+#include <sys/mutex.h>
+#include <sys/pool.h>
+#include <sys/kmem.h>
+
+#include <arm/allwinner/awin_reg.h>
+#include <arm/allwinner/awin_otgreg.h>
+#include <arm/allwinner/awin_var.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/motgvar.h>
+
+struct awin_otg_softc {
+       struct motg_softc sc_motg;
+       void *sc_ih;
+       struct awin_gpio_pindata sc_drv_pin;
+};
+
+#define OTG_READ1(sc, reg) \
+    bus_space_read_1((sc)->sc_motg.sc_iot, (sc)->sc_motg.sc_ioh, (reg))
+#define OTG_WRITE1(sc, reg, val) \
+    bus_space_write_1((sc)->sc_motg.sc_iot, (sc)->sc_motg.sc_ioh, (reg), (val))
+#define OTG_READ2(sc, reg) \
+    bus_space_read_2((sc)->sc_motg.sc_iot, (sc)->sc_motg.sc_ioh, (reg))
+#define OTG_WRITE2(sc, reg, val) \
+    bus_space_write_2((sc)->sc_motg.sc_iot, (sc)->sc_motg.sc_ioh, (reg), (val))
+#define OTG_READ4(sc, reg) \
+    bus_space_read_4((sc)->sc_motg.sc_iot, (sc)->sc_motg.sc_ioh, (reg))
+#define OTG_WRITE4(sc, reg, val) \
+    bus_space_write_4((sc)->sc_motg.sc_iot, (sc)->sc_motg.sc_ioh, (reg), (val))
+
+static int     awin_otg_match(device_t, cfdata_t, void *);
+static void    awin_otg_attach(device_t, device_t, void *);
+static void    awin_otg_init(struct awin_otg_softc *);
+static void    awin_otg_phy_write(struct awin_otg_softc *, u_int,
+                                  u_int, u_int);
+
+static int     awin_otg_intr(void *);
+static void    awin_otg_poll(void *);
+
+CFATTACH_DECL_NEW(awin_otg, sizeof(struct awin_otg_softc),
+       awin_otg_match, awin_otg_attach, NULL, NULL);
+
+static int
+awin_otg_match(device_t parent, cfdata_t cf, void *aux)
+{
+       struct awinio_attach_args * const aio = aux;
+       const struct awin_locators * const loc = &aio->aio_loc;
+
+       if (strcmp(cf->cf_name, loc->loc_name))
+               return 0;
+
+       return 1;
+}
+
+static void
+awin_otg_attach(device_t parent, device_t self, void *aux)
+{
+       struct awin_otg_softc *sc = device_private(self);
+       struct awinio_attach_args * const aio = aux;
+       const struct awin_locators * const loc = &aio->aio_loc;
+
+       aprint_naive("\n");
+       aprint_normal(": OTG\n");
+
+       awin_reg_set_clear(aio->aio_core_bst, aio->aio_ccm_bsh,
+           AWIN_AHB_GATING0_REG, AWIN_AHB_GATING0_USB0, 0);
+       awin_reg_set_clear(aio->aio_core_bst, aio->aio_ccm_bsh,
+           AWIN_USB_CLK_REG,
+           AWIN_USB_CLK_USBPHY_ENABLE|AWIN_USB_CLK_PHY0_ENABLE, 0);
+
+       awin_reg_set_clear(aio->aio_core_bst, aio->aio_core_bsh,
+           AWIN_DRAM_OFFSET + AWIN_SRAM_CTL1_REG,
+           __SHIFTOUT(AWIN_SRAM_CTL1_SRAMD_MAP_USB0,
+                      AWIN_SRAM_CTL1_SRAMD_MAP),
+           0);
+
+       sc->sc_motg.sc_dev = self;
+       sc->sc_motg.sc_bus.dmatag = aio->aio_dmat;
+       sc->sc_motg.sc_iot = aio->aio_core_bst;
+       bus_space_subregion(sc->sc_motg.sc_iot, aio->aio_core_bsh,
+           loc->loc_offset, loc->loc_size, &sc->sc_motg.sc_ioh);
+       sc->sc_motg.sc_size = loc->loc_size;
+       sc->sc_motg.sc_intr_poll = awin_otg_poll;
+       sc->sc_motg.sc_intr_poll_arg = sc;
+
+       sc->sc_motg.sc_mode = MOTG_MODE_HOST;
+       sc->sc_motg.sc_ep_max = 5;
+
+       sc->sc_ih = intr_establish(loc->loc_intr, IPL_SCHED, IST_LEVEL,
+           awin_otg_intr, sc);
+       if (sc->sc_ih == NULL) {
+               aprint_error_dev(self, "couldn't establish interrupt %d\n",
+                   loc->loc_intr);
+               return;
+       }
+       device_printf(self, "interrupting at irq %d\n", loc->loc_intr);
+
+       awin_otg_init(sc);
+
+       motg_init(&sc->sc_motg);
+}
+
+static void
+awin_otg_init(struct awin_otg_softc *sc)
+{
+       uint32_t val;
+
+       /* initialize the USB phy */
+       awin_otg_phy_write(sc, 0x0c, 0x01, 1);
+       awin_otg_phy_write(sc, 0x20, 0x14, 5);
+       awin_otg_phy_write(sc, 0x2a, 0x03, 2);
+
+       if (awin_gpio_pin_reserve("usb0drv", &sc->sc_drv_pin)) {
+               awin_gpio_pindata_write(&sc->sc_drv_pin, 1);
+       } else {
+               aprint_error_dev(sc->sc_motg.sc_dev, "no power gpio found\n");
+       }
+
+       val = OTG_READ4(sc, AWIN_USB0_PHY_CSR_REG);
+       val &= ~AWIN_USB0_PHY_CSR_VBUS_CHANGE_DET;
+       val &= ~AWIN_USB0_PHY_CSR_ID_CHANGE_DET;
+       val &= ~AWIN_USB0_PHY_CSR_DPDM_CHANGE_DET;
+       val |= AWIN_USB0_PHY_CSR_DPDM_PULLUP_EN;
+       val |= AWIN_USB0_PHY_CSR_ID_PULLUP_EN;
+       val &= ~AWIN_USB0_PHY_CSR_FORCE_ID;
+       val |= __SHIFTIN(AWIN_USB0_PHY_CSR_FORCE_ID_LOW,
+                        AWIN_USB0_PHY_CSR_FORCE_ID);
+       val &= ~AWIN_USB0_PHY_CSR_FORCE_VBUS_VALID;
+       val |= __SHIFTIN(AWIN_USB0_PHY_CSR_FORCE_VBUS_VALID_HIGH,
+                        AWIN_USB0_PHY_CSR_FORCE_VBUS_VALID);
+       OTG_WRITE4(sc, AWIN_USB0_PHY_CSR_REG, val);
+
+       OTG_WRITE1(sc, MUSB2_REG_AWIN_VEND0, 0);
+}
+
+static int
+awin_otg_intr(void *priv)
+{
+       struct awin_otg_softc *sc = priv;
+       uint8_t intusb;
+       uint16_t inttx, intrx;
+
+       mutex_enter(&sc->sc_motg.sc_intr_lock);
+
+       intusb = OTG_READ1(sc, MUSB2_REG_INTUSB);
+       inttx = OTG_READ2(sc, MUSB2_REG_INTTX);
+       intrx = OTG_READ2(sc, MUSB2_REG_INTRX);
+       if (!intusb && !inttx && !intrx) {
+               mutex_exit(&sc->sc_motg.sc_intr_lock);
+               return 0;
+       }
+
+#if 0
+       device_printf(sc->sc_motg.sc_dev, "ctrl %02x tx %04x rx %04x\n",
+           intusb, inttx, intrx);
+#endif
+
+       if (intusb)
+               OTG_WRITE1(sc, MUSB2_REG_INTUSB, intusb);
+       if (inttx)
+               OTG_WRITE2(sc, MUSB2_REG_INTTX, inttx);
+       if (intrx)
+               OTG_WRITE2(sc, MUSB2_REG_INTRX, intrx);
+
+       motg_intr(&sc->sc_motg, inttx, intrx, intusb);
+
+       mutex_exit(&sc->sc_motg.sc_intr_lock);
+
+       return 1;
+}
+
+static void
+awin_otg_poll(void *priv)
+{
+       awin_otg_intr(priv);
+}
+
+static void
+awin_otg_phy_write(struct awin_otg_softc *sc, u_int bit_addr, u_int bits,
+    u_int len)
+{
+       bus_space_tag_t bst = sc->sc_motg.sc_iot;
+       bus_space_handle_t bsh = sc->sc_motg.sc_ioh;
+       uint32_t clk = AWIN_USB0_PHY_CTL_CLK0;
+       bus_size_t reg = AWIN_USB0_PHY_CTL_REG;
+
+       uint32_t v = bus_space_read_4(bst, bsh, reg);
+
+       KASSERT((v & AWIN_USB0_PHY_CTL_CLK0) == 0);
+       KASSERT((v & AWIN_USB0_PHY_CTL_CLK1) == 0);
+       KASSERT((v & AWIN_USB0_PHY_CTL_CLK2) == 0);
+
+       v &= ~AWIN_USB0_PHY_CTL_ADDR;
+       v &= ~AWIN_USB0_PHY_CTL_DAT;
+
+       v |= __SHIFTIN(bit_addr, AWIN_USB0_PHY_CTL_ADDR);
+
+       /*
+        * Bitbang the data to the phy, bit by bit, incrementing bit address
+        * as we go.
+        */
+       for (; len > 0; bit_addr++, bits >>= 1, len--) {
+               v |= __SHIFTIN(bits & 1, AWIN_USB0_PHY_CTL_DAT);
+               bus_space_write_4(bst, bsh, reg, v);
+               delay(1);
+               bus_space_write_4(bst, bsh, reg, v | clk);
+               delay(1);
+               bus_space_write_4(bst, bsh, reg, v);
+               delay(1);
+               v += __LOWEST_SET_BIT(AWIN_USB0_PHY_CTL_ADDR);
+               v &= ~AWIN_USB0_PHY_CTL_DAT;
+       }
+}
diff -r 3647d2784a7f -r eecbad198b6b sys/arch/arm/allwinner/awin_otgreg.h
--- a/sys/arch/arm/allwinner/awin_otgreg.h      Sat Sep 13 17:48:00 2014 +0000
+++ b/sys/arch/arm/allwinner/awin_otgreg.h      Sat Sep 13 17:48:52 2014 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: awin_otgreg.h,v 1.1 2014/09/13 17:42:48 jmcneill Exp $ */
+/* $NetBSD: awin_otgreg.h,v 1.2 2014/09/13 17:48:52 jmcneill Exp $ */
 /* FreeBSD: head/sys/dev/usb/controller/musb_otg.h 267122 2014-06-05 18:23:51Z hselasky */
 /*-
  * Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
@@ -287,4 +287,8 @@
 
 #define        MUSB2_EP_MAX 16                 /* maximum number of endpoints */
 
+#define MUSB2_REG_AWIN_VEND0 0x0043
+#define MUSB2_REG_AWIN_VEND1 0x007d
+#define MUSB2_REG_AWIN_VEND3 0x007e
+
 #endif                                 /* _MUSB2_OTG_H_ */
diff -r 3647d2784a7f -r eecbad198b6b sys/arch/arm/allwinner/files.awin
--- a/sys/arch/arm/allwinner/files.awin Sat Sep 13 17:48:00 2014 +0000
+++ b/sys/arch/arm/allwinner/files.awin Sat Sep 13 17:48:52 2014 +0000
@@ -1,4 +1,4 @@
-#      $NetBSD: files.awin,v 1.13 2014/09/11 02:21:19 jmcneill Exp $
+#      $NetBSD: files.awin,v 1.14 2014/09/13 17:48:52 jmcneill Exp $
 #
 # Configuration info for Allwinner ARM Peripherals
 #
@@ -91,6 +91,10 @@
 attach awge at awinio with awin_gige
 file   arch/arm/allwinner/awin_gige.c          awin_gige
 
+# USB2 OTG Controller
+attach motg at awinio with awin_otg
+file   arch/arm/allwinner/awin_otg.c           awin_otg
+
 # USB2 Host Controller (EHCI/OHCI)
 device awinusb { }
 attach awinusb at awinio with awin_usb



Home | Main Index | Thread Index | Old Index