1ccfde508SMikko Perttunen /* 2ccfde508SMikko Perttunen * drivers/ata/ahci_tegra.c 3ccfde508SMikko Perttunen * 4ccfde508SMikko Perttunen * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved. 5ccfde508SMikko Perttunen * 6ccfde508SMikko Perttunen * Author: 7ccfde508SMikko Perttunen * Mikko Perttunen <mperttunen@nvidia.com> 8ccfde508SMikko Perttunen * 9ccfde508SMikko Perttunen * This software is licensed under the terms of the GNU General Public 10ccfde508SMikko Perttunen * License version 2, as published by the Free Software Foundation, and 11ccfde508SMikko Perttunen * may be copied, distributed, and modified under those terms. 12ccfde508SMikko Perttunen * 13ccfde508SMikko Perttunen * This program is distributed in the hope that it will be useful, 14ccfde508SMikko Perttunen * but WITHOUT ANY WARRANTY; without even the implied warranty of 15ccfde508SMikko Perttunen * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16ccfde508SMikko Perttunen * GNU General Public License for more details. 17ccfde508SMikko Perttunen * 18ccfde508SMikko Perttunen */ 19ccfde508SMikko Perttunen 20ccfde508SMikko Perttunen #include <linux/ahci_platform.h> 21ccfde508SMikko Perttunen #include <linux/errno.h> 22ccfde508SMikko Perttunen #include <linux/kernel.h> 23ccfde508SMikko Perttunen #include <linux/module.h> 24ccfde508SMikko Perttunen #include <linux/of_device.h> 25ccfde508SMikko Perttunen #include <linux/platform_device.h> 26ccfde508SMikko Perttunen #include <linux/regulator/consumer.h> 27e327f115SMikko Perttunen #include <linux/reset.h> 28e327f115SMikko Perttunen 29e327f115SMikko Perttunen #include <soc/tegra/fuse.h> 300e574077SMikko Perttunen #include <soc/tegra/pmc.h> 31e327f115SMikko Perttunen 32ccfde508SMikko Perttunen #include "ahci.h" 33ccfde508SMikko Perttunen 34018d5ef2SAkinobu Mita #define DRV_NAME "tegra-ahci" 35018d5ef2SAkinobu Mita 36ccfde508SMikko Perttunen #define SATA_CONFIGURATION_0 0x180 3756337b55SPreetham Ramchandra #define SATA_CONFIGURATION_0_EN_FPCI BIT(0) 3856337b55SPreetham Ramchandra #define SATA_CONFIGURATION_0_CLK_OVERRIDE BIT(31) 39ccfde508SMikko Perttunen 40ccfde508SMikko Perttunen #define SCFG_OFFSET 0x1000 41ccfde508SMikko Perttunen 42ccfde508SMikko Perttunen #define T_SATA0_CFG_1 0x04 43ccfde508SMikko Perttunen #define T_SATA0_CFG_1_IO_SPACE BIT(0) 44ccfde508SMikko Perttunen #define T_SATA0_CFG_1_MEMORY_SPACE BIT(1) 45ccfde508SMikko Perttunen #define T_SATA0_CFG_1_BUS_MASTER BIT(2) 46ccfde508SMikko Perttunen #define T_SATA0_CFG_1_SERR BIT(8) 47ccfde508SMikko Perttunen 48ccfde508SMikko Perttunen #define T_SATA0_CFG_9 0x24 4956337b55SPreetham Ramchandra #define T_SATA0_CFG_9_BASE_ADDRESS 0x40020000 50ccfde508SMikko Perttunen 51ccfde508SMikko Perttunen #define SATA_FPCI_BAR5 0x94 5256337b55SPreetham Ramchandra #define SATA_FPCI_BAR5_START_MASK (0xfffffff << 4) 5356337b55SPreetham Ramchandra #define SATA_FPCI_BAR5_START (0x0040020 << 4) 5456337b55SPreetham Ramchandra #define SATA_FPCI_BAR5_ACCESS_TYPE (0x1) 55ccfde508SMikko Perttunen 56ccfde508SMikko Perttunen #define SATA_INTR_MASK 0x188 57ccfde508SMikko Perttunen #define SATA_INTR_MASK_IP_INT_MASK BIT(16) 58ccfde508SMikko Perttunen 5956337b55SPreetham Ramchandra #define T_SATA0_CFG_35 0x94 6056337b55SPreetham Ramchandra #define T_SATA0_CFG_35_IDP_INDEX_MASK (0x7ff << 2) 6156337b55SPreetham Ramchandra #define T_SATA0_CFG_35_IDP_INDEX (0x2a << 2) 6256337b55SPreetham Ramchandra 6356337b55SPreetham Ramchandra #define T_SATA0_AHCI_IDP1 0x98 6456337b55SPreetham Ramchandra #define T_SATA0_AHCI_IDP1_DATA (0x400040) 6556337b55SPreetham Ramchandra 6656337b55SPreetham Ramchandra #define T_SATA0_CFG_PHY_1 0x12c 6756337b55SPreetham Ramchandra #define T_SATA0_CFG_PHY_1_PADS_IDDQ_EN BIT(23) 6856337b55SPreetham Ramchandra #define T_SATA0_CFG_PHY_1_PAD_PLL_IDDQ_EN BIT(22) 6956337b55SPreetham Ramchandra 7056337b55SPreetham Ramchandra #define T_SATA0_NVOOB 0x114 7156337b55SPreetham Ramchandra #define T_SATA0_NVOOB_COMMA_CNT_MASK (0xff << 16) 7256337b55SPreetham Ramchandra #define T_SATA0_NVOOB_COMMA_CNT (0x07 << 16) 7356337b55SPreetham Ramchandra #define T_SATA0_NVOOB_SQUELCH_FILTER_MODE_MASK (0x3 << 24) 7456337b55SPreetham Ramchandra #define T_SATA0_NVOOB_SQUELCH_FILTER_MODE (0x1 << 24) 7556337b55SPreetham Ramchandra #define T_SATA0_NVOOB_SQUELCH_FILTER_LENGTH_MASK (0x3 << 26) 7656337b55SPreetham Ramchandra #define T_SATA0_NVOOB_SQUELCH_FILTER_LENGTH (0x3 << 26) 7756337b55SPreetham Ramchandra 7856337b55SPreetham Ramchandra #define T_SATA_CFG_PHY_0 0x120 7956337b55SPreetham Ramchandra #define T_SATA_CFG_PHY_0_USE_7BIT_ALIGN_DET_FOR_SPD BIT(11) 8056337b55SPreetham Ramchandra #define T_SATA_CFG_PHY_0_MASK_SQUELCH BIT(24) 8156337b55SPreetham Ramchandra 8256337b55SPreetham Ramchandra #define T_SATA0_CFG2NVOOB_2 0x134 8356337b55SPreetham Ramchandra #define T_SATA0_CFG2NVOOB_2_COMWAKE_IDLE_CNT_LOW_MASK (0x1ff << 18) 8456337b55SPreetham Ramchandra #define T_SATA0_CFG2NVOOB_2_COMWAKE_IDLE_CNT_LOW (0xc << 18) 8556337b55SPreetham Ramchandra 86ccfde508SMikko Perttunen #define T_SATA0_AHCI_HBA_CAP_BKDR 0x300 8756337b55SPreetham Ramchandra #define T_SATA0_AHCI_HBA_CAP_BKDR_PARTIAL_ST_CAP BIT(13) 8856337b55SPreetham Ramchandra #define T_SATA0_AHCI_HBA_CAP_BKDR_SLUMBER_ST_CAP BIT(14) 8956337b55SPreetham Ramchandra #define T_SATA0_AHCI_HBA_CAP_BKDR_SALP BIT(26) 9056337b55SPreetham Ramchandra #define T_SATA0_AHCI_HBA_CAP_BKDR_SUPP_PM BIT(17) 9156337b55SPreetham Ramchandra #define T_SATA0_AHCI_HBA_CAP_BKDR_SNCQ BIT(30) 92ccfde508SMikko Perttunen 93ccfde508SMikko Perttunen #define T_SATA0_BKDOOR_CC 0x4a4 9456337b55SPreetham Ramchandra #define T_SATA0_BKDOOR_CC_CLASS_CODE_MASK (0xffff << 16) 9556337b55SPreetham Ramchandra #define T_SATA0_BKDOOR_CC_CLASS_CODE (0x0106 << 16) 9656337b55SPreetham Ramchandra #define T_SATA0_BKDOOR_CC_PROG_IF_MASK (0xff << 8) 9756337b55SPreetham Ramchandra #define T_SATA0_BKDOOR_CC_PROG_IF (0x01 << 8) 98ccfde508SMikko Perttunen 99ccfde508SMikko Perttunen #define T_SATA0_CFG_SATA 0x54c 100ccfde508SMikko Perttunen #define T_SATA0_CFG_SATA_BACKDOOR_PROG_IF_EN BIT(12) 101ccfde508SMikko Perttunen 102ccfde508SMikko Perttunen #define T_SATA0_CFG_MISC 0x550 103ccfde508SMikko Perttunen 104ccfde508SMikko Perttunen #define T_SATA0_INDEX 0x680 105ccfde508SMikko Perttunen 106ccfde508SMikko Perttunen #define T_SATA0_CHX_PHY_CTRL1_GEN1 0x690 107ccfde508SMikko Perttunen #define T_SATA0_CHX_PHY_CTRL1_GEN1_TX_AMP_MASK 0xff 108ccfde508SMikko Perttunen #define T_SATA0_CHX_PHY_CTRL1_GEN1_TX_AMP_SHIFT 0 109ccfde508SMikko Perttunen #define T_SATA0_CHX_PHY_CTRL1_GEN1_TX_PEAK_MASK (0xff << 8) 110ccfde508SMikko Perttunen #define T_SATA0_CHX_PHY_CTRL1_GEN1_TX_PEAK_SHIFT 8 111ccfde508SMikko Perttunen 112ccfde508SMikko Perttunen #define T_SATA0_CHX_PHY_CTRL1_GEN2 0x694 113ccfde508SMikko Perttunen #define T_SATA0_CHX_PHY_CTRL1_GEN2_TX_AMP_MASK 0xff 114ccfde508SMikko Perttunen #define T_SATA0_CHX_PHY_CTRL1_GEN2_TX_AMP_SHIFT 0 115ccfde508SMikko Perttunen #define T_SATA0_CHX_PHY_CTRL1_GEN2_TX_PEAK_MASK (0xff << 12) 116ccfde508SMikko Perttunen #define T_SATA0_CHX_PHY_CTRL1_GEN2_TX_PEAK_SHIFT 12 117ccfde508SMikko Perttunen 118ccfde508SMikko Perttunen #define T_SATA0_CHX_PHY_CTRL2 0x69c 119ccfde508SMikko Perttunen #define T_SATA0_CHX_PHY_CTRL2_CDR_CNTL_GEN1 0x23 120ccfde508SMikko Perttunen 121ccfde508SMikko Perttunen #define T_SATA0_CHX_PHY_CTRL11 0x6d0 122ccfde508SMikko Perttunen #define T_SATA0_CHX_PHY_CTRL11_GEN2_RX_EQ (0x2800 << 16) 123ccfde508SMikko Perttunen 12456337b55SPreetham Ramchandra #define T_SATA0_CHX_PHY_CTRL17_0 0x6e8 12556337b55SPreetham Ramchandra #define T_SATA0_CHX_PHY_CTRL17_0_RX_EQ_CTRL_L_GEN1 0x55010000 12656337b55SPreetham Ramchandra #define T_SATA0_CHX_PHY_CTRL18_0 0x6ec 12756337b55SPreetham Ramchandra #define T_SATA0_CHX_PHY_CTRL18_0_RX_EQ_CTRL_L_GEN2 0x55010000 12856337b55SPreetham Ramchandra #define T_SATA0_CHX_PHY_CTRL20_0 0x6f4 12956337b55SPreetham Ramchandra #define T_SATA0_CHX_PHY_CTRL20_0_RX_EQ_CTRL_H_GEN1 0x1 13056337b55SPreetham Ramchandra #define T_SATA0_CHX_PHY_CTRL21_0 0x6f8 13156337b55SPreetham Ramchandra #define T_SATA0_CHX_PHY_CTRL21_0_RX_EQ_CTRL_H_GEN2 0x1 13256337b55SPreetham Ramchandra 13356337b55SPreetham Ramchandra /* AUX Registers */ 13456337b55SPreetham Ramchandra #define SATA_AUX_MISC_CNTL_1_0 0x8 13556337b55SPreetham Ramchandra #define SATA_AUX_MISC_CNTL_1_0_DEVSLP_OVERRIDE BIT(17) 13656337b55SPreetham Ramchandra #define SATA_AUX_MISC_CNTL_1_0_SDS_SUPPORT BIT(13) 13756337b55SPreetham Ramchandra #define SATA_AUX_MISC_CNTL_1_0_DESO_SUPPORT BIT(15) 13856337b55SPreetham Ramchandra 13956337b55SPreetham Ramchandra #define SATA_AUX_RX_STAT_INT_0 0xc 14056337b55SPreetham Ramchandra #define SATA_AUX_RX_STAT_INT_0_SATA_DEVSLP BIT(7) 14156337b55SPreetham Ramchandra 14256337b55SPreetham Ramchandra #define SATA_AUX_SPARE_CFG0_0 0x18 14356337b55SPreetham Ramchandra #define SATA_AUX_SPARE_CFG0_0_MDAT_TIMER_AFTER_PG_VALID BIT(14) 14456337b55SPreetham Ramchandra 145ccfde508SMikko Perttunen #define FUSE_SATA_CALIB 0x124 146ccfde508SMikko Perttunen #define FUSE_SATA_CALIB_MASK 0x3 147ccfde508SMikko Perttunen 148ccfde508SMikko Perttunen struct sata_pad_calibration { 149ccfde508SMikko Perttunen u8 gen1_tx_amp; 150ccfde508SMikko Perttunen u8 gen1_tx_peak; 151ccfde508SMikko Perttunen u8 gen2_tx_amp; 152ccfde508SMikko Perttunen u8 gen2_tx_peak; 153ccfde508SMikko Perttunen }; 154ccfde508SMikko Perttunen 155ccfde508SMikko Perttunen static const struct sata_pad_calibration tegra124_pad_calibration[] = { 156ccfde508SMikko Perttunen {0x18, 0x04, 0x18, 0x0a}, 157ccfde508SMikko Perttunen {0x0e, 0x04, 0x14, 0x0a}, 158ccfde508SMikko Perttunen {0x0e, 0x07, 0x1a, 0x0e}, 159ccfde508SMikko Perttunen {0x14, 0x0e, 0x1a, 0x0e}, 160ccfde508SMikko Perttunen }; 161ccfde508SMikko Perttunen 16256337b55SPreetham Ramchandra struct tegra_ahci_ops { 16356337b55SPreetham Ramchandra int (*init)(struct ahci_host_priv *hpriv); 16456337b55SPreetham Ramchandra }; 16556337b55SPreetham Ramchandra 16656337b55SPreetham Ramchandra struct tegra_ahci_soc { 16756337b55SPreetham Ramchandra const struct tegra_ahci_ops *ops; 16856337b55SPreetham Ramchandra }; 16956337b55SPreetham Ramchandra 170ccfde508SMikko Perttunen struct tegra_ahci_priv { 171ccfde508SMikko Perttunen struct platform_device *pdev; 172ccfde508SMikko Perttunen void __iomem *sata_regs; 173ccfde508SMikko Perttunen struct reset_control *sata_rst; 174ccfde508SMikko Perttunen struct reset_control *sata_oob_rst; 175ccfde508SMikko Perttunen struct reset_control *sata_cold_rst; 176ccfde508SMikko Perttunen /* Needs special handling, cannot use ahci_platform */ 177ccfde508SMikko Perttunen struct clk *sata_clk; 178ccfde508SMikko Perttunen struct regulator_bulk_data supplies[5]; 17956337b55SPreetham Ramchandra const struct tegra_ahci_soc *soc; 180ccfde508SMikko Perttunen }; 181ccfde508SMikko Perttunen 18256337b55SPreetham Ramchandra static int tegra124_ahci_init(struct ahci_host_priv *hpriv) 18356337b55SPreetham Ramchandra { 18456337b55SPreetham Ramchandra struct tegra_ahci_priv *tegra = hpriv->plat_data; 18556337b55SPreetham Ramchandra struct sata_pad_calibration calib; 18656337b55SPreetham Ramchandra int ret; 18756337b55SPreetham Ramchandra u32 val; 18856337b55SPreetham Ramchandra 18956337b55SPreetham Ramchandra /* Pad calibration */ 19056337b55SPreetham Ramchandra ret = tegra_fuse_readl(FUSE_SATA_CALIB, &val); 19156337b55SPreetham Ramchandra if (ret) 19256337b55SPreetham Ramchandra return ret; 19356337b55SPreetham Ramchandra 19456337b55SPreetham Ramchandra calib = tegra124_pad_calibration[val & FUSE_SATA_CALIB_MASK]; 19556337b55SPreetham Ramchandra 19656337b55SPreetham Ramchandra writel(BIT(0), tegra->sata_regs + SCFG_OFFSET + T_SATA0_INDEX); 19756337b55SPreetham Ramchandra 19856337b55SPreetham Ramchandra val = readl(tegra->sata_regs + 19956337b55SPreetham Ramchandra SCFG_OFFSET + T_SATA0_CHX_PHY_CTRL1_GEN1); 20056337b55SPreetham Ramchandra val &= ~T_SATA0_CHX_PHY_CTRL1_GEN1_TX_AMP_MASK; 20156337b55SPreetham Ramchandra val &= ~T_SATA0_CHX_PHY_CTRL1_GEN1_TX_PEAK_MASK; 20256337b55SPreetham Ramchandra val |= calib.gen1_tx_amp << T_SATA0_CHX_PHY_CTRL1_GEN1_TX_AMP_SHIFT; 20356337b55SPreetham Ramchandra val |= calib.gen1_tx_peak << T_SATA0_CHX_PHY_CTRL1_GEN1_TX_PEAK_SHIFT; 20456337b55SPreetham Ramchandra writel(val, tegra->sata_regs + SCFG_OFFSET + 20556337b55SPreetham Ramchandra T_SATA0_CHX_PHY_CTRL1_GEN1); 20656337b55SPreetham Ramchandra 20756337b55SPreetham Ramchandra val = readl(tegra->sata_regs + 20856337b55SPreetham Ramchandra SCFG_OFFSET + T_SATA0_CHX_PHY_CTRL1_GEN2); 20956337b55SPreetham Ramchandra val &= ~T_SATA0_CHX_PHY_CTRL1_GEN2_TX_AMP_MASK; 21056337b55SPreetham Ramchandra val &= ~T_SATA0_CHX_PHY_CTRL1_GEN2_TX_PEAK_MASK; 21156337b55SPreetham Ramchandra val |= calib.gen2_tx_amp << T_SATA0_CHX_PHY_CTRL1_GEN1_TX_AMP_SHIFT; 21256337b55SPreetham Ramchandra val |= calib.gen2_tx_peak << T_SATA0_CHX_PHY_CTRL1_GEN1_TX_PEAK_SHIFT; 21356337b55SPreetham Ramchandra writel(val, tegra->sata_regs + SCFG_OFFSET + 21456337b55SPreetham Ramchandra T_SATA0_CHX_PHY_CTRL1_GEN2); 21556337b55SPreetham Ramchandra 21656337b55SPreetham Ramchandra writel(T_SATA0_CHX_PHY_CTRL11_GEN2_RX_EQ, 21756337b55SPreetham Ramchandra tegra->sata_regs + SCFG_OFFSET + T_SATA0_CHX_PHY_CTRL11); 21856337b55SPreetham Ramchandra writel(T_SATA0_CHX_PHY_CTRL2_CDR_CNTL_GEN1, 21956337b55SPreetham Ramchandra tegra->sata_regs + SCFG_OFFSET + T_SATA0_CHX_PHY_CTRL2); 22056337b55SPreetham Ramchandra 22156337b55SPreetham Ramchandra writel(0, tegra->sata_regs + SCFG_OFFSET + T_SATA0_INDEX); 22256337b55SPreetham Ramchandra 22356337b55SPreetham Ramchandra return 0; 22456337b55SPreetham Ramchandra } 22556337b55SPreetham Ramchandra 226ccfde508SMikko Perttunen static int tegra_ahci_power_on(struct ahci_host_priv *hpriv) 227ccfde508SMikko Perttunen { 228ccfde508SMikko Perttunen struct tegra_ahci_priv *tegra = hpriv->plat_data; 229ccfde508SMikko Perttunen int ret; 230ccfde508SMikko Perttunen 231ccfde508SMikko Perttunen ret = regulator_bulk_enable(ARRAY_SIZE(tegra->supplies), 232ccfde508SMikko Perttunen tegra->supplies); 233ccfde508SMikko Perttunen if (ret) 234ccfde508SMikko Perttunen return ret; 235ccfde508SMikko Perttunen 236ccfde508SMikko Perttunen ret = tegra_powergate_sequence_power_up(TEGRA_POWERGATE_SATA, 237ccfde508SMikko Perttunen tegra->sata_clk, 238ccfde508SMikko Perttunen tegra->sata_rst); 239ccfde508SMikko Perttunen if (ret) 240ccfde508SMikko Perttunen goto disable_regulators; 241ccfde508SMikko Perttunen 242ccfde508SMikko Perttunen reset_control_assert(tegra->sata_oob_rst); 243ccfde508SMikko Perttunen reset_control_assert(tegra->sata_cold_rst); 244ccfde508SMikko Perttunen 245ccfde508SMikko Perttunen ret = ahci_platform_enable_resources(hpriv); 246ccfde508SMikko Perttunen if (ret) 247ccfde508SMikko Perttunen goto disable_power; 248ccfde508SMikko Perttunen 249ccfde508SMikko Perttunen reset_control_deassert(tegra->sata_cold_rst); 250ccfde508SMikko Perttunen reset_control_deassert(tegra->sata_oob_rst); 251ccfde508SMikko Perttunen 252ccfde508SMikko Perttunen return 0; 253ccfde508SMikko Perttunen 254ccfde508SMikko Perttunen disable_power: 255ccfde508SMikko Perttunen clk_disable_unprepare(tegra->sata_clk); 256ccfde508SMikko Perttunen 257ccfde508SMikko Perttunen tegra_powergate_power_off(TEGRA_POWERGATE_SATA); 258ccfde508SMikko Perttunen 259ccfde508SMikko Perttunen disable_regulators: 260ccfde508SMikko Perttunen regulator_bulk_disable(ARRAY_SIZE(tegra->supplies), tegra->supplies); 261ccfde508SMikko Perttunen 262ccfde508SMikko Perttunen return ret; 263ccfde508SMikko Perttunen } 264ccfde508SMikko Perttunen 265ccfde508SMikko Perttunen static void tegra_ahci_power_off(struct ahci_host_priv *hpriv) 266ccfde508SMikko Perttunen { 267ccfde508SMikko Perttunen struct tegra_ahci_priv *tegra = hpriv->plat_data; 268ccfde508SMikko Perttunen 269ccfde508SMikko Perttunen ahci_platform_disable_resources(hpriv); 270ccfde508SMikko Perttunen 271ccfde508SMikko Perttunen reset_control_assert(tegra->sata_rst); 272ccfde508SMikko Perttunen reset_control_assert(tegra->sata_oob_rst); 273ccfde508SMikko Perttunen reset_control_assert(tegra->sata_cold_rst); 274ccfde508SMikko Perttunen 275ccfde508SMikko Perttunen clk_disable_unprepare(tegra->sata_clk); 276ccfde508SMikko Perttunen tegra_powergate_power_off(TEGRA_POWERGATE_SATA); 277ccfde508SMikko Perttunen 278ccfde508SMikko Perttunen regulator_bulk_disable(ARRAY_SIZE(tegra->supplies), tegra->supplies); 279ccfde508SMikko Perttunen } 280ccfde508SMikko Perttunen 281ccfde508SMikko Perttunen static int tegra_ahci_controller_init(struct ahci_host_priv *hpriv) 282ccfde508SMikko Perttunen { 283ccfde508SMikko Perttunen struct tegra_ahci_priv *tegra = hpriv->plat_data; 284ccfde508SMikko Perttunen int ret; 28556337b55SPreetham Ramchandra u32 val; 286ccfde508SMikko Perttunen 287ccfde508SMikko Perttunen ret = tegra_ahci_power_on(hpriv); 288ccfde508SMikko Perttunen if (ret) { 289ccfde508SMikko Perttunen dev_err(&tegra->pdev->dev, 290ccfde508SMikko Perttunen "failed to power on AHCI controller: %d\n", ret); 291ccfde508SMikko Perttunen return ret; 292ccfde508SMikko Perttunen } 293ccfde508SMikko Perttunen 29456337b55SPreetham Ramchandra /* 29556337b55SPreetham Ramchandra * Program the following SATA IPFS registers to allow SW accesses to 29656337b55SPreetham Ramchandra * SATA's MMIO register range. 29756337b55SPreetham Ramchandra */ 29856337b55SPreetham Ramchandra val = readl(tegra->sata_regs + SATA_FPCI_BAR5); 29956337b55SPreetham Ramchandra val &= ~(SATA_FPCI_BAR5_START_MASK | SATA_FPCI_BAR5_ACCESS_TYPE); 30056337b55SPreetham Ramchandra val |= SATA_FPCI_BAR5_START | SATA_FPCI_BAR5_ACCESS_TYPE; 30156337b55SPreetham Ramchandra writel(val, tegra->sata_regs + SATA_FPCI_BAR5); 30256337b55SPreetham Ramchandra 30356337b55SPreetham Ramchandra /* Program the following SATA IPFS register to enable the SATA */ 304ccfde508SMikko Perttunen val = readl(tegra->sata_regs + SATA_CONFIGURATION_0); 30556337b55SPreetham Ramchandra val |= SATA_CONFIGURATION_0_EN_FPCI; 306ccfde508SMikko Perttunen writel(val, tegra->sata_regs + SATA_CONFIGURATION_0); 307ccfde508SMikko Perttunen 30856337b55SPreetham Ramchandra /* Electrical settings for better link stability */ 30956337b55SPreetham Ramchandra val = T_SATA0_CHX_PHY_CTRL17_0_RX_EQ_CTRL_L_GEN1; 31056337b55SPreetham Ramchandra writel(val, tegra->sata_regs + SCFG_OFFSET + T_SATA0_CHX_PHY_CTRL17_0); 31156337b55SPreetham Ramchandra val = T_SATA0_CHX_PHY_CTRL18_0_RX_EQ_CTRL_L_GEN2; 31256337b55SPreetham Ramchandra writel(val, tegra->sata_regs + SCFG_OFFSET + T_SATA0_CHX_PHY_CTRL18_0); 31356337b55SPreetham Ramchandra val = T_SATA0_CHX_PHY_CTRL20_0_RX_EQ_CTRL_H_GEN1; 31456337b55SPreetham Ramchandra writel(val, tegra->sata_regs + SCFG_OFFSET + T_SATA0_CHX_PHY_CTRL20_0); 31556337b55SPreetham Ramchandra val = T_SATA0_CHX_PHY_CTRL21_0_RX_EQ_CTRL_H_GEN2; 31656337b55SPreetham Ramchandra writel(val, tegra->sata_regs + SCFG_OFFSET + T_SATA0_CHX_PHY_CTRL21_0); 317ccfde508SMikko Perttunen 31856337b55SPreetham Ramchandra /* For SQUELCH Filter & Gen3 drive getting detected as Gen1 drive */ 319ccfde508SMikko Perttunen 32056337b55SPreetham Ramchandra val = readl(tegra->sata_regs + SCFG_OFFSET + T_SATA_CFG_PHY_0); 32156337b55SPreetham Ramchandra val |= T_SATA_CFG_PHY_0_MASK_SQUELCH; 32256337b55SPreetham Ramchandra val &= ~T_SATA_CFG_PHY_0_USE_7BIT_ALIGN_DET_FOR_SPD; 32356337b55SPreetham Ramchandra writel(val, tegra->sata_regs + SCFG_OFFSET + T_SATA_CFG_PHY_0); 324ccfde508SMikko Perttunen 32556337b55SPreetham Ramchandra val = readl(tegra->sata_regs + SCFG_OFFSET + T_SATA0_NVOOB); 32656337b55SPreetham Ramchandra val &= ~(T_SATA0_NVOOB_COMMA_CNT_MASK | 32756337b55SPreetham Ramchandra T_SATA0_NVOOB_SQUELCH_FILTER_LENGTH_MASK | 32856337b55SPreetham Ramchandra T_SATA0_NVOOB_SQUELCH_FILTER_MODE_MASK); 32956337b55SPreetham Ramchandra val |= (T_SATA0_NVOOB_COMMA_CNT | 33056337b55SPreetham Ramchandra T_SATA0_NVOOB_SQUELCH_FILTER_LENGTH | 33156337b55SPreetham Ramchandra T_SATA0_NVOOB_SQUELCH_FILTER_MODE); 33256337b55SPreetham Ramchandra writel(val, tegra->sata_regs + SCFG_OFFSET + T_SATA0_NVOOB); 333ccfde508SMikko Perttunen 33456337b55SPreetham Ramchandra /* 33556337b55SPreetham Ramchandra * Change CFG2NVOOB_2_COMWAKE_IDLE_CNT_LOW from 83.3 ns to 58.8ns 33656337b55SPreetham Ramchandra */ 33756337b55SPreetham Ramchandra val = readl(tegra->sata_regs + SCFG_OFFSET + T_SATA0_CFG2NVOOB_2); 33856337b55SPreetham Ramchandra val &= ~T_SATA0_CFG2NVOOB_2_COMWAKE_IDLE_CNT_LOW_MASK; 33956337b55SPreetham Ramchandra val |= T_SATA0_CFG2NVOOB_2_COMWAKE_IDLE_CNT_LOW; 34056337b55SPreetham Ramchandra writel(val, tegra->sata_regs + SCFG_OFFSET + T_SATA0_CFG2NVOOB_2); 341ccfde508SMikko Perttunen 34256337b55SPreetham Ramchandra if (tegra->soc->ops && tegra->soc->ops->init) 34356337b55SPreetham Ramchandra tegra->soc->ops->init(hpriv); 344ccfde508SMikko Perttunen 34556337b55SPreetham Ramchandra /* 34656337b55SPreetham Ramchandra * Program the following SATA configuration registers to 34756337b55SPreetham Ramchandra * initialize SATA 34856337b55SPreetham Ramchandra */ 34956337b55SPreetham Ramchandra val = readl(tegra->sata_regs + SCFG_OFFSET + T_SATA0_CFG_1); 35056337b55SPreetham Ramchandra val |= (T_SATA0_CFG_1_IO_SPACE | T_SATA0_CFG_1_MEMORY_SPACE | 35156337b55SPreetham Ramchandra T_SATA0_CFG_1_BUS_MASTER | T_SATA0_CFG_1_SERR); 35256337b55SPreetham Ramchandra writel(val, tegra->sata_regs + SCFG_OFFSET + T_SATA0_CFG_1); 35356337b55SPreetham Ramchandra val = T_SATA0_CFG_9_BASE_ADDRESS; 35456337b55SPreetham Ramchandra writel(val, tegra->sata_regs + SCFG_OFFSET + T_SATA0_CFG_9); 355ccfde508SMikko Perttunen 35656337b55SPreetham Ramchandra /* Program Class Code and Programming interface for SATA */ 357ccfde508SMikko Perttunen val = readl(tegra->sata_regs + SCFG_OFFSET + T_SATA0_CFG_SATA); 358ccfde508SMikko Perttunen val |= T_SATA0_CFG_SATA_BACKDOOR_PROG_IF_EN; 359ccfde508SMikko Perttunen writel(val, tegra->sata_regs + SCFG_OFFSET + T_SATA0_CFG_SATA); 360ccfde508SMikko Perttunen 36156337b55SPreetham Ramchandra val = readl(tegra->sata_regs + SCFG_OFFSET + T_SATA0_BKDOOR_CC); 36256337b55SPreetham Ramchandra val &= 36356337b55SPreetham Ramchandra ~(T_SATA0_BKDOOR_CC_CLASS_CODE_MASK | 36456337b55SPreetham Ramchandra T_SATA0_BKDOOR_CC_PROG_IF_MASK); 36556337b55SPreetham Ramchandra val |= T_SATA0_BKDOOR_CC_CLASS_CODE | T_SATA0_BKDOOR_CC_PROG_IF; 36656337b55SPreetham Ramchandra writel(val, tegra->sata_regs + SCFG_OFFSET + T_SATA0_BKDOOR_CC); 367ccfde508SMikko Perttunen 368ccfde508SMikko Perttunen val = readl(tegra->sata_regs + SCFG_OFFSET + T_SATA0_CFG_SATA); 369ccfde508SMikko Perttunen val &= ~T_SATA0_CFG_SATA_BACKDOOR_PROG_IF_EN; 370ccfde508SMikko Perttunen writel(val, tegra->sata_regs + SCFG_OFFSET + T_SATA0_CFG_SATA); 371ccfde508SMikko Perttunen 37256337b55SPreetham Ramchandra /* Enabling LPM capabilities through Backdoor Programming */ 37356337b55SPreetham Ramchandra val = readl(tegra->sata_regs + SCFG_OFFSET + T_SATA0_AHCI_HBA_CAP_BKDR); 37456337b55SPreetham Ramchandra val |= (T_SATA0_AHCI_HBA_CAP_BKDR_PARTIAL_ST_CAP | 37556337b55SPreetham Ramchandra T_SATA0_AHCI_HBA_CAP_BKDR_SLUMBER_ST_CAP | 37656337b55SPreetham Ramchandra T_SATA0_AHCI_HBA_CAP_BKDR_SALP | 37756337b55SPreetham Ramchandra T_SATA0_AHCI_HBA_CAP_BKDR_SUPP_PM); 37856337b55SPreetham Ramchandra writel(val, tegra->sata_regs + SCFG_OFFSET + T_SATA0_AHCI_HBA_CAP_BKDR); 379ccfde508SMikko Perttunen 38056337b55SPreetham Ramchandra /* SATA Second Level Clock Gating configuration 38156337b55SPreetham Ramchandra * Enabling Gating of Tx/Rx clocks and driving Pad IDDQ and Lane 38256337b55SPreetham Ramchandra * IDDQ Signals 38356337b55SPreetham Ramchandra */ 38456337b55SPreetham Ramchandra val = readl(tegra->sata_regs + SCFG_OFFSET + T_SATA0_CFG_35); 38556337b55SPreetham Ramchandra val &= ~T_SATA0_CFG_35_IDP_INDEX_MASK; 38656337b55SPreetham Ramchandra val |= T_SATA0_CFG_35_IDP_INDEX; 38756337b55SPreetham Ramchandra writel(val, tegra->sata_regs + SCFG_OFFSET + T_SATA0_CFG_35); 388ccfde508SMikko Perttunen 38956337b55SPreetham Ramchandra val = T_SATA0_AHCI_IDP1_DATA; 39056337b55SPreetham Ramchandra writel(val, tegra->sata_regs + SCFG_OFFSET + T_SATA0_AHCI_IDP1); 391ccfde508SMikko Perttunen 39256337b55SPreetham Ramchandra val = readl(tegra->sata_regs + SCFG_OFFSET + T_SATA0_CFG_PHY_1); 39356337b55SPreetham Ramchandra val |= (T_SATA0_CFG_PHY_1_PADS_IDDQ_EN | 39456337b55SPreetham Ramchandra T_SATA0_CFG_PHY_1_PAD_PLL_IDDQ_EN); 39556337b55SPreetham Ramchandra writel(val, tegra->sata_regs + SCFG_OFFSET + T_SATA0_CFG_PHY_1); 396ccfde508SMikko Perttunen 39756337b55SPreetham Ramchandra /* Enabling IPFS Clock Gating */ 39856337b55SPreetham Ramchandra val = readl(tegra->sata_regs + SATA_CONFIGURATION_0); 39956337b55SPreetham Ramchandra val &= ~SATA_CONFIGURATION_0_CLK_OVERRIDE; 40056337b55SPreetham Ramchandra writel(val, tegra->sata_regs + SATA_CONFIGURATION_0); 40156337b55SPreetham Ramchandra 402ccfde508SMikko Perttunen 403ccfde508SMikko Perttunen /* Unmask SATA interrupts */ 404ccfde508SMikko Perttunen 405ccfde508SMikko Perttunen val = readl(tegra->sata_regs + SATA_INTR_MASK); 406ccfde508SMikko Perttunen val |= SATA_INTR_MASK_IP_INT_MASK; 407ccfde508SMikko Perttunen writel(val, tegra->sata_regs + SATA_INTR_MASK); 408ccfde508SMikko Perttunen 409ccfde508SMikko Perttunen return 0; 410ccfde508SMikko Perttunen } 411ccfde508SMikko Perttunen 412ccfde508SMikko Perttunen static void tegra_ahci_controller_deinit(struct ahci_host_priv *hpriv) 413ccfde508SMikko Perttunen { 414ccfde508SMikko Perttunen tegra_ahci_power_off(hpriv); 415ccfde508SMikko Perttunen } 416ccfde508SMikko Perttunen 417ccfde508SMikko Perttunen static void tegra_ahci_host_stop(struct ata_host *host) 418ccfde508SMikko Perttunen { 419ccfde508SMikko Perttunen struct ahci_host_priv *hpriv = host->private_data; 420ccfde508SMikko Perttunen 421ccfde508SMikko Perttunen tegra_ahci_controller_deinit(hpriv); 422ccfde508SMikko Perttunen } 423ccfde508SMikko Perttunen 424ccfde508SMikko Perttunen static struct ata_port_operations ahci_tegra_port_ops = { 425ccfde508SMikko Perttunen .inherits = &ahci_ops, 426ccfde508SMikko Perttunen .host_stop = tegra_ahci_host_stop, 427ccfde508SMikko Perttunen }; 428ccfde508SMikko Perttunen 429ccfde508SMikko Perttunen static const struct ata_port_info ahci_tegra_port_info = { 430ccfde508SMikko Perttunen .flags = AHCI_FLAG_COMMON, 431ccfde508SMikko Perttunen .pio_mask = ATA_PIO4, 432ccfde508SMikko Perttunen .udma_mask = ATA_UDMA6, 433ccfde508SMikko Perttunen .port_ops = &ahci_tegra_port_ops, 434ccfde508SMikko Perttunen }; 435ccfde508SMikko Perttunen 43656337b55SPreetham Ramchandra static const struct tegra_ahci_ops tegra124_ahci_ops = { 43756337b55SPreetham Ramchandra .init = tegra124_ahci_init, 43856337b55SPreetham Ramchandra }; 43956337b55SPreetham Ramchandra 44056337b55SPreetham Ramchandra static const struct tegra_ahci_soc tegra124_ahci_soc = { 44156337b55SPreetham Ramchandra .ops = &tegra124_ahci_ops, 44256337b55SPreetham Ramchandra }; 44356337b55SPreetham Ramchandra 444ccfde508SMikko Perttunen static const struct of_device_id tegra_ahci_of_match[] = { 44556337b55SPreetham Ramchandra { 44656337b55SPreetham Ramchandra .compatible = "nvidia,tegra124-ahci", 44756337b55SPreetham Ramchandra .data = &tegra124_ahci_soc 44856337b55SPreetham Ramchandra }, 449ccfde508SMikko Perttunen {} 450ccfde508SMikko Perttunen }; 451ccfde508SMikko Perttunen MODULE_DEVICE_TABLE(of, tegra_ahci_of_match); 452ccfde508SMikko Perttunen 453018d5ef2SAkinobu Mita static struct scsi_host_template ahci_platform_sht = { 454018d5ef2SAkinobu Mita AHCI_SHT(DRV_NAME), 455018d5ef2SAkinobu Mita }; 456018d5ef2SAkinobu Mita 457ccfde508SMikko Perttunen static int tegra_ahci_probe(struct platform_device *pdev) 458ccfde508SMikko Perttunen { 459ccfde508SMikko Perttunen struct ahci_host_priv *hpriv; 460ccfde508SMikko Perttunen struct tegra_ahci_priv *tegra; 461ccfde508SMikko Perttunen struct resource *res; 462ccfde508SMikko Perttunen int ret; 463ccfde508SMikko Perttunen 464ccfde508SMikko Perttunen hpriv = ahci_platform_get_resources(pdev); 465ccfde508SMikko Perttunen if (IS_ERR(hpriv)) 466ccfde508SMikko Perttunen return PTR_ERR(hpriv); 467ccfde508SMikko Perttunen 468ccfde508SMikko Perttunen tegra = devm_kzalloc(&pdev->dev, sizeof(*tegra), GFP_KERNEL); 469ccfde508SMikko Perttunen if (!tegra) 470ccfde508SMikko Perttunen return -ENOMEM; 471ccfde508SMikko Perttunen 472ccfde508SMikko Perttunen hpriv->plat_data = tegra; 473ccfde508SMikko Perttunen 474ccfde508SMikko Perttunen tegra->pdev = pdev; 47556337b55SPreetham Ramchandra tegra->soc = of_device_get_match_data(&pdev->dev); 476ccfde508SMikko Perttunen 477ccfde508SMikko Perttunen res = platform_get_resource(pdev, IORESOURCE_MEM, 1); 478ccfde508SMikko Perttunen tegra->sata_regs = devm_ioremap_resource(&pdev->dev, res); 479ccfde508SMikko Perttunen if (IS_ERR(tegra->sata_regs)) 480ccfde508SMikko Perttunen return PTR_ERR(tegra->sata_regs); 481ccfde508SMikko Perttunen 482ccfde508SMikko Perttunen tegra->sata_rst = devm_reset_control_get(&pdev->dev, "sata"); 483ccfde508SMikko Perttunen if (IS_ERR(tegra->sata_rst)) { 484ccfde508SMikko Perttunen dev_err(&pdev->dev, "Failed to get sata reset\n"); 485ccfde508SMikko Perttunen return PTR_ERR(tegra->sata_rst); 486ccfde508SMikko Perttunen } 487ccfde508SMikko Perttunen 488ccfde508SMikko Perttunen tegra->sata_oob_rst = devm_reset_control_get(&pdev->dev, "sata-oob"); 489ccfde508SMikko Perttunen if (IS_ERR(tegra->sata_oob_rst)) { 490ccfde508SMikko Perttunen dev_err(&pdev->dev, "Failed to get sata-oob reset\n"); 491ccfde508SMikko Perttunen return PTR_ERR(tegra->sata_oob_rst); 492ccfde508SMikko Perttunen } 493ccfde508SMikko Perttunen 494ccfde508SMikko Perttunen tegra->sata_cold_rst = devm_reset_control_get(&pdev->dev, "sata-cold"); 495ccfde508SMikko Perttunen if (IS_ERR(tegra->sata_cold_rst)) { 496ccfde508SMikko Perttunen dev_err(&pdev->dev, "Failed to get sata-cold reset\n"); 497ccfde508SMikko Perttunen return PTR_ERR(tegra->sata_cold_rst); 498ccfde508SMikko Perttunen } 499ccfde508SMikko Perttunen 500ccfde508SMikko Perttunen tegra->sata_clk = devm_clk_get(&pdev->dev, "sata"); 501ccfde508SMikko Perttunen if (IS_ERR(tegra->sata_clk)) { 502ccfde508SMikko Perttunen dev_err(&pdev->dev, "Failed to get sata clock\n"); 503ccfde508SMikko Perttunen return PTR_ERR(tegra->sata_clk); 504ccfde508SMikko Perttunen } 505ccfde508SMikko Perttunen 506ccfde508SMikko Perttunen tegra->supplies[0].supply = "avdd"; 507ccfde508SMikko Perttunen tegra->supplies[1].supply = "hvdd"; 508ccfde508SMikko Perttunen tegra->supplies[2].supply = "vddio"; 509ccfde508SMikko Perttunen tegra->supplies[3].supply = "target-5v"; 510ccfde508SMikko Perttunen tegra->supplies[4].supply = "target-12v"; 511ccfde508SMikko Perttunen 512ccfde508SMikko Perttunen ret = devm_regulator_bulk_get(&pdev->dev, ARRAY_SIZE(tegra->supplies), 513ccfde508SMikko Perttunen tegra->supplies); 514ccfde508SMikko Perttunen if (ret) { 515ccfde508SMikko Perttunen dev_err(&pdev->dev, "Failed to get regulators\n"); 516ccfde508SMikko Perttunen return ret; 517ccfde508SMikko Perttunen } 518ccfde508SMikko Perttunen 519ccfde508SMikko Perttunen ret = tegra_ahci_controller_init(hpriv); 520ccfde508SMikko Perttunen if (ret) 521ccfde508SMikko Perttunen return ret; 522ccfde508SMikko Perttunen 523018d5ef2SAkinobu Mita ret = ahci_platform_init_host(pdev, hpriv, &ahci_tegra_port_info, 524018d5ef2SAkinobu Mita &ahci_platform_sht); 525ccfde508SMikko Perttunen if (ret) 526ccfde508SMikko Perttunen goto deinit_controller; 527ccfde508SMikko Perttunen 528ccfde508SMikko Perttunen return 0; 529ccfde508SMikko Perttunen 530ccfde508SMikko Perttunen deinit_controller: 531ccfde508SMikko Perttunen tegra_ahci_controller_deinit(hpriv); 532ccfde508SMikko Perttunen 533ccfde508SMikko Perttunen return ret; 534ccfde508SMikko Perttunen }; 535ccfde508SMikko Perttunen 536ccfde508SMikko Perttunen static struct platform_driver tegra_ahci_driver = { 537ccfde508SMikko Perttunen .probe = tegra_ahci_probe, 538ccfde508SMikko Perttunen .remove = ata_platform_remove_one, 539ccfde508SMikko Perttunen .driver = { 540018d5ef2SAkinobu Mita .name = DRV_NAME, 541ccfde508SMikko Perttunen .of_match_table = tegra_ahci_of_match, 542ccfde508SMikko Perttunen }, 543ccfde508SMikko Perttunen /* LP0 suspend support not implemented */ 544ccfde508SMikko Perttunen }; 545ccfde508SMikko Perttunen module_platform_driver(tegra_ahci_driver); 546ccfde508SMikko Perttunen 547ccfde508SMikko Perttunen MODULE_AUTHOR("Mikko Perttunen <mperttunen@nvidia.com>"); 548ccfde508SMikko Perttunen MODULE_DESCRIPTION("Tegra124 AHCI SATA driver"); 549ccfde508SMikko Perttunen MODULE_LICENSE("GPL v2"); 550