git: b9cbd68d1cbb - ARM: Enhance common Nvidia Tegra drivers by support for Tegra210 SoC.

Michal Meloun mmel at FreeBSD.org
Sat Dec 26 18:27:15 UTC 2020


The branch main has been updated by mmel:

URL: https://cgit.FreeBSD.org/src/commit/?id=b9cbd68d1cbbb21eade18182a797d5fa7d0dc110

commit b9cbd68d1cbbb21eade18182a797d5fa7d0dc110
Author:     Michal Meloun <strejda at users.noreply.github.com>
AuthorDate: 2018-01-04 11:50:12 +0000
Commit:     Michal Meloun <mmel at FreeBSD.org>
CommitDate: 2020-12-26 18:13:10 +0000

    ARM: Enhance common Nvidia Tegra drivers by support for Tegra210 SoC.
    
    MFC after:      4 weeks
---
 sys/arm/nvidia/tegra_abpmisc.c              |    1 +
 sys/arm/nvidia/tegra_ahci.c                 |  431 ++--
 sys/arm/nvidia/tegra_efuse.c                |  226 +-
 sys/arm/nvidia/tegra_ehci.c                 |    2 +
 sys/arm/nvidia/tegra_gpio.c                 |    1 +
 sys/arm/nvidia/tegra_i2c.c                  |    2 +-
 sys/arm/nvidia/tegra_lic.c                  |    3 +-
 sys/arm/nvidia/tegra_mc.c                   |    7 +-
 sys/arm/nvidia/tegra_pcie.c                 |  258 +--
 sys/arm/nvidia/tegra_pmc.h                  |   16 +-
 sys/arm/nvidia/tegra_sdhci.c                |   42 +-
 sys/arm/nvidia/tegra_soctherm.c             |  328 ++-
 sys/arm/nvidia/tegra_uart.c                 |    5 +-
 sys/arm/nvidia/tegra_usbphy.c               |    2 +-
 sys/arm/nvidia/tegra_xhci.c                 |  299 ++-
 sys/contrib/dev/nvidia/tegra210_xusb.bin.uu | 2950 +++++++++++++++++++++++++++
 sys/modules/dtb/nvidia/Makefile             |   10 +-
 17 files changed, 4013 insertions(+), 570 deletions(-)

diff --git a/sys/arm/nvidia/tegra_abpmisc.c b/sys/arm/nvidia/tegra_abpmisc.c
index 0841af27f247..8a8e39862ca3 100644
--- a/sys/arm/nvidia/tegra_abpmisc.c
+++ b/sys/arm/nvidia/tegra_abpmisc.c
@@ -63,6 +63,7 @@ __FBSDID("$FreeBSD$");
 
 static struct ofw_compat_data compat_data[] = {
 	{"nvidia,tegra124-apbmisc",	1},
+	{"nvidia,tegra210-apbmisc",	1},
 	{NULL,				0}
 };
 
diff --git a/sys/arm/nvidia/tegra_ahci.c b/sys/arm/nvidia/tegra_ahci.c
index ceb2c9faadfc..725fc999a3a3 100644
--- a/sys/arm/nvidia/tegra_ahci.c
+++ b/sys/arm/nvidia/tegra_ahci.c
@@ -57,54 +57,14 @@ __FBSDID("$FreeBSD$");
 #include <arm/nvidia/tegra_efuse.h>
 #include <arm/nvidia/tegra_pmc.h>
 
-#define	AHCI_WR4(_sc, _r, _v)	bus_write_4((_sc)->ctlr.r_mem, (_r), (_v))
-#define	AHCI_RD4(_sc, _r)	bus_read_4((_sc)->ctlr.r_mem, (_r))
-#define	SATA_WR4(_sc, _r, _v)	bus_write_4((_sc)->sata_mem, (_r), (_v))
-#define	SATA_RD4(_sc, _r)	bus_read_4((_sc)->sata_mem, (_r))
-
-static struct ofw_compat_data compat_data[] = {
-	{"nvidia,tegra124-ahci", 	1},
-	{NULL,			0}
-};
-
-struct tegra_ahci_sc {
-	struct ahci_controller	ctlr;	/* Must be first */
-	device_t		dev;
-	struct resource		*sata_mem;
-	clk_t			clk_sata;
-	clk_t			clk_sata_oob;
-	clk_t			clk_pll_e;
-	clk_t			clk_cml;
-	hwreset_t		hwreset_sata;
-	hwreset_t		hwreset_sata_oob;
-	hwreset_t		hwreset_sata_cold;
-	regulator_t		supply_hvdd;
-	regulator_t		supply_vddio;
-	regulator_t		supply_avdd;
-	regulator_t		supply_target_5v;
-	regulator_t		supply_target_12v;
-	phy_t			phy;
-};
-
-struct sata_pad_calibration {
-	uint32_t gen1_tx_amp;
-	uint32_t gen1_tx_peak;
-	uint32_t gen2_tx_amp;
-	uint32_t gen2_tx_peak;
-};
-
-static const struct sata_pad_calibration tegra124_pad_calibration[] = {
-	{0x18, 0x04, 0x18, 0x0a},
-	{0x0e, 0x04, 0x14, 0x0a},
-	{0x0e, 0x07, 0x1a, 0x0e},
-	{0x14, 0x0e, 0x1a, 0x0e},
-};
 
 #define	SATA_CONFIGURATION			0x180
-#define	 SATA_CONFIGURATION_EN_FPCI			(1 << 0)
+#define  SATA_CONFIGURATION_CLK_OVERRIDE		(1U << 31)
+#define	 SATA_CONFIGURATION_EN_FPCI			(1  <<  0)
 
 #define	SATA_FPCI_BAR5				0x94
-#define	 SATA_FPCI_BAR5_START_SHIFT			4
+#define	 SATA_FPCI_BAR_START(x)				(((x) & 0xFFFFFFF) << 4)
+#define	 SATA_FPCI_BAR_ACCESS_TYPE			(1 << 0)
 
 #define	SATA_INTR_MASK				0x188
 #define	SATA_INTR_MASK_IP_INT_MASK			(1 << 16)
