ARM: Enhance common Nvidia Tegra drivers by support for Tegra210 SoC.
MFC after: 4 weeks
This commit is contained in:
parent
9bc6c7219a
commit
b9cbd68d1c
@ -63,6 +63,7 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
static struct ofw_compat_data compat_data[] = {
|
||||
{"nvidia,tegra124-apbmisc", 1},
|
||||
{"nvidia,tegra210-apbmisc", 1},
|
||||
{NULL, 0}
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
int i, 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);
|
||||
/* 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");
|
||||
|
@ -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);
|
||||
};
|
||||
|
||||
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_FUSE_BEGIN 0x100
|
||||
|
||||
#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;
|
||||
|
||||
|
@ -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},
|
||||
};
|
||||
|
||||
|
@ -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}
|
||||
};
|
||||
|
||||
|
@ -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). */
|
||||
|
@ -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}
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
addr = RD4(sc, MC_ERR_STATUS);
|
||||
addr |= (uint64_t)(MC_ERR_ADR_HI(err)) << 32;
|
||||
printf(" at 0x%012llX [%s %s %s] - %s error.\n",
|
||||
addr,
|
||||
printf(" at 0x%012jX [%s %s %s] - %s error.\n",
|
||||
(uintmax_t)addr,
|
||||
stat & MC_ERR_SWAP ? "Swap, " : "",
|
||||
stat & MC_ERR_SECURITY ? "Sec, " : "",
|
||||
stat & MC_ERR_RW ? "Write" : "Read",
|
||||
|
@ -179,28 +179,36 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
#define AFI_PEXBIAS_CTRL 0x168
|
||||
|
||||
/* FPCI Address space */
|
||||
#define FPCI_MAP_IO 0xfdfc000000ULL
|
||||
#define FPCI_MAP_TYPE0_CONFIG 0xfdfc000000ULL
|
||||
#define FPCI_MAP_TYPE1_CONFIG 0xfdff000000ULL
|
||||
#define FPCI_MAP_EXT_TYPE0_CONFIG 0xfe00000000ULL
|
||||
#define FPCI_MAP_EXT_TYPE1_CONFIG 0xfe10000000ULL
|
||||
|
||||
/* Configuration space */
|
||||
#define RP_VEND_XP 0x00000F00
|
||||
#define RP_VEND_XP_DL_UP (1 << 30)
|
||||
#define RP_VEND_XP 0x0F00
|
||||
#define RP_VEND_XP_DL_UP (1 << 30)
|
||||
|
||||
#define RP_PRIV_MISC 0x00000FE0
|
||||
#define RP_PRIV_MISC_PRSNT_MAP_EP_PRSNT (0xE << 0)
|
||||
#define RP_PRIV_MISC_PRSNT_MAP_EP_ABSNT (0xF << 0)
|
||||
#define RP_VEND_CTL2 0x0fa8
|
||||
#define RP_VEND_CTL2_PCA_ENABLE (1 << 7)
|
||||
|
||||
#define RP_PRIV_MISC 0x0FE0
|
||||
#define RP_PRIV_MISC_PRSNT_MAP_EP_PRSNT (0xE << 0)
|
||||
#define RP_PRIV_MISC_PRSNT_MAP_EP_ABSNT (0xF << 0)
|
||||
|
||||
#define RP_LINK_CONTROL_STATUS 0x0090
|
||||
#define RP_LINK_CONTROL_STATUS_DL_LINK_ACTIVE 0x20000000
|
||||
#define RP_LINK_CONTROL_STATUS_LINKSTAT_MASK 0x3fff0000
|
||||
|
||||
/* PADS space */
|
||||
#define PADS_REFCLK_CFG0 0x000c8
|
||||
#define PADS_REFCLK_CFG1 0x000cc
|
||||
|
||||
#define RP_LINK_CONTROL_STATUS 0x00000090
|
||||
#define RP_LINK_CONTROL_STATUS_DL_LINK_ACTIVE 0x20000000
|
||||
#define RP_LINK_CONTROL_STATUS_LINKSTAT_MASK 0x3fff0000
|
||||
|
||||
/* Wait 50 ms (per port) for link. */
|
||||
#define TEGRA_PCIE_LINKUP_TIMEOUT 50000
|
||||
|
||||
/* FPCI Address space */
|
||||
#define FPCI_MAP_IO 0xFDFC000000ULL
|
||||
#define FPCI_MAP_TYPE0_CONFIG 0xFDFC000000ULL
|
||||
#define FPCI_MAP_TYPE1_CONFIG 0xFDFF000000ULL
|
||||
#define FPCI_MAP_EXT_TYPE0_CONFIG 0xFE00000000ULL
|
||||
#define FPCI_MAP_EXT_TYPE1_CONFIG 0xFE10000000ULL
|
||||
|
||||
#define TEGRA_PCIB_MSI_ENABLE
|
||||
|
||||
#define DEBUG
|
||||
@ -224,7 +232,7 @@ __FBSDID("$FreeBSD$");
|
||||
#define PCI_CFG_FUN(fun) (((fun) & 0x07) << 8)
|
||||
#define PCI_CFG_BASE_REG(reg) ((reg) & 0xff)
|
||||
|
||||
#define PADS_WR4(_sc, _r, _v) bus_write_4((_sc)-pads_mem_res, (_r), (_v))
|
||||
#define PADS_WR4(_sc, _r, _v) bus_write_4((_sc)->pads_mem_res, (_r), (_v))
|
||||
#define PADS_RD4(_sc, _r) bus_read_4((_sc)->pads_mem_res, (_r))
|
||||
#define AFI_WR4(_sc, _r, _v) bus_write_4((_sc)->afi_mem_res, (_r), (_v))
|
||||
#define AFI_RD4(_sc, _r) bus_read_4((_sc)->afi_mem_res, (_r))
|
||||
@ -246,10 +254,57 @@ static struct {
|
||||
{AFI_MSI_AXI_BAR_ST, AFI_MSI_FPCI_BAR_ST, AFI_MSI_BAR_SZ}, /* MSI 9 */
|
||||
};
|
||||
|
||||
|
||||
struct pcie_soc {
|
||||
char **regulator_names;
|
||||
bool cml_clk;
|
||||
bool pca_enable;
|
||||
uint32_t pads_refclk_cfg0;
|
||||
uint32_t pads_refclk_cfg1;
|
||||
};
|
||||
|
||||
/* Tegra 124 config. */
|
||||
static char *tegra124_reg_names[] = {
|
||||
"avddio-pex-supply",
|
||||
"dvddio-pex-supply",
|
||||
"avdd-pex-pll-supply",
|
||||
"hvdd-pex-supply",
|
||||
"hvdd-pex-pll-e-supply",
|
||||
"vddio-pex-ctl-supply",
|
||||
"avdd-pll-erefe-supply",
|
||||
NULL
|
||||
};
|
||||
|
||||
static struct pcie_soc tegra124_soc = {
|
||||
.regulator_names = tegra124_reg_names,
|
||||
.cml_clk = true,
|
||||
.pca_enable = false,
|
||||
.pads_refclk_cfg0 = 0x44ac44ac,
|
||||
};
|
||||
|
||||
/* Tegra 210 config. */
|
||||
static char *tegra210_reg_names[] = {
|
||||
"avdd-pll-uerefe-supply",
|
||||
"hvddio-pex-supply",
|
||||
"dvddio-pex-supply",
|
||||
"dvdd-pex-pll-supply",
|
||||
"hvdd-pex-pll-e-supply",
|
||||
"vddio-pex-ctl-supply",
|
||||
NULL
|
||||
};
|
||||
|
||||
static struct pcie_soc tegra210_soc = {
|
||||
.regulator_names = tegra210_reg_names,
|
||||
.cml_clk = true,
|
||||
.pca_enable = true,
|
||||
.pads_refclk_cfg0 = 0x90b890b8,
|
||||
};
|
||||
|
||||
/* Compatible devices. */
|
||||
static struct ofw_compat_data compat_data[] = {
|
||||
{"nvidia,tegra124-pcie", 1},
|
||||
{NULL, 0},
|
||||
{"nvidia,tegra124-pcie", (uintptr_t)&tegra124_soc},
|
||||
{"nvidia,tegra210-pcie", (uintptr_t)&tegra210_soc},
|
||||
{NULL, 0},
|
||||
};
|
||||
|
||||
#define TEGRA_FLAG_MSI_USED 0x0001
|
||||
@ -277,6 +332,7 @@ struct tegra_pcib_port {
|
||||
struct tegra_pcib_softc {
|
||||
struct ofw_pci_softc ofw_pci;
|
||||
device_t dev;
|
||||
struct pcie_soc *soc;
|
||||
struct mtx mtx;
|
||||
struct resource *pads_mem_res;
|
||||
struct resource *afi_mem_res;
|
||||
@ -297,13 +353,7 @@ struct tegra_pcib_softc {
|
||||
hwreset_t hwreset_pex;
|
||||
hwreset_t hwreset_afi;
|
||||
hwreset_t hwreset_pcie_x;
|
||||
regulator_t supply_avddio_pex;
|
||||
regulator_t supply_dvddio_pex;
|
||||
regulator_t supply_avdd_pex_pll;
|
||||
regulator_t supply_hvdd_pex;
|
||||
regulator_t supply_hvdd_pex_pll_e;
|
||||
regulator_t supply_vddio_pex_ctl;
|
||||
regulator_t supply_avdd_pll_erefe;
|
||||
regulator_t regulators[16]; /* Safe maximum */
|
||||
|
||||
vm_offset_t msi_page; /* VA of MSI page */
|
||||
bus_addr_t cfg_base_addr; /* base address of config */
|
||||
@ -801,7 +851,7 @@ tegra_pcib_pex_ctrl(struct tegra_pcib_softc *sc, int port)
|
||||
static int
|
||||
tegra_pcib_enable_fdt_resources(struct tegra_pcib_softc *sc)
|
||||
{
|
||||
int rv;
|
||||
int i, rv;
|
||||
|
||||
rv = hwreset_assert(sc->hwreset_pcie_x);
|
||||
if (rv != 0) {
|
||||
@ -821,48 +871,17 @@ tegra_pcib_enable_fdt_resources(struct tegra_pcib_softc *sc)
|
||||
|
||||
tegra_powergate_power_off(TEGRA_POWERGATE_PCX);
|
||||
|
||||
/* Power supplies. */
|
||||
rv = regulator_enable(sc->supply_avddio_pex);
|
||||
if (rv != 0) {
|
||||
device_printf(sc->dev,
|
||||
"Cannot enable 'avddio_pex' regulator\n");
|
||||
return (rv);
|
||||
}
|
||||
rv = regulator_enable(sc->supply_dvddio_pex);
|
||||
if (rv != 0) {
|
||||
device_printf(sc->dev,
|
||||
"Cannot enable 'dvddio_pex' regulator\n");
|
||||
return (rv);
|
||||
}
|
||||
rv = regulator_enable(sc->supply_avdd_pex_pll);
|
||||
if (rv != 0) {
|
||||
device_printf(sc->dev,
|
||||
"Cannot enable 'avdd-pex-pll' regulator\n");
|
||||
return (rv);
|
||||
}
|
||||
rv = regulator_enable(sc->supply_hvdd_pex);
|
||||
if (rv != 0) {
|
||||
device_printf(sc->dev,
|
||||
"Cannot enable 'hvdd-pex-supply' regulator\n");
|
||||
return (rv);
|
||||
}
|
||||
rv = regulator_enable(sc->supply_hvdd_pex_pll_e);
|
||||
if (rv != 0) {
|
||||
device_printf(sc->dev,
|
||||
"Cannot enable 'hvdd-pex-pll-e-supply' regulator\n");
|
||||
return (rv);
|
||||
}
|
||||
rv = regulator_enable(sc->supply_vddio_pex_ctl);
|
||||
if (rv != 0) {
|
||||
device_printf(sc->dev,
|
||||
"Cannot enable 'vddio-pex-ctl' regulator\n");
|
||||
return (rv);
|
||||
}
|
||||
rv = regulator_enable(sc->supply_avdd_pll_erefe);
|
||||
if (rv != 0) {
|
||||
device_printf(sc->dev,
|
||||
"Cannot enable 'avdd-pll-erefe-supply' regulator\n");
|
||||
return (rv);
|
||||
/* 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);
|
||||
}
|
||||
}
|
||||
|
||||
rv = tegra_powergate_sequence_power_up(TEGRA_POWERGATE_PCX,
|
||||
@ -883,16 +902,19 @@ tegra_pcib_enable_fdt_resources(struct tegra_pcib_softc *sc)
|
||||
device_printf(sc->dev, "Cannot enable 'afi' 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->soc->cml_clk) {
|
||||
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);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -975,57 +997,23 @@ tegra_pcib_parse_fdt_resources(struct tegra_pcib_softc *sc, phandle_t node)
|
||||
{
|
||||
phandle_t child;
|
||||
struct tegra_pcib_port *port;
|
||||
int rv;
|
||||
int i, rv;
|
||||
|
||||
/* Power supplies. */
|
||||
rv = regulator_get_by_ofw_property(sc->dev, 0, "avddio-pex-supply",
|
||||
&sc->supply_avddio_pex);
|
||||
if (rv != 0) {
|
||||
device_printf(sc->dev,
|
||||
"Cannot get 'avddio-pex' regulator\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
rv = regulator_get_by_ofw_property(sc->dev, 0, "dvddio-pex-supply",
|
||||
&sc->supply_dvddio_pex);
|
||||
if (rv != 0) {
|
||||
device_printf(sc->dev,
|
||||
"Cannot get 'dvddio-pex' regulator\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
rv = regulator_get_by_ofw_property(sc->dev, 0, "avdd-pex-pll-supply",
|
||||
&sc->supply_avdd_pex_pll);
|
||||
if (rv != 0) {
|
||||
device_printf(sc->dev,
|
||||
"Cannot get 'avdd-pex-pll' regulator\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
rv = regulator_get_by_ofw_property(sc->dev, 0, "hvdd-pex-supply",
|
||||
&sc->supply_hvdd_pex);
|
||||
if (rv != 0) {
|
||||
device_printf(sc->dev,
|
||||
"Cannot get 'hvdd-pex' regulator\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
rv = regulator_get_by_ofw_property(sc->dev, 0, "hvdd-pex-pll-e-supply",
|
||||
&sc->supply_hvdd_pex_pll_e);
|
||||
if (rv != 0) {
|
||||
device_printf(sc->dev,
|
||||
"Cannot get 'hvdd-pex-pll-e' regulator\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
rv = regulator_get_by_ofw_property(sc->dev, 0, "vddio-pex-ctl-supply",
|
||||
&sc->supply_vddio_pex_ctl);
|
||||
if (rv != 0) {
|
||||
device_printf(sc->dev,
|
||||
"Cannot get 'vddio-pex-ctl' regulator\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
rv = regulator_get_by_ofw_property(sc->dev, 0, "avdd-pll-erefe-supply",
|
||||
&sc->supply_avdd_pll_erefe);
|
||||
if (rv != 0) {
|
||||
device_printf(sc->dev,
|
||||
"Cannot get 'avdd-pll-erefe' regulator\n");
|
||||
return (ENXIO);
|
||||
/* 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. */
|
||||
@ -1061,10 +1049,12 @@ tegra_pcib_parse_fdt_resources(struct tegra_pcib_softc *sc, phandle_t node)
|
||||
device_printf(sc->dev, "Cannot get 'pll_e' clock\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
rv = clk_get_by_ofw_name(sc->dev, 0, "cml", &sc->clk_cml);
|
||||
if (rv != 0) {
|
||||
device_printf(sc->dev, "Cannot get 'cml' clock\n");
|
||||
return (ENXIO);
|
||||
if (sc->soc->cml_clk) {
|
||||
rv = clk_get_by_ofw_name(sc->dev, 0, "cml", &sc->clk_cml);
|
||||
if (rv != 0) {
|
||||
device_printf(sc->dev, "Cannot get 'cml' clock\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
}
|
||||
|
||||
/* Ports */
|
||||
@ -1196,6 +1186,14 @@ tegra_pcib_port_enable(struct tegra_pcib_softc *sc, int port_num)
|
||||
reg |= AFI_PEX_CTRL_RST_L;
|
||||
AFI_WR4(sc, port->afi_pex_ctrl, reg);
|
||||
|
||||
if (sc->soc->pca_enable) {
|
||||
reg = tegra_pcib_read_config(sc->dev, 0, port->port_idx, 0,
|
||||
RP_VEND_CTL2, 4);
|
||||
reg |= RP_VEND_CTL2_PCA_ENABLE;
|
||||
tegra_pcib_write_config(sc->dev, 0, port->port_idx, 0,
|
||||
RP_VEND_CTL2, reg, 4);
|
||||
}
|
||||
|
||||
rv = tegra_pcib_wait_for_link(sc, port);
|
||||
if (bootverbose)
|
||||
device_printf(sc->dev, " port %d (%d lane%s): Link is %s\n",
|
||||
@ -1259,6 +1257,7 @@ tegra_pcib_enable(struct tegra_pcib_softc *sc)
|
||||
device_printf(sc->dev, "Cannot enable FDT resources\n");
|
||||
return (rv);
|
||||
}
|
||||
|
||||
/* Enable PLLE control. */
|
||||
reg = AFI_RD4(sc, AFI_PLLE_CONTROL);
|
||||
reg &= ~AFI_PLLE_CONTROL_BYPASS_PADS2PLLE_CONTROL;
|
||||
@ -1310,6 +1309,11 @@ tegra_pcib_enable(struct tegra_pcib_softc *sc)
|
||||
}
|
||||
}
|
||||
|
||||
/* Configure PCIe reference clock */
|
||||
PADS_WR4(sc, PADS_REFCLK_CFG0, sc->soc->pads_refclk_cfg0);
|
||||
if (sc->num_ports > 2)
|
||||
PADS_WR4(sc, PADS_REFCLK_CFG1, sc->soc->pads_refclk_cfg1);
|
||||
|
||||
rv = hwreset_deassert(sc->hwreset_pcie_x);
|
||||
if (rv != 0) {
|
||||
device_printf(sc->dev, "Cannot unreset 'pci_x' reset\n");
|
||||
@ -1449,6 +1453,8 @@ tegra_pcib_attach(device_t dev)
|
||||
mtx_init(&sc->mtx, "msi_mtx", NULL, MTX_DEF);
|
||||
|
||||
node = ofw_bus_get_node(dev);
|
||||
sc->soc = (struct pcie_soc *)ofw_bus_search_compatible(dev,
|
||||
compat_data)->ocd_data;
|
||||
|
||||
rv = tegra_pcib_parse_fdt_resources(sc, node);
|
||||
if (rv != 0) {
|
||||
|
@ -39,18 +39,18 @@ enum tegra_suspend_mode {
|
||||
/* PARTIDs for powergate */
|
||||
enum tegra_powergate_id {
|
||||
TEGRA_POWERGATE_CRAIL = 0,
|
||||
TEGRA_POWERGATE_TD = 1,
|
||||
TEGRA_POWERGATE_TD = 1, /* Tegra124 only */
|
||||
TEGRA_POWERGATE_VE = 2,
|
||||
TEGRA_POWERGATE_PCX = 3,
|
||||
TEGRA_POWERGATE_VDE = 4,
|
||||
TEGRA_POWERGATE_L2C = 5,
|
||||
TEGRA_POWERGATE_VDE = 4, /* Tegra124 only */
|
||||
TEGRA_POWERGATE_L2C = 5, /* Tegra124 only */
|
||||
TEGRA_POWERGATE_MPE = 6,
|
||||
TEGRA_POWERGATE_HEG = 7,
|
||||
TEGRA_POWERGATE_HEG = 7, /* Tegra124 only */
|
||||
TEGRA_POWERGATE_SAX = 8,
|
||||
TEGRA_POWERGATE_CE1 = 9,
|
||||
TEGRA_POWERGATE_CE2 = 10,
|
||||
TEGRA_POWERGATE_CE3 = 11,
|
||||
TEGRA_POWERGATE_CELP = 12,
|
||||
TEGRA_POWERGATE_CELP = 12, /* Tegra124 only */
|
||||
/* */
|
||||
TEGRA_POWERGATE_CE0 = 14,
|
||||
TEGRA_POWERGATE_C0NC = 15,
|
||||
@ -63,9 +63,13 @@ enum tegra_powergate_id {
|
||||
TEGRA_POWERGATE_XUSBC = 22,
|
||||
TEGRA_POWERGATE_VIC = 23,
|
||||
TEGRA_POWERGATE_IRAM = 24,
|
||||
TEGRA_POWERGATE_NVDEC = 25, /* Tegra210 only */
|
||||
TEGRA_POWERGATE_NVJPG = 26, /* Tegra210 only */
|
||||
TEGRA_POWERGATE_AUD = 27, /* Tegra210 only */
|
||||
TEGRA_POWERGATE_DFD = 28, /* Tegra210 only */
|
||||
TEGRA_POWERGATE_VE2 = 29, /* Tegra210 only */
|
||||
/* */
|
||||
TEGRA_POWERGATE_3D = 32
|
||||
|
||||
};
|
||||
|
||||
/* PARTIDs for power rails */
|
||||
|
@ -95,6 +95,7 @@ __FBSDID("$FreeBSD$");
|
||||
/* Compatible devices. */
|
||||
static struct ofw_compat_data compat_data[] = {
|
||||
{"nvidia,tegra124-sdhci", 1},
|
||||
{"nvidia,tegra210-sdhci", 1},
|
||||
{NULL, 0},
|
||||
};
|
||||
|
||||
@ -242,15 +243,12 @@ tegra_sdhci_probe(device_t dev)
|
||||
if (!ofw_bus_status_okay(dev))
|
||||
return (ENXIO);
|
||||
|
||||
if (ofw_bus_is_compatible(dev, "nvidia,tegra124-sdhci")) {
|
||||
device_set_desc(dev, "Tegra SDHCI controller");
|
||||
} else
|
||||
return (ENXIO);
|
||||
cd = ofw_bus_search_compatible(dev, compat_data);
|
||||
if (cd->ocd_data == 0)
|
||||
return (ENXIO);
|
||||
|
||||
node = ofw_bus_get_node(dev);
|
||||
device_set_desc(dev, "Tegra SDHCI controller");
|
||||
|
||||
/* Allow dts to patch quirks, slots, and max-frequency. */
|
||||
if ((OF_getencprop(node, "quirks", &cid, sizeof(cid))) > 0)
|
||||
@ -291,25 +289,27 @@ tegra_sdhci_attach(device_t dev)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (bus_setup_intr(dev, sc->irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
|
||||
NULL, tegra_sdhci_intr, sc, &sc->intr_cookie)) {
|
||||
device_printf(dev, "cannot setup interrupt handler\n");
|
||||
rv = ENXIO;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
rv = hwreset_get_by_ofw_name(sc->dev, 0, "sdhci", &sc->reset);
|
||||
if (rv != 0) {
|
||||
device_printf(sc->dev, "Cannot get 'sdhci' reset\n");
|
||||
goto fail;
|
||||
}
|
||||
rv = hwreset_deassert(sc->reset);
|
||||
rv = hwreset_assert(sc->reset);
|
||||
if (rv != 0) {
|
||||
device_printf(dev, "Cannot unreset 'sdhci' reset\n");
|
||||
device_printf(dev, "Cannot reset 'sdhci' reset\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
gpio_pin_get_by_ofw_property(sc->dev, node, "power-gpios", &sc->gpio_power);
|
||||
gpio_pin_get_by_ofw_property(sc->dev, node, "power-gpios",
|
||||
&sc->gpio_power);
|
||||
|
||||
if (OF_hasprop(node, "assigned-clocks")) {
|
||||
rv = clk_set_assigned(sc->dev, node);
|
||||
if (rv != 0) {
|
||||
device_printf(dev, "Cannot set assigned clocks\n");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
rv = clk_get_by_ofw_index(dev, 0, 0, &sc->clk);
|
||||
if (rv != 0) {
|
||||
@ -330,8 +330,14 @@ tegra_sdhci_attach(device_t dev)
|
||||
device_printf(dev, "Cannot get clock frequency\n");
|
||||
goto fail;
|
||||
}
|
||||
DELAY(4000);
|
||||
rv = hwreset_deassert(sc->reset);
|
||||
if (rv != 0) {
|
||||
device_printf(dev, "Cannot unreset 'sdhci' reset\n");
|
||||
goto fail;
|
||||
}
|
||||
if (bootverbose)
|
||||
device_printf(dev, " Base MMC clock: %lld\n", freq);
|
||||
device_printf(dev, " Base MMC clock: %jd\n", (uintmax_t)freq);
|
||||
|
||||
/* Fill slot information. */
|
||||
sc->max_clk = (int)freq;
|
||||
@ -369,6 +375,12 @@ tegra_sdhci_attach(device_t dev)
|
||||
sc->slot.max_clk = sc->max_clk;
|
||||
sc->slot.caps = sc->caps;
|
||||
|
||||
if (bus_setup_intr(dev, sc->irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
|
||||
NULL, tegra_sdhci_intr, sc, &sc->intr_cookie)) {
|
||||
device_printf(dev, "cannot setup interrupt handler\n");
|
||||
rv = ENXIO;
|
||||
goto fail;
|
||||
}
|
||||
rv = sdhci_init_slot(dev, &sc->slot, 0);
|
||||
if (rv != 0) {
|
||||
goto fail;
|
||||
|
@ -86,52 +86,55 @@ __FBSDID("$FreeBSD$");
|
||||
#define TSENSOR_STATUS2_TEMP_MAX(x) (((x) >> 16) & 0xffff)
|
||||
#define TSENSOR_STATUS2_TEMP_MIN(x) (((x) >> 0) & 0xffff)
|
||||
|
||||
/* Global registers */
|
||||
#define TSENSOR_PDIV 0x1c0
|
||||
#define TSENSOR_PDIV_T124 0x8888
|
||||
#define TSENSOR_HOTSPOT_OFF 0x1c4
|
||||
#define TSENSOR_HOTSPOT_OFF_T124 0x00060600
|
||||
#define TSENSOR_TEMP1 0x1c8
|
||||
#define TSENSOR_TEMP2 0x1cc
|
||||
|
||||
/* Readbacks */
|
||||
#define READBACK_VALUE_MASK 0xff00
|
||||
#define READBACK_VALUE_SHIFT 8
|
||||
#define READBACK_VALUE(x) (((x) >> 8) & 0xff)
|
||||
#define READBACK_ADD_HALF (1 << 7)
|
||||
#define READBACK_NEGATE (1 << 0)
|
||||
|
||||
/* Global registers */
|
||||
#define TSENSOR_PDIV 0x1c0
|
||||
#define TSENSOR_HOTSPOT_OFF 0x1c4
|
||||
#define TSENSOR_TEMP1 0x1c8
|
||||
#define TSENSOR_TEMP2 0x1cc
|
||||
|
||||
/* Fuses */
|
||||
#define FUSE_TSENSOR_CALIB_CP_TS_BASE_SHIFT 0
|
||||
#define FUSE_TSENSOR_CALIB_CP_TS_BASE_BITS 13
|
||||
#define FUSE_TSENSOR_CALIB_FT_TS_BASE_SHIFT 13
|
||||
#define FUSE_TSENSOR_CALIB_FT_TS_BASE_BITS 13
|
||||
|
||||
#define FUSE_TSENSOR8_CALIB 0x180
|
||||
#define FUSE_TSENSOR8_CALIB_CP_TS_BASE(x) (((x) >> 0) & 0x3ff)
|
||||
#define FUSE_TSENSOR8_CALIB_FT_TS_BASE(x) (((x) >> 10) & 0x7ff)
|
||||
/* Layout is different for Tegra124 and Tegra210 */
|
||||
#define FUSE_TSENSOR_COMMON 0x180
|
||||
#define TEGRA124_FUSE_COMMON_CP_TS_BASE(x) (((x) >> 0) & 0x3ff)
|
||||
#define TEGRA124_FUSE_COMMON_FT_TS_BASE(x) (((x) >> 10) & 0x7ff)
|
||||
#define TEGRA124_FUSE_COMMON_SHIFT_FT_SHIFT 21
|
||||
#define TEGRA124_FUSE_COMMON_SHIFT_FT_BITS 5
|
||||
|
||||
#define TEGRA210_FUSE_COMMON_CP_TS_BASE(x) (((x) >> 11) & 0x3ff)
|
||||
#define TEGRA210_FUSE_COMMON_FT_TS_BASE(x) (((x) >> 21) & 0x7ff)
|
||||
#define TEGRA210_FUSE_COMMON_SHIFT_CP_SHIFT 0
|
||||
#define TEGRA210_FUSE_COMMON_SHIFT_CP_BITS 6
|
||||
#define TEGRA210_FUSE_COMMON_SHIFT_FT_SHIFT 6
|
||||
#define TEGRA210_FUSE_COMMON_SHIFT_FT_BITS 5
|
||||
|
||||
|
||||
/* Only for Tegra124 */
|
||||
#define FUSE_SPARE_REALIGNMENT_REG 0x1fc
|
||||
#define FUSE_SPARE_REALIGNMENT_REG_SHIFT_CP_SHIFT 0
|
||||
#define FUSE_SPARE_REALIGNMENT_REG_SHIFT_CP_BITS 6
|
||||
#define FUSE_SPARE_REALIGNMENT_REG_SHIFT_FT_SHIFT 21
|
||||
#define FUSE_SPARE_REALIGNMENT_REG_SHIFT_FT_BITS 5
|
||||
#define FUSE_SPARE_REALIGNMENT_REG_SHIFT_CP(x) (((x) >> 0) & 0x3f)
|
||||
#define FUSE_SPARE_REALIGNMENT_REG_SHIFT_FT(x) (((x) >> 21) & 0x1f)
|
||||
|
||||
#define NOMINAL_CALIB_FT_T124 105
|
||||
#define NOMINAL_CALIB_CP_T124 25
|
||||
#define TEGRA124_NOMINAL_CALIB_FT 105
|
||||
#define TEGRA124_NOMINAL_CALIB_CP 25
|
||||
|
||||
#define TEGRA210_NOMINAL_CALIB_FT 105
|
||||
#define TEGRA210_NOMINAL_CALIB_CP 25
|
||||
|
||||
#define WR4(_sc, _r, _v) bus_write_4((_sc)->mem_res, (_r), (_v))
|
||||
#define RD4(_sc, _r) bus_read_4((_sc)->mem_res, (_r))
|
||||
|
||||
static struct sysctl_ctx_list soctherm_sysctl_ctx;
|
||||
|
||||
struct soctherm_shared_cal {
|
||||
uint32_t base_cp;
|
||||
uint32_t base_ft;
|
||||
int32_t actual_temp_cp;
|
||||
int32_t actual_temp_ft;
|
||||
};
|
||||
struct tsensor_cfg {
|
||||
uint32_t tall;
|
||||
uint32_t tsample;
|
||||
@ -142,10 +145,16 @@ struct tsensor_cfg {
|
||||
uint32_t pdiv_ate;
|
||||
};
|
||||
|
||||
struct soctherm_shared_cal {
|
||||
uint32_t base_cp;
|
||||
uint32_t base_ft;
|
||||
int32_t actual_temp_cp;
|
||||
int32_t actual_temp_ft;
|
||||
};
|
||||
|
||||
struct tsensor {
|
||||
char *name;
|
||||
int id;
|
||||
struct tsensor_cfg *cfg;
|
||||
bus_addr_t sensor_base;
|
||||
bus_addr_t calib_fuse;
|
||||
int fuse_corr_alpha;
|
||||
@ -155,6 +164,7 @@ struct tsensor {
|
||||
int16_t therm_b;
|
||||
};
|
||||
|
||||
struct soctherm_soc;
|
||||
struct soctherm_softc {
|
||||
device_t dev;
|
||||
struct resource *mem_res;
|
||||
@ -163,16 +173,22 @@ struct soctherm_softc {
|
||||
|
||||
clk_t tsensor_clk;
|
||||
clk_t soctherm_clk;
|
||||
hwreset_t reset;
|
||||
hwreset_t reset;
|
||||
|
||||
int ntsensors;
|
||||
struct soctherm_soc *soc;
|
||||
struct soctherm_shared_cal shared_cal;
|
||||
};
|
||||
|
||||
struct soctherm_soc {
|
||||
void (*shared_cal)(struct soctherm_softc *sc);
|
||||
uint32_t tsensor_pdiv;
|
||||
uint32_t tsensor_hotspot_off;
|
||||
struct tsensor_cfg *tsensor_cfg;
|
||||
struct tsensor *tsensors;
|
||||
int ntsensors;
|
||||
};
|
||||
|
||||
static struct ofw_compat_data compat_data[] = {
|
||||
{"nvidia,tegra124-soctherm", 1},
|
||||
{NULL, 0},
|
||||
};
|
||||
/* Tegra124 config */
|
||||
|
||||
static struct tsensor_cfg t124_tsensor_config = {
|
||||
.tall = 16300,
|
||||
@ -188,7 +204,6 @@ static struct tsensor t124_tsensors[] = {
|
||||
{
|
||||
.name = "cpu0",
|
||||
.id = TEGRA124_SOCTHERM_SENSOR_CPU,
|
||||
.cfg = &t124_tsensor_config,
|
||||
.sensor_base = 0x0c0,
|
||||
.calib_fuse = 0x098,
|
||||
.fuse_corr_alpha = 1135400,
|
||||
@ -197,7 +212,6 @@ static struct tsensor t124_tsensors[] = {
|
||||
{
|
||||
.name = "cpu1",
|
||||
.id = -1,
|
||||
.cfg = &t124_tsensor_config,
|
||||
.sensor_base = 0x0e0,
|
||||
.calib_fuse = 0x084,
|
||||
.fuse_corr_alpha = 1122220,
|
||||
@ -206,7 +220,6 @@ static struct tsensor t124_tsensors[] = {
|
||||
{
|
||||
.name = "cpu2",
|
||||
.id = -1,
|
||||
.cfg = &t124_tsensor_config,
|
||||
.sensor_base = 0x100,
|
||||
.calib_fuse = 0x088,
|
||||
.fuse_corr_alpha = 1127000,
|
||||
@ -215,7 +228,6 @@ static struct tsensor t124_tsensors[] = {
|
||||
{
|
||||
.name = "cpu3",
|
||||
.id = -1,
|
||||
.cfg = &t124_tsensor_config,
|
||||
.sensor_base = 0x120,
|
||||
.calib_fuse = 0x12c,
|
||||
.fuse_corr_alpha = 1110900,
|
||||
@ -224,7 +236,6 @@ static struct tsensor t124_tsensors[] = {
|
||||
{
|
||||
.name = "mem0",
|
||||
.id = TEGRA124_SOCTHERM_SENSOR_MEM,
|
||||
.cfg = &t124_tsensor_config,
|
||||
.sensor_base = 0x140,
|
||||
.calib_fuse = 0x158,
|
||||
.fuse_corr_alpha = 1122300,
|
||||
@ -233,7 +244,6 @@ static struct tsensor t124_tsensors[] = {
|
||||
{
|
||||
.name = "mem1",
|
||||
.id = -1,
|
||||
.cfg = &t124_tsensor_config,
|
||||
.sensor_base = 0x160,
|
||||
.calib_fuse = 0x15c,
|
||||
.fuse_corr_alpha = 1145700,
|
||||
@ -242,7 +252,6 @@ static struct tsensor t124_tsensors[] = {
|
||||
{
|
||||
.name = "gpu",
|
||||
.id = TEGRA124_SOCTHERM_SENSOR_GPU,
|
||||
.cfg = &t124_tsensor_config,
|
||||
.sensor_base = 0x180,
|
||||
.calib_fuse = 0x154,
|
||||
.fuse_corr_alpha = 1120100,
|
||||
@ -251,7 +260,6 @@ static struct tsensor t124_tsensors[] = {
|
||||
{
|
||||
.name = "pllX",
|
||||
.id = TEGRA124_SOCTHERM_SENSOR_PLLX,
|
||||
.cfg = &t124_tsensor_config,
|
||||
.sensor_base = 0x1a0,
|
||||
.calib_fuse = 0x160,
|
||||
.fuse_corr_alpha = 1106500,
|
||||
@ -259,6 +267,112 @@ static struct tsensor t124_tsensors[] = {
|
||||
},
|
||||
};
|
||||
|
||||
static void tegra124_shared_cal(struct soctherm_softc *sc);
|
||||
|
||||
static struct soctherm_soc tegra124_soc = {
|
||||
.shared_cal = tegra124_shared_cal,
|
||||
.tsensor_pdiv = 0x8888,
|
||||
.tsensor_hotspot_off = 0x00060600 ,
|
||||
.tsensor_cfg = &t124_tsensor_config,
|
||||
.tsensors = t124_tsensors,
|
||||
.ntsensors = nitems(t124_tsensors),
|
||||
};
|
||||
|
||||
/* Tegra210 config */
|
||||
static struct tsensor_cfg t210_tsensor_config = {
|
||||
.tall = 16300,
|
||||
.tsample = 120,
|
||||
.tiddq_en = 1,
|
||||
.ten_count = 1,
|
||||
.pdiv = 8,
|
||||
.tsample_ate = 480,
|
||||
.pdiv_ate = 8
|
||||
};
|
||||
|
||||
static struct tsensor t210_tsensors[] = {
|
||||
{
|
||||
.name = "cpu0",
|
||||
.id = TEGRA124_SOCTHERM_SENSOR_CPU,
|
||||
.sensor_base = 0x0c0,
|
||||
.calib_fuse = 0x098,
|
||||
.fuse_corr_alpha = 1085000,
|
||||
.fuse_corr_beta = 3244200,
|
||||
},
|
||||
{
|
||||
.name = "cpu1",
|
||||
.id = -1,
|
||||
.sensor_base = 0x0e0,
|
||||
.calib_fuse = 0x084,
|
||||
.fuse_corr_alpha = 1126200,
|
||||
.fuse_corr_beta = -67500,
|
||||
},
|
||||
{
|
||||
.name = "cpu2",
|
||||
.id = -1,
|
||||
.sensor_base = 0x100,
|
||||
.calib_fuse = 0x088,
|
||||
.fuse_corr_alpha = 1098400,
|
||||
.fuse_corr_beta = 2251100,
|
||||
},
|
||||
{
|
||||
.name = "cpu3",
|
||||
.id = -1,
|
||||
.sensor_base = 0x120,
|
||||
.calib_fuse = 0x12c,
|
||||
.fuse_corr_alpha = 1108000,
|
||||
.fuse_corr_beta = 602700,
|
||||
},
|
||||
{
|
||||
.name = "mem0",
|
||||
.id = TEGRA124_SOCTHERM_SENSOR_MEM,
|
||||
.sensor_base = 0x140,
|
||||
.calib_fuse = 0x158,
|
||||
.fuse_corr_alpha = 1069200,
|
||||
.fuse_corr_beta = 3549900,
|
||||
},
|
||||
{
|
||||
.name = "mem1",
|
||||
.id = -1,
|
||||
.sensor_base = 0x160,
|
||||
.calib_fuse = 0x15c,
|
||||
.fuse_corr_alpha = 1173700,
|
||||
.fuse_corr_beta = -6263600,
|
||||
},
|
||||
{
|
||||
.name = "gpu",
|
||||
.id = TEGRA124_SOCTHERM_SENSOR_GPU,
|
||||
.sensor_base = 0x180,
|
||||
.calib_fuse = 0x154,
|
||||
.fuse_corr_alpha = 1074300,
|
||||
.fuse_corr_beta = 2734900,
|
||||
},
|
||||
{
|
||||
.name = "pllX",
|
||||
.id = TEGRA124_SOCTHERM_SENSOR_PLLX,
|
||||
.sensor_base = 0x1a0,
|
||||
.calib_fuse = 0x160,
|
||||
.fuse_corr_alpha = 1039700,
|
||||
.fuse_corr_beta = 6829100,
|
||||
},
|
||||
};
|
||||
|
||||
static void tegra210_shared_cal(struct soctherm_softc *sc);
|
||||
|
||||
static struct soctherm_soc tegra210_soc = {
|
||||
.shared_cal = tegra210_shared_cal,
|
||||
.tsensor_pdiv = 0x8888,
|
||||
.tsensor_hotspot_off = 0x000A0500 ,
|
||||
.tsensor_cfg = &t210_tsensor_config,
|
||||
.tsensors = t210_tsensors,
|
||||
.ntsensors = nitems(t210_tsensors),
|
||||
};
|
||||
|
||||
static struct ofw_compat_data compat_data[] = {
|
||||
{"nvidia,tegra124-soctherm", (uintptr_t)&tegra124_soc},
|
||||
{"nvidia,tegra210-soctherm", (uintptr_t)&tegra210_soc},
|
||||
{NULL, 0},
|
||||
};
|
||||
|
||||
/* Extract signed integer bitfield from register */
|
||||
static int
|
||||
extract_signed(uint32_t reg, int shift, int bits)
|
||||
@ -272,35 +386,39 @@ extract_signed(uint32_t reg, int shift, int bits)
|
||||
return ((int32_t)val);
|
||||
}
|
||||
|
||||
static inline int64_t div64_s64_precise(int64_t a, int64_t b)
|
||||
static inline
|
||||
int64_t div64_s64_precise(int64_t a, int64_t b)
|
||||
{
|
||||
int64_t r, al;
|
||||
|
||||
al = a << 16;
|
||||
r = (al * 2 + 1) / (2 * b);
|
||||
return r >> 16;
|
||||
return (r >> 16);
|
||||
}
|
||||
|
||||
static void
|
||||
get_shared_cal(struct soctherm_softc *sc, struct soctherm_shared_cal *cal)
|
||||
tegra124_shared_cal(struct soctherm_softc *sc)
|
||||
{
|
||||
uint32_t val;
|
||||
int calib_cp, calib_ft;
|
||||
struct soctherm_shared_cal *cal;
|
||||
|
||||
val = tegra_fuse_read_4(FUSE_TSENSOR8_CALIB);
|
||||
cal->base_cp = FUSE_TSENSOR8_CALIB_CP_TS_BASE(val);
|
||||
cal->base_ft = FUSE_TSENSOR8_CALIB_FT_TS_BASE(val);
|
||||
cal = &sc->shared_cal;
|
||||
val = tegra_fuse_read_4(FUSE_TSENSOR_COMMON);
|
||||
cal->base_cp = TEGRA124_FUSE_COMMON_CP_TS_BASE(val);
|
||||
cal->base_ft = TEGRA124_FUSE_COMMON_FT_TS_BASE(val);
|
||||
|
||||
calib_ft = extract_signed(val,
|
||||
TEGRA124_FUSE_COMMON_SHIFT_FT_SHIFT,
|
||||
TEGRA124_FUSE_COMMON_SHIFT_FT_BITS);
|
||||
|
||||
val = tegra_fuse_read_4(FUSE_SPARE_REALIGNMENT_REG);
|
||||
calib_ft = extract_signed(val,
|
||||
FUSE_SPARE_REALIGNMENT_REG_SHIFT_FT_SHIFT,
|
||||
FUSE_SPARE_REALIGNMENT_REG_SHIFT_FT_BITS);
|
||||
calib_cp = extract_signed(val,
|
||||
FUSE_SPARE_REALIGNMENT_REG_SHIFT_CP_SHIFT,
|
||||
FUSE_SPARE_REALIGNMENT_REG_SHIFT_CP_BITS);
|
||||
|
||||
cal->actual_temp_cp = 2 * NOMINAL_CALIB_CP_T124 + calib_cp;
|
||||
cal->actual_temp_ft = 2 * NOMINAL_CALIB_FT_T124 + calib_ft;
|
||||
cal->actual_temp_cp = 2 * TEGRA124_NOMINAL_CALIB_CP + calib_cp;
|
||||
cal->actual_temp_ft = 2 * TEGRA124_NOMINAL_CALIB_FT + calib_ft;
|
||||
#ifdef DEBUG
|
||||
printf("%s: base_cp: %u, base_ft: %d,"
|
||||
" actual_temp_cp: %d, actual_temp_ft: %d\n",
|
||||
@ -310,35 +428,70 @@ get_shared_cal(struct soctherm_softc *sc, struct soctherm_shared_cal *cal)
|
||||
}
|
||||
|
||||
static void
|
||||
tsensor_calibration(struct tsensor *sensor, struct soctherm_shared_cal *shared)
|
||||
tegra210_shared_cal(struct soctherm_softc *sc)
|
||||
{
|
||||
uint32_t val;
|
||||
int calib_cp, calib_ft;
|
||||
struct soctherm_shared_cal *cal;
|
||||
|
||||
cal = &sc->shared_cal;
|
||||
|
||||
val = tegra_fuse_read_4(FUSE_TSENSOR_COMMON);
|
||||
cal->base_cp = TEGRA210_FUSE_COMMON_CP_TS_BASE(val);
|
||||
cal->base_ft = TEGRA210_FUSE_COMMON_FT_TS_BASE(val);
|
||||
|
||||
calib_ft = extract_signed(val,
|
||||
TEGRA210_FUSE_COMMON_SHIFT_FT_SHIFT,
|
||||
TEGRA210_FUSE_COMMON_SHIFT_FT_BITS);
|
||||
calib_cp = extract_signed(val,
|
||||
TEGRA210_FUSE_COMMON_SHIFT_CP_SHIFT,
|
||||
TEGRA210_FUSE_COMMON_SHIFT_CP_BITS);
|
||||
|
||||
cal->actual_temp_cp = 2 * TEGRA210_NOMINAL_CALIB_CP + calib_cp;
|
||||
cal->actual_temp_ft = 2 * TEGRA210_NOMINAL_CALIB_FT + calib_ft;
|
||||
#ifdef DEBUG
|
||||
printf("%s: base_cp: %u, base_ft: %d,"
|
||||
" actual_temp_cp: %d, actual_temp_ft: %d\n",
|
||||
__func__, cal->base_cp, cal->base_ft,
|
||||
cal->actual_temp_cp, cal->actual_temp_ft);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
tsensor_calibration(struct soctherm_softc *sc, struct tsensor *sensor)
|
||||
{
|
||||
uint32_t val;
|
||||
int mult, div, calib_cp, calib_ft;
|
||||
int actual_tsensor_ft, actual_tsensor_cp, delta_sens, delta_temp;
|
||||
int temp_a, temp_b;
|
||||
struct tsensor_cfg *cfg;
|
||||
struct soctherm_shared_cal *cal;
|
||||
int64_t tmp;
|
||||
|
||||
cfg = sc->soc->tsensor_cfg;
|
||||
cal = &sc->shared_cal;
|
||||
|
||||
val = tegra_fuse_read_4(sensor->calib_fuse);
|
||||
calib_cp = extract_signed(val,
|
||||
FUSE_TSENSOR_CALIB_CP_TS_BASE_SHIFT,
|
||||
FUSE_TSENSOR_CALIB_CP_TS_BASE_BITS);
|
||||
actual_tsensor_cp = shared->base_cp * 64 + calib_cp;
|
||||
actual_tsensor_cp = cal->base_cp * 64 + calib_cp;
|
||||
|
||||
calib_ft = extract_signed(val,
|
||||
FUSE_TSENSOR_CALIB_FT_TS_BASE_SHIFT,
|
||||
FUSE_TSENSOR_CALIB_FT_TS_BASE_BITS);
|
||||
actual_tsensor_ft = shared->base_ft * 32 + calib_ft;
|
||||
actual_tsensor_ft = cal->base_ft * 32 + calib_ft;
|
||||
|
||||
delta_sens = actual_tsensor_ft - actual_tsensor_cp;
|
||||
delta_temp = shared->actual_temp_ft - shared->actual_temp_cp;
|
||||
mult = sensor->cfg->pdiv * sensor->cfg->tsample_ate;
|
||||
div = sensor->cfg->tsample * sensor->cfg->pdiv_ate;
|
||||
delta_temp = cal->actual_temp_ft - cal->actual_temp_cp;
|
||||
mult = cfg->pdiv * cfg->tsample_ate;
|
||||
div = cfg->tsample * cfg->pdiv_ate;
|
||||
|
||||
temp_a = div64_s64_precise((int64_t) delta_temp * (1LL << 13) * mult,
|
||||
(int64_t) delta_sens * div);
|
||||
|
||||
tmp = (int64_t)actual_tsensor_ft * shared->actual_temp_cp -
|
||||
(int64_t)actual_tsensor_cp * shared->actual_temp_ft;
|
||||
tmp = (int64_t)actual_tsensor_ft * cal->actual_temp_cp -
|
||||
(int64_t)actual_tsensor_cp * cal->actual_temp_ft;
|
||||
temp_b = div64_s64_precise(tmp, (int64_t)delta_sens);
|
||||
|
||||
temp_a = div64_s64_precise((int64_t)temp_a * sensor->fuse_corr_alpha,
|
||||
@ -353,31 +506,32 @@ tsensor_calibration(struct tsensor *sensor, struct soctherm_shared_cal *shared)
|
||||
__func__, sensor->name, val, val & 0x1FFF, (val >> 13) & 0x1FFF,
|
||||
calib_cp, calib_cp, calib_ft, calib_ft);
|
||||
printf("therma: 0x%04X(%d), thermb: 0x%04X(%d)\n",
|
||||
(uint16_t)sensor->therm_a, temp_a,
|
||||
(uint16_t)sensor->therm_a, sensor->therm_a,
|
||||
(uint16_t)sensor->therm_b, sensor->therm_b);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
soctherm_init_tsensor(struct soctherm_softc *sc, struct tsensor *sensor,
|
||||
struct soctherm_shared_cal *shared_cal)
|
||||
soctherm_init_tsensor(struct soctherm_softc *sc, struct tsensor *sensor)
|
||||
{
|
||||
struct tsensor_cfg *cfg;
|
||||
uint32_t val;
|
||||
|
||||
tsensor_calibration(sensor, shared_cal);
|
||||
cfg = sc->soc->tsensor_cfg;
|
||||
tsensor_calibration(sc, sensor);
|
||||
|
||||
val = RD4(sc, sensor->sensor_base + TSENSOR_CONFIG0);
|
||||
val |= TSENSOR_CONFIG0_STOP;
|
||||
val |= TSENSOR_CONFIG0_STATUS_CLR;
|
||||
WR4(sc, sensor->sensor_base + TSENSOR_CONFIG0, val);
|
||||
|
||||
val = TSENSOR_CONFIG0_TALL(sensor->cfg->tall);
|
||||
val = TSENSOR_CONFIG0_TALL(cfg->tall);
|
||||
val |= TSENSOR_CONFIG0_STOP;
|
||||
WR4(sc, sensor->sensor_base + TSENSOR_CONFIG0, val);
|
||||
|
||||
val = TSENSOR_CONFIG1_TSAMPLE(sensor->cfg->tsample - 1);
|
||||
val |= TSENSOR_CONFIG1_TIDDQ_EN(sensor->cfg->tiddq_en);
|
||||
val |= TSENSOR_CONFIG1_TEN_COUNT(sensor->cfg->ten_count);
|
||||
val = TSENSOR_CONFIG1_TSAMPLE(cfg->tsample - 1);
|
||||
val |= TSENSOR_CONFIG1_TIDDQ_EN(cfg->tiddq_en);
|
||||
val |= TSENSOR_CONFIG1_TEN_COUNT(cfg->ten_count);
|
||||
val |= TSENSOR_CONFIG1_TEMP_ENABLE;
|
||||
WR4(sc, sensor->sensor_base + TSENSOR_CONFIG1, val);
|
||||
|
||||
@ -406,13 +560,13 @@ soctherm_convert_raw(uint32_t val)
|
||||
{
|
||||
int32_t t;
|
||||
|
||||
t = ((val & READBACK_VALUE_MASK) >> READBACK_VALUE_SHIFT) * 1000;
|
||||
t = READBACK_VALUE(val) * 1000;
|
||||
if (val & READBACK_ADD_HALF)
|
||||
t += 500;
|
||||
if (val & READBACK_NEGATE)
|
||||
t *= -1;
|
||||
|
||||
return t;
|
||||
return (t);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -422,7 +576,7 @@ soctherm_read_temp(struct soctherm_softc *sc, struct tsensor *sensor, int *temp)
|
||||
uint32_t val;
|
||||
|
||||
/* wait for valid sample */
|
||||
for (timeout = 1000; timeout > 0; timeout--) {
|
||||
for (timeout = 100; timeout > 0; timeout--) {
|
||||
val = RD4(sc, sensor->sensor_base + TSENSOR_STATUS1);
|
||||
if ((val & TSENSOR_STATUS1_TEMP_VALID) != 0)
|
||||
break;
|
||||
@ -443,7 +597,7 @@ soctherm_read_temp(struct soctherm_softc *sc, struct tsensor *sensor, int *temp)
|
||||
RD4(sc, sensor->sensor_base + TSENSOR_STATUS2)
|
||||
);
|
||||
#endif
|
||||
return 0;
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -456,14 +610,16 @@ soctherm_get_temp(device_t dev, device_t cdev, uintptr_t id, int *val)
|
||||
/* The direct sensor map starts at 0x100 */
|
||||
if (id >= 0x100) {
|
||||
id -= 0x100;
|
||||
if (id >= sc->ntsensors)
|
||||
if (id >= sc->soc->ntsensors)
|
||||
return (ERANGE);
|
||||
return(soctherm_read_temp(sc, sc->tsensors + id, val));
|
||||
return(soctherm_read_temp(sc, sc->soc->tsensors + id, val));
|
||||
}
|
||||
/* Linux (DT) compatible thermal zones */
|
||||
for (i = 0; i < sc->ntsensors; i++) {
|
||||
if (sc->tsensors->id == id)
|
||||
return(soctherm_read_temp(sc, sc->tsensors + id, val));
|
||||
for (i = 0; i < sc->soc->ntsensors; i++) {
|
||||
if (sc->soc->tsensors->id == id) {
|
||||
return(soctherm_read_temp(sc, sc->soc->tsensors + id,
|
||||
val));
|
||||
}
|
||||
}
|
||||
return (ERANGE);
|
||||
}
|
||||
@ -483,9 +639,9 @@ soctherm_sysctl_temperature(SYSCTL_HANDLER_ARGS)
|
||||
sc = arg1;
|
||||
id = arg2;
|
||||
|
||||
if (id >= sc->ntsensors)
|
||||
if (id >= sc->soc->ntsensors)
|
||||
return (ERANGE);
|
||||
rv = soctherm_read_temp(sc, sc->tsensors + id, &val);
|
||||
rv = soctherm_read_temp(sc, sc->soc->tsensors + id, &val);
|
||||
if (rv != 0)
|
||||
return (rv);
|
||||
|
||||
@ -510,9 +666,9 @@ soctherm_init_sysctl(struct soctherm_softc *sc)
|
||||
return (ENXIO);
|
||||
|
||||
/* Add sensors */
|
||||
for (i = sc->ntsensors - 1; i >= 0; i--) {
|
||||
for (i = sc->soc->ntsensors - 1; i >= 0; i--) {
|
||||
tmp = SYSCTL_ADD_PROC(&soctherm_sysctl_ctx,
|
||||
SYSCTL_CHILDREN(oid), OID_AUTO, sc->tsensors[i].name,
|
||||
SYSCTL_CHILDREN(oid), OID_AUTO, sc->soc->tsensors[i].name,
|
||||
CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_NEEDGIANT, sc, i,
|
||||
soctherm_sysctl_temperature, "IK", "SoC Temperature");
|
||||
if (tmp == NULL)
|
||||
@ -542,10 +698,11 @@ soctherm_attach(device_t dev)
|
||||
struct soctherm_softc *sc;
|
||||
phandle_t node;
|
||||
int i, rid, rv;
|
||||
struct soctherm_shared_cal shared_calib;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
sc->dev = dev;
|
||||
sc->soc = (struct soctherm_soc *)ofw_bus_search_compatible(dev,
|
||||
compat_data)->ocd_data;
|
||||
node = ofw_bus_get_node(sc->dev);
|
||||
|
||||
rid = 0;
|
||||
@ -610,16 +767,13 @@ soctherm_attach(device_t dev)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Tegra 124 */
|
||||
sc->tsensors = t124_tsensors;
|
||||
sc->ntsensors = nitems(t124_tsensors);
|
||||
get_shared_cal(sc, &shared_calib);
|
||||
sc->soc->shared_cal(sc);
|
||||
|
||||
WR4(sc, TSENSOR_PDIV, TSENSOR_PDIV_T124);
|
||||
WR4(sc, TSENSOR_HOTSPOT_OFF, TSENSOR_HOTSPOT_OFF_T124);
|
||||
WR4(sc, TSENSOR_PDIV, sc->soc->tsensor_pdiv);
|
||||
WR4(sc, TSENSOR_HOTSPOT_OFF, sc->soc->tsensor_hotspot_off);
|
||||
|
||||
for (i = 0; i < sc->ntsensors; i++)
|
||||
soctherm_init_tsensor(sc, sc->tsensors + i, &shared_calib);
|
||||
for (i = 0; i < sc->soc->ntsensors; i++)
|
||||
soctherm_init_tsensor(sc, sc->soc->tsensors + i);
|
||||
|
||||
rv = soctherm_init_sysctl(sc);
|
||||
if (rv != 0) {
|
||||
|
@ -155,7 +155,8 @@ static struct uart_class tegra_uart_class = {
|
||||
/* Compatible devices. */
|
||||
static struct ofw_compat_data compat_data[] = {
|
||||
{"nvidia,tegra124-uart", (uintptr_t)&tegra_uart_class},
|
||||
{NULL, (uintptr_t)NULL},
|
||||
{"nvidia,tegra210-uart", (uintptr_t)&tegra_uart_class},
|
||||
{NULL, (uintptr_t)NULL},
|
||||
};
|
||||
|
||||
UART_FDT_CLASS(compat_data);
|
||||
@ -190,7 +191,6 @@ tegra_uart_probe(device_t dev)
|
||||
if (cd->ocd_data == 0)
|
||||
return (ENXIO);
|
||||
sc->ns8250_base.base.sc_class = (struct uart_class *)cd->ocd_data;
|
||||
|
||||
rv = hwreset_get_by_ofw_name(dev, 0, "serial", &sc->reset);
|
||||
if (rv != 0) {
|
||||
device_printf(dev, "Cannot get 'serial' reset\n");
|
||||
@ -201,7 +201,6 @@ tegra_uart_probe(device_t dev)
|
||||
device_printf(dev, "Cannot unreset 'serial' reset\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
node = ofw_bus_get_node(dev);
|
||||
shift = uart_fdt_get_shift1(node);
|
||||
rv = clk_get_by_ofw_index(dev, 0, 0, &sc->clk);
|
||||
|
@ -39,7 +39,6 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/rman.h>
|
||||
|
||||
#include <machine/bus.h>
|
||||
#include <machine/fdt.h>
|
||||
|
||||
#include <dev/extres/clk/clk.h>
|
||||
#include <dev/extres/hwreset/hwreset.h>
|
||||
@ -291,6 +290,7 @@ struct usbphy_softc {
|
||||
};
|
||||
|
||||
static struct ofw_compat_data compat_data[] = {
|
||||
{"nvidia,tegra210-usb-phy", 1},
|
||||
{"nvidia,tegra30-usb-phy", 1},
|
||||
{NULL, 0},
|
||||
};
|
||||
|
@ -265,15 +265,11 @@ struct tegra_xusb_fw_hdr {
|
||||
uint8_t padding[137]; /* Pad to 256 bytes */
|
||||
};
|
||||
|
||||
/* Compatible devices. */
|
||||
static struct ofw_compat_data compat_data[] = {
|
||||
{"nvidia,tegra124-xusb", 1},
|
||||
{NULL, 0}
|
||||
};
|
||||
|
||||
struct xhci_soc;
|
||||
struct tegra_xhci_softc {
|
||||
struct xhci_softc xhci_softc;
|
||||
device_t dev;
|
||||
struct xhci_soc *soc;
|
||||
struct mtx mtx;
|
||||
struct resource *mem_res_fpci;
|
||||
struct resource *mem_res_ipfs;
|
||||
@ -288,26 +284,86 @@ struct tegra_xhci_softc {
|
||||
clk_t clk_xusb_fs_src;
|
||||
hwreset_t hwreset_xusb_host;
|
||||
hwreset_t hwreset_xusb_ss;
|
||||
regulator_t supply_avddio_pex;
|
||||
regulator_t supply_dvddio_pex;
|
||||
regulator_t supply_avdd_usb;
|
||||
regulator_t supply_avdd_pll_utmip;
|
||||
regulator_t supply_avdd_pll_erefe;
|
||||
regulator_t supply_avdd_usb_ss_pll;
|
||||
regulator_t supply_hvdd_usb_ss;
|
||||
regulator_t supply_hvdd_usb_ss_pll_e;
|
||||
phy_t phy_usb2_0;
|
||||
phy_t phy_usb2_1;
|
||||
phy_t phy_usb2_2;
|
||||
phy_t phy_usb3_0;
|
||||
regulator_t regulators[16]; /* Safe maximum */
|
||||
phy_t phys[8]; /* Safe maximum */
|
||||
|
||||
struct intr_config_hook irq_hook;
|
||||
bool xhci_inited;
|
||||
char *fw_name;
|
||||
vm_offset_t fw_vaddr;
|
||||
vm_size_t fw_size;
|
||||
};
|
||||
|
||||
struct xhci_soc {
|
||||
char *fw_name;
|
||||
char **regulator_names;
|
||||
char **phy_names;
|
||||
};
|
||||
|
||||
/* Tegra 124 config */
|
||||
static char *tegra124_reg_names[] = {
|
||||
"avddio-pex-supply",
|
||||
"dvddio-pex-supply",
|
||||
"avdd-usb-supply",
|
||||
"avdd-pll-utmip-supply",
|
||||
"avdd-pll-erefe-supply",
|
||||
"avdd-usb-ss-pll-supply",
|
||||
"hvdd-usb-ss-supply",
|
||||
"hvdd-usb-ss-pll-e-supply",
|
||||
NULL
|
||||
};
|
||||
|
||||
static char *tegra124_phy_names[] = {
|
||||
"usb2-0",
|
||||
"usb2-1",
|
||||
"usb2-2",
|
||||
"usb3-0",
|
||||
NULL
|
||||
};
|
||||
|
||||
static struct xhci_soc tegra124_soc =
|
||||
{
|
||||
.fw_name = "tegra124_xusb_fw",
|
||||
.regulator_names = tegra124_reg_names,
|
||||
.phy_names = tegra124_phy_names,
|
||||
};
|
||||
|
||||
/* Tegra 210 config */
|
||||
static char *tegra210_reg_names[] = {
|
||||
"dvddio-pex-supply",
|
||||
"hvddio-pex-supply",
|
||||
"avdd-usb-supply",
|
||||
"avdd-pll-utmip-supply",
|
||||
"avdd-pll-uerefe-supply",
|
||||
"dvdd-usb-ss-pll-supply",
|
||||
"hvdd-usb-ss-pll-e-supply",
|
||||
NULL
|
||||
};
|
||||
|
||||
static char *tegra210_phy_names[] = {
|
||||
"usb2-0",
|
||||
"usb2-1",
|
||||
"usb2-2",
|
||||
"usb2-3",
|
||||
"usb3-0",
|
||||
"usb3-1",
|
||||
NULL
|
||||
};
|
||||
|
||||
static struct xhci_soc tegra210_soc =
|
||||
{
|
||||
.fw_name = "tegra210_xusb_fw",
|
||||
.regulator_names = tegra210_reg_names,
|
||||
.phy_names = tegra210_phy_names,
|
||||
};
|
||||
|
||||
/* Compatible devices. */
|
||||
static struct ofw_compat_data compat_data[] = {
|
||||
{"nvidia,tegra124-xusb", (uintptr_t)&tegra124_soc},
|
||||
{"nvidia,tegra210-xusb", (uintptr_t)&tegra210_soc},
|
||||
{NULL, 0}
|
||||
};
|
||||
|
||||
|
||||
static uint32_t
|
||||
CSB_RD4(struct tegra_xhci_softc *sc, uint32_t addr)
|
||||
{
|
||||
@ -327,63 +383,23 @@ CSB_WR4(struct tegra_xhci_softc *sc, uint32_t addr, uint32_t val)
|
||||
static int
|
||||
get_fdt_resources(struct tegra_xhci_softc *sc, phandle_t node)
|
||||
{
|
||||
int rv;
|
||||
int i, rv;
|
||||
|
||||
rv = regulator_get_by_ofw_property(sc->dev, 0, "avddio-pex-supply",
|
||||
&sc->supply_avddio_pex);
|
||||
if (rv != 0) {
|
||||
device_printf(sc->dev,
|
||||
"Cannot get 'avddio-pex' regulator\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
rv = regulator_get_by_ofw_property(sc->dev, 0, "dvddio-pex-supply",
|
||||
&sc->supply_dvddio_pex);
|
||||
if (rv != 0) {
|
||||
device_printf(sc->dev,
|
||||
"Cannot get 'dvddio-pex' regulator\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
rv = regulator_get_by_ofw_property(sc->dev, 0, "avdd-usb-supply",
|
||||
&sc->supply_avdd_usb);
|
||||
if (rv != 0) {
|
||||
device_printf(sc->dev,
|
||||
"Cannot get 'avdd-usb' regulator\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
rv = regulator_get_by_ofw_property(sc->dev, 0, "avdd-pll-utmip-supply",
|
||||
&sc->supply_avdd_pll_utmip);
|
||||
if (rv != 0) {
|
||||
device_printf(sc->dev,
|
||||
"Cannot get 'avdd-pll-utmip' regulator\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
rv = regulator_get_by_ofw_property(sc->dev, 0, "avdd-pll-erefe-supply",
|
||||
&sc->supply_avdd_pll_erefe);
|
||||
if (rv != 0) {
|
||||
device_printf(sc->dev,
|
||||
"Cannot get 'avdd-pll-erefe' regulator\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
rv = regulator_get_by_ofw_property(sc->dev, 0, "avdd-usb-ss-pll-supply",
|
||||
&sc->supply_avdd_usb_ss_pll);
|
||||
if (rv != 0) {
|
||||
device_printf(sc->dev,
|
||||
"Cannot get 'avdd-usb-ss-pll' regulator\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
rv = regulator_get_by_ofw_property(sc->dev, 0, "hvdd-usb-ss-supply",
|
||||
&sc->supply_hvdd_usb_ss);
|
||||
if (rv != 0) {
|
||||
device_printf(sc->dev,
|
||||
"Cannot get 'hvdd-usb-ss' regulator\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
rv = regulator_get_by_ofw_property(sc->dev, 0,
|
||||
"hvdd-usb-ss-pll-e-supply", &sc->supply_hvdd_usb_ss_pll_e);
|
||||
if (rv != 0) {
|
||||
device_printf(sc->dev,
|
||||
"Cannot get 'hvdd-usb-ss-pll-e' regulator\n");
|
||||
return (ENXIO);
|
||||
/* 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);
|
||||
}
|
||||
}
|
||||
|
||||
rv = hwreset_get_by_ofw_name(sc->dev, 0, "xusb_host",
|
||||
@ -399,25 +415,20 @@ get_fdt_resources(struct tegra_xhci_softc *sc, phandle_t node)
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
rv = phy_get_by_ofw_name(sc->dev, 0, "usb2-0", &sc->phy_usb2_0);
|
||||
if (rv != 0) {
|
||||
device_printf(sc->dev, "Cannot get 'usb2-0' phy\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
rv = phy_get_by_ofw_name(sc->dev, 0, "usb2-1", &sc->phy_usb2_1);
|
||||
if (rv != 0) {
|
||||
device_printf(sc->dev, "Cannot get 'usb2-1' phy\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
rv = phy_get_by_ofw_name(sc->dev, 0, "usb2-2", &sc->phy_usb2_2);
|
||||
if (rv != 0) {
|
||||
device_printf(sc->dev, "Cannot get 'usb2-2' phy\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
rv = phy_get_by_ofw_name(sc->dev, 0, "usb3-0", &sc->phy_usb3_0);
|
||||
if (rv != 0) {
|
||||
device_printf(sc->dev, "Cannot get 'usb3-0' phy\n");
|
||||
return (ENXIO);
|
||||
/* Phys. */
|
||||
for (i = 0; sc->soc->phy_names[i] != NULL; i++) {
|
||||
if (i >= nitems(sc->phys)) {
|
||||
device_printf(sc->dev,
|
||||
"Too many phys present in DT.\n");
|
||||
return (EOVERFLOW);
|
||||
}
|
||||
rv = phy_get_by_ofw_name(sc->dev, 0, sc->soc->phy_names[i],
|
||||
sc->phys + i);
|
||||
if (rv != 0 && rv != ENOENT) {
|
||||
device_printf(sc->dev, "Cannot get '%s' phy.\n",
|
||||
sc->soc->phy_names[i]);
|
||||
return (ENXIO);
|
||||
}
|
||||
}
|
||||
|
||||
rv = clk_get_by_ofw_name(sc->dev, 0, "xusb_host",
|
||||
@ -450,8 +461,8 @@ get_fdt_resources(struct tegra_xhci_softc *sc, phandle_t node)
|
||||
device_printf(sc->dev, "Cannot get 'xusb_fs_src' clock\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
rv = clk_get_by_ofw_index_prop(sc->dev, 0, "freebsd,clock-xusb-gate", 0,
|
||||
&sc->clk_xusb_gate);
|
||||
/* Clock xusb_gate is missing in mainstream DT */
|
||||
rv = clk_get_by_name(sc->dev, "xusb_gate", &sc->clk_xusb_gate);
|
||||
if (rv != 0) {
|
||||
device_printf(sc->dev, "Cannot get 'xusb_gate' clock\n");
|
||||
return (ENXIO);
|
||||
@ -462,7 +473,7 @@ get_fdt_resources(struct tegra_xhci_softc *sc, phandle_t node)
|
||||
static int
|
||||
enable_fdt_resources(struct tegra_xhci_softc *sc)
|
||||
{
|
||||
int rv;
|
||||
int i, rv;
|
||||
|
||||
rv = hwreset_assert(sc->hwreset_xusb_host);
|
||||
if (rv != 0) {
|
||||
@ -475,53 +486,17 @@ enable_fdt_resources(struct tegra_xhci_softc *sc)
|
||||
return (rv);
|
||||
}
|
||||
|
||||
rv = regulator_enable(sc->supply_avddio_pex);
|
||||
if (rv != 0) {
|
||||
device_printf(sc->dev,
|
||||
"Cannot enable 'avddio_pex' regulator\n");
|
||||
return (rv);
|
||||
}
|
||||
rv = regulator_enable(sc->supply_dvddio_pex);
|
||||
if (rv != 0) {
|
||||
device_printf(sc->dev,
|
||||
"Cannot enable 'dvddio_pex' regulator\n");
|
||||
return (rv);
|
||||
}
|
||||
rv = regulator_enable(sc->supply_avdd_usb);
|
||||
if (rv != 0) {
|
||||
device_printf(sc->dev,
|
||||
"Cannot enable 'avdd_usb' regulator\n");
|
||||
return (rv);
|
||||
}
|
||||
rv = regulator_enable(sc->supply_avdd_pll_utmip);
|
||||
if (rv != 0) {
|
||||
device_printf(sc->dev,
|
||||
"Cannot enable 'avdd_pll_utmip-5v' regulator\n");
|
||||
return (rv);
|
||||
}
|
||||
rv = regulator_enable(sc->supply_avdd_pll_erefe);
|
||||
if (rv != 0) {
|
||||
device_printf(sc->dev,
|
||||
"Cannot enable 'avdd_pll_erefe' regulator\n");
|
||||
return (rv);
|
||||
}
|
||||
rv = regulator_enable(sc->supply_avdd_usb_ss_pll);
|
||||
if (rv != 0) {
|
||||
device_printf(sc->dev,
|
||||
"Cannot enable 'avdd_usb_ss_pll' regulator\n");
|
||||
return (rv);
|
||||
}
|
||||
rv = regulator_enable(sc->supply_hvdd_usb_ss);
|
||||
if (rv != 0) {
|
||||
device_printf(sc->dev,
|
||||
"Cannot enable 'hvdd_usb_ss' regulator\n");
|
||||
return (rv);
|
||||
}
|
||||
rv = regulator_enable(sc->supply_hvdd_usb_ss_pll_e);
|
||||
if (rv != 0) {
|
||||
device_printf(sc->dev,
|
||||
"Cannot enable 'hvdd_usb_ss_pll_e' regulator\n");
|
||||
return (rv);
|
||||
/* 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);
|
||||
}
|
||||
}
|
||||
|
||||
/* Power off XUSB host and XUSB SS domains. */
|
||||
@ -583,25 +558,16 @@ enable_fdt_resources(struct tegra_xhci_softc *sc)
|
||||
return (rv);
|
||||
}
|
||||
|
||||
rv = phy_enable(sc->phy_usb2_0);
|
||||
if (rv != 0) {
|
||||
device_printf(sc->dev, "Cannot enable USB2_0 phy\n");
|
||||
return (rv);
|
||||
}
|
||||
rv = phy_enable(sc->phy_usb2_1);
|
||||
if (rv != 0) {
|
||||
device_printf(sc->dev, "Cannot enable USB2_1 phy\n");
|
||||
return (rv);
|
||||
}
|
||||
rv = phy_enable(sc->phy_usb2_2);
|
||||
if (rv != 0) {
|
||||
device_printf(sc->dev, "Cannot enable USB2_2 phy\n");
|
||||
return (rv);
|
||||
}
|
||||
rv = phy_enable(sc->phy_usb3_0);
|
||||
if (rv != 0) {
|
||||
device_printf(sc->dev, "Cannot enable USB3_0 phy\n");
|
||||
return (rv);
|
||||
/* Phys. */
|
||||
for (i = 0; i < nitems(sc->phys); i++) {
|
||||
if (sc->phys[i] == NULL)
|
||||
continue;
|
||||
rv = phy_enable(sc->phys[i]);
|
||||
if (rv != 0) {
|
||||
device_printf(sc->dev, "Cannot enable '%s' phy\n",
|
||||
sc->soc->phy_names[i]);
|
||||
return (rv);
|
||||
}
|
||||
}
|
||||
|
||||
return (0);
|
||||
@ -797,7 +763,7 @@ load_fw(struct tegra_xhci_softc *sc)
|
||||
return (0);
|
||||
}
|
||||
|
||||
fw = firmware_get(sc->fw_name);
|
||||
fw = firmware_get(sc->soc->fw_name);
|
||||
if (fw == NULL) {
|
||||
device_printf(sc->dev, "Cannot read xusb firmware\n");
|
||||
return (ENOENT);
|
||||
@ -997,7 +963,8 @@ tegra_xhci_attach(device_t dev)
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
sc->dev = dev;
|
||||
sc->fw_name = "tegra124_xusb_fw";
|
||||
sc->soc = (struct xhci_soc *)ofw_bus_search_compatible(dev,
|
||||
compat_data)->ocd_data;
|
||||
node = ofw_bus_get_node(dev);
|
||||
xsc = &sc->xhci_softc;
|
||||
LOCK_INIT(sc);
|
||||
|
2950
sys/contrib/dev/nvidia/tegra210_xusb.bin.uu
Executable file
2950
sys/contrib/dev/nvidia/tegra210_xusb.bin.uu
Executable file
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,10 @@
|
||||
# $FreeBSD$
|
||||
# All the dts files for Nvidia ARM systems we support.
|
||||
DTS= \
|
||||
tegra124-jetson-tk1-fbsd.dts
|
||||
|
||||
.if ${MACHINE_ARCH} == "armv7"
|
||||
DTS= tegra124-jetson-tk1-fbsd.dts
|
||||
DTS+= tegra124-jetson-tk1.dts
|
||||
.elif ${MACHINE_ARCH} == "aarch64"
|
||||
DTS= nvidia/tegra210-p2371-2180.dts
|
||||
DTS+= nvidia/tegra210-p3450-0000.dts
|
||||
.endif
|
||||
.include <bsd.dtb.mk>
|
||||
|
Loading…
Reference in New Issue
Block a user