Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 3 Jul 2015 14:11:02 +0000 (UTC)
From:      Luiz Otavio O Souza <loos@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r285090 - in head/sys: arm/allwinner arm/conf boot/fdt/dts/arm dev/ahci
Message-ID:  <201507031411.t63EB2xQ035466@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: loos
Date: Fri Jul  3 14:11:01 2015
New Revision: 285090
URL: https://svnweb.freebsd.org/changeset/base/285090

Log:
  Add AHCI attachment code for Allwinner A10/A20 SoCs.
  
  The Allwinner SoC has an AHCI device on its internal main bus rather
  than the PCI bus.  This SoC is somewhat underdocumented, and its SATA
  controller is no exception.  The methods to support this chip were
  harvested from the Linux Allwinner SDK, and then constants invented to
  describe what's going on based on low-level constants contained in the
  SATA standard and guess work.
  
  This SoC requires a specific AHCI channel setup in order to start the
  operations on the channel properly.
  
  Clock setup and AHCI channel setup idea came from NetBSD.
  
  Tested on Cubieboard 2 and Banana pi (and attachment on Cubieboard by
  Pratik Singhal).
  
  Differential Revision:	https://reviews.freebsd.org/D737
  Submitted by:	imp
  Reviewed by:	imp, ganbold, mav, andrew

Added:
  head/sys/arm/allwinner/a10_ahci.c   (contents, props changed)
Modified:
  head/sys/arm/allwinner/a10_clk.c
  head/sys/arm/allwinner/a10_clk.h
  head/sys/arm/allwinner/files.allwinner
  head/sys/arm/conf/CUBIEBOARD
  head/sys/arm/conf/CUBIEBOARD2
  head/sys/boot/fdt/dts/arm/cubieboard.dts
  head/sys/boot/fdt/dts/arm/sun4i-a10.dtsi
  head/sys/boot/fdt/dts/arm/sun7i-a20.dtsi
  head/sys/dev/ahci/ahci.c
  head/sys/dev/ahci/ahci.h

