drivers/phy/allwinner/phy-sun6i-mipi-dphy.c

Source file repositories/reference/linux-study-clean/drivers/phy/allwinner/phy-sun6i-mipi-dphy.c

File Facts

System
Linux kernel
Corpus path
drivers/phy/allwinner/phy-sun6i-mipi-dphy.c
Extension
.c
Size
20167 bytes
Lines
649
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 sun6i_dphy_variant {
	void	(*tx_power_on)(struct sun6i_dphy *dphy);
	bool	rx_supported;
};

struct sun6i_dphy {
	struct clk				*bus_clk;
	struct clk				*mod_clk;
	struct regmap				*regs;
	struct reset_control			*reset;

	struct phy				*phy;
	struct phy_configure_opts_mipi_dphy	config;

	const struct sun6i_dphy_variant		*variant;
	enum sun6i_dphy_direction		direction;
};

static int sun6i_dphy_init(struct phy *phy)
{
	struct sun6i_dphy *dphy = phy_get_drvdata(phy);

	reset_control_deassert(dphy->reset);
	clk_prepare_enable(dphy->mod_clk);
	clk_set_rate_exclusive(dphy->mod_clk, 150000000);

	return 0;
}

static int sun6i_dphy_configure(struct phy *phy, union phy_configure_opts *opts)
{
	struct sun6i_dphy *dphy = phy_get_drvdata(phy);
	int ret;

	ret = phy_mipi_dphy_config_validate(&opts->mipi_dphy);
	if (ret)
		return ret;

	memcpy(&dphy->config, opts, sizeof(dphy->config));

	return 0;
}

static void sun6i_a31_mipi_dphy_tx_power_on(struct sun6i_dphy *dphy)
{
	u8 lanes_mask = GENMASK(dphy->config.lanes - 1, 0);

	regmap_write(dphy->regs, SUN6I_DPHY_ANA0_REG,
		     SUN6I_DPHY_ANA0_REG_PWS |
		     SUN6I_DPHY_ANA0_REG_DMPC |
		     SUN6I_DPHY_ANA0_REG_SLV(7) |
		     SUN6I_DPHY_ANA0_REG_DMPD(lanes_mask) |
		     SUN6I_DPHY_ANA0_REG_DEN(lanes_mask));

	regmap_write(dphy->regs, SUN6I_DPHY_ANA1_REG,
		     SUN6I_DPHY_ANA1_REG_CSMPS(1) |
		     SUN6I_DPHY_ANA1_REG_SVTT(7));

	regmap_write(dphy->regs, SUN6I_DPHY_ANA4_REG,
		     SUN6I_DPHY_ANA4_REG_CKDV(1) |
		     SUN6I_DPHY_ANA4_REG_TMSC(1) |
		     SUN6I_DPHY_ANA4_REG_TMSD(1) |
		     SUN6I_DPHY_ANA4_REG_TXDNSC(1) |
		     SUN6I_DPHY_ANA4_REG_TXDNSD(1) |
		     SUN6I_DPHY_ANA4_REG_TXPUSC(1) |
		     SUN6I_DPHY_ANA4_REG_TXPUSD(1) |
		     SUN6I_DPHY_ANA4_REG_DMPLVC |
		     SUN6I_DPHY_ANA4_REG_DMPLVD(lanes_mask));

	regmap_write(dphy->regs, SUN6I_DPHY_ANA2_REG,
		     SUN6I_DPHY_ANA2_REG_ENIB);
	udelay(5);

	regmap_write(dphy->regs, SUN6I_DPHY_ANA3_REG,
		     SUN6I_DPHY_ANA3_EN_LDOR |
		     SUN6I_DPHY_ANA3_EN_LDOC |
		     SUN6I_DPHY_ANA3_EN_LDOD);
	udelay(1);
}

static void sun50i_a100_mipi_dphy_tx_power_on(struct sun6i_dphy *dphy)
{
	unsigned long mipi_symbol_rate = dphy->config.hs_clk_rate;
	unsigned int div, n;

	regmap_write(dphy->regs, SUN6I_DPHY_ANA4_REG,
		     SUN6I_DPHY_ANA4_REG_IB(2) |
		     SUN6I_DPHY_ANA4_REG_DMPLVD(4) |
		     SUN6I_DPHY_ANA4_REG_VTT_SET(3) |
		     SUN6I_DPHY_ANA4_REG_CKDV(3) |

Annotation

Implementation Notes