drivers/phy/marvell/phy-mvebu-a3700-utmi.c
Source file repositories/reference/linux-study-clean/drivers/phy/marvell/phy-mvebu-a3700-utmi.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/phy/marvell/phy-mvebu-a3700-utmi.c- Extension
.c- Size
- 7693 bytes
- Lines
- 270
- 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.
- 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.
- Allocates kernel memory; connect allocation flags and lifetime to context constraints.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/io.hlinux/iopoll.hlinux/mfd/syscon.hlinux/module.hlinux/of.hlinux/phy/phy.hlinux/platform_device.hlinux/regmap.h
Detected Declarations
struct mvebu_a3700_utmi_capsstruct mvebu_a3700_utmifunction mvebu_a3700_utmi_phy_power_onfunction mvebu_a3700_utmi_phy_power_offfunction mvebu_a3700_utmi_phy_probe
Annotated Snippet
struct mvebu_a3700_utmi_caps {
int usb32;
const struct phy_ops *ops;
};
/**
* struct mvebu_a3700_utmi - PHY driver data
*
* @regs: PHY registers
* @usb_misc: Regmap with USB miscellaneous registers including PHY ones
* @caps: PHY capabilities
* @phy: PHY handle
*/
struct mvebu_a3700_utmi {
void __iomem *regs;
struct regmap *usb_misc;
const struct mvebu_a3700_utmi_caps *caps;
struct phy *phy;
};
static int mvebu_a3700_utmi_phy_power_on(struct phy *phy)
{
struct mvebu_a3700_utmi *utmi = phy_get_drvdata(phy);
struct device *dev = &phy->dev;
int usb32 = utmi->caps->usb32;
int ret = 0;
u32 reg;
/*
* Setup PLL. 40MHz clock used to be the default, being 25MHz now.
* See "PLL Settings for Typical REFCLK" table.
*/
reg = readl(utmi->regs + USB2_PHY_PLL_CTRL_REG0);
reg &= ~(PLL_REF_DIV_MASK | PLL_FB_DIV_MASK | PLL_SEL_LPFR_MASK);
reg |= (PLL_REF_DIV_5 << PLL_REF_DIV_OFF) |
(PLL_FB_DIV_96 << PLL_FB_DIV_OFF);
writel(reg, utmi->regs + USB2_PHY_PLL_CTRL_REG0);
/* Enable PHY pull up and disable USB2 suspend */
regmap_update_bits(utmi->usb_misc, USB2_PHY_CTRL(usb32),
RB_USB2PHY_SUSPM(usb32) | RB_USB2PHY_PU,
RB_USB2PHY_SUSPM(usb32) | RB_USB2PHY_PU);
if (usb32) {
/* Power up OTG module */
reg = readl(utmi->regs + USB2_PHY_OTG_CTRL);
reg |= PHY_PU_OTG;
writel(reg, utmi->regs + USB2_PHY_OTG_CTRL);
/* Disable PHY charger detection */
reg = readl(utmi->regs + USB2_PHY_CHRGR_DETECT);
reg &= ~(PHY_CDP_EN | PHY_DCP_EN | PHY_PD_EN | PHY_PU_CHRG_DTC |
PHY_CDP_DM_AUTO | PHY_ENSWITCH_DP | PHY_ENSWITCH_DM);
writel(reg, utmi->regs + USB2_PHY_CHRGR_DETECT);
/* Disable PHY DP/DM pull-down (used for device mode) */
regmap_update_bits(utmi->usb_misc, USB2_PHY_CTRL(usb32),
USB2_DP_PULLDN_DEV_MODE |
USB2_DM_PULLDN_DEV_MODE, 0);
}
/* Wait for PLL calibration */
ret = readl_poll_timeout(utmi->regs + USB2_PHY_CAL_CTRL, reg,
reg & PHY_PLLCAL_DONE,
PLL_LOCK_DELAY_US, PLL_LOCK_TIMEOUT_US);
if (ret) {
dev_err(dev, "Failed to end USB2 PLL calibration\n");
return ret;
}
/* Wait for impedance calibration */
ret = readl_poll_timeout(utmi->regs + USB2_PHY_CAL_CTRL, reg,
reg & PHY_IMPCAL_DONE,
PLL_LOCK_DELAY_US, PLL_LOCK_TIMEOUT_US);
if (ret) {
dev_err(dev, "Failed to end USB2 impedance calibration\n");
return ret;
}
/* Wait for squelch calibration */
ret = readl_poll_timeout(utmi->regs + USB2_RX_CHAN_CTRL1, reg,
reg & USB2PHY_SQCAL_DONE,
PLL_LOCK_DELAY_US, PLL_LOCK_TIMEOUT_US);
if (ret) {
dev_err(dev, "Failed to end USB2 unknown calibration\n");
return ret;
}
/* Wait for PLL to be locked */
ret = readl_poll_timeout(utmi->regs + USB2_PHY_PLL_CTRL_REG0, reg,
Annotation
- Immediate include surface: `linux/io.h`, `linux/iopoll.h`, `linux/mfd/syscon.h`, `linux/module.h`, `linux/of.h`, `linux/phy/phy.h`, `linux/platform_device.h`, `linux/regmap.h`.
- Detected declarations: `struct mvebu_a3700_utmi_caps`, `struct mvebu_a3700_utmi`, `function mvebu_a3700_utmi_phy_power_on`, `function mvebu_a3700_utmi_phy_power_off`, `function mvebu_a3700_utmi_phy_probe`.
- Atlas domain: Driver Families / drivers/phy.
- Implementation status: source implementation candidate.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.