Added: head/sys/arm/allwinner/a10_ahci.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/arm/allwinner/a10_ahci.c	Fri Jul  3 14:11:01 2015	(r285090)
@@ -0,0 +1,382 @@
+/*-
+ * Copyright (c) 2014-2015 M. Warner Losh <imp@freebsd.org>
+ * Copyright (c) 2015 Luiz Otavio O Souza <loos@freebsd.org>
+ * 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 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 AUTHOR 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.
+ *
+ * The magic-bit-bang sequence used in this code may be based on a linux
+ * platform driver in the Allwinner SDK from Allwinner Technology Co., Ltd.
+ * www.allwinnertech.com, by Daniel Wang <danielwang@allwinnertech.com>
+ * though none of the original code was copied.
+ */
+
+#include "opt_bus.h"
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/rman.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/gpio.h>
+
+#include <machine/bus.h>
+#include <dev/ofw/ofw_bus.h> 
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <dev/ahci/ahci.h>
+#include <arm/allwinner/a10_clk.h>
+#include "gpio_if.h"
+
+/*
+ * Allwinner a1x/a2x/a8x SATA attachment.  This is just the AHCI register
+ * set with a few extra implementation-specific registers that need to
+ * be accounted for.  There's only one PHY in the system, and it needs
+ * to be trained to bring the link up.  In addition, there's some DMA
+ * specific things that need to be done as well.  These things are also
+ * just about completely undocumented, except in ugly code in the Linux
+ * SDK Allwinner releases.
+ */
+
+/* BITx -- Unknown bit that needs to be set/cleared at position x */
+/* UFx -- Uknown multi-bit field frobbed during init */
+#define	AHCI_BISTAFR	0x00A0
+#define	AHCI_BISTCR	0x00A4
+#define	AHCI_BISTFCTR	0x00A8
+#define	AHCI_BISTSR	0x00AC
+#define	AHCI_BISTDECR	0x00B0
+#define	AHCI_DIAGNR	0x00B4
+#define	AHCI_DIAGNR1	0x00B8
+#define	AHCI_OOBR	0x00BC
+#define	AHCI_PHYCS0R	0x00C0
+/* Bits 0..17 are a mystery */
+#define	 PHYCS0R_BIT18			(1 << 18)
+#define	 PHYCS0R_POWER_ENABLE		(1 << 19)
+#define	 PHYCS0R_UF1_MASK		(7 << 20)	/* Unknown Field 1 */
+#define	  PHYCS0R_UF1_INIT		(3 << 20)
+#define	 PHYCS0R_BIT23			(1 << 23)
+#define	 PHYCS0R_UF2_MASK		(7 << 24)	/* Uknown Field 2 */
+#define	  PHYCS0R_UF2_INIT		(5 << 24)
+/* Bit 27 mystery */
+#define	 PHYCS0R_POWER_STATUS_MASK	(7 << 28)
+#define	  PHYCS0R_PS_GOOD		(2 << 28)
+/* Bit 31 mystery */
+#define	AHCI_PHYCS1R	0x00C4
+/* Bits 0..5 are a mystery */
+#define	 PHYCS1R_UF1_MASK		(3 << 6)
+#define	  PHYCS1R_UF1_INIT		(2 << 6)
+#define	 PHYCS1R_UF2_MASK		(0x1f << 8)
+#define	  PHYCS1R_UF2_INIT		(6 << 8)
+/* Bits 13..14 are a mystery */
+#define	 PHYCS1R_BIT15			(1 << 15)
+#define	 PHYCS1R_UF3_MASK		(3 << 16)
+#define	  PHYCS1R_UF3_INIT		(2 << 16)
+/* Bit 18 mystery */
+#define	 PHYCS1R_HIGHZ			(1 << 19)
+/* Bits 20..27 mystery */
+#define	 PHYCS1R_BIT28			(1 << 28)
+/* Bits 29..31 mystery */
+#define	AHCI_PHYCS2R	0x00C8
+/* bits 0..4 mystery */
+#define	 PHYCS2R_UF1_MASK		(0x1f << 5)
+#define	  PHYCS2R_UF1_INIT		(0x19 << 5)
+/* Bits 10..23 mystery */
+#define	 PHYCS2R_CALIBRATE		(1 << 24)
+/* Bits 25..31 mystery */
+#define	AHCI_TIMER1MS	0x00E0
+#define	AHCI_GPARAM1R	0x00E8
+#define	AHCI_GPARAM2R	0x00EC
+#define	AHCI_PPARAMR	0x00F0
+#define	AHCI_TESTR	0x00F4
+#define	AHCI_VERSIONR	0x00F8
+#define	AHCI_IDR	0x00FC
+#define	AHCI_RWCR	0x00FC
+
+#define	AHCI_P0DMACR	0x0070
+#define	AHCI_P0PHYCR	0x0078
+#define	AHCI_P0PHYSR	0x007C
+
+/* Kludge for CUBIEBOARD (and Banana PI too) */
+#define	GPIO_AHCI_PWR           40
+
+static void inline
+ahci_set(struct resource *m, bus_size_t off, uint32_t set)
+{
+	uint32_t val = ATA_INL(m, off);
+
+	val |= set;
+	ATA_OUTL(m, off, val);
+}
+
+static void inline
+ahci_clr(struct resource *m, bus_size_t off, uint32_t clr)
+{
+	uint32_t val = ATA_INL(m, off);
+
+	val &= ~clr;
+	ATA_OUTL(m, off, val);
+}
+
+static void inline
+ahci_mask_set(struct resource *m, bus_size_t off, uint32_t mask, uint32_t set)
+{
+	uint32_t val = ATA_INL(m, off);
+
+	val &= mask;
+	val |= set;
+	ATA_OUTL(m, off, val);
+}
+
+/*
+ * Should this be phy_reset or phy_init
+ */
+#define	PHY_RESET_TIMEOUT	1000
+static void
+ahci_a10_phy_reset(device_t dev)
+{
+	uint32_t to, val;
+	struct ahci_controller *ctlr = device_get_softc(dev);
+
+	/*
+	 * Here start the the magic -- most of the comments are based
+	 * on guesswork, names of routines and printf error
+	 * messages.  The code works, but it will do that even if the
+	 * comments are 100% BS.
+	 */
+
+	/*
+	 * Lock out other access while we initialize.  Or at least that
+	 * seems to be the case based on Linux SDK #defines.  Maybe this
+	 * put things into reset?
+	 */
+	ATA_OUTL(ctlr->r_mem, AHCI_RWCR, 0);
+	DELAY(100);
+
+	/*
+	 * Set bit 19 in PHYCS1R.  Guessing this disables driving the PHY
+	 * port for a bit while we reset things.
+	 */
+	ahci_set(ctlr->r_mem, AHCI_PHYCS1R, PHYCS1R_HIGHZ);
+
+	/*
+	 * Frob PHYCS0R...
+	 */
+	ahci_mask_set(ctlr->r_mem, AHCI_PHYCS0R,
+	    ~PHYCS0R_UF2_MASK,
+	    PHYCS0R_UF2_INIT | PHYCS0R_BIT23 | PHYCS0R_BIT18);
+
+	/*
+	 * Set three fields in PHYCS1R
+	 */
+	ahci_mask_set(ctlr->r_mem, AHCI_PHYCS1R,
+	    ~(PHYCS1R_UF1_MASK | PHYCS1R_UF2_MASK | PHYCS1R_UF3_MASK),
+	    PHYCS1R_UF1_INIT | PHYCS1R_UF2_INIT | PHYCS1R_UF3_INIT);
+
+	/*
+	 * Two more mystery bits in PHYCS1R. -- can these be combined above?
+	 */
+	ahci_set(ctlr->r_mem, AHCI_PHYCS1R, PHYCS1R_BIT15 | PHYCS1R_BIT28);
+
+	/*
+	 * Now clear that first mysery bit.  Perhaps this starts
+	 * driving the PHY again so we can power it up and start
+	 * talking to the SATA drive, if any below.
+	 */
+	ahci_clr(ctlr->r_mem, AHCI_PHYCS1R, PHYCS1R_HIGHZ);
+
+	/*
+	 * Frob PHYCS0R again...
+	 */
+	ahci_mask_set(ctlr->r_mem, AHCI_PHYCS0R,
+	    ~PHYCS0R_UF1_MASK, PHYCS0R_UF1_INIT);
+
+	/*
+	 * Frob PHYCS2R, because 25 means something?
+	 */
+	ahci_mask_set(ctlr->r_mem, AHCI_PHYCS2R, ~PHYCS2R_UF1_MASK,
+	    PHYCS2R_UF1_INIT);
+
+	DELAY(100);		/* WAG */
+
+	/*
+	 * Turn on the power to the PHY and wait for it to report back
+	 * good?
+	 */
+	ahci_set(ctlr->r_mem, AHCI_PHYCS0R, PHYCS0R_POWER_ENABLE);
+	for (to = PHY_RESET_TIMEOUT; to > 0; to--) {
+		val = ATA_INL(ctlr->r_mem, AHCI_PHYCS0R);
+		if ((val & PHYCS0R_POWER_STATUS_MASK) == PHYCS0R_PS_GOOD)
+			break;
+		DELAY(10);
+	}
+	if (to == 0 && bootverbose)
+		device_printf(dev, "PHY Power Failed PHYCS0R = %#x\n", val);
+
+	/*
+	 * Calibrate the clocks between the device and the host.  This appears
+	 * to be an automated process that clears the bit when it is done.
+	 */
+	ahci_set(ctlr->r_mem, AHCI_PHYCS2R, PHYCS2R_CALIBRATE);
+	for (to = PHY_RESET_TIMEOUT; to > 0; to--) {
+		val = ATA_INL(ctlr->r_mem, AHCI_PHYCS2R);
+		if ((val & PHYCS2R_CALIBRATE) == 0)
+			break;
+		DELAY(10);
+	}
+	if (to == 0 && bootverbose)
+		device_printf(dev, "PHY Cal Failed PHYCS2R %#x\n", val);
+
+	/*
+	 * OK, let things settle down a bit.
+	 */
+	DELAY(1000);
+
+	/*
+	 * Go back into normal mode now that we've calibrated the PHY.
+	 */
+	ATA_OUTL(ctlr->r_mem, AHCI_RWCR, 7);
+}
+
+static void
+ahci_a10_ch_start(struct ahci_channel *ch)
+{
+	uint32_t reg;
+
+	/*
+	 * Magical values from Allwinner SDK, setup the DMA before start
+	 * operations on this channel.
+	 */
+	reg = ATA_INL(ch->r_mem, AHCI_P0DMACR);
+	reg &= ~0xff00;
+	reg |= 0x4400;
+	ATA_OUTL(ch->r_mem, AHCI_P0DMACR, reg);
+}
+
+static int
+ahci_a10_ctlr_reset(device_t dev)
+{
+
+	ahci_a10_phy_reset(dev);
+
+	return (ahci_ctlr_reset(dev));
+}
+
+static int
+ahci_a10_probe(device_t dev)
+{
+
+	if (!ofw_bus_is_compatible(dev, "allwinner,sun4i-a10-ahci"))
+		return (ENXIO);
+	device_set_desc(dev, "Allwinner Integrated AHCI controller");
+
+	return (BUS_PROBE_DEFAULT);
+}
+
+static int
+ahci_a10_attach(device_t dev)
+{
+	device_t gpio;
+	int error;
+	struct ahci_controller *ctlr;
+
+	ctlr = device_get_softc(dev);
+	ctlr->quirks = AHCI_Q_NOPMP;
+	ctlr->vendorid = 0;
+	ctlr->deviceid = 0;
+	ctlr->subvendorid = 0;
+	ctlr->subdeviceid = 0;
+	ctlr->r_rid = 0;
+	if (!(ctlr->r_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
+	    &ctlr->r_rid, RF_ACTIVE)))
+		return (ENXIO);
+
+	/* Turn on the PLL for SATA */
+	a10_clk_ahci_activate();
+
+	/* Apply power to the drive, if any */
+	gpio = devclass_get_device(devclass_find("gpio"), 0);
+	if (gpio == NULL) {
+		device_printf(dev,
+		    "GPIO device not yet present (SATA won't work).\n");
+		bus_release_resource(dev, SYS_RES_MEMORY, ctlr->r_rid,
+		    ctlr->r_mem);
+		return (ENXIO);
+	}
+	GPIO_PIN_SETFLAGS(gpio, GPIO_AHCI_PWR, GPIO_PIN_OUTPUT);
+	GPIO_PIN_SET(gpio, GPIO_AHCI_PWR, GPIO_PIN_HIGH);
+	DELAY(10000);
+
+	/* Reset controller */
+	if ((error = ahci_a10_ctlr_reset(dev)) != 0) {
+		bus_release_resource(dev, SYS_RES_MEMORY, ctlr->r_rid,
+		    ctlr->r_mem);
+		return (error);
+	};
+
+	/*
+	 * No MSI registers on this platform.
+	 */
+	ctlr->msi = 0;
+	ctlr->numirqs = 1;
+
+	/* Channel start callback(). */
+	ctlr->ch_start = ahci_a10_ch_start;
+
+	/*
+	 * Note: ahci_attach will release ctlr->r_mem on errors automatically
+	 */
+	return (ahci_attach(dev));
+}
+
+static int
+ahci_a10_detach(device_t dev)
+{
+
+	return (ahci_detach(dev));
+}
+
+devclass_t ahci_devclass;
+
+static device_method_t ahci_ata_methods[] = {
+	DEVMETHOD(device_probe,     ahci_a10_probe),
+	DEVMETHOD(device_attach,    ahci_a10_attach),
+	DEVMETHOD(device_detach,    ahci_a10_detach),
+	DEVMETHOD(bus_print_child,  ahci_print_child),
+	DEVMETHOD(bus_alloc_resource,       ahci_alloc_resource),
+	DEVMETHOD(bus_release_resource,     ahci_release_resource),
+	DEVMETHOD(bus_setup_intr,   ahci_setup_intr),
+	DEVMETHOD(bus_teardown_intr,ahci_teardown_intr),
+	DEVMETHOD(bus_child_location_str, ahci_child_location_str),
+	DEVMETHOD_END
+};
+
+static driver_t ahci_ata_driver = {
+        "ahci",
+        ahci_ata_methods,
+        sizeof(struct ahci_controller)
+};
+
+DRIVER_MODULE(ahci, simplebus, ahci_ata_driver, ahci_devclass, 0, 0);

