linux/drivers/iio/light/si1133.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * si1133.c - Support for Silabs SI1133 combined ambient
   4 * light and UV index sensors
   5 *
   6 * Copyright 2018 Maxime Roussin-Belanger <maxime.roussinbelanger@gmail.com>
   7 */
   8
   9#include <linux/delay.h>
  10#include <linux/i2c.h>
  11#include <linux/interrupt.h>
  12#include <linux/module.h>
  13#include <linux/regmap.h>
  14
  15#include <linux/iio/iio.h>
  16#include <linux/iio/sysfs.h>
  17
  18#include <linux/util_macros.h>
  19
  20#include <asm/unaligned.h>
  21
  22#define SI1133_REG_PART_ID              0x00
  23#define SI1133_REG_REV_ID               0x01
  24#define SI1133_REG_MFR_ID               0x02
  25#define SI1133_REG_INFO0                0x03
  26#define SI1133_REG_INFO1                0x04
  27
  28#define SI1133_PART_ID                  0x33
  29
  30#define SI1133_REG_HOSTIN0              0x0A
  31#define SI1133_REG_COMMAND              0x0B
  32#define SI1133_REG_IRQ_ENABLE           0x0F
  33#define SI1133_REG_RESPONSE1            0x10
  34#define SI1133_REG_RESPONSE0            0x11
  35#define SI1133_REG_IRQ_STATUS           0x12
  36#define SI1133_REG_MEAS_RATE            0x1A
  37
  38#define SI1133_IRQ_CHANNEL_ENABLE       0xF
  39
  40#define SI1133_CMD_RESET_CTR            0x00
  41#define SI1133_CMD_RESET_SW             0x01
  42#define SI1133_CMD_FORCE                0x11
  43#define SI1133_CMD_START_AUTONOMOUS     0x13
  44#define SI1133_CMD_PARAM_SET            0x80
  45#define SI1133_CMD_PARAM_QUERY          0x40
  46#define SI1133_CMD_PARAM_MASK           0x3F
  47
  48#define SI1133_CMD_ERR_MASK             BIT(4)
  49#define SI1133_CMD_SEQ_MASK             0xF
  50#define SI1133_MAX_CMD_CTR              0xF
  51
  52#define SI1133_PARAM_REG_CHAN_LIST      0x01
  53#define SI1133_PARAM_REG_ADCCONFIG(x)   ((x) * 4) + 2
  54#define SI1133_PARAM_REG_ADCSENS(x)     ((x) * 4) + 3
  55#define SI1133_PARAM_REG_ADCPOST(x)     ((x) * 4) + 4
  56
  57#define SI1133_ADCMUX_MASK 0x1F
  58
  59#define SI1133_ADCCONFIG_DECIM_RATE(x)  (x) << 5
  60
  61#define SI1133_ADCSENS_SCALE_MASK 0x70
  62#define SI1133_ADCSENS_SCALE_SHIFT 4
  63#define SI1133_ADCSENS_HSIG_MASK BIT(7)
  64#define SI1133_ADCSENS_HSIG_SHIFT 7
  65#define SI1133_ADCSENS_HW_GAIN_MASK 0xF
  66#define SI1133_ADCSENS_NB_MEAS(x)       fls(x) << SI1133_ADCSENS_SCALE_SHIFT
  67
  68#define SI1133_ADCPOST_24BIT_EN BIT(6)
  69#define SI1133_ADCPOST_POSTSHIFT_BITQTY(x) (x & GENMASK(2, 0)) << 3
  70
  71#define SI1133_PARAM_ADCMUX_SMALL_IR    0x0
  72#define SI1133_PARAM_ADCMUX_MED_IR      0x1
  73#define SI1133_PARAM_ADCMUX_LARGE_IR    0x2
  74#define SI1133_PARAM_ADCMUX_WHITE       0xB
  75#define SI1133_PARAM_ADCMUX_LARGE_WHITE 0xD
  76#define SI1133_PARAM_ADCMUX_UV          0x18
  77#define SI1133_PARAM_ADCMUX_UV_DEEP     0x19
  78
  79#define SI1133_ERR_INVALID_CMD          0x0
  80#define SI1133_ERR_INVALID_LOCATION_CMD 0x1
  81#define SI1133_ERR_SATURATION_ADC_OR_OVERFLOW_ACCUMULATION 0x2
  82#define SI1133_ERR_OUTPUT_BUFFER_OVERFLOW 0x3
  83
  84#define SI1133_COMPLETION_TIMEOUT_MS    500
  85
  86#define SI1133_CMD_MINSLEEP_US_LOW      5000
  87#define SI1133_CMD_MINSLEEP_US_HIGH     7500
  88#define SI1133_CMD_TIMEOUT_MS           25
  89#define SI1133_CMD_LUX_TIMEOUT_MS       5000
  90#define SI1133_CMD_TIMEOUT_US           SI1133_CMD_TIMEOUT_MS * 1000
  91
  92#define SI1133_REG_HOSTOUT(x)           (x) + 0x13
  93
  94#define SI1133_MEASUREMENT_FREQUENCY 1250
  95
  96#define SI1133_X_ORDER_MASK            0x0070
  97#define SI1133_Y_ORDER_MASK            0x0007
  98#define si1133_get_x_order(m)          ((m) & SI1133_X_ORDER_MASK) >> 4
  99#define si1133_get_y_order(m)          ((m) & SI1133_Y_ORDER_MASK)
 100
 101#define SI1133_LUX_ADC_MASK             0xE
 102#define SI1133_ADC_THRESHOLD            16000
 103#define SI1133_INPUT_FRACTION_HIGH      7
 104#define SI1133_INPUT_FRACTION_LOW       15
 105#define SI1133_LUX_OUTPUT_FRACTION      12
 106#define SI1133_LUX_BUFFER_SIZE          9
 107#define SI1133_MEASURE_BUFFER_SIZE      3
 108
 109static const int si1133_scale_available[] = {
 110        1, 2, 4, 8, 16, 32, 64, 128};
 111
 112static IIO_CONST_ATTR(scale_available, "1 2 4 8 16 32 64 128");
 113
 114static IIO_CONST_ATTR_INT_TIME_AVAIL("0.0244 0.0488 0.0975 0.195 0.390 0.780 "
 115                                     "1.560 3.120 6.24 12.48 25.0 50.0");
 116
 117/* A.K.A. HW_GAIN in datasheet */
 118enum si1133_int_time {
 119            _24_4_us = 0,
 120            _48_8_us = 1,
 121            _97_5_us = 2,
 122           _195_0_us = 3,
 123           _390_0_us = 4,
 124           _780_0_us = 5,
 125         _1_560_0_us = 6,
 126         _3_120_0_us = 7,
 127         _6_240_0_us = 8,
 128        _12_480_0_us = 9,
 129        _25_ms = 10,
 130        _50_ms = 11,
 131};
 132
 133/* Integration time in milliseconds, nanoseconds */
 134static const int si1133_int_time_table[][2] = {
 135        [_24_4_us] = {0, 24400},
 136        [_48_8_us] = {0, 48800},
 137        [_97_5_us] = {0, 97500},
 138        [_195_0_us] = {0, 195000},
 139        [_390_0_us] = {0, 390000},
 140        [_780_0_us] = {0, 780000},
 141        [_1_560_0_us] = {1, 560000},
 142        [_3_120_0_us] = {3, 120000},
 143        [_6_240_0_us] = {6, 240000},
 144        [_12_480_0_us] = {12, 480000},
 145        [_25_ms] = {25, 000000},
 146        [_50_ms] = {50, 000000},
 147};
 148
 149static const struct regmap_range si1133_reg_ranges[] = {
 150        regmap_reg_range(0x00, 0x02),
 151        regmap_reg_range(0x0A, 0x0B),
 152        regmap_reg_range(0x0F, 0x0F),
 153        regmap_reg_range(0x10, 0x12),
 154        regmap_reg_range(0x13, 0x2C),
 155};
 156
 157static const struct regmap_range si1133_reg_ro_ranges[] = {
 158        regmap_reg_range(0x00, 0x02),
 159        regmap_reg_range(0x10, 0x2C),
 160};
 161
 162static const struct regmap_range si1133_precious_ranges[] = {
 163        regmap_reg_range(0x12, 0x12),
 164};
 165
 166static const struct regmap_access_table si1133_write_ranges_table = {
 167        .yes_ranges     = si1133_reg_ranges,
 168        .n_yes_ranges   = ARRAY_SIZE(si1133_reg_ranges),
 169        .no_ranges      = si1133_reg_ro_ranges,
 170        .n_no_ranges    = ARRAY_SIZE(si1133_reg_ro_ranges),
 171};
 172
 173static const struct regmap_access_table si1133_read_ranges_table = {
 174        .yes_ranges     = si1133_reg_ranges,
 175        .n_yes_ranges   = ARRAY_SIZE(si1133_reg_ranges),
 176};
 177
 178static const struct regmap_access_table si1133_precious_table = {
 179        .yes_ranges     = si1133_precious_ranges,
 180        .n_yes_ranges   = ARRAY_SIZE(si1133_precious_ranges),
 181};
 182
 183static const struct regmap_config si1133_regmap_config = {
 184        .reg_bits = 8,
 185        .val_bits = 8,
 186
 187        .max_register = 0x2C,
 188
 189        .wr_table = &si1133_write_ranges_table,
 190        .rd_table = &si1133_read_ranges_table,
 191
 192        .precious_table = &si1133_precious_table,
 193};
 194
 195struct si1133_data {
 196        struct regmap *regmap;
 197        struct i2c_client *client;
 198
 199        /* Lock protecting one command at a time can be processed */
 200        struct mutex mutex;
 201
 202        int rsp_seq;
 203        u8 scan_mask;
 204        u8 adc_sens[6];
 205        u8 adc_config[6];
 206
 207        struct completion completion;
 208};
 209
 210struct si1133_coeff {
 211        s16 info;
 212        u16 mag;
 213};
 214
 215struct si1133_lux_coeff {
 216        struct si1133_coeff coeff_high[4];
 217        struct si1133_coeff coeff_low[9];
 218};
 219
 220static const struct si1133_lux_coeff lux_coeff = {
 221        {
 222                {  0,   209},
 223                { 1665,  93},
 224                { 2064,  65},
 225                {-2671, 234}
 226        },
 227        {
 228                {    0,     0},
 229                { 1921, 29053},
 230                {-1022, 36363},
 231                { 2320, 20789},
 232                { -367, 57909},
 233                {-1774, 38240},
 234                { -608, 46775},
 235                {-1503, 51831},
 236                {-1886, 58928}
 237        }
 238};
 239
 240static int si1133_calculate_polynomial_inner(s32 input, u8 fraction, u16 mag,
 241                                             s8 shift)
 242{
 243        return ((input << fraction) / mag) << shift;
 244}
 245
 246static int si1133_calculate_output(s32 x, s32 y, u8 x_order, u8 y_order,
 247                                   u8 input_fraction, s8 sign,
 248                                   const struct si1133_coeff *coeffs)
 249{
 250        s8 shift;
 251        int x1 = 1;
 252        int x2 = 1;
 253        int y1 = 1;
 254        int y2 = 1;
 255
 256        shift = ((u16)coeffs->info & 0xFF00) >> 8;
 257        shift ^= 0xFF;
 258        shift += 1;
 259        shift = -shift;
 260
 261        if (x_order > 0) {
 262                x1 = si1133_calculate_polynomial_inner(x, input_fraction,
 263                                                       coeffs->mag, shift);
 264                if (x_order > 1)
 265                        x2 = x1;
 266        }
 267
 268        if (y_order > 0) {
 269                y1 = si1133_calculate_polynomial_inner(y, input_fraction,
 270                                                       coeffs->mag, shift);
 271                if (y_order > 1)
 272                        y2 = y1;
 273        }
 274
 275        return sign * x1 * x2 * y1 * y2;
 276}
 277
 278/*
 279 * The algorithm is from:
 280 * https://siliconlabs.github.io/Gecko_SDK_Doc/efm32zg/html/si1133_8c_source.html#l00716
 281 */
 282static int si1133_calc_polynomial(s32 x, s32 y, u8 input_fraction, u8 num_coeff,
 283                                  const struct si1133_coeff *coeffs)
 284{
 285        u8 x_order, y_order;
 286        u8 counter;
 287        s8 sign;
 288        int output = 0;
 289
 290        for (counter = 0; counter < num_coeff; counter++) {
 291                if (coeffs->info < 0)
 292                        sign = -1;
 293                else
 294                        sign = 1;
 295
 296                x_order = si1133_get_x_order(coeffs->info);
 297                y_order = si1133_get_y_order(coeffs->info);
 298
 299                if ((x_order == 0) && (y_order == 0))
 300                        output +=
 301                               sign * coeffs->mag << SI1133_LUX_OUTPUT_FRACTION;
 302                else
 303                        output += si1133_calculate_output(x, y, x_order,
 304                                                          y_order,
 305                                                          input_fraction, sign,
 306                                                          coeffs);
 307                coeffs++;
 308        }
 309
 310        return abs(output);
 311}
 312
 313static int si1133_cmd_reset_sw(struct si1133_data *data)
 314{
 315        struct device *dev = &data->client->dev;
 316        unsigned int resp;
 317        unsigned long timeout;
 318        int err;
 319
 320        err = regmap_write(data->regmap, SI1133_REG_COMMAND,
 321                           SI1133_CMD_RESET_SW);
 322        if (err)
 323                return err;
 324
 325        timeout = jiffies + msecs_to_jiffies(SI1133_CMD_TIMEOUT_MS);
 326        while (true) {
 327                err = regmap_read(data->regmap, SI1133_REG_RESPONSE0, &resp);
 328                if (err == -ENXIO) {
 329                        usleep_range(SI1133_CMD_MINSLEEP_US_LOW,
 330                                     SI1133_CMD_MINSLEEP_US_HIGH);
 331                        continue;
 332                }
 333
 334                if ((resp & SI1133_MAX_CMD_CTR) == SI1133_MAX_CMD_CTR)
 335                        break;
 336
 337                if (time_after(jiffies, timeout)) {
 338                        dev_warn(dev, "Timeout on reset ctr resp: %d\n", resp);
 339                        return -ETIMEDOUT;
 340                }
 341        }
 342
 343        if (!err)
 344                data->rsp_seq = SI1133_MAX_CMD_CTR;
 345
 346        return err;
 347}
 348
 349static int si1133_parse_response_err(struct device *dev, u32 resp, u8 cmd)
 350{
 351        resp &= 0xF;
 352
 353        switch (resp) {
 354        case SI1133_ERR_OUTPUT_BUFFER_OVERFLOW:
 355                dev_warn(dev, "Output buffer overflow: 0x%02x\n", cmd);
 356                return -EOVERFLOW;
 357        case SI1133_ERR_SATURATION_ADC_OR_OVERFLOW_ACCUMULATION:
 358                dev_warn(dev, "Saturation of the ADC or overflow of accumulation: 0x%02x\n",
 359                         cmd);
 360                return -EOVERFLOW;
 361        case SI1133_ERR_INVALID_LOCATION_CMD:
 362                dev_warn(dev,
 363                         "Parameter access to an invalid location: 0x%02x\n",
 364                         cmd);
 365                return -EINVAL;
 366        case SI1133_ERR_INVALID_CMD:
 367                dev_warn(dev, "Invalid command 0x%02x\n", cmd);
 368                return -EINVAL;
 369        default:
 370                dev_warn(dev, "Unknown error 0x%02x\n", cmd);
 371                return -EINVAL;
 372        }
 373}
 374
 375static int si1133_cmd_reset_counter(struct si1133_data *data)
 376{
 377        int err = regmap_write(data->regmap, SI1133_REG_COMMAND,
 378                               SI1133_CMD_RESET_CTR);
 379        if (err)
 380                return err;
 381
 382        data->rsp_seq = 0;
 383
 384        return 0;
 385}
 386
 387static int si1133_command(struct si1133_data *data, u8 cmd)
 388{
 389        struct device *dev = &data->client->dev;
 390        u32 resp;
 391        int err;
 392        int expected_seq;
 393
 394        mutex_lock(&data->mutex);
 395
 396        expected_seq = (data->rsp_seq + 1) & SI1133_MAX_CMD_CTR;
 397
 398        if (cmd == SI1133_CMD_FORCE)
 399                reinit_completion(&data->completion);
 400
 401        err = regmap_write(data->regmap, SI1133_REG_COMMAND, cmd);
 402        if (err) {
 403                dev_warn(dev, "Failed to write command 0x%02x, ret=%d\n", cmd,
 404                         err);
 405                goto out;
 406        }
 407
 408        if (cmd == SI1133_CMD_FORCE) {
 409                /* wait for irq */
 410                if (!wait_for_completion_timeout(&data->completion,
 411                        msecs_to_jiffies(SI1133_COMPLETION_TIMEOUT_MS))) {
 412                        err = -ETIMEDOUT;
 413                        goto out;
 414                }
 415                err = regmap_read(data->regmap, SI1133_REG_RESPONSE0, &resp);
 416                if (err)
 417                        goto out;
 418        } else {
 419                err = regmap_read_poll_timeout(data->regmap,
 420                                               SI1133_REG_RESPONSE0, resp,
 421                                               (resp & SI1133_CMD_SEQ_MASK) ==
 422                                               expected_seq ||
 423                                               (resp & SI1133_CMD_ERR_MASK),
 424                                               SI1133_CMD_MINSLEEP_US_LOW,
 425                                               SI1133_CMD_TIMEOUT_MS * 1000);
 426                if (err) {
 427                        dev_warn(dev,
 428                                 "Failed to read command 0x%02x, ret=%d\n",
 429                                 cmd, err);
 430                        goto out;
 431                }
 432        }
 433
 434        if (resp & SI1133_CMD_ERR_MASK) {
 435                err = si1133_parse_response_err(dev, resp, cmd);
 436                si1133_cmd_reset_counter(data);
 437        } else {
 438                data->rsp_seq = expected_seq;
 439        }
 440
 441out:
 442        mutex_unlock(&data->mutex);
 443
 444        return err;
 445}
 446
 447static int si1133_param_set(struct si1133_data *data, u8 param, u32 value)
 448{
 449        int err = regmap_write(data->regmap, SI1133_REG_HOSTIN0, value);
 450
 451        if (err)
 452                return err;
 453
 454        return si1133_command(data, SI1133_CMD_PARAM_SET |
 455                              (param & SI1133_CMD_PARAM_MASK));
 456}
 457
 458static int si1133_param_query(struct si1133_data *data, u8 param, u32 *result)
 459{
 460        int err = si1133_command(data, SI1133_CMD_PARAM_QUERY |
 461                                 (param & SI1133_CMD_PARAM_MASK));
 462        if (err)
 463                return err;
 464
 465        return regmap_read(data->regmap, SI1133_REG_RESPONSE1, result);
 466}
 467
 468#define SI1133_CHANNEL(_ch, _type) \
 469        .type = _type, \
 470        .channel = _ch, \
 471        .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
 472        .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_INT_TIME) | \
 473                BIT(IIO_CHAN_INFO_SCALE) | \
 474                BIT(IIO_CHAN_INFO_HARDWAREGAIN), \
 475
 476static const struct iio_chan_spec si1133_channels[] = {
 477        {
 478                .type = IIO_LIGHT,
 479                .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
 480                .channel = 0,
 481        },
 482        {
 483                SI1133_CHANNEL(SI1133_PARAM_ADCMUX_WHITE, IIO_INTENSITY)
 484                .channel2 = IIO_MOD_LIGHT_BOTH,
 485        },
 486        {
 487                SI1133_CHANNEL(SI1133_PARAM_ADCMUX_LARGE_WHITE, IIO_INTENSITY)
 488                .channel2 = IIO_MOD_LIGHT_BOTH,
 489                .extend_name = "large",
 490        },
 491        {
 492                SI1133_CHANNEL(SI1133_PARAM_ADCMUX_SMALL_IR, IIO_INTENSITY)
 493                .extend_name = "small",
 494                .modified = 1,
 495                .channel2 = IIO_MOD_LIGHT_IR,
 496        },
 497        {
 498                SI1133_CHANNEL(SI1133_PARAM_ADCMUX_MED_IR, IIO_INTENSITY)
 499                .modified = 1,
 500                .channel2 = IIO_MOD_LIGHT_IR,
 501        },
 502        {
 503                SI1133_CHANNEL(SI1133_PARAM_ADCMUX_LARGE_IR, IIO_INTENSITY)
 504                .extend_name = "large",
 505                .modified = 1,
 506                .channel2 = IIO_MOD_LIGHT_IR,
 507        },
 508        {
 509                SI1133_CHANNEL(SI1133_PARAM_ADCMUX_UV, IIO_UVINDEX)
 510        },
 511        {
 512                SI1133_CHANNEL(SI1133_PARAM_ADCMUX_UV_DEEP, IIO_UVINDEX)
 513                .modified = 1,
 514                .channel2 = IIO_MOD_LIGHT_DUV,
 515        }
 516};
 517
 518static int si1133_get_int_time_index(int milliseconds, int nanoseconds)
 519{
 520        int i;
 521
 522        for (i = 0; i < ARRAY_SIZE(si1133_int_time_table); i++) {
 523                if (milliseconds == si1133_int_time_table[i][0] &&
 524                    nanoseconds == si1133_int_time_table[i][1])
 525                        return i;
 526        }
 527        return -EINVAL;
 528}
 529
 530static int si1133_set_integration_time(struct si1133_data *data, u8 adc,
 531                                       int milliseconds, int nanoseconds)
 532{
 533        int index;
 534
 535        index = si1133_get_int_time_index(milliseconds, nanoseconds);
 536        if (index < 0)
 537                return index;
 538
 539        data->adc_sens[adc] &= 0xF0;
 540        data->adc_sens[adc] |= index;
 541
 542        return si1133_param_set(data, SI1133_PARAM_REG_ADCSENS(0),
 543                                data->adc_sens[adc]);
 544}
 545
 546static int si1133_set_chlist(struct si1133_data *data, u8 scan_mask)
 547{
 548        /* channel list already set, no need to reprogram */
 549        if (data->scan_mask == scan_mask)
 550                return 0;
 551
 552        data->scan_mask = scan_mask;
 553
 554        return si1133_param_set(data, SI1133_PARAM_REG_CHAN_LIST, scan_mask);
 555}
 556
 557static int si1133_chan_set_adcconfig(struct si1133_data *data, u8 adc,
 558                                     u8 adc_config)
 559{
 560        int err;
 561
 562        err = si1133_param_set(data, SI1133_PARAM_REG_ADCCONFIG(adc),
 563                               adc_config);
 564        if (err)
 565                return err;
 566
 567        data->adc_config[adc] = adc_config;
 568
 569        return 0;
 570}
 571
 572static int si1133_update_adcconfig(struct si1133_data *data, uint8_t adc,
 573                                   u8 mask, u8 shift, u8 value)
 574{
 575        u32 adc_config;
 576        int err;
 577
 578        err = si1133_param_query(data, SI1133_PARAM_REG_ADCCONFIG(adc),
 579                                 &adc_config);
 580        if (err)
 581                return err;
 582
 583        adc_config &= ~mask;
 584        adc_config |= (value << shift);
 585
 586        return si1133_chan_set_adcconfig(data, adc, adc_config);
 587}
 588
 589static int si1133_set_adcmux(struct si1133_data *data, u8 adc, u8 mux)
 590{
 591        if ((mux & data->adc_config[adc]) == mux)
 592                return 0; /* mux already set to correct value */
 593
 594        return si1133_update_adcconfig(data, adc, SI1133_ADCMUX_MASK, 0, mux);
 595}
 596
 597static int si1133_force_measurement(struct si1133_data *data)
 598{
 599        return si1133_command(data, SI1133_CMD_FORCE);
 600}
 601
 602static int si1133_bulk_read(struct si1133_data *data, u8 start_reg, u8 length,
 603                            u8 *buffer)
 604{
 605        int err;
 606
 607        err = si1133_force_measurement(data);
 608        if (err)
 609                return err;
 610
 611        return regmap_bulk_read(data->regmap, start_reg, buffer, length);
 612}
 613
 614static int si1133_measure(struct si1133_data *data,
 615                          struct iio_chan_spec const *chan,
 616                          int *val)
 617{
 618        int err;
 619
 620        u8 buffer[SI1133_MEASURE_BUFFER_SIZE];
 621
 622        err = si1133_set_adcmux(data, 0, chan->channel);
 623        if (err)
 624                return err;
 625
 626        /* Deactivate lux measurements if they were active */
 627        err = si1133_set_chlist(data, BIT(0));
 628        if (err)
 629                return err;
 630
 631        err = si1133_bulk_read(data, SI1133_REG_HOSTOUT(0), sizeof(buffer),
 632                               buffer);
 633        if (err)
 634                return err;
 635
 636        *val = sign_extend32(get_unaligned_be24(&buffer[0]), 23);
 637
 638        return err;
 639}
 640
 641static irqreturn_t si1133_threaded_irq_handler(int irq, void *private)
 642{
 643        struct iio_dev *iio_dev = private;
 644        struct si1133_data *data = iio_priv(iio_dev);
 645        u32 irq_status;
 646        int err;
 647
 648        err = regmap_read(data->regmap, SI1133_REG_IRQ_STATUS, &irq_status);
 649        if (err) {
 650                dev_err_ratelimited(&iio_dev->dev, "Error reading IRQ\n");
 651                goto out;
 652        }
 653
 654        if (irq_status != data->scan_mask)
 655                return IRQ_NONE;
 656
 657out:
 658        complete(&data->completion);
 659
 660        return IRQ_HANDLED;
 661}
 662
 663static int si1133_scale_to_swgain(int scale_integer, int scale_fractional)
 664{
 665        scale_integer = find_closest(scale_integer, si1133_scale_available,
 666                                     ARRAY_SIZE(si1133_scale_available));
 667        if (scale_integer < 0 ||
 668            scale_integer > ARRAY_SIZE(si1133_scale_available) ||
 669            scale_fractional != 0)
 670                return -EINVAL;
 671
 672        return scale_integer;
 673}
 674
 675static int si1133_chan_set_adcsens(struct si1133_data *data, u8 adc,
 676                                   u8 adc_sens)
 677{
 678        int err;
 679
 680        err = si1133_param_set(data, SI1133_PARAM_REG_ADCSENS(adc), adc_sens);
 681        if (err)
 682                return err;
 683
 684        data->adc_sens[adc] = adc_sens;
 685
 686        return 0;
 687}
 688
 689static int si1133_update_adcsens(struct si1133_data *data, u8 mask,
 690                                 u8 shift, u8 value)
 691{
 692        int err;
 693        u32 adc_sens;
 694
 695        err = si1133_param_query(data, SI1133_PARAM_REG_ADCSENS(0),
 696                                 &adc_sens);
 697        if (err)
 698                return err;
 699
 700        adc_sens &= ~mask;
 701        adc_sens |= (value << shift);
 702
 703        return si1133_chan_set_adcsens(data, 0, adc_sens);
 704}
 705
 706static int si1133_get_lux(struct si1133_data *data, int *val)
 707{
 708        int err;
 709        int lux;
 710        s32 high_vis;
 711        s32 low_vis;
 712        s32 ir;
 713        u8 buffer[SI1133_LUX_BUFFER_SIZE];
 714
 715        /* Activate lux channels */
 716        err = si1133_set_chlist(data, SI1133_LUX_ADC_MASK);
 717        if (err)
 718                return err;
 719
 720        err = si1133_bulk_read(data, SI1133_REG_HOSTOUT(0),
 721                               SI1133_LUX_BUFFER_SIZE, buffer);
 722        if (err)
 723                return err;
 724
 725        high_vis = sign_extend32(get_unaligned_be24(&buffer[0]), 23);
 726
 727        low_vis = sign_extend32(get_unaligned_be24(&buffer[3]), 23);
 728
 729        ir = sign_extend32(get_unaligned_be24(&buffer[6]), 23);
 730
 731        if (high_vis > SI1133_ADC_THRESHOLD || ir > SI1133_ADC_THRESHOLD)
 732                lux = si1133_calc_polynomial(high_vis, ir,
 733                                             SI1133_INPUT_FRACTION_HIGH,
 734                                             ARRAY_SIZE(lux_coeff.coeff_high),
 735                                             &lux_coeff.coeff_high[0]);
 736        else
 737                lux = si1133_calc_polynomial(low_vis, ir,
 738                                             SI1133_INPUT_FRACTION_LOW,
 739                                             ARRAY_SIZE(lux_coeff.coeff_low),
 740                                             &lux_coeff.coeff_low[0]);
 741
 742        *val = lux >> SI1133_LUX_OUTPUT_FRACTION;
 743
 744        return err;
 745}
 746
 747static int si1133_read_raw(struct iio_dev *iio_dev,
 748                           struct iio_chan_spec const *chan,
 749                           int *val, int *val2, long mask)
 750{
 751        struct si1133_data *data = iio_priv(iio_dev);
 752        u8 adc_sens = data->adc_sens[0];
 753        int err;
 754
 755        switch (mask) {
 756        case IIO_CHAN_INFO_PROCESSED:
 757                switch (chan->type) {
 758                case IIO_LIGHT:
 759                        err = si1133_get_lux(data, val);
 760                        if (err)
 761                                return err;
 762
 763                        return IIO_VAL_INT;
 764                default:
 765                        return -EINVAL;
 766                }
 767        case IIO_CHAN_INFO_RAW:
 768                switch (chan->type) {
 769                case IIO_INTENSITY:
 770                case IIO_UVINDEX:
 771                        err = si1133_measure(data, chan, val);
 772                        if (err)
 773                                return err;
 774
 775                        return IIO_VAL_INT;
 776                default:
 777                        return -EINVAL;
 778                }
 779        case IIO_CHAN_INFO_INT_TIME:
 780                switch (chan->type) {
 781                case IIO_INTENSITY:
 782                case IIO_UVINDEX:
 783                        adc_sens &= SI1133_ADCSENS_HW_GAIN_MASK;
 784
 785                        *val = si1133_int_time_table[adc_sens][0];
 786                        *val2 = si1133_int_time_table[adc_sens][1];
 787                        return IIO_VAL_INT_PLUS_MICRO;
 788                default:
 789                        return -EINVAL;
 790                }
 791        case IIO_CHAN_INFO_SCALE:
 792                switch (chan->type) {
 793                case IIO_INTENSITY:
 794                case IIO_UVINDEX:
 795                        adc_sens &= SI1133_ADCSENS_SCALE_MASK;
 796                        adc_sens >>= SI1133_ADCSENS_SCALE_SHIFT;
 797
 798                        *val = BIT(adc_sens);
 799
 800                        return IIO_VAL_INT;
 801                default:
 802                        return -EINVAL;
 803                }
 804        case IIO_CHAN_INFO_HARDWAREGAIN:
 805                switch (chan->type) {
 806                case IIO_INTENSITY:
 807                case IIO_UVINDEX:
 808                        adc_sens >>= SI1133_ADCSENS_HSIG_SHIFT;
 809
 810                        *val = adc_sens;
 811
 812                        return IIO_VAL_INT;
 813                default:
 814                        return -EINVAL;
 815                }
 816        default:
 817                return -EINVAL;
 818        }
 819}
 820
 821static int si1133_write_raw(struct iio_dev *iio_dev,
 822                            struct iio_chan_spec const *chan,
 823                            int val, int val2, long mask)
 824{
 825        struct si1133_data *data = iio_priv(iio_dev);
 826
 827        switch (mask) {
 828        case IIO_CHAN_INFO_SCALE:
 829                switch (chan->type) {
 830                case IIO_INTENSITY:
 831                case IIO_UVINDEX:
 832                        val = si1133_scale_to_swgain(val, val2);
 833                        if (val < 0)
 834                                return val;
 835
 836                        return si1133_update_adcsens(data,
 837                                                     SI1133_ADCSENS_SCALE_MASK,
 838                                                     SI1133_ADCSENS_SCALE_SHIFT,
 839                                                     val);
 840                default:
 841                        return -EINVAL;
 842                }
 843        case IIO_CHAN_INFO_INT_TIME:
 844                return si1133_set_integration_time(data, 0, val, val2);
 845        case IIO_CHAN_INFO_HARDWAREGAIN:
 846                switch (chan->type) {
 847                case IIO_INTENSITY:
 848                case IIO_UVINDEX:
 849                        if (val != 0 && val != 1)
 850                                return -EINVAL;
 851
 852                        return si1133_update_adcsens(data,
 853                                                     SI1133_ADCSENS_HSIG_MASK,
 854                                                     SI1133_ADCSENS_HSIG_SHIFT,
 855                                                     val);
 856                default:
 857                        return -EINVAL;
 858                }
 859        default:
 860                return -EINVAL;
 861        }
 862}
 863
 864static struct attribute *si1133_attributes[] = {
 865        &iio_const_attr_integration_time_available.dev_attr.attr,
 866        &iio_const_attr_scale_available.dev_attr.attr,
 867        NULL,
 868};
 869
 870static const struct attribute_group si1133_attribute_group = {
 871        .attrs = si1133_attributes,
 872};
 873
 874static const struct iio_info si1133_info = {
 875        .read_raw = si1133_read_raw,
 876        .write_raw = si1133_write_raw,
 877        .attrs = &si1133_attribute_group,
 878};
 879
 880/*
 881 * si1133_init_lux_channels - Configure 3 different channels(adc) (1,2 and 3)
 882 * The channel configuration for the lux measurement was taken from :
 883 * https://siliconlabs.github.io/Gecko_SDK_Doc/efm32zg/html/si1133_8c_source.html#l00578
 884 *
 885 * Reserved the channel 0 for the other raw measurements
 886 */
 887static int si1133_init_lux_channels(struct si1133_data *data)
 888{
 889        int err;
 890
 891        err = si1133_chan_set_adcconfig(data, 1,
 892                                        SI1133_ADCCONFIG_DECIM_RATE(1) |
 893                                        SI1133_PARAM_ADCMUX_LARGE_WHITE);
 894        if (err)
 895                return err;
 896
 897        err = si1133_param_set(data, SI1133_PARAM_REG_ADCPOST(1),
 898                               SI1133_ADCPOST_24BIT_EN |
 899                               SI1133_ADCPOST_POSTSHIFT_BITQTY(0));
 900        if (err)
 901                return err;
 902        err = si1133_chan_set_adcsens(data, 1, SI1133_ADCSENS_HSIG_MASK |
 903                                      SI1133_ADCSENS_NB_MEAS(64) | _48_8_us);
 904        if (err)
 905                return err;
 906
 907        err = si1133_chan_set_adcconfig(data, 2,
 908                                        SI1133_ADCCONFIG_DECIM_RATE(1) |
 909                                        SI1133_PARAM_ADCMUX_LARGE_WHITE);
 910        if (err)
 911                return err;
 912
 913        err = si1133_param_set(data, SI1133_PARAM_REG_ADCPOST(2),
 914                               SI1133_ADCPOST_24BIT_EN |
 915                               SI1133_ADCPOST_POSTSHIFT_BITQTY(2));
 916        if (err)
 917                return err;
 918
 919        err = si1133_chan_set_adcsens(data, 2, SI1133_ADCSENS_HSIG_MASK |
 920                                      SI1133_ADCSENS_NB_MEAS(1) | _3_120_0_us);
 921        if (err)
 922                return err;
 923
 924        err = si1133_chan_set_adcconfig(data, 3,
 925                                        SI1133_ADCCONFIG_DECIM_RATE(1) |
 926                                        SI1133_PARAM_ADCMUX_MED_IR);
 927        if (err)
 928                return err;
 929
 930        err = si1133_param_set(data, SI1133_PARAM_REG_ADCPOST(3),
 931                               SI1133_ADCPOST_24BIT_EN |
 932                               SI1133_ADCPOST_POSTSHIFT_BITQTY(2));
 933        if (err)
 934                return err;
 935
 936        return  si1133_chan_set_adcsens(data, 3, SI1133_ADCSENS_HSIG_MASK |
 937                                        SI1133_ADCSENS_NB_MEAS(64) | _48_8_us);
 938}
 939
 940static int si1133_initialize(struct si1133_data *data)
 941{
 942        int err;
 943
 944        err = si1133_cmd_reset_sw(data);
 945        if (err)
 946                return err;
 947
 948        /* Turn off autonomous mode */
 949        err = si1133_param_set(data, SI1133_REG_MEAS_RATE, 0);
 950        if (err)
 951                return err;
 952
 953        err = si1133_init_lux_channels(data);
 954        if (err)
 955                return err;
 956
 957        return regmap_write(data->regmap, SI1133_REG_IRQ_ENABLE,
 958                            SI1133_IRQ_CHANNEL_ENABLE);
 959}
 960
 961static int si1133_validate_ids(struct iio_dev *iio_dev)
 962{
 963        struct si1133_data *data = iio_priv(iio_dev);
 964
 965        unsigned int part_id, rev_id, mfr_id;
 966        int err;
 967
 968        err = regmap_read(data->regmap, SI1133_REG_PART_ID, &part_id);
 969        if (err)
 970                return err;
 971
 972        err = regmap_read(data->regmap, SI1133_REG_REV_ID, &rev_id);
 973        if (err)
 974                return err;
 975
 976        err = regmap_read(data->regmap, SI1133_REG_MFR_ID, &mfr_id);
 977        if (err)
 978                return err;
 979
 980        dev_info(&iio_dev->dev,
 981                 "Device ID part 0x%02x rev 0x%02x mfr 0x%02x\n",
 982                 part_id, rev_id, mfr_id);
 983        if (part_id != SI1133_PART_ID) {
 984                dev_err(&iio_dev->dev,
 985                        "Part ID mismatch got 0x%02x, expected 0x%02x\n",
 986                        part_id, SI1133_PART_ID);
 987                return -ENODEV;
 988        }
 989
 990        return 0;
 991}
 992
 993static int si1133_probe(struct i2c_client *client,
 994                        const struct i2c_device_id *id)
 995{
 996        struct si1133_data *data;
 997        struct iio_dev *iio_dev;
 998        int err;
 999
1000        iio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
1001        if (!iio_dev)
1002                return -ENOMEM;
1003
1004        data = iio_priv(iio_dev);
1005
1006        init_completion(&data->completion);
1007
1008        data->regmap = devm_regmap_init_i2c(client, &si1133_regmap_config);
1009        if (IS_ERR(data->regmap)) {
1010                err = PTR_ERR(data->regmap);
1011                dev_err(&client->dev, "Failed to initialise regmap: %d\n", err);
1012                return err;
1013        }
1014
1015        i2c_set_clientdata(client, iio_dev);
1016        data->client = client;
1017
1018        iio_dev->name = id->name;
1019        iio_dev->channels = si1133_channels;
1020        iio_dev->num_channels = ARRAY_SIZE(si1133_channels);
1021        iio_dev->info = &si1133_info;
1022        iio_dev->modes = INDIO_DIRECT_MODE;
1023
1024        mutex_init(&data->mutex);
1025
1026        err = si1133_validate_ids(iio_dev);
1027        if (err)
1028                return err;
1029
1030        err = si1133_initialize(data);
1031        if (err) {
1032                dev_err(&client->dev,
1033                        "Error when initializing chip: %d\n", err);
1034                return err;
1035        }
1036
1037        if (!client->irq) {
1038                dev_err(&client->dev,
1039                        "Required interrupt not provided, cannot proceed\n");
1040                return -EINVAL;
1041        }
1042
1043        err = devm_request_threaded_irq(&client->dev, client->irq,
1044                                        NULL,
1045                                        si1133_threaded_irq_handler,
1046                                        IRQF_ONESHOT | IRQF_SHARED,
1047                                        client->name, iio_dev);
1048        if (err) {
1049                dev_warn(&client->dev, "Request irq %d failed: %i\n",
1050                         client->irq, err);
1051                return err;
1052        }
1053
1054        return devm_iio_device_register(&client->dev, iio_dev);
1055}
1056
1057static const struct i2c_device_id si1133_ids[] = {
1058        { "si1133", 0 },
1059        { }
1060};
1061MODULE_DEVICE_TABLE(i2c, si1133_ids);
1062
1063static struct i2c_driver si1133_driver = {
1064        .driver = {
1065            .name   = "si1133",
1066        },
1067        .probe  = si1133_probe,
1068        .id_table = si1133_ids,
1069};
1070
1071module_i2c_driver(si1133_driver);
1072
1073MODULE_AUTHOR("Maxime Roussin-Belanger <maxime.roussinbelanger@gmail.com>");
1074MODULE_DESCRIPTION("Silabs SI1133, UV index sensor and ambient light sensor driver");
1075MODULE_LICENSE("GPL");
1076