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