in broadcom/phy-bcm-ns2-usbdrd.c [290:413]
static int ns2_drd_phy_probe(struct platform_device *pdev)
{
struct phy_provider *phy_provider;
struct device *dev = &pdev->dev;
struct ns2_phy_driver *driver;
struct ns2_phy_data *data;
int ret;
u32 val;
driver = devm_kzalloc(dev, sizeof(struct ns2_phy_driver),
GFP_KERNEL);
if (!driver)
return -ENOMEM;
driver->data = devm_kzalloc(dev, sizeof(struct ns2_phy_data),
GFP_KERNEL);
if (!driver->data)
return -ENOMEM;
driver->icfgdrd_regs = devm_platform_ioremap_resource_byname(pdev, "icfg");
if (IS_ERR(driver->icfgdrd_regs))
return PTR_ERR(driver->icfgdrd_regs);
driver->idmdrd_rst_ctrl = devm_platform_ioremap_resource_byname(pdev, "rst-ctrl");
if (IS_ERR(driver->idmdrd_rst_ctrl))
return PTR_ERR(driver->idmdrd_rst_ctrl);
driver->crmu_usb2_ctrl = devm_platform_ioremap_resource_byname(pdev, "crmu-ctrl");
if (IS_ERR(driver->crmu_usb2_ctrl))
return PTR_ERR(driver->crmu_usb2_ctrl);
driver->usb2h_strap_reg = devm_platform_ioremap_resource_byname(pdev, "usb2-strap");
if (IS_ERR(driver->usb2h_strap_reg))
return PTR_ERR(driver->usb2h_strap_reg);
/* create extcon */
driver->id_gpiod = devm_gpiod_get(&pdev->dev, "id", GPIOD_IN);
if (IS_ERR(driver->id_gpiod)) {
dev_err(dev, "failed to get ID GPIO\n");
return PTR_ERR(driver->id_gpiod);
}
driver->vbus_gpiod = devm_gpiod_get(&pdev->dev, "vbus", GPIOD_IN);
if (IS_ERR(driver->vbus_gpiod)) {
dev_err(dev, "failed to get VBUS GPIO\n");
return PTR_ERR(driver->vbus_gpiod);
}
driver->edev = devm_extcon_dev_allocate(dev, usb_extcon_cable);
if (IS_ERR(driver->edev)) {
dev_err(dev, "failed to allocate extcon device\n");
return -ENOMEM;
}
ret = devm_extcon_dev_register(dev, driver->edev);
if (ret < 0) {
dev_err(dev, "failed to register extcon device\n");
return ret;
}
ret = gpiod_set_debounce(driver->id_gpiod, GPIO_DELAY * 1000);
if (ret < 0)
driver->debounce_jiffies = msecs_to_jiffies(GPIO_DELAY);
INIT_DELAYED_WORK(&driver->wq_extcon, extcon_work);
driver->id_irq = gpiod_to_irq(driver->id_gpiod);
if (driver->id_irq < 0) {
dev_err(dev, "failed to get ID IRQ\n");
return driver->id_irq;
}
driver->vbus_irq = gpiod_to_irq(driver->vbus_gpiod);
if (driver->vbus_irq < 0) {
dev_err(dev, "failed to get ID IRQ\n");
return driver->vbus_irq;
}
ret = devm_request_irq(dev, driver->id_irq, gpio_irq_handler,
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
"usb_id", driver);
if (ret < 0) {
dev_err(dev, "failed to request handler for ID IRQ\n");
return ret;
}
ret = devm_request_irq(dev, driver->vbus_irq, gpio_irq_handler,
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
"usb_vbus", driver);
if (ret < 0) {
dev_err(dev, "failed to request handler for VBUS IRQ\n");
return ret;
}
dev_set_drvdata(dev, driver);
/* Shutdown all ports. They can be powered up as required */
val = readl(driver->crmu_usb2_ctrl);
val &= ~(AFE_CORERDY_VDDC | PHY_RESETB);
writel(val, driver->crmu_usb2_ctrl);
data = driver->data;
data->phy = devm_phy_create(dev, dev->of_node, &ops);
if (IS_ERR(data->phy)) {
dev_err(dev, "Failed to create usb drd phy\n");
return PTR_ERR(data->phy);
}
data->driver = driver;
phy_set_drvdata(data->phy, data);
phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
if (IS_ERR(phy_provider)) {
dev_err(dev, "Failed to register as phy provider\n");
return PTR_ERR(phy_provider);
}
platform_set_drvdata(pdev, driver);
dev_info(dev, "Registered NS2 DRD Phy device\n");
queue_delayed_work(system_power_efficient_wq, &driver->wq_extcon,
driver->debounce_jiffies);
return 0;
}