xref: /openbmc/linux/drivers/ata/ahci_tegra.c (revision 56337b55)
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