static int dwc3_omap_extcon_register(struct dwc3_omap *omap) { int ret; struct device_node *node = omap->dev->of_node; struct extcon_dev *edev; if (of_property_read_bool(node, "extcon")) { edev = extcon_get_edev_by_phandle(omap->dev, 0); if (IS_ERR(edev)) { dev_vdbg(omap->dev, "couldn't get extcon device\n"); return -EPROBE_DEFER; } omap->vbus_nb.notifier_call = dwc3_omap_vbus_notifier; ret = extcon_register_notifier(edev, EXTCON_USB, &omap->vbus_nb); if (ret < 0) dev_vdbg(omap->dev, "failed to register notifier for USB\n"); omap->id_nb.notifier_call = dwc3_omap_id_notifier; ret = extcon_register_notifier(edev, EXTCON_USB_HOST, &omap->id_nb); if (ret < 0) dev_vdbg(omap->dev, "failed to register notifier for USB-HOST\n"); if (extcon_get_cable_state_(edev, EXTCON_USB) == true) dwc3_omap_set_mailbox(omap, OMAP_DWC3_VBUS_VALID); if (extcon_get_cable_state_(edev, EXTCON_USB_HOST) == true) dwc3_omap_set_mailbox(omap, OMAP_DWC3_ID_GROUND); omap->edev = edev; } return 0; }
static int msm_otg_read_dt(struct platform_device *pdev, struct msm_otg *motg) { struct msm_otg_platform_data *pdata; struct extcon_dev *ext_id, *ext_vbus; struct device_node *node = pdev->dev.of_node; struct property *prop; int len, ret, words; u32 val, tmp[3]; pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); if (!pdata) return -ENOMEM; motg->pdata = pdata; pdata->phy_type = (enum msm_usb_phy_type)of_device_get_match_data(&pdev->dev); if (!pdata->phy_type) return 1; motg->link_rst = devm_reset_control_get(&pdev->dev, "link"); if (IS_ERR(motg->link_rst)) return PTR_ERR(motg->link_rst); motg->phy_rst = devm_reset_control_get(&pdev->dev, "phy"); if (IS_ERR(motg->phy_rst)) motg->phy_rst = NULL; pdata->mode = usb_get_dr_mode(&pdev->dev); if (pdata->mode == USB_DR_MODE_UNKNOWN) pdata->mode = USB_DR_MODE_OTG; pdata->otg_control = OTG_PHY_CONTROL; if (!of_property_read_u32(node, "qcom,otg-control", &val)) if (val == OTG_PMIC_CONTROL) pdata->otg_control = val; if (!of_property_read_u32(node, "qcom,phy-num", &val) && val < 2) motg->phy_number = val; motg->vdd_levels[VDD_LEVEL_NONE] = USB_PHY_SUSP_DIG_VOL; motg->vdd_levels[VDD_LEVEL_MIN] = USB_PHY_VDD_DIG_VOL_MIN; motg->vdd_levels[VDD_LEVEL_MAX] = USB_PHY_VDD_DIG_VOL_MAX; if (of_get_property(node, "qcom,vdd-levels", &len) && len == sizeof(tmp)) { of_property_read_u32_array(node, "qcom,vdd-levels", tmp, len / sizeof(*tmp)); motg->vdd_levels[VDD_LEVEL_NONE] = tmp[VDD_LEVEL_NONE]; motg->vdd_levels[VDD_LEVEL_MIN] = tmp[VDD_LEVEL_MIN]; motg->vdd_levels[VDD_LEVEL_MAX] = tmp[VDD_LEVEL_MAX]; } motg->manual_pullup = of_property_read_bool(node, "qcom,manual-pullup"); motg->switch_gpio = devm_gpiod_get_optional(&pdev->dev, "switch", GPIOD_OUT_LOW); if (IS_ERR(motg->switch_gpio)) return PTR_ERR(motg->switch_gpio); ext_id = ERR_PTR(-ENODEV); ext_vbus = ERR_PTR(-ENODEV); if (of_property_read_bool(node, "extcon")) { /* Each one of them is not mandatory */ ext_vbus = extcon_get_edev_by_phandle(&pdev->dev, 0); if (IS_ERR(ext_vbus) && PTR_ERR(ext_vbus) != -ENODEV) return PTR_ERR(ext_vbus); ext_id = extcon_get_edev_by_phandle(&pdev->dev, 1); if (IS_ERR(ext_id) && PTR_ERR(ext_id) != -ENODEV) return PTR_ERR(ext_id); } if (!IS_ERR(ext_vbus)) { motg->vbus.extcon = ext_vbus; motg->vbus.nb.notifier_call = msm_otg_vbus_notifier; ret = extcon_register_notifier(ext_vbus, EXTCON_USB, &motg->vbus.nb); if (ret < 0) { dev_err(&pdev->dev, "register VBUS notifier failed\n"); return ret; } ret = extcon_get_cable_state_(ext_vbus, EXTCON_USB); if (ret) set_bit(B_SESS_VLD, &motg->inputs); else clear_bit(B_SESS_VLD, &motg->inputs); } if (!IS_ERR(ext_id)) { motg->id.extcon = ext_id; motg->id.nb.notifier_call = msm_otg_id_notifier; ret = extcon_register_notifier(ext_id, EXTCON_USB_HOST, &motg->id.nb); if (ret < 0) { dev_err(&pdev->dev, "register ID notifier failed\n"); extcon_unregister_notifier(motg->vbus.extcon, EXTCON_USB, &motg->vbus.nb); return ret; } ret = extcon_get_cable_state_(ext_id, EXTCON_USB_HOST); if (ret) clear_bit(ID, &motg->inputs); else set_bit(ID, &motg->inputs); } prop = of_find_property(node, "qcom,phy-init-sequence", &len); if (!prop || !len) return 0; words = len / sizeof(u32); if (words >= ULPI_EXT_VENDOR_SPECIFIC) { dev_warn(&pdev->dev, "Too big PHY init sequence %d\n", words); return 0; } pdata->phy_init_seq = devm_kzalloc(&pdev->dev, len, GFP_KERNEL); if (!pdata->phy_init_seq) return 0; ret = of_property_read_u32_array(node, "qcom,phy-init-sequence", pdata->phy_init_seq, words); if (!ret) pdata->phy_init_sz = words; return 0; }
static int usbhs_probe(struct platform_device *pdev) { struct renesas_usbhs_platform_info *info = dev_get_platdata(&pdev->dev); struct renesas_usbhs_driver_callback *dfunc; struct usbhs_priv *priv; struct resource *res, *irq_res; int ret; /* check device node */ if (pdev->dev.of_node) info = pdev->dev.platform_data = usbhs_parse_dt(&pdev->dev); /* check platform information */ if (!info) { dev_err(&pdev->dev, "no platform information\n"); return -EINVAL; } /* platform data */ irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (!irq_res) { dev_err(&pdev->dev, "Not enough Renesas USB platform resources.\n"); return -ENODEV; } /* usb private data */ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); priv->base = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(priv->base)) return PTR_ERR(priv->base); if (of_property_read_bool(pdev->dev.of_node, "extcon")) { priv->edev = extcon_get_edev_by_phandle(&pdev->dev, 0); if (IS_ERR(priv->edev)) return PTR_ERR(priv->edev); } /* * care platform info */ memcpy(&priv->dparam, &info->driver_param, sizeof(struct renesas_usbhs_driver_param)); switch (priv->dparam.type) { case USBHS_TYPE_RCAR_GEN2: priv->pfunc = usbhs_rcar2_ops; if (!priv->dparam.pipe_type) { priv->dparam.pipe_type = usbhsc_new_pipe_type; priv->dparam.pipe_size = ARRAY_SIZE(usbhsc_new_pipe_type); } break; default: if (!info->platform_callback.get_id) { dev_err(&pdev->dev, "no platform callbacks"); return -EINVAL; } memcpy(&priv->pfunc, &info->platform_callback, sizeof(struct renesas_usbhs_platform_callback)); break; } /* set driver callback functions for platform */ dfunc = &info->driver_callback; dfunc->notify_hotplug = usbhsc_drvcllbck_notify_hotplug; /* set default param if platform doesn't have */ if (!priv->dparam.pipe_type) { priv->dparam.pipe_type = usbhsc_default_pipe_type; priv->dparam.pipe_size = ARRAY_SIZE(usbhsc_default_pipe_type); } if (!priv->dparam.pio_dma_border) priv->dparam.pio_dma_border = 64; /* 64byte */ /* FIXME */ /* runtime power control ? */ if (priv->pfunc.get_vbus) usbhsc_flags_set(priv, USBHSF_RUNTIME_PWCTRL); /* * priv settings */ priv->irq = irq_res->start; if (irq_res->flags & IORESOURCE_IRQ_SHAREABLE) priv->irqflags = IRQF_SHARED; priv->pdev = pdev; INIT_DELAYED_WORK(&priv->notify_hotplug_work, usbhsc_notify_hotplug); spin_lock_init(usbhs_priv_to_lock(priv)); /* call pipe and module init */ ret = usbhs_pipe_probe(priv); if (ret < 0) return ret; ret = usbhs_fifo_probe(priv); if (ret < 0) goto probe_end_pipe_exit; ret = usbhs_mod_probe(priv); if (ret < 0) goto probe_end_fifo_exit; /* dev_set_drvdata should be called after usbhs_mod_init */ platform_set_drvdata(pdev, priv); /* * deviece reset here because * USB device might be used in boot loader. */ usbhs_sys_clock_ctrl(priv, 0); /* check GPIO determining if USB function should be enabled */ if (priv->dparam.enable_gpio) { gpio_request_one(priv->dparam.enable_gpio, GPIOF_IN, NULL); ret = !gpio_get_value(priv->dparam.enable_gpio); gpio_free(priv->dparam.enable_gpio); if (ret) { dev_warn(&pdev->dev, "USB function not selected (GPIO %d)\n", priv->dparam.enable_gpio); ret = -ENOTSUPP; goto probe_end_mod_exit; } } /* * platform call * * USB phy setup might depend on CPU/Board. * If platform has its callback functions, * call it here. */ ret = usbhs_platform_call(priv, hardware_init, pdev); if (ret < 0) { dev_err(&pdev->dev, "platform init failed.\n"); goto probe_end_mod_exit; } /* reset phy for connection */ usbhs_platform_call(priv, phy_reset, pdev); /* power control */ pm_runtime_enable(&pdev->dev); if (!usbhsc_flags_has(priv, USBHSF_RUNTIME_PWCTRL)) { usbhsc_power_ctrl(priv, 1); usbhs_mod_autonomy_mode(priv); } /* * manual call notify_hotplug for cold plug */ usbhsc_drvcllbck_notify_hotplug(pdev); dev_info(&pdev->dev, "probed\n"); return ret; probe_end_mod_exit: usbhs_mod_remove(priv); probe_end_fifo_exit: usbhs_fifo_remove(priv); probe_end_pipe_exit: usbhs_pipe_remove(priv); dev_info(&pdev->dev, "probe failed\n"); return ret; }
static int qcom_usb_hs_phy_probe(struct ulpi *ulpi) { struct qcom_usb_hs_phy *uphy; struct phy_provider *p; struct clk *clk; struct regulator *reg; struct reset_control *reset; int size; int ret; uphy = devm_kzalloc(&ulpi->dev, sizeof(*uphy), GFP_KERNEL); if (!uphy) return -ENOMEM; ulpi_set_drvdata(ulpi, uphy); uphy->ulpi = ulpi; size = of_property_count_u8_elems(ulpi->dev.of_node, "qcom,init-seq"); if (size < 0) size = 0; uphy->init_seq = devm_kmalloc_array(&ulpi->dev, (size / 2) + 1, sizeof(*uphy->init_seq), GFP_KERNEL); if (!uphy->init_seq) return -ENOMEM; ret = of_property_read_u8_array(ulpi->dev.of_node, "qcom,init-seq", (u8 *)uphy->init_seq, size); if (ret && size) return ret; /* NUL terminate */ uphy->init_seq[size / 2].addr = uphy->init_seq[size / 2].val = 0; uphy->ref_clk = clk = devm_clk_get(&ulpi->dev, "ref"); if (IS_ERR(clk)) return PTR_ERR(clk); uphy->sleep_clk = clk = devm_clk_get(&ulpi->dev, "sleep"); if (IS_ERR(clk)) return PTR_ERR(clk); uphy->v1p8 = reg = devm_regulator_get(&ulpi->dev, "v1p8"); if (IS_ERR(reg)) return PTR_ERR(reg); uphy->v3p3 = reg = devm_regulator_get(&ulpi->dev, "v3p3"); if (IS_ERR(reg)) return PTR_ERR(reg); uphy->reset = reset = devm_reset_control_get(&ulpi->dev, "por"); if (IS_ERR(reset)) { if (PTR_ERR(reset) == -EPROBE_DEFER) return PTR_ERR(reset); uphy->reset = NULL; } uphy->phy = devm_phy_create(&ulpi->dev, ulpi->dev.of_node, &qcom_usb_hs_phy_ops); if (IS_ERR(uphy->phy)) return PTR_ERR(uphy->phy); uphy->vbus_edev = extcon_get_edev_by_phandle(&ulpi->dev, 0); if (IS_ERR(uphy->vbus_edev)) { if (PTR_ERR(uphy->vbus_edev) != -ENODEV) return PTR_ERR(uphy->vbus_edev); uphy->vbus_edev = NULL; } uphy->vbus_notify.notifier_call = qcom_usb_hs_phy_vbus_notifier; phy_set_drvdata(uphy->phy, uphy); p = devm_of_phy_provider_register(&ulpi->dev, of_phy_simple_xlate); return PTR_ERR_OR_ZERO(p); }
static struct jack_platform_data *extcon_port_dt_parse(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; struct jack_platform_data *pdata; const struct extcon_dev *edev; pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); if (!pdata) { dev_err(&pdev->dev, "Failed to allocate memory\n"); return NULL; } edev = extcon_get_edev_by_phandle(&pdev->dev, 0); if (IS_ERR(edev)) dev_warn(&pdev->dev, "Failed to get extcon dev for muic from DT\n"); else { dev_info(&pdev->dev, "Using extcon for muic device: %s\n", edev->name); pdata->extcon_name_muic = edev->name; } edev = extcon_get_edev_by_phandle(&pdev->dev, 1); if (IS_ERR(edev)) dev_warn(&pdev->dev, "Failed to get extcon dev for jack from DT\n"); else { dev_info(&pdev->dev, "Using extcon for jack device: %s\n", edev->name); pdata->extcon_name_jack = edev->name; } edev = extcon_get_edev_by_phandle(&pdev->dev, 2); if (IS_ERR(edev)) dev_warn(&pdev->dev, "Failed to get extcon dev for hdmi from DT\n"); else { dev_info(&pdev->dev, "Using extcon for hdmi device: %s\n", edev->name); pdata->extcon_name_hdmi = edev->name; } if (!of_property_read_bool(np, "samsung,extcon-online-usb")) pdata->usb_online = -1; if (!of_property_read_bool(np, "samsung,extcon-online-charger")) pdata->charger_online = -1; if (!of_property_read_bool(np, "samsung,extcon-online-hdmi")) pdata->hdmi_online = -1; if (!of_property_read_bool(np, "samsung,extcon-online-earjack")) pdata->earjack_online = -1; if (!of_property_read_bool(np, "samsung,extcon-online-earkey")) pdata->earkey_online = -1; if (!of_property_read_bool(np, "samsung,extcon-online-ums")) pdata->ums_online = -1; if (!of_property_read_bool(np, "samsung,extcon-online-cdrom")) pdata->cdrom_online = -1; if (!of_property_read_bool(np, "samsung,extcon-online-jig")) pdata->jig_online = -1; if (!of_property_read_bool(np, "samsung,extcon-online-host")) pdata->host_online = -1; if (!of_property_read_bool(np, "samsung,extcon-online-cradle")) pdata->cradle_online = -1; return pdata; }
static int get_ssusb_rscs(struct platform_device *pdev, struct ssusb_mtk *ssusb) { struct device_node *node = pdev->dev.of_node; struct otg_switch_mtk *otg_sx = &ssusb->otg_switch; struct device *dev = &pdev->dev; struct regulator *vbus; struct resource *res; int i; int ret; ssusb->vusb33 = devm_regulator_get(&pdev->dev, "vusb33"); if (IS_ERR(ssusb->vusb33)) { dev_err(dev, "failed to get vusb33\n"); return PTR_ERR(ssusb->vusb33); } ssusb->sys_clk = devm_clk_get(dev, "sys_ck"); if (IS_ERR(ssusb->sys_clk)) { dev_err(dev, "failed to get sys clock\n"); return PTR_ERR(ssusb->sys_clk); } ssusb->ref_clk = get_optional_clk(dev, "ref_ck"); if (IS_ERR(ssusb->ref_clk)) return PTR_ERR(ssusb->ref_clk); ssusb->mcu_clk = get_optional_clk(dev, "mcu_ck"); if (IS_ERR(ssusb->mcu_clk)) return PTR_ERR(ssusb->mcu_clk); ssusb->dma_clk = get_optional_clk(dev, "dma_ck"); if (IS_ERR(ssusb->dma_clk)) return PTR_ERR(ssusb->dma_clk); ssusb->num_phys = of_count_phandle_with_args(node, "phys", "#phy-cells"); if (ssusb->num_phys > 0) { ssusb->phys = devm_kcalloc(dev, ssusb->num_phys, sizeof(*ssusb->phys), GFP_KERNEL); if (!ssusb->phys) return -ENOMEM; } else { ssusb->num_phys = 0; } for (i = 0; i < ssusb->num_phys; i++) { ssusb->phys[i] = devm_of_phy_get_by_index(dev, node, i); if (IS_ERR(ssusb->phys[i])) { dev_err(dev, "failed to get phy-%d\n", i); return PTR_ERR(ssusb->phys[i]); } } res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ippc"); ssusb->ippc_base = devm_ioremap_resource(dev, res); if (IS_ERR(ssusb->ippc_base)) return PTR_ERR(ssusb->ippc_base); ssusb->dr_mode = usb_get_dr_mode(dev); if (ssusb->dr_mode == USB_DR_MODE_UNKNOWN) ssusb->dr_mode = USB_DR_MODE_OTG; if (ssusb->dr_mode == USB_DR_MODE_PERIPHERAL) return 0; /* if host role is supported */ ret = ssusb_wakeup_of_property_parse(ssusb, node); if (ret) { dev_err(dev, "failed to parse uwk property\n"); return ret; } /* optional property, ignore the error if it does not exist */ of_property_read_u32(node, "mediatek,u3p-dis-msk", &ssusb->u3p_dis_msk); vbus = devm_regulator_get(&pdev->dev, "vbus"); if (IS_ERR(vbus)) { dev_err(dev, "failed to get vbus\n"); return PTR_ERR(vbus); } otg_sx->vbus = vbus; if (ssusb->dr_mode == USB_DR_MODE_HOST) return 0; /* if dual-role mode is supported */ otg_sx->is_u3_drd = of_property_read_bool(node, "mediatek,usb3-drd"); otg_sx->manual_drd_enabled = of_property_read_bool(node, "enable-manual-drd"); if (of_property_read_bool(node, "extcon")) { otg_sx->edev = extcon_get_edev_by_phandle(ssusb->dev, 0); if (IS_ERR(otg_sx->edev)) { dev_err(ssusb->dev, "couldn't get extcon device\n"); return PTR_ERR(otg_sx->edev); } } dev_info(dev, "dr_mode: %d, is_u3_dr: %d, u3p_dis_msk: %x, drd: %s\n", ssusb->dr_mode, otg_sx->is_u3_drd, ssusb->u3p_dis_msk, otg_sx->manual_drd_enabled ? "manual" : "auto"); return 0; }