Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 11 Sep 2017 22:28:38 +0000 (UTC)
From:      Ian Lepore <ian@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org
Subject:   svn commit: r323468 - in stable/11/sys/arm: conf freescale/imx
Message-ID:  <201709112228.v8BMScMV065607@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: ian
Date: Mon Sep 11 22:28:38 2017
New Revision: 323468
URL: https://svnweb.freebsd.org/changeset/base/323468

Log:
  MFC r321938, r322015
  
  r321938:
  Fix the interface to imx_iomux_gpr_get/set().  The functions were defined
  as taking a register number, and that would get multiplied by 4 to make
  a register address.  But the header file that consumers have to reference
  this stuff publishes register addresses, not numbers.  So now everything
  works in terms of register addresses.
  
  Note that the HDMI init code was writing into the wrong register before
  this change.  Apparently whatever it wrote to was harmless, and apparently
  HDMI was working because uboot had set up the right bits.
  
  r322015:
  Add an ahci driver for imx6.
  
  This was submitted by Rogiel Sulzbach (thank you!) but has a few last-minute
  changes by me, mostly where the code interfaces to my still-utterly-deficient
  imx6_ccm clocks implementation.  So blame me for any mistakes.
  
  Submitted by:	Rogiel Sulzbach <rogiel@rogiel.com>
  Differential Revision:	https://reviews.freebsd.org/D11177

Added:
  stable/11/sys/arm/freescale/imx/imx6_ahci.c
     - copied unchanged from r322015, head/sys/arm/freescale/imx/imx6_ahci.c
Modified:
  stable/11/sys/arm/conf/IMX6
  stable/11/sys/arm/freescale/imx/files.imx6
  stable/11/sys/arm/freescale/imx/imx6_ccm.c
  stable/11/sys/arm/freescale/imx/imx6_ccmreg.h
  stable/11/sys/arm/freescale/imx/imx_ccmvar.h
  stable/11/sys/arm/freescale/imx/imx_iomux.c
  stable/11/sys/arm/freescale/imx/imx_iomuxreg.h
  stable/11/sys/arm/freescale/imx/imx_iomuxvar.h
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/sys/arm/conf/IMX6
==============================================================================
--- stable/11/sys/arm/conf/IMX6	Mon Sep 11 22:21:15 2017	(r323467)
+++ stable/11/sys/arm/conf/IMX6	Mon Sep 11 22:28:38 2017	(r323468)
@@ -78,6 +78,9 @@ device		da			# Direct Access (disks)
 device		cd			# CD
 device		pass			# Passthrough device (direct ATA/SCSI access)
 
+# ATA controllers
+device 		ahci			# AHCI-compatible SATA controllers
+
 # USB support
 device		ehci			# OHCI USB interface
 device		usb			# USB Bus (required)

Modified: stable/11/sys/arm/freescale/imx/files.imx6
==============================================================================
--- stable/11/sys/arm/freescale/imx/files.imx6	Mon Sep 11 22:21:15 2017	(r323467)
+++ stable/11/sys/arm/freescale/imx/files.imx6	Mon Sep 11 22:28:38 2017	(r323468)
@@ -25,6 +25,7 @@ arm/freescale/imx/imx_i2c.c		optional fsliic
 arm/freescale/imx/imx6_sdma.c		optional sdma
 arm/freescale/imx/imx6_audmux.c		optional sound
 arm/freescale/imx/imx6_ssi.c		optional sound
+arm/freescale/imx/imx6_ahci.c		optional ahci
 
 arm/arm/hdmi_if.m			optional hdmi
 arm/freescale/imx/imx6_hdmi.c		optional hdmi

