Module Name: src
Committed By: matt
Date: Sat Sep 7 19:48:57 UTC 2013
Modified Files:
src/sys/arch/arm/allwinner: awin_ahcisata.c awin_usb.c
Added Files:
src/sys/arch/arm/allwinner: sdxcreg.h
Log Message:
Add more initialization code for AHCI and USB.
Alas, neither still is coming up.
To generate a diff of this commit:
cvs rdiff -u -r1.4 -r1.5 src/sys/arch/arm/allwinner/awin_ahcisata.c
cvs rdiff -u -r1.6 -r1.7 src/sys/arch/arm/allwinner/awin_usb.c
cvs rdiff -u -r0 -r1.1 src/sys/arch/arm/allwinner/sdxcreg.h
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/arch/arm/allwinner/awin_ahcisata.c
diff -u src/sys/arch/arm/allwinner/awin_ahcisata.c:1.4 src/sys/arch/arm/allwinner/awin_ahcisata.c:1.5
--- src/sys/arch/arm/allwinner/awin_ahcisata.c:1.4 Sat Sep 7 02:10:02 2013
+++ src/sys/arch/arm/allwinner/awin_ahcisata.c Sat Sep 7 19:48:57 2013
@@ -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 @@ static void awin_ahci_attach(device_t, d
struct awin_ahci_softc {
struct ahci_softc asc_sc;
+ struct awin_gpio_pindata asc_gpio_pin;
void *asc_ih;
};
@@ -73,6 +74,70 @@ awin_ahci_match(device_t parent, cfdata_
}
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_ahci_enable(bus_space_tag_t bst, bu
*/
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 @@ awin_ahci_attach(device_t parent, device
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) {
Index: src/sys/arch/arm/allwinner/awin_usb.c
diff -u src/sys/arch/arm/allwinner/awin_usb.c:1.6 src/sys/arch/arm/allwinner/awin_usb.c:1.7
--- src/sys/arch/arm/allwinner/awin_usb.c:1.6 Sat Sep 7 10:46:18 2013
+++ src/sys/arch/arm/allwinner/awin_usb.c Sat Sep 7 19:48:57 2013
@@ -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 @@ struct awinusb_softc {
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 @@ ehci_awinusb_attach(device_t parent, dev
}
#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 @@ CFATTACH_DECL_NEW(awin_usb, sizeof(struc
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 @@ awinusb_attach(device_t parent, device_t
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 @@ awinusb_attach(device_t parent, device_t
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 @@ awinusb_attach(device_t parent, device_t
caplength + EHCI_USBINTR, 0);
#endif
- aprint_naive("\n");
- aprint_normal("\n");
-
#if NOHCI > 0
struct awinusb_attach_args usbaa_ohci = {
.usbaa_name = "ohci",
Added files:
Index: src/sys/arch/arm/allwinner/sdxcreg.h
diff -u /dev/null src/sys/arch/arm/allwinner/sdxcreg.h:1.1
--- /dev/null Sat Sep 7 19:48:57 2013
+++ src/sys/arch/arm/allwinner/sdxcreg.h Sat Sep 7 19:48:57 2013
@@ -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
+ * 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.
+ */
+
+#ifndef _ARM_ALLWINNER_SDXCREG_H_
+#define _ARM_ALLWINNER_SDXCREG_H_
+
+/* SDXC definitions */
+#define SDXC_GCTRL_REG 0x0000
+#define SDXC_CLKCR_REG 0x0004
+#define SDXC_TIMEOUT_REG 0x0008
+#define SDXC_WIDTH_REG 0x000c
+#define SDXC_BLKSZ_REG 0x0010
+#define SDXC_BYTECNT_REG 0x0014
+#define SDXC_CMD_REG 0x0018
+#define SDXC_ARG_REG 0x001c
+#define SDXC_RESP0_REG 0x0020
+#define SDXC_RESP1_REG 0x0024
+#define SDXC_RESP2_REG 0x0028
+#define SDXC_RESP3_REG 0x002c
+#define SDXC_IMASK_REG 0x0030
+#define SDXC_MINT_REG 0x0034
+#define SDXC_RINT_REG 0x0038
+#define SDXC_STATUS_REG 0x003c
+#define SDXC_FTRGLVL_REG 0x0040
+#define SDXC_FUNCSEL_REG 0x0044
+#define SDXC_CBCR_REG 0x0048
+#define SDXC_BBCR_REG 0x004c
+#define SDXC_DMAC_REG 0x0080
+#define SDXC_DLBA_REG 0x0084
+#define SDXC_IDST_REG 0x0088
+#define SDXC_IDIE_REG 0x008c
+#define SDXC_CHDA_REG 0x0090
+#define SDXC_CBDA_REG 0x0094
+#define SDXC_FIFO_REG 0x0100
+
+#define SDXC_GCTRL_AHB_ACCESS __BIT(31)
+#define SDXC_GCTRL_DDR_MODE __BIT(10)
+#define SDXC_GCTRL_POS_EDGE_LATCH_DATA __BIT(9)
+#define SDXC_GCTRL_DEBOUNCE_ENABLE __BIT(8)
+#define SDXC_GCTRL_DMA_ENABLE __BIT(5)
+#define SDXC_GCTRL_INT_ENABLE __BIT(4)
+#define SDXC_GCTRL_DMA_RESET __BIT(2)
+#define SDXC_GCTRL_FIFO_RESET __BIT(1)
+#define SDXC_GCTRL_SOFT_RESET __BIT(0)
+
+#define SDXC_CARD_LOW_POWER_ON __BIT(17)
+#define SDXC_CARD_CLK_ON __BIT(16)
+
+#define SDXC_BUS_WIDTH_1 (0)
+#define SDXC_BUS_WIDTH_4 (1)
+#define SDXC_BUS_WIDTH_8 (2)
+
+#define SDXC_CMD_START __BIT(31)
+#define SDXC_CMD_VOL_SWITCH __BIT(27)
+#define SDXC_CMD_DISBALE_BOOT __BIT(26)
+#define SDXC_CMD_BOOT_ACK_EXP __BIT(25)
+#define SDXC_CMD_ALT_BOOT_OP __BIT(24)
+#define SDXC_CMD_END_BOOT __BIT(24)
+#define SDXC_CMD_CCS_EXP __BIT(23)
+#define SDXC_CMD_RD_CE_ATA_DEV __BIT(22)
+#define SDXC_CMD_UP_CLK_ONLY __BIT(21)
+#define SDXC_CMD_SEND_INIT_SEQ __BIT(15)
+#define SDXC_CMD_STOP_ABORT_CMD __BIT(11)
+#define SDXC_CMD_WAIT_PRE_OVER __BIT(11)
+#define SDXC_CMD_SEND_AUTO_STOP __BIT(11)
+#define SDXC_CMD_SEQ_MODE __BIT(11)
+#define SDXC_CMD_WRITE __BIT(10)
+#define SDXC_CMD_DATA_EXP __BIT(9)
+#define SDXC_CMD_CHECK_RESP_CRC __BIT(8)
+#define SDXC_CMD_LONG_RESP __BIT(7)
+#define SDXC_CMD_RESP_EXP __BIT(6)
+
+#define SDXC_INT_ERR_SUM ( SDXC_INT_END_BIT_ERR \
+ | SDXC_INT_START_BIT_ERR \
+ | SDXC_INT_HARDWARE_LOCKED \
+ | SDXC_INT_FIFO_RUN_ERR \
+ | SDXC_INT_DATA_TIMEOUT \
+ | SDXC_INT_RESP_TIMEOUT \
+ | SDXC_INT_RESP_CRC_ERR \
+ | SDXC_INT_DATA_CRC_ERR \
+ | SDXC_INT_RESP_ERR )
+#define SDXC_INT_CARD_REMOVE __BIT(31)
+#define SDXC_INT_CARD_INSERT __BIT(30)
+#define SDXC_INT_SDIO_INT __BIT(16)
+#define SDXC_INT_END_BIT_ERR __BIT(15)
+#define SDXC_INT_AUTO_CMD_DONE __BIT(14)
+#define SDXC_INT_START_BIT_ERR __BIT(13)
+#define SDXC_INT_HARDWARE_LOCKED __BIT(12)
+#define SDXC_INT_FIFO_RUN_ERR __BIT(11)
+#define SDXC_INT_VOL_CHG_DONE __BIT(10)
+#define SDXC_INT_DATA_STARVE __BIT(10)
+#define SDXC_INT_BOOT_START __BIT(9)
+#define SDXC_INT_DATA_TIMEOUT __BIT(9)
+#define SDXC_INT_ACK_RCV __BIT(8)
+#define SDXC_INT_RESP_TIMEOUT __BIT(8)
+#define SDXC_INT_DATA_CRC_ERR __BIT(7)
+#define SDXC_INT_RESP_CRC_ERR __BIT(6)
+#define SDXC_INT_RX_DATA_REQ __BIT(5)
+#define SDXC_INT_TX_DATA_REQ __BIT(4)
+#define SDXC_INT_DATA_OVER __BIT(3)
+#define SDXC_INT_CMD_DONE __BIT(2)
+#define SDXC_INT_RESP_ERR __BIT(1)
+
+#endif /* _ARM_ALLWINNER_SDXCREG_H_ */