static int gpio_charger_get_irq(struct device *dev, void *dev_id, struct gpio_desc *gpio) { int ret, irq = gpiod_to_irq(gpio); if (irq > 0) { ret = devm_request_any_context_irq(dev, irq, gpio_charger_irq, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, dev_name(dev), dev_id); if (ret < 0) { dev_warn(dev, "Failed to request irq: %d\n", ret); irq = 0; } } return irq; }
static int gpio_keys_setup_key(struct platform_device *pdev, struct input_dev *input, struct gpio_button_data *bdata, const struct gpio_keys_button *button) { const char *desc = button->desc ? button->desc : "gpio_keys"; struct device *dev = &pdev->dev; irq_handler_t isr; unsigned long irqflags; int irq; int error; bdata->input = input; bdata->button = button; spin_lock_init(&bdata->lock); if (gpio_is_valid(button->gpio)) { error = devm_gpio_request_one(&pdev->dev, button->gpio, GPIOF_IN, desc); if (error < 0) { dev_err(dev, "Failed to request GPIO %d, error %d\n", button->gpio, error); return error; } if (button->debounce_interval) { error = gpio_set_debounce(button->gpio, button->debounce_interval * 1000); /* use timer if gpiolib doesn't provide debounce */ if (error < 0) bdata->software_debounce = button->debounce_interval; } if (button->irq) { bdata->irq = button->irq; } else { irq = gpio_to_irq(button->gpio); if (irq < 0) { error = irq; dev_err(dev, "Unable to get irq number for GPIO %d, error %d\n", button->gpio, error); return error; } bdata->irq = irq; } INIT_DELAYED_WORK(&bdata->work, gpio_keys_gpio_work_func); isr = gpio_keys_gpio_isr; irqflags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING; } else { if (!button->irq) { dev_err(dev, "No IRQ specified\n"); return -EINVAL; } bdata->irq = button->irq; if (button->type && button->type != EV_KEY) { dev_err(dev, "Only EV_KEY allowed for IRQ buttons.\n"); return -EINVAL; } bdata->release_delay = button->debounce_interval; setup_timer(&bdata->release_timer, gpio_keys_irq_timer, (unsigned long)bdata); isr = gpio_keys_irq_isr; irqflags = 0; } input_set_capability(input, button->type ?: EV_KEY, button->code); /* * Install custom action to cancel release timer and * workqueue item. */ error = devm_add_action(&pdev->dev, gpio_keys_quiesce_key, bdata); if (error) { dev_err(&pdev->dev, "failed to register quiesce action, error: %d\n", error); return error; } /* * If platform has specified that the button can be disabled, * we don't want it to share the interrupt line. */ if (!button->can_disable) irqflags |= IRQF_SHARED; error = devm_request_any_context_irq(&pdev->dev, bdata->irq, isr, irqflags, desc, bdata); if (error < 0) { dev_err(dev, "Unable to claim irq %d; error %d\n", bdata->irq, error); return error; } return 0; }
/* * keypad controller should be initialized in the following sequence * only, otherwise it might get into FSM stuck state. * * - Initialize keypad control parameters, like no. of rows, columns, * timing values etc., * - configure rows and column gpios pull up/down. * - set irq edge type. * - enable the keypad controller. */ static int pmic8xxx_kp_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; unsigned int rows, cols; bool repeat; bool wakeup; struct pmic8xxx_kp *kp; int rc; unsigned int ctrl_val; rc = matrix_keypad_parse_of_params(&pdev->dev, &rows, &cols); if (rc) return rc; if (cols > PM8XXX_MAX_COLS || rows > PM8XXX_MAX_ROWS || cols < PM8XXX_MIN_COLS) { dev_err(&pdev->dev, "invalid platform data\n"); return -EINVAL; } repeat = !of_property_read_bool(np, "linux,input-no-autorepeat"); wakeup = of_property_read_bool(np, "wakeup-source") || /* legacy name */ of_property_read_bool(np, "linux,keypad-wakeup"); kp = devm_kzalloc(&pdev->dev, sizeof(*kp), GFP_KERNEL); if (!kp) return -ENOMEM; kp->regmap = dev_get_regmap(pdev->dev.parent, NULL); if (!kp->regmap) return -ENODEV; platform_set_drvdata(pdev, kp); kp->num_rows = rows; kp->num_cols = cols; kp->dev = &pdev->dev; kp->input = devm_input_allocate_device(&pdev->dev); if (!kp->input) { dev_err(&pdev->dev, "unable to allocate input device\n"); return -ENOMEM; } kp->key_sense_irq = platform_get_irq(pdev, 0); if (kp->key_sense_irq < 0) { dev_err(&pdev->dev, "unable to get keypad sense irq\n"); return kp->key_sense_irq; } kp->key_stuck_irq = platform_get_irq(pdev, 1); if (kp->key_stuck_irq < 0) { dev_err(&pdev->dev, "unable to get keypad stuck irq\n"); return kp->key_stuck_irq; } kp->input->name = "PMIC8XXX keypad"; kp->input->phys = "pmic8xxx_keypad/input0"; kp->input->id.bustype = BUS_I2C; kp->input->id.version = 0x0001; kp->input->id.product = 0x0001; kp->input->id.vendor = 0x0001; kp->input->open = pmic8xxx_kp_open; kp->input->close = pmic8xxx_kp_close; rc = matrix_keypad_build_keymap(NULL, NULL, PM8XXX_MAX_ROWS, PM8XXX_MAX_COLS, kp->keycodes, kp->input); if (rc) { dev_err(&pdev->dev, "failed to build keymap\n"); return rc; } if (repeat) __set_bit(EV_REP, kp->input->evbit); input_set_capability(kp->input, EV_MSC, MSC_SCAN); input_set_drvdata(kp->input, kp); /* initialize keypad state */ memset(kp->keystate, 0xff, sizeof(kp->keystate)); memset(kp->stuckstate, 0xff, sizeof(kp->stuckstate)); rc = pmic8xxx_kpd_init(kp, pdev); if (rc < 0) { dev_err(&pdev->dev, "unable to initialize keypad controller\n"); return rc; } rc = devm_request_any_context_irq(&pdev->dev, kp->key_sense_irq, pmic8xxx_kp_irq, IRQF_TRIGGER_RISING, "pmic-keypad", kp); if (rc < 0) { dev_err(&pdev->dev, "failed to request keypad sense irq\n"); return rc; } rc = devm_request_any_context_irq(&pdev->dev, kp->key_stuck_irq, pmic8xxx_kp_stuck_irq, IRQF_TRIGGER_RISING, "pmic-keypad-stuck", kp); if (rc < 0) { dev_err(&pdev->dev, "failed to request keypad stuck irq\n"); return rc; } rc = regmap_read(kp->regmap, KEYP_CTRL, &ctrl_val); if (rc < 0) { dev_err(&pdev->dev, "failed to read KEYP_CTRL register\n"); return rc; } kp->ctrl_reg = ctrl_val; rc = input_register_device(kp->input); if (rc < 0) { dev_err(&pdev->dev, "unable to register keypad input device\n"); return rc; } device_init_wakeup(&pdev->dev, wakeup); return 0; }
static int max77650_charger_probe(struct platform_device *pdev) { struct power_supply_config pscfg = {}; struct max77650_charger_data *chg; struct power_supply *battery; struct device *dev, *parent; int rv, chg_irq, chgin_irq; unsigned int prop; dev = &pdev->dev; parent = dev->parent; chg = devm_kzalloc(dev, sizeof(*chg), GFP_KERNEL); if (!chg) return -ENOMEM; platform_set_drvdata(pdev, chg); chg->map = dev_get_regmap(parent, NULL); if (!chg->map) return -ENODEV; chg->dev = dev; pscfg.of_node = dev->of_node; pscfg.drv_data = chg; chg_irq = platform_get_irq_byname(pdev, "CHG"); if (chg_irq < 0) return chg_irq; chgin_irq = platform_get_irq_byname(pdev, "CHGIN"); if (chgin_irq < 0) return chgin_irq; rv = devm_request_any_context_irq(dev, chg_irq, max77650_charger_check_status, IRQF_ONESHOT, "chg", chg); if (rv < 0) return rv; rv = devm_request_any_context_irq(dev, chgin_irq, max77650_charger_check_status, IRQF_ONESHOT, "chgin", chg); if (rv < 0) return rv; battery = devm_power_supply_register(dev, &max77650_battery_desc, &pscfg); if (IS_ERR(battery)) return PTR_ERR(battery); rv = of_property_read_u32(dev->of_node, "input-voltage-min-microvolt", &prop); if (rv == 0) { rv = max77650_charger_set_vchgin_min(chg, prop); if (rv) return rv; } rv = of_property_read_u32(dev->of_node, "input-current-limit-microamp", &prop); if (rv == 0) { rv = max77650_charger_set_ichgin_lim(chg, prop); if (rv) return rv; } return max77650_charger_enable(chg); }
static int gpio_charger_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; const struct gpio_charger_platform_data *pdata = dev->platform_data; struct power_supply_config psy_cfg = {}; struct gpio_charger *gpio_charger; struct power_supply_desc *charger_desc; unsigned long flags; int irq, ret; if (!pdata && !dev->of_node) { dev_err(dev, "No platform data\n"); return -ENOENT; } gpio_charger = devm_kzalloc(dev, sizeof(*gpio_charger), GFP_KERNEL); if (!gpio_charger) return -ENOMEM; /* * This will fetch a GPIO descriptor from device tree, ACPI or * boardfile descriptor tables. It's good to try this first. */ gpio_charger->gpiod = devm_gpiod_get(dev, NULL, GPIOD_IN); /* * If this fails and we're not using device tree, try the * legacy platform data method. */ if (IS_ERR(gpio_charger->gpiod) && !dev->of_node) { /* Non-DT: use legacy GPIO numbers */ if (!gpio_is_valid(pdata->gpio)) { dev_err(dev, "Invalid gpio pin in pdata\n"); return -EINVAL; } flags = GPIOF_IN; if (pdata->gpio_active_low) flags |= GPIOF_ACTIVE_LOW; ret = devm_gpio_request_one(dev, pdata->gpio, flags, dev_name(dev)); if (ret) { dev_err(dev, "Failed to request gpio pin: %d\n", ret); return ret; } /* Then convert this to gpiod for now */ gpio_charger->gpiod = gpio_to_desc(pdata->gpio); } else if (IS_ERR(gpio_charger->gpiod)) { /* Just try again if this happens */ if (PTR_ERR(gpio_charger->gpiod) == -EPROBE_DEFER) return -EPROBE_DEFER; dev_err(dev, "error getting GPIO descriptor\n"); return PTR_ERR(gpio_charger->gpiod); } charger_desc = &gpio_charger->charger_desc; charger_desc->properties = gpio_charger_properties; charger_desc->num_properties = ARRAY_SIZE(gpio_charger_properties); charger_desc->get_property = gpio_charger_get_property; psy_cfg.of_node = dev->of_node; psy_cfg.drv_data = gpio_charger; if (pdata) { charger_desc->name = pdata->name; charger_desc->type = pdata->type; psy_cfg.supplied_to = pdata->supplied_to; psy_cfg.num_supplicants = pdata->num_supplicants; } else { charger_desc->name = dev->of_node->name; charger_desc->type = gpio_charger_get_type(dev); } if (!charger_desc->name) charger_desc->name = pdev->name; gpio_charger->charger = devm_power_supply_register(dev, charger_desc, &psy_cfg); if (IS_ERR(gpio_charger->charger)) { ret = PTR_ERR(gpio_charger->charger); dev_err(dev, "Failed to register power supply: %d\n", ret); return ret; } irq = gpiod_to_irq(gpio_charger->gpiod); if (irq > 0) { ret = devm_request_any_context_irq(dev, irq, gpio_charger_irq, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, dev_name(dev), gpio_charger->charger); if (ret < 0) dev_warn(dev, "Failed to request irq: %d\n", ret); else gpio_charger->irq = irq; } platform_set_drvdata(pdev, gpio_charger); device_init_wakeup(dev, 1); 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 gpio_keys_setup_key(struct platform_device *pdev, struct input_dev *input, struct gpio_keys_drvdata *ddata, const struct gpio_keys_button *button, int idx, struct fwnode_handle *child) { const char *desc = button->desc ? button->desc : "gpio_keys"; struct device *dev = &pdev->dev; struct gpio_button_data *bdata = &ddata->data[idx]; irq_handler_t isr; unsigned long irqflags; int irq; int error; bdata->input = input; bdata->button = button; spin_lock_init(&bdata->lock); if (child) { bdata->gpiod = devm_fwnode_get_gpiod_from_child(dev, NULL, child, GPIOD_IN, desc); if (IS_ERR(bdata->gpiod)) { error = PTR_ERR(bdata->gpiod); if (error == -ENOENT) { /* * GPIO is optional, we may be dealing with * purely interrupt-driven setup. */ bdata->gpiod = NULL; } else { if (error != -EPROBE_DEFER) dev_err(dev, "failed to get gpio: %d\n", error); return error; } } } else if (gpio_is_valid(button->gpio)) { /* * Legacy GPIO number, so request the GPIO here and * convert it to descriptor. */ unsigned flags = GPIOF_IN; if (button->active_low) flags |= GPIOF_ACTIVE_LOW; error = devm_gpio_request_one(dev, button->gpio, flags, desc); if (error < 0) { dev_err(dev, "Failed to request GPIO %d, error %d\n", button->gpio, error); return error; } bdata->gpiod = gpio_to_desc(button->gpio); if (!bdata->gpiod) return -EINVAL; } if (bdata->gpiod) { if (button->debounce_interval) { error = gpiod_set_debounce(bdata->gpiod, button->debounce_interval * 1000); /* use timer if gpiolib doesn't provide debounce */ if (error < 0) bdata->software_debounce = button->debounce_interval; } if (button->irq) { bdata->irq = button->irq; } else { irq = gpiod_to_irq(bdata->gpiod); if (irq < 0) { error = irq; dev_err(dev, "Unable to get irq number for GPIO %d, error %d\n", button->gpio, error); return error; } bdata->irq = irq; } INIT_DELAYED_WORK(&bdata->work, gpio_keys_gpio_work_func); isr = gpio_keys_gpio_isr; irqflags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING; } else { if (!button->irq) { dev_err(dev, "Found button without gpio or irq\n"); return -EINVAL; } bdata->irq = button->irq; if (button->type && button->type != EV_KEY) { dev_err(dev, "Only EV_KEY allowed for IRQ buttons.\n"); return -EINVAL; } bdata->release_delay = button->debounce_interval; setup_timer(&bdata->release_timer, gpio_keys_irq_timer, (unsigned long)bdata); isr = gpio_keys_irq_isr; irqflags = 0; } bdata->code = &ddata->keymap[idx]; *bdata->code = button->code; input_set_capability(input, button->type ?: EV_KEY, *bdata->code); /* * Install custom action to cancel release timer and * workqueue item. */ error = devm_add_action(dev, gpio_keys_quiesce_key, bdata); if (error) { dev_err(dev, "failed to register quiesce action, error: %d\n", error); return error; } /* * If platform has specified that the button can be disabled, * we don't want it to share the interrupt line. */ if (!button->can_disable) irqflags |= IRQF_SHARED; error = devm_request_any_context_irq(dev, bdata->irq, isr, irqflags, desc, bdata); if (error < 0) { dev_err(dev, "Unable to claim irq %d; error %d\n", bdata->irq, error); return error; } return 0; }