drivers/phy/sunplus/phy-sunplus-usb2.c

Source file repositories/reference/linux-study-clean/drivers/phy/sunplus/phy-sunplus-usb2.c

File Facts

System
Linux kernel
Corpus path
drivers/phy/sunplus/phy-sunplus-usb2.c
Extension
.c
Size
8358 bytes
Lines
300
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 sp_usbphy {
	struct device *dev;
	struct resource *phy_res_mem;
	struct resource *moon4_res_mem;
	struct reset_control *rstc;
	struct clk *phy_clk;
	void __iomem *phy_regs;
	void __iomem *moon4_regs;
	u32 disc_vol_addr_off;
};

static int update_disc_vol(struct sp_usbphy *usbphy)
{
	struct nvmem_cell *cell;
	char *disc_name = "disc_vol";
	ssize_t otp_l = 0;
	char *otp_v;
	u32 val, set;

	cell = nvmem_cell_get(usbphy->dev, disc_name);
	if (IS_ERR_OR_NULL(cell)) {
		if (PTR_ERR(cell) == -EPROBE_DEFER)
			return -EPROBE_DEFER;
	}

	otp_v = nvmem_cell_read(cell, &otp_l);
	nvmem_cell_put(cell);

	if (!IS_ERR(otp_v)) {
		set = *(otp_v + 1);
		set = (set << (sizeof(char) * 8)) | *otp_v;
		set = (set >> usbphy->disc_vol_addr_off) & J_DISC;
	}

	if (IS_ERR(otp_v) || set == 0)
		set = OTP_DISC_LEVEL_DEFAULT;

	val = readl(usbphy->phy_regs + CONFIG7);
	val = (val & ~J_DISC) | set;
	writel(val, usbphy->phy_regs + CONFIG7);

	return 0;
}

static int sp_uphy_init(struct phy *phy)
{
	struct sp_usbphy *usbphy = phy_get_drvdata(phy);
	u32 val;
	int ret;

	ret = clk_prepare_enable(usbphy->phy_clk);
	if (ret)
		goto err_clk;

	ret = reset_control_deassert(usbphy->rstc);
	if (ret)
		goto err_reset;

	/* Default value modification */
	writel(HIGH_MASK_BITS | 0x4002, usbphy->moon4_regs + UPHY_CONTROL0);
	writel(HIGH_MASK_BITS | 0x8747, usbphy->moon4_regs + UPHY_CONTROL1);

	/* disconnect voltage */
	ret = update_disc_vol(usbphy);
	if (ret < 0)
		return ret;

	/* board uphy 0 internal register modification for tid certification */
	val = readl(usbphy->phy_regs + CONFIG9);
	val &= ~(J_ECO_PATH);
	writel(val, usbphy->phy_regs + CONFIG9);

	val = readl(usbphy->phy_regs + CONFIG1);
	val &= ~(J_HS_TX_PWRSAV);
	writel(val, usbphy->phy_regs + CONFIG1);

	val = readl(usbphy->phy_regs + CONFIG23);
	val = (val & ~PROB) | PROB;
	writel(val, usbphy->phy_regs + CONFIG23);

	/* port 0 uphy clk fix */
	writel(MASK_MO1_UPHY_RX_CLK_SEL | MO1_UPHY_RX_CLK_SEL,
	       usbphy->moon4_regs + UPHY_CONTROL2);

	/* battery charger */
	writel(J_TBCWAIT_1P1_MS | J_TVDM_SRC_DIS_8P2_MS | J_TVDM_SRC_EN_1P6_MS | J_BC_EN,
	       usbphy->phy_regs + CONFIG16);
	writel(IBG_TRIM0_SSLVHT | J_VDATREE_TRIM_DEFAULT, usbphy->phy_regs + CONFIG17);

	/* chirp mode */

Annotation

Implementation Notes