From 12bbdac5a5c7cc357dc0c032ec34a76fddb9c4c2 Mon Sep 17 00:00:00 2001 From: Denis Date: Sun, 10 Sep 2023 16:42:18 +0200 Subject: [PATCH 1/4] debugging... --- drivers/iio/accel/bmc150-accel-core.c | 904 +++++++++++++++++++++++++- drivers/iio/accel/bmc150-accel-i2c.c | 83 ++- drivers/iio/accel/bmc150-accel.h | 43 +- drivers/iio/industrialio-core.c | 62 +- 4 files changed, 1077 insertions(+), 15 deletions(-) diff --git a/drivers/iio/accel/bmc150-accel-core.c b/drivers/iio/accel/bmc150-accel-core.c index 110591804b4c..1e634cc2f740 100644 --- a/drivers/iio/accel/bmc150-accel-core.c +++ b/drivers/iio/accel/bmc150-accel-core.c @@ -28,6 +28,9 @@ #define BMC150_ACCEL_DRV_NAME "bmc150_accel" #define BMC150_ACCEL_IRQ_NAME "bmc150_accel_event" +#define BMI323_IRQ_NAME "bmi323_event" + + #define BMC150_ACCEL_REG_CHIP_ID 0x00 #define BMC150_ACCEL_REG_INT_STATUS_2 0x0B @@ -50,6 +53,16 @@ #define BMC150_ACCEL_DEF_RANGE_8G 0x08 #define BMC150_ACCEL_DEF_RANGE_16G 0x0C +#define BMI323_ACCEL_DEF_RANGE_2G 0x03 +#define BMI323_ACCEL_DEF_RANGE_4G 0x05 +#define BMI323_ACCEL_DEF_RANGE_8G 0x20 // TODO: do the rest, this is only one true +#define BMI323_ACCEL_DEF_RANGE_16G 0x0C + +#define BMI323_GYRO_DEF_RANGE_2G 0x03 +#define BMI323_GYRO_DEF_RANGE_4G 0x05 +#define BMI323_GYRO_DEF_RANGE_2KDPS 0x40 // TODO: do the rest, this is only one true +#define BMI323_GYRO_DEF_RANGE_16G 0x0C + /* Default BW: 125Hz */ #define BMC150_ACCEL_REG_PMU_BW 0x10 #define BMC150_ACCEL_DEF_BW 125 @@ -130,6 +143,16 @@ #define BMC150_ACCEL_REG_FIFO_DATA 0x3F #define BMC150_ACCEL_FIFO_LENGTH 32 +enum bmi323_axis { + BMI323_ACCEL_AXIS_X = 0, + BMI323_ACCEL_AXIS_Y, + BMI323_ACCEL_AXIS_Z, + BMI323_GYRO_AXIS_X, + BMI323_GYRO_AXIS_Y, + BMI323_GYRO_AXIS_Z, + BMI323_AXIS_MAX, +}; + enum bmc150_accel_axis { AXIS_X, AXIS_Y, @@ -149,6 +172,11 @@ struct bmc150_scale_info { u8 reg_range; }; +struct bmi323_scale_info { + int scale; + u8 reg_range; +}; + struct bmc150_accel_chip_info { const char *name; u8 chip_id; @@ -170,6 +198,19 @@ static const struct { {1000, 0, 0x0E}, {2000, 0, 0x0F} }; +static const struct { + int val; + int val2; // IIO_VAL_INT_PLUS_MICRO + u8 bw_bits; +} bmi323_samp_freq_table[] = { {15, 620000, 0x08}, + {31, 260000, 0x09}, + {62, 500000, 0x0A}, + {125, 0, 0x0B}, + {250, 0, 0x0C}, + {500, 0, 0x0D}, + {1000, 0, 0x0E}, + {2000, 0, 0x0F} }; + static __maybe_unused const struct { int bw_bits; int msec; @@ -350,11 +391,20 @@ static int bmc150_accel_set_power_state(struct bmc150_accel_data *data, bool on) return 0; } + +static int bmi323_set_power_state(struct bmc150_accel_data *data, bool on) { + return 0; +} + #else static int bmc150_accel_set_power_state(struct bmc150_accel_data *data, bool on) { return 0; } + +static int bmi323_set_power_state(struct bmc150_accel_data *data, bool on) { + return 0; +} #endif #ifdef CONFIG_ACPI @@ -911,6 +961,20 @@ static ssize_t bmc150_accel_get_fifo_state(struct device *dev, return sprintf(buf, "%d\n", state); } +static const struct iio_mount_matrix * +bmi323_accel_get_mount_matrix(const struct iio_dev *indio_dev, + const struct iio_chan_spec *chan) +{ + struct bmc150_accel_data *data = iio_priv(indio_dev); + + return &data->orientation; +} + +static const struct iio_chan_spec_ext_info bmi323_accel_ext_info[] = { + //IIO_MOUNT_MATRIX(IIO_SHARED_BY_DIR, bmc150_accel_get_mount_matrix), + { } +}; + static const struct iio_mount_matrix * bmc150_accel_get_mount_matrix(const struct iio_dev *indio_dev, const struct iio_chan_spec *chan) @@ -1085,6 +1149,14 @@ static const struct attribute_group bmc150_accel_attrs_group = { .attrs = bmc150_accel_attributes, }; +static const struct iio_event_spec bmi323_accel_event = { + .type = IIO_EV_TYPE_ROC, + .dir = IIO_EV_DIR_EITHER, + .mask_separate = BIT(IIO_EV_INFO_VALUE) | + BIT(IIO_EV_INFO_ENABLE) | + BIT(IIO_EV_INFO_PERIOD) +}; + static const struct iio_event_spec bmc150_accel_event = { .type = IIO_EV_TYPE_ROC, .dir = IIO_EV_DIR_EITHER, @@ -1113,6 +1185,46 @@ static const struct iio_event_spec bmc150_accel_event = { .num_event_specs = 1 \ } +#define BMI323_ACCEL_CHANNEL(_axis, bits) { \ + .type = IIO_ACCEL, \ + .modified = 1, \ + .channel2 = IIO_MOD_##_axis, \ + /*.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),*/ \ + /*.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |*/ \ + /* BIT(IIO_CHAN_INFO_SAMP_FREQ),*/ \ + .scan_index = BMI323_ACCEL_AXIS_##_axis, \ + .scan_type = { \ + .sign = 's', \ + .realbits = (bits), \ + .storagebits = 16, \ + .shift = 16 - (bits), \ + .endianness = IIO_LE, \ + }, \ + /*.ext_info = bmi323_accel_ext_info,*/ \ + /*.event_spec = &bmi323_accel_event,*/ \ + /*.num_event_specs = 1*/ \ +} + +#define BMI323_GYRO_CHANNEL(_axis, bits) { \ + .type = IIO_ANGL_VEL, \ + .modified = 1, \ + .channel2 = IIO_MOD_##_axis, \ + /*.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),*/ \ + /*.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |*/ \ + /*BIT(IIO_CHAN_INFO_SAMP_FREQ),*/ \ + .scan_index = BMI323_GYRO_AXIS_##_axis, \ + .scan_type = { \ + .sign = 's', \ + .realbits = (bits), \ + .storagebits = 16, \ + .shift = 16 - (bits), \ + .endianness = IIO_LE, \ + }, \ + /*.ext_info = bmi323_accel_ext_info,*/ \ + /*.event_spec = &bmi323_accel_event,*/ \ + /*.num_event_specs = 1*/ \ +} + #define BMC150_ACCEL_CHANNELS(bits) { \ { \ .type = IIO_TEMP, \ @@ -1245,6 +1357,32 @@ static irqreturn_t bmc150_accel_trigger_handler(int irq, void *p) return IRQ_HANDLED; } +static irqreturn_t bmi323_trigger_handler(int irq, void *p) +{ + struct iio_poll_func *pf = p; + struct iio_dev *indio_dev = pf->indio_dev; + struct bmc150_accel_data *data = iio_priv(indio_dev); + int ret; + +/* + mutex_lock(&data->mutex); + ret = regmap_bulk_read(data->regmap, BMC150_ACCEL_REG_XOUT_L, + data->buffer, AXIS_MAX * 2); + mutex_unlock(&data->mutex); + if (ret < 0) + goto err_read; + + iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, + pf->timestamp); +err_read: +*/ + iio_trigger_notify_done(indio_dev->trig); + + + return IRQ_HANDLED; +} + + static void bmc150_accel_trig_reen(struct iio_trigger *trig) { struct bmc150_accel_trigger *t = iio_trigger_get_drvdata(trig); @@ -1590,12 +1728,21 @@ static const struct iio_buffer_setup_ops bmc150_accel_buffer_ops = { .postdisable = bmc150_accel_buffer_postdisable, }; +static const struct iio_buffer_setup_ops bmi323_buffer_ops = { +/* + .preenable = bmi323_buffer_preenable, + .postenable = bmi323_buffer_postenable, + .predisable = bmi323_buffer_predisable, + .postdisable = bmi323_buffer_postdisable, +*/ +}; + static int bmc150_accel_chip_init(struct bmc150_accel_data *data) { struct device *dev = regmap_get_device(data->regmap); int ret, i; unsigned int val; - + /* * Reset chip to get it in a known good state. A delay of 1.8ms after * reset is required according to the data sheets of supported chips. @@ -1679,7 +1826,7 @@ int bmc150_accel_core_probe(struct device *dev, struct regmap *regmap, int irq, data->regmap = regmap; data->type = type; - + if (!bmc150_apply_acpi_orientation(dev, &data->orientation)) { ret = iio_read_mount_matrix(dev, &data->orientation); if (ret) @@ -1711,8 +1858,10 @@ int bmc150_accel_core_probe(struct device *dev, struct regmap *regmap, int irq, msleep(5); ret = bmc150_accel_chip_init(data); - if (ret < 0) + if (ret < 0) { + // here data->dev_type == BMI323. I will return an error from here so that the caller can reinitialize the driver goto err_disable_regulators; + } mutex_init(&data->mutex); @@ -1826,12 +1975,728 @@ void bmc150_accel_core_remove(struct device *dev) } EXPORT_SYMBOL_NS_GPL(bmc150_accel_core_remove, IIO_BMC150); +/* =========================== BEGIN OF BCM323 FUNCTIONS ========================== */ +int bmc323_write_u16(struct bmi323_private_data *bmi323, u8 in_reg, u16 in_value) { + s32 ret; + + u16 send_val = cpu_to_le16(in_value); + + if (bmi323->i2c_client != NULL) { + ret = i2c_smbus_write_i2c_block_data(bmi323->i2c_client, in_reg, sizeof(in_value), (u8*)(&send_val)); + if (ret != 0) { + dev_err(&bmi323->i2c_client->dev, "error in i2c_smbus_write_i2c_block_data = %d: reg = 0x%02x, val = 0x%02x 0x%02x", (int)ret, in_reg, ((u8*)&in_value)[0], ((u8*)&in_value)[1]); + + return -2; + } + + dev_err(&bmi323->i2c_client->dev, "success in i2c_smbus_write_i2c_block_data = %d: reg = 0x%02x, val = 0x%02x 0x%02x", (int)ret, in_reg, ((u8*)&in_value)[0], ((u8*)&in_value)[1]); + + return 0; + } else if (bmi323->spi_client != NULL) { + return -4; // TODO: change with 0 once implemented + } + + return -3; +} +EXPORT_SYMBOL_NS_GPL(bmc323_write_u16, IIO_BMC150); + +int bmc323_read_u16(struct bmi323_private_data *bmi323, u8 in_reg, u16* out_value) { + s32 ret; + u8 read_bytes[4]; + + if (bmi323->i2c_client != NULL) { + ret = i2c_smbus_read_i2c_block_data(bmi323->i2c_client, in_reg, sizeof(read_bytes), &read_bytes[0]); + if (ret != 4) { + dev_err(bmi323->dev, "error in i2c_smbus_read_i2c_block_data = %d: reg = 0x%02x", (int)ret, in_reg); + return -2; + } + + // LSB = read_bytes[2] + // MSB = read_bytes[3] + u16 output = 0; + u8* o = (u8*)&output; + o[0] = read_bytes[2]; + o[1] = read_bytes[3]; + + //output = le16_to_cpu(output); // TODO: how does someone use this stuff? No documentation. IN? OUT? + *out_value = output; + + dev_err(bmi323->dev, "success in i2c_smbus_read_i2c_block_data = %d: reg = 0x%02x, val = 0x%02x 0x%02x", (int)ret, in_reg, read_bytes[2], read_bytes[3]); + + return 0; + } else if (bmi323->spi_client != NULL) { + printk(KERN_CRIT "bmi150 or bmi323: Using SPI interface?!?!? In a i2c driver? U crazy?!?!?\n"); + + + return -4; // TODO: change with 0 once implemented + } + + return -3; +} +EXPORT_SYMBOL_NS_GPL(bmc323_read_u16, IIO_BMC150); + +int bmc323_read_s16(struct bmi323_private_data *bmi323, u8 in_reg, s16* out_value) { + s32 ret; + u8 read_bytes[4]; + + if (bmi323->i2c_client != NULL) { + ret = i2c_smbus_read_i2c_block_data(bmi323->i2c_client, in_reg, sizeof(read_bytes), &read_bytes[0]); + if (ret != 4) { + dev_err(bmi323->dev, "error in i2c_smbus_read_i2c_block_data = %d: reg = 0x%02x", (int)ret, in_reg); + return -2; + } + + // LSB = read_bytes[2] + // MSB = read_bytes[3] + u16 output = 0; + u8* o = (u8*)&output; + o[0] = read_bytes[2]; + o[1] = read_bytes[3]; + + //output = le16_to_cpu(output); // TODO: how does someone use this stuff? No documentation. IN? OUT? + *((u16*)out_value) = output; + + dev_err(bmi323->dev, "success in i2c_smbus_read_i2c_block_data = %d: reg = 0x%02x, val = 0x%02x 0x%02x", (int)ret, in_reg, read_bytes[2], read_bytes[3]); + + return 0; + } else if (bmi323->spi_client != NULL) { + return -4; // TODO: change with 0 once implemented + } + + return -3; +} +EXPORT_SYMBOL_NS_GPL(bmc323_read_s16, IIO_BMC150); + +int bmi323_chip_check(struct bmi323_private_data *bmi323) +{ + u16 chip_id; + int ret; + + ret = bmc323_read_u16(bmi323, 0x00, &chip_id); + if (ret != 0) { + return -1; + } + + if (((chip_id) & 0x00FF) != 0x0043) { + dev_err(bmi323->dev, "bmi323_chip_check failed with: %d; chip_id = 0x%04x", ret, chip_id); + + return -2; + } + + return 0; +} +EXPORT_SYMBOL_NS_GPL(bmi323_chip_check, IIO_BMC150); + +/** + * Note: after issuing a reset the the chip will be in what it is called "suspended mode" and the feature angine is + * ready to be set. This mode has everything disabled and consumes aroud 15uA. + * + * When removing the driver or suspend has been requested it's best to reset the chip so that power consumption + * will be the lowest possible. + */ +int bmi323_chip_rst(struct bmi323_private_data *bmi323) { + u16 sensor_status = 0x0000, device_status = 0x0000; + int ret; + + ret = bmc323_write_u16(bmi323, BCM150_BMI323_SOFT_RESET_REG, BCM150_BMI323_SOFT_RESET_VAL); + if (ret != 0) { + return -1; + } + + /* wait the specified amount of time... better safe than sorry, no? :) */ + msleep(5); + + // if the device is connected over SPI a dummy read is to be performed once after each reset + if (bmi323->spi_client != NULL) { + dev_err(bmi323->dev, "issuing the dummy read to switch mode to SPI"); + + // do not even check the result of that... it's just a dummy read + bmi323_chip_check(bmi323); + } + + ret = bmi323_chip_check(bmi323); + if (ret != 0) { + return -2; + } + + // now check the correct initialization status as per datasheet + ret = bmc323_read_u16(bmi323, 0x01, &device_status); + if (ret != 0) { + return -3; + } + + if ((device_status & 0x00FF) != 0x0000) { + dev_err(bmi323->dev, "bmi323: device_status incorrect: %d; device_status = 0x%04x", ret, device_status); + + // power error + return -4; + } + + // power ok + ret = bmc323_read_u16(bmi323, 0x02, &sensor_status); + if (ret != 0) { + return -5; + } + + if ((sensor_status & 0x00FF) != 0x0001) { + if (bmi323->i2c_client != NULL) { + dev_err(&bmi323->i2c_client->dev, "bmi323: sensor_status incorrect: %d; sensor_status = 0x%04x", ret, sensor_status); + } else if (bmi323->spi_client != NULL) { + dev_err(&bmi323->spi_client->dev, "bmi323: sensor_status incorrect: %d; sensor_status = 0x%04x", ret, sensor_status); + } + + // initialization error + return -6; + } + + // initialization ok + return 0; +} +EXPORT_SYMBOL_NS_GPL(bmi323_chip_rst, IIO_BMC150); + +static const struct iio_chan_spec bmi323_channels[] = { + { + .type = IIO_TEMP, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_SCALE) | + BIT(IIO_CHAN_INFO_OFFSET), + .scan_index = -1, + }, + BMI323_ACCEL_CHANNEL(X, 16), + BMI323_ACCEL_CHANNEL(Y, 16), + BMI323_ACCEL_CHANNEL(Z, 16), + BMI323_GYRO_CHANNEL(X, 16), + BMI323_GYRO_CHANNEL(Y, 16), + BMI323_GYRO_CHANNEL(Z, 16), + IIO_CHAN_SOFT_TIMESTAMP(6), +}; + +/* +static struct attribute *bmi323_accel_attributes[] = { + &iio_const_attr_sampling_frequency_available.dev_attr.attr, + NULL, +}; +*/ + +static const struct attribute_group bmi323_accel_attrs_group = { + //.attrs = bmi323_accel_attributes, +}; + +static const struct bmi323_scale_info bmi323_accel_scale_table[] = { + {153229, BMI323_ACCEL_DEF_RANGE_2G}, + {306458, BMI323_ACCEL_DEF_RANGE_4G}, + {612916, BMI323_ACCEL_DEF_RANGE_8G}, + {1225831, BMI323_ACCEL_DEF_RANGE_16G} +}; + +static const struct bmi323_scale_info bmi323_gyro_scale_table[] = { + {153229, BMI323_GYRO_DEF_RANGE_2G}, + {306458, BMI323_GYRO_DEF_RANGE_4G}, + {612916, BMI323_GYRO_DEF_RANGE_2KDPS}, + {1225831, BMI323_GYRO_DEF_RANGE_16G} +}; + +static int bmi323_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + struct bmc150_accel_data *data = iio_priv(indio_dev); + int ret; + u16 raw_read = 0x8000; + u8 reg = 0x00; + + printk(KERN_CRIT "bmc150 bmi323_read_raw\n"); + + switch (mask) { + case IIO_CHAN_INFO_RAW: + { + switch (chan->type) { + case IIO_TEMP: + reg = 0x09; + ret = bmc323_read_s16(&data->bmi323, reg, &raw_read); + if (ret != 0) { + //return -EBUSY; + return -EINVAL; + } + + *val = cpu_to_le32((int)raw_read); + return IIO_VAL_INT; + + case IIO_ACCEL: + if (iio_buffer_enabled(indio_dev)) { + //return -EBUSY; + return -EINVAL; + } + + reg = 0x03 + (u8)(chan->scan_index); + + ret = bmc323_read_s16(&data->bmi323, reg, &raw_read); + if (ret != 0) { + return -EINVAL; + } + *val = cpu_to_le32((int)raw_read); + return IIO_VAL_INT; + + case IIO_ANGL_VEL: + if (iio_buffer_enabled(indio_dev)) { + //return -EBUSY; + return -EINVAL; + } + + reg = 0x03 + (u8)(chan->scan_index); + + ret = bmc323_read_s16(&data->bmi323, reg, &raw_read); + if (ret != 0) { + return -EINVAL; + } + *val = cpu_to_le32((int)raw_read); + return IIO_VAL_INT; + default: + return -EINVAL; + } + } + case IIO_CHAN_INFO_OFFSET: + { + if (chan->type == IIO_TEMP) { + *val = BMC150_ACCEL_TEMP_CENTER_VAL; + return IIO_VAL_INT; + } + + return -EINVAL; + } + case IIO_CHAN_INFO_SCALE: + *val = 0; + switch (chan->type) { + case IIO_TEMP: + *val2 = 500000; + return IIO_VAL_INT_PLUS_MICRO; + case IIO_ACCEL: + { + int i; + const struct bmi323_scale_info *si = &bmi323_accel_scale_table[2]; + int st_size = ARRAY_SIZE(bmi323_accel_scale_table); + + // TODO: hardcoded for now + *val2 = si->scale; + return IIO_VAL_INT_PLUS_MICRO; +/* + for (i = 0; i < st_size; ++i) { + si = &data->chip_info->scale_table[i]; + if (si->reg_range == data->range) { + *val2 = si->scale; + return IIO_VAL_INT_PLUS_MICRO; + } + } +*/ + return -EINVAL; + } + case IIO_ANGL_VEL: + { + int i; + const struct bmi323_scale_info *si = &bmi323_gyro_scale_table[2]; + int st_size = ARRAY_SIZE(bmi323_gyro_scale_table); + + // TODO: hardcoded for now + *val2 = si->scale; + return IIO_VAL_INT_PLUS_MICRO; + +/* + for (i = 0; i < st_size; ++i) { + si = &data->chip_info->scale_table[i]; + if (si->reg_range == data->range) { + *val2 = si->scale; + return IIO_VAL_INT_PLUS_MICRO; + } + } +*/ + + return -EINVAL; + } + + default: + return -EINVAL; + } + case IIO_CHAN_INFO_SAMP_FREQ: + switch (chan->type) { + case IIO_TEMP: + *val = 0; + *val2 = 0; + return IIO_VAL_INT_PLUS_MICRO; + + case IIO_ACCEL: + *val = 0; + *val2 = 0; + return IIO_VAL_INT_PLUS_MICRO; + + case IIO_ANGL_VEL: + *val = 0; + *val2 = 0; + return IIO_VAL_INT_PLUS_MICRO; + } + + return -EINVAL; + /* + mutex_lock(&data->mutex); + ret = bmc150_accel_get_bw(data, val, val2); + mutex_unlock(&data->mutex); + return ret; + */ + default: + return -EINVAL; + } +} + +static int bmi323_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, int val2, long mask) +{ + struct bmc150_accel_data *data = iio_priv(indio_dev); + int ret; + + printk(KERN_CRIT "bmc150 bmi323_write_raw\n"); + +/* + switch (mask) { + case IIO_CHAN_INFO_SAMP_FREQ: + mutex_lock(&data->mutex); + ret = bmc150_accel_set_bw(data, val, val2); + mutex_unlock(&data->mutex); + break; + case IIO_CHAN_INFO_SCALE: + if (val) + return -EINVAL; + + mutex_lock(&data->mutex); + ret = bmc150_accel_set_scale(data, val2); + mutex_unlock(&data->mutex); + return ret; + default: + ret = -EINVAL; + } +*/ + + return ret; +} + +static int bmi323_read_event(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + enum iio_event_info info, + int *val, int *val2) +{ + struct bmc150_accel_data *data = iio_priv(indio_dev); + + printk(KERN_CRIT "bmc150 bmi323_read_event\n"); + +/* + *val2 = 0; + switch (info) { + case IIO_EV_INFO_VALUE: + *val = data->slope_thres; + break; + case IIO_EV_INFO_PERIOD: + *val = data->slope_dur; + break; + default: + return -EINVAL; + } +*/ + + return IIO_VAL_INT; +} + +static int bmi323_write_event(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + enum iio_event_info info, + int val, int val2) +{ + struct bmc150_accel_data *data = iio_priv(indio_dev); + + printk(KERN_CRIT "bmc150 bmi323_write_event\n"); + +/* + if (data->ev_enable_state) + return -EBUSY; + + switch (info) { + case IIO_EV_INFO_VALUE: + data->slope_thres = val & BMC150_ACCEL_SLOPE_THRES_MASK; + break; + case IIO_EV_INFO_PERIOD: + data->slope_dur = val & BMC150_ACCEL_SLOPE_DUR_MASK; + break; + default: + return -EINVAL; + } +*/ + + return 0; +} + +static int bmi323_read_event_config(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir) +{ + struct bmc150_accel_data *data = iio_priv(indio_dev); + + printk(KERN_CRIT "bmc150 bmi323_read_event_config\n"); + + return 0; +} + +static int bmi323_write_event_config(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + int state) +{ + struct bmc150_accel_data *data = iio_priv(indio_dev); + int ret; + + printk(KERN_CRIT "bmc150 bmi323_write_event_config\n"); + +/* + if (state == data->ev_enable_state) + return 0; + + mutex_lock(&data->mutex); + + ret = bmc150_accel_set_interrupt(data, BMC150_ACCEL_INT_ANY_MOTION, + state); + if (ret < 0) { + mutex_unlock(&data->mutex); + return ret; + } + + data->ev_enable_state = state; + mutex_unlock(&data->mutex); +*/ + + return 0; +} + +static const struct iio_info bmi323_accel_info = { + .attrs = &bmi323_accel_attrs_group, + .read_raw = bmi323_read_raw, + //.write_raw = bmi323_write_raw, + //.read_event_value = bmi323_read_event, + //.write_event_value = bmi323_write_event, + //.write_event_config = bmi323_write_event_config, + //.read_event_config = bmc150_accel_read_event_config, +}; + + +/** + * iio_simple_dummy_trigger_h() - the trigger handler function + * @irq: the interrupt number + * @p: private data - always a pointer to the poll func. + * + * This is the guts of buffered capture. On a trigger event occurring, + * if the pollfunc is attached then this handler is called as a threaded + * interrupt (and hence may sleep). It is responsible for grabbing data + * from the device and pushing it into the associated buffer. + */ +static irqreturn_t iio_bmi323_trigger_h(int irq, void *p) +{ + struct iio_poll_func *pf = p; + struct iio_dev *indio_dev = pf->indio_dev; + u16 *data; + struct bmc150_accel_data *indio_data = iio_priv(indio_dev); + + /*data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL); + if (!data) + goto bmi323_irq_done;*/ + + /* + CHANNEL scan_index + ========================== + TEMP -1 + ACCEL_X 0 + ACCEL_Y 1 + ACCEL_Y 2 + GYRO_X 3 + GYRO_Y 4 + GYRO_Z 5 + TIMESTAMP ? + */ + + /*int ret = 0; + u8 read_bytes[] = { 0xFF, 0xFF, 0xFF, 0xFF}; + int d_idx = 0; + u8 reg = 0x03; + for (u32 i = 0; i < indio_dev->masklength; ++i) { + if (((0x0001U << i) & (*indio_dev->active_scan_mask)) != 0) { + + struct i2c_client* i2c_dev = indio_data->bmi323.i2c_client; + if (i2c_dev != NULL) { + ret = i2c_smbus_read_i2c_block_data(i2c_dev, reg + i, sizeof(read_bytes), &read_bytes[0]); + if (ret != 4) { + goto bmi323_irq_done; + } + + data[d_idx++] = ((u16)read_bytes[2] << (u16)8U) | ((u16)read_bytes[3]); + } else { + // TODO: what about SPI? + goto bmi323_irq_done; + } + } + }*/ + + /* + * Three common options here: + * hardware scans: + * certain combinations of channels make up a fast read. The capture + * will consist of all of them. Hence we just call the grab data + * function and fill the buffer without processing. + * software scans: + * can be considered to be random access so efficient reading is just + * a case of minimal bus transactions. + * software culled hardware scans: + * occasionally a driver may process the nearest hardware scan to avoid + * storing elements that are not desired. This is the fiddliest option + * by far. + * Here let's pretend we have random access. And the values are in the + * constant table fakedata. + */ + int j = 0, i = 0; + for_each_set_bit(j, indio_dev->active_scan_mask, indio_dev->masklength) + data[i++] = 0xFFFF; + + iio_push_to_buffers_with_timestamp(indio_dev, data, + iio_get_time_ns(indio_dev)); + + kfree(data); + +bmi323_irq_done: + /* + * Tell the core we are done with this trigger and ready for the + * next one. + */ + iio_trigger_notify_done(indio_dev->trig); + + return IRQ_HANDLED; +} + +/* +BMI323_GYRO_AXIS_Z, +*/ +static const unsigned long bmi323_accel_scan_masks[] = { + BIT(BMI323_ACCEL_AXIS_X) | BIT(BMI323_ACCEL_AXIS_Y) | BIT(BMI323_ACCEL_AXIS_Z), + BIT(BMI323_GYRO_AXIS_X) | BIT(BMI323_GYRO_AXIS_Y) | BIT(BMI323_GYRO_AXIS_Z), + 0}; + +int bmi323_iio_init(struct iio_dev *indio_dev) { + const struct iio_dev_attr **fifo_attrs = NULL; + struct bmc150_accel_data *data = iio_priv(indio_dev); + struct device* dev = NULL; + + if (data->bmi323.i2c_client != NULL) { + data->bmi323.dev = &data->bmi323.i2c_client->dev; + } else if (&data->bmi323.spi_client != NULL) { + data->bmi323.dev = &data->bmi323.spi_client->dev; + } else { + return -ENODEV; + } + + int ret = 0; + + mutex_init(&data->bmi323.mutex); + + // now set normal mode... + // normal mode: 0x4000 + // no averaging: 0x0000 + // range 8g: 0x0020 + // ODR 50Hz: 0x0007 + ret = bmc323_write_u16(&data->bmi323, 0x20, 0x4027); + if (ret != 0) { + return -1; + } + + // now set normal mode... + // normal mode: 0x4000 + // no averaging: 0x0000 + // filtering to ODR/2: 0x0000 + // range: 2kdps: 0x0040 + // ODR 800Hz + ret = bmc323_write_u16(&data->bmi323, 0x21, 0x4027); + if (ret != 0) { + return -2; + } + + indio_dev->channels = bmi323_channels; + indio_dev->num_channels = ARRAY_SIZE(bmi323_channels); + indio_dev->name = "bmi323"; + indio_dev->available_scan_masks = bmi323_accel_scan_masks; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->info = &bmi323_accel_info; + + /* + ret = iio_triggered_buffer_setup_ext(indio_dev, + &iio_pollfunc_store_time, + bmi323_trigger_handler, + IIO_BUFFER_DIRECTION_IN, + &bmi323_buffer_ops, + fifo_attrs); + if (ret < 0) { + dev_err(dev, "Failed: iio triggered buffer setup\n"); + return -500; + } + */ + + ret = iio_triggered_buffer_setup(indio_dev, NULL, + iio_bmi323_trigger_h, + &bmi323_buffer_ops); + if (ret < 0) { + dev_err(dev, "Failed: iio triggered buffer setup\n"); + return -500; + } + + if (data->bmi323.irq > 0) { + dev_err(data->bmi323.dev, "IRQ pin connected: %d :)", data->bmi323.irq); + } else { + dev_err(data->bmi323.dev, "IRQ pin NOT connected: %d :(", data->bmi323.irq); + } + + // TODO: look at https://www.kernel.org/doc/html/latest/driver-api/iio/core.html + ret = iio_device_register(indio_dev); + if (ret < 0) { + //dev_err(dev, "bmi323 unable to register iio device\n"); + return ret; + } + + return 0; +} +EXPORT_SYMBOL_NS_GPL(bmi323_iio_init, IIO_BMC150); + + +/* ============================ END OF BCM323 FUNCTIONS =========================== */ + #ifdef CONFIG_PM_SLEEP static int bmc150_accel_suspend(struct device *dev) { struct iio_dev *indio_dev = dev_get_drvdata(dev); struct bmc150_accel_data *data = iio_priv(indio_dev); + int ret; + + if (data->dev_type == BMI323) { + dev_err(dev, "bmi323 suspending driver..."); + + ret = bmi323_chip_rst(&data->bmi323); + if (ret != 0) { + data->bmi323.flags |= BMI323_FLAGS_RESET_FAILED; + + dev_err(dev, "bmi323 error in resetting the chip on suspend: will sleep in high consumption mode."); + } + + // TODO: do something here + return 0; + } + mutex_lock(&data->mutex); bmc150_accel_set_mode(data, BMC150_ACCEL_SLEEP_MODE_SUSPEND, 0); mutex_unlock(&data->mutex); @@ -1844,6 +2709,29 @@ static int bmc150_accel_resume(struct device *dev) struct iio_dev *indio_dev = dev_get_drvdata(dev); struct bmc150_accel_data *data = iio_priv(indio_dev); + int ret; + + if (data->dev_type == BMI323) { + dev_err(dev, "bmi323 resuming driver..."); + + if ((data->bmi323.flags & BMI323_FLAGS_RESET_FAILED) != 0) { + dev_err(dev, "bmi323 was left in a dirty state: resetting the chip now..."); + + ret = bmi323_chip_rst(&data->bmi323); + if (ret != 0) { + dev_err(dev, "bmi323 error in resetting the chip on resume. All hope is gone."); + + return ret; + } + + data->bmi323.flags &= ~BMI323_FLAGS_RESET_FAILED; + } + + // TODO: set the correct power mode (and re-enable triggers?) + + return 0; + } + mutex_lock(&data->mutex); bmc150_accel_set_mode(data, BMC150_ACCEL_SLEEP_MODE_NORMAL, 0); bmc150_accel_fifo_set_mode(data); @@ -1863,6 +2751,11 @@ static int bmc150_accel_runtime_suspend(struct device *dev) struct bmc150_accel_data *data = iio_priv(indio_dev); int ret; + if (data->dev_type == BMI323) { + // TODO: do something here + return 0; + } + ret = bmc150_accel_set_mode(data, BMC150_ACCEL_SLEEP_MODE_SUSPEND, 0); if (ret < 0) return -EAGAIN; @@ -1877,6 +2770,11 @@ static int bmc150_accel_runtime_resume(struct device *dev) int ret; int sleep_val; + if (data->dev_type == BMI323) { + // TODO: do something here + return 0; + } + ret = bmc150_accel_set_mode(data, BMC150_ACCEL_SLEEP_MODE_NORMAL, 0); if (ret < 0) return ret; diff --git a/drivers/iio/accel/bmc150-accel-i2c.c b/drivers/iio/accel/bmc150-accel-i2c.c index ee1ba134ad42..c30198489e1a 100644 --- a/drivers/iio/accel/bmc150-accel-i2c.c +++ b/drivers/iio/accel/bmc150-accel-i2c.c @@ -173,16 +173,70 @@ static void bmc150_acpi_dual_accel_remove(struct i2c_client *client) {} static int bmc150_accel_probe(struct i2c_client *client) { + int ret; + u8 chip_id_first[4]; + enum bmc150_device_type dev_type = BMC150; const struct i2c_device_id *id = i2c_client_get_device_id(client); struct regmap *regmap; const char *name = NULL; enum bmc150_type type = BOSCH_UNKNOWN; - bool block_supported = + bool block_supported = false; + + ret = i2c_smbus_read_i2c_block_data(client, 0x00, 4, &chip_id_first[0]); + if (ret != 4) { + dev_err(&client->dev, "error in i2c_smbus_read_i2c_block_data = %d: reg = 0x%02x", (int)ret, 0x00); + goto bmi150_old_probe; + } + + if (chip_id_first[2] != 0x43) { + dev_err(&client->dev, "chip is not a bmi323."); + } else { + dev_err(&client->dev, "chip is a bmi323!"); + dev_type = BMI323; + } + + if (dev_type == BMI323) { + /*dev_warn*/ dev_err(&client->dev, "bmc323: the bmc150 is for sure a bmc323...\n"); + + struct iio_dev *indio_dev = devm_iio_device_alloc(&client->dev, sizeof(struct bmc150_accel_data)); + if (!indio_dev) { + dev_err(&client->dev, "bmc323: out of memory\n"); + + return -ENOMEM; + } + + dev_set_drvdata(&client->dev, indio_dev); + struct bmc150_accel_data *data = iio_priv(indio_dev); + + struct bmi323_private_data* bmi323_data = &data->bmi323; + bmi323_data->i2c_client = client; + bmi323_data->spi_client = NULL; + bmi323_data->irq = client->irq; + + ret = bmi323_chip_rst(bmi323_data); + if (ret != 0) { + dev_err(&client->dev, "bmc323: error issuing the chip reset: %d\n", ret); + return ret; + } + + /*dev_info*/ dev_err(&client->dev, "bmc323: chip rst success\n"); + + ret = bmi323_iio_init(indio_dev); + if (ret != 0) { + return ret; + } + + return 0; + } + +bmi150_old_probe: + dev_err(&client->dev, "executing the normal procedure for a bmc150..."); + + block_supported = i2c_check_functionality(client->adapter, I2C_FUNC_I2C) || i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_I2C_BLOCK); - int ret; - + regmap = devm_regmap_init_i2c(client, &bmc150_regmap_conf); if (IS_ERR(regmap)) { dev_err(&client->dev, "Failed to initialize i2c regmap\n"); @@ -196,9 +250,10 @@ static int bmc150_accel_probe(struct i2c_client *client) ret = bmc150_accel_core_probe(&client->dev, regmap, client->irq, type, name, block_supported); - if (ret) + if (ret) { return ret; - + } + /* * The !id check avoids recursion when probe() gets called * for the second client. @@ -211,6 +266,24 @@ static int bmc150_accel_probe(struct i2c_client *client) static void bmc150_accel_remove(struct i2c_client *client) { + struct iio_dev *indio_dev = dev_get_drvdata(&client->dev); + struct bmc150_accel_data *data = iio_priv(indio_dev); + + if (data->dev_type == BMI323) { + /*dev_info*/ dev_err(&client->dev, "bmc323 removing driver...\n"); + + iio_device_unregister(indio_dev); + + /*dev_info*/ dev_err(&client->dev, "bmc323 deallocating driver storage...\n"); + + iio_device_free(indio_dev); + + /*dev_info*/ dev_err(&client->dev, "bmc323 removal done.\n"); + + // TODO: create and call functions for bmi323 + return; + } + bmc150_acpi_dual_accel_remove(client); bmc150_accel_core_remove(&client->dev); diff --git a/drivers/iio/accel/bmc150-accel.h b/drivers/iio/accel/bmc150-accel.h index 7775c5edaeef..6d7d99ee4ae5 100644 --- a/drivers/iio/accel/bmc150-accel.h +++ b/drivers/iio/accel/bmc150-accel.h @@ -8,6 +8,9 @@ #include #include +#include +#include + struct regmap; struct i2c_client; struct bmc150_accel_chip_info; @@ -34,6 +37,11 @@ struct bmc150_accel_interrupt { atomic_t users; }; +enum bmc150_device_type { + BMC150, + BMI323, +}; + struct bmc150_accel_trigger { struct bmc150_accel_data *data; struct iio_trigger *indio_trig; @@ -55,6 +63,17 @@ enum bmc150_accel_trigger_id { BMC150_ACCEL_TRIGGERS, }; +#define BMI323_FLAGS_RESET_FAILED 0x00000001U + +struct bmi323_private_data { + struct i2c_client* i2c_client; + struct spi_device* spi_client; + struct device* dev; // pointer at i2c_client->dev or spi_client->dev + struct mutex mutex; + int irq; + uint32_t flags; +}; + struct bmc150_accel_data { struct regmap *regmap; struct regulator_bulk_data regulators[2]; @@ -83,7 +102,29 @@ struct bmc150_accel_data { void (*resume_callback)(struct device *dev); struct delayed_work resume_work; struct iio_mount_matrix orientation; -}; + enum bmc150_device_type dev_type; + struct bmi323_private_data bmi323; + }; + +#define BCM150_BMI323_SOFT_RESET_REG 0x7E +#define BCM150_BMI323_SOFT_RESET_VAL 0xDEAF + + + +int bmc323_write_u16(struct bmi323_private_data *bmi323, u8 in_reg, u16 in_value); +int bmc323_read_s16(struct bmi323_private_data *bmi323, u8 in_reg, s16* out_value); +int bmc323_read_u16(struct bmi323_private_data *bmi323, u8 in_reg, u16* out_value); +int bmi323_chip_check(struct bmi323_private_data *bmi323); +int bmi323_chip_rst(struct bmi323_private_data *bmi323); + +/** + * This function MUST be called in probe and is responsible for registering the userspace sysfs. + * + * The indio_dev MUST have been allocated but not registered. This function will perform userspace registration. + * + * @param indio_dev the industrual io device already allocated but not yet registered + */ +int bmi323_iio_init(struct iio_dev *indio_dev); int bmc150_accel_core_probe(struct device *dev, struct regmap *regmap, int irq, enum bmc150_type type, const char *name, diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c index adcba832e6fa..f1e0af45c9fd 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c @@ -1523,8 +1523,10 @@ static int iio_device_register_sysfs(struct iio_dev *indio_dev) if (chan->type == IIO_TIMESTAMP) clk = &dev_attr_current_timestamp_clock.attr; - + + dev_err(NULL, " begin iio_device_add_channel_sysfs #%d/%d", i, (int)indio_dev->num_channels); ret = iio_device_add_channel_sysfs(indio_dev, chan); + dev_err(NULL, " end iio_device_add_channel_sysfs #%d/%d", i, (int)indio_dev->num_channels); if (ret < 0) goto error_clear_attrs; attrcount += ret; @@ -1540,20 +1542,24 @@ static int iio_device_register_sysfs(struct iio_dev *indio_dev) if (clk) attrcount++; + dev_err(NULL, " begin kcalloc"); iio_dev_opaque->chan_attr_group.attrs = kcalloc(attrcount + 1, sizeof(iio_dev_opaque->chan_attr_group.attrs[0]), GFP_KERNEL); + dev_err(NULL, " end kcalloc"); if (iio_dev_opaque->chan_attr_group.attrs == NULL) { ret = -ENOMEM; goto error_clear_attrs; } /* Copy across original attributes, and point to original binary attributes */ if (indio_dev->info->attrs) { + dev_err(NULL, " begin memcpy"); memcpy(iio_dev_opaque->chan_attr_group.attrs, indio_dev->info->attrs->attrs, sizeof(iio_dev_opaque->chan_attr_group.attrs[0]) *attrcount_orig); + dev_err(NULL, " end memcpy"); iio_dev_opaque->chan_attr_group.is_visible = indio_dev->info->attrs->is_visible; iio_dev_opaque->chan_attr_group.bin_attrs = @@ -1561,8 +1567,10 @@ static int iio_device_register_sysfs(struct iio_dev *indio_dev) } attrn = attrcount_orig; /* Add all elements from the list. */ + dev_err(NULL, " begin list_for_each_entry"); list_for_each_entry(p, &iio_dev_opaque->channel_attr_list, l) iio_dev_opaque->chan_attr_group.attrs[attrn++] = &p->dev_attr.attr; + dev_err(NULL, " end list_for_each_entry"); if (indio_dev->name) iio_dev_opaque->chan_attr_group.attrs[attrn++] = &dev_attr_name.attr; if (indio_dev->label) @@ -1570,15 +1578,19 @@ static int iio_device_register_sysfs(struct iio_dev *indio_dev) if (clk) iio_dev_opaque->chan_attr_group.attrs[attrn++] = clk; + dev_err(NULL, " begin iio_device_register_sysfs_group"); ret = iio_device_register_sysfs_group(indio_dev, &iio_dev_opaque->chan_attr_group); + dev_err(NULL, " end iio_device_register_sysfs_group"); if (ret) goto error_clear_attrs; return 0; error_clear_attrs: + dev_err(NULL, " ERROR HERE: begin iio_free_chan_devattr_list"); iio_free_chan_devattr_list(&iio_dev_opaque->channel_attr_list); + dev_err(NULL, " ERROR HERE: end iio_free_chan_devattr_list"); return ret; } @@ -1856,8 +1868,8 @@ static int iio_check_unique_scan_index(struct iio_dev *indio_dev) for (j = i + 1; j < indio_dev->num_channels; j++) if (channels[i].scan_index == channels[j].scan_index) { dev_err(&indio_dev->dev, - "Duplicate scan index %d\n", - channels[i].scan_index); + "Duplicate scan index %d at elements (%d, %d)\n", + channels[i].scan_index, i , j); return -EINVAL; } } @@ -1887,6 +1899,7 @@ static const struct iio_buffer_setup_ops noop_ring_setup_ops; int __iio_device_register(struct iio_dev *indio_dev, struct module *this_mod) { + dev_err(NULL, "begin __iio_device_register\n"); struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); struct fwnode_handle *fwnode = NULL; int ret; @@ -1894,6 +1907,8 @@ int __iio_device_register(struct iio_dev *indio_dev, struct module *this_mod) if (!indio_dev->info) return -EINVAL; + dev_err(NULL, " indio_dev->info is NOT NULL\n"); + iio_dev_opaque->driver_module = this_mod; /* If the calling driver did not initialize firmware node, do it here */ @@ -1902,60 +1917,95 @@ int __iio_device_register(struct iio_dev *indio_dev, struct module *this_mod) /* The default dummy IIO device has no parent */ else if (indio_dev->dev.parent) fwnode = dev_fwnode(indio_dev->dev.parent); + + dev_err(NULL, " begin device_set_node\n"); device_set_node(&indio_dev->dev, fwnode); + dev_err(NULL, " end device_set_node\n"); + dev_err(NULL, " begin fwnode_property_read_string\n"); fwnode_property_read_string(fwnode, "label", &indio_dev->label); + dev_err(NULL, " end fwnode_property_read_string\n"); + dev_err(NULL, " begin iio_check_unique_scan_index\n"); ret = iio_check_unique_scan_index(indio_dev); + dev_err(NULL, " end iio_check_unique_scan_index\n"); if (ret < 0) return ret; + dev_err(NULL, " begin iio_check_extended_name\n"); ret = iio_check_extended_name(indio_dev); + dev_err(NULL, " end iio_check_extended_name\n"); if (ret < 0) return ret; + dev_err(NULL, " begin iio_device_register_debugfs\n"); iio_device_register_debugfs(indio_dev); + dev_err(NULL, " end iio_device_register_debugfs\n"); + dev_err(NULL, " begin iio_buffers_alloc_sysfs_and_mask\n"); ret = iio_buffers_alloc_sysfs_and_mask(indio_dev); + dev_err(NULL, " end iio_buffers_alloc_sysfs_and_mask\n"); if (ret) { dev_err(indio_dev->dev.parent, "Failed to create buffer sysfs interfaces\n"); goto error_unreg_debugfs; } + dev_err(NULL, " begin iio_device_register_sysfs\n"); ret = iio_device_register_sysfs(indio_dev); + dev_err(NULL, " end iio_device_register_sysfs\n"); if (ret) { dev_err(indio_dev->dev.parent, "Failed to register sysfs interfaces\n"); goto error_buffer_free_sysfs; } + + dev_err(NULL, " begin iio_device_register_eventset\n"); ret = iio_device_register_eventset(indio_dev); + dev_err(NULL, " end iio_device_register_eventset\n"); if (ret) { dev_err(indio_dev->dev.parent, "Failed to register event set\n"); goto error_free_sysfs; } - if (indio_dev->modes & INDIO_ALL_TRIGGERED_MODES) + if (indio_dev->modes & INDIO_ALL_TRIGGERED_MODES) { + dev_err(NULL, " begin iio_device_register_trigger_consumer\n"); iio_device_register_trigger_consumer(indio_dev); + dev_err(NULL, " end iio_device_register_trigger_consumer\n"); + } else { + dev_err(NULL, " no iio_device_register_trigger_consumer performed\n"); + } if ((indio_dev->modes & INDIO_ALL_BUFFER_MODES) && indio_dev->setup_ops == NULL) indio_dev->setup_ops = &noop_ring_setup_ops; - if (iio_dev_opaque->attached_buffers_cnt) + if (iio_dev_opaque->attached_buffers_cnt) { + dev_err(NULL, " begin cdev_init 1\n"); cdev_init(&iio_dev_opaque->chrdev, &iio_buffer_fileops); - else if (iio_dev_opaque->event_interface) + dev_err(NULL, " end cdev_init 1\n"); + } + else if (iio_dev_opaque->event_interface) { + dev_err(NULL, " begin cdev_init 2\n"); cdev_init(&iio_dev_opaque->chrdev, &iio_event_fileops); + dev_err(NULL, " end cdev_init 1\n"); + } else { + dev_err(NULL, " no cdev_init\n"); + } if (iio_dev_opaque->attached_buffers_cnt || iio_dev_opaque->event_interface) { + dev_err(NULL, " begin MKDEV\n"); indio_dev->dev.devt = MKDEV(MAJOR(iio_devt), iio_dev_opaque->id); iio_dev_opaque->chrdev.owner = this_mod; + dev_err(NULL, " end MKDEV\n"); } /* assign device groups now; they should be all registered now */ indio_dev->dev.groups = iio_dev_opaque->groups; + dev_err(NULL, " begin cdev_device_add\n"); ret = cdev_device_add(&iio_dev_opaque->chrdev, &indio_dev->dev); + dev_err(NULL, " end cdev_device_add\n"); if (ret < 0) goto error_unreg_eventset; From 0adb30c4e33617b67647f1bd7b3230c512f176e4 Mon Sep 17 00:00:00 2001 From: Denis Date: Sun, 10 Sep 2023 16:43:06 +0200 Subject: [PATCH 2/4] still debugging.... --- drivers/iio/accel/bmc150-accel-core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/iio/accel/bmc150-accel-core.c b/drivers/iio/accel/bmc150-accel-core.c index 1e634cc2f740..09b84efb516e 100644 --- a/drivers/iio/accel/bmc150-accel-core.c +++ b/drivers/iio/accel/bmc150-accel-core.c @@ -2633,6 +2633,7 @@ int bmi323_iio_init(struct iio_dev *indio_dev) { indio_dev->available_scan_masks = bmi323_accel_scan_masks; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->info = &bmi323_accel_info; + indio_dev->label = "bmi323-accel_base"; /* ret = iio_triggered_buffer_setup_ext(indio_dev, From 51baa879312ce4f692e7ad029f3c1dd78c7df942 Mon Sep 17 00:00:00 2001 From: Denis Date: Sun, 10 Sep 2023 16:55:06 +0200 Subject: [PATCH 3/4] print more debug! --- drivers/iio/industrialio-core.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c index f1e0af45c9fd..72f88e86b5f9 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c @@ -1500,17 +1500,26 @@ static DEVICE_ATTR_RW(current_timestamp_clock); static int iio_device_register_sysfs(struct iio_dev *indio_dev) { + dev_err(NULL, " begin to_iio_dev_opaque"); struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); int i, ret = 0, attrcount, attrn, attrcount_orig = 0; struct iio_dev_attr *p; struct attribute **attr, *clk = NULL; + dev_err(NULL, " end to_iio_dev_opaque"); /* First count elements in any existing group */ + dev_err(NULL, " begin if (indio_dev->info->attrs)"); if (indio_dev->info->attrs) { + dev_err(NULL, " begin attr = indio_dev->info->attrs->attrs"); attr = indio_dev->info->attrs->attrs; + dev_err(NULL, " end attr = indio_dev->info->attrs->attrs"); + + dev_err(NULL, " begin while (*attr++ != NULL)"); while (*attr++ != NULL) attrcount_orig++; + dev_err(NULL, " end while (*attr++ != NULL)"); } + dev_err(NULL, " begin end (indio_dev->info->attrs)"); attrcount = attrcount_orig; /* * New channel registration method - relies on the fact a group does From 1c885459bbb80e9405c8b0904914f899fd5c2f9d Mon Sep 17 00:00:00 2001 From: Denis Date: Sun, 10 Sep 2023 16:58:50 +0200 Subject: [PATCH 4/4] comment a thing --- drivers/iio/accel/bmc150-accel-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/accel/bmc150-accel-core.c b/drivers/iio/accel/bmc150-accel-core.c index 09b84efb516e..cb8762adb2d3 100644 --- a/drivers/iio/accel/bmc150-accel-core.c +++ b/drivers/iio/accel/bmc150-accel-core.c @@ -2480,7 +2480,7 @@ static int bmi323_write_event_config(struct iio_dev *indio_dev, } static const struct iio_info bmi323_accel_info = { - .attrs = &bmi323_accel_attrs_group, + //.attrs = &bmi323_accel_attrs_group, // this gets accessed in iio_device_register_sysfs .read_raw = bmi323_read_raw, //.write_raw = bmi323_write_raw, //.read_event_value = bmi323_read_event,