Modified: head/sys/arm/allwinner/a10_clk.c
==============================================================================
--- head/sys/arm/allwinner/a10_clk.c	Fri Jul  3 12:09:05 2015	(r285089)
+++ head/sys/arm/allwinner/a10_clk.c	Fri Jul  3 14:11:01 2015	(r285090)
@@ -56,6 +56,7 @@ struct a10_ccm_softc {
 	struct resource		*res;
 	bus_space_tag_t		bst;
 	bus_space_handle_t	bsh;
+	int			pll6_enabled;
 };
 
 static struct a10_ccm_softc *a10_ccm_sc = NULL;
@@ -203,6 +204,8 @@ a10_clk_pll6_enable(void)
 	 * For other uses the output frequency is 24MHz * n * k / 2.
 	 */
 	sc = a10_ccm_sc;
+	if (sc->pll6_enabled)
+		return;
 	reg_value = ccm_read_4(sc, CCM_PLL6_CFG);
 	reg_value &= ~CCM_PLL_CFG_BYPASS;
 	reg_value &= ~(CCM_PLL_CFG_FACTOR_K | CCM_PLL_CFG_FACTOR_M |
@@ -211,6 +214,7 @@ a10_clk_pll6_enable(void)
 	reg_value |= CCM_PLL6_CFG_SATA_CLKEN;
 	reg_value |= CCM_PLL_CFG_ENABLE;
 	ccm_write_4(sc, CCM_PLL6_CFG, reg_value);
+	sc->pll6_enabled = 1;
 }
 
 static unsigned int
