drivers/phy/marvell/phy-mvebu-cp110-utmi.c

Source file repositories/reference/linux-study-clean/drivers/phy/marvell/phy-mvebu-cp110-utmi.c

File Facts

System
Linux kernel
Corpus path
drivers/phy/marvell/phy-mvebu-cp110-utmi.c
Extension
.c
Size
11308 bytes
Lines
401
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 mvebu_cp110_utmi {
	void __iomem *regs;
	struct regmap *syscon;
	struct device *dev;
	const struct phy_ops *ops;
};

/**
 * struct mvebu_cp110_utmi_port - PHY port data
 *
 * @priv: PHY driver data
 * @id: PHY port ID
 * @dr_mode: PHY connection: USB_DR_MODE_HOST or USB_DR_MODE_PERIPHERAL
 * @swap_dx: whether to swap d+/d- signals
 */
struct mvebu_cp110_utmi_port {
	struct mvebu_cp110_utmi *priv;
	u32 id;
	enum usb_dr_mode dr_mode;
	bool swap_dx;
};

static void mvebu_cp110_utmi_port_setup(struct mvebu_cp110_utmi_port *port)
{
	u32 reg;

	/*
	 * Setup PLL.
	 * The reference clock is the frequency of quartz resonator
	 * connected to pins REFCLK_XIN and REFCLK_XOUT of the SoC.
	 * Register init values are matching the 40MHz default clock.
	 * The crystal used for all platform boards is now 25MHz.
	 * See the functional specification for details.
	 */
	reg = readl(PORT_REGS(port) + UTMI_PLL_CTRL_REG);
	reg &= ~(PLL_REFDIV_MASK | PLL_FBDIV_MASK | PLL_SEL_LPFR_MASK);
	reg |= (PLL_REFDIV_VAL << PLL_REFDIV_OFFSET) |
	       (PLL_FBDIV_VAL << PLL_FBDIV_OFFSET);
	writel(reg, PORT_REGS(port) + UTMI_PLL_CTRL_REG);

	/* Impedance Calibration Threshold Setting */
	reg = readl(PORT_REGS(port) + UTMI_CAL_CTRL_REG);
	reg &= ~IMPCAL_VTH_MASK;
	reg |= IMPCAL_VTH_VAL << IMPCAL_VTH_OFFSET;
	writel(reg, PORT_REGS(port) + UTMI_CAL_CTRL_REG);

	/* Set LS TX driver strength coarse control */
	reg = readl(PORT_REGS(port) + UTMI_TX_CH_CTRL_REG);
	reg &= ~TX_AMP_MASK;
	reg |= TX_AMP_VAL << TX_AMP_OFFSET;
	writel(reg, PORT_REGS(port) + UTMI_TX_CH_CTRL_REG);

	/* Disable SQ and enable analog squelch detect */
	reg = readl(PORT_REGS(port) + UTMI_RX_CH_CTRL0_REG);
	reg &= ~SQ_DET_EN;
	reg |= SQ_ANA_DTC_SEL;
	writel(reg, PORT_REGS(port) + UTMI_RX_CH_CTRL0_REG);

	/*
	 * Set External squelch calibration number and
	 * enable the External squelch calibration
	 */
	reg = readl(PORT_REGS(port) + UTMI_RX_CH_CTRL1_REG);
	reg &= ~SQ_AMP_CAL_MASK;
	reg |= (SQ_AMP_CAL_VAL << SQ_AMP_CAL_OFFSET) | SQ_AMP_CAL_EN;
	writel(reg, PORT_REGS(port) + UTMI_RX_CH_CTRL1_REG);

	/*
	 * Set Control VDAT Reference Voltage - 0.325V and
	 * Control VSRC Reference Voltage - 0.6V
	 */
	reg = readl(PORT_REGS(port) + UTMI_CHGDTC_CTRL_REG);
	reg &= ~(VDAT_MASK | VSRC_MASK);
	reg |= (VDAT_VAL << VDAT_OFFSET) | (VSRC_VAL << VSRC_OFFSET);
	writel(reg, PORT_REGS(port) + UTMI_CHGDTC_CTRL_REG);

	/* Swap D+/D- */
	reg = readl(PORT_REGS(port) + UTMI_DIG_CTRL1_REG);
	reg &= ~(SWAP_DPDM);
	if (port->swap_dx)
		reg |= SWAP_DPDM;
	writel(reg, PORT_REGS(port) + UTMI_DIG_CTRL1_REG);
}

static int mvebu_cp110_utmi_phy_power_off(struct phy *phy)
{
	struct mvebu_cp110_utmi_port *port = phy_get_drvdata(phy);
	struct mvebu_cp110_utmi *utmi = port->priv;
	int i;

Annotation

Implementation Notes