in imu/inv_mpu6050/inv_mpu_core.c [1435:1646]
int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name,
int (*inv_mpu_bus_setup)(struct iio_dev *), int chip_type)
{
struct inv_mpu6050_state *st;
struct iio_dev *indio_dev;
struct inv_mpu6050_platform_data *pdata;
struct device *dev = regmap_get_device(regmap);
int result;
struct irq_data *desc;
int irq_type;
indio_dev = devm_iio_device_alloc(dev, sizeof(*st));
if (!indio_dev)
return -ENOMEM;
BUILD_BUG_ON(ARRAY_SIZE(hw_info) != INV_NUM_PARTS);
if (chip_type < 0 || chip_type >= INV_NUM_PARTS) {
dev_err(dev, "Bad invensense chip_type=%d name=%s\n",
chip_type, name);
return -ENODEV;
}
st = iio_priv(indio_dev);
mutex_init(&st->lock);
st->chip_type = chip_type;
st->irq = irq;
st->map = regmap;
pdata = dev_get_platdata(dev);
if (!pdata) {
result = iio_read_mount_matrix(dev, &st->orientation);
if (result) {
dev_err(dev, "Failed to retrieve mounting matrix %d\n",
result);
return result;
}
} else {
st->plat_data = *pdata;
}
if (irq > 0) {
desc = irq_get_irq_data(irq);
if (!desc) {
dev_err(dev, "Could not find IRQ %d\n", irq);
return -EINVAL;
}
irq_type = irqd_get_trigger_type(desc);
if (!irq_type)
irq_type = IRQF_TRIGGER_RISING;
} else {
/* Doesn't really matter, use the default */
irq_type = IRQF_TRIGGER_RISING;
}
if (irq_type & IRQF_TRIGGER_RISING) // rising or both-edge
st->irq_mask = INV_MPU6050_ACTIVE_HIGH;
else if (irq_type == IRQF_TRIGGER_FALLING)
st->irq_mask = INV_MPU6050_ACTIVE_LOW;
else if (irq_type == IRQF_TRIGGER_HIGH)
st->irq_mask = INV_MPU6050_ACTIVE_HIGH |
INV_MPU6050_LATCH_INT_EN;
else if (irq_type == IRQF_TRIGGER_LOW)
st->irq_mask = INV_MPU6050_ACTIVE_LOW |
INV_MPU6050_LATCH_INT_EN;
else {
dev_err(dev, "Invalid interrupt type 0x%x specified\n",
irq_type);
return -EINVAL;
}
st->vdd_supply = devm_regulator_get(dev, "vdd");
if (IS_ERR(st->vdd_supply))
return dev_err_probe(dev, PTR_ERR(st->vdd_supply),
"Failed to get vdd regulator\n");
st->vddio_supply = devm_regulator_get(dev, "vddio");
if (IS_ERR(st->vddio_supply))
return dev_err_probe(dev, PTR_ERR(st->vddio_supply),
"Failed to get vddio regulator\n");
result = regulator_enable(st->vdd_supply);
if (result) {
dev_err(dev, "Failed to enable vdd regulator: %d\n", result);
return result;
}
msleep(INV_MPU6050_POWER_UP_TIME);
result = inv_mpu_core_enable_regulator_vddio(st);
if (result) {
regulator_disable(st->vdd_supply);
return result;
}
result = devm_add_action_or_reset(dev, inv_mpu_core_disable_regulator_action,
st);
if (result) {
dev_err(dev, "Failed to setup regulator cleanup action %d\n",
result);
return result;
}
/* fill magnetometer orientation */
result = inv_mpu_magn_set_orient(st);
if (result)
return result;
/* power is turned on inside check chip type*/
result = inv_check_and_setup_chip(st);
if (result)
return result;
result = inv_mpu6050_init_config(indio_dev);
if (result) {
dev_err(dev, "Could not initialize device.\n");
goto error_power_off;
}
dev_set_drvdata(dev, indio_dev);
/* name will be NULL when enumerated via ACPI */
if (name)
indio_dev->name = name;
else
indio_dev->name = dev_name(dev);
/* requires parent device set in indio_dev */
if (inv_mpu_bus_setup) {
result = inv_mpu_bus_setup(indio_dev);
if (result)
goto error_power_off;
}
/* chip init is done, turning on runtime power management */
result = pm_runtime_set_active(dev);
if (result)
goto error_power_off;
pm_runtime_get_noresume(dev);
pm_runtime_enable(dev);
pm_runtime_set_autosuspend_delay(dev, INV_MPU6050_SUSPEND_DELAY_MS);
pm_runtime_use_autosuspend(dev);
pm_runtime_put(dev);
result = devm_add_action_or_reset(dev, inv_mpu_pm_disable, dev);
if (result)
return result;
switch (chip_type) {
case INV_MPU9150:
indio_dev->channels = inv_mpu9150_channels;
indio_dev->num_channels = ARRAY_SIZE(inv_mpu9150_channels);
indio_dev->available_scan_masks = inv_mpu9x50_scan_masks;
break;
case INV_MPU9250:
case INV_MPU9255:
indio_dev->channels = inv_mpu9250_channels;
indio_dev->num_channels = ARRAY_SIZE(inv_mpu9250_channels);
indio_dev->available_scan_masks = inv_mpu9x50_scan_masks;
break;
case INV_ICM20602:
indio_dev->channels = inv_mpu_channels;
indio_dev->num_channels = ARRAY_SIZE(inv_mpu_channels);
indio_dev->available_scan_masks = inv_icm20602_scan_masks;
break;
default:
indio_dev->channels = inv_mpu_channels;
indio_dev->num_channels = ARRAY_SIZE(inv_mpu_channels);
indio_dev->available_scan_masks = inv_mpu_scan_masks;
break;
}
/*
* Use magnetometer inside the chip only if there is no i2c
* auxiliary device in use. Otherwise Going back to 6-axis only.
*/
if (st->magn_disabled) {
indio_dev->channels = inv_mpu_channels;
indio_dev->num_channels = ARRAY_SIZE(inv_mpu_channels);
indio_dev->available_scan_masks = inv_mpu_scan_masks;
}
indio_dev->info = &mpu_info;
if (irq > 0) {
/*
* The driver currently only supports buffered capture with its
* own trigger. So no IRQ, no trigger, no buffer
*/
result = devm_iio_triggered_buffer_setup(dev, indio_dev,
iio_pollfunc_store_time,
inv_mpu6050_read_fifo,
NULL);
if (result) {
dev_err(dev, "configure buffer fail %d\n", result);
return result;
}
result = inv_mpu6050_probe_trigger(indio_dev, irq_type);
if (result) {
dev_err(dev, "trigger probe fail %d\n", result);
return result;
}
}
result = devm_iio_device_register(dev, indio_dev);
if (result) {
dev_err(dev, "IIO register fail %d\n", result);
return result;
}
return 0;
error_power_off:
inv_mpu6050_set_power_itg(st, false);
return result;
}