907 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * ROHM BH1745 digital colour sensor driver4 *5 * Copyright (C) Mudit Sharma <muditsharma.info@gmail.com>6 *7 * 7-bit I2C slave addresses:8 * 0x38 (ADDR pin low)9 * 0x39 (ADDR pin high)10 */11 12#include <linux/i2c.h>13#include <linux/mutex.h>14#include <linux/util_macros.h>15#include <linux/iio/events.h>16#include <linux/regmap.h>17#include <linux/bits.h>18#include <linux/bitfield.h>19 20#include <linux/iio/iio.h>21#include <linux/iio/sysfs.h>22#include <linux/iio/trigger.h>23#include <linux/iio/trigger_consumer.h>24#include <linux/iio/triggered_buffer.h>25#include <linux/iio/iio-gts-helper.h>26 27/* BH1745 configuration registers */28 29/* System control */30#define BH1745_SYS_CTRL 0x4031#define BH1745_SYS_CTRL_SW_RESET BIT(7)32#define BH1745_SYS_CTRL_INTR_RESET BIT(6)33#define BH1745_SYS_CTRL_PART_ID_MASK GENMASK(5, 0)34#define BH1745_PART_ID 0x0B35 36/* Mode control 1 */37#define BH1745_MODE_CTRL1 0x4138#define BH1745_CTRL1_MEASUREMENT_TIME_MASK GENMASK(2, 0)39 40/* Mode control 2 */41#define BH1745_MODE_CTRL2 0x4242#define BH1745_CTRL2_RGBC_EN BIT(4)43#define BH1745_CTRL2_ADC_GAIN_MASK GENMASK(1, 0)44 45/* Interrupt */46#define BH1745_INTR 0x6047#define BH1745_INTR_STATUS BIT(7)48#define BH1745_INTR_SOURCE_MASK GENMASK(3, 2)49#define BH1745_INTR_ENABLE BIT(0)50 51#define BH1745_PERSISTENCE 0x6152 53/* Threshold high */54#define BH1745_TH_LSB 0x6255#define BH1745_TH_MSB 0x6356 57/* Threshold low */58#define BH1745_TL_LSB 0x6459#define BH1745_TL_MSB 0x6560 61/* BH1745 data output regs */62#define BH1745_RED_LSB 0x5063#define BH1745_RED_MSB 0x5164#define BH1745_GREEN_LSB 0x5265#define BH1745_GREEN_MSB 0x5366#define BH1745_BLUE_LSB 0x5467#define BH1745_BLUE_MSB 0x5568#define BH1745_CLEAR_LSB 0x5669#define BH1745_CLEAR_MSB 0x5770 71#define BH1745_MANU_ID_REG 0x9272 73/* From 16x max HW gain and 32x max integration time */74#define BH1745_MAX_GAIN 51275 76enum bh1745_int_source {77 BH1745_INTR_SOURCE_RED,78 BH1745_INTR_SOURCE_GREEN,79 BH1745_INTR_SOURCE_BLUE,80 BH1745_INTR_SOURCE_CLEAR,81};82 83enum bh1745_gain {84 BH1745_ADC_GAIN_1X,85 BH1745_ADC_GAIN_2X,86 BH1745_ADC_GAIN_16X,87};88 89enum bh1745_measurement_time {90 BH1745_MEASUREMENT_TIME_160MS,91 BH1745_MEASUREMENT_TIME_320MS,92 BH1745_MEASUREMENT_TIME_640MS,93 BH1745_MEASUREMENT_TIME_1280MS,94 BH1745_MEASUREMENT_TIME_2560MS,95 BH1745_MEASUREMENT_TIME_5120MS,96};97 98enum bh1745_presistence_value {99 BH1745_PRESISTENCE_UPDATE_TOGGLE,100 BH1745_PRESISTENCE_UPDATE_EACH_MEASUREMENT,101 BH1745_PRESISTENCE_UPDATE_FOUR_MEASUREMENT,102 BH1745_PRESISTENCE_UPDATE_EIGHT_MEASUREMENT,103};104 105static const struct iio_gain_sel_pair bh1745_gain[] = {106 GAIN_SCALE_GAIN(1, BH1745_ADC_GAIN_1X),107 GAIN_SCALE_GAIN(2, BH1745_ADC_GAIN_2X),108 GAIN_SCALE_GAIN(16, BH1745_ADC_GAIN_16X),109};110 111static const struct iio_itime_sel_mul bh1745_itimes[] = {112 GAIN_SCALE_ITIME_US(5120000, BH1745_MEASUREMENT_TIME_5120MS, 32),113 GAIN_SCALE_ITIME_US(2560000, BH1745_MEASUREMENT_TIME_2560MS, 16),114 GAIN_SCALE_ITIME_US(1280000, BH1745_MEASUREMENT_TIME_1280MS, 8),115 GAIN_SCALE_ITIME_US(640000, BH1745_MEASUREMENT_TIME_640MS, 4),116 GAIN_SCALE_ITIME_US(320000, BH1745_MEASUREMENT_TIME_320MS, 2),117 GAIN_SCALE_ITIME_US(160000, BH1745_MEASUREMENT_TIME_160MS, 1),118};119 120struct bh1745_data {121 /*122 * Lock to prevent device setting update or read before123 * related calculations are completed124 */125 struct mutex lock;126 struct regmap *regmap;127 struct device *dev;128 struct iio_trigger *trig;129 struct iio_gts gts;130};131 132static const struct regmap_range bh1745_volatile_ranges[] = {133 regmap_reg_range(BH1745_MODE_CTRL2, BH1745_MODE_CTRL2), /* VALID */134 regmap_reg_range(BH1745_RED_LSB, BH1745_CLEAR_MSB), /* Data */135 regmap_reg_range(BH1745_INTR, BH1745_INTR), /* Interrupt */136};137 138static const struct regmap_access_table bh1745_volatile_regs = {139 .yes_ranges = bh1745_volatile_ranges,140 .n_yes_ranges = ARRAY_SIZE(bh1745_volatile_ranges),141};142 143static const struct regmap_range bh1745_readable_ranges[] = {144 regmap_reg_range(BH1745_SYS_CTRL, BH1745_MODE_CTRL2),145 regmap_reg_range(BH1745_RED_LSB, BH1745_CLEAR_MSB),146 regmap_reg_range(BH1745_INTR, BH1745_INTR),147 regmap_reg_range(BH1745_PERSISTENCE, BH1745_TL_MSB),148 regmap_reg_range(BH1745_MANU_ID_REG, BH1745_MANU_ID_REG),149};150 151static const struct regmap_access_table bh1745_readable_regs = {152 .yes_ranges = bh1745_readable_ranges,153 .n_yes_ranges = ARRAY_SIZE(bh1745_readable_ranges),154};155 156static const struct regmap_range bh1745_writable_ranges[] = {157 regmap_reg_range(BH1745_SYS_CTRL, BH1745_MODE_CTRL2),158 regmap_reg_range(BH1745_INTR, BH1745_INTR),159 regmap_reg_range(BH1745_PERSISTENCE, BH1745_TL_MSB),160};161 162static const struct regmap_access_table bh1745_writable_regs = {163 .yes_ranges = bh1745_writable_ranges,164 .n_yes_ranges = ARRAY_SIZE(bh1745_writable_ranges),165};166 167static const struct regmap_config bh1745_regmap = {168 .reg_bits = 8,169 .val_bits = 8,170 .max_register = BH1745_MANU_ID_REG,171 .cache_type = REGCACHE_RBTREE,172 .volatile_table = &bh1745_volatile_regs,173 .wr_table = &bh1745_writable_regs,174 .rd_table = &bh1745_readable_regs,175};176 177static const struct iio_event_spec bh1745_event_spec[] = {178 {179 .type = IIO_EV_TYPE_THRESH,180 .dir = IIO_EV_DIR_RISING,181 .mask_shared_by_type = BIT(IIO_EV_INFO_VALUE),182 },183 {184 .type = IIO_EV_TYPE_THRESH,185 .dir = IIO_EV_DIR_FALLING,186 .mask_shared_by_type = BIT(IIO_EV_INFO_VALUE),187 },188 {189 .type = IIO_EV_TYPE_THRESH,190 .dir = IIO_EV_DIR_EITHER,191 .mask_shared_by_type = BIT(IIO_EV_INFO_PERIOD),192 .mask_separate = BIT(IIO_EV_INFO_ENABLE),193 },194};195 196#define BH1745_CHANNEL(_colour, _si, _addr) \197 { \198 .type = IIO_INTENSITY, .modified = 1, \199 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \200 .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SCALE) | \201 BIT(IIO_CHAN_INFO_INT_TIME), \202 .info_mask_shared_by_all_available = \203 BIT(IIO_CHAN_INFO_SCALE) | \204 BIT(IIO_CHAN_INFO_INT_TIME), \205 .event_spec = bh1745_event_spec, \206 .num_event_specs = ARRAY_SIZE(bh1745_event_spec), \207 .channel2 = IIO_MOD_LIGHT_##_colour, .address = _addr, \208 .scan_index = _si, \209 .scan_type = { \210 .sign = 'u', \211 .realbits = 16, \212 .storagebits = 16, \213 .endianness = IIO_CPU, \214 }, \215 }216 217static const struct iio_chan_spec bh1745_channels[] = {218 BH1745_CHANNEL(RED, 0, BH1745_RED_LSB),219 BH1745_CHANNEL(GREEN, 1, BH1745_GREEN_LSB),220 BH1745_CHANNEL(BLUE, 2, BH1745_BLUE_LSB),221 BH1745_CHANNEL(CLEAR, 3, BH1745_CLEAR_LSB),222 IIO_CHAN_SOFT_TIMESTAMP(4),223};224 225static int bh1745_reset(struct bh1745_data *data)226{227 return regmap_set_bits(data->regmap, BH1745_SYS_CTRL,228 BH1745_SYS_CTRL_SW_RESET |229 BH1745_SYS_CTRL_INTR_RESET);230}231 232static int bh1745_power_on(struct bh1745_data *data)233{234 return regmap_set_bits(data->regmap, BH1745_MODE_CTRL2,235 BH1745_CTRL2_RGBC_EN);236}237 238static void bh1745_power_off(void *data_ptr)239{240 struct bh1745_data *data = data_ptr;241 struct device *dev = data->dev;242 int ret;243 244 ret = regmap_clear_bits(data->regmap, BH1745_MODE_CTRL2,245 BH1745_CTRL2_RGBC_EN);246 if (ret)247 dev_err(dev, "Failed to turn off device\n");248}249 250static int bh1745_get_scale(struct bh1745_data *data, int *val, int *val2)251{252 int ret;253 int value;254 int gain_sel, int_time_sel;255 int gain;256 const struct iio_itime_sel_mul *int_time;257 258 ret = regmap_read(data->regmap, BH1745_MODE_CTRL2, &value);259 if (ret)260 return ret;261 262 gain_sel = FIELD_GET(BH1745_CTRL2_ADC_GAIN_MASK, value);263 gain = iio_gts_find_gain_by_sel(&data->gts, gain_sel);264 265 ret = regmap_read(data->regmap, BH1745_MODE_CTRL1, &value);266 if (ret)267 return ret;268 269 int_time_sel = FIELD_GET(BH1745_CTRL1_MEASUREMENT_TIME_MASK, value);270 int_time = iio_gts_find_itime_by_sel(&data->gts, int_time_sel);271 272 return iio_gts_get_scale(&data->gts, gain, int_time->time_us, val,273 val2);274}275 276static int bh1745_set_scale(struct bh1745_data *data, int val)277{278 struct device *dev = data->dev;279 int ret;280 int value;281 int hw_gain_sel, current_int_time_sel, new_int_time_sel;282 283 ret = regmap_read(data->regmap, BH1745_MODE_CTRL1, &value);284 if (ret)285 return ret;286 287 current_int_time_sel = FIELD_GET(BH1745_CTRL1_MEASUREMENT_TIME_MASK,288 value);289 ret = iio_gts_find_gain_sel_for_scale_using_time(&data->gts,290 current_int_time_sel,291 val, 0, &hw_gain_sel);292 if (ret) {293 for (int i = 0; i < data->gts.num_itime; i++) {294 new_int_time_sel = data->gts.itime_table[i].sel;295 296 if (new_int_time_sel == current_int_time_sel)297 continue;298 299 ret = iio_gts_find_gain_sel_for_scale_using_time(&data->gts,300 new_int_time_sel,301 val, 0,302 &hw_gain_sel);303 if (!ret)304 break;305 }306 307 if (ret) {308 dev_dbg(dev, "Unsupported scale value requested: %d\n",309 val);310 return -EINVAL;311 }312 313 ret = regmap_write_bits(data->regmap, BH1745_MODE_CTRL1,314 BH1745_CTRL1_MEASUREMENT_TIME_MASK,315 new_int_time_sel);316 if (ret)317 return ret;318 }319 320 return regmap_write_bits(data->regmap, BH1745_MODE_CTRL2,321 BH1745_CTRL2_ADC_GAIN_MASK, hw_gain_sel);322}323 324static int bh1745_get_int_time(struct bh1745_data *data, int *val)325{326 int ret;327 int value;328 int int_time, int_time_sel;329 330 ret = regmap_read(data->regmap, BH1745_MODE_CTRL1, &value);331 if (ret)332 return ret;333 334 int_time_sel = FIELD_GET(BH1745_CTRL1_MEASUREMENT_TIME_MASK, value);335 int_time = iio_gts_find_int_time_by_sel(&data->gts, int_time_sel);336 if (int_time < 0)337 return int_time;338 339 *val = int_time;340 341 return 0;342}343 344static int bh1745_set_int_time(struct bh1745_data *data, int val, int val2)345{346 struct device *dev = data->dev;347 int ret;348 int value;349 int current_int_time, current_hwgain_sel, current_hwgain;350 int new_hwgain, new_hwgain_sel, new_int_time_sel;351 int req_int_time = (1000000 * val) + val2;352 353 if (!iio_gts_valid_time(&data->gts, req_int_time)) {354 dev_dbg(dev, "Unsupported integration time requested: %d\n",355 req_int_time);356 return -EINVAL;357 }358 359 ret = bh1745_get_int_time(data, ¤t_int_time);360 if (ret)361 return ret;362 363 if (current_int_time == req_int_time)364 return 0;365 366 ret = regmap_read(data->regmap, BH1745_MODE_CTRL2, &value);367 if (ret)368 return ret;369 370 current_hwgain_sel = FIELD_GET(BH1745_CTRL2_ADC_GAIN_MASK, value);371 current_hwgain = iio_gts_find_gain_by_sel(&data->gts,372 current_hwgain_sel);373 ret = iio_gts_find_new_gain_by_old_gain_time(&data->gts, current_hwgain,374 current_int_time,375 req_int_time,376 &new_hwgain);377 if (new_hwgain < 0) {378 dev_dbg(dev, "No corresponding gain for requested integration time\n");379 return ret;380 }381 382 if (ret) {383 bool in_range;384 385 new_hwgain = iio_find_closest_gain_low(&data->gts, new_hwgain,386 &in_range);387 if (new_hwgain < 0) {388 new_hwgain = iio_gts_get_min_gain(&data->gts);389 if (new_hwgain < 0)390 return ret;391 }392 393 if (!in_range)394 dev_dbg(dev, "Optimal gain out of range\n");395 396 dev_dbg(dev, "Scale changed, new hw_gain %d\n", new_hwgain);397 }398 399 new_hwgain_sel = iio_gts_find_sel_by_gain(&data->gts, new_hwgain);400 if (new_hwgain_sel < 0)401 return new_hwgain_sel;402 403 ret = regmap_write_bits(data->regmap, BH1745_MODE_CTRL2,404 BH1745_CTRL2_ADC_GAIN_MASK,405 new_hwgain_sel);406 if (ret)407 return ret;408 409 new_int_time_sel = iio_gts_find_sel_by_int_time(&data->gts,410 req_int_time);411 if (new_int_time_sel < 0)412 return new_int_time_sel;413 414 return regmap_write_bits(data->regmap, BH1745_MODE_CTRL1,415 BH1745_CTRL1_MEASUREMENT_TIME_MASK,416 new_int_time_sel);417}418 419static int bh1745_read_raw(struct iio_dev *indio_dev,420 struct iio_chan_spec const *chan,421 int *val, int *val2, long mask)422{423 struct bh1745_data *data = iio_priv(indio_dev);424 int ret;425 int value;426 427 switch (mask) {428 case IIO_CHAN_INFO_RAW:429 iio_device_claim_direct_scoped(return -EBUSY, indio_dev) {430 ret = regmap_bulk_read(data->regmap, chan->address,431 &value, 2);432 if (ret)433 return ret;434 *val = value;435 436 return IIO_VAL_INT;437 }438 unreachable();439 440 case IIO_CHAN_INFO_SCALE: {441 guard(mutex)(&data->lock);442 ret = bh1745_get_scale(data, val, val2);443 if (ret)444 return ret;445 446 return IIO_VAL_INT;447 }448 449 case IIO_CHAN_INFO_INT_TIME: {450 guard(mutex)(&data->lock);451 *val = 0;452 ret = bh1745_get_int_time(data, val2);453 if (ret)454 return 0;455 456 return IIO_VAL_INT_PLUS_MICRO;457 }458 459 default:460 return -EINVAL;461 }462}463 464static int bh1745_write_raw(struct iio_dev *indio_dev,465 struct iio_chan_spec const *chan,466 int val, int val2, long mask)467{468 struct bh1745_data *data = iio_priv(indio_dev);469 470 guard(mutex)(&data->lock);471 switch (mask) {472 case IIO_CHAN_INFO_SCALE:473 return bh1745_set_scale(data, val);474 475 case IIO_CHAN_INFO_INT_TIME:476 return bh1745_set_int_time(data, val, val2);477 478 default:479 return -EINVAL;480 }481}482 483static int bh1745_write_raw_get_fmt(struct iio_dev *indio_dev,484 struct iio_chan_spec const *chan,485 long mask)486{487 switch (mask) {488 case IIO_CHAN_INFO_SCALE:489 return IIO_VAL_INT;490 491 case IIO_CHAN_INFO_INT_TIME:492 return IIO_VAL_INT_PLUS_MICRO;493 494 default:495 return -EINVAL;496 }497}498 499static int bh1745_read_thresh(struct iio_dev *indio_dev,500 const struct iio_chan_spec *chan,501 enum iio_event_type type,502 enum iio_event_direction dir,503 enum iio_event_info info, int *val, int *val2)504{505 struct bh1745_data *data = iio_priv(indio_dev);506 int ret;507 508 switch (info) {509 case IIO_EV_INFO_VALUE:510 switch (dir) {511 case IIO_EV_DIR_RISING:512 ret = regmap_bulk_read(data->regmap, BH1745_TH_LSB,513 val, 2);514 if (ret)515 return ret;516 517 return IIO_VAL_INT;518 519 case IIO_EV_DIR_FALLING:520 ret = regmap_bulk_read(data->regmap, BH1745_TL_LSB,521 val, 2);522 if (ret)523 return ret;524 525 return IIO_VAL_INT;526 527 default:528 return -EINVAL;529 }530 531 case IIO_EV_INFO_PERIOD:532 ret = regmap_read(data->regmap, BH1745_PERSISTENCE, val);533 if (ret)534 return ret;535 536 return IIO_VAL_INT;537 538 default:539 return -EINVAL;540 }541}542 543static int bh1745_write_thresh(struct iio_dev *indio_dev,544 const struct iio_chan_spec *chan,545 enum iio_event_type type,546 enum iio_event_direction dir,547 enum iio_event_info info, int val, int val2)548{549 struct bh1745_data *data = iio_priv(indio_dev);550 int ret;551 552 switch (info) {553 case IIO_EV_INFO_VALUE:554 if (val < 0x0 || val > 0xFFFF)555 return -EINVAL;556 557 switch (dir) {558 case IIO_EV_DIR_RISING:559 ret = regmap_bulk_write(data->regmap, BH1745_TH_LSB,560 &val, 2);561 if (ret)562 return ret;563 564 return IIO_VAL_INT;565 566 case IIO_EV_DIR_FALLING:567 ret = regmap_bulk_write(data->regmap, BH1745_TL_LSB,568 &val, 2);569 if (ret)570 return ret;571 572 return IIO_VAL_INT;573 574 default:575 return -EINVAL;576 }577 578 case IIO_EV_INFO_PERIOD:579 if (val < BH1745_PRESISTENCE_UPDATE_TOGGLE ||580 val > BH1745_PRESISTENCE_UPDATE_EIGHT_MEASUREMENT)581 return -EINVAL;582 ret = regmap_write(data->regmap, BH1745_PERSISTENCE, val);583 if (ret)584 return ret;585 586 return IIO_VAL_INT;587 588 default:589 return -EINVAL;590 }591}592 593static int bh1745_read_event_config(struct iio_dev *indio_dev,594 const struct iio_chan_spec *chan,595 enum iio_event_type type,596 enum iio_event_direction dir)597{598 struct bh1745_data *data = iio_priv(indio_dev);599 int ret;600 int value;601 int int_src;602 603 ret = regmap_read(data->regmap, BH1745_INTR, &value);604 if (ret)605 return ret;606 607 if (!FIELD_GET(BH1745_INTR_ENABLE, value))608 return 0;609 610 int_src = FIELD_GET(BH1745_INTR_SOURCE_MASK, value);611 612 switch (chan->channel2) {613 case IIO_MOD_LIGHT_RED:614 if (int_src == BH1745_INTR_SOURCE_RED)615 return 1;616 return 0;617 618 case IIO_MOD_LIGHT_GREEN:619 if (int_src == BH1745_INTR_SOURCE_GREEN)620 return 1;621 return 0;622 623 case IIO_MOD_LIGHT_BLUE:624 if (int_src == BH1745_INTR_SOURCE_BLUE)625 return 1;626 return 0;627 628 case IIO_MOD_LIGHT_CLEAR:629 if (int_src == BH1745_INTR_SOURCE_CLEAR)630 return 1;631 return 0;632 633 default:634 return -EINVAL;635 }636}637 638static int bh1745_write_event_config(struct iio_dev *indio_dev,639 const struct iio_chan_spec *chan,640 enum iio_event_type type,641 enum iio_event_direction dir, int state)642{643 struct bh1745_data *data = iio_priv(indio_dev);644 int value;645 646 if (state == 0)647 return regmap_clear_bits(data->regmap,648 BH1745_INTR, BH1745_INTR_ENABLE);649 650 if (state == 1) {651 /* Latch is always enabled when enabling interrupt */652 value = BH1745_INTR_ENABLE;653 654 switch (chan->channel2) {655 case IIO_MOD_LIGHT_RED:656 return regmap_write(data->regmap, BH1745_INTR,657 value | FIELD_PREP(BH1745_INTR_SOURCE_MASK,658 BH1745_INTR_SOURCE_RED));659 660 case IIO_MOD_LIGHT_GREEN:661 return regmap_write(data->regmap, BH1745_INTR,662 value | FIELD_PREP(BH1745_INTR_SOURCE_MASK,663 BH1745_INTR_SOURCE_GREEN));664 665 case IIO_MOD_LIGHT_BLUE:666 return regmap_write(data->regmap, BH1745_INTR,667 value | FIELD_PREP(BH1745_INTR_SOURCE_MASK,668 BH1745_INTR_SOURCE_BLUE));669 670 case IIO_MOD_LIGHT_CLEAR:671 return regmap_write(data->regmap, BH1745_INTR,672 value | FIELD_PREP(BH1745_INTR_SOURCE_MASK,673 BH1745_INTR_SOURCE_CLEAR));674 675 default:676 return -EINVAL;677 }678 }679 680 return -EINVAL;681}682 683static int bh1745_read_avail(struct iio_dev *indio_dev,684 struct iio_chan_spec const *chan, const int **vals,685 int *type, int *length, long mask)686{687 struct bh1745_data *data = iio_priv(indio_dev);688 689 switch (mask) {690 case IIO_CHAN_INFO_INT_TIME:691 return iio_gts_avail_times(&data->gts, vals, type, length);692 693 case IIO_CHAN_INFO_SCALE:694 return iio_gts_all_avail_scales(&data->gts, vals, type, length);695 696 default:697 return -EINVAL;698 }699}700 701static const struct iio_info bh1745_info = {702 .read_raw = bh1745_read_raw,703 .write_raw = bh1745_write_raw,704 .write_raw_get_fmt = bh1745_write_raw_get_fmt,705 .read_event_value = bh1745_read_thresh,706 .write_event_value = bh1745_write_thresh,707 .read_event_config = bh1745_read_event_config,708 .write_event_config = bh1745_write_event_config,709 .read_avail = bh1745_read_avail,710};711 712static irqreturn_t bh1745_interrupt_handler(int interrupt, void *p)713{714 struct iio_dev *indio_dev = p;715 struct bh1745_data *data = iio_priv(indio_dev);716 int ret;717 int value;718 int int_src;719 720 ret = regmap_read(data->regmap, BH1745_INTR, &value);721 if (ret)722 return IRQ_NONE;723 724 int_src = FIELD_GET(BH1745_INTR_SOURCE_MASK, value);725 726 if (value & BH1745_INTR_STATUS) {727 iio_push_event(indio_dev,728 IIO_UNMOD_EVENT_CODE(IIO_INTENSITY, int_src,729 IIO_EV_TYPE_THRESH,730 IIO_EV_DIR_EITHER),731 iio_get_time_ns(indio_dev));732 733 return IRQ_HANDLED;734 }735 736 return IRQ_NONE;737}738 739static irqreturn_t bh1745_trigger_handler(int interrupt, void *p)740{741 struct iio_poll_func *pf = p;742 struct iio_dev *indio_dev = pf->indio_dev;743 struct bh1745_data *data = iio_priv(indio_dev);744 struct {745 u16 chans[4];746 s64 timestamp __aligned(8);747 } scan;748 u16 value;749 int ret;750 int i;751 int j = 0;752 753 iio_for_each_active_channel(indio_dev, i) {754 ret = regmap_bulk_read(data->regmap, BH1745_RED_LSB + 2 * i,755 &value, 2);756 if (ret)757 goto err;758 759 scan.chans[j++] = value;760 }761 762 iio_push_to_buffers_with_timestamp(indio_dev, &scan,763 iio_get_time_ns(indio_dev));764 765err:766 iio_trigger_notify_done(indio_dev->trig);767 768 return IRQ_HANDLED;769}770 771static int bh1745_setup_triggered_buffer(struct iio_dev *indio_dev,772 struct device *parent,773 int irq)774{775 struct bh1745_data *data = iio_priv(indio_dev);776 struct device *dev = data->dev;777 int ret;778 779 ret = devm_iio_triggered_buffer_setup(parent, indio_dev, NULL,780 bh1745_trigger_handler, NULL);781 if (ret)782 return dev_err_probe(dev, ret,783 "Triggered buffer setup failed\n");784 785 if (irq) {786 ret = devm_request_threaded_irq(dev, irq, NULL,787 bh1745_interrupt_handler,788 IRQF_ONESHOT,789 "bh1745_interrupt", indio_dev);790 if (ret)791 return dev_err_probe(dev, ret,792 "Request for IRQ failed\n");793 }794 795 return 0;796}797 798static int bh1745_init(struct bh1745_data *data)799{800 int ret;801 struct device *dev = data->dev;802 803 mutex_init(&data->lock);804 805 ret = devm_iio_init_iio_gts(dev, BH1745_MAX_GAIN, 0, bh1745_gain,806 ARRAY_SIZE(bh1745_gain), bh1745_itimes,807 ARRAY_SIZE(bh1745_itimes), &data->gts);808 if (ret)809 return ret;810 811 ret = bh1745_reset(data);812 if (ret)813 return dev_err_probe(dev, ret, "Failed to reset sensor\n");814 815 ret = bh1745_power_on(data);816 if (ret)817 return dev_err_probe(dev, ret, "Failed to turn on sensor\n");818 819 ret = devm_add_action_or_reset(dev, bh1745_power_off, data);820 if (ret)821 return dev_err_probe(dev, ret,822 "Failed to add action or reset\n");823 824 return 0;825}826 827static int bh1745_probe(struct i2c_client *client)828{829 int ret;830 int value;831 int part_id;832 struct bh1745_data *data;833 struct iio_dev *indio_dev;834 struct device *dev = &client->dev;835 836 indio_dev = devm_iio_device_alloc(dev, sizeof(*data));837 if (!indio_dev)838 return -ENOMEM;839 840 indio_dev->info = &bh1745_info;841 indio_dev->name = "bh1745";842 indio_dev->channels = bh1745_channels;843 indio_dev->modes = INDIO_DIRECT_MODE;844 indio_dev->num_channels = ARRAY_SIZE(bh1745_channels);845 data = iio_priv(indio_dev);846 data->dev = &client->dev;847 data->regmap = devm_regmap_init_i2c(client, &bh1745_regmap);848 if (IS_ERR(data->regmap))849 return dev_err_probe(dev, PTR_ERR(data->regmap),850 "Failed to initialize Regmap\n");851 852 ret = regmap_read(data->regmap, BH1745_SYS_CTRL, &value);853 if (ret)854 return ret;855 856 part_id = FIELD_GET(BH1745_SYS_CTRL_PART_ID_MASK, value);857 if (part_id != BH1745_PART_ID)858 dev_warn(dev, "Unknown part ID 0x%x\n", part_id);859 860 ret = devm_regulator_get_enable(dev, "vdd");861 if (ret)862 return dev_err_probe(dev, ret,863 "Failed to get and enable regulator\n");864 865 ret = bh1745_init(data);866 if (ret)867 return ret;868 869 ret = bh1745_setup_triggered_buffer(indio_dev, indio_dev->dev.parent,870 client->irq);871 if (ret)872 return ret;873 874 ret = devm_iio_device_register(dev, indio_dev);875 if (ret)876 return dev_err_probe(dev, ret, "Failed to register device\n");877 878 return 0;879}880 881static const struct i2c_device_id bh1745_idtable[] = {882 { "bh1745" },883 { }884};885MODULE_DEVICE_TABLE(i2c, bh1745_idtable);886 887static const struct of_device_id bh1745_of_match[] = {888 { .compatible = "rohm,bh1745" },889 { }890};891MODULE_DEVICE_TABLE(of, bh1745_of_match);892 893static struct i2c_driver bh1745_driver = {894 .driver = {895 .name = "bh1745",896 .of_match_table = bh1745_of_match,897 },898 .probe = bh1745_probe,899 .id_table = bh1745_idtable,900};901module_i2c_driver(bh1745_driver);902 903MODULE_LICENSE("GPL");904MODULE_AUTHOR("Mudit Sharma <muditsharma.info@gmail.com>");905MODULE_DESCRIPTION("BH1745 colour sensor driver");906MODULE_IMPORT_NS(IIO_GTS_HELPER);907