Date: Sat, 26 Dec 2020 18:27:15 GMT From: Michal Meloun <mmel@FreeBSD.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org Subject: git: b9cbd68d1cbb - ARM: Enhance common Nvidia Tegra drivers by support for Tegra210 SoC. Message-ID: <202012261827.0BQIRFk4043704@gitrepo.freebsd.org>
next in thread | raw e-mail | index | archive | help
The branch main has been updated by mmel: URL: https://cgit.FreeBSD.org/src/commit/?id=b9cbd68d1cbbb21eade18182a797d5fa7d0dc110 commit b9cbd68d1cbbb21eade18182a797d5fa7d0dc110 Author: Michal Meloun <strejda@users.noreply.github.com> AuthorDate: 2018-01-04 11:50:12 +0000 Commit: Michal Meloun <mmel@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 ***
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202012261827.0BQIRFk4043704>