@@ -229,6 +233,29 @@ a10_clk_pll6_get_rate(void)
 }
 
 int
+a10_clk_ahci_activate(void)
+{
+	struct a10_ccm_softc *sc;
+	uint32_t reg_value;
+
+	sc = a10_ccm_sc;
+	if (sc == NULL)
+		return (ENXIO);
+
+	a10_clk_pll6_enable();
+
+	/* Gating AHB clock for SATA */
+	reg_value = ccm_read_4(sc, CCM_AHB_GATING0);
+	reg_value |= CCM_AHB_GATING_SATA;
+	ccm_write_4(sc, CCM_AHB_GATING0, reg_value);
+	DELAY(1000);
+
+	ccm_write_4(sc, CCM_SATA_CLK, CCM_PLL_CFG_ENABLE);
+
+	return (0);
+}
+
+int
 a10_clk_mmc_activate(int devid)
 {
 	struct a10_ccm_softc *sc;

Modified: head/sys/arm/allwinner/a10_clk.h
==============================================================================
--- head/sys/arm/allwinner/a10_clk.h	Fri Jul  3 12:09:05 2015	(r285089)
+++ head/sys/arm/allwinner/a10_clk.h	Fri Jul  3 14:11:01 2015	(r285090)
@@ -105,6 +105,7 @@
 #define	CCM_AHB_GATING_EHCI1	(1 << 3)
 #define	CCM_AHB_GATING_SDMMC0	(1 << 8)
 #define	CCM_AHB_GATING_EMAC	(1 << 17)
+#define	CCM_AHB_GATING_SATA	(1 << 25)
 
 #define	CCM_USB_PHY		(1 << 8)
 #define	CCM_USB0_RESET		(1 << 0)
@@ -140,6 +141,7 @@
 int a10_clk_usb_activate(void);
 int a10_clk_usb_deactivate(void);
 int a10_clk_emac_activate(void);
+int a10_clk_ahci_activate(void);
 int a10_clk_mmc_activate(int);
 int a10_clk_mmc_cfg(int, int);
 

Modified: head/sys/arm/allwinner/files.allwinner
==============================================================================
--- head/sys/arm/allwinner/files.allwinner	Fri Jul  3 12:09:05 2015	(r285089)
+++ head/sys/arm/allwinner/files.allwinner	Fri Jul  3 14:11:01 2015	(r285090)
@@ -5,6 +5,7 @@ arm/arm/bus_space_base.c		standard
 arm/arm/bus_space_asm_generic.S		standard
 arm/arm/bus_space_generic.c		standard
 
+arm/allwinner/a10_ahci.c		optional	ahci
 arm/allwinner/a10_clk.c			standard
 arm/allwinner/a10_common.c		standard
 arm/allwinner/a10_ehci.c		optional	ehci

Modified: head/sys/arm/conf/CUBIEBOARD
==============================================================================
--- head/sys/arm/conf/CUBIEBOARD	Fri Jul  3 12:09:05 2015	(r285089)
+++ head/sys/arm/conf/CUBIEBOARD	Fri Jul  3 14:11:01 2015	(r285090)
@@ -57,7 +57,7 @@ device		mmc			# mmc/sd bus
 device		mmcsd			# mmc/sd flash cards
 
 # ATA controllers
-#device		ahci			# AHCI-compatible SATA controllers
+device		ahci			# AHCI-compatible SATA controllers
 #device		ata			# Legacy ATA/SATA controllers
 #options 	ATA_STATIC_ID		# Static device numbering
 
@@ -78,7 +78,7 @@ device		gpio
 
 device		scbus			# SCSI bus (required for ATA/SCSI)
 device		da			# Direct Access (disks)
-device		pass
+device		pass			# Passthrough device (direct ATA/SCSI access)
 
 # USB support
 options 	USB_HOST_ALIGN=64	# Align usb buffers to cache line size.

Modified: head/sys/arm/conf/CUBIEBOARD2
==============================================================================
--- head/sys/arm/conf/CUBIEBOARD2	Fri Jul  3 12:09:05 2015	(r285089)
+++ head/sys/arm/conf/CUBIEBOARD2	Fri Jul  3 14:11:01 2015	(r285090)
@@ -61,7 +61,7 @@ device		mmc			# mmc/sd bus
 device		mmcsd			# mmc/sd flash cards
 
 # ATA controllers
-#device		ahci			# AHCI-compatible SATA controllers
+device		ahci			# AHCI-compatible SATA controllers
 #device		ata			# Legacy ATA/SATA controllers
 #options 	ATA_STATIC_ID		# Static device numbering
 
@@ -82,7 +82,7 @@ device		gpio
 
 device		scbus			# SCSI bus (required for ATA/SCSI)
 device		da			# Direct Access (disks)
-device		pass
+device		pass			# Passthrough device (direct ATA/SCSI access)
 
 # USB support
 options 	USB_HOST_ALIGN=64	# Align usb buffers to cache line size.

Modified: head/sys/boot/fdt/dts/arm/cubieboard.dts
==============================================================================
--- head/sys/boot/fdt/dts/arm/cubieboard.dts	Fri Jul  3 12:09:05 2015	(r285089)
+++ head/sys/boot/fdt/dts/arm/cubieboard.dts	Fri Jul  3 14:11:01 2015	(r285090)
@@ -64,6 +64,10 @@
 		emac@01c0b000 {
 			status = "okay";
 		};
+
+		ahci: sata@01c18000 {
+			status = "okay";
+		};
 	};
 
 	chosen {

Modified: head/sys/boot/fdt/dts/arm/sun4i-a10.dtsi
==============================================================================
--- head/sys/boot/fdt/dts/arm/sun4i-a10.dtsi	Fri Jul  3 12:09:05 2015	(r285089)
+++ head/sys/boot/fdt/dts/arm/sun4i-a10.dtsi	Fri Jul  3 14:11:01 2015	(r285090)
@@ -112,10 +112,11 @@
 		};
 
 		sata@01c18000 {
-			compatible = "allwinner,sun4i-ahci";
+			compatible = "allwinner,sun4i-a10-ahci";
 			reg = <0x01c18000 0x1000>;
 			interrupts = <56>;
 			interrupt-parent = <&AINTC>;
+			status = "disabled";
 		};
 
 		UART0: serial@01c28000 {

Modified: head/sys/boot/fdt/dts/arm/sun7i-a20.dtsi
==============================================================================
--- head/sys/boot/fdt/dts/arm/sun7i-a20.dtsi	Fri Jul  3 12:09:05 2015	(r285089)
+++ head/sys/boot/fdt/dts/arm/sun7i-a20.dtsi	Fri Jul  3 14:11:01 2015	(r285090)
@@ -122,6 +122,7 @@
 			reg = <0x01c18000 0x1000>;
 			interrupts = <56>;
 			interrupt-parent = <&GIC>;
+			status = "disabled";
 		};
 
 		UART0: serial@01c28000 {

Modified: head/sys/dev/ahci/ahci.c
==============================================================================
--- head/sys/dev/ahci/ahci.c	Fri Jul  3 12:09:05 2015	(r285089)
+++ head/sys/dev/ahci/ahci.c	Fri Jul  3 14:11:01 2015	(r285090)
@@ -654,6 +654,7 @@ ahci_ch_attach(device_t dev)
 	ch->unit = (intptr_t)device_get_ivars(dev);
 	ch->caps = ctlr->caps;
 	ch->caps2 = ctlr->caps2;
+	ch->start = ctlr->ch_start;
 	ch->quirks = ctlr->quirks;
 	ch->vendorid = ctlr->vendorid;
 	ch->deviceid = ctlr->deviceid;
@@ -2114,6 +2115,10 @@ ahci_start(struct ahci_channel *ch, int 
 {
 	u_int32_t cmd;
 
+	/* Run the channel start callback, if any. */
+	if (ch->start)
+		ch->start(ch);
+
 	/* Clear SATA error register */
 	ATA_OUTL(ch->r_mem, AHCI_P_SERR, 0xFFFFFFFF);
 	/* Clear any interrupts pending on this channel */

Modified: head/sys/dev/ahci/ahci.h
==============================================================================
--- head/sys/dev/ahci/ahci.h	Fri Jul  3 12:09:05 2015	(r285089)
+++ head/sys/dev/ahci/ahci.h	Fri Jul  3 14:11:01 2015	(r285090)
@@ -427,6 +427,8 @@ struct ahci_channel {
 	int			pm_present;	/* PM presence reported */
 	int			fbs_enabled;	/* FIS-based switching enabled */
 
+	void			(*start)(struct ahci_channel *);
+
 	union ccb		*hold[AHCI_MAX_SLOTS];
 	struct ahci_slot	slot[AHCI_MAX_SLOTS];
 	uint32_t		oslots;		/* Occupied slots */
@@ -512,6 +514,7 @@ struct ahci_controller {
 		void			(*function)(void *);
 		void			*argument;
 	} interrupt[AHCI_MAX_PORTS];
+	void			(*ch_start)(struct ahci_channel *);
 };
 
 enum ahci_err_type {



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201507031411.t63EB2xQ035466>