static int palmas_usb_probe(struct platform_device *pdev) { struct palmas *palmas = dev_get_drvdata(pdev->dev.parent); struct palmas_platform_data *pdata; struct palmas_extcon_platform_data *epdata = NULL; struct device_node *node = pdev->dev.of_node; struct palmas_usb *palmas_usb; int status; const char *ext_name = NULL; palmas_usb = devm_kzalloc(&pdev->dev, sizeof(*palmas_usb), GFP_KERNEL); if (!palmas_usb) return -ENOMEM; pdata = dev_get_platdata(pdev->dev.parent); if (pdata) epdata = pdata->extcon_pdata; if (node && !epdata) { palmas_usb->wakeup = of_property_read_bool(node, "ti,wakeup"); palmas_usb->enable_id_detection = of_property_read_bool(node, "ti,enable-id-detection"); palmas_usb->enable_vbus_detection = of_property_read_bool(node, "ti,enable-vbus-detection"); status = of_property_read_string(node, "extcon-name", &ext_name); if (status < 0) ext_name = NULL; } else { palmas_usb->wakeup = true; palmas_usb->enable_id_detection = true; palmas_usb->enable_vbus_detection = true; if (epdata) { palmas_usb->wakeup = epdata->wakeup; palmas_usb->enable_id_detection = epdata->enable_id_pin_detection; palmas_usb->enable_vbus_detection = epdata->enable_vbus_detection; if (palmas_usb->enable_id_detection) palmas_usb->wakeup = true; ext_name = epdata->connection_name; } } palmas_usb->palmas = palmas; palmas_usb->dev = &pdev->dev; palmas_usb->cable_debounce_time = 300; palmas_usb->id_otg_irq = palmas_irq_get_virq(palmas, PALMAS_ID_OTG_IRQ); palmas_usb->id_irq = palmas_irq_get_virq(palmas, PALMAS_ID_IRQ); palmas_usb->vbus_otg_irq = palmas_irq_get_virq(palmas, PALMAS_VBUS_OTG_IRQ); palmas_usb->vbus_irq = palmas_irq_get_virq(palmas, PALMAS_VBUS_IRQ); palmas_usb_wakeup(palmas, palmas_usb->wakeup); platform_set_drvdata(pdev, palmas_usb); palmas_usb->edev.supported_cable = palmas_extcon_cable; palmas_usb->edev.mutually_exclusive = mutually_exclusive; palmas_usb->edev.name = (ext_name) ? ext_name : dev_name(&pdev->dev); status = extcon_dev_register(&palmas_usb->edev, palmas_usb->dev); if (status < 0) { dev_err(&pdev->dev, "failed to register extcon device\n"); return status; } if (palmas_usb->enable_id_detection) { status = devm_request_threaded_irq(palmas_usb->dev, palmas_usb->id_irq, NULL, palmas_id_irq_handler, IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING | IRQF_ONESHOT | IRQF_EARLY_RESUME, "palmas_usb_id", palmas_usb); if (status < 0) { dev_err(&pdev->dev, "can't get IRQ %d, err %d\n", palmas_usb->id_irq, status); goto fail_extcon; } status = devm_request_threaded_irq(palmas_usb->dev, palmas_usb->id_otg_irq, NULL, palmas_id_irq_handler, IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING | IRQF_ONESHOT | IRQF_EARLY_RESUME, "palmas_usb_id-otg", palmas_usb); if (status < 0) { dev_err(&pdev->dev, "can't get IRQ %d, err %d\n", palmas_usb->id_irq, status); goto fail_extcon; } INIT_DELAYED_WORK(&palmas_usb->cable_update_wq, palmas_usb_id_st_wq); } if (palmas_usb->enable_vbus_detection) { status = devm_request_threaded_irq(palmas_usb->dev, palmas_usb->vbus_irq, NULL, palmas_vbus_irq_handler, IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING | IRQF_ONESHOT | IRQF_EARLY_RESUME, "palmas_usb_vbus", palmas_usb); if (status < 0) { dev_err(&pdev->dev, "can't get IRQ %d, err %d\n", palmas_usb->vbus_irq, status); goto fail_extcon; } } palmas_enable_irq(palmas_usb); device_set_wakeup_capable(&pdev->dev, true); return 0; fail_extcon: extcon_dev_unregister(&palmas_usb->edev); if (palmas_usb->enable_id_detection) cancel_delayed_work(&palmas_usb->cable_update_wq); return status; }
static int palmas_usb_probe(struct platform_device *pdev) { struct palmas *palmas = dev_get_drvdata(pdev->dev.parent); struct palmas_usb_platform_data *pdata = dev_get_platdata(&pdev->dev); struct device_node *node = pdev->dev.of_node; struct palmas_usb *palmas_usb; int status; palmas_usb = devm_kzalloc(&pdev->dev, sizeof(*palmas_usb), GFP_KERNEL); if (!palmas_usb) return -ENOMEM; if (node && !pdata) { palmas_usb->wakeup = of_property_read_bool(node, "ti,wakeup"); palmas_usb->enable_id_detection = of_property_read_bool(node, "ti,enable-id-detection"); palmas_usb->enable_vbus_detection = of_property_read_bool(node, "ti,enable-vbus-detection"); } else { palmas_usb->wakeup = true; palmas_usb->enable_id_detection = true; palmas_usb->enable_vbus_detection = true; if (pdata) palmas_usb->wakeup = pdata->wakeup; } palmas->usb = palmas_usb; palmas_usb->palmas = palmas; palmas_usb->dev = &pdev->dev; palmas_usb->id_otg_irq = regmap_irq_get_virq(palmas->irq_data, PALMAS_ID_OTG_IRQ); palmas_usb->id_irq = regmap_irq_get_virq(palmas->irq_data, PALMAS_ID_IRQ); palmas_usb->vbus_otg_irq = regmap_irq_get_virq(palmas->irq_data, PALMAS_VBUS_OTG_IRQ); palmas_usb->vbus_irq = regmap_irq_get_virq(palmas->irq_data, PALMAS_VBUS_IRQ); palmas_usb_wakeup(palmas, palmas_usb->wakeup); platform_set_drvdata(pdev, palmas_usb); palmas_usb->edev.supported_cable = palmas_extcon_cable; palmas_usb->edev.dev.parent = palmas_usb->dev; palmas_usb->edev.name = kstrdup(node->name, GFP_KERNEL); palmas_usb->edev.mutually_exclusive = mutually_exclusive; status = extcon_dev_register(&palmas_usb->edev); if (status) { dev_err(&pdev->dev, "failed to register extcon device\n"); kfree(palmas_usb->edev.name); return status; } if (palmas_usb->enable_id_detection) { status = devm_request_threaded_irq(palmas_usb->dev, palmas_usb->id_irq, NULL, palmas_id_irq_handler, IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING | IRQF_ONESHOT | IRQF_EARLY_RESUME, "palmas_usb_id", palmas_usb); if (status < 0) { dev_err(&pdev->dev, "can't get IRQ %d, err %d\n", palmas_usb->id_irq, status); goto fail_extcon; } } if (palmas_usb->enable_vbus_detection) { status = devm_request_threaded_irq(palmas_usb->dev, palmas_usb->vbus_irq, NULL, palmas_vbus_irq_handler, IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING | IRQF_ONESHOT | IRQF_EARLY_RESUME, "palmas_usb_vbus", palmas_usb); if (status < 0) { dev_err(&pdev->dev, "can't get IRQ %d, err %d\n", palmas_usb->vbus_irq, status); goto fail_extcon; } } palmas_enable_irq(palmas_usb); device_set_wakeup_capable(&pdev->dev, true); return 0; fail_extcon: extcon_dev_unregister(&palmas_usb->edev); kfree(palmas_usb->edev.name); return status; }
static int __devinit palmas_usb_probe(struct platform_device *pdev) { struct palmas_usb *palmas_usb; int status; struct palmas_platform_data *pdata; struct palmas *palmas; palmas = dev_get_drvdata(pdev->dev.parent); pdata = palmas->dev->platform_data; palmas_usb = kzalloc(sizeof(*palmas_usb), GFP_KERNEL); if (!palmas_usb) return -ENOMEM; palmas->usb = palmas_usb; palmas_usb->palmas = palmas; palmas_usb->dev = &pdev->dev; palmas_usb->irq1 = platform_get_irq(pdev, 0); palmas_usb->irq2 = platform_get_irq(pdev, 1); palmas_usb->irq3 = platform_get_irq(pdev, 2); palmas_usb->irq4 = platform_get_irq(pdev, 3); palmas_usb_wakeup(palmas, pdata->usb_pdata->wakeup); /* init spinlock for workqueue */ spin_lock_init(&palmas_usb->lock); if (!pdata->usb_pdata->no_control_vbus) { palmas_usb->vbus_reg = regulator_get(palmas->dev, "vbus"); if (IS_ERR(palmas_usb->vbus_reg)) { dev_err(&pdev->dev, "vbus init failed\n"); kfree(palmas_usb); return PTR_ERR(palmas_usb->vbus_reg); } } platform_set_drvdata(pdev, palmas_usb); if (device_create_file(&pdev->dev, &dev_attr_vbus)) dev_warn(&pdev->dev, "could not create sysfs file\n"); /* init spinlock for workqueue */ spin_lock_init(&palmas_usb->lock); INIT_WORK(&palmas_usb->set_vbus_work, palmas_set_vbus_work); status = request_threaded_irq(palmas_usb->irq1, NULL, palmas_id_irq, IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, "palmas_usb", palmas_usb); if (status < 0) { dev_err(&pdev->dev, "can't get IRQ %d, err %d\n", palmas_usb->irq1, status); goto fail_irq1; } status = request_threaded_irq(palmas_usb->irq2, NULL, palmas_id_wakeup_irq, IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, "palmas_usb", palmas_usb); if (status < 0) { dev_err(&pdev->dev, "can't get IRQ %d, err %d\n", palmas_usb->irq2, status); goto fail_irq2; } status = request_threaded_irq(palmas_usb->irq3, NULL, palmas_vbus_irq, IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, "palmas_usb", palmas_usb); if (status < 0) { dev_err(&pdev->dev, "can't get IRQ %d, err %d\n", palmas_usb->irq3, status); goto fail_irq3; } status = request_threaded_irq(palmas_usb->irq4, NULL, palmas_vbus_wakeup_irq, IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, "palmas_usb", palmas_usb); if (status < 0) { dev_err(&pdev->dev, "can't get IRQ %d, err %d\n", palmas_usb->irq4, status); goto fail_irq4; } dev_info(&pdev->dev, "Initialized Palmas USB module\n"); palmas_enable_irq(palmas_usb); return 0; fail_irq4: free_irq(palmas_usb->irq3, palmas_usb); fail_irq3: free_irq(palmas_usb->irq2, palmas_usb); fail_irq2: free_irq(palmas_usb->irq1, palmas_usb); fail_irq1: cancel_work_sync(&palmas_usb->set_vbus_work); device_remove_file(palmas_usb->dev, &dev_attr_vbus); kfree(palmas_usb); return status; }
static int palmas_usb_probe(struct platform_device *pdev) { struct palmas *palmas = dev_get_drvdata(pdev->dev.parent); struct palmas_usb_platform_data *pdata = dev_get_platdata(&pdev->dev); struct device_node *node = pdev->dev.of_node; struct palmas_usb *palmas_usb; int status; palmas_usb = devm_kzalloc(&pdev->dev, sizeof(*palmas_usb), GFP_KERNEL); if (!palmas_usb) return -ENOMEM; if (node && !pdata) { palmas_usb->wakeup = of_property_read_bool(node, "ti,wakeup"); palmas_usb->enable_id_detection = of_property_read_bool(node, "ti,enable-id-detection"); palmas_usb->enable_vbus_detection = of_property_read_bool(node, "ti,enable-vbus-detection"); } else { palmas_usb->wakeup = true; palmas_usb->enable_id_detection = true; palmas_usb->enable_vbus_detection = true; if (pdata) palmas_usb->wakeup = pdata->wakeup; } palmas_usb->id_gpiod = devm_gpiod_get_optional(&pdev->dev, "id", GPIOD_IN); if (IS_ERR(palmas_usb->id_gpiod)) { dev_err(&pdev->dev, "failed to get id gpio\n"); return PTR_ERR(palmas_usb->id_gpiod); } palmas_usb->vbus_gpiod = devm_gpiod_get_optional(&pdev->dev, "vbus", GPIOD_IN); if (IS_ERR(palmas_usb->vbus_gpiod)) { dev_err(&pdev->dev, "failed to get vbus gpio\n"); return PTR_ERR(palmas_usb->vbus_gpiod); } if (palmas_usb->enable_id_detection && palmas_usb->id_gpiod) { palmas_usb->enable_id_detection = false; palmas_usb->enable_gpio_id_detection = true; } if (palmas_usb->enable_vbus_detection && palmas_usb->vbus_gpiod) { palmas_usb->enable_vbus_detection = false; palmas_usb->enable_gpio_vbus_detection = true; } if (palmas_usb->enable_gpio_id_detection) { u32 debounce; if (of_property_read_u32(node, "debounce-delay-ms", &debounce)) debounce = USB_GPIO_DEBOUNCE_MS; status = gpiod_set_debounce(palmas_usb->id_gpiod, debounce * 1000); if (status < 0) palmas_usb->sw_debounce_jiffies = msecs_to_jiffies(debounce); } INIT_DELAYED_WORK(&palmas_usb->wq_detectid, palmas_gpio_id_detect); palmas->usb = palmas_usb; palmas_usb->palmas = palmas; palmas_usb->dev = &pdev->dev; palmas_usb_wakeup(palmas, palmas_usb->wakeup); platform_set_drvdata(pdev, palmas_usb); palmas_usb->edev = devm_extcon_dev_allocate(&pdev->dev, palmas_extcon_cable); if (IS_ERR(palmas_usb->edev)) { dev_err(&pdev->dev, "failed to allocate extcon device\n"); return -ENOMEM; } status = devm_extcon_dev_register(&pdev->dev, palmas_usb->edev); if (status) { dev_err(&pdev->dev, "failed to register extcon device\n"); return status; } if (palmas_usb->enable_id_detection) { palmas_usb->id_otg_irq = regmap_irq_get_virq(palmas->irq_data, PALMAS_ID_OTG_IRQ); palmas_usb->id_irq = regmap_irq_get_virq(palmas->irq_data, PALMAS_ID_IRQ); status = devm_request_threaded_irq(palmas_usb->dev, palmas_usb->id_irq, NULL, palmas_id_irq_handler, IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING | IRQF_ONESHOT, "palmas_usb_id", palmas_usb); if (status < 0) { dev_err(&pdev->dev, "can't get IRQ %d, err %d\n", palmas_usb->id_irq, status); return status; } } else if (palmas_usb->enable_gpio_id_detection) { palmas_usb->gpio_id_irq = gpiod_to_irq(palmas_usb->id_gpiod); if (palmas_usb->gpio_id_irq < 0) { dev_err(&pdev->dev, "failed to get id irq\n"); return palmas_usb->gpio_id_irq; } status = devm_request_threaded_irq(&pdev->dev, palmas_usb->gpio_id_irq, NULL, palmas_gpio_id_irq_handler, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, "palmas_usb_id", palmas_usb); if (status < 0) { dev_err(&pdev->dev, "failed to request handler for id irq\n"); return status; } } if (palmas_usb->enable_vbus_detection) { palmas_usb->vbus_otg_irq = regmap_irq_get_virq(palmas->irq_data, PALMAS_VBUS_OTG_IRQ); palmas_usb->vbus_irq = regmap_irq_get_virq(palmas->irq_data, PALMAS_VBUS_IRQ); status = devm_request_threaded_irq(palmas_usb->dev, palmas_usb->vbus_irq, NULL, palmas_vbus_irq_handler, IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING | IRQF_ONESHOT, "palmas_usb_vbus", palmas_usb); if (status < 0) { dev_err(&pdev->dev, "can't get IRQ %d, err %d\n", palmas_usb->vbus_irq, status); return status; } } else if (palmas_usb->enable_gpio_vbus_detection) { /* remux GPIO_1 as VBUSDET */ status = palmas_update_bits(palmas, PALMAS_PU_PD_OD_BASE, PALMAS_PRIMARY_SECONDARY_PAD1, PALMAS_PRIMARY_SECONDARY_PAD1_GPIO_1_MASK, (1 << PALMAS_PRIMARY_SECONDARY_PAD1_GPIO_1_SHIFT)); if (status < 0) { dev_err(&pdev->dev, "can't remux GPIO1\n"); return status; } palmas_usb->vbus_otg_irq = regmap_irq_get_virq(palmas->irq_data, PALMAS_VBUS_OTG_IRQ); palmas_usb->gpio_vbus_irq = gpiod_to_irq(palmas_usb->vbus_gpiod); if (palmas_usb->gpio_vbus_irq < 0) { dev_err(&pdev->dev, "failed to get vbus irq\n"); return palmas_usb->gpio_vbus_irq; } status = devm_request_threaded_irq(&pdev->dev, palmas_usb->gpio_vbus_irq, NULL, palmas_vbus_irq_handler, IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING | IRQF_ONESHOT, "palmas_usb_vbus", palmas_usb); if (status < 0) { dev_err(&pdev->dev, "failed to request handler for vbus irq\n"); return status; } } palmas_enable_irq(palmas_usb); /* perform initial detection */ if (palmas_usb->enable_gpio_vbus_detection) palmas_vbus_irq_handler(palmas_usb->gpio_vbus_irq, palmas_usb); palmas_gpio_id_detect(&palmas_usb->wq_detectid.work); device_set_wakeup_capable(&pdev->dev, true); return 0; }