static int __devinit isp1704_charger_probe(struct platform_device *pdev) { struct isp1704_charger *isp; int ret = -ENODEV; isp = kzalloc(sizeof *isp, GFP_KERNEL); if (!isp) return -ENOMEM; isp->otg = otg_get_transceiver(); if (!isp->otg) goto fail0; ret = isp1704_test_ulpi(isp); if (ret < 0) goto fail1; isp->dev = &pdev->dev; platform_set_drvdata(pdev, isp); isp->psy.name = "isp1704"; isp->psy.type = POWER_SUPPLY_TYPE_USB; isp->psy.properties = power_props; isp->psy.num_properties = ARRAY_SIZE(power_props); isp->psy.get_property = isp1704_charger_get_property; ret = power_supply_register(isp->dev, &isp->psy); if (ret) goto fail1; /* * REVISIT: using work in order to allow the otg notifications to be * made atomically in the future. */ INIT_WORK(&isp->work, isp1704_charger_work); isp->nb.notifier_call = isp1704_notifier_call; ret = otg_register_notifier(isp->otg, &isp->nb); if (ret) goto fail2; dev_info(isp->dev, "registered with product id %s\n", isp->model); return 0; fail2: power_supply_unregister(&isp->psy); fail1: otg_put_transceiver(isp->otg); fail0: kfree(isp); dev_err(&pdev->dev, "failed to register isp1704 with error %d\n", ret); return ret; }
static int isp1704_charger_probe(struct platform_device *pdev) { struct isp1704_charger *isp; int ret = -ENODEV; struct power_supply_config psy_cfg = {}; struct isp1704_charger_data *pdata = dev_get_platdata(&pdev->dev); struct device_node *np = pdev->dev.of_node; if (np) { int gpio = of_get_named_gpio(np, "nxp,enable-gpio", 0); if (gpio < 0) { dev_err(&pdev->dev, "missing DT GPIO nxp,enable-gpio\n"); return gpio; } pdata = devm_kzalloc(&pdev->dev, sizeof(struct isp1704_charger_data), GFP_KERNEL); if (!pdata) { ret = -ENOMEM; goto fail0; } pdata->enable_gpio = gpio; dev_info(&pdev->dev, "init gpio %d\n", pdata->enable_gpio); ret = devm_gpio_request_one(&pdev->dev, pdata->enable_gpio, GPIOF_OUT_INIT_HIGH, "isp1704_reset"); if (ret) { dev_err(&pdev->dev, "gpio request failed\n"); goto fail0; } } if (!pdata) { dev_err(&pdev->dev, "missing platform data!\n"); return -ENODEV; } isp = devm_kzalloc(&pdev->dev, sizeof(*isp), GFP_KERNEL); if (!isp) return -ENOMEM; if (np) isp->phy = devm_usb_get_phy_by_phandle(&pdev->dev, "usb-phy", 0); else isp->phy = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2); if (IS_ERR(isp->phy)) { ret = PTR_ERR(isp->phy); dev_err(&pdev->dev, "usb_get_phy failed\n"); goto fail0; } isp->dev = &pdev->dev; platform_set_drvdata(pdev, isp); isp1704_charger_set_power(isp, 1); ret = isp1704_test_ulpi(isp); if (ret < 0) { dev_err(&pdev->dev, "isp1704_test_ulpi failed\n"); goto fail1; } isp->psy_desc.name = "isp1704"; isp->psy_desc.type = POWER_SUPPLY_TYPE_USB; isp->psy_desc.properties = power_props; isp->psy_desc.num_properties = ARRAY_SIZE(power_props); isp->psy_desc.get_property = isp1704_charger_get_property; psy_cfg.drv_data = isp; isp->psy = power_supply_register(isp->dev, &isp->psy_desc, &psy_cfg); if (IS_ERR(isp->psy)) { ret = PTR_ERR(isp->psy); dev_err(&pdev->dev, "power_supply_register failed\n"); goto fail1; } /* * REVISIT: using work in order to allow the usb notifications to be * made atomically in the future. */ INIT_WORK(&isp->work, isp1704_charger_work); isp->nb.notifier_call = isp1704_notifier_call; ret = usb_register_notifier(isp->phy, &isp->nb); if (ret) { dev_err(&pdev->dev, "usb_register_notifier failed\n"); goto fail2; } dev_info(isp->dev, "registered with product id %s\n", isp->model); /* * Taking over the D+ pullup. * * FIXME: The device will be disconnected if it was already * enumerated. The charger driver should be always loaded before any * gadget is loaded. */ if (isp->phy->otg->gadget) usb_gadget_disconnect(isp->phy->otg->gadget); if (isp->phy->last_event == USB_EVENT_NONE) isp1704_charger_set_power(isp, 0); /* Detect charger if VBUS is valid (the cable was already plugged). */ if (isp->phy->last_event == USB_EVENT_VBUS && !isp->phy->otg->default_a) schedule_work(&isp->work); return 0; fail2: power_supply_unregister(isp->psy); fail1: isp1704_charger_set_power(isp, 0); fail0: dev_err(&pdev->dev, "failed to register isp1704 with error %d\n", ret); return ret; }
static int __devinit isp1704_charger_probe(struct platform_device *pdev) { struct isp1704_charger *isp; int ret = -ENODEV; isp = kzalloc(sizeof *isp, GFP_KERNEL); if (!isp) return -ENOMEM; isp->phy = usb_get_phy(); if (!isp->phy) goto fail0; isp->dev = &pdev->dev; platform_set_drvdata(pdev, isp); isp1704_charger_set_power(isp, 1); ret = isp1704_test_ulpi(isp); if (ret < 0) goto fail1; isp->psy.name = "isp1704"; isp->psy.type = POWER_SUPPLY_TYPE_USB; isp->psy.properties = power_props; isp->psy.num_properties = ARRAY_SIZE(power_props); isp->psy.get_property = isp1704_charger_get_property; ret = power_supply_register(isp->dev, &isp->psy); if (ret) goto fail1; /* * REVISIT: using work in order to allow the usb notifications to be * made atomically in the future. */ INIT_WORK(&isp->work, isp1704_charger_work); isp->nb.notifier_call = isp1704_notifier_call; ret = usb_register_notifier(isp->phy, &isp->nb); if (ret) goto fail2; dev_info(isp->dev, "registered with product id %s\n", isp->model); /* * Taking over the D+ pullup. * * FIXME: The device will be disconnected if it was already * enumerated. The charger driver should be always loaded before any * gadget is loaded. */ if (isp->phy->otg->gadget) usb_gadget_disconnect(isp->phy->otg->gadget); /* Detect charger if VBUS is valid (the cable was already plugged). */ ret = isp1704_read(isp, ULPI_USB_INT_STS); isp1704_charger_set_power(isp, 0); if ((ret & ULPI_INT_VBUS_VALID) && !isp->phy->otg->default_a) { isp->event = USB_EVENT_VBUS; schedule_work(&isp->work); } return 0; fail2: power_supply_unregister(&isp->psy); fail1: usb_put_phy(isp->phy); fail0: kfree(isp); dev_err(&pdev->dev, "failed to register isp1704 with error %d\n", ret); isp1704_charger_set_power(isp, 0); return ret; }