drivers/phy/st/phy-stm32-combophy.c
Source file repositories/reference/linux-study-clean/drivers/phy/st/phy-stm32-combophy.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/phy/st/phy-stm32-combophy.c- Extension
.c- Size
- 16533 bytes
- Lines
- 606
- 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.
- Touches IRQ or DMA behavior; this matters for the representative real-device path.
- 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/bitfield.hlinux/clk.hlinux/mfd/syscon.hlinux/platform_device.hlinux/phy/phy.hlinux/pm_runtime.hlinux/regmap.hlinux/reset.hdt-bindings/phy/phy.h
Detected Declarations
struct stm32_combophystruct clk_impedancefunction stm32_impedance_tunefunction stm32_combophy_pll_initfunction stm32_combophy_set_modefunction stm32_combophy_suspend_noirqfunction stm32_combophy_resume_noirqfunction stm32_combophy_exitfunction stm32_combophy_initfunction stm32_combophy_irq_wakeup_handlerfunction stm32_combophy_get_clocksfunction stm32_combophy_probe
Annotated Snippet
struct stm32_combophy {
struct phy *phy;
struct regmap *regmap;
struct device *dev;
void __iomem *base;
struct reset_control *phy_reset;
struct clk_bulk_data clks[ARRAY_SIZE(combophy_clks)];
int num_clks;
bool have_pad_clk;
unsigned int type;
bool is_init;
int irq_wakeup;
};
struct clk_impedance {
u32 microohm;
u32 vswing[4];
};
/*
* lookup table to hold the settings needed for a ref clock frequency
* impedance, the offset is used to set the IMP_CTL and DE_EMP bit of the
* PRG_IMP_CTRL register. Use ordered discrete values in the table
*/
static const struct clk_impedance imp_lookup[] = {
{ 6090000, { 442000, 564000, 684000, 802000 } },
{ 5662000, { 528000, 621000, 712000, 803000 } },
{ 5292000, { 491000, 596000, 700000, 802000 } },
{ 4968000, { 558000, 640000, 722000, 803000 } },
{ 4684000, { 468000, 581000, 692000, 802000 } },
{ 4429000, { 554000, 613000, 717000, 803000 } },
{ 4204000, { 511000, 609000, 706000, 802000 } },
{ 3999000, { 571000, 648000, 726000, 803000 } }
};
#define DEFAULT_IMP_INDEX 3 /* Default impedance is 50 Ohm */
static int stm32_impedance_tune(struct stm32_combophy *combophy)
{
u8 imp_size = ARRAY_SIZE(imp_lookup);
u8 vswing_size = ARRAY_SIZE(imp_lookup[0].vswing);
u8 imp_of, vswing_of;
u32 max_imp = imp_lookup[0].microohm;
u32 min_imp = imp_lookup[imp_size - 1].microohm;
u32 max_vswing;
u32 min_vswing = imp_lookup[0].vswing[0];
u32 val;
if (!of_property_read_u32(combophy->dev->of_node, "st,output-micro-ohms", &val)) {
if (val < min_imp || val > max_imp) {
dev_err(combophy->dev, "Invalid value %u for output ohm\n", val);
return -EINVAL;
}
for (imp_of = 0; imp_of < ARRAY_SIZE(imp_lookup); imp_of++)
if (imp_lookup[imp_of].microohm <= val)
break;
if (WARN_ON(imp_of == ARRAY_SIZE(imp_lookup)))
return -EINVAL;
dev_dbg(combophy->dev, "Set %u micro-ohms output impedance\n",
imp_lookup[imp_of].microohm);
regmap_update_bits(combophy->regmap, SYSCFG_PCIEPRGCR,
STM32MP25_PCIEPRG_IMPCTRL_OHM,
FIELD_PREP(STM32MP25_PCIEPRG_IMPCTRL_OHM, imp_of));
} else
imp_of = DEFAULT_IMP_INDEX;
if (!of_property_read_u32(combophy->dev->of_node, "st,output-vswing-microvolt", &val)) {
max_vswing = imp_lookup[imp_of].vswing[vswing_size - 1];
if (val < min_vswing || val > max_vswing) {
dev_err(combophy->dev, "Invalid value %u for output vswing\n", val);
return -EINVAL;
}
for (vswing_of = 0; vswing_of < ARRAY_SIZE(imp_lookup[imp_of].vswing); vswing_of++)
if (imp_lookup[imp_of].vswing[vswing_of] >= val)
break;
if (WARN_ON(vswing_of == ARRAY_SIZE(imp_lookup[imp_of].vswing)))
return -EINVAL;
dev_dbg(combophy->dev, "Set %u microvolt swing\n",
imp_lookup[imp_of].vswing[vswing_of]);
regmap_update_bits(combophy->regmap, SYSCFG_PCIEPRGCR,
STM32MP25_PCIEPRG_IMPCTRL_VSWING,
FIELD_PREP(STM32MP25_PCIEPRG_IMPCTRL_VSWING, vswing_of));
Annotation
- Immediate include surface: `linux/bitfield.h`, `linux/clk.h`, `linux/mfd/syscon.h`, `linux/platform_device.h`, `linux/phy/phy.h`, `linux/pm_runtime.h`, `linux/regmap.h`, `linux/reset.h`.
- Detected declarations: `struct stm32_combophy`, `struct clk_impedance`, `function stm32_impedance_tune`, `function stm32_combophy_pll_init`, `function stm32_combophy_set_mode`, `function stm32_combophy_suspend_noirq`, `function stm32_combophy_resume_noirq`, `function stm32_combophy_exit`, `function stm32_combophy_init`, `function stm32_combophy_irq_wakeup_handler`.
- Atlas domain: Driver Families / drivers/phy.
- Implementation status: source implementation candidate.
- IRQ or DMA behavior appears here, which is relevant to the selected PCIe/NVMe device path.
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.