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-main
mailing list