static int arizona_map_irq(struct arizona *arizona, int irq) { int ret; ret = regmap_irq_get_virq(arizona->aod_irq_chip, irq); if (ret < 0) ret = regmap_irq_get_virq(arizona->irq_chip, irq); return ret; }
static int wm8994_gpio_to_irq(struct gpio_chip *chip, unsigned offset) { struct wm8994_gpio *wm8994_gpio = gpiochip_get_data(chip); struct wm8994 *wm8994 = wm8994_gpio->wm8994; return regmap_irq_get_virq(wm8994->irq_data, offset); }
int mc13xxx_irq_unmask(struct mc13xxx *mc13xxx, int irq) { int virq = regmap_irq_get_virq(mc13xxx->irq_data, irq); enable_irq(virq); return 0; }
int mc13xxx_irq_request(struct mc13xxx *mc13xxx, int irq, irq_handler_t handler, const char *name, void *dev) { int virq = regmap_irq_get_virq(mc13xxx->irq_data, irq); return devm_request_threaded_irq(mc13xxx->dev, virq, NULL, handler, IRQF_ONESHOT, name, dev); }
int mc13xxx_irq_mask(struct mc13xxx *mc13xxx, int irq) { int virq = regmap_irq_get_virq(mc13xxx->irq_data, irq); disable_irq_nosync(virq); return 0; }
int mc13xxx_irq_free(struct mc13xxx *mc13xxx, int irq, void *dev) { int virq = regmap_irq_get_virq(mc13xxx->irq_data, irq); devm_free_irq(mc13xxx->dev, virq, dev); return 0; }
static int da9055_onkey_remove(struct platform_device *pdev) { struct da9055_onkey *onkey = platform_get_drvdata(pdev); int irq = platform_get_irq_byname(pdev, "ONKEY"); irq = regmap_irq_get_virq(onkey->da9055->irq_data, irq); free_irq(irq, onkey); cancel_delayed_work_sync(&onkey->work); input_unregister_device(onkey->input); return 0; }
static int da9055_rtc_probe(struct platform_device *pdev) { struct da9055_rtc *rtc; struct da9055_pdata *pdata = NULL; int ret, alm_irq; rtc = devm_kzalloc(&pdev->dev, sizeof(struct da9055_rtc), GFP_KERNEL); if (!rtc) return -ENOMEM; rtc->da9055 = dev_get_drvdata(pdev->dev.parent); pdata = rtc->da9055->dev->platform_data; platform_set_drvdata(pdev, rtc); ret = da9055_rtc_device_init(rtc->da9055, pdata); if (ret < 0) goto err_rtc; ret = da9055_reg_read(rtc->da9055, DA9055_REG_ALARM_Y); if (ret < 0) goto err_rtc; if (ret & DA9055_RTC_ALM_EN) rtc->alarm_enable = 1; device_init_wakeup(&pdev->dev, 1); rtc->rtc = rtc_device_register(pdev->name, &pdev->dev, &da9055_rtc_ops, THIS_MODULE); if (IS_ERR(rtc->rtc)) { ret = PTR_ERR(rtc->rtc); goto err_rtc; } alm_irq = platform_get_irq_byname(pdev, "ALM"); alm_irq = regmap_irq_get_virq(rtc->da9055->irq_data, alm_irq); ret = devm_request_threaded_irq(&pdev->dev, alm_irq, NULL, da9055_rtc_alm_irq, IRQF_TRIGGER_HIGH | IRQF_ONESHOT, "ALM", rtc); if (ret != 0) dev_err(rtc->da9055->dev, "irq registration failed: %d\n", ret); err_rtc: return ret; }
static int bxt_wcove_tmu_probe(struct platform_device *pdev) { struct intel_soc_pmic *pmic = dev_get_drvdata(pdev->dev.parent); struct regmap_irq_chip_data *regmap_irq_chip; struct wcove_tmu *wctmu; int ret, virq, irq; wctmu = devm_kzalloc(&pdev->dev, sizeof(*wctmu), GFP_KERNEL); if (!wctmu) return -ENOMEM; wctmu->dev = &pdev->dev; wctmu->regmap = pmic->regmap; irq = platform_get_irq(pdev, 0); if (irq < 0) { dev_err(&pdev->dev, "invalid irq %d\n", irq); return irq; } regmap_irq_chip = pmic->irq_chip_data_tmu; virq = regmap_irq_get_virq(regmap_irq_chip, irq); if (virq < 0) { dev_err(&pdev->dev, "failed to get virtual interrupt=%d\n", irq); return virq; } ret = devm_request_threaded_irq(&pdev->dev, virq, NULL, bxt_wcove_tmu_irq_handler, IRQF_ONESHOT, "bxt_wcove_tmu", wctmu); if (ret) { dev_err(&pdev->dev, "request irq failed: %d,virq: %d\n", ret, virq); return ret; } wctmu->irq = virq; /* Unmask TMU second level Wake & System alarm */ regmap_update_bits(wctmu->regmap, BXTWC_MTMUIRQ_REG, BXTWC_TMU_ALRM_MASK, 0); platform_set_drvdata(pdev, wctmu); return 0; }
static int max8907_rtc_probe(struct platform_device *pdev) { struct max8907 *max8907 = dev_get_drvdata(pdev->dev.parent); struct max8907_rtc *rtc; int ret; rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL); if (!rtc) return -ENOMEM; platform_set_drvdata(pdev, rtc); rtc->max8907 = max8907; rtc->regmap = max8907->regmap_rtc; rtc->rtc_dev = rtc_device_register("max8907-rtc", &pdev->dev, &max8907_rtc_ops, THIS_MODULE); if (IS_ERR(rtc->rtc_dev)) { ret = PTR_ERR(rtc->rtc_dev); dev_err(&pdev->dev, "Failed to register RTC device: %d\n", ret); return ret; } rtc->irq = regmap_irq_get_virq(max8907->irqc_rtc, MAX8907_IRQ_RTC_ALARM0); if (rtc->irq < 0) { ret = rtc->irq; goto err_unregister; } ret = devm_request_threaded_irq(&pdev->dev, rtc->irq, NULL, max8907_irq_handler, IRQF_ONESHOT, "max8907-alarm0", rtc); if (ret < 0) { dev_err(&pdev->dev, "Failed to request IRQ%d: %d\n", rtc->irq, ret); goto err_unregister; } return 0; err_unregister: rtc_device_unregister(rtc->rtc_dev); return ret; }
static irqreturn_t da9052_bat_irq(int irq, void *data) { struct da9052_battery *bat = data; int virq; virq = regmap_irq_get_virq(bat->da9052->irq_data, irq); irq -= virq; if (irq == DA9052_IRQ_CHGEND) bat->status = POWER_SUPPLY_STATUS_FULL; else da9052_bat_check_status(bat, NULL); if (irq == DA9052_IRQ_CHGEND || irq == DA9052_IRQ_DCIN || irq == DA9052_IRQ_VBUS || irq == DA9052_IRQ_TBAT) { power_supply_changed(&bat->psy); } return IRQ_HANDLED; }
static int twl6040_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct twl6040_platform_data *pdata = client->dev.platform_data; struct device_node *node = client->dev.of_node; struct twl6040 *twl6040; struct mfd_cell *cell = NULL; int irq, ret, children = 0; if (!pdata && !node) { dev_err(&client->dev, "Platform data is missing\n"); return -EINVAL; } /* In order to operate correctly we need valid interrupt config */ if (!client->irq) { dev_err(&client->dev, "Invalid IRQ configuration\n"); return -EINVAL; } twl6040 = devm_kzalloc(&client->dev, sizeof(struct twl6040), GFP_KERNEL); if (!twl6040) { ret = -ENOMEM; goto err; } twl6040->regmap = devm_regmap_init_i2c(client, &twl6040_regmap_config); if (IS_ERR(twl6040->regmap)) { ret = PTR_ERR(twl6040->regmap); goto err; } i2c_set_clientdata(client, twl6040); twl6040->supplies[0].supply = "vio"; twl6040->supplies[1].supply = "v2v1"; ret = devm_regulator_bulk_get(&client->dev, TWL6040_NUM_SUPPLIES, twl6040->supplies); if (ret != 0) { dev_err(&client->dev, "Failed to get supplies: %d\n", ret); goto regulator_get_err; } ret = regulator_bulk_enable(TWL6040_NUM_SUPPLIES, twl6040->supplies); if (ret != 0) { dev_err(&client->dev, "Failed to enable supplies: %d\n", ret); goto regulator_get_err; } twl6040->dev = &client->dev; twl6040->irq = client->irq; mutex_init(&twl6040->mutex); init_completion(&twl6040->ready); twl6040->rev = twl6040_reg_read(twl6040, TWL6040_REG_ASICREV); /* ERRATA: Automatic power-up is not possible in ES1.0 */ if (twl6040_get_revid(twl6040) > TWL6040_REV_ES1_0) { if (pdata) twl6040->audpwron = pdata->audpwron_gpio; else twl6040->audpwron = of_get_named_gpio(node, "ti,audpwron-gpio", 0); } else twl6040->audpwron = -EINVAL; if (gpio_is_valid(twl6040->audpwron)) { ret = devm_gpio_request_one(&client->dev, twl6040->audpwron, GPIOF_OUT_INIT_LOW, "audpwron"); if (ret) goto gpio_err; } ret = regmap_add_irq_chip(twl6040->regmap, twl6040->irq, IRQF_ONESHOT, 0, &twl6040_irq_chip, &twl6040->irq_data); if (ret < 0) goto gpio_err; twl6040->irq_ready = regmap_irq_get_virq(twl6040->irq_data, TWL6040_IRQ_READY); twl6040->irq_th = regmap_irq_get_virq(twl6040->irq_data, TWL6040_IRQ_TH); ret = devm_request_threaded_irq(twl6040->dev, twl6040->irq_ready, NULL, twl6040_readyint_handler, IRQF_ONESHOT, "twl6040_irq_ready", twl6040); if (ret) { dev_err(twl6040->dev, "READY IRQ request failed: %d\n", ret); goto readyirq_err; } ret = devm_request_threaded_irq(twl6040->dev, twl6040->irq_th, NULL, twl6040_thint_handler, IRQF_ONESHOT, "twl6040_irq_th", twl6040); if (ret) { dev_err(twl6040->dev, "Thermal IRQ request failed: %d\n", ret); goto thirq_err; } /* dual-access registers controlled by I2C only */ twl6040_set_bits(twl6040, TWL6040_REG_ACCCTL, TWL6040_I2CSEL); /* * The main functionality of twl6040 to provide audio on OMAP4+ systems. * We can add the ASoC codec child whenever this driver has been loaded. * The ASoC codec can work without pdata, pass the platform_data only if * it has been provided. */ irq = regmap_irq_get_virq(twl6040->irq_data, TWL6040_IRQ_PLUG); cell = &twl6040->cells[children]; cell->name = "twl6040-codec"; twl6040_codec_rsrc[0].start = irq; twl6040_codec_rsrc[0].end = irq; cell->resources = twl6040_codec_rsrc; cell->num_resources = ARRAY_SIZE(twl6040_codec_rsrc); if (pdata && pdata->codec) { cell->platform_data = pdata->codec; cell->pdata_size = sizeof(*pdata->codec); } children++; if (twl6040_has_vibra(pdata, node)) { irq = regmap_irq_get_virq(twl6040->irq_data, TWL6040_IRQ_VIB); cell = &twl6040->cells[children]; cell->name = "twl6040-vibra"; twl6040_vibra_rsrc[0].start = irq; twl6040_vibra_rsrc[0].end = irq; cell->resources = twl6040_vibra_rsrc; cell->num_resources = ARRAY_SIZE(twl6040_vibra_rsrc); if (pdata && pdata->vibra) { cell->platform_data = pdata->vibra; cell->pdata_size = sizeof(*pdata->vibra); } children++; } /* * Enable the GPO driver in the following cases: * DT booted kernel or legacy boot with valid gpo platform_data */ if (!pdata || (pdata && pdata->gpo)) { cell = &twl6040->cells[children]; cell->name = "twl6040-gpo"; if (pdata) { cell->platform_data = pdata->gpo; cell->pdata_size = sizeof(*pdata->gpo); } children++; } ret = mfd_add_devices(&client->dev, -1, twl6040->cells, children, NULL, 0, NULL); if (ret) goto mfd_err; return 0; mfd_err: devm_free_irq(&client->dev, twl6040->irq_th, twl6040); thirq_err: devm_free_irq(&client->dev, twl6040->irq_ready, twl6040); readyirq_err: regmap_del_irq_chip(twl6040->irq, twl6040->irq_data); gpio_err: regulator_bulk_disable(TWL6040_NUM_SUPPLIES, twl6040->supplies); regulator_get_err: i2c_set_clientdata(client, NULL); err: return ret; }
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; }
static int twl6040_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct device_node *node = client->dev.of_node; struct twl6040 *twl6040; struct mfd_cell *cell = NULL; int irq, ret, children = 0; if (!node) { dev_err(&client->dev, "of node is missing\n"); return -EINVAL; } /* In order to operate correctly we need valid interrupt config */ if (!client->irq) { dev_err(&client->dev, "Invalid IRQ configuration\n"); return -EINVAL; } twl6040 = devm_kzalloc(&client->dev, sizeof(struct twl6040), GFP_KERNEL); if (!twl6040) return -ENOMEM; twl6040->regmap = devm_regmap_init_i2c(client, &twl6040_regmap_config); if (IS_ERR(twl6040->regmap)) return PTR_ERR(twl6040->regmap); i2c_set_clientdata(client, twl6040); twl6040->clk32k = devm_clk_get(&client->dev, "clk32k"); if (IS_ERR(twl6040->clk32k)) { if (PTR_ERR(twl6040->clk32k) == -EPROBE_DEFER) return -EPROBE_DEFER; dev_dbg(&client->dev, "clk32k is not handled\n"); twl6040->clk32k = NULL; } twl6040->mclk = devm_clk_get(&client->dev, "mclk"); if (IS_ERR(twl6040->mclk)) { if (PTR_ERR(twl6040->mclk) == -EPROBE_DEFER) return -EPROBE_DEFER; dev_dbg(&client->dev, "mclk is not handled\n"); twl6040->mclk = NULL; } twl6040->supplies[0].supply = "vio"; twl6040->supplies[1].supply = "v2v1"; ret = devm_regulator_bulk_get(&client->dev, TWL6040_NUM_SUPPLIES, twl6040->supplies); if (ret != 0) { dev_err(&client->dev, "Failed to get supplies: %d\n", ret); return ret; } ret = regulator_bulk_enable(TWL6040_NUM_SUPPLIES, twl6040->supplies); if (ret != 0) { dev_err(&client->dev, "Failed to enable supplies: %d\n", ret); return ret; } twl6040->dev = &client->dev; twl6040->irq = client->irq; mutex_init(&twl6040->mutex); init_completion(&twl6040->ready); regmap_register_patch(twl6040->regmap, twl6040_patch, ARRAY_SIZE(twl6040_patch)); twl6040->rev = twl6040_reg_read(twl6040, TWL6040_REG_ASICREV); if (twl6040->rev < 0) { dev_err(&client->dev, "Failed to read revision register: %d\n", twl6040->rev); ret = twl6040->rev; goto gpio_err; } /* ERRATA: Automatic power-up is not possible in ES1.0 */ if (twl6040_get_revid(twl6040) > TWL6040_REV_ES1_0) twl6040->audpwron = of_get_named_gpio(node, "ti,audpwron-gpio", 0); else twl6040->audpwron = -EINVAL; if (gpio_is_valid(twl6040->audpwron)) { ret = devm_gpio_request_one(&client->dev, twl6040->audpwron, GPIOF_OUT_INIT_LOW, "audpwron"); if (ret) goto gpio_err; /* Clear any pending interrupt */ twl6040_reg_read(twl6040, TWL6040_REG_INTID); } ret = regmap_add_irq_chip(twl6040->regmap, twl6040->irq, IRQF_ONESHOT, 0, &twl6040_irq_chip, &twl6040->irq_data); if (ret < 0) goto gpio_err; twl6040->irq_ready = regmap_irq_get_virq(twl6040->irq_data, TWL6040_IRQ_READY); twl6040->irq_th = regmap_irq_get_virq(twl6040->irq_data, TWL6040_IRQ_TH); ret = devm_request_threaded_irq(twl6040->dev, twl6040->irq_ready, NULL, twl6040_readyint_handler, IRQF_ONESHOT, "twl6040_irq_ready", twl6040); if (ret) { dev_err(twl6040->dev, "READY IRQ request failed: %d\n", ret); goto readyirq_err; } ret = devm_request_threaded_irq(twl6040->dev, twl6040->irq_th, NULL, twl6040_thint_handler, IRQF_ONESHOT, "twl6040_irq_th", twl6040); if (ret) { dev_err(twl6040->dev, "Thermal IRQ request failed: %d\n", ret); goto readyirq_err; } /* * The main functionality of twl6040 to provide audio on OMAP4+ systems. * We can add the ASoC codec child whenever this driver has been loaded. */ irq = regmap_irq_get_virq(twl6040->irq_data, TWL6040_IRQ_PLUG); cell = &twl6040->cells[children]; cell->name = "twl6040-codec"; twl6040_codec_rsrc[0].start = irq; twl6040_codec_rsrc[0].end = irq; cell->resources = twl6040_codec_rsrc; cell->num_resources = ARRAY_SIZE(twl6040_codec_rsrc); children++; /* Vibra input driver support */ if (twl6040_has_vibra(node)) { irq = regmap_irq_get_virq(twl6040->irq_data, TWL6040_IRQ_VIB); cell = &twl6040->cells[children]; cell->name = "twl6040-vibra"; twl6040_vibra_rsrc[0].start = irq; twl6040_vibra_rsrc[0].end = irq; cell->resources = twl6040_vibra_rsrc; cell->num_resources = ARRAY_SIZE(twl6040_vibra_rsrc); children++; } /* GPO support */ cell = &twl6040->cells[children]; cell->name = "twl6040-gpo"; children++; /* PDM clock support */ cell = &twl6040->cells[children]; cell->name = "twl6040-pdmclk"; children++; /* The chip is powered down so mark regmap to cache only and dirty */ regcache_cache_only(twl6040->regmap, true); regcache_mark_dirty(twl6040->regmap); ret = mfd_add_devices(&client->dev, -1, twl6040->cells, children, NULL, 0, NULL); if (ret) goto readyirq_err; return 0; readyirq_err: regmap_del_irq_chip(twl6040->irq, twl6040->irq_data); gpio_err: regulator_bulk_disable(TWL6040_NUM_SUPPLIES, twl6040->supplies); return ret; }
static int da9055_onkey_probe(struct platform_device *pdev) { struct da9055 *da9055 = dev_get_drvdata(pdev->dev.parent); struct da9055_onkey *onkey; struct input_dev *input_dev; int irq, err; irq = platform_get_irq_byname(pdev, "ONKEY"); if (irq < 0) { dev_err(&pdev->dev, "Failed to get an IRQ for input device, %d\n", irq); return -EINVAL; } onkey = devm_kzalloc(&pdev->dev, sizeof(*onkey), GFP_KERNEL); if (!onkey) { dev_err(&pdev->dev, "Failed to allocate memory\n"); return -ENOMEM; } input_dev = input_allocate_device(); if (!input_dev) { dev_err(&pdev->dev, "Failed to allocate memory\n"); return -ENOMEM; } onkey->input = input_dev; onkey->da9055 = da9055; input_dev->name = "da9055-onkey"; input_dev->phys = "da9055-onkey/input0"; input_dev->dev.parent = &pdev->dev; input_dev->evbit[0] = BIT_MASK(EV_KEY); __set_bit(KEY_POWER, input_dev->keybit); INIT_DELAYED_WORK(&onkey->work, da9055_onkey_work); irq = regmap_irq_get_virq(da9055->irq_data, irq); err = request_threaded_irq(irq, NULL, da9055_onkey_irq, IRQF_TRIGGER_HIGH | IRQF_ONESHOT, "ONKEY", onkey); if (err < 0) { dev_err(&pdev->dev, "Failed to register ONKEY IRQ %d, error = %d\n", irq, err); goto err_free_input; } err = input_register_device(input_dev); if (err) { dev_err(&pdev->dev, "Unable to register input device, %d\n", err); goto err_free_irq; } platform_set_drvdata(pdev, onkey); return 0; err_free_irq: free_irq(irq, onkey); cancel_delayed_work_sync(&onkey->work); err_free_input: input_free_device(input_dev); return err; }
static int da9063_regulator_probe(struct platform_device *pdev) { struct da9063 *da9063 = dev_get_drvdata(pdev->dev.parent); struct da9063_pdata *da9063_pdata = dev_get_platdata(da9063->dev); struct of_regulator_match *da9063_reg_matches = NULL; struct da9063_regulators_pdata *regl_pdata; const struct da9063_dev_model *model; struct da9063_regulators *regulators; struct da9063_regulator *regl; struct regulator_config config; bool bcores_merged, bmem_bio_merged; int id, irq, n, n_regulators, ret, val; size_t size; regl_pdata = da9063_pdata ? da9063_pdata->regulators_pdata : NULL; if (!regl_pdata) regl_pdata = da9063_parse_regulators_dt(pdev, &da9063_reg_matches); if (IS_ERR(regl_pdata) || regl_pdata->n_regulators == 0) { dev_err(&pdev->dev, "No regulators defined for the platform\n"); return PTR_ERR(regl_pdata); } /* Find regulators set for particular device model */ for (model = regulators_models; model->regulator_info; model++) { if (model->dev_model == da9063->model) break; } if (!model->regulator_info) { dev_err(&pdev->dev, "Chip model not recognised (%u)\n", da9063->model); return -ENODEV; } ret = regmap_read(da9063->regmap, DA9063_REG_CONFIG_H, &val); if (ret < 0) { dev_err(&pdev->dev, "Error while reading BUCKs configuration\n"); return -EIO; } bcores_merged = val & DA9063_BCORE_MERGE; bmem_bio_merged = val & DA9063_BUCK_MERGE; n_regulators = model->n_regulators; if (bcores_merged) n_regulators -= 2; /* remove BCORE1, BCORE2 */ else n_regulators--; /* remove BCORES_MERGED */ if (bmem_bio_merged) n_regulators -= 2; /* remove BMEM, BIO */ else n_regulators--; /* remove BMEM_BIO_MERGED */ /* Allocate memory required by usable regulators */ size = sizeof(struct da9063_regulators) + n_regulators * sizeof(struct da9063_regulator); regulators = devm_kzalloc(&pdev->dev, size, GFP_KERNEL); if (!regulators) { dev_err(&pdev->dev, "No memory for regulators\n"); return -ENOMEM; } regulators->n_regulators = n_regulators; platform_set_drvdata(pdev, regulators); /* Register all regulators declared in platform information */ n = 0; id = 0; while (n < regulators->n_regulators) { /* Skip regulator IDs depending on merge mode configuration */ switch (id) { case DA9063_ID_BCORE1: case DA9063_ID_BCORE2: if (bcores_merged) { id++; continue; } break; case DA9063_ID_BMEM: case DA9063_ID_BIO: if (bmem_bio_merged) { id++; continue; } break; case DA9063_ID_BCORES_MERGED: if (!bcores_merged) { id++; continue; } break; case DA9063_ID_BMEM_BIO_MERGED: if (!bmem_bio_merged) { id++; continue; } break; } /* Initialise regulator structure */ regl = ®ulators->regulator[n]; regl->hw = da9063; regl->info = &model->regulator_info[id]; regl->desc = regl->info->desc; regl->desc.type = REGULATOR_VOLTAGE; regl->desc.owner = THIS_MODULE; if (regl->info->mode.reg) regl->mode = devm_regmap_field_alloc(&pdev->dev, da9063->regmap, regl->info->mode); if (regl->info->suspend.reg) regl->suspend = devm_regmap_field_alloc(&pdev->dev, da9063->regmap, regl->info->suspend); if (regl->info->sleep.reg) regl->sleep = devm_regmap_field_alloc(&pdev->dev, da9063->regmap, regl->info->sleep); if (regl->info->suspend_sleep.reg) regl->suspend_sleep = devm_regmap_field_alloc(&pdev->dev, da9063->regmap, regl->info->suspend_sleep); if (regl->info->ilimit.reg) regl->ilimit = devm_regmap_field_alloc(&pdev->dev, da9063->regmap, regl->info->ilimit); /* Register regulator */ memset(&config, 0, sizeof(config)); config.dev = &pdev->dev; config.init_data = da9063_get_regulator_initdata(regl_pdata, id); config.driver_data = regl; if (da9063_reg_matches) config.of_node = da9063_reg_matches[id].of_node; config.regmap = da9063->regmap; regl->rdev = devm_regulator_register(&pdev->dev, ®l->desc, &config); if (IS_ERR(regl->rdev)) { dev_err(&pdev->dev, "Failed to register %s regulator\n", regl->desc.name); return PTR_ERR(regl->rdev); } id++; n++; } /* LDOs overcurrent event support */ irq = platform_get_irq_byname(pdev, "LDO_LIM"); if (irq < 0) { dev_err(&pdev->dev, "Failed to get IRQ.\n"); return irq; } regulators->irq_ldo_lim = regmap_irq_get_virq(da9063->regmap_irq, irq); if (regulators->irq_ldo_lim >= 0) { ret = request_threaded_irq(regulators->irq_ldo_lim, NULL, da9063_ldo_lim_event, IRQF_TRIGGER_LOW | IRQF_ONESHOT, "LDO_LIM", regulators); if (ret) { dev_err(&pdev->dev, "Failed to request LDO_LIM IRQ.\n"); regulators->irq_ldo_lim = -ENXIO; } } return 0; }
static int axp20x_usb_power_probe(struct platform_device *pdev) { struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent); struct power_supply_config psy_cfg = {}; struct axp20x_usb_power *power; static const char * const axp20x_irq_names[] = { "VBUS_PLUGIN", "VBUS_REMOVAL", "VBUS_VALID", "VBUS_NOT_VALID", NULL }; static const char * const axp22x_irq_names[] = { "VBUS_PLUGIN", "VBUS_REMOVAL", NULL }; const char * const *irq_names; const struct power_supply_desc *usb_power_desc; int i, irq, ret; if (!of_device_is_available(pdev->dev.of_node)) return -ENODEV; if (!axp20x) { dev_err(&pdev->dev, "Parent drvdata not set\n"); return -EINVAL; } power = devm_kzalloc(&pdev->dev, sizeof(*power), GFP_KERNEL); if (!power) return -ENOMEM; power->axp20x_id = (enum axp20x_variants)of_device_get_match_data( &pdev->dev); power->np = pdev->dev.of_node; power->regmap = axp20x->regmap; if (power->axp20x_id == AXP202_ID) { /* Enable vbus valid checking */ ret = regmap_update_bits(power->regmap, AXP20X_VBUS_MON, AXP20X_VBUS_MON_VBUS_VALID, AXP20X_VBUS_MON_VBUS_VALID); if (ret) return ret; if (IS_ENABLED(CONFIG_AXP20X_ADC)) ret = configure_iio_channels(pdev, power); else ret = configure_adc_registers(power); if (ret) return ret; usb_power_desc = &axp20x_usb_power_desc; irq_names = axp20x_irq_names; } else if (power->axp20x_id == AXP221_ID || power->axp20x_id == AXP223_ID) { usb_power_desc = &axp22x_usb_power_desc; irq_names = axp22x_irq_names; } else { dev_err(&pdev->dev, "Unsupported AXP variant: %ld\n", axp20x->variant); return -EINVAL; } psy_cfg.of_node = pdev->dev.of_node; psy_cfg.drv_data = power; power->supply = devm_power_supply_register(&pdev->dev, usb_power_desc, &psy_cfg); if (IS_ERR(power->supply)) return PTR_ERR(power->supply); /* Request irqs after registering, as irqs may trigger immediately */ for (i = 0; irq_names[i]; i++) { irq = platform_get_irq_byname(pdev, irq_names[i]); if (irq < 0) { dev_warn(&pdev->dev, "No IRQ for %s: %d\n", irq_names[i], irq); continue; } irq = regmap_irq_get_virq(axp20x->regmap_irqc, irq); ret = devm_request_any_context_irq(&pdev->dev, irq, axp20x_usb_power_irq, 0, DRVNAME, power); if (ret < 0) dev_warn(&pdev->dev, "Error requesting %s IRQ: %d\n", irq_names[i], ret); } return 0; }
static int max14577_muic_probe(struct platform_device *pdev) { struct max14577 *max14577 = dev_get_drvdata(pdev->dev.parent); struct max14577_muic_info *info; int delay_jiffies; int ret; int i; u8 id; info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL); if (!info) return -ENOMEM; info->dev = &pdev->dev; info->max14577 = max14577; platform_set_drvdata(pdev, info); mutex_init(&info->mutex); INIT_WORK(&info->irq_work, max14577_muic_irq_work); switch (max14577->dev_type) { case MAXIM_DEVICE_TYPE_MAX77836: info->muic_irqs = max77836_muic_irqs; info->muic_irqs_num = ARRAY_SIZE(max77836_muic_irqs); break; case MAXIM_DEVICE_TYPE_MAX14577: default: info->muic_irqs = max14577_muic_irqs; info->muic_irqs_num = ARRAY_SIZE(max14577_muic_irqs); } /* Support irq domain for max14577 MUIC device */ for (i = 0; i < info->muic_irqs_num; i++) { struct max14577_muic_irq *muic_irq = &info->muic_irqs[i]; int virq = 0; virq = regmap_irq_get_virq(max14577->irq_data, muic_irq->irq); if (virq <= 0) return -EINVAL; muic_irq->virq = virq; ret = devm_request_threaded_irq(&pdev->dev, virq, NULL, max14577_muic_irq_handler, IRQF_NO_SUSPEND, muic_irq->name, info); if (ret) { dev_err(&pdev->dev, "failed: irq request (IRQ: %d, error :%d)\n", muic_irq->irq, ret); return ret; } } /* Initialize extcon device */ info->edev = devm_extcon_dev_allocate(&pdev->dev, max14577_extcon_cable); if (IS_ERR(info->edev)) { dev_err(&pdev->dev, "failed to allocate memory for extcon\n"); return -ENOMEM; } ret = devm_extcon_dev_register(&pdev->dev, info->edev); if (ret) { dev_err(&pdev->dev, "failed to register extcon device\n"); return ret; } /* Default h/w line path */ info->path_usb = CTRL1_SW_USB; info->path_uart = CTRL1_SW_UART; delay_jiffies = msecs_to_jiffies(DELAY_MS_DEFAULT); /* Set initial path for UART */ max14577_muic_set_path(info, info->path_uart, true); /* Check revision number of MUIC device*/ ret = max14577_read_reg(info->max14577->regmap, MAX14577_REG_DEVICEID, &id); if (ret < 0) { dev_err(&pdev->dev, "failed to read revision number\n"); return ret; } dev_info(info->dev, "device ID : 0x%x\n", id); /* Set ADC debounce time */ max14577_muic_set_debounce_time(info, ADC_DEBOUNCE_TIME_25MS); /* * Detect accessory after completing the initialization of platform * * - Use delayed workqueue to detect cable state and then * notify cable state to notifiee/platform through uevent. * After completing the booting of platform, the extcon provider * driver should notify cable state to upper layer. */ INIT_DELAYED_WORK(&info->wq_detcable, max14577_muic_detect_cable_wq); queue_delayed_work(system_power_efficient_wq, &info->wq_detcable, delay_jiffies); return ret; }
static int da9052_map_irq(struct da9052 *da9052, int irq) { return regmap_irq_get_virq(da9052->irq_data, irq); }
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 max77693_muic_probe(struct platform_device *pdev) { struct max77693_dev *max77693 = dev_get_drvdata(pdev->dev.parent); struct max77693_platform_data *pdata = dev_get_platdata(max77693->dev); struct max77693_muic_info *info; struct max77693_reg_data *init_data; int num_init_data; int delay_jiffies; int ret; int i; unsigned int id; info = devm_kzalloc(&pdev->dev, sizeof(struct max77693_muic_info), GFP_KERNEL); if (!info) return -ENOMEM; info->dev = &pdev->dev; info->max77693 = max77693; if (info->max77693->regmap_muic) { dev_dbg(&pdev->dev, "allocate register map\n"); } else { info->max77693->regmap_muic = devm_regmap_init_i2c( info->max77693->i2c_muic, &max77693_muic_regmap_config); if (IS_ERR(info->max77693->regmap_muic)) { ret = PTR_ERR(info->max77693->regmap_muic); dev_err(max77693->dev, "failed to allocate register map: %d\n", ret); return ret; } } /* Register input device for button of dock device */ info->dock = devm_input_allocate_device(&pdev->dev); if (!info->dock) { dev_err(&pdev->dev, "%s: failed to allocate input\n", __func__); return -ENOMEM; } info->dock->name = "max77693-muic/dock"; info->dock->phys = "max77693-muic/extcon"; info->dock->dev.parent = &pdev->dev; __set_bit(EV_REP, info->dock->evbit); input_set_capability(info->dock, EV_KEY, KEY_VOLUMEUP); input_set_capability(info->dock, EV_KEY, KEY_VOLUMEDOWN); input_set_capability(info->dock, EV_KEY, KEY_PLAYPAUSE); input_set_capability(info->dock, EV_KEY, KEY_PREVIOUSSONG); input_set_capability(info->dock, EV_KEY, KEY_NEXTSONG); ret = input_register_device(info->dock); if (ret < 0) { dev_err(&pdev->dev, "Cannot register input device error(%d)\n", ret); return ret; } platform_set_drvdata(pdev, info); mutex_init(&info->mutex); INIT_WORK(&info->irq_work, max77693_muic_irq_work); /* Support irq domain for MAX77693 MUIC device */ for (i = 0; i < ARRAY_SIZE(muic_irqs); i++) { struct max77693_muic_irq *muic_irq = &muic_irqs[i]; int virq; virq = regmap_irq_get_virq(max77693->irq_data_muic, muic_irq->irq); if (virq <= 0) return -EINVAL; muic_irq->virq = virq; ret = devm_request_threaded_irq(&pdev->dev, virq, NULL, max77693_muic_irq_handler, IRQF_NO_SUSPEND, muic_irq->name, info); if (ret) { dev_err(&pdev->dev, "failed: irq request (IRQ: %d, error :%d)\n", muic_irq->irq, ret); return ret; } } /* Initialize extcon device */ info->edev = devm_extcon_dev_allocate(&pdev->dev, max77693_extcon_cable); if (IS_ERR(info->edev)) { dev_err(&pdev->dev, "failed to allocate memory for extcon\n"); return -ENOMEM; } ret = devm_extcon_dev_register(&pdev->dev, info->edev); if (ret) { dev_err(&pdev->dev, "failed to register extcon device\n"); return ret; } /* Initialize MUIC register by using platform data or default data */ if (pdata && pdata->muic_data) { init_data = pdata->muic_data->init_data; num_init_data = pdata->muic_data->num_init_data; } else { init_data = default_init_data; num_init_data = ARRAY_SIZE(default_init_data); } for (i = 0; i < num_init_data; i++) { regmap_write(info->max77693->regmap_muic, init_data[i].addr, init_data[i].data); } if (pdata && pdata->muic_data) { struct max77693_muic_platform_data *muic_pdata = pdata->muic_data; /* * Default usb/uart path whether UART/USB or AUX_UART/AUX_USB * h/w path of COMP2/COMN1 on CONTROL1 register. */ if (muic_pdata->path_uart) info->path_uart = muic_pdata->path_uart; else info->path_uart = MAX77693_CONTROL1_SW_UART; if (muic_pdata->path_usb) info->path_usb = muic_pdata->path_usb; else info->path_usb = MAX77693_CONTROL1_SW_USB; /* * Default delay time for detecting cable state * after certain time. */ if (muic_pdata->detcable_delay_ms) delay_jiffies = msecs_to_jiffies(muic_pdata->detcable_delay_ms); else delay_jiffies = msecs_to_jiffies(DELAY_MS_DEFAULT); } else { info->path_usb = MAX77693_CONTROL1_SW_USB; info->path_uart = MAX77693_CONTROL1_SW_UART; delay_jiffies = msecs_to_jiffies(DELAY_MS_DEFAULT); } /* Set initial path for UART */ max77693_muic_set_path(info, info->path_uart, true); /* Check revision number of MUIC device*/ ret = regmap_read(info->max77693->regmap_muic, MAX77693_MUIC_REG_ID, &id); if (ret < 0) { dev_err(&pdev->dev, "failed to read revision number\n"); return ret; } dev_info(info->dev, "device ID : 0x%x\n", id); /* Set ADC debounce time */ max77693_muic_set_debounce_time(info, ADC_DEBOUNCE_TIME_25MS); /* * Detect accessory after completing the initialization of platform * * - Use delayed workqueue to detect cable state and then * notify cable state to notifiee/platform through uevent. * After completing the booting of platform, the extcon provider * driver should notify cable state to upper layer. */ INIT_DELAYED_WORK(&info->wq_detcable, max77693_muic_detect_cable_wq); queue_delayed_work(system_power_efficient_wq, &info->wq_detcable, delay_jiffies); return ret; }
static int axp288_extcon_probe(struct platform_device *pdev) { struct axp288_extcon_info *info; struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent); int ret, i, pirq, gpio; info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL); if (!info) return -ENOMEM; info->dev = &pdev->dev; info->regmap = axp20x->regmap; info->regmap_irqc = axp20x->regmap_irqc; info->pdata = pdev->dev.platform_data; if (!info->pdata) { /* Try ACPI provided pdata via device properties */ if (!device_property_present(&pdev->dev, "axp288_extcon_data\n")) dev_err(&pdev->dev, "failed to get platform data\n"); return -ENODEV; } platform_set_drvdata(pdev, info); axp288_extcon_log_rsi(info); /* Initialize extcon device */ info->edev = devm_extcon_dev_allocate(&pdev->dev, axp288_extcon_cables); if (IS_ERR(info->edev)) { dev_err(&pdev->dev, "failed to allocate memory for extcon\n"); return PTR_ERR(info->edev); } /* Register extcon device */ ret = devm_extcon_dev_register(&pdev->dev, info->edev); if (ret) { dev_err(&pdev->dev, "failed to register extcon device\n"); return ret; } /* Get otg transceiver phy */ info->otg = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2); if (IS_ERR(info->otg)) { dev_err(&pdev->dev, "failed to get otg transceiver\n"); return PTR_ERR(info->otg); } /* Set up gpio control for USB Mux */ if (info->pdata->gpio_mux_cntl) { gpio = desc_to_gpio(info->pdata->gpio_mux_cntl); ret = devm_gpio_request(&pdev->dev, gpio, "USB_MUX"); if (ret < 0) { dev_err(&pdev->dev, "failed to request the gpio=%d\n", gpio); return ret; } gpiod_direction_output(info->pdata->gpio_mux_cntl, EXTCON_GPIO_MUX_SEL_PMIC); } for (i = 0; i < EXTCON_IRQ_END; i++) { pirq = platform_get_irq(pdev, i); info->irq[i] = regmap_irq_get_virq(info->regmap_irqc, pirq); if (info->irq[i] < 0) { dev_err(&pdev->dev, "failed to get virtual interrupt=%d\n", pirq); ret = info->irq[i]; return ret; } ret = devm_request_threaded_irq(&pdev->dev, info->irq[i], NULL, axp288_extcon_isr, IRQF_ONESHOT | IRQF_NO_SUSPEND, pdev->name, info); if (ret) { dev_err(&pdev->dev, "failed to request interrupt=%d\n", info->irq[i]); return ret; } } /* Enable interrupts */ axp288_extcon_enable_irq(info); return 0; }
static int axp288_charger_probe(struct platform_device *pdev) { int ret, i, pirq; struct axp288_chrg_info *info; struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent); struct power_supply_config charger_cfg = {}; info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL); if (!info) return -ENOMEM; info->pdev = pdev; info->regmap = axp20x->regmap; info->regmap_irqc = axp20x->regmap_irqc; info->pdata = pdev->dev.platform_data; if (!info->pdata) { /* Try ACPI provided pdata via device properties */ if (!device_property_present(&pdev->dev, "axp288_charger_data\n")) dev_err(&pdev->dev, "failed to get platform data\n"); return -ENODEV; } info->cable.edev = extcon_get_extcon_dev(AXP288_EXTCON_DEV_NAME); if (info->cable.edev == NULL) { dev_dbg(&pdev->dev, "%s is not ready, probe deferred\n", AXP288_EXTCON_DEV_NAME); return -EPROBE_DEFER; } /* Register for extcon notification */ INIT_WORK(&info->cable.work, axp288_charger_extcon_evt_worker); info->cable.nb.notifier_call = axp288_charger_handle_cable_evt; ret = extcon_register_notifier(info->cable.edev, EXTCON_CHG_USB_SDP, &info->cable.nb); if (ret) { dev_err(&info->pdev->dev, "failed to register extcon notifier for SDP %d\n", ret); return ret; } ret = extcon_register_notifier(info->cable.edev, EXTCON_CHG_USB_CDP, &info->cable.nb); if (ret) { dev_err(&info->pdev->dev, "failed to register extcon notifier for CDP %d\n", ret); extcon_unregister_notifier(info->cable.edev, EXTCON_CHG_USB_SDP, &info->cable.nb); return ret; } ret = extcon_register_notifier(info->cable.edev, EXTCON_CHG_USB_DCP, &info->cable.nb); if (ret) { dev_err(&info->pdev->dev, "failed to register extcon notifier for DCP %d\n", ret); extcon_unregister_notifier(info->cable.edev, EXTCON_CHG_USB_SDP, &info->cable.nb); extcon_unregister_notifier(info->cable.edev, EXTCON_CHG_USB_CDP, &info->cable.nb); return ret; } platform_set_drvdata(pdev, info); mutex_init(&info->lock); /* Register with power supply class */ charger_cfg.drv_data = info; info->psy_usb = power_supply_register(&pdev->dev, &axp288_charger_desc, &charger_cfg); if (IS_ERR(info->psy_usb)) { dev_err(&pdev->dev, "failed to register power supply charger\n"); ret = PTR_ERR(info->psy_usb); goto psy_reg_failed; } /* Register for OTG notification */ INIT_WORK(&info->otg.work, axp288_charger_otg_evt_worker); info->otg.id_nb.notifier_call = axp288_charger_handle_otg_evt; ret = extcon_register_notifier(info->otg.cable, EXTCON_USB_HOST, &info->otg.id_nb); if (ret) dev_warn(&pdev->dev, "failed to register otg notifier\n"); if (info->otg.cable) info->otg.id_short = extcon_get_cable_state_( info->otg.cable, EXTCON_USB_HOST); /* Register charger interrupts */ for (i = 0; i < CHRG_INTR_END; i++) { pirq = platform_get_irq(info->pdev, i); info->irq[i] = regmap_irq_get_virq(info->regmap_irqc, pirq); if (info->irq[i] < 0) { dev_warn(&info->pdev->dev, "failed to get virtual interrupt=%d\n", pirq); ret = info->irq[i]; goto intr_reg_failed; } ret = devm_request_threaded_irq(&info->pdev->dev, info->irq[i], NULL, axp288_charger_irq_thread_handler, IRQF_ONESHOT, info->pdev->name, info); if (ret) { dev_err(&pdev->dev, "failed to request interrupt=%d\n", info->irq[i]); goto intr_reg_failed; } } charger_init_hw_regs(info); return 0; intr_reg_failed: if (info->otg.cable) extcon_unregister_notifier(info->otg.cable, EXTCON_USB_HOST, &info->otg.id_nb); power_supply_unregister(info->psy_usb); psy_reg_failed: extcon_unregister_notifier(info->cable.edev, EXTCON_CHG_USB_SDP, &info->cable.nb); extcon_unregister_notifier(info->cable.edev, EXTCON_CHG_USB_CDP, &info->cable.nb); extcon_unregister_notifier(info->cable.edev, EXTCON_CHG_USB_DCP, &info->cable.nb); return ret; }
static int max77686_rtc_probe(struct platform_device *pdev) { struct max77686_dev *max77686 = dev_get_drvdata(pdev->dev.parent); struct max77686_rtc_info *info; int ret; dev_info(&pdev->dev, "%s\n", __func__); info = devm_kzalloc(&pdev->dev, sizeof(struct max77686_rtc_info), GFP_KERNEL); if (!info) return -ENOMEM; mutex_init(&info->lock); info->dev = &pdev->dev; info->max77686 = max77686; info->rtc = max77686->rtc; platform_set_drvdata(pdev, info); ret = max77686_rtc_init_reg(info); if (ret < 0) { dev_err(&pdev->dev, "Failed to initialize RTC reg:%d\n", ret); goto err_rtc; } device_init_wakeup(&pdev->dev, 1); info->rtc_dev = devm_rtc_device_register(&pdev->dev, "max77686-rtc", &max77686_rtc_ops, THIS_MODULE); if (IS_ERR(info->rtc_dev)) { ret = PTR_ERR(info->rtc_dev); dev_err(&pdev->dev, "Failed to register RTC device: %d\n", ret); if (ret == 0) ret = -EINVAL; goto err_rtc; } if (!max77686->rtc_irq_data) { ret = -EINVAL; dev_err(&pdev->dev, "%s: no RTC regmap IRQ chip\n", __func__); goto err_rtc; } info->virq = regmap_irq_get_virq(max77686->rtc_irq_data, MAX77686_RTCIRQ_RTCA1); if (info->virq <= 0) { ret = -ENXIO; goto err_rtc; } ret = devm_request_threaded_irq(&pdev->dev, info->virq, NULL, max77686_rtc_alarm_irq, 0, "rtc-alarm1", info); if (ret < 0) dev_err(&pdev->dev, "Failed to request alarm IRQ: %d: %d\n", info->virq, ret); err_rtc: return ret; }