@@ -120,8 +80,46 @@ static const struct sata_pad_calibration tegra124_pad_calibration[] = {
 #define	T_SATA0_CFG_9				0x24
 #define	 T_SATA0_CFG_9_BASE_ADDRESS_SHIFT		13
 
+#define	T_SATA0_CFG_35				0x94
+#define	 T_SATA0_CFG_35_IDP_INDEX_MASK			(0x7ff << 2)
+#define	 T_SATA0_CFG_35_IDP_INDEX			(0x2a << 2)
+
+#define	T_SATA0_AHCI_IDP1			0x98
+#define	 T_SATA0_AHCI_IDP1_DATA				0x400040
+
+#define	T_SATA0_CFG_PHY_1			0x12c
+#define	 T_SATA0_CFG_PHY_1_PADS_IDDQ_EN			(1 << 23)
+#define	 T_SATA0_CFG_PHY_1_PAD_PLL_IDDQ_EN		(1 << 22)
+
+#define	T_SATA0_NVOOB				0x114
+#define	 T_SATA0_NVOOB_SQUELCH_FILTER_LENGTH_MASK	(0x3 << 26)
+#define	 T_SATA0_NVOOB_SQUELCH_FILTER_LENGTH		(0x3 << 26)
+#define	 T_SATA0_NVOOB_SQUELCH_FILTER_MODE_MASK		(0x3 << 24)
+#define	 T_SATA0_NVOOB_SQUELCH_FILTER_MODE		(0x1 << 24)
+#define	 T_SATA0_NVOOB_COMMA_CNT_MASK			(0xff << 16)
+#define	 T_SATA0_NVOOB_COMMA_CNT			(0x07 << 16)
+
+#define	T_SATA0_CFG_PHY				0x120
+#define	 T_SATA0_CFG_PHY_MASK_SQUELCH			(1 << 24)
+#define	 T_SATA0_CFG_PHY_USE_7BIT_ALIGN_DET_FOR_SPD	(1 << 11)
+
+#define	T_SATA0_CFG2NVOOB_2			0x134
+#define	 T_SATA0_CFG2NVOOB_2_COMWAKE_IDLE_CNT_LOW_MASK	(0x1ff << 18)
+#define	 T_SATA0_CFG2NVOOB_2_COMWAKE_IDLE_CNT_LOW	(0xc << 18)
+
 #define	T_SATA0_AHCI_HBA_CAP_BKDR		0x300
+#define	 T_SATA0_AHCI_HBA_CAP_BKDR_SNCQ			(1 << 30)
+#define	 T_SATA0_AHCI_HBA_CAP_BKDR_SUPP_PM		(1 << 17)
+#define	 T_SATA0_AHCI_HBA_CAP_BKDR_SALP			(1 << 26)
+#define	 T_SATA0_AHCI_HBA_CAP_BKDR_SLUMBER_ST_CAP	(1 << 14)
+#define	 T_SATA0_AHCI_HBA_CAP_BKDR_PARTIAL_ST_CAP	(1 << 13)
+
 #define	T_SATA0_BKDOOR_CC			0x4a4
+#define	 T_SATA0_BKDOOR_CC_CLASS_CODE_MASK		(0xffff << 16)
+#define	 T_SATA0_BKDOOR_CC_CLASS_CODE			(0x0106 << 16)
+#define	 T_SATA0_BKDOOR_CC_PROG_IF_MASK			(0xff << 8)
+#define	 T_SATA0_BKDOOR_CC_PROG_IF			(0x01 << 8)
+
 #define	T_SATA0_CFG_SATA			0x54c
 #define	 T_SATA0_CFG_SATA_BACKDOOR_PROG_IF_EN		(1 << 12)
 
@@ -146,6 +144,11 @@ static const struct sata_pad_calibration tegra124_pad_calibration[] = {
 #define	T_SATA0_CHX_PHY_CTRL11			0x6d0
 #define	 T_SATA0_CHX_PHY_CTRL11_GEN2_RX_EQ		(0x2800 << 16)
 
+#define T_SATA0_CHX_PHY_CTRL17			0x6e8
+#define T_SATA0_CHX_PHY_CTRL18			0x6ec
+#define T_SATA0_CHX_PHY_CTRL20			0x6f4
+#define T_SATA0_CHX_PHY_CTRL21			0x6f8
+
 #define	FUSE_SATA_CALIB				0x124
 #define	FUSE_SATA_CALIB_MASK			0x3
 
@@ -197,42 +200,109 @@ static const struct sata_pad_calibration tegra124_pad_calibration[] = {
 #define	 T_AHCI_PORT_BKDR_COLD_PRSN_DET			(1 <<  1)
 #define	 T_AHCI_PORT_BKDR_EXT_SATA_SUPP			(1 <<  0)
 
+/* AUX registers */
+#define	SATA_AUX_MISC_CNTL_1			0x008
+#define	 SATA_AUX_MISC_CNTL_1_DEVSLP_OVERRIDE		(1 << 17)
+#define	 SATA_AUX_MISC_CNTL_1_SDS_SUPPORT		(1 << 13)
+#define	 SATA_AUX_MISC_CNTL_1_DESO_SUPPORT		(1 << 15)
+
+#define	AHCI_WR4(_sc, _r, _v)	bus_write_4((_sc)->ctlr.r_mem, (_r), (_v))
+#define	AHCI_RD4(_sc, _r)	bus_read_4((_sc)->ctlr.r_mem, (_r))
+#define	SATA_WR4(_sc, _r, _v)	bus_write_4((_sc)->sata_mem, (_r), (_v))
+#define	SATA_RD4(_sc, _r)	bus_read_4((_sc)->sata_mem, (_r))
+
+struct sata_pad_calibration {
+	uint32_t gen1_tx_amp;
+	uint32_t gen1_tx_peak;
+	uint32_t gen2_tx_amp;
+	uint32_t gen2_tx_peak;
+};
+
+static const struct sata_pad_calibration tegra124_pad_calibration[] = {
+	{0x18, 0x04, 0x18, 0x0a},
+	{0x0e, 0x04, 0x14, 0x0a},
+	{0x0e, 0x07, 0x1a, 0x0e},
+	{0x14, 0x0e, 0x1a, 0x0e},
+};
+
+struct ahci_soc;
+struct tegra_ahci_sc {
+	struct ahci_controller	ctlr;	/* Must be first */
+	device_t		dev;
+	struct ahci_soc		*soc;
+	struct resource		*sata_mem;
+	struct resource		*aux_mem;
+	clk_t			clk_sata;
+	clk_t			clk_sata_oob;
+	clk_t			clk_pll_e;
+	clk_t			clk_cml;
+	hwreset_t		hwreset_sata;
+	hwreset_t		hwreset_sata_oob;
+	hwreset_t		hwreset_sata_cold;
+	regulator_t		regulators[16];		/* Safe maximum */
+	phy_t			phy;
+};
+
+struct ahci_soc {
+	char 	**regulator_names;
+	int	(*init)(struct tegra_ahci_sc *sc);
+};
+
+/* Tegra 124 config. */
+static char *tegra124_reg_names[] = {
+	"hvdd-supply",
+	"vddio-supply",
+	"avdd-supply",
+	"target-5v-supply",
+	"target-12v-supply",
+	NULL
+};
+
+static int tegra124_ahci_init(struct tegra_ahci_sc *sc);
+static struct ahci_soc tegra124_soc = {
+	.regulator_names = tegra124_reg_names,
+	.init = tegra124_ahci_init,
+};
+
+/* Tegra 210 config. */
+static char *tegra210_reg_names[] = {
+	NULL
+};
+
+static struct ahci_soc tegra210_soc = {
+	.regulator_names = tegra210_reg_names,
+};
+
+
+static struct ofw_compat_data compat_data[] = {
+	{"nvidia,tegra124-ahci", (uintptr_t)&tegra124_soc},
+	{"nvidia,tegra210-ahci", (uintptr_t)&tegra210_soc},
+	{NULL,			0}
+};
+
 static int
 get_fdt_resources(struct tegra_ahci_sc *sc, phandle_t node)
 {
-	int rv;
-
-	rv = regulator_get_by_ofw_property(sc->dev, 0, "hvdd-supply",
-	    &sc->supply_hvdd );
-	if (rv != 0) {
-		device_printf(sc->dev, "Cannot get 'hvdd' regulator\n");
-		return (ENXIO);
-	}
-	rv = regulator_get_by_ofw_property(sc->dev, 0, "vddio-supply",
-	    &sc->supply_vddio);
-	if (rv != 0) {
-		device_printf(sc->dev, "Cannot get 'vddio' regulator\n");
-		return (ENXIO);
-	}
-	rv = regulator_get_by_ofw_property(sc->dev, 0, "avdd-supply",
-	    &sc->supply_avdd);
-	if (rv != 0) {
-		device_printf(sc->dev, "Cannot get 'avdd' regulator\n");
-		return (ENXIO);
-	}
-	rv = regulator_get_by_ofw_property(sc->dev, 0, "target-5v-supply",
-	    &sc->supply_target_5v);
-	if (rv != 0) {
-		device_printf(sc->dev, "Cannot get 'target-5v' regulator\n");
-		return (ENXIO);
-	}
-	rv = regulator_get_by_ofw_property(sc->dev, 0, "target-12v-supply",
-	    &sc->supply_target_12v);
-	if (rv != 0) {
-		device_printf(sc->dev, "Cannot get 'target-12v' regulator\n");
-		return (ENXIO);
-	}
-
+	int i, rv;
+
+	/* Regulators. */
+	for (i = 0; sc->soc->regulator_names[i] != NULL; i++) {
+		if (i >= nitems(sc->regulators)) {
+			device_printf(sc->dev,
+			    "Too many regulators present in DT.\n");
+			return (EOVERFLOW);
+		}
+		rv = regulator_get_by_ofw_property(sc->dev, 0,
+		    sc->soc->regulator_names[i], sc->regulators + i);
+		if (rv != 0) {
+			device_printf(sc->dev,
+			    "Cannot get '%s' regulator\n",
+			    sc->soc->regulator_names[i]);
+			return (ENXIO);
+		}
+	}
+
+	/* Resets. */
 	rv = hwreset_get_by_ofw_name(sc->dev, 0, "sata", &sc->hwreset_sata );
 	if (rv != 0) {
 		device_printf(sc->dev, "Cannot get 'sata' reset\n");
@@ -251,12 +321,17 @@ get_fdt_resources(struct tegra_ahci_sc *sc, phandle_t node)
 		return (ENXIO);
 	}
 
+	/* Phy */
 	rv = phy_get_by_ofw_name(sc->dev, 0, "sata-0", &sc->phy);
 	if (rv != 0) {
-		device_printf(sc->dev, "Cannot get 'sata' phy\n");
-		return (ENXIO);
+		rv = phy_get_by_ofw_idx(sc->dev, 0, 0, &sc->phy);
+		if (rv != 0) {
+			device_printf(sc->dev, "Cannot get 'sata' phy\n");
+			return (ENXIO);
+		}
 	}
 
+	/* Clocks. */
 	rv = clk_get_by_ofw_name(sc->dev, 0, "sata", &sc->clk_sata);
 	if (rv != 0) {
 		device_printf(sc->dev, "Cannot get 'sata' clock\n");
@@ -267,50 +342,33 @@ get_fdt_resources(struct tegra_ahci_sc *sc, phandle_t node)
 		device_printf(sc->dev, "Cannot get 'sata oob' clock\n");
 		return (ENXIO);
 	}
+	/* These are optional */
 	rv = clk_get_by_ofw_name(sc->dev, 0, "cml1", &sc->clk_cml);
-	if (rv != 0) {
-		device_printf(sc->dev, "Cannot get 'cml1' clock\n");
-		return (ENXIO);
-	}
+	if (rv != 0)
+		sc->clk_cml = NULL;
+
 	rv = clk_get_by_ofw_name(sc->dev, 0, "pll_e", &sc->clk_pll_e);
-	if (rv != 0) {
-		device_printf(sc->dev, "Cannot get 'pll_e' clock\n");
-		return (ENXIO);
-	}
+	if (rv != 0)
+		sc->clk_pll_e = NULL;
 	return (0);
 }
 
 static int
 enable_fdt_resources(struct tegra_ahci_sc *sc)
 {
-	int rv;
+	int i, rv;
 
-	rv = regulator_enable(sc->supply_hvdd);
-	if (rv != 0) {
-		device_printf(sc->dev, "Cannot enable  'hvdd' regulator\n");
-		return (rv);
-	}
-	rv = regulator_enable(sc->supply_vddio);
-	if (rv != 0) {
-		device_printf(sc->dev, "Cannot enable  'vddio' regulator\n");
-		return (rv);
-	}
-	rv = regulator_enable(sc->supply_avdd);
-	if (rv != 0) {
-		device_printf(sc->dev, "Cannot enable  'avdd' regulator\n");
-		return (rv);
-	}
-	rv = regulator_enable(sc->supply_target_5v);
-	if (rv != 0) {
-		device_printf(sc->dev,
-		    "Cannot enable  'target-5v' regulator\n");
-		return (rv);
-	}
-	rv = regulator_enable(sc->supply_target_12v);
-	if (rv != 0) {
-		device_printf(sc->dev,
-		    "Cannot enable  'sc->target-12v' regulator\n");
-		return (rv);
+	/* Enable regulators. */
+	for (i = 0; i < nitems(sc->regulators); i++) {
+		if (sc->regulators[i] == NULL)
+			continue;
+		rv = regulator_enable(sc->regulators[i]);
+		if (rv != 0) {
+			device_printf(sc->dev,
+			    "Cannot enable '%s' regulator\n",
+			    sc->soc->regulator_names[i]);
+			return (rv);
+		}
 	}
 
 	/* Stop clocks */
@@ -346,15 +404,19 @@ enable_fdt_resources(struct tegra_ahci_sc *sc)
 		device_printf(sc->dev, "Cannot enable 'sata oob' clock\n");
 		return (rv);
 	}
-	rv = clk_enable(sc->clk_cml);
-	if (rv != 0) {
-		device_printf(sc->dev, "Cannot enable 'cml' clock\n");
-		return (rv);
+	if (sc->clk_cml != NULL) {
+		rv = clk_enable(sc->clk_cml);
+		if (rv != 0) {
+			device_printf(sc->dev, "Cannot enable 'cml' clock\n");
+			return (rv);
+		}
 	}
-	rv = clk_enable(sc->clk_pll_e);
-	if (rv != 0) {
-		device_printf(sc->dev, "Cannot enable 'pll e' clock\n");
-		return (rv);
+	if (sc->clk_pll_e != NULL) {
+		rv = clk_enable(sc->clk_pll_e);
+		if (rv != 0) {
+			device_printf(sc->dev, "Cannot enable 'pll e' clock\n");
+			return (rv);
+		}
 	}
 
 	rv = hwreset_deassert(sc->hwreset_sata_cold);
@@ -378,15 +440,11 @@ enable_fdt_resources(struct tegra_ahci_sc *sc)
 }
 
 static int
-tegra_ahci_ctrl_init(struct tegra_ahci_sc *sc)
+tegra124_ahci_init(struct tegra_ahci_sc *sc)
 {
 	uint32_t val;
 	const struct sata_pad_calibration *calib;
 
-	val = SATA_RD4(sc, SATA_CONFIGURATION);
-	val |= SATA_CONFIGURATION_EN_FPCI;
-	SATA_WR4(sc, SATA_CONFIGURATION, val);
-
 	/* Pad calibration. */
 	val = tegra_fuse_read_4(FUSE_SATA_CALIB);
 	calib = tegra124_pad_calibration + (val & FUSE_SATA_CALIB_MASK);
@@ -418,17 +476,118 @@ tegra_ahci_ctrl_init(struct tegra_ahci_sc *sc)
 
 	SATA_WR4(sc, SCFG_OFFSET + T_SATA0_INDEX, 0);
 
-	/* Set device ID. */
+	return (0);
+}
+
+static int
+tegra_ahci_ctrl_init(struct tegra_ahci_sc *sc)
+{
+	uint32_t val;
+	int rv;
+
+	/* Enable SATA MMIO. */
+	val = SATA_RD4(sc, SATA_FPCI_BAR5);
+	val &= ~SATA_FPCI_BAR_START(~0);
+	val |= SATA_FPCI_BAR_START(0x10000);
+	val |= SATA_FPCI_BAR_ACCESS_TYPE;
+	SATA_WR4(sc, SATA_FPCI_BAR5, val);
+
+	/* Enable FPCI access */
+	val = SATA_RD4(sc, SATA_CONFIGURATION);
+	val |= SATA_CONFIGURATION_EN_FPCI;
+	SATA_WR4(sc, SATA_CONFIGURATION, val);
+
+	/* Recommended electrical settings for phy */
+	SATA_WR4(sc, SCFG_OFFSET + T_SATA0_CHX_PHY_CTRL17, 0x55010000);
+	SATA_WR4(sc, SCFG_OFFSET + T_SATA0_CHX_PHY_CTRL18, 0x55010000);
+	SATA_WR4(sc, SCFG_OFFSET + T_SATA0_CHX_PHY_CTRL20, 0x1);
+	SATA_WR4(sc, SCFG_OFFSET + T_SATA0_CHX_PHY_CTRL21, 0x1);
+
+	/* SQUELCH and Gen3 */
+	val = SATA_RD4(sc, SCFG_OFFSET + T_SATA0_CFG_PHY);
+	val |= T_SATA0_CFG_PHY_MASK_SQUELCH;
+	val &= ~T_SATA0_CFG_PHY_USE_7BIT_ALIGN_DET_FOR_SPD;
+	SATA_WR4(sc, SCFG_OFFSET + T_SATA0_CFG_PHY, val);
+
+	val = SATA_RD4(sc, SCFG_OFFSET + T_SATA0_NVOOB);
+	val &= ~T_SATA0_NVOOB_COMMA_CNT_MASK;
+	val &= ~T_SATA0_NVOOB_SQUELCH_FILTER_LENGTH_MASK;
+	val &= ~T_SATA0_NVOOB_SQUELCH_FILTER_MODE_MASK;
+	val |= T_SATA0_NVOOB_COMMA_CNT;
+	val |= T_SATA0_NVOOB_SQUELCH_FILTER_LENGTH;
+	val |= T_SATA0_NVOOB_SQUELCH_FILTER_MODE;
+	SATA_WR4(sc, SCFG_OFFSET + T_SATA0_NVOOB, val);
+
+	 /* Setup COMWAKE_IDLE_CNT */
+	val = SATA_RD4(sc, SCFG_OFFSET + T_SATA0_CFG2NVOOB_2);
+	val &= ~T_SATA0_CFG2NVOOB_2_COMWAKE_IDLE_CNT_LOW_MASK;
+	val |= T_SATA0_CFG2NVOOB_2_COMWAKE_IDLE_CNT_LOW;
+	SATA_WR4(sc, SCFG_OFFSET + T_SATA0_CFG2NVOOB_2, val);
+
+	if (sc->soc->init != NULL) {
+		rv = sc->soc->init(sc);
+		if (rv != 0) {
+			device_printf(sc->dev,
+			    "SOC specific intialization failed: %d\n", rv);
+			return (rv);
+		}
+	}
+
+	/* Enable backdoor programming. */
 	val = SATA_RD4(sc, SCFG_OFFSET + T_SATA0_CFG_SATA);
 	val |= T_SATA0_CFG_SATA_BACKDOOR_PROG_IF_EN;
 	SATA_WR4(sc, SCFG_OFFSET + T_SATA0_CFG_SATA, val);
 
-	SATA_WR4(sc, SCFG_OFFSET + T_SATA0_BKDOOR_CC, 0x01060100);
-
+	/* Set device class and interface */
+	val = SATA_RD4(sc, SCFG_OFFSET + T_SATA0_BKDOOR_CC);
+	val &= ~T_SATA0_BKDOOR_CC_CLASS_CODE_MASK;
+	val &= ~T_SATA0_BKDOOR_CC_PROG_IF_MASK;
+	val |= T_SATA0_BKDOOR_CC_CLASS_CODE;
+	val |= T_SATA0_BKDOOR_CC_PROG_IF;
+	SATA_WR4(sc, SCFG_OFFSET + T_SATA0_BKDOOR_CC, val);
+
+	/* Enable LPM capabilities  */
+	val = SATA_RD4(sc, SCFG_OFFSET +  T_SATA0_AHCI_HBA_CAP_BKDR);
+	val |= T_SATA0_AHCI_HBA_CAP_BKDR_PARTIAL_ST_CAP;
+	val |= T_SATA0_AHCI_HBA_CAP_BKDR_SLUMBER_ST_CAP;
+	val |= T_SATA0_AHCI_HBA_CAP_BKDR_SALP;
+	val |= T_SATA0_AHCI_HBA_CAP_BKDR_SUPP_PM;
+	SATA_WR4(sc, SCFG_OFFSET + T_SATA0_AHCI_HBA_CAP_BKDR, val);
+
+	/* Disable backdoor programming. */
 	val = SATA_RD4(sc, SCFG_OFFSET + T_SATA0_CFG_SATA);
 	val &= ~T_SATA0_CFG_SATA_BACKDOOR_PROG_IF_EN;
 	SATA_WR4(sc, SCFG_OFFSET + T_SATA0_CFG_SATA, val);
 
+	/* SATA Second Level Clock Gating */
+	val = SATA_RD4(sc, SCFG_OFFSET + T_SATA0_CFG_35);
+	val &= ~T_SATA0_CFG_35_IDP_INDEX_MASK;
+	val |= T_SATA0_CFG_35_IDP_INDEX;
+	SATA_WR4(sc, SCFG_OFFSET + T_SATA0_CFG_35, val);
+
+	SATA_WR4(sc, SCFG_OFFSET + T_SATA0_AHCI_IDP1, 0x400040);
+
+	val = SATA_RD4(sc, SCFG_OFFSET + T_SATA0_CFG_PHY_1);
+	val |= T_SATA0_CFG_PHY_1_PADS_IDDQ_EN;
+	val |= T_SATA0_CFG_PHY_1_PAD_PLL_IDDQ_EN;
+	SATA_WR4(sc, SCFG_OFFSET + T_SATA0_CFG_PHY_1, val);
+
+	/*
+	 * Indicate Sata only has the capability to enter DevSleep
+	 * from slumber link.
+	 */
+	if (sc->aux_mem != NULL) {
+		val = bus_read_4(sc->aux_mem, SATA_AUX_MISC_CNTL_1);
+		val |= SATA_AUX_MISC_CNTL_1_DESO_SUPPORT;
+		bus_write_4(sc->aux_mem, SATA_AUX_MISC_CNTL_1, val);
+	}
+
+	/* Enable IPFS Clock Gating */
+	val = SATA_RD4(sc, SCFG_OFFSET + SATA_CONFIGURATION);
+	val &= ~SATA_CONFIGURATION_CLK_OVERRIDE;
+	SATA_WR4(sc, SCFG_OFFSET + SATA_CONFIGURATION, val);
+
+
 	/* Enable IO & memory access, bus master mode */
 	val = SATA_RD4(sc, SCFG_OFFSET + T_SATA0_CFG_1);
 	val |= T_SATA0_CFG_1_IO_SPACE;
@@ -437,10 +596,8 @@ tegra_ahci_ctrl_init(struct tegra_ahci_sc *sc)
 	val |= T_SATA0_CFG_1_SERR;
 	SATA_WR4(sc, SCFG_OFFSET + T_SATA0_CFG_1, val);
 
-	/* SATA MMIO. */
-	SATA_WR4(sc, SATA_FPCI_BAR5, 0x10000 << SATA_FPCI_BAR5_START_SHIFT);
 	/* AHCI bar */
-	SATA_WR4(sc,  SCFG_OFFSET + T_SATA0_CFG_9,
+	SATA_WR4(sc, SCFG_OFFSET + T_SATA0_CFG_9,
 	    0x08000 << T_SATA0_CFG_9_BASE_ADDRESS_SHIFT);
 
 	/* Unmask  interrupts. */
@@ -513,6 +670,8 @@ tegra_ahci_attach(device_t dev)
 	sc->dev = dev;
 	ctlr = &sc->ctlr;
 	node = ofw_bus_get_node(dev);
+	sc->soc = (struct ahci_soc *)ofw_bus_search_compatible(dev,
+	    compat_data)->ocd_data;
 
 	ctlr->r_rid = 0;
 	ctlr->r_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
@@ -527,6 +686,12 @@ tegra_ahci_attach(device_t dev)
 		rv = ENXIO;
 		goto fail;
 	}
+
+	/* Aux is optionall */
+	rid = 2;
+	sc->aux_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
+	    &rid, RF_ACTIVE);
+
 	rv = get_fdt_resources(sc, node);
 	if (rv != 0) {
 		device_printf(sc->dev, "Failed to allocate FDT resource(s)\n");
diff --git a/sys/arm/nvidia/tegra_efuse.c b/sys/arm/nvidia/tegra_efuse.c
index 253ae8b6cf36..e18fd9c3a274 100644
--- a/sys/arm/nvidia/tegra_efuse.c
+++ b/sys/arm/nvidia/tegra_efuse.c
@@ -49,23 +49,20 @@ __FBSDID("$FreeBSD$");
 
 #include <arm/nvidia/tegra_efuse.h>
 
-#define	RD4(_sc, _r)	bus_read_4((_sc)->mem_res, (_sc)->fuse_begin + (_r))
-
-static struct ofw_compat_data compat_data[] = {
-	{"nvidia,tegra124-efuse",	1},
-	{NULL,			0}
-};
+#define FUSES_START	0x100
+#define	RD4(_sc, _r)	bus_read_4((_sc)->mem_res, (FUSES_START + (_r)))
 
+struct efuse_soc;
 struct tegra_efuse_softc {
 	device_t		dev;
 	struct resource		*mem_res;
 
-	int			fuse_begin;
+	struct efuse_soc 	*soc;
 	clk_t			clk;
-	hwreset_t			reset;
+	hwreset_t		reset;
 };
-struct tegra_efuse_softc *dev_sc;
 
+struct tegra_efuse_softc *dev_sc;
 struct tegra_sku_info tegra_sku_info;
 static char *tegra_rev_name[] = {
 	[TEGRA_REVISION_UNKNOWN] = "unknown",
@@ -76,18 +73,30 @@ static char *tegra_rev_name[] = {
 	[TEGRA_REVISION_A04]     = "A04",
 };
 
-/* Tegra30 and later */
-#define	FUSE_VENDOR_CODE	0x100
-#define	FUSE_FAB_CODE		0x104
-#define	FUSE_LOT_CODE_0		0x108
-#define	FUSE_LOT_CODE_1		0x10c
-#define	FUSE_WAFER_ID		0x110
-#define	FUSE_X_COORDINATE	0x114
-#define	FUSE_Y_COORDINATE	0x118
+struct efuse_soc {
+	void	(*init)(struct tegra_efuse_softc *sc,
+		    struct tegra_sku_info *sku);
+};
 
-/* ---------------------- Tegra 124 specific code & data --------------- */
-#define	TEGRA124_FUSE_BEGIN		0x100
+static void tegra124_init(struct tegra_efuse_softc *sc,
+    struct tegra_sku_info *sku);
+struct efuse_soc tegra124_efuse_soc = {
+	.init = tegra124_init,
+};
+
+static void tegra210_init(struct tegra_efuse_softc *sc,
+    struct tegra_sku_info *sku);
+struct efuse_soc tegra210_efuse_soc = {
+	.init = tegra210_init,
+};
 
+static struct ofw_compat_data compat_data[] = {
+	{"nvidia,tegra124-efuse", (intptr_t)&tegra124_efuse_soc},
+	{"nvidia,tegra210-efuse", (intptr_t)&tegra210_efuse_soc},
+	{NULL,			0}
+};
+
+/* ---------------------- Tegra 124 specific code & data --------------- */
 #define	TEGRA124_CPU_PROCESS_CORNERS	2
 #define	TEGRA124_GPU_PROCESS_CORNERS	2
 #define	TEGRA124_SOC_PROCESS_CORNERS	2
@@ -128,12 +137,13 @@ static uint32_t tegra124_soc_process_speedos[][TEGRA124_SOC_PROCESS_CORNERS] =
 	{0,	UINT_MAX},
 };
 
+
 static void
 tegra124_rev_sku_to_speedo_ids(struct tegra_efuse_softc *sc,
     struct tegra_sku_info *sku, int *threshold)
 {
 
-	/* Assign to default */
+	/* Set default */
 	sku->cpu_speedo_id = 0;
 	sku->soc_speedo_id = 0;
 	sku->gpu_speedo_id = 0;
@@ -180,7 +190,7 @@ tegra124_rev_sku_to_speedo_ids(struct tegra_efuse_softc *sc,
 }
 
 static void
-tegra124_init_speedo(struct tegra_efuse_softc *sc, struct tegra_sku_info *sku)
+tegra124_init(struct tegra_efuse_softc *sc, struct tegra_sku_info *sku)
 {
 	int i, threshold;
 
@@ -221,9 +231,175 @@ tegra124_init_speedo(struct tegra_efuse_softc *sc, struct tegra_sku_info *sku)
 	sku->gpu_process_id = i;
 
 }
-
 /* ----------------- End of Tegra 124 specific code & data --------------- */
 
+/* -------------------- Tegra 201 specific code & data ------------------- */
+#define	TEGRA210_CPU_PROCESS_CORNERS	2
+#define	TEGRA210_GPU_PROCESS_CORNERS	2
+#define	TEGRA210_SOC_PROCESS_CORNERS	3
+
+#define	TEGRA210_FUSE_SKU_INFO		0x010
+#define	TEGRA210_FUSE_CPU_SPEEDO_0	0x014
+#define	TEGRA210_FUSE_CPU_IDDQ		0x018
+#define	TEGRA210_FUSE_FT_REV		0x028
+#define	TEGRA210_FUSE_CPU_SPEEDO_1	0x02c
+#define	TEGRA210_FUSE_CPU_SPEEDO_2	0x030
+#define	TEGRA210_FUSE_SOC_SPEEDO_0	0x034
+#define	TEGRA210_FUSE_SOC_SPEEDO_1	0x038
+#define	TEGRA210_FUSE_SOC_SPEEDO_2	0x03c
+#define	TEGRA210_FUSE_SOC_IDDQ		0x040
+#define	TEGRA210_FUSE_GPU_IDDQ		0x128
+#define	TEGRA210_FUSE_SPARE		0x270
+
+enum {
+	TEGRA210_THRESHOLD_INDEX_0,
+	TEGRA210_THRESHOLD_INDEX_1,
+	TEGRA210_THRESHOLD_INDEX_COUNT,
+};
+
+static uint32_t tegra210_cpu_process_speedos[][TEGRA210_CPU_PROCESS_CORNERS] =
+{
+	{2119, UINT_MAX},
+	{2119, UINT_MAX},
+};
+
+static uint32_t tegra210_gpu_process_speedos[][TEGRA210_GPU_PROCESS_CORNERS] =
+{
+	{UINT_MAX, UINT_MAX},
+	{UINT_MAX, UINT_MAX},
+};
+
+static uint32_t tegra210_soc_process_speedos[][TEGRA210_SOC_PROCESS_CORNERS] =
+{
+	{1950, 2100, UINT_MAX},
+	{1950, 2100, UINT_MAX},
+};
+
+static uint32_t
+tegra210_get_speedo_revision(struct tegra_efuse_softc *sc)
+{
+	uint32_t reg;
+	uint32_t val;
+
+	val = 0;
+
+	/* Revision i encoded in spare fields */
+	reg = RD4(sc, TEGRA210_FUSE_SPARE + 2 * 4);
+	val |=  (reg & 1) << 0;
+	reg = RD4(sc, TEGRA210_FUSE_SPARE + 3 * 4);
+	val |=  (reg & 1) << 1;
+	reg = RD4(sc, TEGRA210_FUSE_SPARE + 4 * 4);
+	val |=  (reg & 1) << 2;
+
+	return (val);
+}
+
+
+static void
+tegra210_rev_sku_to_speedo_ids(struct tegra_efuse_softc *sc,
+    struct tegra_sku_info *sku, int speedo_rev, int *threshold)
+{
+
+	/* Set defaults */
+	sku->cpu_speedo_id = 0;
+	sku->soc_speedo_id = 0;
+	sku->gpu_speedo_id = 0;
+	*threshold = TEGRA210_THRESHOLD_INDEX_0;
+
+	switch (sku->sku_id) {
+	case 0x00: /* Eng sku */
+	case 0x01: /* Eng sku */
+	case 0x07:
+	case 0x17:
+	case 0x27:
+		/* Use defaults */
+		if (speedo_rev >= 2)
+			sku->gpu_speedo_id = 1;
+		break;
+	case 0x13:
+		if (speedo_rev >= 2)
+			sku->gpu_speedo_id = 1;
+		sku->cpu_speedo_id = 1;
+		break;
+
+	default:
+		device_printf(sc->dev, " Unknown SKU ID %d\n", sku->sku_id);
+		break;
+	}
+}
+
+
+static void
+tegra210_init(struct tegra_efuse_softc *sc, struct tegra_sku_info *sku)
+{
+	int i, threshold, speedo_rev;
+	uint32_t cpu_speedo[3], soc_speedo[3];
+	uint32_t cpu_iddq, soc_iddq, gpu_iddq;
+
+	cpu_speedo[0] = RD4(sc, TEGRA210_FUSE_CPU_SPEEDO_0);
+	cpu_speedo[1] = RD4(sc, TEGRA210_FUSE_CPU_SPEEDO_1);
+	cpu_speedo[2] = RD4(sc, TEGRA210_FUSE_CPU_SPEEDO_2);
+	soc_speedo[0] = RD4(sc, TEGRA210_FUSE_SOC_SPEEDO_0);
+	soc_speedo[1] = RD4(sc, TEGRA210_FUSE_SOC_SPEEDO_1);
+	soc_speedo[2] = RD4(sc, TEGRA210_FUSE_SOC_SPEEDO_2);
+
+
+	sku->cpu_iddq_value = RD4(sc, TEGRA210_FUSE_CPU_IDDQ);
+	sku->soc_iddq_value = RD4(sc, TEGRA210_FUSE_SOC_IDDQ);
+	sku->gpu_iddq_value = RD4(sc, TEGRA210_FUSE_GPU_IDDQ);
+
+	cpu_iddq = RD4(sc, TEGRA210_FUSE_CPU_IDDQ) * 4;
+	soc_iddq = RD4(sc, TEGRA210_FUSE_SOC_IDDQ) * 4;
+	gpu_iddq = RD4(sc, TEGRA210_FUSE_GPU_IDDQ) * 5;
+
+	speedo_rev = tegra210_get_speedo_revision(sc);
+device_printf(sc->dev, " Speedo revision: %u\n", speedo_rev);
+
+	if (speedo_rev >= 3) {
+		sku->cpu_speedo_value = cpu_speedo[0];
+		sku->gpu_speedo_value = cpu_speedo[2];
+		sku->soc_speedo_value = soc_speedo[0];
+	} else if (speedo_rev == 2) {
+		sku->cpu_speedo_value =
+		    (-1938 + (1095 * cpu_speedo[0] / 100)) / 10;
+		sku->gpu_speedo_value =
+		    (-1662 + (1082 * cpu_speedo[2] / 100)) / 10;
+		sku->soc_speedo_value =
+		    ( -705 + (1037 * soc_speedo[0] / 100)) / 10;
+	} else {
+		sku->cpu_speedo_value = 2100;
+		sku->gpu_speedo_value = cpu_speedo[2] - 75;
+		sku->soc_speedo_value = 1900;
+	}
+
+	tegra210_rev_sku_to_speedo_ids(sc, sku, speedo_rev, &threshold);
+
+	for (i = 0; i < TEGRA210_SOC_PROCESS_CORNERS; i++) {
+		if (sku->soc_speedo_value <
+			tegra210_soc_process_speedos[threshold][i])
+			break;
+	}
+	sku->soc_process_id = i;
+
+	for (i = 0; i < TEGRA210_CPU_PROCESS_CORNERS; i++) {
+		if (sku->cpu_speedo_value <
+			tegra210_cpu_process_speedos[threshold][i])
+				break;
+	}
+	sku->cpu_process_id = i;
+
+	for (i = 0; i < TEGRA210_GPU_PROCESS_CORNERS; i++) {
+		if (sku->gpu_speedo_value <
+			tegra210_gpu_process_speedos[threshold][i])
+			break;
+	}
+	sku->gpu_process_id = i;
+
+}
+
+/* ----------------- End of Tegra 210 specific code & data --------------- */
+
+
 uint32_t
 tegra_fuse_read_4(int addr) {
 	if (dev_sc == NULL)
@@ -274,6 +450,8 @@ tegra_efuse_attach(device_t dev)
 	sc = device_get_softc(dev);
 	sc->dev = dev;
 	node = ofw_bus_get_node(dev);
+	sc->soc = (struct efuse_soc *)ofw_bus_search_compatible(dev,
+	    compat_data)->ocd_data;
 
 	/* Get the memory resource for the register mapping. */
 	rid = 0;
@@ -307,9 +485,7 @@ tegra_efuse_attach(device_t dev)
 		goto fail;
 	}
 
-	/* Tegra124 specific init. */
-	sc->fuse_begin = TEGRA124_FUSE_BEGIN;
-	tegra124_init_speedo(sc, &tegra_sku_info);
+	sc->soc->init(sc, &tegra_sku_info);
 
 	dev_sc = sc;
 
diff --git a/sys/arm/nvidia/tegra_ehci.c b/sys/arm/nvidia/tegra_ehci.c
index de0ebd8801a6..058cbe7c5fb9 100644
--- a/sys/arm/nvidia/tegra_ehci.c
+++ b/sys/arm/nvidia/tegra_ehci.c
@@ -65,8 +65,10 @@ __FBSDID("$FreeBSD$");
 
 /* Compatible devices. */
 #define	TEGRA124_EHCI		1
+#define	TEGRA210_EHCI		2
 static struct ofw_compat_data compat_data[] = {
 	{"nvidia,tegra124-ehci",	(uintptr_t)TEGRA124_EHCI},
+	{"nvidia,tegra210-ehci",	(uintptr_t)TEGRA210_EHCI},
 	{NULL,		 	0},
 };
 
diff --git a/sys/arm/nvidia/tegra_gpio.c b/sys/arm/nvidia/tegra_gpio.c
index 3cd30ad0dc30..17a7ac2a9fb7 100644
--- a/sys/arm/nvidia/tegra_gpio.c
+++ b/sys/arm/nvidia/tegra_gpio.c
@@ -137,6 +137,7 @@ struct tegra_gpio_softc {
 
 static struct ofw_compat_data compat_data[] = {
 	{"nvidia,tegra124-gpio", 1},
+	{"nvidia,tegra210-gpio", 1},
 	{NULL,			0}
 };
 
diff --git a/sys/arm/nvidia/tegra_i2c.c b/sys/arm/nvidia/tegra_i2c.c
index 6e5285808bc7..02db5218b883 100644
--- a/sys/arm/nvidia/tegra_i2c.c
+++ b/sys/arm/nvidia/tegra_i2c.c
@@ -205,6 +205,7 @@ __FBSDID("$FreeBSD$");
 
 static struct ofw_compat_data compat_data[] = {
 	{"nvidia,tegra124-i2c",	1},
+	{"nvidia,tegra210-i2c",	1},
 	{NULL,			0}
 };
 enum tegra_i2c_xfer_type {
@@ -678,7 +679,6 @@ tegra_i2c_attach(device_t dev)
 	    sizeof(sc->bus_freq));
 	if (rv != sizeof(sc->bus_freq)) {
 		sc->bus_freq = 100000;
-		goto fail;
 	}
 
 	/* Request maximum frequency for I2C block 136MHz (408MHz / 3). */
diff --git a/sys/arm/nvidia/tegra_lic.c b/sys/arm/nvidia/tegra_lic.c
index 0ac293f4962d..d457bd4b0f73 100644
--- a/sys/arm/nvidia/tegra_lic.c
+++ b/sys/arm/nvidia/tegra_lic.c
@@ -38,7 +38,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/kernel.h>
 #include <sys/rman.h>
 
-#include <machine/fdt.h>
+#include <machine/bus.h>
 #include <machine/intr.h>
 #include <machine/resource.h>
 
@@ -78,6 +78,7 @@ static struct resource_spec lic_spec[] = {
 
 static struct ofw_compat_data compat_data[] = {
 	{"nvidia,tegra124-ictlr", 	1},
+	{"nvidia,tegra210-ictlr", 	1},
 	{NULL,				0}
 };
 
diff --git a/sys/arm/nvidia/tegra_mc.c b/sys/arm/nvidia/tegra_mc.c
index 7612e7bbff6a..7ff480b55dbd 100644
--- a/sys/arm/nvidia/tegra_mc.c
+++ b/sys/arm/nvidia/tegra_mc.c
@@ -110,6 +110,7 @@ __FBSDID("$FreeBSD$");
 
 static struct ofw_compat_data compat_data[] = {
 	{"nvidia,tegra124-mc",	1},
+	{"nvidia,tegra210-mc",	1},
 	{NULL,			0}
 };
 
@@ -132,7 +133,7 @@ static char *smmu_err_tbl[16] = {
 	"Security carveout",	/*  4 */
 	"reserved",		/*  5 */
 	"Invalid SMMU page",	/*  6 */
-	"reserved",	/*  7 */
+	"reserved",		/*  7 */
 };
 
 static void
@@ -173,8 +174,8 @@ tegra_mc_intr(void *arg)
 		err = RD4(sc, MC_ERR_STATUS);
*** 4533 LINES SKIPPED ***


More information about the dev-commits-src-all mailing list