drivers/phy/amlogic/phy-meson-axg-mipi-dphy.c

Source file repositories/reference/linux-study-clean/drivers/phy/amlogic/phy-meson-axg-mipi-dphy.c

File Facts

System
Linux kernel
Corpus path
drivers/phy/amlogic/phy-meson-axg-mipi-dphy.c
Extension
.c
Size
12155 bytes
Lines
409
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 phy_meson_axg_mipi_dphy_priv {
	struct device				*dev;
	struct regmap				*regmap;
	struct clk				*clk;
	struct reset_control			*reset;
	struct phy				*analog;
	struct phy_configure_opts_mipi_dphy	config;
};

static const struct regmap_config phy_meson_axg_mipi_dphy_regmap_conf = {
	.reg_bits = 8,
	.val_bits = 32,
	.reg_stride = 4,
	.max_register = MIPI_DSI_TEST_CTRL1,
};

static int phy_meson_axg_mipi_dphy_init(struct phy *phy)
{
	struct phy_meson_axg_mipi_dphy_priv *priv = phy_get_drvdata(phy);
	int ret;

	ret = phy_init(priv->analog);
	if (ret)
		return ret;

	ret = reset_control_reset(priv->reset);
	if (ret)
		return ret;

	return 0;
}

static int phy_meson_axg_mipi_dphy_configure(struct phy *phy,
					      union phy_configure_opts *opts)
{
	struct phy_meson_axg_mipi_dphy_priv *priv = phy_get_drvdata(phy);
	int ret;

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

	ret = phy_configure(priv->analog, opts);
	if (ret)
		return ret;

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

	return 0;
}

static int phy_meson_axg_mipi_dphy_power_on(struct phy *phy)
{
	struct phy_meson_axg_mipi_dphy_priv *priv = phy_get_drvdata(phy);
	int ret;
	unsigned long temp;

	ret = phy_power_on(priv->analog);
	if (ret)
		return ret;

	/* enable phy clock */
	regmap_write(priv->regmap, MIPI_DSI_PHY_CTRL,  0x1);
	regmap_write(priv->regmap, MIPI_DSI_PHY_CTRL,
		     BIT(0) | /* enable the DSI PLL clock . */
		     BIT(7) | /* enable pll clock which connected to DDR clock path */
		     BIT(8)); /* enable the clock divider counter */

	/* enable the divider clock out */
	regmap_update_bits(priv->regmap, MIPI_DSI_PHY_CTRL, BIT(9), BIT(9));

	/* enable the byte clock generation. */
	regmap_update_bits(priv->regmap, MIPI_DSI_PHY_CTRL, BIT(12), BIT(12));
	regmap_update_bits(priv->regmap, MIPI_DSI_PHY_CTRL, BIT(31), BIT(31));
	regmap_update_bits(priv->regmap, MIPI_DSI_PHY_CTRL, BIT(31), 0);

	/* Calculate lanebyteclk period in ps */
	temp = (1000000 * 100) / (priv->config.hs_clk_rate / 1000);
	temp = temp * 8 * 10;

	regmap_write(priv->regmap, MIPI_DSI_CLK_TIM,
		     DIV_ROUND_UP(priv->config.clk_trail, temp) |
		     (DIV_ROUND_UP(priv->config.clk_post +
				   priv->config.hs_trail, temp) << 8) |
		     (DIV_ROUND_UP(priv->config.clk_zero, temp) << 16) |
		     (DIV_ROUND_UP(priv->config.clk_prepare, temp) << 24));
	regmap_write(priv->regmap, MIPI_DSI_CLK_TIM1,
		     DIV_ROUND_UP(priv->config.clk_pre, BITS_PER_BYTE));

	regmap_write(priv->regmap, MIPI_DSI_HS_TIM,

Annotation

Implementation Notes