switch (pm_event) { case PM_HIBERNATION_PREPARE: case PM_SUSPEND_PREPARE:
priv->pm_active = true; break; case PM_POST_RESTORE: case PM_POST_HIBERNATION: case PM_POST_SUSPEND:
priv->pm_active = false; break;
} return NOTIFY_DONE;
}
/* * Use a lock to make sure a second caller waits until * the base phy is inited before using it.
*/
mutex_lock(&priv->mutex); if (priv->init_count++ == 0) {
clk_prepare_enable(priv->usb_20_clk);
clk_prepare_enable(priv->usb_30_clk);
clk_prepare_enable(priv->suspend_clk);
brcm_usb_init_common(&priv->ini);
}
mutex_unlock(&priv->mutex); if (phy->id == BRCM_USB_PHY_2_0)
brcm_usb_init_eohci(&priv->ini); elseif (phy->id == BRCM_USB_PHY_3_0)
brcm_usb_init_xhci(&priv->ini);
phy->inited = true;
dev_dbg(&gphy->dev, "INIT, id: %d, total: %d\n", phy->id,
priv->init_count);
/* * values 0 and 1 are for backward compatibility with * device tree nodes from older bootloaders.
*/ switch (args->args[0]) { case 0: case PHY_TYPE_USB2: if (data->phys[BRCM_USB_PHY_2_0].phy) return data->phys[BRCM_USB_PHY_2_0].phy;
dev_warn(dev, "Error, 2.0 Phy not found\n"); break; case 1: case PHY_TYPE_USB3: if (data->phys[BRCM_USB_PHY_3_0].phy) return data->phys[BRCM_USB_PHY_3_0].phy;
dev_warn(dev, "Error, 3.0 Phy not found\n"); break;
} return ERR_PTR(-ENODEV);
}
staticint name_to_value(conststruct value_to_name_map *table, int count, constchar *name, int *value)
{ int x;
*value = 0; for (x = 0; x < count; x++) { if (sysfs_streq(name, table[x].name)) {
*value = x; return 0;
}
} return -EINVAL;
}
staticconstchar *value_to_name(conststruct value_to_name_map *table, int count, int value)
{ if (value >= count) return"unknown"; return table[value].name;
}
priv->usb_20_clk = of_clk_get_by_name(dn, "sw_usb"); if (IS_ERR(priv->usb_20_clk)) { if (PTR_ERR(priv->usb_20_clk) == -EPROBE_DEFER) return -EPROBE_DEFER;
dev_info(dev, "Clock not found in Device Tree\n");
priv->usb_20_clk = NULL;
}
err = clk_prepare_enable(priv->usb_20_clk); if (err) return err;
if (priv->has_eohci) {
gphy = devm_phy_create(dev, NULL, &brcm_usb_phy_ops); if (IS_ERR(gphy)) {
dev_err(dev, "failed to create EHCI/OHCI PHY\n"); return PTR_ERR(gphy);
}
priv->phys[BRCM_USB_PHY_2_0].phy = gphy;
priv->phys[BRCM_USB_PHY_2_0].id = BRCM_USB_PHY_2_0;
phy_set_drvdata(gphy, &priv->phys[BRCM_USB_PHY_2_0]);
}
if (priv->has_xhci) {
gphy = devm_phy_create(dev, NULL, &brcm_usb_phy_ops); if (IS_ERR(gphy)) {
dev_err(dev, "failed to create XHCI PHY\n"); return PTR_ERR(gphy);
}
priv->phys[BRCM_USB_PHY_3_0].phy = gphy;
priv->phys[BRCM_USB_PHY_3_0].id = BRCM_USB_PHY_3_0;
phy_set_drvdata(gphy, &priv->phys[BRCM_USB_PHY_3_0]);
priv->usb_30_clk = of_clk_get_by_name(dn, "sw_usb3"); if (IS_ERR(priv->usb_30_clk)) { if (PTR_ERR(priv->usb_30_clk) == -EPROBE_DEFER) return -EPROBE_DEFER;
dev_info(dev, "USB3.0 clock not found in Device Tree\n");
priv->usb_30_clk = NULL;
}
err = clk_prepare_enable(priv->usb_30_clk); if (err) return err;
}
priv->suspend_clk = clk_get(dev, "usb0_freerun"); if (IS_ERR(priv->suspend_clk)) { if (PTR_ERR(priv->suspend_clk) == -EPROBE_DEFER) return -EPROBE_DEFER;
dev_err(dev, "Suspend Clock not found in Device Tree\n");
priv->suspend_clk = NULL;
}
priv->wake_irq = platform_get_irq_byname_optional(pdev, "wake"); if (priv->wake_irq < 0)
priv->wake_irq = platform_get_irq_byname_optional(pdev, "wakeup"); if (priv->wake_irq >= 0) {
err = devm_request_irq(dev, priv->wake_irq,
brcm_usb_phy_wake_isr, 0,
dev_name(dev), dev); if (err < 0) return err;
device_set_wakeup_capable(dev, 1);
} else {
dev_info(dev, "Wake interrupt missing, system wake not supported\n");
}
/* make sure invert settings are correct */
brcm_usb_init_ipp(&priv->ini);
/* * Create sysfs entries for mode. * Remove "dual_select" attribute if not in dual mode
*/ if (priv->ini.supported_port_modes != USB_CTLR_MODE_DRD)
brcm_usb_phy_attrs[1] = NULL;
err = sysfs_create_group(&dev->kobj, &brcm_usb_phy_group); if (err)
dev_warn(dev, "Error creating sysfs attributes\n");
/* Get piarbctl syscon if it exists */
rmap = syscon_regmap_lookup_by_phandle(dev->of_node, "syscon-piarbctl"); if (IS_ERR(rmap))
rmap = syscon_regmap_lookup_by_phandle(dev->of_node, "brcm,syscon-piarbctl"); if (!IS_ERR(rmap))
priv->ini.syscon_piarbctl = rmap;
/* start with everything off */ if (priv->has_xhci)
brcm_usb_uninit_xhci(&priv->ini); if (priv->has_eohci)
brcm_usb_uninit_eohci(&priv->ini);
brcm_usb_uninit_common(&priv->ini);
clk_disable_unprepare(priv->usb_20_clk);
clk_disable_unprepare(priv->usb_30_clk);
if (priv->init_count) {
dev_dbg(dev, "SUSPEND\n");
priv->ini.wake_enabled = device_may_wakeup(dev); if (priv->phys[BRCM_USB_PHY_3_0].inited)
brcm_usb_uninit_xhci(&priv->ini); if (priv->phys[BRCM_USB_PHY_2_0].inited)
brcm_usb_uninit_eohci(&priv->ini);
brcm_usb_uninit_common(&priv->ini);
/* * Handle the clocks unless needed for wake. This has * to work for both older XHCI->3.0-clks, EOHCI->2.0-clks * and newer XHCI->2.0-clks/3.0-clks.
*/
if (!priv->ini.wake_enabled) { if (priv->phys[BRCM_USB_PHY_3_0].inited)
clk_disable_unprepare(priv->usb_30_clk); if (priv->phys[BRCM_USB_PHY_2_0].inited ||
!priv->has_eohci)
clk_disable_unprepare(priv->usb_20_clk);
} if (priv->wake_irq >= 0)
enable_irq_wake(priv->wake_irq);
} return 0;
}
MODULE_ALIAS("platform:brcmstb-usb-phy");
MODULE_AUTHOR("Al Cooper <acooper@broadcom.com>");
MODULE_DESCRIPTION("BRCM USB PHY driver");
MODULE_LICENSE("GPL v2");
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.10 Sekunden
(vorverarbeitet am 2026-04-29)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.