/** * adis_probe_trigger() - Sets up trigger for a adis device * @adis: The adis device * @indio_dev: The IIO device * * Returns 0 on success or a negative error code * * adis_remove_trigger() should be used to free the trigger. */ int adis_probe_trigger(struct adis *adis, struct iio_dev *indio_dev) { int ret; adis->trig = iio_trigger_alloc("%s-dev%d", indio_dev->name, indio_dev->id); if (adis->trig == NULL) return -ENOMEM; ret = request_irq(adis->spi->irq, &iio_trigger_generic_data_rdy_poll, IRQF_TRIGGER_RISING, indio_dev->name, adis->trig); if (ret) goto error_free_trig; adis->trig->dev.parent = &adis->spi->dev; adis->trig->ops = &adis_trigger_ops; iio_trigger_set_drvdata(adis->trig, adis); ret = iio_trigger_register(adis->trig); indio_dev->trig = iio_trigger_get(adis->trig); if (ret) goto error_free_irq; return 0; error_free_irq: free_irq(adis->spi->irq, adis->trig); error_free_trig: iio_trigger_free(adis->trig); return ret; }
int inv_mpu6050_probe_trigger(struct iio_dev *indio_dev) { int ret; struct inv_mpu6050_state *st = iio_priv(indio_dev); st->trig = iio_trigger_alloc("%s-dev%d", indio_dev->name, indio_dev->id); if (st->trig == NULL) { ret = -ENOMEM; goto error_ret; } ret = request_irq(st->client->irq, &iio_trigger_generic_data_rdy_poll, IRQF_TRIGGER_RISING, "inv_mpu", st->trig); if (ret) goto error_free_trig; st->trig->dev.parent = &st->client->dev; st->trig->ops = &inv_mpu_trigger_ops; iio_trigger_set_drvdata(st->trig, indio_dev); ret = iio_trigger_register(st->trig); if (ret) goto error_free_irq; indio_dev->trig = iio_trigger_get(st->trig); return 0; error_free_irq: free_irq(st->client->irq, st->trig); error_free_trig: iio_trigger_free(st->trig); error_ret: return ret; }
int hid_sensor_setup_trigger(struct iio_dev *indio_dev, const char *name, struct hid_sensor_common *attrb) { int ret; struct iio_trigger *trig; trig = iio_trigger_alloc("%s-dev%d", name, indio_dev->id); if (trig == NULL) { dev_err(&indio_dev->dev, "Trigger Allocate Failed\n"); ret = -ENOMEM; goto error_ret; } trig->dev.parent = indio_dev->dev.parent; iio_trigger_set_drvdata(trig, attrb); trig->ops = &hid_sensor_trigger_ops; ret = iio_trigger_register(trig); if (ret) { dev_err(&indio_dev->dev, "Trigger Register Failed\n"); goto error_free_trig; } attrb->trigger = trig; indio_dev->trig = iio_trigger_get(trig); return ret; error_free_trig: iio_trigger_free(trig); error_ret: return ret; }
int iio_trigger_set_immutable(struct iio_dev *indio_dev, struct iio_trigger *trig) { if (!indio_dev || !trig) return -EINVAL; mutex_lock(&indio_dev->mlock); WARN_ON(indio_dev->trig_readonly); indio_dev->trig = iio_trigger_get(trig); indio_dev->trig_readonly = true; mutex_unlock(&indio_dev->mlock); return 0; }
static struct iio_trigger *iio_trigger_acquire_by_name(const char *name) { struct iio_trigger *trig = NULL, *iter; mutex_lock(&iio_trigger_list_lock); list_for_each_entry(iter, &iio_trigger_list, list) if (sysfs_streq(iter->name, name)) { trig = iter; iio_trigger_get(trig); break; } mutex_unlock(&iio_trigger_list_lock); return trig; }
int hid_sensor_setup_trigger(struct iio_dev *indio_dev, const char *name, struct hid_sensor_common *attrb) { int ret; struct iio_trigger *trig; trig = iio_trigger_alloc("%s-dev%d", name, indio_dev->id); if (trig == NULL) { dev_err(&indio_dev->dev, "Trigger Allocate Failed\n"); ret = -ENOMEM; goto error_ret; } trig->dev.parent = indio_dev->dev.parent; iio_trigger_set_drvdata(trig, attrb); trig->ops = &hid_sensor_trigger_ops; ret = iio_trigger_register(trig); if (ret) { dev_err(&indio_dev->dev, "Trigger Register Failed\n"); goto error_free_trig; } attrb->trigger = trig; indio_dev->trig = iio_trigger_get(trig); ret = pm_runtime_set_active(&indio_dev->dev); if (ret) goto error_unreg_trigger; iio_device_set_drvdata(indio_dev, attrb); pm_suspend_ignore_children(&attrb->pdev->dev, true); pm_runtime_enable(&attrb->pdev->dev); /* Default to 3 seconds, but can be changed from sysfs */ pm_runtime_set_autosuspend_delay(&attrb->pdev->dev, 3000); pm_runtime_use_autosuspend(&attrb->pdev->dev); return ret; error_unreg_trigger: iio_trigger_unregister(trig); error_free_trig: iio_trigger_free(trig); error_ret: return ret; }
int st_sensors_allocate_trigger(struct iio_dev *indio_dev, const struct iio_trigger_ops *trigger_ops) { int err, irq; struct st_sensor_data *sdata = iio_priv(indio_dev); unsigned long irq_trig; sdata->trig = iio_trigger_alloc("%s-trigger", indio_dev->name); if (sdata->trig == NULL) { dev_err(&indio_dev->dev, "failed to allocate iio trigger.\n"); return -ENOMEM; } irq = sdata->get_irq_data_ready(indio_dev); irq_trig = irqd_get_trigger_type(irq_get_irq_data(irq)); /* * If the IRQ is triggered on falling edge, we need to mark the * interrupt as active low, if the hardware supports this. */ if (irq_trig == IRQF_TRIGGER_FALLING) { if (!sdata->sensor_settings->drdy_irq.addr_ihl) { dev_err(&indio_dev->dev, "falling edge specified for IRQ but hardware " "only support rising edge, will request " "rising edge\n"); irq_trig = IRQF_TRIGGER_RISING; } else { /* Set up INT active low i.e. falling edge */ err = st_sensors_write_data_with_mask(indio_dev, sdata->sensor_settings->drdy_irq.addr_ihl, sdata->sensor_settings->drdy_irq.mask_ihl, 1); if (err < 0) goto iio_trigger_free; dev_info(&indio_dev->dev, "interrupts on the falling edge\n"); } } else if (irq_trig == IRQF_TRIGGER_RISING) { dev_info(&indio_dev->dev, "interrupts on the rising edge\n"); } else { dev_err(&indio_dev->dev, "unsupported IRQ trigger specified (%lx), only " "rising and falling edges supported, enforce " "rising edge\n", irq_trig); irq_trig = IRQF_TRIGGER_RISING; } /* * If the interrupt pin is Open Drain, by definition this * means that the interrupt line may be shared with other * peripherals. But to do this we also need to have a status * register and mask to figure out if this sensor was firing * the IRQ or not, so we can tell the interrupt handle that * it was "our" interrupt. */ if (sdata->int_pin_open_drain && sdata->sensor_settings->drdy_irq.addr_stat_drdy) irq_trig |= IRQF_SHARED; err = request_threaded_irq(irq, iio_trigger_generic_data_rdy_poll, NULL, irq_trig, sdata->trig->name, sdata->trig); if (err) { dev_err(&indio_dev->dev, "failed to request trigger IRQ.\n"); goto iio_trigger_free; } iio_trigger_set_drvdata(sdata->trig, indio_dev); sdata->trig->ops = trigger_ops; sdata->trig->dev.parent = sdata->dev; err = iio_trigger_register(sdata->trig); if (err < 0) { dev_err(&indio_dev->dev, "failed to register iio trigger.\n"); goto iio_trigger_register_error; } indio_dev->trig = iio_trigger_get(sdata->trig); return 0; iio_trigger_register_error: free_irq(sdata->get_irq_data_ready(indio_dev), sdata->trig); iio_trigger_free: iio_trigger_free(sdata->trig); return err; }
static int mpu3050_trigger_probe(struct iio_dev *indio_dev, int irq) { struct mpu3050 *mpu3050 = iio_priv(indio_dev); unsigned long irq_trig; int ret; mpu3050->trig = devm_iio_trigger_alloc(&indio_dev->dev, "%s-dev%d", indio_dev->name, indio_dev->id); if (!mpu3050->trig) return -ENOMEM; /* Check if IRQ is open drain */ if (of_property_read_bool(mpu3050->dev->of_node, "drive-open-drain")) mpu3050->irq_opendrain = true; irq_trig = irqd_get_trigger_type(irq_get_irq_data(irq)); /* * Configure the interrupt generator hardware to supply whatever * the interrupt is configured for, edges low/high level low/high, * we can provide it all. */ switch (irq_trig) { case IRQF_TRIGGER_RISING: dev_info(&indio_dev->dev, "pulse interrupts on the rising edge\n"); break; case IRQF_TRIGGER_FALLING: mpu3050->irq_actl = true; dev_info(&indio_dev->dev, "pulse interrupts on the falling edge\n"); break; case IRQF_TRIGGER_HIGH: mpu3050->irq_latch = true; dev_info(&indio_dev->dev, "interrupts active high level\n"); /* * With level IRQs, we mask the IRQ until it is processed, * but with edge IRQs (pulses) we can queue several interrupts * in the top half. */ irq_trig |= IRQF_ONESHOT; break; case IRQF_TRIGGER_LOW: mpu3050->irq_latch = true; mpu3050->irq_actl = true; irq_trig |= IRQF_ONESHOT; dev_info(&indio_dev->dev, "interrupts active low level\n"); break; default: /* This is the most preferred mode, if possible */ dev_err(&indio_dev->dev, "unsupported IRQ trigger specified (%lx), enforce " "rising edge\n", irq_trig); irq_trig = IRQF_TRIGGER_RISING; break; } /* An open drain line can be shared with several devices */ if (mpu3050->irq_opendrain) irq_trig |= IRQF_SHARED; ret = request_threaded_irq(irq, mpu3050_irq_handler, mpu3050_irq_thread, irq_trig, mpu3050->trig->name, mpu3050->trig); if (ret) { dev_err(mpu3050->dev, "can't get IRQ %d, error %d\n", irq, ret); return ret; } mpu3050->irq = irq; mpu3050->trig->dev.parent = mpu3050->dev; mpu3050->trig->ops = &mpu3050_trigger_ops; iio_trigger_set_drvdata(mpu3050->trig, indio_dev); ret = iio_trigger_register(mpu3050->trig); if (ret) return ret; indio_dev->trig = iio_trigger_get(mpu3050->trig); return 0; }
int st_sensors_allocate_trigger(struct iio_dev *indio_dev, const struct iio_trigger_ops *trigger_ops) { int err, irq; struct st_sensor_data *sdata = iio_priv(indio_dev); unsigned long irq_trig; sdata->trig = iio_trigger_alloc("%s-trigger", indio_dev->name); if (sdata->trig == NULL) { dev_err(&indio_dev->dev, "failed to allocate iio trigger.\n"); return -ENOMEM; } irq = sdata->get_irq_data_ready(indio_dev); irq_trig = irqd_get_trigger_type(irq_get_irq_data(irq)); /* * If the IRQ is triggered on falling edge, we need to mark the * interrupt as active low, if the hardware supports this. */ if (irq_trig == IRQF_TRIGGER_FALLING) { if (!sdata->sensor_settings->drdy_irq.addr_ihl) { dev_err(&indio_dev->dev, "falling edge specified for IRQ but hardware " "only support rising edge, will request " "rising edge\n"); irq_trig = IRQF_TRIGGER_RISING; } else { /* Set up INT active low i.e. falling edge */ err = st_sensors_write_data_with_mask(indio_dev, sdata->sensor_settings->drdy_irq.addr_ihl, sdata->sensor_settings->drdy_irq.mask_ihl, 1); if (err < 0) goto iio_trigger_free; dev_info(&indio_dev->dev, "interrupts on the falling edge\n"); } } else if (irq_trig == IRQF_TRIGGER_RISING) { dev_info(&indio_dev->dev, "interrupts on the rising edge\n"); } else { dev_err(&indio_dev->dev, "unsupported IRQ trigger specified (%lx), only " "rising and falling edges supported, enforce " "rising edge\n", irq_trig); irq_trig = IRQF_TRIGGER_RISING; } err = request_threaded_irq(irq, iio_trigger_generic_data_rdy_poll, NULL, irq_trig, sdata->trig->name, sdata->trig); if (err) { dev_err(&indio_dev->dev, "failed to request trigger IRQ.\n"); goto iio_trigger_free; } iio_trigger_set_drvdata(sdata->trig, indio_dev); sdata->trig->ops = trigger_ops; sdata->trig->dev.parent = sdata->dev; err = iio_trigger_register(sdata->trig); if (err < 0) { dev_err(&indio_dev->dev, "failed to register iio trigger.\n"); goto iio_trigger_register_error; } indio_dev->trig = iio_trigger_get(sdata->trig); return 0; iio_trigger_register_error: free_irq(sdata->get_irq_data_ready(indio_dev), sdata->trig); iio_trigger_free: iio_trigger_free(sdata->trig); return err; }