brintos

brintos / linux-shallow public Read only

0
0
Text · 32.2 KiB · 850c246 Raw
1224 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Copyright (C) 2021 Joe Sandom <joe.g.sandom@gmail.com>4 *5 * Datasheet: https://ams.com/tsl25911#tab/documents6 *7 * Device driver for the TAOS TSL2591. This is a very-high sensitivity8 * light-to-digital converter that transforms light intensity into a digital9 * signal.10 */11 12#include <linux/bitfield.h>13#include <linux/debugfs.h>14#include <linux/delay.h>15#include <linux/i2c.h>16#include <linux/interrupt.h>17#include <linux/iopoll.h>18#include <linux/kernel.h>19#include <linux/module.h>20#include <linux/mutex.h>21#include <linux/pm_runtime.h>22#include <linux/sysfs.h>23 24#include <linux/unaligned.h>25 26#include <linux/iio/events.h>27#include <linux/iio/iio.h>28#include <linux/iio/sysfs.h>29 30/* ADC integration time, field value to time in ms */31#define TSL2591_FVAL_TO_MSEC(x) (((x) + 1) * 100)32/* ADC integration time, field value to time in seconds */33#define TSL2591_FVAL_TO_SEC(x) ((x) + 1)34/* ADC integration time, time in seconds to field value */35#define TSL2591_SEC_TO_FVAL(x) ((x) - 1)36 37/* TSL2591 register set */38#define TSL2591_ENABLE      0x0039#define TSL2591_CONTROL     0x0140#define TSL2591_AILTL       0x0441#define TSL2591_AILTH       0x0542#define TSL2591_AIHTL       0x0643#define TSL2591_AIHTH       0x0744#define TSL2591_NP_AILTL    0x0845#define TSL2591_NP_AILTH    0x0946#define TSL2591_NP_AIHTL    0x0A47#define TSL2591_NP_AIHTH    0x0B48#define TSL2591_PERSIST     0x0C49#define TSL2591_PACKAGE_ID  0x1150#define TSL2591_DEVICE_ID   0x1251#define TSL2591_STATUS      0x1352#define TSL2591_C0_DATAL    0x1453#define TSL2591_C0_DATAH    0x1554#define TSL2591_C1_DATAL    0x1655#define TSL2591_C1_DATAH    0x1756 57/* TSL2591 command register definitions */58#define TSL2591_CMD_NOP             0xA059#define TSL2591_CMD_SF_INTSET       0xE460#define TSL2591_CMD_SF_CALS_I       0xE561#define TSL2591_CMD_SF_CALS_NPI     0xE762#define TSL2591_CMD_SF_CNP_ALSI     0xEA63 64/* TSL2591 enable register definitions */65#define TSL2591_PWR_ON              0x0166#define TSL2591_PWR_OFF             0x0067#define TSL2591_ENABLE_ALS          0x0268#define TSL2591_ENABLE_ALS_INT      0x1069#define TSL2591_ENABLE_SLEEP_INT    0x4070#define TSL2591_ENABLE_NP_INT       0x8071 72/* TSL2591 control register definitions */73#define TSL2591_CTRL_ALS_INTEGRATION_100MS  0x0074#define TSL2591_CTRL_ALS_INTEGRATION_200MS  0x0175#define TSL2591_CTRL_ALS_INTEGRATION_300MS  0x0276#define TSL2591_CTRL_ALS_INTEGRATION_400MS  0x0377#define TSL2591_CTRL_ALS_INTEGRATION_500MS  0x0478#define TSL2591_CTRL_ALS_INTEGRATION_600MS  0x0579#define TSL2591_CTRL_ALS_LOW_GAIN           0x0080#define TSL2591_CTRL_ALS_MED_GAIN           0x1081#define TSL2591_CTRL_ALS_HIGH_GAIN          0x2082#define TSL2591_CTRL_ALS_MAX_GAIN           0x3083#define TSL2591_CTRL_SYS_RESET              0x8084 85/* TSL2591 persist register definitions */86#define TSL2591_PRST_ALS_INT_CYCLE_0        0x0087#define TSL2591_PRST_ALS_INT_CYCLE_ANY      0x0188#define TSL2591_PRST_ALS_INT_CYCLE_2        0x0289#define TSL2591_PRST_ALS_INT_CYCLE_3        0x0390#define TSL2591_PRST_ALS_INT_CYCLE_5        0x0491#define TSL2591_PRST_ALS_INT_CYCLE_10       0x0592#define TSL2591_PRST_ALS_INT_CYCLE_15       0x0693#define TSL2591_PRST_ALS_INT_CYCLE_20       0x0794#define TSL2591_PRST_ALS_INT_CYCLE_25       0x0895#define TSL2591_PRST_ALS_INT_CYCLE_30       0x0996#define TSL2591_PRST_ALS_INT_CYCLE_35       0x0A97#define TSL2591_PRST_ALS_INT_CYCLE_40       0x0B98#define TSL2591_PRST_ALS_INT_CYCLE_45       0x0C99#define TSL2591_PRST_ALS_INT_CYCLE_50       0x0D100#define TSL2591_PRST_ALS_INT_CYCLE_55       0x0E101#define TSL2591_PRST_ALS_INT_CYCLE_60       0x0F102#define TSL2591_PRST_ALS_INT_CYCLE_MAX      (BIT(4) - 1)103 104/* TSL2591 PID register mask */105#define TSL2591_PACKAGE_ID_MASK  GENMASK(5, 4)106 107/* TSL2591 ID register mask */108#define TSL2591_DEVICE_ID_MASK   GENMASK(7, 0)109 110/* TSL2591 status register masks */111#define TSL2591_STS_ALS_VALID_MASK   BIT(0)112#define TSL2591_STS_ALS_INT_MASK     BIT(4)113#define TSL2591_STS_NPERS_INT_MASK   BIT(5)114#define TSL2591_STS_VAL_HIGH_MASK    BIT(0)115 116/* TSL2591 constant values */117#define TSL2591_PACKAGE_ID_VAL  0x00118#define TSL2591_DEVICE_ID_VAL   0x50119 120/* Power off suspend delay time MS */121#define TSL2591_POWER_OFF_DELAY_MS   2000122 123/* TSL2591 default values */124#define TSL2591_DEFAULT_ALS_INT_TIME          TSL2591_CTRL_ALS_INTEGRATION_300MS125#define TSL2591_DEFAULT_ALS_GAIN              TSL2591_CTRL_ALS_MED_GAIN126#define TSL2591_DEFAULT_ALS_PERSIST           TSL2591_PRST_ALS_INT_CYCLE_ANY127#define TSL2591_DEFAULT_ALS_LOWER_THRESH      100128#define TSL2591_DEFAULT_ALS_UPPER_THRESH      1500129 130/* TSL2591 number of data registers */131#define TSL2591_NUM_DATA_REGISTERS     4132 133/* TSL2591 number of valid status reads on ADC complete */134#define TSL2591_ALS_STS_VALID_COUNT    10135 136/* TSL2591 delay period between polls when checking for ALS valid flag */137#define TSL2591_DELAY_PERIOD_US        10000138 139/* TSL2591 maximum values */140#define TSL2591_MAX_ALS_INT_TIME_MS    600141#define TSL2591_ALS_MAX_VALUE	       (BIT(16) - 1)142 143/*144 * LUX calculations;145 * AGAIN values from Adafruit's TSL2591 Arduino library146 * https://github.com/adafruit/Adafruit_TSL2591_Library147 */148#define TSL2591_CTRL_ALS_LOW_GAIN_MULTIPLIER   1149#define TSL2591_CTRL_ALS_MED_GAIN_MULTIPLIER   25150#define TSL2591_CTRL_ALS_HIGH_GAIN_MULTIPLIER  428151#define TSL2591_CTRL_ALS_MAX_GAIN_MULTIPLIER   9876152#define TSL2591_LUX_COEFFICIENT                408153 154struct tsl2591_als_settings {155	u16 als_lower_thresh;156	u16 als_upper_thresh;157	u8 als_int_time;158	u8 als_persist;159	u8 als_gain;160};161 162struct tsl2591_chip {163	struct tsl2591_als_settings als_settings;164	struct i2c_client *client;165	/*166	 * Keep als_settings in sync with hardware state167	 * and ensure multiple readers are serialized.168	 */169	struct mutex als_mutex;170	bool events_enabled;171};172 173/*174 * Period table is ALS persist cycle x integration time setting175 * Integration times: 100ms, 200ms, 300ms, 400ms, 500ms, 600ms176 * ALS cycles: 1, 2, 3, 5, 10, 20, 25, 30, 35, 40, 45, 50, 55, 60177 */178static const char * const tsl2591_als_period_list[] = {179	"0.1 0.2 0.3 0.5 1.0 2.0 2.5 3.0 3.5 4.0 4.5 5.0 5.5 6.0",180	"0.2 0.4 0.6 1.0 2.0 4.0 5.0 6.0 7.0 8.0 9.0 10.0 11.0 12.0",181	"0.3 0.6 0.9 1.5 3.0 6.0 7.5 9.0 10.5 12.0 13.5 15.0 16.5 18.0",182	"0.4 0.8 1.2 2.0 4.0 8.0 10.0 12.0 14.0 16.0 18.0 20.0 22.0 24.0",183	"0.5 1.0 1.5 2.5 5.0 10.0 12.5 15.0 17.5 20.0 22.5 25.0 27.5 30.0",184	"0.6 1.2 1.8 3.0 6.0 12.0 15.0 18.0 21.0 24.0 27.0 30.0 33.0 36.0",185};186 187static const int tsl2591_int_time_available[] = {188	1, 2, 3, 4, 5, 6,189};190 191static const int tsl2591_calibscale_available[] = {192	1, 25, 428, 9876,193};194 195static int tsl2591_set_als_lower_threshold(struct tsl2591_chip *chip,196					   u16 als_lower_threshold);197static int tsl2591_set_als_upper_threshold(struct tsl2591_chip *chip,198					   u16 als_upper_threshold);199 200static int tsl2591_gain_to_multiplier(const u8 als_gain)201{202	switch (als_gain) {203	case TSL2591_CTRL_ALS_LOW_GAIN:204		return TSL2591_CTRL_ALS_LOW_GAIN_MULTIPLIER;205	case TSL2591_CTRL_ALS_MED_GAIN:206		return TSL2591_CTRL_ALS_MED_GAIN_MULTIPLIER;207	case TSL2591_CTRL_ALS_HIGH_GAIN:208		return TSL2591_CTRL_ALS_HIGH_GAIN_MULTIPLIER;209	case TSL2591_CTRL_ALS_MAX_GAIN:210		return TSL2591_CTRL_ALS_MAX_GAIN_MULTIPLIER;211	default:212		return -EINVAL;213	}214}215 216static int tsl2591_multiplier_to_gain(const u32 multiplier)217{218	switch (multiplier) {219	case TSL2591_CTRL_ALS_LOW_GAIN_MULTIPLIER:220		return TSL2591_CTRL_ALS_LOW_GAIN;221	case TSL2591_CTRL_ALS_MED_GAIN_MULTIPLIER:222		return TSL2591_CTRL_ALS_MED_GAIN;223	case TSL2591_CTRL_ALS_HIGH_GAIN_MULTIPLIER:224		return TSL2591_CTRL_ALS_HIGH_GAIN;225	case TSL2591_CTRL_ALS_MAX_GAIN_MULTIPLIER:226		return TSL2591_CTRL_ALS_MAX_GAIN;227	default:228		return -EINVAL;229	}230}231 232static int tsl2591_persist_cycle_to_lit(const u8 als_persist)233{234	switch (als_persist) {235	case TSL2591_PRST_ALS_INT_CYCLE_ANY:236		return 1;237	case TSL2591_PRST_ALS_INT_CYCLE_2:238		return 2;239	case TSL2591_PRST_ALS_INT_CYCLE_3:240		return 3;241	case TSL2591_PRST_ALS_INT_CYCLE_5:242		return 5;243	case TSL2591_PRST_ALS_INT_CYCLE_10:244		return 10;245	case TSL2591_PRST_ALS_INT_CYCLE_15:246		return 15;247	case TSL2591_PRST_ALS_INT_CYCLE_20:248		return 20;249	case TSL2591_PRST_ALS_INT_CYCLE_25:250		return 25;251	case TSL2591_PRST_ALS_INT_CYCLE_30:252		return 30;253	case TSL2591_PRST_ALS_INT_CYCLE_35:254		return 35;255	case TSL2591_PRST_ALS_INT_CYCLE_40:256		return 40;257	case TSL2591_PRST_ALS_INT_CYCLE_45:258		return 45;259	case TSL2591_PRST_ALS_INT_CYCLE_50:260		return 50;261	case TSL2591_PRST_ALS_INT_CYCLE_55:262		return 55;263	case TSL2591_PRST_ALS_INT_CYCLE_60:264		return 60;265	default:266		return -EINVAL;267	}268}269 270static int tsl2591_persist_lit_to_cycle(const u8 als_persist)271{272	switch (als_persist) {273	case 1:274		return TSL2591_PRST_ALS_INT_CYCLE_ANY;275	case 2:276		return TSL2591_PRST_ALS_INT_CYCLE_2;277	case 3:278		return TSL2591_PRST_ALS_INT_CYCLE_3;279	case 5:280		return TSL2591_PRST_ALS_INT_CYCLE_5;281	case 10:282		return TSL2591_PRST_ALS_INT_CYCLE_10;283	case 15:284		return TSL2591_PRST_ALS_INT_CYCLE_15;285	case 20:286		return TSL2591_PRST_ALS_INT_CYCLE_20;287	case 25:288		return TSL2591_PRST_ALS_INT_CYCLE_25;289	case 30:290		return TSL2591_PRST_ALS_INT_CYCLE_30;291	case 35:292		return TSL2591_PRST_ALS_INT_CYCLE_35;293	case 40:294		return TSL2591_PRST_ALS_INT_CYCLE_40;295	case 45:296		return TSL2591_PRST_ALS_INT_CYCLE_45;297	case 50:298		return TSL2591_PRST_ALS_INT_CYCLE_50;299	case 55:300		return TSL2591_PRST_ALS_INT_CYCLE_55;301	case 60:302		return TSL2591_PRST_ALS_INT_CYCLE_60;303	default:304		return -EINVAL;305	}306}307 308static int tsl2591_compatible_int_time(struct tsl2591_chip *chip,309				       const u32 als_integration_time)310{311	switch (als_integration_time) {312	case TSL2591_CTRL_ALS_INTEGRATION_100MS:313	case TSL2591_CTRL_ALS_INTEGRATION_200MS:314	case TSL2591_CTRL_ALS_INTEGRATION_300MS:315	case TSL2591_CTRL_ALS_INTEGRATION_400MS:316	case TSL2591_CTRL_ALS_INTEGRATION_500MS:317	case TSL2591_CTRL_ALS_INTEGRATION_600MS:318		return 0;319	default:320		return -EINVAL;321	}322}323 324static int tsl2591_als_time_to_fval(const u32 als_integration_time)325{326	int i;327 328	for (i = 0; i < ARRAY_SIZE(tsl2591_int_time_available); i++) {329		if (als_integration_time == tsl2591_int_time_available[i])330			return TSL2591_SEC_TO_FVAL(als_integration_time);331	}332 333	return -EINVAL;334}335 336static int tsl2591_compatible_gain(struct tsl2591_chip *chip, const u8 als_gain)337{338	switch (als_gain) {339	case TSL2591_CTRL_ALS_LOW_GAIN:340	case TSL2591_CTRL_ALS_MED_GAIN:341	case TSL2591_CTRL_ALS_HIGH_GAIN:342	case TSL2591_CTRL_ALS_MAX_GAIN:343		return 0;344	default:345		return -EINVAL;346	}347}348 349static int tsl2591_compatible_als_persist_cycle(struct tsl2591_chip *chip,350						const u32 als_persist)351{352	switch (als_persist) {353	case TSL2591_PRST_ALS_INT_CYCLE_ANY:354	case TSL2591_PRST_ALS_INT_CYCLE_2:355	case TSL2591_PRST_ALS_INT_CYCLE_3:356	case TSL2591_PRST_ALS_INT_CYCLE_5:357	case TSL2591_PRST_ALS_INT_CYCLE_10:358	case TSL2591_PRST_ALS_INT_CYCLE_15:359	case TSL2591_PRST_ALS_INT_CYCLE_20:360	case TSL2591_PRST_ALS_INT_CYCLE_25:361	case TSL2591_PRST_ALS_INT_CYCLE_30:362	case TSL2591_PRST_ALS_INT_CYCLE_35:363	case TSL2591_PRST_ALS_INT_CYCLE_40:364	case TSL2591_PRST_ALS_INT_CYCLE_45:365	case TSL2591_PRST_ALS_INT_CYCLE_50:366	case TSL2591_PRST_ALS_INT_CYCLE_55:367	case TSL2591_PRST_ALS_INT_CYCLE_60:368		return 0;369	default:370		return -EINVAL;371	}372}373 374static int tsl2591_check_als_valid(struct i2c_client *client)375{376	int ret;377 378	ret = i2c_smbus_read_byte_data(client, TSL2591_CMD_NOP | TSL2591_STATUS);379	if (ret < 0) {380		dev_err(&client->dev, "Failed to read register\n");381		return -EINVAL;382	}383 384	return FIELD_GET(TSL2591_STS_ALS_VALID_MASK, ret);385}386 387static int tsl2591_wait_adc_complete(struct tsl2591_chip *chip)388{389	struct tsl2591_als_settings settings = chip->als_settings;390	struct i2c_client *client = chip->client;391	int delay;392	int val;393	int ret;394 395	delay = TSL2591_FVAL_TO_MSEC(settings.als_int_time);396	if (!delay)397		return -EINVAL;398 399	/*400	 * Sleep for ALS integration time to allow enough time or an ADC read401	 * cycle to complete. Check status after delay for ALS valid.402	 */403	msleep(delay);404 405	/* Check for status ALS valid flag for up to 100ms */406	ret = readx_poll_timeout(tsl2591_check_als_valid, client,407				 val, val == TSL2591_STS_VAL_HIGH_MASK,408				 TSL2591_DELAY_PERIOD_US,409				 TSL2591_DELAY_PERIOD_US * TSL2591_ALS_STS_VALID_COUNT);410	if (ret)411		dev_err(&client->dev, "Timed out waiting for valid ALS data\n");412 413	return ret;414}415 416/*417 * tsl2591_read_channel_data - Reads raw channel data and calculates lux418 *419 * Formula for lux calculation;420 * Derived from Adafruit's TSL2591 library421 * Link: https://github.com/adafruit/Adafruit_TSL2591_Library422 * Counts Per Lux (CPL) = (ATIME_ms * AGAIN) / LUX DF423 * lux = ((C0DATA - C1DATA) * (1 - (C1DATA / C0DATA))) / CPL424 *425 * Scale values to get more representative value of lux i.e.426 * lux = ((C0DATA - C1DATA) * (1000 - ((C1DATA * 1000) / C0DATA))) / CPL427 *428 * Channel 0 = IR + Visible429 * Channel 1 = IR only430 */431static int tsl2591_read_channel_data(struct iio_dev *indio_dev,432				     struct iio_chan_spec const *chan,433				     int *val, int *val2)434{435	struct tsl2591_chip *chip = iio_priv(indio_dev);436	struct tsl2591_als_settings *settings = &chip->als_settings;437	struct i2c_client *client = chip->client;438	u8 als_data[TSL2591_NUM_DATA_REGISTERS];439	int counts_per_lux, int_time_fval, gain_multi, lux;440	u16 als_ch0, als_ch1;441	int ret;442 443	ret = tsl2591_wait_adc_complete(chip);444	if (ret < 0) {445		dev_err(&client->dev, "No data available. Err: %d\n", ret);446		return ret;447	}448 449	ret = i2c_smbus_read_i2c_block_data(client,450					    TSL2591_CMD_NOP | TSL2591_C0_DATAL,451					    sizeof(als_data), als_data);452	if (ret < 0) {453		dev_err(&client->dev, "Failed to read data bytes");454		return ret;455	}456 457	als_ch0 = get_unaligned_le16(&als_data[0]);458	als_ch1 = get_unaligned_le16(&als_data[2]);459 460	switch (chan->type) {461	case IIO_INTENSITY:462		if (chan->channel2 == IIO_MOD_LIGHT_BOTH)463			*val = als_ch0;464		else if (chan->channel2 == IIO_MOD_LIGHT_IR)465			*val = als_ch1;466		else467			return -EINVAL;468		break;469	case IIO_LIGHT:470		gain_multi = tsl2591_gain_to_multiplier(settings->als_gain);471		if (gain_multi < 0) {472			dev_err(&client->dev, "Invalid multiplier");473			return gain_multi;474		}475 476		int_time_fval = TSL2591_FVAL_TO_MSEC(settings->als_int_time);477		/* Calculate counts per lux value */478		counts_per_lux = (int_time_fval * gain_multi) / TSL2591_LUX_COEFFICIENT;479 480		dev_dbg(&client->dev, "Counts Per Lux: %d\n", counts_per_lux);481 482		/* Calculate lux value */483		lux = ((als_ch0 - als_ch1) *484		       (1000 - ((als_ch1 * 1000) / als_ch0))) / counts_per_lux;485 486		dev_dbg(&client->dev, "Raw lux calculation: %d\n", lux);487 488		/* Divide by 1000 to get real lux value before scaling */489		*val = lux / 1000;490 491		/* Get the decimal part of lux reading */492		*val2 = (lux - (*val * 1000)) * 1000;493 494		break;495	default:496		return -EINVAL;497	}498 499	return 0;500}501 502static int tsl2591_set_als_gain_int_time(struct tsl2591_chip *chip)503{504	struct tsl2591_als_settings als_settings = chip->als_settings;505	struct i2c_client *client = chip->client;506	int ret;507 508	ret = i2c_smbus_write_byte_data(client,509					TSL2591_CMD_NOP | TSL2591_CONTROL,510					als_settings.als_int_time | als_settings.als_gain);511	if (ret)512		dev_err(&client->dev, "Failed to set als gain & int time\n");513 514	return ret;515}516 517static int tsl2591_set_als_lower_threshold(struct tsl2591_chip *chip,518					   u16 als_lower_threshold)519{520	struct tsl2591_als_settings als_settings = chip->als_settings;521	struct i2c_client *client = chip->client;522	u16 als_upper_threshold;523	u8 als_lower_l;524	u8 als_lower_h;525	int ret;526 527	chip->als_settings.als_lower_thresh = als_lower_threshold;528 529	/*530	 * Lower threshold should not be greater or equal to upper.531	 * If this is the case, then assert upper threshold to new lower532	 * threshold + 1 to avoid ordering issues when setting thresholds.533	 */534	if (als_lower_threshold >= als_settings.als_upper_thresh) {535		als_upper_threshold = als_lower_threshold + 1;536		tsl2591_set_als_upper_threshold(chip, als_upper_threshold);537	}538 539	als_lower_l = als_lower_threshold;540	als_lower_h = als_lower_threshold >> 8;541 542	ret = i2c_smbus_write_byte_data(client,543					TSL2591_CMD_NOP | TSL2591_AILTL,544					als_lower_l);545	if (ret) {546		dev_err(&client->dev, "Failed to set als lower threshold\n");547		return ret;548	}549 550	ret = i2c_smbus_write_byte_data(client,551					TSL2591_CMD_NOP | TSL2591_AILTH,552					als_lower_h);553	if (ret) {554		dev_err(&client->dev, "Failed to set als lower threshold\n");555		return ret;556	}557 558	return 0;559}560 561static int tsl2591_set_als_upper_threshold(struct tsl2591_chip *chip,562					   u16 als_upper_threshold)563{564	struct tsl2591_als_settings als_settings = chip->als_settings;565	struct i2c_client *client = chip->client;566	u16 als_lower_threshold;567	u8 als_upper_l;568	u8 als_upper_h;569	int ret;570 571	if (als_upper_threshold > TSL2591_ALS_MAX_VALUE)572		return -EINVAL;573 574	chip->als_settings.als_upper_thresh = als_upper_threshold;575 576	/*577	 * Upper threshold should not be less than lower. If this578	 * is the case, then assert lower threshold to new upper579	 * threshold - 1 to avoid ordering issues when setting thresholds.580	 */581	if (als_upper_threshold < als_settings.als_lower_thresh) {582		als_lower_threshold = als_upper_threshold - 1;583		tsl2591_set_als_lower_threshold(chip, als_lower_threshold);584	}585 586	als_upper_l = als_upper_threshold;587	als_upper_h = als_upper_threshold >> 8;588 589	ret = i2c_smbus_write_byte_data(client,590					TSL2591_CMD_NOP | TSL2591_AIHTL,591					als_upper_l);592	if (ret) {593		dev_err(&client->dev, "Failed to set als upper threshold\n");594		return ret;595	}596 597	ret = i2c_smbus_write_byte_data(client,598					TSL2591_CMD_NOP | TSL2591_AIHTH,599					als_upper_h);600	if (ret) {601		dev_err(&client->dev, "Failed to set als upper threshold\n");602		return ret;603	}604 605	return 0;606}607 608static int tsl2591_set_als_persist_cycle(struct tsl2591_chip *chip,609					 u8 als_persist)610{611	struct i2c_client *client = chip->client;612	int ret;613 614	ret = i2c_smbus_write_byte_data(client,615					TSL2591_CMD_NOP | TSL2591_PERSIST,616					als_persist);617	if (ret)618		dev_err(&client->dev, "Failed to set als persist cycle\n");619 620	chip->als_settings.als_persist = als_persist;621 622	return ret;623}624 625static int tsl2591_set_power_state(struct tsl2591_chip *chip, u8 state)626{627	struct i2c_client *client = chip->client;628	int ret;629 630	ret = i2c_smbus_write_byte_data(client,631					TSL2591_CMD_NOP | TSL2591_ENABLE,632					state);633	if (ret)634		dev_err(&client->dev,635			"Failed to set the power state to %#04x\n", state);636 637	return ret;638}639 640static ssize_t tsl2591_in_illuminance_period_available_show(struct device *dev,641							    struct device_attribute *attr,642							    char *buf)643{644	struct iio_dev *indio_dev = dev_to_iio_dev(dev);645	struct tsl2591_chip *chip = iio_priv(indio_dev);646 647	return sysfs_emit(buf, "%s\n",648		       tsl2591_als_period_list[chip->als_settings.als_int_time]);649}650 651static IIO_DEVICE_ATTR_RO(tsl2591_in_illuminance_period_available, 0);652 653static struct attribute *tsl2591_event_attrs_ctrl[] = {654	&iio_dev_attr_tsl2591_in_illuminance_period_available.dev_attr.attr,655	NULL656};657 658static const struct attribute_group tsl2591_event_attribute_group = {659	.attrs = tsl2591_event_attrs_ctrl,660};661 662static const struct iio_event_spec tsl2591_events[] = {663	{664		.type = IIO_EV_TYPE_THRESH,665		.dir = IIO_EV_DIR_RISING,666		.mask_separate = BIT(IIO_EV_INFO_VALUE),667	}, {668		.type = IIO_EV_TYPE_THRESH,669		.dir = IIO_EV_DIR_FALLING,670		.mask_separate = BIT(IIO_EV_INFO_VALUE),671	}, {672		.type = IIO_EV_TYPE_THRESH,673		.dir = IIO_EV_DIR_EITHER,674		.mask_separate = BIT(IIO_EV_INFO_PERIOD) |675				BIT(IIO_EV_INFO_ENABLE),676	},677};678 679static const struct iio_chan_spec tsl2591_channels[] = {680	{681		.type = IIO_INTENSITY,682		.modified = 1,683		.channel2 = IIO_MOD_LIGHT_IR,684		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),685		.info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_INT_TIME) |686						     BIT(IIO_CHAN_INFO_CALIBSCALE),687		.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_INT_TIME) |688					   BIT(IIO_CHAN_INFO_CALIBSCALE)689	},690	{691		.type = IIO_INTENSITY,692		.modified = 1,693		.channel2 = IIO_MOD_LIGHT_BOTH,694		.event_spec = tsl2591_events,695		.num_event_specs = ARRAY_SIZE(tsl2591_events),696		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),697		.info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_INT_TIME) |698						     BIT(IIO_CHAN_INFO_CALIBSCALE),699		.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_INT_TIME) |700					   BIT(IIO_CHAN_INFO_CALIBSCALE)701	},702	{703		.type = IIO_LIGHT,704		.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),705		.info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_INT_TIME) |706						     BIT(IIO_CHAN_INFO_CALIBSCALE),707		.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_INT_TIME) |708					   BIT(IIO_CHAN_INFO_CALIBSCALE)709	},710};711 712static int tsl2591_read_raw(struct iio_dev *indio_dev,713			    struct iio_chan_spec const *chan,714			    int *val, int *val2, long mask)715{716	struct tsl2591_chip *chip = iio_priv(indio_dev);717	struct i2c_client *client = chip->client;718	int ret;719 720	pm_runtime_get_sync(&client->dev);721 722	mutex_lock(&chip->als_mutex);723 724	switch (mask) {725	case IIO_CHAN_INFO_RAW:726		if (chan->type != IIO_INTENSITY) {727			ret = -EINVAL;728			goto err_unlock;729		}730 731		ret = tsl2591_read_channel_data(indio_dev, chan, val, val2);732		if (ret < 0)733			goto err_unlock;734 735		ret = IIO_VAL_INT;736		break;737	case IIO_CHAN_INFO_PROCESSED:738		if (chan->type != IIO_LIGHT) {739			ret = -EINVAL;740			goto err_unlock;741		}742 743		ret = tsl2591_read_channel_data(indio_dev, chan, val, val2);744		if (ret < 0)745			break;746 747		ret = IIO_VAL_INT_PLUS_MICRO;748		break;749	case IIO_CHAN_INFO_INT_TIME:750		if (chan->type != IIO_INTENSITY) {751			ret = -EINVAL;752			goto err_unlock;753		}754 755		*val = TSL2591_FVAL_TO_SEC(chip->als_settings.als_int_time);756		ret = IIO_VAL_INT;757		break;758	case IIO_CHAN_INFO_CALIBSCALE:759		if (chan->type != IIO_INTENSITY) {760			ret = -EINVAL;761			goto err_unlock;762		}763 764		*val = tsl2591_gain_to_multiplier(chip->als_settings.als_gain);765		ret = IIO_VAL_INT;766		break;767	default:768		ret = -EINVAL;769		break;770	}771 772err_unlock:773	mutex_unlock(&chip->als_mutex);774 775	pm_runtime_mark_last_busy(&client->dev);776	pm_runtime_put_autosuspend(&client->dev);777 778	return ret;779}780 781static int tsl2591_write_raw(struct iio_dev *indio_dev,782			     struct iio_chan_spec const *chan,783			     int val, int val2, long mask)784{785	struct tsl2591_chip *chip = iio_priv(indio_dev);786	int int_time;787	int gain;788	int ret;789 790	mutex_lock(&chip->als_mutex);791 792	switch (mask) {793	case IIO_CHAN_INFO_INT_TIME:794		int_time = tsl2591_als_time_to_fval(val);795		if (int_time < 0) {796			ret = int_time;797			goto err_unlock;798		}799		ret = tsl2591_compatible_int_time(chip, int_time);800		if (ret < 0)801			goto err_unlock;802 803		chip->als_settings.als_int_time = int_time;804		break;805	case IIO_CHAN_INFO_CALIBSCALE:806		gain = tsl2591_multiplier_to_gain(val);807		if (gain < 0) {808			ret = gain;809			goto err_unlock;810		}811		ret = tsl2591_compatible_gain(chip, gain);812		if (ret < 0)813			goto err_unlock;814 815		chip->als_settings.als_gain = gain;816		break;817	default:818		ret = -EINVAL;819		goto err_unlock;820	}821 822	ret = tsl2591_set_als_gain_int_time(chip);823 824err_unlock:825	mutex_unlock(&chip->als_mutex);826	return ret;827}828 829static int tsl2591_read_available(struct iio_dev *indio_dev,830				  struct iio_chan_spec const *chan,831				  const int **vals, int *type, int *length,832				  long mask)833{834	switch (mask) {835	case IIO_CHAN_INFO_INT_TIME:836		*length = ARRAY_SIZE(tsl2591_int_time_available);837		*vals = tsl2591_int_time_available;838		*type = IIO_VAL_INT;839		return IIO_AVAIL_LIST;840 841	case IIO_CHAN_INFO_CALIBSCALE:842		*length = ARRAY_SIZE(tsl2591_calibscale_available);843		*vals = tsl2591_calibscale_available;844		*type = IIO_VAL_INT;845		return IIO_AVAIL_LIST;846	default:847		return -EINVAL;848	}849}850 851static int tsl2591_read_event_value(struct iio_dev *indio_dev,852				    const struct iio_chan_spec *chan,853				    enum iio_event_type type,854				    enum iio_event_direction dir,855				    enum iio_event_info info, int *val,856				    int *val2)857{858	struct tsl2591_chip *chip = iio_priv(indio_dev);859	struct i2c_client *client = chip->client;860	int als_persist, int_time, period;861	int ret;862 863	mutex_lock(&chip->als_mutex);864 865	switch (info) {866	case IIO_EV_INFO_VALUE:867		switch (dir) {868		case IIO_EV_DIR_RISING:869			*val = chip->als_settings.als_upper_thresh;870			break;871		case IIO_EV_DIR_FALLING:872			*val = chip->als_settings.als_lower_thresh;873			break;874		default:875			ret = -EINVAL;876			goto err_unlock;877		}878		ret = IIO_VAL_INT;879		break;880	case IIO_EV_INFO_PERIOD:881		ret = i2c_smbus_read_byte_data(client,882					       TSL2591_CMD_NOP | TSL2591_PERSIST);883		if (ret <= 0 || ret > TSL2591_PRST_ALS_INT_CYCLE_MAX)884			goto err_unlock;885 886		als_persist = tsl2591_persist_cycle_to_lit(ret);887		int_time = TSL2591_FVAL_TO_MSEC(chip->als_settings.als_int_time);888		period = als_persist * (int_time * MSEC_PER_SEC);889 890		*val = period / USEC_PER_SEC;891		*val2 = period % USEC_PER_SEC;892 893		ret = IIO_VAL_INT_PLUS_MICRO;894		break;895	default:896		ret = -EINVAL;897		break;898	}899 900err_unlock:901	mutex_unlock(&chip->als_mutex);902	return ret;903}904 905static int tsl2591_write_event_value(struct iio_dev *indio_dev,906				     const struct iio_chan_spec *chan,907				     enum iio_event_type type,908				     enum iio_event_direction dir,909				     enum iio_event_info info, int val,910				     int val2)911{912	struct tsl2591_chip *chip = iio_priv(indio_dev);913	int period, int_time, als_persist;914	int ret;915 916	if (val < 0 || val2 < 0)917		return -EINVAL;918 919	mutex_lock(&chip->als_mutex);920 921	switch (info) {922	case IIO_EV_INFO_VALUE:923		if (val > TSL2591_ALS_MAX_VALUE) {924			ret = -EINVAL;925			goto err_unlock;926		}927 928		switch (dir) {929		case IIO_EV_DIR_RISING:930			ret = tsl2591_set_als_upper_threshold(chip, val);931			if (ret < 0)932				goto err_unlock;933			break;934		case IIO_EV_DIR_FALLING:935			ret = tsl2591_set_als_lower_threshold(chip, val);936			if (ret < 0)937				goto err_unlock;938			break;939		default:940			ret = -EINVAL;941			goto err_unlock;942		}943		break;944	case IIO_EV_INFO_PERIOD:945		int_time = TSL2591_FVAL_TO_MSEC(chip->als_settings.als_int_time);946 947		period = ((val * MSEC_PER_SEC) +948			 (val2 / MSEC_PER_SEC)) / int_time;949 950		als_persist = tsl2591_persist_lit_to_cycle(period);951		if (als_persist < 0) {952			ret = -EINVAL;953			goto err_unlock;954		}955 956		ret = tsl2591_compatible_als_persist_cycle(chip, als_persist);957		if (ret < 0)958			goto err_unlock;959 960		ret = tsl2591_set_als_persist_cycle(chip, als_persist);961		if (ret < 0)962			goto err_unlock;963		break;964	default:965		ret = -EINVAL;966		break;967	}968 969err_unlock:970	mutex_unlock(&chip->als_mutex);971	return ret;972}973 974static int tsl2591_read_event_config(struct iio_dev *indio_dev,975				     const struct iio_chan_spec *chan,976				     enum iio_event_type type,977				     enum iio_event_direction dir)978{979	struct tsl2591_chip *chip = iio_priv(indio_dev);980 981	return chip->events_enabled;982}983 984static int tsl2591_write_event_config(struct iio_dev *indio_dev,985				      const struct iio_chan_spec *chan,986				      enum iio_event_type type,987				      enum iio_event_direction dir,988				      int state)989{990	struct tsl2591_chip *chip = iio_priv(indio_dev);991	struct i2c_client *client = chip->client;992 993	if (state && !chip->events_enabled) {994		chip->events_enabled = true;995		pm_runtime_get_sync(&client->dev);996	} else if (!state && chip->events_enabled) {997		chip->events_enabled = false;998		pm_runtime_mark_last_busy(&client->dev);999		pm_runtime_put_autosuspend(&client->dev);1000	}1001 1002	return 0;1003}1004 1005static const struct iio_info tsl2591_info = {1006	.event_attrs = &tsl2591_event_attribute_group,1007	.read_raw = tsl2591_read_raw,1008	.write_raw = tsl2591_write_raw,1009	.read_avail = tsl2591_read_available,1010	.read_event_value = tsl2591_read_event_value,1011	.write_event_value = tsl2591_write_event_value,1012	.read_event_config = tsl2591_read_event_config,1013	.write_event_config = tsl2591_write_event_config,1014};1015 1016static const struct iio_info tsl2591_info_no_irq = {1017	.read_raw = tsl2591_read_raw,1018	.write_raw = tsl2591_write_raw,1019	.read_avail = tsl2591_read_available,1020};1021 1022static int tsl2591_suspend(struct device *dev)1023{1024	struct iio_dev *indio_dev = dev_get_drvdata(dev);1025	struct tsl2591_chip *chip = iio_priv(indio_dev);1026	int ret;1027 1028	mutex_lock(&chip->als_mutex);1029	ret = tsl2591_set_power_state(chip, TSL2591_PWR_OFF);1030	mutex_unlock(&chip->als_mutex);1031 1032	return ret;1033}1034 1035static int tsl2591_resume(struct device *dev)1036{1037	int power_state = TSL2591_PWR_ON | TSL2591_ENABLE_ALS;1038	struct iio_dev *indio_dev = dev_get_drvdata(dev);1039	struct tsl2591_chip *chip = iio_priv(indio_dev);1040	int ret;1041 1042	if (chip->events_enabled)1043		power_state |= TSL2591_ENABLE_ALS_INT;1044 1045	mutex_lock(&chip->als_mutex);1046	ret = tsl2591_set_power_state(chip, power_state);1047	mutex_unlock(&chip->als_mutex);1048 1049	return ret;1050}1051 1052static DEFINE_RUNTIME_DEV_PM_OPS(tsl2591_pm_ops, tsl2591_suspend,1053				 tsl2591_resume, NULL);1054 1055static irqreturn_t tsl2591_event_handler(int irq, void *private)1056{1057	struct iio_dev *dev_info = private;1058	struct tsl2591_chip *chip = iio_priv(dev_info);1059	struct i2c_client *client = chip->client;1060 1061	if (!chip->events_enabled)1062		return IRQ_NONE;1063 1064	iio_push_event(dev_info,1065		       IIO_UNMOD_EVENT_CODE(IIO_LIGHT, 0,1066					    IIO_EV_TYPE_THRESH,1067					    IIO_EV_DIR_EITHER),1068					    iio_get_time_ns(dev_info));1069 1070	/* Clear ALS irq */1071	i2c_smbus_write_byte(client, TSL2591_CMD_SF_CALS_NPI);1072 1073	return IRQ_HANDLED;1074}1075 1076static int tsl2591_load_defaults(struct tsl2591_chip *chip)1077{1078	int ret;1079 1080	chip->als_settings.als_int_time = TSL2591_DEFAULT_ALS_INT_TIME;1081	chip->als_settings.als_gain = TSL2591_DEFAULT_ALS_GAIN;1082	chip->als_settings.als_lower_thresh = TSL2591_DEFAULT_ALS_LOWER_THRESH;1083	chip->als_settings.als_upper_thresh = TSL2591_DEFAULT_ALS_UPPER_THRESH;1084 1085	ret = tsl2591_set_als_gain_int_time(chip);1086	if (ret < 0)1087		return ret;1088 1089	ret = tsl2591_set_als_persist_cycle(chip, TSL2591_DEFAULT_ALS_PERSIST);1090	if (ret < 0)1091		return ret;1092 1093	ret = tsl2591_set_als_lower_threshold(chip, TSL2591_DEFAULT_ALS_LOWER_THRESH);1094	if (ret < 0)1095		return ret;1096 1097	ret = tsl2591_set_als_upper_threshold(chip, TSL2591_DEFAULT_ALS_UPPER_THRESH);1098	if (ret < 0)1099		return ret;1100 1101	return 0;1102}1103 1104static void tsl2591_chip_off(void *data)1105{1106	struct iio_dev *indio_dev = data;1107	struct tsl2591_chip *chip = iio_priv(indio_dev);1108	struct i2c_client *client = chip->client;1109 1110	pm_runtime_disable(&client->dev);1111	pm_runtime_set_suspended(&client->dev);1112	pm_runtime_put_noidle(&client->dev);1113 1114	tsl2591_set_power_state(chip, TSL2591_PWR_OFF);1115}1116 1117static int tsl2591_probe(struct i2c_client *client)1118{1119	struct tsl2591_chip *chip;1120	struct iio_dev *indio_dev;1121	int ret;1122 1123	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {1124		dev_err(&client->dev,1125			"I2C smbus byte data functionality is not supported\n");1126		return -EOPNOTSUPP;1127	}1128 1129	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*chip));1130	if (!indio_dev)1131		return -ENOMEM;1132 1133	chip = iio_priv(indio_dev);1134	chip->client = client;1135	i2c_set_clientdata(client, indio_dev);1136 1137	if (client->irq) {1138		ret = devm_request_threaded_irq(&client->dev, client->irq,1139						NULL, tsl2591_event_handler,1140						IRQF_TRIGGER_FALLING | IRQF_ONESHOT,1141						"tsl2591_irq", indio_dev);1142		if (ret) {1143			dev_err_probe(&client->dev, ret, "IRQ request error\n");1144			return -EINVAL;1145		}1146		indio_dev->info = &tsl2591_info;1147	} else {1148		indio_dev->info = &tsl2591_info_no_irq;1149	}1150 1151	mutex_init(&chip->als_mutex);1152 1153	ret = i2c_smbus_read_byte_data(client,1154				       TSL2591_CMD_NOP | TSL2591_DEVICE_ID);1155	if (ret < 0) {1156		dev_err(&client->dev,1157			"Failed to read the device ID register\n");1158		return ret;1159	}1160	ret = FIELD_GET(TSL2591_DEVICE_ID_MASK, ret);1161	if (ret != TSL2591_DEVICE_ID_VAL) {1162		dev_err(&client->dev, "Device ID: %#04x unknown\n", ret);1163		return -EINVAL;1164	}1165 1166	indio_dev->channels = tsl2591_channels;1167	indio_dev->num_channels = ARRAY_SIZE(tsl2591_channels);1168	indio_dev->modes = INDIO_DIRECT_MODE;1169	indio_dev->name = chip->client->name;1170	chip->events_enabled = false;1171 1172	pm_runtime_enable(&client->dev);1173	pm_runtime_set_autosuspend_delay(&client->dev,1174					 TSL2591_POWER_OFF_DELAY_MS);1175	pm_runtime_use_autosuspend(&client->dev);1176 1177	/*1178	 * Add chip off to automatically managed path and disable runtime1179	 * power management. This ensures that the chip power management1180	 * is handled correctly on driver remove. tsl2591_chip_off() must be1181	 * added to the managed path after pm runtime is enabled and before1182	 * any error exit paths are met to ensure we're not left in a state1183	 * of pm runtime not being disabled properly.1184	 */1185	ret = devm_add_action_or_reset(&client->dev, tsl2591_chip_off,1186				       indio_dev);1187	if (ret < 0)1188		return -EINVAL;1189 1190	ret = tsl2591_load_defaults(chip);1191	if (ret < 0) {1192		dev_err(&client->dev, "Failed to load sensor defaults\n");1193		return -EINVAL;1194	}1195 1196	ret = i2c_smbus_write_byte(client, TSL2591_CMD_SF_CALS_NPI);1197	if (ret < 0) {1198		dev_err(&client->dev, "Failed to clear als irq\n");1199		return -EINVAL;1200	}1201 1202	return devm_iio_device_register(&client->dev, indio_dev);1203}1204 1205static const struct of_device_id tsl2591_of_match[] = {1206	{ .compatible = "amstaos,tsl2591"},1207	{}1208};1209MODULE_DEVICE_TABLE(of, tsl2591_of_match);1210 1211static struct i2c_driver tsl2591_driver = {1212	.driver = {1213		.name = "tsl2591",1214		.pm = pm_ptr(&tsl2591_pm_ops),1215		.of_match_table = tsl2591_of_match,1216	},1217	.probe = tsl2591_probe1218};1219module_i2c_driver(tsl2591_driver);1220 1221MODULE_AUTHOR("Joe Sandom <joe.g.sandom@gmail.com>");1222MODULE_DESCRIPTION("TAOS tsl2591 ambient light sensor driver");1223MODULE_LICENSE("GPL");1224