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 Add more initialization code for AHCI...



details:   https://anonhg.NetBSD.org/src/rev/a5995e773b7c
branches:  trunk
changeset: 789783:a5995e773b7c
user:      matt <matt%NetBSD.org@localhost>
date:      Sat Sep 07 19:48:57 2013 +0000

description:
Add more initialization code for AHCI and USB.
Alas, neither still is coming up.

diffstat:

 sys/arch/arm/allwinner/awin_ahcisata.c |   91 ++++++++++++++++++++++-
 sys/arch/arm/allwinner/awin_usb.c      |   92 ++++++++++++++++++++++-
 sys/arch/arm/allwinner/sdxcreg.h       |  131 +++++++++++++++++++++++++++++++++
 3 files changed, 308 insertions(+), 6 deletions(-)

diffs (truncated from 410 to 300 lines):

diff -r 69175340b846 -r a5995e773b7c sys/arch/arm/allwinner/awin_ahcisata.c
--- a/sys/arch/arm/allwinner/awin_ahcisata.c    Sat Sep 07 19:47:28 2013 +0000
+++ b/sys/arch/arm/allwinner/awin_ahcisata.c    Sat Sep 07 19:48:57 2013 +0000
@@ -31,7 +31,7 @@
 
 #include <sys/cdefs.h>
 
-__KERNEL_RCSID(1, "$NetBSD: awin_ahcisata.c,v 1.4 2013/09/07 02:10:02 matt Exp $");
+__KERNEL_RCSID(1, "$NetBSD: awin_ahcisata.c,v 1.5 2013/09/07 19:48:57 matt Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -50,6 +50,7 @@
 
 struct awin_ahci_softc {
        struct ahci_softc asc_sc;
+       struct awin_gpio_pindata asc_gpio_pin;
        void *asc_ih;
 };
 
@@ -73,6 +74,70 @@
 }
 
 static void
