+CC linux-tegra@xxxxxxxxxxxxxxx >-----Original Message----- >From: Preetham Chandru >Sent: Friday, May 12, 2017 3:04 PM >To: thierry.reding@xxxxxxxxx; tj@xxxxxxxxxx >Cc: tegra@xxxxxxxxxxxxxxx; linux-ide@xxxxxxxxxxxxxxx; Laxman Dewangan ><ldewangan@xxxxxxxxxx>; preetham260@xxxxxxxxx; Venu Byravarasu ><vbyravarasu@xxxxxxxxxx>; Pavan Kunapuli <pkunapuli@xxxxxxxxxx>; Preetham >Chandru <pchandru@xxxxxxxxxx> >Subject: [PATCH V3 1/3] ata: ahci_tegra: Add AHCI support for tegra210 > >From: Preetham Chandru R <pchandru@xxxxxxxxxx> > >1. Move tegra124 specifics to tegra124_ahci_init. >2. Separate the regulators needed for tegra124 and tegra210. >3. Disable DIPM and Devslp for t210 and t124 as there are known issues > >Signed-off-by: Preetham Chandru R <pchandru@xxxxxxxxxx> >--- >v3: >* Remove inline functions for read/write and modify to > SATA, SATA Config and SATA Aux registers. >* Add code to disable DIPM and DevSlp for t210 and t124 >v2: >* Fix indentation issues >* Move the change to disable DIPM, HIPM, DevSlp, partial, > slumber and NCQ into a separate patch >--- > drivers/ata/ahci_tegra.c | 377 ++++++++++++++++++++++++++++++++++++------- >---- > 1 file changed, 293 insertions(+), 84 deletions(-) > >diff --git a/drivers/ata/ahci_tegra.c b/drivers/ata/ahci_tegra.c index >3a62eb2..cd581a6 100644 >--- a/drivers/ata/ahci_tegra.c >+++ b/drivers/ata/ahci_tegra.c >@@ -34,7 +34,8 @@ > #define DRV_NAME "tegra-ahci" > > #define SATA_CONFIGURATION_0 0x180 >-#define SATA_CONFIGURATION_EN_FPCI BIT(0) >+#define SATA_CONFIGURATION_0_EN_FPCI BIT(0) >+#define SATA_CONFIGURATION_0_CLK_OVERRIDE BIT(31) > > #define SCFG_OFFSET 0x1000 > >@@ -45,17 +46,55 @@ > #define T_SATA0_CFG_1_SERR BIT(8) > > #define T_SATA0_CFG_9 0x24 >-#define T_SATA0_CFG_9_BASE_ADDRESS_SHIFT 13 >+#define T_SATA0_CFG_9_BASE_ADDRESS 0x40020000 > > #define SATA_FPCI_BAR5 0x94 >-#define SATA_FPCI_BAR5_START_SHIFT 4 >+#define SATA_FPCI_BAR5_START_MASK (0xfffffff << 4) >+#define SATA_FPCI_BAR5_START (0x0040020 << >4) >+#define SATA_FPCI_BAR5_ACCESS_TYPE (0x1) > > #define SATA_INTR_MASK 0x188 > #define SATA_INTR_MASK_IP_INT_MASK BIT(16) > >+#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 BIT(23) >+#define T_SATA0_CFG_PHY_1_PAD_PLL_IDDQ_EN BIT(22) >+ >+#define T_SATA0_NVOOB 0x114 >+#define T_SATA0_NVOOB_COMMA_CNT_MASK (0xff << 16) >+#define T_SATA0_NVOOB_COMMA_CNT (0x07 << 16) >+#define T_SATA0_NVOOB_SQUELCH_FILTER_MODE_MASK (0x3 << 24) >+#define T_SATA0_NVOOB_SQUELCH_FILTER_MODE (0x1 << 24) >+#define T_SATA0_NVOOB_SQUELCH_FILTER_LENGTH_MASK (0x3 << 26) >+#define T_SATA0_NVOOB_SQUELCH_FILTER_LENGTH (0x3 << 26) >+ >+#define T_SATA_CFG_PHY_0 0x120 >+#define T_SATA_CFG_PHY_0_USE_7BIT_ALIGN_DET_FOR_SPD BIT(11) >+#define T_SATA_CFG_PHY_0_MASK_SQUELCH BIT(24) >+ >+#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_PARTIAL_ST_CAP BIT(13) >+#define T_SATA0_AHCI_HBA_CAP_BKDR_SLUMBER_ST_CAP BIT(14) >+#define T_SATA0_AHCI_HBA_CAP_BKDR_SALP BIT(26) >+#define T_SATA0_AHCI_HBA_CAP_BKDR_SUPP_PM BIT(17) >+#define T_SATA0_AHCI_HBA_CAP_BKDR_SNCQ BIT(30) > > #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 BIT(12) >@@ -82,9 +121,35 @@ > #define T_SATA0_CHX_PHY_CTRL11 0x6d0 > #define T_SATA0_CHX_PHY_CTRL11_GEN2_RX_EQ (0x2800 << 16) > >+#define T_SATA0_CHX_PHY_CTRL17_0 0x6e8 >+#define T_SATA0_CHX_PHY_CTRL17_0_RX_EQ_CTRL_L_GEN1 0x55010000 >+#define T_SATA0_CHX_PHY_CTRL18_0 0x6ec >+#define T_SATA0_CHX_PHY_CTRL18_0_RX_EQ_CTRL_L_GEN2 0x55010000 >+#define T_SATA0_CHX_PHY_CTRL20_0 0x6f4 >+#define T_SATA0_CHX_PHY_CTRL20_0_RX_EQ_CTRL_H_GEN1 0x1 >+#define T_SATA0_CHX_PHY_CTRL21_0 0x6f8 >+#define T_SATA0_CHX_PHY_CTRL21_0_RX_EQ_CTRL_H_GEN2 0x1 >+ >+/* AUX Registers */ >+#define SATA_AUX_MISC_CNTL_1_0 0x8 >+#define SATA_AUX_MISC_CNTL_1_0_DEVSLP_OVERRIDE BIT(17) >+#define SATA_AUX_MISC_CNTL_1_0_SDS_SUPPORT BIT(13) >+#define SATA_AUX_MISC_CNTL_1_0_DESO_SUPPORT BIT(15) >+ >+#define SATA_AUX_RX_STAT_INT_0 0xc >+#define SATA_AUX_RX_STAT_INT_0_SATA_DEVSLP BIT(7) >+ >+#define SATA_AUX_SPARE_CFG0_0 0x18 >+#define SATA_AUX_SPARE_CFG0_0_MDAT_TIMER_AFTER_PG_VALID BIT(14) >+ > #define FUSE_SATA_CALIB 0x124 > #define FUSE_SATA_CALIB_MASK 0x3 > >+enum { >+ NO_DEVSLP = (1 << 0), >+ NO_DIPM = (1 << 1), >+}; >+ > struct sata_pad_calibration { > u8 gen1_tx_amp; > u8 gen1_tx_peak; >@@ -99,15 +164,89 @@ static const struct sata_pad_calibration >tegra124_pad_calibration[] = { > {0x14, 0x0e, 0x1a, 0x0e}, > }; > >+struct tegra_ahci_ops { >+ int (*init)(struct ahci_host_priv *); >+}; >+ >+struct tegra_ahci_soc { >+ const char *const *supply_names; >+ u32 num_supplies; >+ u32 quirks; >+ struct tegra_ahci_ops ops; >+}; >+ > struct tegra_ahci_priv { > struct platform_device *pdev; > void __iomem *sata_regs; >+ void __iomem *sata_aux_regs; > struct reset_control *sata_rst; > struct reset_control *sata_oob_rst; > struct reset_control *sata_cold_rst; > /* Needs special handling, cannot use ahci_platform */ > struct clk *sata_clk; >- struct regulator_bulk_data supplies[5]; >+ struct regulator_bulk_data *supplies; >+ struct tegra_ahci_soc *soc_data; >+}; >+ >+static const char *const tegra124_supply_names[] = { >+ "avdd", "hvdd", "vddio", "target-5v", "target-12v" >+}; >+ >+static int tegra124_ahci_init(struct ahci_host_priv *hpriv) { >+ struct tegra_ahci_priv *tegra = hpriv->plat_data; >+ struct sata_pad_calibration calib; >+ int ret; >+ u32 val; >+ >+ /* Pad calibration */ >+ ret = tegra_fuse_readl(FUSE_SATA_CALIB, &val); >+ if (ret) >+ return ret; >+ >+ calib = tegra124_pad_calibration[val & FUSE_SATA_CALIB_MASK]; >+ >+ writel(BIT(0), tegra->sata_regs + SCFG_OFFSET + T_SATA0_INDEX); >+ >+ val = readl(tegra->sata_regs + >+ SCFG_OFFSET + T_SATA0_CHX_PHY_CTRL1_GEN1); >+ val &= ~T_SATA0_CHX_PHY_CTRL1_GEN1_TX_AMP_MASK; >+ val &= ~T_SATA0_CHX_PHY_CTRL1_GEN1_TX_PEAK_MASK; >+ val |= calib.gen1_tx_amp << >T_SATA0_CHX_PHY_CTRL1_GEN1_TX_AMP_SHIFT; >+ val |= calib.gen1_tx_peak << >T_SATA0_CHX_PHY_CTRL1_GEN1_TX_PEAK_SHIFT; >+ writel(val, tegra->sata_regs + SCFG_OFFSET + >+ T_SATA0_CHX_PHY_CTRL1_GEN1); >+ >+ val = readl(tegra->sata_regs + >+ SCFG_OFFSET + T_SATA0_CHX_PHY_CTRL1_GEN2); >+ val &= ~T_SATA0_CHX_PHY_CTRL1_GEN2_TX_AMP_MASK; >+ val &= ~T_SATA0_CHX_PHY_CTRL1_GEN2_TX_PEAK_MASK; >+ val |= calib.gen2_tx_amp << >T_SATA0_CHX_PHY_CTRL1_GEN1_TX_AMP_SHIFT; >+ val |= calib.gen2_tx_peak << >T_SATA0_CHX_PHY_CTRL1_GEN1_TX_PEAK_SHIFT; >+ writel(val, tegra->sata_regs + SCFG_OFFSET + >+ T_SATA0_CHX_PHY_CTRL1_GEN2); >+ >+ writel(T_SATA0_CHX_PHY_CTRL11_GEN2_RX_EQ, >+ tegra->sata_regs + SCFG_OFFSET + T_SATA0_CHX_PHY_CTRL11); >+ writel(T_SATA0_CHX_PHY_CTRL2_CDR_CNTL_GEN1, >+ tegra->sata_regs + SCFG_OFFSET + T_SATA0_CHX_PHY_CTRL2); >+ >+ writel(0, tegra->sata_regs + SCFG_OFFSET + T_SATA0_INDEX); >+ >+ return 0; >+} >+ >+static const struct tegra_ahci_soc tegra124_ahci_soc_data = { >+ .supply_names = tegra124_supply_names, >+ .num_supplies = ARRAY_SIZE(tegra124_supply_names), >+ .quirks = NO_DIPM | NO_DEVSLP, >+ .ops = { >+ .init = tegra124_ahci_init, >+ }, >+}; >+ >+static const struct tegra_ahci_soc tegra210_ahci_soc_data = { >+ .quirks = NO_DIPM | NO_DEVSLP, > }; > > static int tegra_ahci_power_on(struct ahci_host_priv *hpriv) @@ -115,7 +254,7 >@@ static int tegra_ahci_power_on(struct ahci_host_priv *hpriv) > struct tegra_ahci_priv *tegra = hpriv->plat_data; > int ret; > >- ret = regulator_bulk_enable(ARRAY_SIZE(tegra->supplies), >+ ret = regulator_bulk_enable(tegra->soc_data->num_supplies, > tegra->supplies); > if (ret) > return ret; >@@ -144,8 +283,7 @@ static int tegra_ahci_power_on(struct ahci_host_priv >*hpriv) > tegra_powergate_power_off(TEGRA_POWERGATE_SATA); > > disable_regulators: >- regulator_bulk_disable(ARRAY_SIZE(tegra->supplies), tegra->supplies); >- >+ regulator_bulk_disable(tegra->soc_data->num_supplies, >+tegra->supplies); > return ret; > } > >@@ -162,97 +300,137 @@ static void tegra_ahci_power_off(struct >ahci_host_priv *hpriv) > clk_disable_unprepare(tegra->sata_clk); > tegra_powergate_power_off(TEGRA_POWERGATE_SATA); > >- regulator_bulk_disable(ARRAY_SIZE(tegra->supplies), tegra->supplies); >+ regulator_bulk_disable(tegra->soc_data->num_supplies, >+tegra->supplies); > } > > static int tegra_ahci_controller_init(struct ahci_host_priv *hpriv) { > struct tegra_ahci_priv *tegra = hpriv->plat_data; > int ret; >- unsigned int val; >- struct sata_pad_calibration calib; >+ u32 val; > > ret = tegra_ahci_power_on(hpriv); >- if (ret) { >- dev_err(&tegra->pdev->dev, >- "failed to power on AHCI controller: %d\n", ret); >+ if (ret) > return ret; >- } > >+ /* >+ * Program the following SATA IPFS registers >+ * to allow SW accesses to SATA's MMIO Register >+ */ >+ val = readl(tegra->sata_regs + SATA_FPCI_BAR5); >+ val &= ~(SATA_FPCI_BAR5_START_MASK | >SATA_FPCI_BAR5_ACCESS_TYPE); >+ val |= SATA_FPCI_BAR5_START | SATA_FPCI_BAR5_ACCESS_TYPE; >+ writel(val, tegra->sata_regs + SATA_FPCI_BAR5); >+ >+ /* Program the following SATA IPFS register to enable the SATA */ > val = readl(tegra->sata_regs + SATA_CONFIGURATION_0); >- val |= SATA_CONFIGURATION_EN_FPCI; >+ val |= SATA_CONFIGURATION_0_EN_FPCI; > writel(val, tegra->sata_regs + SATA_CONFIGURATION_0); > >- /* Pad calibration */ >- >- ret = tegra_fuse_readl(FUSE_SATA_CALIB, &val); >- if (ret) { >- dev_err(&tegra->pdev->dev, >- "failed to read calibration fuse: %d\n", ret); >- return ret; >- } >- >- calib = tegra124_pad_calibration[val & FUSE_SATA_CALIB_MASK]; >- >- writel(BIT(0), tegra->sata_regs + SCFG_OFFSET + T_SATA0_INDEX); >- >- val = readl(tegra->sata_regs + >- SCFG_OFFSET + T_SATA0_CHX_PHY_CTRL1_GEN1); >- val &= ~T_SATA0_CHX_PHY_CTRL1_GEN1_TX_AMP_MASK; >- val &= ~T_SATA0_CHX_PHY_CTRL1_GEN1_TX_PEAK_MASK; >- val |= calib.gen1_tx_amp << >- T_SATA0_CHX_PHY_CTRL1_GEN1_TX_AMP_SHIFT; >- val |= calib.gen1_tx_peak << >- T_SATA0_CHX_PHY_CTRL1_GEN1_TX_PEAK_SHIFT; >- writel(val, tegra->sata_regs + SCFG_OFFSET + >- T_SATA0_CHX_PHY_CTRL1_GEN1); >- >- val = readl(tegra->sata_regs + >- SCFG_OFFSET + T_SATA0_CHX_PHY_CTRL1_GEN2); >- val &= ~T_SATA0_CHX_PHY_CTRL1_GEN2_TX_AMP_MASK; >- val &= ~T_SATA0_CHX_PHY_CTRL1_GEN2_TX_PEAK_MASK; >- val |= calib.gen2_tx_amp << >- T_SATA0_CHX_PHY_CTRL1_GEN1_TX_AMP_SHIFT; >- val |= calib.gen2_tx_peak << >- T_SATA0_CHX_PHY_CTRL1_GEN1_TX_PEAK_SHIFT; >- writel(val, tegra->sata_regs + SCFG_OFFSET + >- T_SATA0_CHX_PHY_CTRL1_GEN2); >- >- writel(T_SATA0_CHX_PHY_CTRL11_GEN2_RX_EQ, >- tegra->sata_regs + SCFG_OFFSET + T_SATA0_CHX_PHY_CTRL11); >- writel(T_SATA0_CHX_PHY_CTRL2_CDR_CNTL_GEN1, >- tegra->sata_regs + SCFG_OFFSET + T_SATA0_CHX_PHY_CTRL2); >- >- writel(0, tegra->sata_regs + SCFG_OFFSET + T_SATA0_INDEX); >- >- /* Program controller device ID */ >+ /* Electrical settings for better link stability */ >+ val = T_SATA0_CHX_PHY_CTRL17_0_RX_EQ_CTRL_L_GEN1; >+ writel(val, tegra->sata_regs + SCFG_OFFSET + >T_SATA0_CHX_PHY_CTRL17_0); >+ val = T_SATA0_CHX_PHY_CTRL18_0_RX_EQ_CTRL_L_GEN2; >+ writel(val, tegra->sata_regs + SCFG_OFFSET + >T_SATA0_CHX_PHY_CTRL18_0); >+ val = T_SATA0_CHX_PHY_CTRL20_0_RX_EQ_CTRL_H_GEN1; >+ writel(val, tegra->sata_regs + SCFG_OFFSET + >T_SATA0_CHX_PHY_CTRL20_0); >+ val = T_SATA0_CHX_PHY_CTRL21_0_RX_EQ_CTRL_H_GEN2; >+ writel(val, tegra->sata_regs + SCFG_OFFSET + >+T_SATA0_CHX_PHY_CTRL21_0); >+ >+ /* For SQUELCH Filter & Gen3 drive getting detected as Gen1 drive */ >+ >+ val = readl(tegra->sata_regs + SCFG_OFFSET + T_SATA_CFG_PHY_0); >+ val |= T_SATA_CFG_PHY_0_MASK_SQUELCH; >+ val &= ~T_SATA_CFG_PHY_0_USE_7BIT_ALIGN_DET_FOR_SPD; >+ writel(val, tegra->sata_regs + SCFG_OFFSET + T_SATA_CFG_PHY_0); >+ >+ val = readl(tegra->sata_regs + SCFG_OFFSET + T_SATA0_NVOOB); >+ val &= ~(T_SATA0_NVOOB_COMMA_CNT_MASK | >+ T_SATA0_NVOOB_SQUELCH_FILTER_LENGTH_MASK | >+ T_SATA0_NVOOB_SQUELCH_FILTER_MODE_MASK); >+ val |= (T_SATA0_NVOOB_COMMA_CNT | >+ T_SATA0_NVOOB_SQUELCH_FILTER_LENGTH | >+ T_SATA0_NVOOB_SQUELCH_FILTER_MODE); >+ writel(val, tegra->sata_regs + SCFG_OFFSET + T_SATA0_NVOOB); >+ >+ /* >+ * Change CFG2NVOOB_2_COMWAKE_IDLE_CNT_LOW from 83.3 ns to >58.8ns >+ */ >+ val = readl(tegra->sata_regs + 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; >+ writel(val, tegra->sata_regs + SCFG_OFFSET + T_SATA0_CFG2NVOOB_2); >+ >+ if (tegra->soc_data->ops.init) >+ tegra->soc_data->ops.init(hpriv); >+ >+ /* >+ * Program the following SATA configuration registers >+ * to initialize SATA >+ */ >+ val = readl(tegra->sata_regs + SCFG_OFFSET + T_SATA0_CFG_1); >+ val |= (T_SATA0_CFG_1_IO_SPACE | T_SATA0_CFG_1_MEMORY_SPACE | >+ T_SATA0_CFG_1_BUS_MASTER | T_SATA0_CFG_1_SERR); >+ writel(val, tegra->sata_regs + SCFG_OFFSET + T_SATA0_CFG_1); >+ val = T_SATA0_CFG_9_BASE_ADDRESS; >+ writel(val, tegra->sata_regs + SCFG_OFFSET + T_SATA0_CFG_9); > >+ /* Program Class Code and Programming interface for SATA */ > val = readl(tegra->sata_regs + SCFG_OFFSET + T_SATA0_CFG_SATA); > val |= T_SATA0_CFG_SATA_BACKDOOR_PROG_IF_EN; > writel(val, tegra->sata_regs + SCFG_OFFSET + T_SATA0_CFG_SATA); > >- writel(0x01060100, tegra->sata_regs + SCFG_OFFSET + >T_SATA0_BKDOOR_CC); >+ val = readl(tegra->sata_regs + SCFG_OFFSET + T_SATA0_BKDOOR_CC); >+ val &= >+ ~(T_SATA0_BKDOOR_CC_CLASS_CODE_MASK | >+ T_SATA0_BKDOOR_CC_PROG_IF_MASK); >+ val |= T_SATA0_BKDOOR_CC_CLASS_CODE | >T_SATA0_BKDOOR_CC_PROG_IF; >+ writel(val, tegra->sata_regs + SCFG_OFFSET + T_SATA0_BKDOOR_CC); > > val = readl(tegra->sata_regs + SCFG_OFFSET + T_SATA0_CFG_SATA); > val &= ~T_SATA0_CFG_SATA_BACKDOOR_PROG_IF_EN; > writel(val, tegra->sata_regs + SCFG_OFFSET + T_SATA0_CFG_SATA); > >- /* Enable IO & memory access, bus master mode */ >- >- val = readl(tegra->sata_regs + SCFG_OFFSET + T_SATA0_CFG_1); >- val |= T_SATA0_CFG_1_IO_SPACE | T_SATA0_CFG_1_MEMORY_SPACE | >- T_SATA0_CFG_1_BUS_MASTER | T_SATA0_CFG_1_SERR; >- writel(val, tegra->sata_regs + SCFG_OFFSET + T_SATA0_CFG_1); >- >- /* Program SATA MMIO */ >- >- writel(0x10000 << SATA_FPCI_BAR5_START_SHIFT, >- tegra->sata_regs + SATA_FPCI_BAR5); >- >- writel(0x08000 << T_SATA0_CFG_9_BASE_ADDRESS_SHIFT, >- tegra->sata_regs + SCFG_OFFSET + T_SATA0_CFG_9); >+ /* Enabling LPM capabilities through Backdoor Programming */ >+ val = readl(tegra->sata_regs + SCFG_OFFSET + >T_SATA0_AHCI_HBA_CAP_BKDR); >+ val |= (T_SATA0_AHCI_HBA_CAP_BKDR_PARTIAL_ST_CAP | >+ T_SATA0_AHCI_HBA_CAP_BKDR_SLUMBER_ST_CAP | >+ T_SATA0_AHCI_HBA_CAP_BKDR_SALP | >+ T_SATA0_AHCI_HBA_CAP_BKDR_SUPP_PM); >+ writel(val, tegra->sata_regs + SCFG_OFFSET + >+T_SATA0_AHCI_HBA_CAP_BKDR); >+ >+ /* SATA Second Level Clock Gating configuration >+ * Enabling Gating of Tx/Rx clocks and driving Pad IDDQ and Lane >+ * IDDQ Signals >+ */ >+ val = readl(tegra->sata_regs + SCFG_OFFSET + T_SATA0_CFG_35); >+ val &= ~T_SATA0_CFG_35_IDP_INDEX_MASK; >+ val |= T_SATA0_CFG_35_IDP_INDEX; >+ writel(val, tegra->sata_regs + SCFG_OFFSET + T_SATA0_CFG_35); >+ >+ val = T_SATA0_AHCI_IDP1_DATA; >+ writel(val, tegra->sata_regs + SCFG_OFFSET + T_SATA0_AHCI_IDP1); >+ >+ val = readl(tegra->sata_regs + SCFG_OFFSET + T_SATA0_CFG_PHY_1); >+ val |= (T_SATA0_CFG_PHY_1_PADS_IDDQ_EN | >+ T_SATA0_CFG_PHY_1_PAD_PLL_IDDQ_EN); >+ writel(val, tegra->sata_regs + SCFG_OFFSET + T_SATA0_CFG_PHY_1); >+ >+ /* >+ * Indicate Sata only has the capability to enter DevSleep >+ * from slumber link. >+ */ >+ >+ val = readl(tegra->sata_aux_regs + SATA_AUX_MISC_CNTL_1_0); >+ val |= SATA_AUX_MISC_CNTL_1_0_DESO_SUPPORT; >+ writel(val, tegra->sata_aux_regs + SATA_AUX_MISC_CNTL_1_0); >+ >+ /* Enabling IPFS Clock Gating */ >+ val = readl(tegra->sata_regs + SATA_CONFIGURATION_0); >+ val &= ~SATA_CONFIGURATION_0_CLK_OVERRIDE; >+ writel(val, tegra->sata_regs + SATA_CONFIGURATION_0); > >- /* Unmask SATA interrupts */ >+ tegra_ahci_handle_quirks(hpriv); > > val = readl(tegra->sata_regs + SATA_INTR_MASK); > val |= SATA_INTR_MASK_IP_INT_MASK; >@@ -278,7 +456,7 @@ static struct ata_port_operations ahci_tegra_port_ops = >{ > .host_stop = tegra_ahci_host_stop, > }; > >-static const struct ata_port_info ahci_tegra_port_info = { >+static struct ata_port_info ahci_tegra_port_info = { > .flags = AHCI_FLAG_COMMON, > .pio_mask = ATA_PIO4, > .udma_mask = ATA_UDMA6, >@@ -286,7 +464,14 @@ static const struct ata_port_info ahci_tegra_port_info = >{ }; > > static const struct of_device_id tegra_ahci_of_match[] = { >- { .compatible = "nvidia,tegra124-ahci" }, >+ { >+ .compatible = "nvidia,tegra124-ahci", >+ .data = &tegra124_ahci_soc_data >+ }, >+ { >+ .compatible = "nvidia,tegra210-ahci", >+ .data = &tegra210_ahci_soc_data >+ }, > {} > }; > MODULE_DEVICE_TABLE(of, tegra_ahci_of_match); @@ -295,12 +480,27 @@ >static struct scsi_host_template ahci_platform_sht = { > AHCI_SHT(DRV_NAME), > }; > >+static void tegra_ahci_handle_quirks(struct ahci_host_priv *hpriv) { >+ struct tegra_ahci_priv *tegra = hpriv->plat_data; >+ u32 val; >+ >+ if (tegra->soc_data->quirks & NO_DEVSLP) { >+ val = readl(tegra->sata_aux_regs + SATA_AUX_MISC_CNTL_1_0); >+ val &= ~SATA_AUX_MISC_CNTL_1_0_SDS_SUPPORT; >+ writel(val, tegra->sata_aux_regs + SATA_AUX_MISC_CNTL_1_0); >+ } else if (tegra->soc_data->quirks & NO_DIPM) { >+ ahci_tegra_port_info.flags |= ATA_FLAG_NO_DIPM; >+ } >+} >+ > static int tegra_ahci_probe(struct platform_device *pdev) { > struct ahci_host_priv *hpriv; > struct tegra_ahci_priv *tegra; > struct resource *res; > int ret; >+ unsigned int i; > > hpriv = ahci_platform_get_resources(pdev); > if (IS_ERR(hpriv)) >@@ -311,13 +511,18 @@ static int tegra_ahci_probe(struct platform_device >*pdev) > return -ENOMEM; > > hpriv->plat_data = tegra; >- > tegra->pdev = pdev; >+ tegra->soc_data = >+ (struct tegra_ahci_soc *)of_device_get_match_data(&pdev->dev); > > res = platform_get_resource(pdev, IORESOURCE_MEM, 1); > tegra->sata_regs = devm_ioremap_resource(&pdev->dev, res); > if (IS_ERR(tegra->sata_regs)) > return PTR_ERR(tegra->sata_regs); >+ res = platform_get_resource(pdev, IORESOURCE_MEM, 2); >+ tegra->sata_aux_regs = devm_ioremap_resource(&pdev->dev, res); >+ if (IS_ERR(tegra->sata_aux_regs)) >+ return PTR_ERR(tegra->sata_aux_regs); > > tegra->sata_rst = devm_reset_control_get(&pdev->dev, "sata"); > if (IS_ERR(tegra->sata_rst)) { >@@ -343,13 +548,17 @@ static int tegra_ahci_probe(struct platform_device >*pdev) > return PTR_ERR(tegra->sata_clk); > } > >- tegra->supplies[0].supply = "avdd"; >- tegra->supplies[1].supply = "hvdd"; >- tegra->supplies[2].supply = "vddio"; >- tegra->supplies[3].supply = "target-5v"; >- tegra->supplies[4].supply = "target-12v"; >+ tegra->supplies = devm_kcalloc(&pdev->dev, >+ tegra->soc_data->num_supplies, >+ sizeof(*tegra->supplies), GFP_KERNEL); >+ if (!tegra->supplies) >+ return -ENOMEM; >+ >+ for (i = 0; i < tegra->soc_data->num_supplies; i++) >+ tegra->supplies[i].supply = tegra->soc_data->supply_names[i]; > >- ret = devm_regulator_bulk_get(&pdev->dev, ARRAY_SIZE(tegra- >>supplies), >+ ret = devm_regulator_bulk_get(&pdev->dev, >+ tegra->soc_data->num_supplies, > tegra->supplies); > if (ret) { > dev_err(&pdev->dev, "Failed to get regulators\n"); @@ -385,5 >+594,5 @@ static struct platform_driver tegra_ahci_driver = { >module_platform_driver(tegra_ahci_driver); > > MODULE_AUTHOR("Mikko Perttunen <mperttunen@xxxxxxxxxx>"); >-MODULE_DESCRIPTION("Tegra124 AHCI SATA driver"); >+MODULE_DESCRIPTION("Tegra AHCI SATA driver"); > MODULE_LICENSE("GPL v2"); >-- >2.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-tegra" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html