Copied: stable/11/sys/arm/freescale/imx/imx6_ahci.c (from r322015, head/sys/arm/freescale/imx/imx6_ahci.c)
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ stable/11/sys/arm/freescale/imx/imx6_ahci.c	Mon Sep 11 22:28:38 2017	(r323468, copy of r322015, head/sys/arm/freescale/imx/imx6_ahci.c)
@@ -0,0 +1,358 @@
+/*-
+ * Copyright (c) 2017 Rogiel Sulzbach <rogiel@allogica.com>
+ * 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.
+ */
+
+#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 <machine/bus.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <dev/ahci/ahci.h>
+#include <arm/freescale/imx/imx_iomuxreg.h>
+#include <arm/freescale/imx/imx_iomuxvar.h>
+#include <arm/freescale/imx/imx_ccmvar.h>
+
+#define	SATA_TIMER1MS				0x000000e0
+
+#define	SATA_P0PHYCR				0x00000178
+#define	  SATA_P0PHYCR_CR_READ			  (1 << 19)
+#define	  SATA_P0PHYCR_CR_WRITE			  (1 << 18)
+#define	  SATA_P0PHYCR_CR_CAP_DATA		  (1 << 17)
+#define	  SATA_P0PHYCR_CR_CAP_ADDR		  (1 << 16)
+#define	  SATA_P0PHYCR_CR_DATA_IN(v)		  ((v) & 0xffff)
+
+#define	SATA_P0PHYSR				0x0000017c
+#define	  SATA_P0PHYSR_CR_ACK			  (1 << 18)
+#define	  SATA_P0PHYSR_CR_DATA_OUT(v)		  ((v) & 0xffff)
+
+/* phy registers */
+#define	SATA_PHY_CLOCK_RESET			0x7f3f
+#define	  SATA_PHY_CLOCK_RESET_RST		  (1 << 0)
+
+#define	SATA_PHY_LANE0_OUT_STAT			0x2003
+#define	  SATA_PHY_LANE0_OUT_STAT_RX_PLL_STATE	  (1 << 1)
+
+static int
+imx6_ahci_phy_ctrl(struct ahci_controller* sc, uint32_t bitmask, bool on)
+{
+	uint32_t v;
+	int timeout;
+	bool state;
+
+	v = ATA_INL(sc->r_mem, SATA_P0PHYCR);
+	if (on) {
+		v |= bitmask;
+	} else {
+		v &= ~bitmask;
+	}
+	ATA_OUTL(sc->r_mem, SATA_P0PHYCR, v);
+
+	for (timeout = 5000; timeout > 0; --timeout) {
+		v = ATA_INL(sc->r_mem, SATA_P0PHYSR);
+		state = (v & SATA_P0PHYSR_CR_ACK) == SATA_P0PHYSR_CR_ACK;
+		if(state == on) {
+			break;
+		}
+		DELAY(100);
+	}
+
+	if (timeout > 0) {
+		return (0);
+	}
+
+	return (ETIMEDOUT);
+}
+
+static int
+imx6_ahci_phy_addr(struct ahci_controller* sc, uint32_t addr)
+{
+	int error;
+
+	DELAY(100);
+
+	ATA_OUTL(sc->r_mem, SATA_P0PHYCR, addr);
+
+	error = imx6_ahci_phy_ctrl(sc, SATA_P0PHYCR_CR_CAP_ADDR, true);
+	if (error != 0) {
+		device_printf(sc->dev,
+		    "%s: timeout on SATA_P0PHYCR_CR_CAP_ADDR=1\n",
+		    __FUNCTION__);
+		return (error);
+	}
+
+	error = imx6_ahci_phy_ctrl(sc, SATA_P0PHYCR_CR_CAP_ADDR, false);
+	if (error != 0) {
+		device_printf(sc->dev,
+		    "%s: timeout on SATA_P0PHYCR_CR_CAP_ADDR=0\n",
+		    __FUNCTION__);
+		return (error);
+	}
+
+	return (0);
+}
+
+static int
+imx6_ahci_phy_write(struct ahci_controller* sc, uint32_t addr,
+		    uint16_t data)
+{
+	int error;
+
+	error = imx6_ahci_phy_addr(sc, addr);
+	if (error != 0) {
+		device_printf(sc->dev, "%s: error on imx6_ahci_phy_addr\n",
+		    __FUNCTION__);
+		return (error);
+	}
+
+	ATA_OUTL(sc->r_mem, SATA_P0PHYCR, data);
+
+	error = imx6_ahci_phy_ctrl(sc, SATA_P0PHYCR_CR_CAP_DATA, true);
+	if (error != 0) {
+		device_printf(sc->dev,
+		    "%s: error on SATA_P0PHYCR_CR_CAP_DATA=1\n", __FUNCTION__);
+		return (error);
+	}
+	if (imx6_ahci_phy_ctrl(sc, SATA_P0PHYCR_CR_CAP_DATA, false) != 0) {
+		device_printf(sc->dev,
+		    "%s: error on SATA_P0PHYCR_CR_CAP_DATA=0\n", __FUNCTION__);
+		return (error);
+	}
+
+	if ((addr == SATA_PHY_CLOCK_RESET) && data) {
+		/* we can't check ACK after RESET */
+		ATA_OUTL(sc->r_mem, SATA_P0PHYCR,
+		    SATA_P0PHYCR_CR_DATA_IN(data) | SATA_P0PHYCR_CR_WRITE);
+		return (0);
+	}
+
+	error = imx6_ahci_phy_ctrl(sc, SATA_P0PHYCR_CR_WRITE, true);
+	if (error != 0) {
+		device_printf(sc->dev, "%s: error on SATA_P0PHYCR_CR_WRITE=1\n",
+		    __FUNCTION__);
+		return (error);
+	}
+
+	error = imx6_ahci_phy_ctrl(sc, SATA_P0PHYCR_CR_WRITE, false);
+	if (error != 0) {
+		device_printf(sc->dev, "%s: error on SATA_P0PHYCR_CR_WRITE=0\n",
+		    __FUNCTION__);
+		return (error);
+	}
+
+	return (0);
+}
+
+static int
+imx6_ahci_phy_read(struct ahci_controller* sc, uint32_t addr, uint16_t* val)
+{
+	int error;
+	uint32_t v;
+
+	error = imx6_ahci_phy_addr(sc, addr);
+	if (error != 0) {
+		device_printf(sc->dev, "%s: error on imx6_ahci_phy_addr\n",
+		    __FUNCTION__);
+		return (error);
+	}
+
+	error = imx6_ahci_phy_ctrl(sc, SATA_P0PHYCR_CR_READ, true);
+	if (error != 0) {
+		device_printf(sc->dev, "%s: error on SATA_P0PHYCR_CR_READ=1\n",
+		    __FUNCTION__);
+		return (error);
+	}
+
+	v = ATA_INL(sc->r_mem, SATA_P0PHYSR);
+
+	error = imx6_ahci_phy_ctrl(sc, SATA_P0PHYCR_CR_READ, false);
+	if (error != 0) {
+		device_printf(sc->dev, "%s: error on SATA_P0PHYCR_CR_READ=0\n",
+		    __FUNCTION__);
+		return (error);
+	}
+
+	*val = SATA_P0PHYSR_CR_DATA_OUT(v);
+	return (0);
+}
+
+static int
+imx6_ahci_probe(device_t dev)
+{
+
+	if (!ofw_bus_status_okay(dev)) {
+		return (ENXIO);
+	}
+
+	if (!ofw_bus_is_compatible(dev, "fsl,imx6q-ahci")) {
+		return (ENXIO);
+	}
+	device_set_desc(dev, "i.MX6 Integrated AHCI controller");
+
+	return (BUS_PROBE_DEFAULT);
+}
+
+static int
+imx6_ahci_attach(device_t dev)
+{
+	struct ahci_controller* ctlr;
+	uint16_t pllstat;
+	uint32_t v;
+	int error, timeout;
+
+	ctlr = device_get_softc(dev);
+
+	/* Power up the controller and phy. */
+	error = imx6_ccm_sata_enable();
+	if (error != 0) {
+		device_printf(dev, "error enabling controller and phy\n");
+		return (error);
+	}
+
+	ctlr->vendorid = 0;
+	ctlr->deviceid = 0;
+	ctlr->subvendorid = 0;
+	ctlr->subdeviceid = 0;
+	ctlr->numirqs = 1;
+	ctlr->r_rid = 0;
+	if ((ctlr->r_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
+	    &ctlr->r_rid, RF_ACTIVE)) == NULL) {
+		return (ENXIO);
+	}
+
+	v = imx_iomux_gpr_get(IOMUX_GPR13);
+	/* Clear out existing values; these numbers are bitmasks. */
+	v &= ~(IOMUX_GPR13_SATA_PHY_8(7) 	|
+	       IOMUX_GPR13_SATA_PHY_7(0x1f) 	|
+	       IOMUX_GPR13_SATA_PHY_6(7) 	|
+	       IOMUX_GPR13_SATA_SPEED(1) 	|
+	       IOMUX_GPR13_SATA_PHY_5(1) 	|
+	       IOMUX_GPR13_SATA_PHY_4(7) 	|
+	       IOMUX_GPR13_SATA_PHY_3(0xf) 	|
+	       IOMUX_GPR13_SATA_PHY_2(0x1f) 	|
+	       IOMUX_GPR13_SATA_PHY_1(1) 	|
+	       IOMUX_GPR13_SATA_PHY_0(1));
+	/* setting */
+	v |= IOMUX_GPR13_SATA_PHY_8(5) 		|     /* Rx 3.0db */
+	     IOMUX_GPR13_SATA_PHY_7(0x12) 	|     /* Rx SATA2m */
+	     IOMUX_GPR13_SATA_PHY_6(3) 		|     /* Rx DPLL mode */
+	     IOMUX_GPR13_SATA_SPEED(1) 		|     /* 3.0GHz */
+	     IOMUX_GPR13_SATA_PHY_5(0) 		|     /* SpreadSpectram */
+	     IOMUX_GPR13_SATA_PHY_4(4) 		|     /* Tx Attenuation 9/16 */
+	     IOMUX_GPR13_SATA_PHY_3(0) 		|     /* Tx Boost 0db */
+	     IOMUX_GPR13_SATA_PHY_2(0x11) 	|     /* Tx Level 1.104V */
+	     IOMUX_GPR13_SATA_PHY_1(1);               /* PLL clock enable */
+	imx_iomux_gpr_set(IOMUX_GPR13, v);
+
+	/* phy reset */
+	error = imx6_ahci_phy_write(ctlr, SATA_PHY_CLOCK_RESET,
+	    SATA_PHY_CLOCK_RESET_RST);
+	if (error != 0) {
+		device_printf(dev, "cannot reset PHY\n");
+		goto fail;
+	}
+
+	for (timeout = 50; timeout > 0; --timeout) {
+		DELAY(100);
+		error = imx6_ahci_phy_read(ctlr, SATA_PHY_LANE0_OUT_STAT,
+		    &pllstat);
+		if (error != 0) {
+			device_printf(dev, "cannot read LANE0 status\n");
+			goto fail;
+		}
+		if (pllstat & SATA_PHY_LANE0_OUT_STAT_RX_PLL_STATE) {
+			break;
+		}
+	}
+	if (timeout <= 0) {
+		device_printf(dev, "time out reading LANE0 status\n");
+		error = ETIMEDOUT;
+		goto fail;
+	}
+
+	/* Support Staggered Spin-up */
+	v = ATA_INL(ctlr->r_mem, AHCI_CAP);
+	ATA_OUTL(ctlr->r_mem, AHCI_CAP, v | AHCI_CAP_SSS);
+
+	/* Ports Implemented. must set 1 */
+	v = ATA_INL(ctlr->r_mem, AHCI_PI);
+	ATA_OUTL(ctlr->r_mem, AHCI_PI, v | (1 << 0));
+
+	/* set 1ms-timer = AHB clock / 1000 */
+	ATA_OUTL(ctlr->r_mem, SATA_TIMER1MS,
+		 imx_ccm_ahb_hz() / 1000);
+
+	/*
+	 * Note: ahci_attach will release ctlr->r_mem on errors automatically
+	 */
+	return (ahci_attach(dev));
+
+fail:
+	bus_release_resource(dev, SYS_RES_MEMORY, ctlr->r_rid, ctlr->r_mem);
+	return (error);
+}
+
+static int
+imx6_ahci_detach(device_t dev)
+{
+
+	return (ahci_detach(dev));
+}
+
+devclass_t ahci_devclass;
+
+static device_method_t imx6_ahci_ata_methods[] = {
+	/* device probe, attach and detach methods */
+	DEVMETHOD(device_probe,  imx6_ahci_probe),
+	DEVMETHOD(device_attach, imx6_ahci_attach),
+	DEVMETHOD(device_detach, imx6_ahci_detach),
+
+	/* ahci bus methods */
+	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",
+	imx6_ahci_ata_methods,
+	sizeof(struct ahci_controller)
+};
+
+DRIVER_MODULE(ahci, simplebus, ahci_ata_driver, ahci_devclass, 0, 0);

