drivers/ata/ahci_tegra.c

Source file repositories/reference/linux-study-clean/drivers/ata/ahci_tegra.c

File Facts

System
Linux kernel
Corpus path
drivers/ata/ahci_tegra.c
Extension
.c
Size
19144 bytes
Lines
630
Domain
Driver Families
Bucket
drivers/ata
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct sata_pad_calibration {
	u8 gen1_tx_amp;
	u8 gen1_tx_peak;
	u8 gen2_tx_amp;
	u8 gen2_tx_peak;
};

static const struct sata_pad_calibration tegra124_pad_calibration[] = {
	{0x18, 0x04, 0x18, 0x0a},
	{0x0e, 0x04, 0x14, 0x0a},
	{0x0e, 0x07, 0x1a, 0x0e},
	{0x14, 0x0e, 0x1a, 0x0e},
};

struct tegra_ahci_ops {
	int (*init)(struct ahci_host_priv *hpriv);
};

struct tegra_ahci_regs {
	unsigned int nvoob_comma_cnt_mask;
	unsigned int nvoob_comma_cnt_val;
};

struct tegra_ahci_soc {
	const char *const		*supply_names;
	u32				num_supplies;
	bool				supports_devslp;
	bool				has_sata_oob_rst;
	const struct tegra_ahci_ops	*ops;
	const struct tegra_ahci_regs	*regs;
};

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 tegra_pmc	   *pmc;
	struct regulator_bulk_data *supplies;
	const struct tegra_ahci_soc *soc;
};

static void tegra_ahci_handle_quirks(struct ahci_host_priv *hpriv)
{
	struct tegra_ahci_priv *tegra = hpriv->plat_data;
	u32 val;

	if (tegra->sata_aux_regs && !tegra->soc->supports_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);
	}
}

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 +

Annotation

Implementation Notes