drivers/phy/samsung/phy-exynos5250-sata.c

Source file repositories/reference/linux-study-clean/drivers/phy/samsung/phy-exynos5250-sata.c

File Facts

System
Linux kernel
Corpus path
drivers/phy/samsung/phy-exynos5250-sata.c
Extension
.c
Size
6959 bytes
Lines
255
Domain
Driver Families
Bucket
drivers/phy
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 exynos_sata_phy {
	struct phy *phy;
	struct clk *phyclk;
	void __iomem *regs;
	struct regmap *pmureg;
	struct i2c_client *client;
};

static int wait_for_reg_status(void __iomem *base, u32 reg, u32 checkbit,
				u32 status)
{
	unsigned long timeout = jiffies + PHY_PLL_TIMEOUT;

	while (time_before(jiffies, timeout)) {
		if ((readl(base + reg) & checkbit) == status)
			return 0;
	}

	return -EFAULT;
}

static int exynos_sata_phy_power_on(struct phy *phy)
{
	struct exynos_sata_phy *sata_phy = phy_get_drvdata(phy);

	return regmap_update_bits(sata_phy->pmureg, SATAPHY_CONTROL_OFFSET,
			EXYNOS5_SATAPHY_PMU_ENABLE, true);

}

static int exynos_sata_phy_power_off(struct phy *phy)
{
	struct exynos_sata_phy *sata_phy = phy_get_drvdata(phy);

	return regmap_update_bits(sata_phy->pmureg, SATAPHY_CONTROL_OFFSET,
			EXYNOS5_SATAPHY_PMU_ENABLE, false);

}

static int exynos_sata_phy_init(struct phy *phy)
{
	u32 val = 0;
	int ret = 0;
	u8 buf[] = { 0x3a, 0x0b };
	struct exynos_sata_phy *sata_phy = phy_get_drvdata(phy);

	ret = regmap_update_bits(sata_phy->pmureg, SATAPHY_CONTROL_OFFSET,
			EXYNOS5_SATAPHY_PMU_ENABLE, true);
	if (ret != 0)
		dev_err(&sata_phy->phy->dev, "phy init failed\n");

	writel(val, sata_phy->regs + EXYNOS5_SATA_RESET);

	val = readl(sata_phy->regs + EXYNOS5_SATA_RESET);
	val |= RESET_GLOBAL_RST_N | RESET_CMN_RST_N | RESET_CMN_BLOCK_RST_N
		| RESET_CMN_I2C_RST_N | RESET_TX_RX_PIPE_RST_N
		| RESET_TX_RX_BLOCK_RST_N | RESET_TX_RX_I2C_RST_N;
	writel(val, sata_phy->regs + EXYNOS5_SATA_RESET);

	val = readl(sata_phy->regs + EXYNOS5_SATA_RESET);
	val |= LINK_RESET;
	writel(val, sata_phy->regs + EXYNOS5_SATA_RESET);

	val = readl(sata_phy->regs + EXYNOS5_SATA_RESET);
	val |= RESET_CMN_RST_N;
	writel(val, sata_phy->regs + EXYNOS5_SATA_RESET);

	val = readl(sata_phy->regs + EXYNOS5_SATA_PHSATA_CTRLM);
	val &= ~PHCTRLM_REF_RATE;
	writel(val, sata_phy->regs + EXYNOS5_SATA_PHSATA_CTRLM);

	/* High speed enable for Gen3 */
	val = readl(sata_phy->regs + EXYNOS5_SATA_PHSATA_CTRLM);
	val |= PHCTRLM_HIGH_SPEED;
	writel(val, sata_phy->regs + EXYNOS5_SATA_PHSATA_CTRLM);

	val = readl(sata_phy->regs + EXYNOS5_SATA_CTRL0);
	val |= CTRL0_P0_PHY_CALIBRATED_SEL | CTRL0_P0_PHY_CALIBRATED;
	writel(val, sata_phy->regs + EXYNOS5_SATA_CTRL0);

	val = readl(sata_phy->regs + EXYNOS5_SATA_MODE0);
	val |= SATA_SPD_GEN3;
	writel(val, sata_phy->regs + EXYNOS5_SATA_MODE0);

	ret = i2c_master_send(sata_phy->client, buf, sizeof(buf));
	if (ret < 0)
		return ret;

	/* release cmu reset */
	val = readl(sata_phy->regs + EXYNOS5_SATA_RESET);

Annotation

Implementation Notes