+awin_ahci_phy_init(struct awin_ahci_softc *asc)
+{
+       bus_space_tag_t bst = asc->asc_sc.sc_ahcit;
+       bus_space_handle_t bsh = asc->asc_sc.sc_ahcih;
+       u_int timeout;
+       uint32_t v;
+
+       /*
+        * This is dark magic.
+        */
+       bus_space_write_4(bst, bsh, AWIN_AHCI_RWCR_REG, 0);
+       delay(2);
+       awin_reg_set_clear(bst, bsh, AWIN_AHCI_PHYCS1R_REG, __BIT(19), 0);
+       delay(1);
+       awin_reg_set_clear(bst, bsh, AWIN_AHCI_PHYCS1R_REG,
+           __BIT(23)|__BIT(18)|__SHIFTIN(5, __BITS(26,24)),
+           __BITS(26,24));
+       delay(1);
+       awin_reg_set_clear(bst, bsh, AWIN_AHCI_PHYCS1R_REG,
+           __BIT(17)|__BITS(10,9)|__BIT(7),
+           __BIT(16)|__BITS(12,11)|__BIT(8)|__BIT(6));
+       delay(1);
+       awin_reg_set_clear(bst, bsh, AWIN_AHCI_PHYCS1R_REG,
+           __BIT(28)|__BIT(15), 0);
+       delay(1);
+       awin_reg_set_clear(bst, bsh, AWIN_AHCI_PHYCS1R_REG, 0, __BIT(19));
+       delay(1);
+       awin_reg_set_clear(bst, bsh, AWIN_AHCI_PHYCS0R_REG,
+           __BITS(21,20), __BIT(22));
+       delay(1);
+       awin_reg_set_clear(bst, bsh, AWIN_AHCI_PHYCS2R_REG,
+           __BITS(9,8)|__BIT(5), __BITS(7,6));
+       delay(2);
+       awin_reg_set_clear(bst, bsh, AWIN_AHCI_PHYCS0R_REG, __BIT(19), 0);
+       delay(2);
+
+       timeout = 100000;
+       do {
+               delay(1);
+               v = bus_space_read_4(bst, bsh, AWIN_AHCI_PHYCS0R_REG);
+       } while (--timeout && __SHIFTOUT(v, __BITS(30,28)) != 2);
+
+       if (!timeout) {
+               aprint_error_dev(
+                   asc->asc_sc.sc_atac.atac_dev,
+                   "SATA PHY power failed (%#x)\n", v);
+       }
+
+       awin_reg_set_clear(bst, bsh, AWIN_AHCI_PHYCS2R_REG, __BIT(24), 0);
+       timeout = 100000;
+       do {
+               delay(1);
+               v = bus_space_read_4(bst, bsh, AWIN_AHCI_PHYCS0R_REG);
+       } while (--timeout && (v & __BIT(24)));
+
+       if (!timeout) {
+               aprint_error_dev(
+                   asc->asc_sc.sc_atac.atac_dev,
+                   "SATA PHY calibration failed (%#x)\n", v);
+       }
+       bus_space_write_4(bst, bsh, AWIN_AHCI_RWCR_REG, 7);
+}
+
+static void
 awin_ahci_enable(bus_space_tag_t bst, bus_space_handle_t bsh)
 {
        /*
@@ -85,7 +150,7 @@
         */
        awin_reg_set_clear(bst, bsh, AWIN_AHB_GATING0_REG,
            AWIN_AHB_GATING0_SATA, 0);
-       delay(10000);
+       delay(1000);
 
        /*
         * Now turn it on.
@@ -114,6 +179,28 @@
        aprint_naive(": AHCI SATA controller\n");
        aprint_normal(": AHCI SATA controller\n");
 
+       /*
+        * Bring up the PHY.
+        */
+       awin_ahci_phy_init(asc);
+
+       /*
+        * If there is a GPIO to turn on power, do it now.
+        */
+       const char *pin_name;
+       prop_dictionary_t dict = device_properties(self);
+       if (prop_dictionary_get_cstring_nocopy(dict, "power-gpio", &pin_name)) {
+               if (awin_gpio_pin_reserve(pin_name, &asc->asc_gpio_pin)) {
+                       awin_gpio_pindata_write(&asc->asc_gpio_pin, 1);
+               } else {
+                       aprint_error_dev(self,
+                           "failed to reserve GPIO \"%s\"\n", pin_name);
+               }
+       }
+
+       /*
+        * Establish the interrupt
+        */
        asc->asc_ih = intr_establish(loc->loc_intr, IPL_VM, IST_LEVEL,
            ahci_intr, sc);
        if (asc->asc_ih == NULL) {
diff -r 69175340b846 -r a5995e773b7c sys/arch/arm/allwinner/awin_usb.c
--- a/sys/arch/arm/allwinner/awin_usb.c Sat Sep 07 19:47:28 2013 +0000
+++ b/sys/arch/arm/allwinner/awin_usb.c Sat Sep 07 19:48:57 2013 +0000
@@ -34,7 +34,7 @@
 
 #include <sys/cdefs.h>
 
-__KERNEL_RCSID(1, "$NetBSD: awin_usb.c,v 1.6 2013/09/07 10:46:18 jmcneill Exp $");
+__KERNEL_RCSID(1, "$NetBSD: awin_usb.c,v 1.7 2013/09/07 19:48:57 matt Exp $");
 
 #include <sys/bus.h>
 #include <sys/device.h>
@@ -67,6 +67,9 @@
        bus_space_tag_t usbsc_bst;
        bus_space_handle_t usbsc_ehci_bsh;
        bus_space_handle_t usbsc_ohci_bsh;
+       bus_space_handle_t usbsc_usb0_phy_csr_bsh;
+       u_int usbsc_number;
+       struct awin_gpio_pindata usbsc_drv_pin;
 
        device_t usbsc_ohci_dev;
        device_t usbsc_ehci_dev;
@@ -246,6 +249,42 @@
 }
 #endif /* NEHCI > 0 */
 
+static void
+awin_usb_phy_write(struct awinusb_softc *usbsc, u_int bit_addr, u_int bits,
+       u_int len)
+{
+       bus_space_tag_t bst = usbsc->usbsc_bst;
+       bus_space_handle_t bsh = usbsc->usbsc_usb0_phy_csr_bsh;
+       uint32_t clk = AWIN_USB0_PHY_CSR_CLK0 << usbsc->usbsc_number;
+
+       uint32_t v = bus_space_read_4(bst, bsh, 0);
+
+       KASSERT((v & AWIN_USB0_PHY_CSR_CLK0) == 0);
+       KASSERT((v & AWIN_USB0_PHY_CSR_CLK1) == 0);
+       KASSERT((v & AWIN_USB0_PHY_CSR_CLK2) == 0);
+
+       v &= ~AWIN_USB0_PHY_CSR_ADDR;
+       v &= ~AWIN_USB0_PHY_CSR_DAT;
+
+       v |= __SHIFTIN(bit_addr, AWIN_USB0_PHY_CSR_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_CSR_DAT);
+               bus_space_write_4(bst, bsh, 0, v);
+               delay(1);
+               bus_space_write_4(bst, bsh, 0, v | clk);
+               delay(1);
+               bus_space_write_4(bst, bsh, 0, v);
+               delay(1);
+               v += __LOWEST_SET_BIT(AWIN_USB0_PHY_CSR_ADDR);
+               v &= ~AWIN_USB0_PHY_CSR_DAT;
+       }
+}
+
 static int awinusb_match(device_t, cfdata_t, void *);
 static void awinusb_attach(device_t, device_t, void *);
 
