drivers/phy/phy-google-usb.c
Source file repositories/reference/linux-study-clean/drivers/phy/phy-google-usb.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/phy/phy-google-usb.c- Extension
.c- Size
- 8293 bytes
- Lines
- 297
- 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/bitfield.hlinux/cleanup.hlinux/clk.hlinux/io.hlinux/kernel.hlinux/mfd/syscon.hlinux/module.hlinux/mutex.hlinux/of.hlinux/phy/phy.hlinux/platform_device.hlinux/regmap.hlinux/reset.hlinux/usb/typec_mux.h
Detected Declarations
struct google_usb_phy_instancestruct google_usb_phyenum google_usb_phy_idfunction set_vbus_validfunction google_usb_set_orientationfunction google_usb2_phy_initfunction google_usb2_phy_exitfunction google_usb_phy_probefunction google_usb_phy_remove
Annotated Snippet
struct google_usb_phy_instance {
struct google_usb_phy *parent;
unsigned int index;
struct phy *phy;
unsigned int num_clks;
struct clk_bulk_data *clks;
unsigned int num_rsts;
struct reset_control_bulk_data *rsts;
};
struct google_usb_phy {
struct device *dev;
struct regmap *usb_cfg_regmap;
unsigned int usb2_cfg_offset;
void __iomem *usbdp_top_base;
struct google_usb_phy_instance *insts;
/*
* Protect phy registers from concurrent access, specifically via
* google_usb_set_orientation callback.
*/
struct mutex phy_mutex;
struct typec_switch_dev *sw;
enum typec_orientation orientation;
};
static void set_vbus_valid(struct google_usb_phy *gphy)
{
u32 reg;
if (gphy->orientation == TYPEC_ORIENTATION_NONE) {
reg = readl(gphy->usbdp_top_base + USBCS_PHY_CFG1_OFFSET);
reg &= ~USBCS_PHY_CFG1_SYS_VBUSVALID;
writel(reg, gphy->usbdp_top_base + USBCS_PHY_CFG1_OFFSET);
} else {
reg = readl(gphy->usbdp_top_base + USBCS_PHY_CFG1_OFFSET);
reg |= USBCS_PHY_CFG1_SYS_VBUSVALID;
writel(reg, gphy->usbdp_top_base + USBCS_PHY_CFG1_OFFSET);
}
}
static int google_usb_set_orientation(struct typec_switch_dev *sw,
enum typec_orientation orientation)
{
struct google_usb_phy *gphy = typec_switch_get_drvdata(sw);
dev_dbg(gphy->dev, "set orientation %d\n", orientation);
gphy->orientation = orientation;
if (pm_runtime_suspended(gphy->dev))
return 0;
guard(mutex)(&gphy->phy_mutex);
set_vbus_valid(gphy);
return 0;
}
static int google_usb2_phy_init(struct phy *_phy)
{
struct google_usb_phy_instance *inst = phy_get_drvdata(_phy);
struct google_usb_phy *gphy = inst->parent;
u32 reg;
int ret;
dev_dbg(gphy->dev, "initializing usb2 phy\n");
guard(mutex)(&gphy->phy_mutex);
regmap_read(gphy->usb_cfg_regmap, gphy->usb2_cfg_offset + USBCS_USB2PHY_CFG21_OFFSET, ®);
reg &= ~USBCS_USB2PHY_CFG21_PHY_TX_DIG_BYPASS_SEL;
reg &= ~USBCS_USB2PHY_CFG21_REF_FREQ_SEL;
reg |= FIELD_PREP(USBCS_USB2PHY_CFG21_REF_FREQ_SEL, 0);
regmap_write(gphy->usb_cfg_regmap, gphy->usb2_cfg_offset + USBCS_USB2PHY_CFG21_OFFSET, reg);
regmap_read(gphy->usb_cfg_regmap, gphy->usb2_cfg_offset + USBCS_USB2PHY_CFG19_OFFSET, ®);
reg &= ~USBCS_USB2PHY_CFG19_PHY_CFG_PLL_FB_DIV;
reg |= FIELD_PREP(USBCS_USB2PHY_CFG19_PHY_CFG_PLL_FB_DIV, 368);
regmap_write(gphy->usb_cfg_regmap, gphy->usb2_cfg_offset + USBCS_USB2PHY_CFG19_OFFSET, reg);
set_vbus_valid(gphy);
ret = clk_bulk_prepare_enable(inst->num_clks, inst->clks);
if (ret)
return ret;
ret = reset_control_bulk_deassert(inst->num_rsts, inst->rsts);
if (ret) {
clk_bulk_disable_unprepare(inst->num_clks, inst->clks);
Annotation
- Immediate include surface: `linux/bitfield.h`, `linux/cleanup.h`, `linux/clk.h`, `linux/io.h`, `linux/kernel.h`, `linux/mfd/syscon.h`, `linux/module.h`, `linux/mutex.h`.
- Detected declarations: `struct google_usb_phy_instance`, `struct google_usb_phy`, `enum google_usb_phy_id`, `function set_vbus_valid`, `function google_usb_set_orientation`, `function google_usb2_phy_init`, `function google_usb2_phy_exit`, `function google_usb_phy_probe`, `function google_usb_phy_remove`.
- 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.