diff options
author | Jay Agarwal <jagarwal@nvidia.com> | 2013-08-09 10:49:24 -0400 |
---|---|---|
committer | Stephen Warren <swarren@nvidia.com> | 2013-08-13 14:07:48 -0400 |
commit | 94716cddbec6602643e2c7fe10f4385d951cf2f8 (patch) | |
tree | 038b88ea028ab41c898d9309489bc71edfef5ea4 | |
parent | d1523b52bff35ea709141abac87dd701559ef290 (diff) |
PCI: tegra: Add Tegra 30 PCIe support
Introduce a data structure to parameterize the driver according to SoC
generation, add Tegra30 specific code and update the device tree binding
document for Tegra30 support.
Signed-off-by: Jay Agarwal <jagarwal@nvidia.com>
Signed-off-by: Thierry Reding <treding@nvidia.com>
Acked-by: Bjorn Helgaas <bhelgaas@google.com>
Signed-off-by: Stephen Warren <swarren@nvidia.com>
-rw-r--r-- | Documentation/devicetree/bindings/pci/nvidia,tegra20-pcie.txt | 4 | ||||
-rw-r--r-- | drivers/pci/host/pci-tegra.c | 209 |
2 files changed, 179 insertions, 34 deletions
diff --git a/Documentation/devicetree/bindings/pci/nvidia,tegra20-pcie.txt b/Documentation/devicetree/bindings/pci/nvidia,tegra20-pcie.txt index 90c112f671da..6b7510775c50 100644 --- a/Documentation/devicetree/bindings/pci/nvidia,tegra20-pcie.txt +++ b/Documentation/devicetree/bindings/pci/nvidia,tegra20-pcie.txt | |||
@@ -1,7 +1,7 @@ | |||
1 | NVIDIA Tegra PCIe controller | 1 | NVIDIA Tegra PCIe controller |
2 | 2 | ||
3 | Required properties: | 3 | Required properties: |
4 | - compatible: "nvidia,tegra20-pcie" | 4 | - compatible: "nvidia,tegra20-pcie" or "nvidia,tegra30-pcie" |
5 | - device_type: Must be "pci" | 5 | - device_type: Must be "pci" |
6 | - reg: A list of physical base address and length for each set of controller | 6 | - reg: A list of physical base address and length for each set of controller |
7 | registers. Must contain an entry for each entry in the reg-names property. | 7 | registers. Must contain an entry for each entry in the reg-names property. |
@@ -16,6 +16,7 @@ Required properties: | |||
16 | "msi": The Tegra interrupt that is asserted when an MSI is received | 16 | "msi": The Tegra interrupt that is asserted when an MSI is received |
17 | - pex-clk-supply: Supply voltage for internal reference clock | 17 | - pex-clk-supply: Supply voltage for internal reference clock |
18 | - vdd-supply: Power supply for controller (1.05V) | 18 | - vdd-supply: Power supply for controller (1.05V) |
19 | - avdd-supply: Power supply for controller (1.05V) (not required for Tegra20) | ||
19 | - bus-range: Range of bus numbers associated with this controller | 20 | - bus-range: Range of bus numbers associated with this controller |
20 | - #address-cells: Address representation for root ports (must be 3) | 21 | - #address-cells: Address representation for root ports (must be 3) |
21 | - cell 0 specifies the bus and device numbers of the root port: | 22 | - cell 0 specifies the bus and device numbers of the root port: |
@@ -48,6 +49,7 @@ Required properties: | |||
48 | "afi": The Tegra clock of that name | 49 | "afi": The Tegra clock of that name |
49 | "pcie_xclk": The Tegra clock of that name | 50 | "pcie_xclk": The Tegra clock of that name |
50 | "pll_e": The Tegra clock of that name | 51 | "pll_e": The Tegra clock of that name |
52 | "cml": The Tegra clock of that name (not required for Tegra20) | ||
51 | 53 | ||
52 | Root ports are defined as subnodes of the PCIe controller node. | 54 | Root ports are defined as subnodes of the PCIe controller node. |
53 | 55 | ||
diff --git a/drivers/pci/host/pci-tegra.c b/drivers/pci/host/pci-tegra.c index a54a01138927..75607c788ff6 100644 --- a/drivers/pci/host/pci-tegra.c +++ b/drivers/pci/host/pci-tegra.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * PCIe host controller driver for TEGRA(2) SOCs | 2 | * PCIe host controller driver for Tegra SoCs |
3 | * | 3 | * |
4 | * Copyright (c) 2010, CompuLab, Ltd. | 4 | * Copyright (c) 2010, CompuLab, Ltd. |
5 | * Author: Mike Rapoport <mike@compulab.co.il> | 5 | * Author: Mike Rapoport <mike@compulab.co.il> |
@@ -50,7 +50,6 @@ | |||
50 | #include <asm/mach/pci.h> | 50 | #include <asm/mach/pci.h> |
51 | 51 | ||
52 | #define INT_PCI_MSI_NR (8 * 32) | 52 | #define INT_PCI_MSI_NR (8 * 32) |
53 | #define TEGRA_MAX_PORTS 2 | ||
54 | 53 | ||
55 | /* register definitions */ | 54 | /* register definitions */ |
56 | 55 | ||
@@ -142,22 +141,30 @@ | |||
142 | #define AFI_INTR_EN_DFPCI_DECERR (1 << 5) | 141 | #define AFI_INTR_EN_DFPCI_DECERR (1 << 5) |
143 | #define AFI_INTR_EN_AXI_DECERR (1 << 6) | 142 | #define AFI_INTR_EN_AXI_DECERR (1 << 6) |
144 | #define AFI_INTR_EN_FPCI_TIMEOUT (1 << 7) | 143 | #define AFI_INTR_EN_FPCI_TIMEOUT (1 << 7) |
144 | #define AFI_INTR_EN_PRSNT_SENSE (1 << 8) | ||
145 | 145 | ||
146 | #define AFI_PCIE_CONFIG 0x0f8 | 146 | #define AFI_PCIE_CONFIG 0x0f8 |
147 | #define AFI_PCIE_CONFIG_PCIE_DISABLE(x) (1 << ((x) + 1)) | 147 | #define AFI_PCIE_CONFIG_PCIE_DISABLE(x) (1 << ((x) + 1)) |
148 | #define AFI_PCIE_CONFIG_PCIE_DISABLE_ALL 0xe | 148 | #define AFI_PCIE_CONFIG_PCIE_DISABLE_ALL 0xe |
149 | #define AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_MASK (0xf << 20) | 149 | #define AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_MASK (0xf << 20) |
150 | #define AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_SINGLE (0x0 << 20) | 150 | #define AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_SINGLE (0x0 << 20) |
151 | #define AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_420 (0x0 << 20) | ||
151 | #define AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_DUAL (0x1 << 20) | 152 | #define AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_DUAL (0x1 << 20) |
153 | #define AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_222 (0x1 << 20) | ||
154 | #define AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_411 (0x2 << 20) | ||
152 | 155 | ||
153 | #define AFI_FUSE 0x104 | 156 | #define AFI_FUSE 0x104 |
154 | #define AFI_FUSE_PCIE_T0_GEN2_DIS (1 << 2) | 157 | #define AFI_FUSE_PCIE_T0_GEN2_DIS (1 << 2) |
155 | 158 | ||
156 | #define AFI_PEX0_CTRL 0x110 | 159 | #define AFI_PEX0_CTRL 0x110 |
157 | #define AFI_PEX1_CTRL 0x118 | 160 | #define AFI_PEX1_CTRL 0x118 |
161 | #define AFI_PEX2_CTRL 0x128 | ||
158 | #define AFI_PEX_CTRL_RST (1 << 0) | 162 | #define AFI_PEX_CTRL_RST (1 << 0) |
163 | #define AFI_PEX_CTRL_CLKREQ_EN (1 << 1) | ||
159 | #define AFI_PEX_CTRL_REFCLK_EN (1 << 3) | 164 | #define AFI_PEX_CTRL_REFCLK_EN (1 << 3) |
160 | 165 | ||
166 | #define AFI_PEXBIAS_CTRL_0 0x168 | ||
167 | |||
161 | #define RP_VEND_XP 0x00000F00 | 168 | #define RP_VEND_XP 0x00000F00 |
162 | #define RP_VEND_XP_DL_UP (1 << 30) | 169 | #define RP_VEND_XP_DL_UP (1 << 30) |
163 | 170 | ||
@@ -172,7 +179,8 @@ | |||
172 | #define PADS_CTL_TX_DATA_EN_1L (1 << 6) | 179 | #define PADS_CTL_TX_DATA_EN_1L (1 << 6) |
173 | #define PADS_CTL_RX_DATA_EN_1L (1 << 10) | 180 | #define PADS_CTL_RX_DATA_EN_1L (1 << 10) |
174 | 181 | ||
175 | #define PADS_PLL_CTL 0x000000B8 | 182 | #define PADS_PLL_CTL_TEGRA20 0x000000B8 |
183 | #define PADS_PLL_CTL_TEGRA30 0x000000B4 | ||
176 | #define PADS_PLL_CTL_RST_B4SM (1 << 1) | 184 | #define PADS_PLL_CTL_RST_B4SM (1 << 1) |
177 | #define PADS_PLL_CTL_LOCKDET (1 << 8) | 185 | #define PADS_PLL_CTL_LOCKDET (1 << 8) |
178 | #define PADS_PLL_CTL_REFCLK_MASK (0x3 << 16) | 186 | #define PADS_PLL_CTL_REFCLK_MASK (0x3 << 16) |
@@ -182,6 +190,10 @@ | |||
182 | #define PADS_PLL_CTL_TXCLKREF_MASK (0x1 << 20) | 190 | #define PADS_PLL_CTL_TXCLKREF_MASK (0x1 << 20) |
183 | #define PADS_PLL_CTL_TXCLKREF_DIV10 (0 << 20) | 191 | #define PADS_PLL_CTL_TXCLKREF_DIV10 (0 << 20) |
184 | #define PADS_PLL_CTL_TXCLKREF_DIV5 (1 << 20) | 192 | #define PADS_PLL_CTL_TXCLKREF_DIV5 (1 << 20) |
193 | #define PADS_PLL_CTL_TXCLKREF_BUF_EN (1 << 22) | ||
194 | |||
195 | #define PADS_REFCLK_CFG0 0x000000C8 | ||
196 | #define PADS_REFCLK_CFG1 0x000000CC | ||
185 | 197 | ||
186 | struct tegra_msi { | 198 | struct tegra_msi { |
187 | struct msi_chip chip; | 199 | struct msi_chip chip; |
@@ -192,6 +204,19 @@ struct tegra_msi { | |||
192 | int irq; | 204 | int irq; |
193 | }; | 205 | }; |
194 | 206 | ||
207 | /* used to differentiate between Tegra SoC generations */ | ||
208 | struct tegra_pcie_soc_data { | ||
209 | unsigned int num_ports; | ||
210 | unsigned int msi_base_shift; | ||
211 | u32 pads_pll_ctl; | ||
212 | u32 tx_ref_sel; | ||
213 | bool has_pex_clkreq_en; | ||
214 | bool has_pex_bias_ctrl; | ||
215 | bool has_intr_prsnt_sense; | ||
216 | bool has_avdd_supply; | ||
217 | bool has_cml_clk; | ||
218 | }; | ||
219 | |||
195 | static inline struct tegra_msi *to_tegra_msi(struct msi_chip *chip) | 220 | static inline struct tegra_msi *to_tegra_msi(struct msi_chip *chip) |
196 | { | 221 | { |
197 | return container_of(chip, struct tegra_msi, chip); | 222 | return container_of(chip, struct tegra_msi, chip); |
@@ -216,6 +241,7 @@ struct tegra_pcie { | |||
216 | struct clk *afi_clk; | 241 | struct clk *afi_clk; |
217 | struct clk *pcie_xclk; | 242 | struct clk *pcie_xclk; |
218 | struct clk *pll_e; | 243 | struct clk *pll_e; |
244 | struct clk *cml_clk; | ||
219 | 245 | ||
220 | struct tegra_msi msi; | 246 | struct tegra_msi msi; |
221 | 247 | ||
@@ -225,6 +251,9 @@ struct tegra_pcie { | |||
225 | 251 | ||
226 | struct regulator *pex_clk_supply; | 252 | struct regulator *pex_clk_supply; |
227 | struct regulator *vdd_supply; | 253 | struct regulator *vdd_supply; |
254 | struct regulator *avdd_supply; | ||
255 | |||
256 | const struct tegra_pcie_soc_data *soc_data; | ||
228 | }; | 257 | }; |
229 | 258 | ||
230 | struct tegra_pcie_port { | 259 | struct tegra_pcie_port { |
@@ -469,6 +498,10 @@ static unsigned long tegra_pcie_port_get_pex_ctrl(struct tegra_pcie_port *port) | |||
469 | case 1: | 498 | case 1: |
470 | ret = AFI_PEX1_CTRL; | 499 | ret = AFI_PEX1_CTRL; |
471 | break; | 500 | break; |
501 | |||
502 | case 2: | ||
503 | ret = AFI_PEX2_CTRL; | ||
504 | break; | ||
472 | } | 505 | } |
473 | 506 | ||
474 | return ret; | 507 | return ret; |
@@ -493,12 +526,17 @@ static void tegra_pcie_port_reset(struct tegra_pcie_port *port) | |||
493 | 526 | ||
494 | static void tegra_pcie_port_enable(struct tegra_pcie_port *port) | 527 | static void tegra_pcie_port_enable(struct tegra_pcie_port *port) |
495 | { | 528 | { |
529 | const struct tegra_pcie_soc_data *soc = port->pcie->soc_data; | ||
496 | unsigned long ctrl = tegra_pcie_port_get_pex_ctrl(port); | 530 | unsigned long ctrl = tegra_pcie_port_get_pex_ctrl(port); |
497 | unsigned long value; | 531 | unsigned long value; |
498 | 532 | ||
499 | /* enable reference clock */ | 533 | /* enable reference clock */ |
500 | value = afi_readl(port->pcie, ctrl); | 534 | value = afi_readl(port->pcie, ctrl); |
501 | value |= AFI_PEX_CTRL_REFCLK_EN; | 535 | value |= AFI_PEX_CTRL_REFCLK_EN; |
536 | |||
537 | if (soc->has_pex_clkreq_en) | ||
538 | value |= AFI_PEX_CTRL_CLKREQ_EN; | ||
539 | |||
502 | afi_writel(port->pcie, value, ctrl); | 540 | afi_writel(port->pcie, value, ctrl); |
503 | 541 | ||
504 | tegra_pcie_port_reset(port); | 542 | tegra_pcie_port_reset(port); |
@@ -551,6 +589,8 @@ static void tegra_pcie_fixup_class(struct pci_dev *dev) | |||
551 | } | 589 | } |
552 | DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_NVIDIA, 0x0bf0, tegra_pcie_fixup_class); | 590 | DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_NVIDIA, 0x0bf0, tegra_pcie_fixup_class); |
553 | DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_NVIDIA, 0x0bf1, tegra_pcie_fixup_class); | 591 | DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_NVIDIA, 0x0bf1, tegra_pcie_fixup_class); |
592 | DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_NVIDIA, 0x0e1c, tegra_pcie_fixup_class); | ||
593 | DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_NVIDIA, 0x0e1d, tegra_pcie_fixup_class); | ||
554 | 594 | ||
555 | /* Tegra PCIE requires relaxed ordering */ | 595 | /* Tegra PCIE requires relaxed ordering */ |
556 | static void tegra_pcie_relax_enable(struct pci_dev *dev) | 596 | static void tegra_pcie_relax_enable(struct pci_dev *dev) |
@@ -723,10 +763,15 @@ static void tegra_pcie_setup_translations(struct tegra_pcie *pcie) | |||
723 | 763 | ||
724 | static int tegra_pcie_enable_controller(struct tegra_pcie *pcie) | 764 | static int tegra_pcie_enable_controller(struct tegra_pcie *pcie) |
725 | { | 765 | { |
766 | const struct tegra_pcie_soc_data *soc = pcie->soc_data; | ||
726 | struct tegra_pcie_port *port; | 767 | struct tegra_pcie_port *port; |
727 | unsigned int timeout; | 768 | unsigned int timeout; |
728 | unsigned long value; | 769 | unsigned long value; |
729 | 770 | ||
771 | /* power down PCIe slot clock bias pad */ | ||
772 | if (soc->has_pex_bias_ctrl) | ||
773 | afi_writel(pcie, 0, AFI_PEXBIAS_CTRL_0); | ||
774 | |||
730 | /* configure mode and disable all ports */ | 775 | /* configure mode and disable all ports */ |
731 | value = afi_readl(pcie, AFI_PCIE_CONFIG); | 776 | value = afi_readl(pcie, AFI_PCIE_CONFIG); |
732 | value &= ~AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_MASK; | 777 | value &= ~AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_MASK; |
@@ -753,27 +798,26 @@ static int tegra_pcie_enable_controller(struct tegra_pcie *pcie) | |||
753 | * Set up PHY PLL inputs select PLLE output as refclock, | 798 | * Set up PHY PLL inputs select PLLE output as refclock, |
754 | * set TX ref sel to div10 (not div5). | 799 | * set TX ref sel to div10 (not div5). |
755 | */ | 800 | */ |
756 | value = pads_readl(pcie, PADS_PLL_CTL); | 801 | value = pads_readl(pcie, soc->pads_pll_ctl); |
757 | value &= ~(PADS_PLL_CTL_REFCLK_MASK | PADS_PLL_CTL_TXCLKREF_MASK); | 802 | value &= ~(PADS_PLL_CTL_REFCLK_MASK | PADS_PLL_CTL_TXCLKREF_MASK); |
758 | value |= PADS_PLL_CTL_REFCLK_INTERNAL_CML | | 803 | value |= PADS_PLL_CTL_REFCLK_INTERNAL_CML | soc->tx_ref_sel; |
759 | PADS_PLL_CTL_TXCLKREF_DIV10; | 804 | pads_writel(pcie, value, soc->pads_pll_ctl); |
760 | pads_writel(pcie, value, PADS_PLL_CTL); | ||
761 | 805 | ||
762 | /* take PLL out of reset */ | 806 | /* take PLL out of reset */ |
763 | value = pads_readl(pcie, PADS_PLL_CTL); | 807 | value = pads_readl(pcie, soc->pads_pll_ctl); |
764 | value |= PADS_PLL_CTL_RST_B4SM; | 808 | value |= PADS_PLL_CTL_RST_B4SM; |
765 | pads_writel(pcie, value, PADS_PLL_CTL); | 809 | pads_writel(pcie, value, soc->pads_pll_ctl); |
766 | 810 | ||
767 | /* | 811 | /* |
768 | * Hack, set the clock voltage to the DEFAULT provided by hw folks. | 812 | * Hack, set the clock voltage to the DEFAULT provided by hw folks. |
769 | * This doesn't exist in the documentation. | 813 | * This doesn't exist in the documentation. |
770 | */ | 814 | */ |
771 | pads_writel(pcie, 0xfa5cfa5c, 0xc8); | 815 | pads_writel(pcie, 0xfa5cfa5c, PADS_REFCLK_CFG0); |
772 | 816 | ||
773 | /* wait for the PLL to lock */ | 817 | /* wait for the PLL to lock */ |
774 | timeout = 300; | 818 | timeout = 300; |
775 | do { | 819 | do { |
776 | value = pads_readl(pcie, PADS_PLL_CTL); | 820 | value = pads_readl(pcie, soc->pads_pll_ctl); |
777 | usleep_range(1000, 2000); | 821 | usleep_range(1000, 2000); |
778 | if (--timeout == 0) { | 822 | if (--timeout == 0) { |
779 | pr_err("Tegra PCIe error: timeout waiting for PLL\n"); | 823 | pr_err("Tegra PCIe error: timeout waiting for PLL\n"); |
@@ -802,6 +846,10 @@ static int tegra_pcie_enable_controller(struct tegra_pcie *pcie) | |||
802 | value = AFI_INTR_EN_INI_SLVERR | AFI_INTR_EN_INI_DECERR | | 846 | value = AFI_INTR_EN_INI_SLVERR | AFI_INTR_EN_INI_DECERR | |
803 | AFI_INTR_EN_TGT_SLVERR | AFI_INTR_EN_TGT_DECERR | | 847 | AFI_INTR_EN_TGT_SLVERR | AFI_INTR_EN_TGT_DECERR | |
804 | AFI_INTR_EN_TGT_WRERR | AFI_INTR_EN_DFPCI_DECERR; | 848 | AFI_INTR_EN_TGT_WRERR | AFI_INTR_EN_DFPCI_DECERR; |
849 | |||
850 | if (soc->has_intr_prsnt_sense) | ||
851 | value |= AFI_INTR_EN_PRSNT_SENSE; | ||
852 | |||
805 | afi_writel(pcie, value, AFI_AFI_INTR_ENABLE); | 853 | afi_writel(pcie, value, AFI_AFI_INTR_ENABLE); |
806 | afi_writel(pcie, 0xffffffff, AFI_SM_INTR_ENABLE); | 854 | afi_writel(pcie, 0xffffffff, AFI_SM_INTR_ENABLE); |
807 | 855 | ||
@@ -816,6 +864,7 @@ static int tegra_pcie_enable_controller(struct tegra_pcie *pcie) | |||
816 | 864 | ||
817 | static void tegra_pcie_power_off(struct tegra_pcie *pcie) | 865 | static void tegra_pcie_power_off(struct tegra_pcie *pcie) |
818 | { | 866 | { |
867 | const struct tegra_pcie_soc_data *soc = pcie->soc_data; | ||
819 | int err; | 868 | int err; |
820 | 869 | ||
821 | /* TODO: disable and unprepare clocks? */ | 870 | /* TODO: disable and unprepare clocks? */ |
@@ -826,19 +875,28 @@ static void tegra_pcie_power_off(struct tegra_pcie *pcie) | |||
826 | 875 | ||
827 | tegra_powergate_power_off(TEGRA_POWERGATE_PCIE); | 876 | tegra_powergate_power_off(TEGRA_POWERGATE_PCIE); |
828 | 877 | ||
878 | if (soc->has_avdd_supply) { | ||
879 | err = regulator_disable(pcie->avdd_supply); | ||
880 | if (err < 0) | ||
881 | dev_warn(pcie->dev, | ||
882 | "failed to disable AVDD regulator: %d\n", | ||
883 | err); | ||
884 | } | ||
885 | |||
829 | err = regulator_disable(pcie->pex_clk_supply); | 886 | err = regulator_disable(pcie->pex_clk_supply); |
830 | if (err < 0) | 887 | if (err < 0) |
831 | dev_err(pcie->dev, "failed to disable pex-clk regulator: %d\n", | 888 | dev_warn(pcie->dev, "failed to disable pex-clk regulator: %d\n", |
832 | err); | 889 | err); |
833 | 890 | ||
834 | err = regulator_disable(pcie->vdd_supply); | 891 | err = regulator_disable(pcie->vdd_supply); |
835 | if (err < 0) | 892 | if (err < 0) |
836 | dev_err(pcie->dev, "failed to disable VDD regulator: %d\n", | 893 | dev_warn(pcie->dev, "failed to disable VDD regulator: %d\n", |
837 | err); | 894 | err); |
838 | } | 895 | } |
839 | 896 | ||
840 | static int tegra_pcie_power_on(struct tegra_pcie *pcie) | 897 | static int tegra_pcie_power_on(struct tegra_pcie *pcie) |
841 | { | 898 | { |
899 | const struct tegra_pcie_soc_data *soc = pcie->soc_data; | ||
842 | int err; | 900 | int err; |
843 | 901 | ||
844 | tegra_periph_reset_assert(pcie->pcie_xclk); | 902 | tegra_periph_reset_assert(pcie->pcie_xclk); |
@@ -861,6 +919,16 @@ static int tegra_pcie_power_on(struct tegra_pcie *pcie) | |||
861 | return err; | 919 | return err; |
862 | } | 920 | } |
863 | 921 | ||
922 | if (soc->has_avdd_supply) { | ||
923 | err = regulator_enable(pcie->avdd_supply); | ||
924 | if (err < 0) { | ||
925 | dev_err(pcie->dev, | ||
926 | "failed to enable AVDD regulator: %d\n", | ||
927 | err); | ||
928 | return err; | ||
929 | } | ||
930 | } | ||
931 | |||
864 | err = tegra_powergate_sequence_power_up(TEGRA_POWERGATE_PCIE, | 932 | err = tegra_powergate_sequence_power_up(TEGRA_POWERGATE_PCIE, |
865 | pcie->pex_clk); | 933 | pcie->pex_clk); |
866 | if (err) { | 934 | if (err) { |
@@ -876,6 +944,15 @@ static int tegra_pcie_power_on(struct tegra_pcie *pcie) | |||
876 | return err; | 944 | return err; |
877 | } | 945 | } |
878 | 946 | ||
947 | if (soc->has_cml_clk) { | ||
948 | err = clk_prepare_enable(pcie->cml_clk); | ||
949 | if (err < 0) { | ||
950 | dev_err(pcie->dev, "failed to enable CML clock: %d\n", | ||
951 | err); | ||
952 | return err; | ||
953 | } | ||
954 | } | ||
955 | |||
879 | err = clk_prepare_enable(pcie->pll_e); | 956 | err = clk_prepare_enable(pcie->pll_e); |
880 | if (err < 0) { | 957 | if (err < 0) { |
881 | dev_err(pcie->dev, "failed to enable PLLE clock: %d\n", err); | 958 | dev_err(pcie->dev, "failed to enable PLLE clock: %d\n", err); |
@@ -887,6 +964,8 @@ static int tegra_pcie_power_on(struct tegra_pcie *pcie) | |||
887 | 964 | ||
888 | static int tegra_pcie_clocks_get(struct tegra_pcie *pcie) | 965 | static int tegra_pcie_clocks_get(struct tegra_pcie *pcie) |
889 | { | 966 | { |
967 | const struct tegra_pcie_soc_data *soc = pcie->soc_data; | ||
968 | |||
890 | pcie->pex_clk = devm_clk_get(pcie->dev, "pex"); | 969 | pcie->pex_clk = devm_clk_get(pcie->dev, "pex"); |
891 | if (IS_ERR(pcie->pex_clk)) | 970 | if (IS_ERR(pcie->pex_clk)) |
892 | return PTR_ERR(pcie->pex_clk); | 971 | return PTR_ERR(pcie->pex_clk); |
@@ -903,6 +982,12 @@ static int tegra_pcie_clocks_get(struct tegra_pcie *pcie) | |||
903 | if (IS_ERR(pcie->pll_e)) | 982 | if (IS_ERR(pcie->pll_e)) |
904 | return PTR_ERR(pcie->pll_e); | 983 | return PTR_ERR(pcie->pll_e); |
905 | 984 | ||
985 | if (soc->has_cml_clk) { | ||
986 | pcie->cml_clk = devm_clk_get(pcie->dev, "cml"); | ||
987 | if (IS_ERR(pcie->cml_clk)) | ||
988 | return PTR_ERR(pcie->cml_clk); | ||
989 | } | ||
990 | |||
906 | return 0; | 991 | return 0; |
907 | } | 992 | } |
908 | 993 | ||
@@ -1127,6 +1212,7 @@ static const struct irq_domain_ops msi_domain_ops = { | |||
1127 | static int tegra_pcie_enable_msi(struct tegra_pcie *pcie) | 1212 | static int tegra_pcie_enable_msi(struct tegra_pcie *pcie) |
1128 | { | 1213 | { |
1129 | struct platform_device *pdev = to_platform_device(pcie->dev); | 1214 | struct platform_device *pdev = to_platform_device(pcie->dev); |
1215 | const struct tegra_pcie_soc_data *soc = pcie->soc_data; | ||
1130 | struct tegra_msi *msi = &pcie->msi; | 1216 | struct tegra_msi *msi = &pcie->msi; |
1131 | unsigned long base; | 1217 | unsigned long base; |
1132 | int err; | 1218 | int err; |
@@ -1164,7 +1250,7 @@ static int tegra_pcie_enable_msi(struct tegra_pcie *pcie) | |||
1164 | msi->pages = __get_free_pages(GFP_KERNEL, 0); | 1250 | msi->pages = __get_free_pages(GFP_KERNEL, 0); |
1165 | base = virt_to_phys((void *)msi->pages); | 1251 | base = virt_to_phys((void *)msi->pages); |
1166 | 1252 | ||
1167 | afi_writel(pcie, base, AFI_MSI_FPCI_BAR_ST); | 1253 | afi_writel(pcie, base >> soc->msi_base_shift, AFI_MSI_FPCI_BAR_ST); |
1168 | afi_writel(pcie, base, AFI_MSI_AXI_BAR_ST); | 1254 | afi_writel(pcie, base, AFI_MSI_AXI_BAR_ST); |
1169 | /* this register is in 4K increments */ | 1255 | /* this register is in 4K increments */ |
1170 | afi_writel(pcie, 1, AFI_MSI_BAR_SZ); | 1256 | afi_writel(pcie, 1, AFI_MSI_BAR_SZ); |
@@ -1233,16 +1319,35 @@ static int tegra_pcie_get_xbar_config(struct tegra_pcie *pcie, u32 lanes, | |||
1233 | { | 1319 | { |
1234 | struct device_node *np = pcie->dev->of_node; | 1320 | struct device_node *np = pcie->dev->of_node; |
1235 | 1321 | ||
1236 | switch (lanes) { | 1322 | if (of_device_is_compatible(np, "nvidia,tegra30-pcie")) { |
1237 | case 0x00000004: | 1323 | switch (lanes) { |
1238 | dev_info(pcie->dev, "single-mode configuration\n"); | 1324 | case 0x00000204: |
1239 | *xbar = AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_SINGLE; | 1325 | dev_info(pcie->dev, "4x1, 2x1 configuration\n"); |
1240 | return 0; | 1326 | *xbar = AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_420; |
1241 | 1327 | return 0; | |
1242 | case 0x00000202: | 1328 | |
1243 | dev_info(pcie->dev, "dual-mode configuration\n"); | 1329 | case 0x00020202: |
1244 | *xbar = AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_DUAL; | 1330 | dev_info(pcie->dev, "2x3 configuration\n"); |
1245 | return 0; | 1331 | *xbar = AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_222; |
1332 | return 0; | ||
1333 | |||
1334 | case 0x00010104: | ||
1335 | dev_info(pcie->dev, "4x1, 1x2 configuration\n"); | ||
1336 | *xbar = AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_411; | ||
1337 | return 0; | ||
1338 | } | ||
1339 | } else if (of_device_is_compatible(np, "nvidia,tegra20-pcie")) { | ||
1340 | switch (lanes) { | ||
1341 | case 0x00000004: | ||
1342 | dev_info(pcie->dev, "single-mode configuration\n"); | ||
1343 | *xbar = AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_SINGLE; | ||
1344 | return 0; | ||
1345 | |||
1346 | case 0x00000202: | ||
1347 | dev_info(pcie->dev, "dual-mode configuration\n"); | ||
1348 | *xbar = AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_DUAL; | ||
1349 | return 0; | ||
1350 | } | ||
1246 | } | 1351 | } |
1247 | 1352 | ||
1248 | return -EINVAL; | 1353 | return -EINVAL; |
@@ -1250,6 +1355,7 @@ static int tegra_pcie_get_xbar_config(struct tegra_pcie *pcie, u32 lanes, | |||
1250 | 1355 | ||
1251 | static int tegra_pcie_parse_dt(struct tegra_pcie *pcie) | 1356 | static int tegra_pcie_parse_dt(struct tegra_pcie *pcie) |
1252 | { | 1357 | { |
1358 | const struct tegra_pcie_soc_data *soc = pcie->soc_data; | ||
1253 | struct device_node *np = pcie->dev->of_node, *port; | 1359 | struct device_node *np = pcie->dev->of_node, *port; |
1254 | struct of_pci_range_parser parser; | 1360 | struct of_pci_range_parser parser; |
1255 | struct of_pci_range range; | 1361 | struct of_pci_range range; |
@@ -1270,6 +1376,12 @@ static int tegra_pcie_parse_dt(struct tegra_pcie *pcie) | |||
1270 | if (IS_ERR(pcie->pex_clk_supply)) | 1376 | if (IS_ERR(pcie->pex_clk_supply)) |
1271 | return PTR_ERR(pcie->pex_clk_supply); | 1377 | return PTR_ERR(pcie->pex_clk_supply); |
1272 | 1378 | ||
1379 | if (soc->has_avdd_supply) { | ||
1380 | pcie->avdd_supply = devm_regulator_get(pcie->dev, "avdd"); | ||
1381 | if (IS_ERR(pcie->avdd_supply)) | ||
1382 | return PTR_ERR(pcie->avdd_supply); | ||
1383 | } | ||
1384 | |||
1273 | for_each_of_pci_range(&parser, &range) { | 1385 | for_each_of_pci_range(&parser, &range) { |
1274 | of_pci_range_to_resource(&range, np, &res); | 1386 | of_pci_range_to_resource(&range, np, &res); |
1275 | 1387 | ||
@@ -1316,7 +1428,7 @@ static int tegra_pcie_parse_dt(struct tegra_pcie *pcie) | |||
1316 | 1428 | ||
1317 | index = PCI_SLOT(err); | 1429 | index = PCI_SLOT(err); |
1318 | 1430 | ||
1319 | if (index < 1 || index > TEGRA_MAX_PORTS) { | 1431 | if (index < 1 || index > soc->num_ports) { |
1320 | dev_err(pcie->dev, "invalid port number: %d\n", index); | 1432 | dev_err(pcie->dev, "invalid port number: %d\n", index); |
1321 | return -EINVAL; | 1433 | return -EINVAL; |
1322 | } | 1434 | } |
@@ -1454,17 +1566,54 @@ static int tegra_pcie_enable(struct tegra_pcie *pcie) | |||
1454 | return 0; | 1566 | return 0; |
1455 | } | 1567 | } |
1456 | 1568 | ||
1569 | static const struct tegra_pcie_soc_data tegra20_pcie_data = { | ||
1570 | .num_ports = 2, | ||
1571 | .msi_base_shift = 0, | ||
1572 | .pads_pll_ctl = PADS_PLL_CTL_TEGRA20, | ||
1573 | .tx_ref_sel = PADS_PLL_CTL_TXCLKREF_DIV10, | ||
1574 | .has_pex_clkreq_en = false, | ||
1575 | .has_pex_bias_ctrl = false, | ||
1576 | .has_intr_prsnt_sense = false, | ||
1577 | .has_avdd_supply = false, | ||
1578 | .has_cml_clk = false, | ||
1579 | }; | ||
1580 | |||
1581 | static const struct tegra_pcie_soc_data tegra30_pcie_data = { | ||
1582 | .num_ports = 3, | ||
1583 | .msi_base_shift = 8, | ||
1584 | .pads_pll_ctl = PADS_PLL_CTL_TEGRA30, | ||
1585 | .tx_ref_sel = PADS_PLL_CTL_TXCLKREF_BUF_EN, | ||
1586 | .has_pex_clkreq_en = true, | ||
1587 | .has_pex_bias_ctrl = true, | ||
1588 | .has_intr_prsnt_sense = true, | ||
1589 | .has_avdd_supply = true, | ||
1590 | .has_cml_clk = true, | ||
1591 | }; | ||
1592 | |||
1593 | static const struct of_device_id tegra_pcie_of_match[] = { | ||
1594 | { .compatible = "nvidia,tegra30-pcie", .data = &tegra30_pcie_data }, | ||
1595 | { .compatible = "nvidia,tegra20-pcie", .data = &tegra20_pcie_data }, | ||
1596 | { }, | ||
1597 | }; | ||
1598 | MODULE_DEVICE_TABLE(of, tegra_pcie_of_match); | ||
1599 | |||
1457 | static int tegra_pcie_probe(struct platform_device *pdev) | 1600 | static int tegra_pcie_probe(struct platform_device *pdev) |
1458 | { | 1601 | { |
1602 | const struct of_device_id *match; | ||
1459 | struct tegra_pcie *pcie; | 1603 | struct tegra_pcie *pcie; |
1460 | int err; | 1604 | int err; |
1461 | 1605 | ||
1606 | match = of_match_device(tegra_pcie_of_match, &pdev->dev); | ||
1607 | if (!match) | ||
1608 | return -ENODEV; | ||
1609 | |||
1462 | pcie = devm_kzalloc(&pdev->dev, sizeof(*pcie), GFP_KERNEL); | 1610 | pcie = devm_kzalloc(&pdev->dev, sizeof(*pcie), GFP_KERNEL); |
1463 | if (!pcie) | 1611 | if (!pcie) |
1464 | return -ENOMEM; | 1612 | return -ENOMEM; |
1465 | 1613 | ||
1466 | INIT_LIST_HEAD(&pcie->busses); | 1614 | INIT_LIST_HEAD(&pcie->busses); |
1467 | INIT_LIST_HEAD(&pcie->ports); | 1615 | INIT_LIST_HEAD(&pcie->ports); |
1616 | pcie->soc_data = match->data; | ||
1468 | pcie->dev = &pdev->dev; | 1617 | pcie->dev = &pdev->dev; |
1469 | 1618 | ||
1470 | err = tegra_pcie_parse_dt(pcie); | 1619 | err = tegra_pcie_parse_dt(pcie); |
@@ -1513,12 +1662,6 @@ put_resources: | |||
1513 | return err; | 1662 | return err; |
1514 | } | 1663 | } |
1515 | 1664 | ||
1516 | static const struct of_device_id tegra_pcie_of_match[] = { | ||
1517 | { .compatible = "nvidia,tegra20-pcie", }, | ||
1518 | { }, | ||
1519 | }; | ||
1520 | MODULE_DEVICE_TABLE(of, tegra_pcie_of_match); | ||
1521 | |||
1522 | static struct platform_driver tegra_pcie_driver = { | 1665 | static struct platform_driver tegra_pcie_driver = { |
1523 | .driver = { | 1666 | .driver = { |
1524 | .name = "tegra-pcie", | 1667 | .name = "tegra-pcie", |