@@ -254,6 +293,12 @@
 
 static int awinusb_ports;
 
+static const char awinusb_drvpin_names[2][8] = { "usb1drv", "usb2drv" };
+static const bus_size_t awinusb_dram_hpcr_regs[2] = {
+       AWIN_DRAM_HPCR_USB1_REG,
+       AWIN_DRAM_HPCR_USB2_REG,
+};
+
 int
 awinusb_match(device_t parent, cfdata_t cf, void *aux)
 {
@@ -277,8 +322,10 @@
        const struct awin_locators * const loc = &aio->aio_loc;
 
        awinusb_ports |= __BIT(loc->loc_port);
+
        usbsc->usbsc_bst = aio->aio_core_bst;
        usbsc->usbsc_dmat = aio->aio_dmat;
+       usbsc->usbsc_number = loc->loc_port + 1;
 
        bus_space_subregion(usbsc->usbsc_bst, aio->aio_core_bsh,
            loc->loc_offset + AWIN_EHCI_OFFSET, AWIN_EHCI_SIZE,
@@ -286,6 +333,46 @@
        bus_space_subregion(usbsc->usbsc_bst, aio->aio_core_bsh,
            loc->loc_offset + AWIN_OHCI_OFFSET, AWIN_OHCI_SIZE,
            &usbsc->usbsc_ohci_bsh);
+       bus_space_subregion(usbsc->usbsc_bst, aio->aio_core_bsh,
+           AWIN_USB0_OFFSET + AWIN_USB0_PHY_CSR_REG, 4,
+           &usbsc->usbsc_usb0_phy_csr_bsh);
+
+       aprint_naive("\n");
+       aprint_normal("\n");
+
+       /*
+        * Access to the USB phy is off USB0 so make sure it's on.
+       */
+       awin_reg_set_clear(usbsc->usbsc_bst, aio->aio_ccm_bsh,
+           AWIN_AHB_GATING0_REG, AWIN_AHB_GATING0_USB0, 0);
+
+       awin_reg_set_clear(usbsc->usbsc_bst, aio->aio_core_bsh,
+           loc->loc_offset + AWIN_USB_PMU_IRQ_REG,
+           AWIN_USB_PMU_IRQ_AHB_INCR8 | AWIN_USB_PMU_IRQ_AHB_INCR4
+              | AWIN_USB_PMU_IRQ_AHB_INCRX | AWIN_USB_PMU_IRQ_ULPI_BYPASS,
+           0);
+
+       /*
+        * Allow USB DMA engine access to the DRAM.
+        */
+       awin_reg_set_clear(usbsc->usbsc_bst, aio->aio_core_bsh,
+           AWIN_DRAM_OFFSET + awinusb_dram_hpcr_regs[loc->loc_port],
+           AWIN_DRAM_HPCR_ACCESS_EN, 0);
+
+       /* initialize the USB phy */
+       awin_usb_phy_write(usbsc, 0x20, 0x14, 5);
+       awin_usb_phy_write(usbsc, 0x2a, 0x03, 2);
+
+       /*
+        * Now get the GPIO that enables the power to the port and
+        * turn it on.
+        */
+       if (awin_gpio_pin_reserve(awinusb_drvpin_names[loc->loc_port],
+                   &usbsc->usbsc_drv_pin)) {
+               awin_gpio_pindata_write(&usbsc->usbsc_drv_pin, 1);
+       } else {
+               aprint_error_dev(self, "no power gpio found\n");
+       }
 
        /*
         * Disable interrupts
@@ -301,9 +388,6 @@
            caplength + EHCI_USBINTR, 0);
 #endif
 
-       aprint_naive("\n");
-       aprint_normal("\n");
-
 #if NOHCI > 0
        struct awinusb_attach_args usbaa_ohci = {
                .usbaa_name = "ohci",
diff -r 69175340b846 -r a5995e773b7c sys/arch/arm/allwinner/sdxcreg.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/arch/arm/allwinner/sdxcreg.h  Sat Sep 07 19:48:57 2013 +0000
@@ -0,0 +1,131 @@
+/* $NetBSD: sdxcreg.h,v 1.1 2013/09/07 19:48:57 matt Exp $ */
+/*-
+ * Copyright (c) 2013 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Matt Thomas of 3am Software Foundry.
+ *
+ * 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``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 FOUNDATION OR CONTRIBUTORS



Home | Main Index | Thread Index | Old Index