Modified: stable/11/sys/arm/freescale/imx/imx6_ccm.c
==============================================================================
--- stable/11/sys/arm/freescale/imx/imx6_ccm.c	Mon Sep 11 22:21:15 2017	(r323467)
+++ stable/11/sys/arm/freescale/imx/imx6_ccm.c	Mon Sep 11 22:28:38 2017	(r323468)
@@ -314,6 +314,41 @@ imx_ccm_usbphy_enable(device_t _phydev)
 #endif
 }
 
+int
+imx6_ccm_sata_enable(void)
+{
+	uint32_t v;
+	int timeout;
+
+	/* Un-gate the sata controller. */
+	WR4(ccm_sc, CCM_CCGR5, RD4(ccm_sc, CCM_CCGR5) | CCGR5_SATA);
+
+	/* Power up the PLL that feeds ENET/SATA/PCI phys, wait for lock. */
+	v = RD4(ccm_sc, CCM_ANALOG_PLL_ENET);
+	v &= ~CCM_ANALOG_PLL_ENET_POWERDOWN;
+	WR4(ccm_sc, CCM_ANALOG_PLL_ENET, v);
+
+	for (timeout = 100000; timeout > 0; timeout--) {
+		if (RD4(ccm_sc, CCM_ANALOG_PLL_ENET) &
+		   CCM_ANALOG_PLL_ENET_LOCK) {
+			break;
+		}
+	}
+	if (timeout <= 0) {
+		return ETIMEDOUT;
+	}
+
+	/* Enable the PLL, and enable its 100mhz output. */
+	v |= CCM_ANALOG_PLL_ENET_ENABLE;
+	v &= ~CCM_ANALOG_PLL_ENET_BYPASS;
+	WR4(ccm_sc, CCM_ANALOG_PLL_ENET, v);
+
+	v |= CCM_ANALOG_PLL_ENET_ENABLE_100M;
+	WR4(ccm_sc, CCM_ANALOG_PLL_ENET, v);
+
+	return 0;
+}
+
 uint32_t
 imx_ccm_ipg_hz(void)
 {

Modified: stable/11/sys/arm/freescale/imx/imx6_ccmreg.h
==============================================================================
--- stable/11/sys/arm/freescale/imx/imx6_ccmreg.h	Mon Sep 11 22:21:15 2017	(r323467)
+++ stable/11/sys/arm/freescale/imx/imx6_ccmreg.h	Mon Sep 11 22:28:38 2017	(r323468)
@@ -116,6 +116,7 @@
 #define		CCGR4_PL301_MX6QPER1_BCH	(0x3 << 12)
 #define		CCGR4_PL301_MX6QPER2_MAIN	(0x3 << 14)
 #define	CCM_CCGR5			0x07C
+#define		CCGR5_SATA        		(0x3 << 4)
 #define		CCGR5_SDMA			(0x3 << 6)
 #define		CCGR5_SSI1			(0x3 << 18)
 #define		CCGR5_SSI2			(0x3 << 20)
@@ -129,5 +130,12 @@
 #define		CCGR6_USDHC3			(0x3 << 6)
 #define		CCGR6_USDHC4			(0x3 << 8)
 #define	CCM_CMEOR			0x088
+
+#define CCM_ANALOG_PLL_ENET			0x000040e0
+#define  CCM_ANALOG_PLL_ENET_LOCK		(1u << 31)
+#define  CCM_ANALOG_PLL_ENET_ENABLE_100M	(1u << 20)	/* SATA */
+#define  CCM_ANALOG_PLL_ENET_BYPASS		(1u << 16)
+#define  CCM_ANALOG_PLL_ENET_ENABLE		(1u << 13)	/* Ether */
+#define  CCM_ANALOG_PLL_ENET_POWERDOWN		(1u << 12)
 
 #endif

Modified: stable/11/sys/arm/freescale/imx/imx_ccmvar.h
==============================================================================
--- stable/11/sys/arm/freescale/imx/imx_ccmvar.h	Mon Sep 11 22:21:15 2017	(r323467)
+++ stable/11/sys/arm/freescale/imx/imx_ccmvar.h	Mon Sep 11 22:28:38 2017	(r323468)
@@ -54,6 +54,7 @@ void imx_ccm_usbphy_enable(device_t _phydev);
 void imx_ccm_ssi_configure(device_t _ssidev);
 void imx_ccm_hdmi_enable(void);
 void imx_ccm_ipu_enable(int ipu);
+int  imx6_ccm_sata_enable(void);
 
 /* Routines to get and set the arm clock root divisor register. */
 uint32_t imx_ccm_get_cacrr(void);

Modified: stable/11/sys/arm/freescale/imx/imx_iomux.c
==============================================================================
--- stable/11/sys/arm/freescale/imx/imx_iomux.c	Mon Sep 11 22:21:15 2017	(r323467)
+++ stable/11/sys/arm/freescale/imx/imx_iomux.c	Mon Sep 11 22:28:38 2017	(r323468)
@@ -71,7 +71,7 @@
 struct iomux_softc {
 	device_t	dev;
 	struct resource	*mem_res;
-	u_int		last_gpreg;
+	u_int		last_gpregaddr;
 };
 
 static struct iomux_softc *iomux_sc;
@@ -214,19 +214,19 @@ iomux_attach(device_t dev)
 
 	switch (imx_soc_type()) {
 	case IMXSOC_51:
-		sc->last_gpreg = 1;
+		sc->last_gpregaddr = 1 * sizeof(uint32_t);
 		break;
 	case IMXSOC_53:
-		sc->last_gpreg = 2;
+		sc->last_gpregaddr = 2 * sizeof(uint32_t);
 		break;
 	case IMXSOC_6DL:
 	case IMXSOC_6S:
 	case IMXSOC_6SL:
 	case IMXSOC_6Q:
-		sc->last_gpreg = 13;
+		sc->last_gpregaddr = 13 * sizeof(uint32_t);
 		break;
 	case IMXSOC_6UL:
-		sc->last_gpreg = 14;
+		sc->last_gpregaddr = 14 * sizeof(uint32_t);
 		break;
 	default:
 		device_printf(dev, "Unknown SoC type\n");
@@ -262,45 +262,48 @@ iomux_attach(device_t dev)
 }
 
 uint32_t
-imx_iomux_gpr_get(u_int regnum)
+imx_iomux_gpr_get(u_int regaddr)
 {
 	struct iomux_softc * sc;
 
 	sc = iomux_sc;
 	KASSERT(sc != NULL, ("%s called before attach", __FUNCTION__));
-	KASSERT(regnum >= 0 && regnum <= sc->last_gpreg, 
-	    ("%s bad regnum %u, max %u", __FUNCTION__, regnum, sc->last_gpreg));
+	KASSERT(regaddr >= 0 && regaddr <= sc->last_gpregaddr, 
+	    ("%s bad regaddr %u, max %u", __FUNCTION__, regaddr,
+	    sc->last_gpregaddr));
 
-	return (RD4(iomux_sc, regnum * 4));
+	return (RD4(iomux_sc, regaddr));
 }
 
 void
-imx_iomux_gpr_set(u_int regnum, uint32_t val)
+imx_iomux_gpr_set(u_int regaddr, uint32_t val)
 {
 	struct iomux_softc * sc;
 
 	sc = iomux_sc;
 	KASSERT(sc != NULL, ("%s called before attach", __FUNCTION__));
-	KASSERT(regnum >= 0 && regnum <= sc->last_gpreg, 
-	    ("%s bad regnum %u, max %u", __FUNCTION__, regnum, sc->last_gpreg));
+	KASSERT(regaddr >= 0 && regaddr <= sc->last_gpregaddr, 
+	    ("%s bad regaddr %u, max %u", __FUNCTION__, regaddr,
+	    sc->last_gpregaddr));
 
-	WR4(iomux_sc, regnum * 4, val);
+	WR4(iomux_sc, regaddr, val);
 }
 
 void
-imx_iomux_gpr_set_masked(u_int regnum, uint32_t clrbits, uint32_t setbits)
+imx_iomux_gpr_set_masked(u_int regaddr, uint32_t clrbits, uint32_t setbits)
 {
 	struct iomux_softc * sc;
 	uint32_t val;
 
 	sc = iomux_sc;
 	KASSERT(sc != NULL, ("%s called before attach", __FUNCTION__));
-	KASSERT(regnum >= 0 && regnum <= sc->last_gpreg, 
-	    ("%s bad regnum %u, max %u", __FUNCTION__, regnum, sc->last_gpreg));
+	KASSERT(regaddr >= 0 && regaddr <= sc->last_gpregaddr, 
+	    ("%s bad regaddr %u, max %u", __FUNCTION__, regaddr,
+	    sc->last_gpregaddr));
 
-	val = RD4(iomux_sc, regnum * 4);
+	val = RD4(iomux_sc, regaddr * 4);
 	val = (val & ~clrbits) | setbits;
-	WR4(iomux_sc, regnum * 4, val);
+	WR4(iomux_sc, regaddr, val);
 }
 
 static device_method_t imx_iomux_methods[] = {

Modified: stable/11/sys/arm/freescale/imx/imx_iomuxreg.h
==============================================================================
--- stable/11/sys/arm/freescale/imx/imx_iomuxreg.h	Mon Sep 11 22:21:15 2017	(r323467)
+++ stable/11/sys/arm/freescale/imx/imx_iomuxreg.h	Mon Sep 11 22:28:38 2017	(r323468)
@@ -29,14 +29,33 @@
 #ifndef	IMX_IOMUXREG_H
 #define	IMX_IOMUXREG_H
 
-#define	IOMUXC_GPR0	0x00
-#define	IOMUXC_GPR1	0x04
-#define	IOMUXC_GPR2	0x08
-#define	IOMUXC_GPR3	0x0C
-#define		IOMUXC_GPR3_HDMI_MASK		(3 << 2)
-#define		IOMUXC_GPR3_HDMI_IPU1_DI0	(0 << 2)
-#define		IOMUXC_GPR3_HDMI_IPU1_DI1	(1 << 2)
-#define		IOMUXC_GPR3_HDMI_IPU2_DI0	(2 << 2)
-#define		IOMUXC_GPR3_HDMI_IPU2_DI1	(3 << 2)
+#define	IMX_IOMUXREG_LOWEST_SET_BIT(__mask) ((((__mask) - 1) & (__mask)) ^ (__mask))
+#define	IMX_IOMUXREG_SHIFTIN(__x, __mask) ((__x) * IMX_IOMUXREG_LOWEST_SET_BIT(__mask))
+
+#define IMX_IOMUXREG_BIT(n) (1 << (n))
+#define	IMX_IOMUXREG_BITS(__m, __n)	\
+	((IMX_IOMUXREG_BIT(MAX((__m), (__n)) + 1) - 1) ^ (IMX_IOMUXREG_BIT(MIN((__m), (__n))) - 1))
+
+#define	IOMUXC_GPR0			0x00
+#define	IOMUXC_GPR1			0x04
+#define	IOMUXC_GPR2			0x08
+#define	IOMUXC_GPR3			0x0C
+#define	  IOMUXC_GPR3_HDMI_MASK		  (3 << 2)
+#define	  IOMUXC_GPR3_HDMI_IPU1_DI0	  (0 << 2)
+#define	  IOMUXC_GPR3_HDMI_IPU1_DI1	  (1 << 2)
+#define	  IOMUXC_GPR3_HDMI_IPU2_DI0	  (2 << 2)
+#define	  IOMUXC_GPR3_HDMI_IPU2_DI1	  (3 << 2)
+
+#define IOMUX_GPR13			0x34
+#define	  IOMUX_GPR13_SATA_PHY_8(n)	  IMX_IOMUXREG_SHIFTIN(n, IMX_IOMUXREG_BITS(26, 24))
+#define	  IOMUX_GPR13_SATA_PHY_7(n)	  IMX_IOMUXREG_SHIFTIN(n, IMX_IOMUXREG_BITS(23, 19))
+#define	  IOMUX_GPR13_SATA_PHY_6(n)	  IMX_IOMUXREG_SHIFTIN(n, IMX_IOMUXREG_BITS(18, 16))
+#define	  IOMUX_GPR13_SATA_SPEED(n)	  IMX_IOMUXREG_SHIFTIN(n, (1 << 15))
+#define	  IOMUX_GPR13_SATA_PHY_5(n)	  IMX_IOMUXREG_SHIFTIN(n, (1 << 14))
+#define	  IOMUX_GPR13_SATA_PHY_4(n)	  IMX_IOMUXREG_SHIFTIN(n, IMX_IOMUXREG_BITS(13, 11))
+#define	  IOMUX_GPR13_SATA_PHY_3(n)	  IMX_IOMUXREG_SHIFTIN(n, IMX_IOMUXREG_BITS(10, 7))
+#define	  IOMUX_GPR13_SATA_PHY_2(n)	  IMX_IOMUXREG_SHIFTIN(n, IMX_IOMUXREG_BITS(6, 2))
+#define	  IOMUX_GPR13_SATA_PHY_1(n)	  IMX_IOMUXREG_SHIFTIN(n, (1 << 1))
+#define	  IOMUX_GPR13_SATA_PHY_0(n)	  IMX_IOMUXREG_SHIFTIN(n, (1 << 0))
 
 #endif

Modified: stable/11/sys/arm/freescale/imx/imx_iomuxvar.h
==============================================================================
--- stable/11/sys/arm/freescale/imx/imx_iomuxvar.h	Mon Sep 11 22:21:15 2017	(r323467)
+++ stable/11/sys/arm/freescale/imx/imx_iomuxvar.h	Mon Sep 11 22:28:38 2017	(r323468)
@@ -42,8 +42,8 @@ u_int    iomux_get_pad_config(u_int pin);
  * with IO pin assignments or pad control.  These functions let other soc level
  * code manipulate these values.
  */
-uint32_t imx_iomux_gpr_get(u_int regnum);
-void     imx_iomux_gpr_set(u_int regnum, uint32_t val);
-void     imx_iomux_gpr_set_masked(u_int regnum, uint32_t clrbits, uint32_t setbits);
+uint32_t imx_iomux_gpr_get(u_int regaddr);
+void     imx_iomux_gpr_set(u_int regaddr, uint32_t val);
+void     imx_iomux_gpr_set_masked(u_int regaddr, uint32_t clrbits, uint32_t setbits);
 
 #endif



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