Compare commits
21 Commits
443c947541
...
2c90f5e347
| Author | SHA1 | Date | |
|---|---|---|---|
| 2c90f5e347 | |||
|
|
6aba9ba3f1 | ||
| a78a344fd0 | |||
| c1ee39366e | |||
|
|
3aa523ae1d | ||
|
|
a929bd5691 | ||
|
|
c40af5a19a | ||
|
|
51ab98c25e | ||
|
|
5f8f949eb9 | ||
|
|
93c3ba9fdf | ||
|
|
348ae91e1a | ||
|
|
8af3eba1f7 | ||
|
|
f83cd25494 | ||
|
|
e9c1ca6fac | ||
|
|
ddc4aa6226 | ||
|
|
0b7877f108 | ||
| 355f66d016 | |||
| 27390404e4 | |||
| b6d2c6e4c0 | |||
| fbbdd32f90 | |||
| aef62ecd2f |
@@ -12,10 +12,14 @@
|
|||||||
|
|
||||||
dc@54200000 {
|
dc@54200000 {
|
||||||
nvidia,outputs = <&dsia &dsib &sor1>;
|
nvidia,outputs = <&dsia &dsib &sor1>;
|
||||||
|
/delete-property/ interconnects;
|
||||||
|
/delete-property/ interconnect-names;
|
||||||
};
|
};
|
||||||
|
|
||||||
dc@54240000 {
|
dc@54240000 {
|
||||||
nvidia,outputs = <&dsia &dsib &sor1>;
|
nvidia,outputs = <&dsia &dsib &sor1>;
|
||||||
|
/delete-property/ interconnects;
|
||||||
|
/delete-property/ interconnect-names;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -29,14 +33,28 @@
|
|||||||
/delete-property/ pinctrl-names;
|
/delete-property/ pinctrl-names;
|
||||||
};
|
};
|
||||||
|
|
||||||
emc: external-memory-controller@7001b000 {
|
mc: memory-controller@70019000 {
|
||||||
compatible = "nvidia,tegra210b01-emc";
|
emc: external-memory-controller@7001b000 {
|
||||||
|
compatible = "nvidia,tegra210b01-emc";
|
||||||
|
reg = <0x0 0x7001b000 0x0 0x1000>,
|
||||||
|
<0x0 0x7001e000 0x0 0x1000>,
|
||||||
|
<0x0 0x7001f000 0x0 0x1000>;
|
||||||
|
clocks = <&bpmp 0>;
|
||||||
|
clock-names = "emc";
|
||||||
|
interrupts = <GIC_SPI 78 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
|
|
||||||
clocks = <&bpmp 0>;
|
#interconnect-cells = <0>;
|
||||||
clock-names = "emc";
|
#cooling-cells = <2>;
|
||||||
|
|
||||||
nvidia,bpmp = <&bpmp>;
|
nvidia,bpmp = <&bpmp>;
|
||||||
/delete-property/ operating-points-v2;
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/delete-node/ external-memory-controller@7001b000;
|
||||||
|
|
||||||
|
actmon@6000c800 {
|
||||||
|
clocks = <&tegra_car TEGRA210_CLK_ACTMON>,
|
||||||
|
<&bpmp 0>;
|
||||||
};
|
};
|
||||||
|
|
||||||
mmc@700b0600 {
|
mmc@700b0600 {
|
||||||
@@ -89,7 +107,7 @@
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
bpmp@70016000 {
|
bpmp: bpmp@70016000 {
|
||||||
status = "okay";
|
status = "okay";
|
||||||
|
|
||||||
#clock-cells = <1>;
|
#clock-cells = <1>;
|
||||||
@@ -105,35 +123,31 @@
|
|||||||
|
|
||||||
pinmux@700008d4 {
|
pinmux@700008d4 {
|
||||||
status = "okay";
|
status = "okay";
|
||||||
sdmmc1_drv_code_1_8V: sdmmc1_drv_code {
|
sdmmc1_1v8_drv: pinmux-sdmmc1-1v8-drv {
|
||||||
sdmmc1 {
|
sdmmc1 {
|
||||||
nvidia,pins = "drive_sdmmc1";
|
nvidia,pull-down-strength = <0x8>;
|
||||||
nvidia,pull-down-strength = <8>;
|
nvidia,pull-up-strength = <0x8>;
|
||||||
nvidia,pull-up-strength = <8>;
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
sdmmc1_default_drv_code_3_3V: sdmmc1_default_drv_code {
|
sdmmc1_3v3_drv: pinmux-sdmmc1-3v3-drv {
|
||||||
sdmmc1 {
|
sdmmc1 {
|
||||||
nvidia,pins = "drive_sdmmc1";
|
nvidia,pull-down-strength = <0x8>;
|
||||||
nvidia,pull-down-strength = <8>;
|
nvidia,pull-up-strength = <0x8>;
|
||||||
nvidia,pull-up-strength = <8>;
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
sdmmc3_drv_code_1_8V: sdmmc3_drv_code {
|
sdmmc3_1v8_drv: pinmux-sdmmc3-1v8-drv {
|
||||||
sdmmc3 {
|
sdmmc3 {
|
||||||
nvidia,pins = "drive_sdmmc3";
|
nvidia,pull-down-strength = <0x8>;
|
||||||
nvidia,pull-down-strength = <8>;
|
nvidia,pull-up-strength = <0x8>;
|
||||||
nvidia,pull-up-strength = <8>;
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
sdmmc3_default_drv_code_3_3V: sdmmc3_default_drv_code {
|
sdmmc3_3v3_drv: pinmux-sdmmc3-3v3-drv {
|
||||||
sdmmc3 {
|
sdmmc3 {
|
||||||
nvidia,pins = "drive_sdmmc3";
|
nvidia,pull-down-strength = <0x8>;
|
||||||
nvidia,pull-down-strength = <8>;
|
nvidia,pull-up-strength = <0x8>;
|
||||||
nvidia,pull-up-strength = <8>;
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -2173,6 +2173,15 @@ static int fw_devlink_create_devlink(struct device *con,
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SYNC_STATE_ONLY links are useless once a consumer device has probed.
|
||||||
|
* So, only create it if the consumer hasn't probed yet.
|
||||||
|
*/
|
||||||
|
if (flags & DL_FLAG_SYNC_STATE_ONLY &&
|
||||||
|
con->links.status != DL_DEV_NO_DRIVER &&
|
||||||
|
con->links.status != DL_DEV_PROBING)
|
||||||
|
goto out;
|
||||||
|
|
||||||
if (con != sup_dev && !device_link_add(con, sup_dev, flags)) {
|
if (con != sup_dev && !device_link_add(con, sup_dev, flags)) {
|
||||||
dev_err(con, "Failed to create device link (0x%x) with %s\n",
|
dev_err(con, "Failed to create device link (0x%x) with %s\n",
|
||||||
flags, dev_name(sup_dev));
|
flags, dev_name(sup_dev));
|
||||||
|
|||||||
@@ -503,6 +503,72 @@ static unsigned long tegra210_input_freq[] = {
|
|||||||
#define PLLE_SS_COEFFICIENTS_VAL \
|
#define PLLE_SS_COEFFICIENTS_VAL \
|
||||||
(PLLE_SS_MAX_VAL | PLLE_SS_INC_VAL | PLLE_SS_INCINTRV_VAL)
|
(PLLE_SS_MAX_VAL | PLLE_SS_INC_VAL | PLLE_SS_INCINTRV_VAL)
|
||||||
|
|
||||||
|
bool tegra210b01_plle_hw_sequence_is_enabled(void)
|
||||||
|
{
|
||||||
|
u32 value;
|
||||||
|
|
||||||
|
value = readl_relaxed(clk_base + PLLE_AUX);
|
||||||
|
if (value & PLLE_AUX_SEQ_ENABLE)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(tegra210b01_plle_hw_sequence_is_enabled);
|
||||||
|
|
||||||
|
int tegra210b01_plle_hw_sequence_start(void)
|
||||||
|
{
|
||||||
|
u32 value;
|
||||||
|
|
||||||
|
if (tegra210b01_plle_hw_sequence_is_enabled())
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* skip if PLLE is not enabled yet */
|
||||||
|
value = readl_relaxed(clk_base + PLLE_MISC0);
|
||||||
|
if (!(value & PLLE_MISC_LOCK))
|
||||||
|
return -EIO;
|
||||||
|
|
||||||
|
value &= ~PLLE_MISC_IDDQ_SW_CTRL;
|
||||||
|
writel_relaxed(value, clk_base + PLLE_MISC0);
|
||||||
|
|
||||||
|
value = readl_relaxed(clk_base + PLLE_AUX);
|
||||||
|
value |= (PLLE_AUX_USE_LOCKDET | PLLE_AUX_SS_SEQ_INCLUDE);
|
||||||
|
value &= ~(PLLE_AUX_ENABLE_SWCTL | PLLE_AUX_SS_SWCTL);
|
||||||
|
writel_relaxed(value, clk_base + PLLE_AUX);
|
||||||
|
|
||||||
|
fence_udelay(1, clk_base);
|
||||||
|
|
||||||
|
value |= PLLE_AUX_SEQ_ENABLE;
|
||||||
|
writel_relaxed(value, clk_base + PLLE_AUX);
|
||||||
|
|
||||||
|
fence_udelay(1, clk_base);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(tegra210b01_plle_hw_sequence_start);
|
||||||
|
|
||||||
|
void tegra210b01_xusb_pll_hw_control_enable(void)
|
||||||
|
{
|
||||||
|
u32 val;
|
||||||
|
|
||||||
|
val = readl_relaxed(clk_base + XUSBIO_PLL_CFG0);
|
||||||
|
val &= ~(XUSBIO_PLL_CFG0_CLK_ENABLE_SWCTL |
|
||||||
|
XUSBIO_PLL_CFG0_PADPLL_RESET_SWCTL);
|
||||||
|
val |= XUSBIO_PLL_CFG0_PADPLL_USE_LOCKDET |
|
||||||
|
XUSBIO_PLL_CFG0_PADPLL_SLEEP_IDDQ;
|
||||||
|
writel_relaxed(val, clk_base + XUSBIO_PLL_CFG0);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(tegra210b01_xusb_pll_hw_control_enable);
|
||||||
|
|
||||||
|
void tegra210b01_xusb_pll_hw_sequence_start(void)
|
||||||
|
{
|
||||||
|
u32 val;
|
||||||
|
|
||||||
|
val = readl_relaxed(clk_base + XUSBIO_PLL_CFG0);
|
||||||
|
val |= XUSBIO_PLL_CFG0_SEQ_ENABLE;
|
||||||
|
writel_relaxed(val, clk_base + XUSBIO_PLL_CFG0);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(tegra210b01_xusb_pll_hw_sequence_start);
|
||||||
|
|
||||||
static inline void _pll_misc_chk_default(void __iomem *base,
|
static inline void _pll_misc_chk_default(void __iomem *base,
|
||||||
struct tegra_clk_pll_params *params,
|
struct tegra_clk_pll_params *params,
|
||||||
u8 misc_num, u32 default_val, u32 mask)
|
u8 misc_num, u32 default_val, u32 mask)
|
||||||
|
|||||||
@@ -395,8 +395,12 @@ static int tegra_emc_interconnect_init(struct tegra186_emc *emc)
|
|||||||
emc->provider.xlate = tegra_emc_of_icc_xlate;
|
emc->provider.xlate = tegra_emc_of_icc_xlate;
|
||||||
emc->provider.get_bw = tegra_emc_icc_get_init_bw;
|
emc->provider.get_bw = tegra_emc_icc_get_init_bw;
|
||||||
|
|
||||||
|
printk("186-emc: init icc provider\n");
|
||||||
|
|
||||||
icc_provider_init(&emc->provider);
|
icc_provider_init(&emc->provider);
|
||||||
|
|
||||||
|
printk("186-emc: create icc node\n");
|
||||||
|
|
||||||
/* create External Memory Controller node */
|
/* create External Memory Controller node */
|
||||||
node = icc_node_create(TEGRA_ICC_EMC);
|
node = icc_node_create(TEGRA_ICC_EMC);
|
||||||
if (IS_ERR(node)) {
|
if (IS_ERR(node)) {
|
||||||
@@ -404,14 +408,20 @@ static int tegra_emc_interconnect_init(struct tegra186_emc *emc)
|
|||||||
goto err_msg;
|
goto err_msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
printk("186-emc: add icc node\n");
|
||||||
|
|
||||||
node->name = "External Memory Controller";
|
node->name = "External Memory Controller";
|
||||||
icc_node_add(node, &emc->provider);
|
icc_node_add(node, &emc->provider);
|
||||||
|
|
||||||
|
printk("186-emc: link emc icc to dram\n");
|
||||||
|
|
||||||
/* link External Memory Controller to External Memory (DRAM) */
|
/* link External Memory Controller to External Memory (DRAM) */
|
||||||
err = icc_link_create(node, TEGRA_ICC_EMEM);
|
err = icc_link_create(node, TEGRA_ICC_EMEM);
|
||||||
if (err)
|
if (err)
|
||||||
goto remove_nodes;
|
goto remove_nodes;
|
||||||
|
|
||||||
|
printk("186-emc: create dram node\n");
|
||||||
|
|
||||||
/* create External Memory node */
|
/* create External Memory node */
|
||||||
node = icc_node_create(TEGRA_ICC_EMEM);
|
node = icc_node_create(TEGRA_ICC_EMEM);
|
||||||
if (IS_ERR(node)) {
|
if (IS_ERR(node)) {
|
||||||
@@ -419,16 +429,23 @@ static int tegra_emc_interconnect_init(struct tegra186_emc *emc)
|
|||||||
goto remove_nodes;
|
goto remove_nodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
printk("186-emc: add dram node\n");
|
||||||
|
|
||||||
node->name = "External Memory (DRAM)";
|
node->name = "External Memory (DRAM)";
|
||||||
icc_node_add(node, &emc->provider);
|
icc_node_add(node, &emc->provider);
|
||||||
|
|
||||||
|
printk("186-emc: register icc provider\n");
|
||||||
|
|
||||||
err = icc_provider_register(&emc->provider);
|
err = icc_provider_register(&emc->provider);
|
||||||
if (err)
|
if (err)
|
||||||
goto remove_nodes;
|
goto remove_nodes;
|
||||||
|
|
||||||
|
printk("186-emc: icc init success\n");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
remove_nodes:
|
remove_nodes:
|
||||||
|
printk("186-emc: removing icc nodes\n");
|
||||||
icc_nodes_remove(&emc->provider);
|
icc_nodes_remove(&emc->provider);
|
||||||
err_msg:
|
err_msg:
|
||||||
dev_err(emc->dev, "failed to initialize ICC: %d\n", err);
|
dev_err(emc->dev, "failed to initialize ICC: %d\n", err);
|
||||||
@@ -460,16 +477,24 @@ static int tegra186_emc_probe(struct platform_device *pdev)
|
|||||||
platform_set_drvdata(pdev, emc);
|
platform_set_drvdata(pdev, emc);
|
||||||
emc->dev = &pdev->dev;
|
emc->dev = &pdev->dev;
|
||||||
|
|
||||||
|
printk("186-emc: emc_rate_requests_init\n");
|
||||||
|
|
||||||
tegra_emc_rate_requests_init(emc);
|
tegra_emc_rate_requests_init(emc);
|
||||||
|
|
||||||
|
printk("186-emc: mrq supported?\n");
|
||||||
|
|
||||||
if (tegra_bpmp_mrq_is_supported(emc->bpmp, MRQ_EMC_DVFS_LATENCY)) {
|
if (tegra_bpmp_mrq_is_supported(emc->bpmp, MRQ_EMC_DVFS_LATENCY)) {
|
||||||
|
printk("186-emc: mrq supported\n");
|
||||||
err = tegra186_emc_get_emc_dvfs_latency(emc);
|
err = tegra186_emc_get_emc_dvfs_latency(emc);
|
||||||
if (err)
|
if (err)
|
||||||
goto put_bpmp;
|
goto put_bpmp;
|
||||||
|
printk("186-emc: got emc dvfs latency\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mc && mc->soc->icc_ops) {
|
if (mc && mc->soc->icc_ops) {
|
||||||
|
printk("186-emc: icc ops -> mrq supported?\n");
|
||||||
if (tegra_bpmp_mrq_is_supported(emc->bpmp, MRQ_BWMGR_INT)) {
|
if (tegra_bpmp_mrq_is_supported(emc->bpmp, MRQ_BWMGR_INT)) {
|
||||||
|
printk("186-emc: mrq supported, configuring mc\n");
|
||||||
mc->bwmgr_mrq_supported = true;
|
mc->bwmgr_mrq_supported = true;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -481,6 +506,8 @@ static int tegra186_emc_probe(struct platform_device *pdev)
|
|||||||
barrier();
|
barrier();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
printk("186-emc: init emc interconnect\n");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initialize the ICC even if BPMP-FW doesn't support 'MRQ_BWMGR_INT'.
|
* Initialize the ICC even if BPMP-FW doesn't support 'MRQ_BWMGR_INT'.
|
||||||
* Use the flag 'mc->bwmgr_mrq_supported' within MC driver and return
|
* Use the flag 'mc->bwmgr_mrq_supported' within MC driver and return
|
||||||
@@ -497,6 +524,7 @@ static int tegra186_emc_probe(struct platform_device *pdev)
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
put_bpmp:
|
put_bpmp:
|
||||||
|
printk("186-emc: FAILED\n");
|
||||||
tegra_bpmp_put(emc->bpmp);
|
tegra_bpmp_put(emc->bpmp);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
* Author: Mike Rapoport <mike@compulab.co.il>
|
* Author: Mike Rapoport <mike@compulab.co.il>
|
||||||
*
|
*
|
||||||
* Based on NVIDIA PCIe driver
|
* Based on NVIDIA PCIe driver
|
||||||
* Copyright (c) 2008-2009, NVIDIA Corporation.
|
* Copyright (c) 2008-2020, NVIDIA Corporation.
|
||||||
*
|
*
|
||||||
* Bits taken from arch/arm/mach-dove/pcie.c
|
* Bits taken from arch/arm/mach-dove/pcie.c
|
||||||
*
|
*
|
||||||
@@ -163,10 +163,64 @@
|
|||||||
|
|
||||||
#define AFI_PLLE_CONTROL 0x160
|
#define AFI_PLLE_CONTROL 0x160
|
||||||
#define AFI_PLLE_CONTROL_BYPASS_PADS2PLLE_CONTROL (1 << 9)
|
#define AFI_PLLE_CONTROL_BYPASS_PADS2PLLE_CONTROL (1 << 9)
|
||||||
|
#define AFI_PLLE_CONTROL_BYPASS_PCIE2PLLE_CONTROL (1 << 8)
|
||||||
#define AFI_PLLE_CONTROL_PADS2PLLE_CONTROL_EN (1 << 1)
|
#define AFI_PLLE_CONTROL_PADS2PLLE_CONTROL_EN (1 << 1)
|
||||||
|
#define AFI_PLLE_CONTROL_PCIE2PLLE_CONTROL_EN (1 << 0)
|
||||||
|
|
||||||
#define AFI_PEXBIAS_CTRL_0 0x168
|
#define AFI_PEXBIAS_CTRL_0 0x168
|
||||||
|
|
||||||
|
|
||||||
|
#define RP_PRIV_XP_DL 0x00000494
|
||||||
|
#define RP_PRIV_XP_DL_GEN2_UPD_FC_TSHOLD (0x1ff << 1)
|
||||||
|
|
||||||
|
#define RP_L1_PM_SUBSTATES_CTL 0xc00
|
||||||
|
#define RP_L1_PM_SUBSTATES_CTL_PCI_PM_L1_2 (0x1 << 0)
|
||||||
|
#define RP_L1_PM_SUBSTATES_CTL_PCI_PM_L1_1 (0x1 << 1)
|
||||||
|
#define RP_L1_PM_SUBSTATES_CTL_ASPM_L1_2 (0x1 << 2)
|
||||||
|
#define RP_L1_PM_SUBSTATES_CTL_ASPM_L1_1 (0x1 << 3)
|
||||||
|
#define RP_L1_PM_SUBSTATES_CTL_CM_RTIME_MASK (0xff << 8)
|
||||||
|
#define RP_L1_PM_SUBSTATES_CTL_CM_RTIME_SHIFT 8
|
||||||
|
#define RP_L1_PM_SUBSTATES_CTL_T_PWRN_SCL_MASK (0x3 << 16)
|
||||||
|
#define RP_L1_PM_SUBSTATES_CTL_T_PWRN_SCL_SHIFT 16
|
||||||
|
#define RP_L1_PM_SUBSTATES_CTL_T_PWRN_VAL_MASK (0x1f << 19)
|
||||||
|
#define RP_L1_PM_SUBSTATES_CTL_T_PWRN_VAL_SHIFT 19
|
||||||
|
#define RP_L1_PM_SUBSTATES_CTL_HIDE_CAP (0x1 << 24)
|
||||||
|
|
||||||
|
#define RP_L1_PM_SUBSTATES_1_CTL 0xc04
|
||||||
|
#define RP_L1_PM_SUBSTATES_1_CTL_PWR_OFF_DLY_MASK 0x1fff
|
||||||
|
#define RP_L1_PM_SUBSTATES_1_CTL_PWR_OFF_DLY 0x26
|
||||||
|
#define RP_L1SS_1_CTL_CLKREQ_ASSERTED_DLY_MASK (0x1ff << 13)
|
||||||
|
#define RP_L1SS_1_CTL_CLKREQ_ASSERTED_DLY (0x27 << 13)
|
||||||
|
|
||||||
|
#define RP_L1_PM_SUBSTATES_2_CTL 0xc08
|
||||||
|
#define RP_L1_PM_SUBSTATES_2_CTL_T_L1_2_DLY_MASK 0x1fff
|
||||||
|
#define RP_L1_PM_SUBSTATES_2_CTL_T_L1_2_DLY 0x4d
|
||||||
|
#define RP_L1_PM_SUBSTATES_2_CTL_MICROSECOND_MASK (0xff << 13)
|
||||||
|
#define RP_L1_PM_SUBSTATES_2_CTL_MICROSECOND (0x13 << 13)
|
||||||
|
#define RP_L1_PM_SUBSTATES_2_CTL_MICROSECOND_COMP_MASK (0xf << 21)
|
||||||
|
#define RP_L1_PM_SUBSTATES_2_CTL_MICROSECOND_COMP (0x2 << 21)
|
||||||
|
|
||||||
|
#define RP_RX_HDR_LIMIT 0x00000e00
|
||||||
|
#define RP_RX_HDR_LIMIT_PW_MASK (0xff << 8)
|
||||||
|
#define RP_RX_HDR_LIMIT_PW (0x0e << 8)
|
||||||
|
|
||||||
|
#define RP_TIMEOUT0 0xe24
|
||||||
|
#define RP_TIMEOUT0_PAD_PWRUP_MASK 0xff
|
||||||
|
#define RP_TIMEOUT0_PAD_PWRUP 0xa
|
||||||
|
#define RP_TIMEOUT0_PAD_PWRUP_CM_MASK 0xffff00
|
||||||
|
#define RP_TIMEOUT0_PAD_PWRUP_CM (0x180 << 8)
|
||||||
|
#define RP_TIMEOUT0_PAD_SPDCHNG_GEN2_MASK (0xff << 24)
|
||||||
|
#define RP_TIMEOUT0_PAD_SPDCHNG_GEN2 (0xa << 24)
|
||||||
|
|
||||||
|
#define RP_TIMEOUT1 0xe28
|
||||||
|
#define RP_TIMEOUT1_RCVRY_SPD_SUCCESS_EIDLE_MASK (0xff << 16)
|
||||||
|
#define RP_TIMEOUT1_RCVRY_SPD_SUCCESS_EIDLE (0x10 << 16)
|
||||||
|
#define RP_TIMEOUT1_RCVRY_SPD_UNSUCCESS_EIDLE_MASK (0xff << 24)
|
||||||
|
#define RP_TIMEOUT1_RCVRY_SPD_UNSUCCESS_EIDLE (0x74 << 24)
|
||||||
|
|
||||||
|
#define RP_ECTL_1_R1 0x00000e80
|
||||||
|
#define RP_ECTL_1_R1_TX_DRV_AMP_1C_MASK 0x3f
|
||||||
|
|
||||||
#define RP_ECTL_2_R1 0x00000e84
|
#define RP_ECTL_2_R1 0x00000e84
|
||||||
#define RP_ECTL_2_R1_RX_CTLE_1C_MASK 0xffff
|
#define RP_ECTL_2_R1_RX_CTLE_1C_MASK 0xffff
|
||||||
|
|
||||||
@@ -180,6 +234,9 @@
|
|||||||
#define RP_ECTL_6_R1 0x00000e94
|
#define RP_ECTL_6_R1 0x00000e94
|
||||||
#define RP_ECTL_6_R1_RX_EQ_CTRL_H_1C_MASK 0xffffffff
|
#define RP_ECTL_6_R1_RX_EQ_CTRL_H_1C_MASK 0xffffffff
|
||||||
|
|
||||||
|
#define RP_ECTL_1_R2 0x00000ea0
|
||||||
|
#define RP_ECTL_1_R2_TX_DRV_AMP_1C_MASK 0x3f
|
||||||
|
|
||||||
#define RP_ECTL_2_R2 0x00000ea4
|
#define RP_ECTL_2_R2 0x00000ea4
|
||||||
#define RP_ECTL_2_R2_RX_CTLE_1C_MASK 0xffff
|
#define RP_ECTL_2_R2_RX_CTLE_1C_MASK 0xffff
|
||||||
|
|
||||||
@@ -199,6 +256,19 @@
|
|||||||
#define RP_VEND_XP_OPPORTUNISTIC_UPDATEFC (1 << 28)
|
#define RP_VEND_XP_OPPORTUNISTIC_UPDATEFC (1 << 28)
|
||||||
#define RP_VEND_XP_UPDATE_FC_THRESHOLD_MASK (0xff << 18)
|
#define RP_VEND_XP_UPDATE_FC_THRESHOLD_MASK (0xff << 18)
|
||||||
|
|
||||||
|
#define RP_VEND_XP1 0xf04
|
||||||
|
#define RP_VEND_XP1_LINK_PVT_CTL_IGNORE_L0S (1 << 23)
|
||||||
|
#define RP_VEND_XP1_LINK_PVT_CTL_L1_ASPM_SUPPORT (1 << 21)
|
||||||
|
|
||||||
|
|
||||||
|
#define RP_XP_REF 0xf30
|
||||||
|
#define RP_XP_REF_MICROSECOND_LIMIT_MASK 0xff
|
||||||
|
#define RP_XP_REF_MICROSECOND_LIMIT 0x14
|
||||||
|
#define RP_XP_REF_MICROSECOND_ENABLE (1 << 8)
|
||||||
|
#define RP_XP_REF_CPL_TO_OVERRIDE (1 << 13)
|
||||||
|
#define RP_XP_REF_CPL_TO_CUSTOM_VALUE_MASK (0x1ffff << 14)
|
||||||
|
#define RP_XP_REF_CPL_TO_CUSTOM_VALUE (0x1770 << 14)
|
||||||
|
|
||||||
#define RP_VEND_CTL0 0x00000f44
|
#define RP_VEND_CTL0 0x00000f44
|
||||||
#define RP_VEND_CTL0_DSK_RST_PULSE_WIDTH_MASK (0xf << 12)
|
#define RP_VEND_CTL0_DSK_RST_PULSE_WIDTH_MASK (0xf << 12)
|
||||||
#define RP_VEND_CTL0_DSK_RST_PULSE_WIDTH (0x9 << 12)
|
#define RP_VEND_CTL0_DSK_RST_PULSE_WIDTH (0x9 << 12)
|
||||||
@@ -222,12 +292,23 @@
|
|||||||
#define RP_PRIV_MISC_TMS_CLK_CLAMP_THRESHOLD (0xf << 24)
|
#define RP_PRIV_MISC_TMS_CLK_CLAMP_THRESHOLD (0xf << 24)
|
||||||
#define RP_PRIV_MISC_TMS_CLK_CLAMP_ENABLE (1 << 31)
|
#define RP_PRIV_MISC_TMS_CLK_CLAMP_ENABLE (1 << 31)
|
||||||
|
|
||||||
|
#define RP_VEND_XP_PAD_PWRDN 0x00000f50
|
||||||
|
#define RP_VEND_XP_PAD_PWRDN_L1_EN (1 << 0)
|
||||||
|
#define RP_VEND_XP_PAD_PWRDN_DYNAMIC_EN (1 << 1)
|
||||||
|
#define RP_VEND_XP_PAD_PWRDN_DISABLED_EN (1 << 2)
|
||||||
|
#define RP_VEND_XP_PAD_PWRDN_L1_CLKREQ_EN (1 << 15)
|
||||||
|
#define RP_VEND_XP_PAD_PWRDN_SLEEP_MODE_DYNAMIC_L1PP (3 << 5)
|
||||||
|
#define RP_VEND_XP_PAD_PWRDN_SLEEP_MODE_L1_L1PP (3 << 3)
|
||||||
|
#define RP_VEND_XP_PAD_PWRDN_SLEEP_MODE_L1_CLKREQ_L1PP (3 << 16)
|
||||||
|
|
||||||
#define RP_LINK_CONTROL_STATUS 0x00000090
|
#define RP_LINK_CONTROL_STATUS 0x00000090
|
||||||
#define RP_LINK_CONTROL_STATUS_DL_LINK_ACTIVE 0x20000000
|
#define RP_LINK_CONTROL_STATUS_DL_LINK_ACTIVE 0x20000000
|
||||||
#define RP_LINK_CONTROL_STATUS_LINKSTAT_MASK 0x3fff0000
|
#define RP_LINK_CONTROL_STATUS_LINKSTAT_MASK 0x3fff0000
|
||||||
|
|
||||||
#define RP_LINK_CONTROL_STATUS_2 0x000000b0
|
#define RP_LINK_CONTROL_STATUS_2 0x000000b0
|
||||||
|
|
||||||
|
#define RP_L1_PM_SUBSTATES_CAP 0x144
|
||||||
|
|
||||||
#define PADS_CTL_SEL 0x0000009c
|
#define PADS_CTL_SEL 0x0000009c
|
||||||
|
|
||||||
#define PADS_CTL 0x000000a0
|
#define PADS_CTL 0x000000a0
|
||||||
@@ -304,12 +385,18 @@ struct tegra_pcie_soc {
|
|||||||
bool program_deskew_time;
|
bool program_deskew_time;
|
||||||
bool update_fc_timer;
|
bool update_fc_timer;
|
||||||
bool has_cache_bars;
|
bool has_cache_bars;
|
||||||
|
bool enable_wrap;
|
||||||
|
bool has_aspm_l1;
|
||||||
|
bool has_aspm_l1ss;
|
||||||
|
bool l1ss_rp_wake_fixup;
|
||||||
struct {
|
struct {
|
||||||
struct {
|
struct {
|
||||||
|
u32 rp_ectl_1_r1;
|
||||||
u32 rp_ectl_2_r1;
|
u32 rp_ectl_2_r1;
|
||||||
u32 rp_ectl_4_r1;
|
u32 rp_ectl_4_r1;
|
||||||
u32 rp_ectl_5_r1;
|
u32 rp_ectl_5_r1;
|
||||||
u32 rp_ectl_6_r1;
|
u32 rp_ectl_6_r1;
|
||||||
|
u32 rp_ectl_1_r2;
|
||||||
u32 rp_ectl_2_r2;
|
u32 rp_ectl_2_r2;
|
||||||
u32 rp_ectl_4_r2;
|
u32 rp_ectl_4_r2;
|
||||||
u32 rp_ectl_5_r2;
|
u32 rp_ectl_5_r2;
|
||||||
@@ -366,6 +453,8 @@ struct tegra_pcie_port {
|
|||||||
void __iomem *base;
|
void __iomem *base;
|
||||||
unsigned int index;
|
unsigned int index;
|
||||||
unsigned int lanes;
|
unsigned int lanes;
|
||||||
|
unsigned int aspm_state;
|
||||||
|
bool supports_clkreq;
|
||||||
|
|
||||||
struct phy **phys;
|
struct phy **phys;
|
||||||
|
|
||||||
@@ -394,6 +483,14 @@ static inline u32 pads_readl(struct tegra_pcie *pcie, unsigned long offset)
|
|||||||
return readl(pcie->pads + offset);
|
return readl(pcie->pads + offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool tegra_pcie_link_up(struct tegra_pcie_port *port)
|
||||||
|
{
|
||||||
|
u32 value;
|
||||||
|
|
||||||
|
value = readl(port->base + RP_LINK_CONTROL_STATUS);
|
||||||
|
return !!(value & RP_LINK_CONTROL_STATUS_DL_LINK_ACTIVE);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The configuration space mapping on Tegra is somewhat similar to the ECAM
|
* The configuration space mapping on Tegra is somewhat similar to the ECAM
|
||||||
* defined by PCIe. However it deviates a bit in how the 4 bits for extended
|
* defined by PCIe. However it deviates a bit in how the 4 bits for extended
|
||||||
@@ -459,20 +556,50 @@ static void __iomem *tegra_pcie_map_bus(struct pci_bus *bus,
|
|||||||
static int tegra_pcie_config_read(struct pci_bus *bus, unsigned int devfn,
|
static int tegra_pcie_config_read(struct pci_bus *bus, unsigned int devfn,
|
||||||
int where, int size, u32 *value)
|
int where, int size, u32 *value)
|
||||||
{
|
{
|
||||||
|
struct tegra_pcie *pcie = bus->sysdata;
|
||||||
|
struct pci_dev *bridge;
|
||||||
|
struct tegra_pcie_port *port;
|
||||||
|
|
||||||
if (bus->number == 0)
|
if (bus->number == 0)
|
||||||
return pci_generic_config_read32(bus, devfn, where, size,
|
return pci_generic_config_read32(bus, devfn, where, size,
|
||||||
value);
|
value);
|
||||||
|
|
||||||
|
bridge = pcie_find_root_port(bus->self);
|
||||||
|
|
||||||
|
list_for_each_entry(port, &pcie->ports, list)
|
||||||
|
if (port->index + 1 == PCI_SLOT(bridge->devfn))
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* If there is no link, then there is no device */
|
||||||
|
if (!tegra_pcie_link_up(port)) {
|
||||||
|
*value = 0xffffffff;
|
||||||
|
return PCIBIOS_DEVICE_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
return pci_generic_config_read(bus, devfn, where, size, value);
|
return pci_generic_config_read(bus, devfn, where, size, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int tegra_pcie_config_write(struct pci_bus *bus, unsigned int devfn,
|
static int tegra_pcie_config_write(struct pci_bus *bus, unsigned int devfn,
|
||||||
int where, int size, u32 value)
|
int where, int size, u32 value)
|
||||||
{
|
{
|
||||||
|
struct tegra_pcie *pcie = bus->sysdata;
|
||||||
|
struct tegra_pcie_port *port;
|
||||||
|
struct pci_dev *bridge;
|
||||||
|
|
||||||
if (bus->number == 0)
|
if (bus->number == 0)
|
||||||
return pci_generic_config_write32(bus, devfn, where, size,
|
return pci_generic_config_write32(bus, devfn, where, size,
|
||||||
value);
|
value);
|
||||||
|
|
||||||
|
bridge = pcie_find_root_port(bus->self);
|
||||||
|
|
||||||
|
list_for_each_entry(port, &pcie->ports, list)
|
||||||
|
if (port->index + 1 == PCI_SLOT(bridge->devfn))
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* If there is no link, then there is no device */
|
||||||
|
if (!tegra_pcie_link_up(port))
|
||||||
|
return PCIBIOS_DEVICE_NOT_FOUND;
|
||||||
|
|
||||||
return pci_generic_config_write(bus, devfn, where, size, value);
|
return pci_generic_config_write(bus, devfn, where, size, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -529,6 +656,44 @@ static void tegra_pcie_port_reset(struct tegra_pcie_port *port)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void disable_aspm_l0s(struct tegra_pcie_port *port)
|
||||||
|
{
|
||||||
|
u32 val = 0;
|
||||||
|
|
||||||
|
val = readl(port->base + RP_VEND_XP1);
|
||||||
|
val |= RP_VEND_XP1_LINK_PVT_CTL_IGNORE_L0S;
|
||||||
|
writel(val, port->base + RP_VEND_XP1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void disable_aspm_l10(struct tegra_pcie_port *port)
|
||||||
|
{
|
||||||
|
u32 val = 0;
|
||||||
|
|
||||||
|
val = readl(port->base + RP_VEND_XP1);
|
||||||
|
val &= ~RP_VEND_XP1_LINK_PVT_CTL_L1_ASPM_SUPPORT;
|
||||||
|
writel(val, port->base + RP_VEND_XP1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void disable_aspm_l11(struct tegra_pcie_port *port)
|
||||||
|
{
|
||||||
|
u32 val = 0;
|
||||||
|
|
||||||
|
val = readl(port->base + RP_L1_PM_SUBSTATES_CTL);
|
||||||
|
val &= ~RP_L1_PM_SUBSTATES_CTL_PCI_PM_L1_1;
|
||||||
|
val &= ~RP_L1_PM_SUBSTATES_CTL_ASPM_L1_1;
|
||||||
|
writel(val, port->base + RP_L1_PM_SUBSTATES_CTL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void disable_aspm_l12(struct tegra_pcie_port *port)
|
||||||
|
{
|
||||||
|
u32 val = 0;
|
||||||
|
|
||||||
|
val = readl(port->base + RP_L1_PM_SUBSTATES_CTL);
|
||||||
|
val &= ~RP_L1_PM_SUBSTATES_CTL_PCI_PM_L1_2;
|
||||||
|
val &= ~RP_L1_PM_SUBSTATES_CTL_ASPM_L1_2;
|
||||||
|
writel(val, port->base + RP_L1_PM_SUBSTATES_CTL);
|
||||||
|
}
|
||||||
|
|
||||||
static void tegra_pcie_enable_rp_features(struct tegra_pcie_port *port)
|
static void tegra_pcie_enable_rp_features(struct tegra_pcie_port *port)
|
||||||
{
|
{
|
||||||
const struct tegra_pcie_soc *soc = port->pcie->soc;
|
const struct tegra_pcie_soc *soc = port->pcie->soc;
|
||||||
@@ -565,6 +730,47 @@ static void tegra_pcie_enable_rp_features(struct tegra_pcie_port *port)
|
|||||||
}
|
}
|
||||||
|
|
||||||
writel(value, port->base + RP_PRIV_MISC);
|
writel(value, port->base + RP_PRIV_MISC);
|
||||||
|
|
||||||
|
if (soc->has_aspm_l1) {
|
||||||
|
/* Advertise ASPM-L1 state capability*/
|
||||||
|
value = readl(port->base + RP_VEND_XP1);
|
||||||
|
value |= RP_VEND_XP1_LINK_PVT_CTL_L1_ASPM_SUPPORT;
|
||||||
|
writel(value, port->base + RP_VEND_XP1);
|
||||||
|
|
||||||
|
/* Power saving configuration for L1 sleep/idle */
|
||||||
|
value = readl(port->base + RP_VEND_XP_PAD_PWRDN);
|
||||||
|
value |= RP_VEND_XP_PAD_PWRDN_DISABLED_EN;
|
||||||
|
value |= RP_VEND_XP_PAD_PWRDN_DYNAMIC_EN;
|
||||||
|
value |= RP_VEND_XP_PAD_PWRDN_L1_EN;
|
||||||
|
value |= RP_VEND_XP_PAD_PWRDN_L1_CLKREQ_EN;
|
||||||
|
value |= RP_VEND_XP_PAD_PWRDN_SLEEP_MODE_DYNAMIC_L1PP;
|
||||||
|
value |= RP_VEND_XP_PAD_PWRDN_SLEEP_MODE_L1_L1PP;
|
||||||
|
value |= RP_VEND_XP_PAD_PWRDN_SLEEP_MODE_L1_CLKREQ_L1PP;
|
||||||
|
writel(value, port->base + RP_VEND_XP_PAD_PWRDN);
|
||||||
|
|
||||||
|
if (port->aspm_state & 0x1)
|
||||||
|
disable_aspm_l0s(port);
|
||||||
|
if (port->aspm_state & 0x2)
|
||||||
|
disable_aspm_l10(port);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (soc->has_aspm_l1ss) {
|
||||||
|
if (port->aspm_state & 0x2) {
|
||||||
|
disable_aspm_l11(port);
|
||||||
|
disable_aspm_l12(port);
|
||||||
|
}
|
||||||
|
if (port->aspm_state & 0x4)
|
||||||
|
disable_aspm_l11(port);
|
||||||
|
if (port->aspm_state & 0x8)
|
||||||
|
disable_aspm_l12(port);
|
||||||
|
|
||||||
|
/* Disable L1SS capability if CLKREQ# is not present */
|
||||||
|
if (!port->supports_clkreq) {
|
||||||
|
value = readl(port->base + RP_L1_PM_SUBSTATES_CTL);
|
||||||
|
value |= RP_L1_PM_SUBSTATES_CTL_HIDE_CAP;
|
||||||
|
writel(value, port->base + RP_L1_PM_SUBSTATES_CTL);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tegra_pcie_program_ectl_settings(struct tegra_pcie_port *port)
|
static void tegra_pcie_program_ectl_settings(struct tegra_pcie_port *port)
|
||||||
@@ -572,6 +778,11 @@ static void tegra_pcie_program_ectl_settings(struct tegra_pcie_port *port)
|
|||||||
const struct tegra_pcie_soc *soc = port->pcie->soc;
|
const struct tegra_pcie_soc *soc = port->pcie->soc;
|
||||||
u32 value;
|
u32 value;
|
||||||
|
|
||||||
|
value = readl(port->base + RP_ECTL_1_R1);
|
||||||
|
value &= ~RP_ECTL_1_R1_TX_DRV_AMP_1C_MASK;
|
||||||
|
value |= soc->ectl.regs.rp_ectl_1_r1;
|
||||||
|
writel(value, port->base + RP_ECTL_1_R1);
|
||||||
|
|
||||||
value = readl(port->base + RP_ECTL_2_R1);
|
value = readl(port->base + RP_ECTL_2_R1);
|
||||||
value &= ~RP_ECTL_2_R1_RX_CTLE_1C_MASK;
|
value &= ~RP_ECTL_2_R1_RX_CTLE_1C_MASK;
|
||||||
value |= soc->ectl.regs.rp_ectl_2_r1;
|
value |= soc->ectl.regs.rp_ectl_2_r1;
|
||||||
@@ -593,6 +804,11 @@ static void tegra_pcie_program_ectl_settings(struct tegra_pcie_port *port)
|
|||||||
value |= soc->ectl.regs.rp_ectl_6_r1;
|
value |= soc->ectl.regs.rp_ectl_6_r1;
|
||||||
writel(value, port->base + RP_ECTL_6_R1);
|
writel(value, port->base + RP_ECTL_6_R1);
|
||||||
|
|
||||||
|
value = readl(port->base + RP_ECTL_1_R2);
|
||||||
|
value &= ~RP_ECTL_1_R2_TX_DRV_AMP_1C_MASK;
|
||||||
|
value |= soc->ectl.regs.rp_ectl_1_r2;
|
||||||
|
writel(value, port->base + RP_ECTL_1_R2);
|
||||||
|
|
||||||
value = readl(port->base + RP_ECTL_2_R2);
|
value = readl(port->base + RP_ECTL_2_R2);
|
||||||
value &= ~RP_ECTL_2_R2_RX_CTLE_1C_MASK;
|
value &= ~RP_ECTL_2_R2_RX_CTLE_1C_MASK;
|
||||||
value |= soc->ectl.regs.rp_ectl_2_r2;
|
value |= soc->ectl.regs.rp_ectl_2_r2;
|
||||||
@@ -615,6 +831,26 @@ static void tegra_pcie_program_ectl_settings(struct tegra_pcie_port *port)
|
|||||||
writel(value, port->base + RP_ECTL_6_R2);
|
writel(value, port->base + RP_ECTL_6_R2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void tegra_pcie_enable_wrap(void)
|
||||||
|
{
|
||||||
|
u32 val;
|
||||||
|
void __iomem *msel_base;
|
||||||
|
|
||||||
|
#define MSELECT_CONFIG_BASE 0x50060000
|
||||||
|
#define MSELECT_CONFIG_WRAP_TO_INCR_SLAVE1 BIT(28)
|
||||||
|
#define MSELECT_CONFIG_ERR_RESP_EN_SLAVE1 BIT(24)
|
||||||
|
|
||||||
|
/* Config MSELECT to support wrap trans for normal NC & GRE mapping */
|
||||||
|
msel_base = ioremap(MSELECT_CONFIG_BASE, 4);
|
||||||
|
val = readl(msel_base);
|
||||||
|
/* Enable WRAP_TO_INCR_SLAVE1 */
|
||||||
|
val |= MSELECT_CONFIG_WRAP_TO_INCR_SLAVE1;
|
||||||
|
/* Disable ERR_RESP_EN_SLAVE1 */
|
||||||
|
val &= ~MSELECT_CONFIG_ERR_RESP_EN_SLAVE1;
|
||||||
|
writel(val, msel_base);
|
||||||
|
iounmap(msel_base);
|
||||||
|
}
|
||||||
|
|
||||||
static void tegra_pcie_apply_sw_fixup(struct tegra_pcie_port *port)
|
static void tegra_pcie_apply_sw_fixup(struct tegra_pcie_port *port)
|
||||||
{
|
{
|
||||||
const struct tegra_pcie_soc *soc = port->pcie->soc;
|
const struct tegra_pcie_soc *soc = port->pcie->soc;
|
||||||
@@ -649,6 +885,76 @@ static void tegra_pcie_apply_sw_fixup(struct tegra_pcie_port *port)
|
|||||||
value &= ~PCI_EXP_LNKSTA_CLS;
|
value &= ~PCI_EXP_LNKSTA_CLS;
|
||||||
value |= PCI_EXP_LNKSTA_CLS_2_5GB;
|
value |= PCI_EXP_LNKSTA_CLS_2_5GB;
|
||||||
writel(value, port->base + RP_LINK_CONTROL_STATUS_2);
|
writel(value, port->base + RP_LINK_CONTROL_STATUS_2);
|
||||||
|
|
||||||
|
if (soc->enable_wrap)
|
||||||
|
tegra_pcie_enable_wrap();
|
||||||
|
|
||||||
|
if (soc->has_aspm_l1ss) {
|
||||||
|
/* Set port Common_Mode_Restore_Time to 30us */
|
||||||
|
value = readl(port->base + RP_L1_PM_SUBSTATES_CTL);
|
||||||
|
value &= ~RP_L1_PM_SUBSTATES_CTL_CM_RTIME_MASK;
|
||||||
|
value |= (0x1E << RP_L1_PM_SUBSTATES_CTL_CM_RTIME_SHIFT);
|
||||||
|
writel(value, port->base + RP_L1_PM_SUBSTATES_CTL);
|
||||||
|
|
||||||
|
/* set port T_POWER_ON to 70us */
|
||||||
|
value = readl(port->base + RP_L1_PM_SUBSTATES_CTL);
|
||||||
|
value &= ~(RP_L1_PM_SUBSTATES_CTL_T_PWRN_SCL_MASK |
|
||||||
|
RP_L1_PM_SUBSTATES_CTL_T_PWRN_VAL_MASK);
|
||||||
|
value |= (1 << RP_L1_PM_SUBSTATES_CTL_T_PWRN_SCL_SHIFT) |
|
||||||
|
(7 << RP_L1_PM_SUBSTATES_CTL_T_PWRN_VAL_SHIFT);
|
||||||
|
writel(value, port->base + RP_L1_PM_SUBSTATES_CTL);
|
||||||
|
|
||||||
|
/* Following is based on clk_m being 19.2 MHz */
|
||||||
|
value = readl(port->base + RP_TIMEOUT0);
|
||||||
|
value &= ~RP_TIMEOUT0_PAD_PWRUP_MASK;
|
||||||
|
value |= RP_TIMEOUT0_PAD_PWRUP;
|
||||||
|
value &= ~RP_TIMEOUT0_PAD_PWRUP_CM_MASK;
|
||||||
|
value |= RP_TIMEOUT0_PAD_PWRUP_CM;
|
||||||
|
value &= ~RP_TIMEOUT0_PAD_SPDCHNG_GEN2_MASK;
|
||||||
|
value |= RP_TIMEOUT0_PAD_SPDCHNG_GEN2;
|
||||||
|
writel(value, port->base + RP_TIMEOUT0);
|
||||||
|
|
||||||
|
value = readl(port->base + RP_TIMEOUT1);
|
||||||
|
value &= ~RP_TIMEOUT1_RCVRY_SPD_SUCCESS_EIDLE_MASK;
|
||||||
|
value |= RP_TIMEOUT1_RCVRY_SPD_SUCCESS_EIDLE;
|
||||||
|
value &= ~RP_TIMEOUT1_RCVRY_SPD_UNSUCCESS_EIDLE_MASK;
|
||||||
|
value |= RP_TIMEOUT1_RCVRY_SPD_UNSUCCESS_EIDLE;
|
||||||
|
writel(value, port->base + RP_TIMEOUT1);
|
||||||
|
|
||||||
|
value = readl(port->base + RP_XP_REF);
|
||||||
|
value &= ~RP_XP_REF_MICROSECOND_LIMIT_MASK;
|
||||||
|
value |= RP_XP_REF_MICROSECOND_LIMIT;
|
||||||
|
value |= RP_XP_REF_MICROSECOND_ENABLE;
|
||||||
|
value |= RP_XP_REF_CPL_TO_OVERRIDE;
|
||||||
|
value &= ~RP_XP_REF_CPL_TO_CUSTOM_VALUE_MASK;
|
||||||
|
value |= RP_XP_REF_CPL_TO_CUSTOM_VALUE;
|
||||||
|
writel(value, port->base + RP_XP_REF);
|
||||||
|
|
||||||
|
value = readl(port->base + RP_L1_PM_SUBSTATES_1_CTL);
|
||||||
|
value &= ~RP_L1_PM_SUBSTATES_1_CTL_PWR_OFF_DLY_MASK;
|
||||||
|
value |= RP_L1_PM_SUBSTATES_1_CTL_PWR_OFF_DLY;
|
||||||
|
writel(value, port->base + RP_L1_PM_SUBSTATES_1_CTL);
|
||||||
|
|
||||||
|
value = readl(port->base + RP_L1_PM_SUBSTATES_2_CTL);
|
||||||
|
value &= ~RP_L1_PM_SUBSTATES_2_CTL_T_L1_2_DLY_MASK;
|
||||||
|
value |= RP_L1_PM_SUBSTATES_2_CTL_T_L1_2_DLY;
|
||||||
|
value &= ~RP_L1_PM_SUBSTATES_2_CTL_MICROSECOND_MASK;
|
||||||
|
value |= RP_L1_PM_SUBSTATES_2_CTL_MICROSECOND;
|
||||||
|
value &= ~RP_L1_PM_SUBSTATES_2_CTL_MICROSECOND_COMP_MASK;
|
||||||
|
value |= RP_L1_PM_SUBSTATES_2_CTL_MICROSECOND_COMP;
|
||||||
|
writel(value, port->base + RP_L1_PM_SUBSTATES_2_CTL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (soc->l1ss_rp_wake_fixup) {
|
||||||
|
/*
|
||||||
|
* Set CLKREQ asserted delay greater than Power_Off
|
||||||
|
* time (2us) to avoid RP wakeup in L1.2.ENTRY
|
||||||
|
*/
|
||||||
|
value = readl(port->base + RP_L1_PM_SUBSTATES_1_CTL);
|
||||||
|
value &= ~RP_L1SS_1_CTL_CLKREQ_ASSERTED_DLY_MASK;
|
||||||
|
value |= RP_L1SS_1_CTL_CLKREQ_ASSERTED_DLY;
|
||||||
|
writel(value, port->base + RP_L1_PM_SUBSTATES_1_CTL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tegra_pcie_port_enable(struct tegra_pcie_port *port)
|
static void tegra_pcie_port_enable(struct tegra_pcie_port *port)
|
||||||
@@ -661,8 +967,12 @@ static void tegra_pcie_port_enable(struct tegra_pcie_port *port)
|
|||||||
value = afi_readl(port->pcie, ctrl);
|
value = afi_readl(port->pcie, ctrl);
|
||||||
value |= AFI_PEX_CTRL_REFCLK_EN;
|
value |= AFI_PEX_CTRL_REFCLK_EN;
|
||||||
|
|
||||||
if (soc->has_pex_clkreq_en)
|
if (soc->has_pex_clkreq_en) {
|
||||||
value |= AFI_PEX_CTRL_CLKREQ_EN;
|
if (port->supports_clkreq)
|
||||||
|
value &= ~AFI_PEX_CTRL_CLKREQ_EN;
|
||||||
|
else
|
||||||
|
value |= AFI_PEX_CTRL_CLKREQ_EN;
|
||||||
|
}
|
||||||
|
|
||||||
value |= AFI_PEX_CTRL_OVERRIDE_EN;
|
value |= AFI_PEX_CTRL_OVERRIDE_EN;
|
||||||
|
|
||||||
@@ -1092,10 +1402,20 @@ static void tegra_pcie_enable_controller(struct tegra_pcie *pcie)
|
|||||||
unsigned long value;
|
unsigned long value;
|
||||||
|
|
||||||
/* enable PLL power down */
|
/* enable PLL power down */
|
||||||
if (pcie->phy) {
|
if (soc->has_aspm_l1ss) {
|
||||||
value = afi_readl(pcie, AFI_PLLE_CONTROL);
|
value = afi_readl(pcie, AFI_PLLE_CONTROL);
|
||||||
value &= ~AFI_PLLE_CONTROL_BYPASS_PADS2PLLE_CONTROL;
|
value &= ~AFI_PLLE_CONTROL_BYPASS_PADS2PLLE_CONTROL;
|
||||||
value |= AFI_PLLE_CONTROL_PADS2PLLE_CONTROL_EN;
|
value |= AFI_PLLE_CONTROL_PADS2PLLE_CONTROL_EN;
|
||||||
|
|
||||||
|
list_for_each_entry(port, &pcie->ports, list) {
|
||||||
|
if (!port->supports_clkreq) {
|
||||||
|
value &= ~AFI_PLLE_CONTROL_PADS2PLLE_CONTROL_EN;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
value &= ~AFI_PLLE_CONTROL_BYPASS_PCIE2PLLE_CONTROL;
|
||||||
|
value |= AFI_PLLE_CONTROL_PCIE2PLLE_CONTROL_EN;
|
||||||
afi_writel(pcie, value, AFI_PLLE_CONTROL);
|
afi_writel(pcie, value, AFI_PLLE_CONTROL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1527,6 +1847,11 @@ static void tegra_pcie_pme_turnoff(struct tegra_pcie_port *port)
|
|||||||
val = afi_readl(pcie, AFI_PCIE_PME);
|
val = afi_readl(pcie, AFI_PCIE_PME);
|
||||||
val &= ~(0x1 << soc->ports[port->index].pme.turnoff_bit);
|
val &= ~(0x1 << soc->ports[port->index].pme.turnoff_bit);
|
||||||
afi_writel(pcie, val, AFI_PCIE_PME);
|
afi_writel(pcie, val, AFI_PCIE_PME);
|
||||||
|
|
||||||
|
/* PCIe link is in L2, bypass CLKREQ# control over PLLE power down */
|
||||||
|
val = afi_readl(pcie, AFI_PLLE_CONTROL);
|
||||||
|
val |= AFI_PLLE_CONTROL_BYPASS_PADS2PLLE_CONTROL;
|
||||||
|
afi_writel(pcie, val, AFI_PLLE_CONTROL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tegra_pcie_msi_irq(struct irq_desc *desc)
|
static void tegra_pcie_msi_irq(struct irq_desc *desc)
|
||||||
@@ -1876,6 +2201,10 @@ static int tegra_pcie_get_xbar_config(struct tegra_pcie *pcie, u32 lanes,
|
|||||||
*xbar = AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_211;
|
*xbar = AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_211;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
} else if (of_device_is_compatible(np, "nvidia,tegra210b01-pcie")) {
|
||||||
|
dev_info(dev, "4x1, 1x1 configuration\n");
|
||||||
|
*xbar = AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_X4_X1;
|
||||||
|
return 0;
|
||||||
} else if (of_device_is_compatible(np, "nvidia,tegra124-pcie") ||
|
} else if (of_device_is_compatible(np, "nvidia,tegra124-pcie") ||
|
||||||
of_device_is_compatible(np, "nvidia,tegra210-pcie")) {
|
of_device_is_compatible(np, "nvidia,tegra210-pcie")) {
|
||||||
switch (lanes) {
|
switch (lanes) {
|
||||||
@@ -2209,6 +2538,14 @@ static int tegra_pcie_parse_dt(struct tegra_pcie *pcie)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = of_property_read_u32(port, "nvidia,disable-aspm-states",
|
||||||
|
&rp->aspm_state);
|
||||||
|
if (err < 0)
|
||||||
|
rp->aspm_state = 0;
|
||||||
|
|
||||||
|
rp->supports_clkreq = of_property_read_bool(port,
|
||||||
|
"supports-clkreq");
|
||||||
|
|
||||||
list_add_tail(&rp->list, &pcie->ports);
|
list_add_tail(&rp->list, &pcie->ports);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2402,6 +2739,10 @@ static const struct tegra_pcie_soc tegra20_pcie = {
|
|||||||
.program_deskew_time = false,
|
.program_deskew_time = false,
|
||||||
.update_fc_timer = false,
|
.update_fc_timer = false,
|
||||||
.has_cache_bars = true,
|
.has_cache_bars = true,
|
||||||
|
.enable_wrap = false,
|
||||||
|
.has_aspm_l1 = false,
|
||||||
|
.has_aspm_l1ss = false,
|
||||||
|
.l1ss_rp_wake_fixup = false,
|
||||||
.ectl.enable = false,
|
.ectl.enable = false,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -2431,6 +2772,10 @@ static const struct tegra_pcie_soc tegra30_pcie = {
|
|||||||
.program_deskew_time = false,
|
.program_deskew_time = false,
|
||||||
.update_fc_timer = false,
|
.update_fc_timer = false,
|
||||||
.has_cache_bars = false,
|
.has_cache_bars = false,
|
||||||
|
.enable_wrap = false,
|
||||||
|
.has_aspm_l1 = true,
|
||||||
|
.has_aspm_l1ss = false,
|
||||||
|
.l1ss_rp_wake_fixup = false,
|
||||||
.ectl.enable = false,
|
.ectl.enable = false,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -2452,6 +2797,10 @@ static const struct tegra_pcie_soc tegra124_pcie = {
|
|||||||
.program_deskew_time = false,
|
.program_deskew_time = false,
|
||||||
.update_fc_timer = false,
|
.update_fc_timer = false,
|
||||||
.has_cache_bars = false,
|
.has_cache_bars = false,
|
||||||
|
.enable_wrap = false,
|
||||||
|
.has_aspm_l1 = true,
|
||||||
|
.has_aspm_l1ss = false,
|
||||||
|
.l1ss_rp_wake_fixup = false,
|
||||||
.ectl.enable = false,
|
.ectl.enable = false,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -2475,12 +2824,18 @@ static const struct tegra_pcie_soc tegra210_pcie = {
|
|||||||
.program_deskew_time = true,
|
.program_deskew_time = true,
|
||||||
.update_fc_timer = true,
|
.update_fc_timer = true,
|
||||||
.has_cache_bars = false,
|
.has_cache_bars = false,
|
||||||
|
.enable_wrap = true,
|
||||||
|
.has_aspm_l1 = true,
|
||||||
|
.has_aspm_l1ss = true,
|
||||||
|
.l1ss_rp_wake_fixup = true,
|
||||||
.ectl = {
|
.ectl = {
|
||||||
.regs = {
|
.regs = {
|
||||||
|
.rp_ectl_1_r1 = 0x0000001f,
|
||||||
.rp_ectl_2_r1 = 0x0000000f,
|
.rp_ectl_2_r1 = 0x0000000f,
|
||||||
.rp_ectl_4_r1 = 0x00000067,
|
.rp_ectl_4_r1 = 0x00000067,
|
||||||
.rp_ectl_5_r1 = 0x55010000,
|
.rp_ectl_5_r1 = 0x55010000,
|
||||||
.rp_ectl_6_r1 = 0x00000001,
|
.rp_ectl_6_r1 = 0x00000001,
|
||||||
|
.rp_ectl_1_r2 = 0x0000001f,
|
||||||
.rp_ectl_2_r2 = 0x0000008f,
|
.rp_ectl_2_r2 = 0x0000008f,
|
||||||
.rp_ectl_4_r2 = 0x000000c7,
|
.rp_ectl_4_r2 = 0x000000c7,
|
||||||
.rp_ectl_5_r2 = 0x55010000,
|
.rp_ectl_5_r2 = 0x55010000,
|
||||||
@@ -2490,6 +2845,42 @@ static const struct tegra_pcie_soc tegra210_pcie = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct tegra_pcie_soc tegra210b01_pcie = {
|
||||||
|
.num_ports = 2,
|
||||||
|
.ports = tegra20_pcie_ports,
|
||||||
|
.msi_base_shift = 8,
|
||||||
|
.pads_pll_ctl = PADS_PLL_CTL_TEGRA30,
|
||||||
|
.tx_ref_sel = PADS_PLL_CTL_TXCLKREF_BUF_EN,
|
||||||
|
.pads_refclk_cfg0 = 0x90b890b8,
|
||||||
|
/* FC threshold is bit[25:18] */
|
||||||
|
.update_fc_threshold = 0x01800000,
|
||||||
|
.has_pex_clkreq_en = true,
|
||||||
|
.has_pex_bias_ctrl = true,
|
||||||
|
.has_intr_prsnt_sense = true,
|
||||||
|
.has_cml_clk = true,
|
||||||
|
.has_gen2 = true,
|
||||||
|
.force_pca_enable = true,
|
||||||
|
.program_uphy = true,
|
||||||
|
.program_deskew_time = true,
|
||||||
|
.update_fc_timer = true,
|
||||||
|
.has_cache_bars = false,
|
||||||
|
.ectl = {
|
||||||
|
.regs = {
|
||||||
|
.rp_ectl_1_r1 = 0x00000027,
|
||||||
|
.rp_ectl_2_r1 = 0x0000000f,
|
||||||
|
.rp_ectl_4_r1 = 0x00000067,
|
||||||
|
.rp_ectl_5_r1 = 0x00000000,
|
||||||
|
.rp_ectl_6_r1 = 0x00000000,
|
||||||
|
.rp_ectl_1_r2 = 0x00000027,
|
||||||
|
.rp_ectl_2_r2 = 0x0000008f,
|
||||||
|
.rp_ectl_4_r2 = 0x000000c7,
|
||||||
|
.rp_ectl_5_r2 = 0x00000000,
|
||||||
|
.rp_ectl_6_r2 = 0x00000000,
|
||||||
|
},
|
||||||
|
.enable = true,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
static const struct tegra_pcie_port_soc tegra186_pcie_ports[] = {
|
static const struct tegra_pcie_port_soc tegra186_pcie_ports[] = {
|
||||||
{ .pme.turnoff_bit = 0, .pme.ack_bit = 5 },
|
{ .pme.turnoff_bit = 0, .pme.ack_bit = 5 },
|
||||||
{ .pme.turnoff_bit = 8, .pme.ack_bit = 10 },
|
{ .pme.turnoff_bit = 8, .pme.ack_bit = 10 },
|
||||||
@@ -2516,11 +2907,16 @@ static const struct tegra_pcie_soc tegra186_pcie = {
|
|||||||
.program_deskew_time = false,
|
.program_deskew_time = false,
|
||||||
.update_fc_timer = false,
|
.update_fc_timer = false,
|
||||||
.has_cache_bars = false,
|
.has_cache_bars = false,
|
||||||
|
.enable_wrap = false,
|
||||||
|
.has_aspm_l1 = true,
|
||||||
|
.has_aspm_l1ss = true,
|
||||||
|
.l1ss_rp_wake_fixup = false,
|
||||||
.ectl.enable = false,
|
.ectl.enable = false,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct of_device_id tegra_pcie_of_match[] = {
|
static const struct of_device_id tegra_pcie_of_match[] = {
|
||||||
{ .compatible = "nvidia,tegra186-pcie", .data = &tegra186_pcie },
|
{ .compatible = "nvidia,tegra186-pcie", .data = &tegra186_pcie },
|
||||||
|
{ .compatible = "nvidia,tegra210b01-pcie", .data = &tegra210b01_pcie },
|
||||||
{ .compatible = "nvidia,tegra210-pcie", .data = &tegra210_pcie },
|
{ .compatible = "nvidia,tegra210-pcie", .data = &tegra210_pcie },
|
||||||
{ .compatible = "nvidia,tegra124-pcie", .data = &tegra124_pcie },
|
{ .compatible = "nvidia,tegra124-pcie", .data = &tegra124_pcie },
|
||||||
{ .compatible = "nvidia,tegra30-pcie", .data = &tegra30_pcie },
|
{ .compatible = "nvidia,tegra30-pcie", .data = &tegra30_pcie },
|
||||||
@@ -2607,6 +3003,7 @@ static int tegra_pcie_probe(struct platform_device *pdev)
|
|||||||
{
|
{
|
||||||
struct device *dev = &pdev->dev;
|
struct device *dev = &pdev->dev;
|
||||||
struct pci_host_bridge *host;
|
struct pci_host_bridge *host;
|
||||||
|
struct tegra_pcie_port *port;
|
||||||
struct tegra_pcie *pcie;
|
struct tegra_pcie *pcie;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
@@ -2645,6 +3042,8 @@ static int tegra_pcie_probe(struct platform_device *pdev)
|
|||||||
goto pm_runtime_put;
|
goto pm_runtime_put;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pci_add_flags(PCI_REASSIGN_ALL_BUS);
|
||||||
|
|
||||||
host->ops = &tegra_pcie_ops;
|
host->ops = &tegra_pcie_ops;
|
||||||
host->map_irq = tegra_pcie_map_irq;
|
host->map_irq = tegra_pcie_map_irq;
|
||||||
|
|
||||||
|
|||||||
@@ -230,6 +230,12 @@
|
|||||||
#define XUSB_PADCTL_UPHY_MISC_PAD_CTL2_RX_SLEEP_VAL GENMASK(13, 12)
|
#define XUSB_PADCTL_UPHY_MISC_PAD_CTL2_RX_SLEEP_VAL GENMASK(13, 12)
|
||||||
#define XUSB_PADCTL_UPHY_MISC_PAD_CTL2_RX_PWR_OVRD BIT(25)
|
#define XUSB_PADCTL_UPHY_MISC_PAD_CTL2_RX_PWR_OVRD BIT(25)
|
||||||
|
|
||||||
|
#define XUSB_PADCTL_UPHY_MISC_PAD_PX_CTL8(x) (0x460 + (x) * (0x1c))
|
||||||
|
#define CFG_ADDR(x) (((x) & 0xff) << 16)
|
||||||
|
#define CFG_WDATA(x) (((x) & 0xffff) << 0)
|
||||||
|
#define CFG_RESET (1 << 27)
|
||||||
|
#define CFG_WS (1 << 24)
|
||||||
|
|
||||||
#define XUSB_PADCTL_UPHY_PLL_S0_CTL1 0x860
|
#define XUSB_PADCTL_UPHY_PLL_S0_CTL1 0x860
|
||||||
|
|
||||||
#define XUSB_PADCTL_UPHY_PLL_S0_CTL2 0x864
|
#define XUSB_PADCTL_UPHY_PLL_S0_CTL2 0x864
|
||||||
@@ -240,6 +246,8 @@
|
|||||||
|
|
||||||
#define XUSB_PADCTL_UPHY_PLL_S0_CTL8 0x87c
|
#define XUSB_PADCTL_UPHY_PLL_S0_CTL8 0x87c
|
||||||
|
|
||||||
|
#define XUSB_PADCTL_UPHY_PLL_S0_CTL10 0x384
|
||||||
|
|
||||||
#define XUSB_PADCTL_UPHY_MISC_PAD_S0_CTL1 0x960
|
#define XUSB_PADCTL_UPHY_MISC_PAD_S0_CTL1 0x960
|
||||||
#define XUSB_PADCTL_UPHY_MISC_PAD_S0_CTL2 0x964
|
#define XUSB_PADCTL_UPHY_MISC_PAD_S0_CTL2 0x964
|
||||||
|
|
||||||
@@ -407,6 +415,18 @@
|
|||||||
#define UHSIC_STROBE_RPD_C BIT(16)
|
#define UHSIC_STROBE_RPD_C BIT(16)
|
||||||
#define UHSIC_STROBE_RPD_D BIT(24)
|
#define UHSIC_STROBE_RPD_D BIT(24)
|
||||||
|
|
||||||
|
struct init_data {
|
||||||
|
u8 cfg_addr;
|
||||||
|
u16 cfg_wdata;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct init_data usb3_pll_g1_init_data[] = {
|
||||||
|
{.cfg_addr = 0x2, .cfg_wdata = 0x0000},
|
||||||
|
{.cfg_addr = 0x3, .cfg_wdata = 0x7051},
|
||||||
|
{.cfg_addr = 0x25, .cfg_wdata = 0x0130},
|
||||||
|
{.cfg_addr = 0x1E, .cfg_wdata = 0x0017},
|
||||||
|
};
|
||||||
|
|
||||||
struct tegra210_xusb_fuse_calibration {
|
struct tegra210_xusb_fuse_calibration {
|
||||||
u32 hs_curr_level[4];
|
u32 hs_curr_level[4];
|
||||||
u32 hs_term_range_adj;
|
u32 hs_term_range_adj;
|
||||||
@@ -444,11 +464,38 @@ static const struct tegra_xusb_lane_map tegra210_usb3_map[] = {
|
|||||||
{ 0, NULL, 0 }
|
{ 0, NULL, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct tegra_xusb_lane_map tegra210b01_usb3_map[] = {
|
||||||
|
{ 0, "pcie", 5 },
|
||||||
|
{ 1, "pcie", 4 },
|
||||||
|
{ 2, "pcie", 1 },
|
||||||
|
{ 0, NULL, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
static int t210b01_compatible(struct tegra_xusb_padctl *padctl)
|
||||||
|
{
|
||||||
|
struct device_node *np;
|
||||||
|
const char *compatible;
|
||||||
|
|
||||||
|
np = padctl->dev->of_node;
|
||||||
|
compatible = of_get_property(np, "compatible", NULL);
|
||||||
|
|
||||||
|
if (!compatible) {
|
||||||
|
dev_err(padctl->dev, "Failed to get compatible property\n");
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strstr(compatible, "tegra210b01") != NULL)
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int tegra210_usb3_lane_map(struct tegra_xusb_lane *lane)
|
static int tegra210_usb3_lane_map(struct tegra_xusb_lane *lane)
|
||||||
{
|
{
|
||||||
const struct tegra_xusb_lane_map *map;
|
const struct tegra_xusb_lane_map *map;
|
||||||
|
|
||||||
for (map = tegra210_usb3_map; map->type; map++) {
|
for (map = t210b01_compatible(lane->pad->padctl) ?
|
||||||
|
tegra210b01_usb3_map : tegra210_usb3_map;
|
||||||
|
map->type; map++) {
|
||||||
if (map->index == lane->index &&
|
if (map->index == lane->index &&
|
||||||
strcmp(map->type, lane->pad->soc->name) == 0) {
|
strcmp(map->type, lane->pad->soc->name) == 0) {
|
||||||
dev_dbg(lane->pad->padctl->dev, "lane = %s map to port = usb3-%d\n",
|
dev_dbg(lane->pad->padctl->dev, "lane = %s map to port = usb3-%d\n",
|
||||||
@@ -476,6 +523,12 @@ static int tegra210_pex_uphy_enable(struct tegra_xusb_padctl *padctl)
|
|||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
|
if (t210b01_compatible(padctl) == 1) {
|
||||||
|
err = clk_prepare_enable(pcie->uphy_mgmt_clk);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
if (tegra210_plle_hw_sequence_is_enabled())
|
if (tegra210_plle_hw_sequence_is_enabled())
|
||||||
goto skip_pll_init;
|
goto skip_pll_init;
|
||||||
|
|
||||||
@@ -483,6 +536,18 @@ static int tegra210_pex_uphy_enable(struct tegra_xusb_padctl *padctl)
|
|||||||
if (err < 0)
|
if (err < 0)
|
||||||
goto disable;
|
goto disable;
|
||||||
|
|
||||||
|
if (t210b01_compatible(padctl) == 1) {
|
||||||
|
for (i = 0; i < ARRAY_SIZE(usb3_pll_g1_init_data); i++) {
|
||||||
|
value = 0;
|
||||||
|
value |= CFG_ADDR(usb3_pll_g1_init_data[i].cfg_addr);
|
||||||
|
value |= CFG_WDATA(usb3_pll_g1_init_data[i].cfg_wdata);
|
||||||
|
value |= CFG_RESET;
|
||||||
|
value |= CFG_WS;
|
||||||
|
padctl_writel(padctl, value,
|
||||||
|
XUSB_PADCTL_UPHY_PLL_S0_CTL10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL2);
|
value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL2);
|
||||||
value &= ~(XUSB_PADCTL_UPHY_PLL_CTL2_CAL_CTRL_MASK <<
|
value &= ~(XUSB_PADCTL_UPHY_PLL_CTL2_CAL_CTRL_MASK <<
|
||||||
XUSB_PADCTL_UPHY_PLL_CTL2_CAL_CTRL_SHIFT);
|
XUSB_PADCTL_UPHY_PLL_CTL2_CAL_CTRL_SHIFT);
|
||||||
@@ -676,6 +741,8 @@ reset:
|
|||||||
reset_control_assert(pcie->rst);
|
reset_control_assert(pcie->rst);
|
||||||
disable:
|
disable:
|
||||||
clk_disable_unprepare(pcie->pll);
|
clk_disable_unprepare(pcie->pll);
|
||||||
|
if (t210b01_compatible(padctl) == 1)
|
||||||
|
clk_disable_unprepare(pcie->uphy_mgmt_clk);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -697,6 +764,8 @@ static void tegra210_pex_uphy_disable(struct tegra_xusb_padctl *padctl)
|
|||||||
}
|
}
|
||||||
|
|
||||||
clk_disable_unprepare(pcie->pll);
|
clk_disable_unprepare(pcie->pll);
|
||||||
|
if (t210b01_compatible(padctl) == 1)
|
||||||
|
clk_disable_unprepare(pcie->uphy_mgmt_clk);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* must be called under padctl->lock */
|
/* must be called under padctl->lock */
|
||||||
@@ -2560,12 +2629,12 @@ static const struct tegra_xusb_lane_soc tegra210_pcie_lanes[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static const struct tegra_xusb_lane_soc tegra210b01_pcie_lanes[] = {
|
static const struct tegra_xusb_lane_soc tegra210b01_pcie_lanes[] = {
|
||||||
TEGRA210_UPHY_LANE("pcie-0", 0x028, 12, 0x3, pcie, XUSB_PADCTL_UPHY_MISC_PAD_PX_CTL2(0)),
|
TEGRA210_UPHY_LANE("pcie-0", 0x28, 12, 0x3, pcie, XUSB_PADCTL_UPHY_MISC_PAD_PX_CTL2(0)),
|
||||||
TEGRA210_UPHY_LANE("pcie-1", 0x028, 14, 0x3, pcie, XUSB_PADCTL_UPHY_MISC_PAD_PX_CTL2(1)),
|
TEGRA210_UPHY_LANE("pcie-1", 0x28, 14, 0x3, pcie, XUSB_PADCTL_UPHY_MISC_PAD_PX_CTL2(0)),
|
||||||
TEGRA210_UPHY_LANE("pcie-2", 0x028, 16, 0x3, pcie, XUSB_PADCTL_UPHY_MISC_PAD_PX_CTL2(2)),
|
TEGRA210_UPHY_LANE("pcie-2", 0x28, 16, 0x3, pcie, XUSB_PADCTL_UPHY_MISC_PAD_PX_CTL2(0)),
|
||||||
TEGRA210_UPHY_LANE("pcie-3", 0x028, 18, 0x3, pcie, XUSB_PADCTL_UPHY_MISC_PAD_PX_CTL2(3)),
|
TEGRA210_UPHY_LANE("pcie-3", 0x28, 18, 0x3, pcie, XUSB_PADCTL_UPHY_MISC_PAD_PX_CTL2(0)),
|
||||||
TEGRA210_UPHY_LANE("pcie-4", 0x028, 20, 0x3, pcie, XUSB_PADCTL_UPHY_MISC_PAD_PX_CTL2(4)),
|
TEGRA210_UPHY_LANE("pcie-4", 0x28, 20, 0x3, pcie, XUSB_PADCTL_UPHY_MISC_PAD_PX_CTL2(0)),
|
||||||
TEGRA210_UPHY_LANE("pcie-5", 0x028, 22, 0x3, pcie, XUSB_PADCTL_UPHY_MISC_PAD_PX_CTL2(5)),
|
TEGRA210_UPHY_LANE("pcie-5", 0x28, 22, 0x3, pcie, XUSB_PADCTL_UPHY_MISC_PAD_PX_CTL2(0)),
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct tegra_xusb_usb3_port *
|
static struct tegra_xusb_usb3_port *
|
||||||
@@ -2816,6 +2885,15 @@ tegra210_pcie_pad_probe(struct tegra_xusb_padctl *padctl,
|
|||||||
goto unregister;
|
goto unregister;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (t210b01_compatible(padctl) == 1) {
|
||||||
|
pcie->uphy_mgmt_clk = devm_clk_get(&pad->dev, "uphy_mgmt");
|
||||||
|
if (IS_ERR(pcie->uphy_mgmt_clk)) {
|
||||||
|
err = PTR_ERR(pcie->uphy_mgmt_clk);
|
||||||
|
dev_err(&pad->dev,
|
||||||
|
"failed to get uphy_mgmt_clk clock: %d\n", err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pcie->rst = devm_reset_control_get(&pad->dev, "phy");
|
pcie->rst = devm_reset_control_get(&pad->dev, "phy");
|
||||||
if (IS_ERR(pcie->rst)) {
|
if (IS_ERR(pcie->rst)) {
|
||||||
err = PTR_ERR(pcie->rst);
|
err = PTR_ERR(pcie->rst);
|
||||||
@@ -3094,7 +3172,16 @@ static void tegra210_usb3_port_disable(struct tegra_xusb_port *port)
|
|||||||
static struct tegra_xusb_lane *
|
static struct tegra_xusb_lane *
|
||||||
tegra210_usb3_port_map(struct tegra_xusb_port *port)
|
tegra210_usb3_port_map(struct tegra_xusb_port *port)
|
||||||
{
|
{
|
||||||
return tegra_xusb_port_find_lane(port, tegra210_usb3_map, "usb3-ss");
|
int err = t210b01_compatible(port->padctl);
|
||||||
|
|
||||||
|
if (err == 1)
|
||||||
|
return tegra_xusb_port_find_lane(port,
|
||||||
|
tegra210b01_usb3_map, "usb3-ss");
|
||||||
|
else if (err == 0)
|
||||||
|
return tegra_xusb_port_find_lane(port,
|
||||||
|
tegra210_usb3_map, "usb3-ss");
|
||||||
|
else
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct tegra_xusb_port_ops tegra210_usb3_port_ops = {
|
static const struct tegra_xusb_port_ops tegra210_usb3_port_ops = {
|
||||||
@@ -3287,6 +3374,14 @@ static const char * const tegra210_xusb_padctl_supply_names[] = {
|
|||||||
"hvdd-pex-pll-e",
|
"hvdd-pex-pll-e",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const char * const tegra210b01_supply_names[] = {
|
||||||
|
"avdd_pll_uerefe",
|
||||||
|
"hvdd_pex_pll_e",
|
||||||
|
"dvdd_pex_pll",
|
||||||
|
"hvddio_pex",
|
||||||
|
"dvddio_pex",
|
||||||
|
};
|
||||||
|
|
||||||
const struct tegra_xusb_padctl_soc tegra210_xusb_padctl_soc = {
|
const struct tegra_xusb_padctl_soc tegra210_xusb_padctl_soc = {
|
||||||
.num_pads = ARRAY_SIZE(tegra210_pads),
|
.num_pads = ARRAY_SIZE(tegra210_pads),
|
||||||
.pads = tegra210_pads,
|
.pads = tegra210_pads,
|
||||||
@@ -3325,8 +3420,8 @@ const struct tegra_xusb_padctl_soc tegra210b01_xusb_padctl_soc = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
.ops = &tegra210_xusb_padctl_ops,
|
.ops = &tegra210_xusb_padctl_ops,
|
||||||
.supply_names = tegra210_xusb_padctl_supply_names,
|
.supply_names = tegra210b01_supply_names,
|
||||||
.num_supplies = ARRAY_SIZE(tegra210_xusb_padctl_supply_names),
|
.num_supplies = ARRAY_SIZE(tegra210b01_supply_names),
|
||||||
.need_fake_usb3_port = true,
|
.need_fake_usb3_port = true,
|
||||||
};
|
};
|
||||||
EXPORT_SYMBOL_GPL(tegra210b01_xusb_padctl_soc);
|
EXPORT_SYMBOL_GPL(tegra210b01_xusb_padctl_soc);
|
||||||
|
|||||||
@@ -564,6 +564,7 @@ static int tegra_xusb_port_init(struct tegra_xusb_port *port,
|
|||||||
if (err < 0)
|
if (err < 0)
|
||||||
goto put_device;
|
goto put_device;
|
||||||
|
|
||||||
|
printk("init done!\n");
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
put_device:
|
put_device:
|
||||||
@@ -799,24 +800,31 @@ static int tegra_xusb_add_usb2_port(struct tegra_xusb_padctl *padctl,
|
|||||||
struct device_node *np;
|
struct device_node *np;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
|
printk("adding usb2 port");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* USB2 ports don't require additional properties, but if the port is
|
* USB2 ports don't require additional properties, but if the port is
|
||||||
* marked as disabled there is no reason to register it.
|
* marked as disabled there is no reason to register it.
|
||||||
*/
|
*/
|
||||||
|
printk("find port node");
|
||||||
np = tegra_xusb_find_port_node(padctl, "usb2", index);
|
np = tegra_xusb_find_port_node(padctl, "usb2", index);
|
||||||
if (!np || !of_device_is_available(np))
|
if (!np || !of_device_is_available(np))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
printk("kzalloc");
|
||||||
usb2 = kzalloc(sizeof(*usb2), GFP_KERNEL);
|
usb2 = kzalloc(sizeof(*usb2), GFP_KERNEL);
|
||||||
if (!usb2) {
|
if (!usb2) {
|
||||||
err = -ENOMEM;
|
err = -ENOMEM;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
printk("init usb2 xusb port");
|
||||||
err = tegra_xusb_port_init(&usb2->base, padctl, np, "usb2", index);
|
err = tegra_xusb_port_init(&usb2->base, padctl, np, "usb2", index);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
printk("set usb2 ops");
|
||||||
|
|
||||||
usb2->base.ops = padctl->soc->ports.usb2.ops;
|
usb2->base.ops = padctl->soc->ports.usb2.ops;
|
||||||
|
|
||||||
usb2->base.lane = usb2->base.ops->map(&usb2->base);
|
usb2->base.lane = usb2->base.ops->map(&usb2->base);
|
||||||
@@ -880,6 +888,8 @@ static int tegra_xusb_add_ulpi_port(struct tegra_xusb_padctl *padctl,
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
printk("init ulpi xusb port");
|
||||||
|
|
||||||
err = tegra_xusb_port_init(&ulpi->base, padctl, np, "ulpi", index);
|
err = tegra_xusb_port_init(&ulpi->base, padctl, np, "ulpi", index);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
goto out;
|
goto out;
|
||||||
@@ -926,6 +936,7 @@ static int tegra_xusb_add_hsic_port(struct tegra_xusb_padctl *padctl,
|
|||||||
struct device_node *np;
|
struct device_node *np;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
|
printk("find hsic port node");
|
||||||
np = tegra_xusb_find_port_node(padctl, "hsic", index);
|
np = tegra_xusb_find_port_node(padctl, "hsic", index);
|
||||||
if (!np || !of_device_is_available(np))
|
if (!np || !of_device_is_available(np))
|
||||||
goto out;
|
goto out;
|
||||||
@@ -936,10 +947,13 @@ static int tegra_xusb_add_hsic_port(struct tegra_xusb_padctl *padctl,
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
printk("init hsic xusb port");
|
||||||
|
|
||||||
err = tegra_xusb_port_init(&hsic->base, padctl, np, "hsic", index);
|
err = tegra_xusb_port_init(&hsic->base, padctl, np, "hsic", index);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
printk("setting hsic ops");
|
||||||
hsic->base.ops = padctl->soc->ports.hsic.ops;
|
hsic->base.ops = padctl->soc->ports.hsic.ops;
|
||||||
|
|
||||||
hsic->base.lane = hsic->base.ops->map(&hsic->base);
|
hsic->base.lane = hsic->base.ops->map(&hsic->base);
|
||||||
@@ -1028,10 +1042,14 @@ static int tegra_xusb_add_usb3_port(struct tegra_xusb_padctl *padctl,
|
|||||||
if (err < 0)
|
if (err < 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
printk("xusb port inited. setting ops");
|
||||||
usb3->base.ops = padctl->soc->ports.usb3.ops;
|
usb3->base.ops = padctl->soc->ports.usb3.ops;
|
||||||
|
|
||||||
|
printk("set lane");
|
||||||
|
|
||||||
usb3->base.lane = usb3->base.ops->map(&usb3->base);
|
usb3->base.lane = usb3->base.ops->map(&usb3->base);
|
||||||
if (IS_ERR(usb3->base.lane)) {
|
if (IS_ERR(usb3->base.lane)) {
|
||||||
|
printk("usb3 lane is error!");
|
||||||
err = PTR_ERR(usb3->base.lane);
|
err = PTR_ERR(usb3->base.lane);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user