136edc939SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2b9d453a5SGwendal Grignou /*
3be9e6229STiberiu Breana * Sensortek STK3310/STK3311 Ambient Light and Proximity Sensor
4be9e6229STiberiu Breana *
5be9e6229STiberiu Breana * Copyright (c) 2015, Intel Corporation.
6be9e6229STiberiu Breana *
7be9e6229STiberiu Breana * IIO driver for STK3310/STK3311. 7-bit I2C address: 0x48.
8be9e6229STiberiu Breana */
9be9e6229STiberiu Breana
10be9e6229STiberiu Breana #include <linux/acpi.h>
11be9e6229STiberiu Breana #include <linux/i2c.h>
123dd477acSTiberiu Breana #include <linux/interrupt.h>
13be9e6229STiberiu Breana #include <linux/kernel.h>
14be9e6229STiberiu Breana #include <linux/module.h>
15be9e6229STiberiu Breana #include <linux/regmap.h>
163dd477acSTiberiu Breana #include <linux/iio/events.h>
17be9e6229STiberiu Breana #include <linux/iio/iio.h>
18be9e6229STiberiu Breana #include <linux/iio/sysfs.h>
19be9e6229STiberiu Breana
20be9e6229STiberiu Breana #define STK3310_REG_STATE 0x00
21be9e6229STiberiu Breana #define STK3310_REG_PSCTRL 0x01
22be9e6229STiberiu Breana #define STK3310_REG_ALSCTRL 0x02
233dd477acSTiberiu Breana #define STK3310_REG_INT 0x04
243dd477acSTiberiu Breana #define STK3310_REG_THDH_PS 0x06
253dd477acSTiberiu Breana #define STK3310_REG_THDL_PS 0x08
263dd477acSTiberiu Breana #define STK3310_REG_FLAG 0x10
27be9e6229STiberiu Breana #define STK3310_REG_PS_DATA_MSB 0x11
28be9e6229STiberiu Breana #define STK3310_REG_PS_DATA_LSB 0x12
29be9e6229STiberiu Breana #define STK3310_REG_ALS_DATA_MSB 0x13
30be9e6229STiberiu Breana #define STK3310_REG_ALS_DATA_LSB 0x14
31be9e6229STiberiu Breana #define STK3310_REG_ID 0x3E
32be9e6229STiberiu Breana #define STK3310_MAX_REG 0x80
33be9e6229STiberiu Breana
34952c3aa3SHartmut Knaack #define STK3310_STATE_EN_PS BIT(0)
35952c3aa3SHartmut Knaack #define STK3310_STATE_EN_ALS BIT(1)
36be9e6229STiberiu Breana #define STK3310_STATE_STANDBY 0x00
37be9e6229STiberiu Breana
38be9e6229STiberiu Breana #define STK3310_CHIP_ID_VAL 0x13
39be9e6229STiberiu Breana #define STK3311_CHIP_ID_VAL 0x1D
405ef8f84aSIcenowy Zheng #define STK3311X_CHIP_ID_VAL 0x12
41677f1681SMartijn Braam #define STK3335_CHIP_ID_VAL 0x51
423dd477acSTiberiu Breana #define STK3310_PSINT_EN 0x01
43be9e6229STiberiu Breana #define STK3310_PS_MAX_VAL 0xFFFF
44be9e6229STiberiu Breana
45be9e6229STiberiu Breana #define STK3310_DRIVER_NAME "stk3310"
46be9e6229STiberiu Breana #define STK3310_REGMAP_NAME "stk3310_regmap"
473dd477acSTiberiu Breana #define STK3310_EVENT "stk3310_event"
48be9e6229STiberiu Breana
49be9e6229STiberiu Breana #define STK3310_SCALE_AVAILABLE "6.4 1.6 0.4 0.1"
50be9e6229STiberiu Breana
51be9e6229STiberiu Breana #define STK3310_IT_AVAILABLE \
52be9e6229STiberiu Breana "0.000185 0.000370 0.000741 0.001480 0.002960 0.005920 0.011840 " \
53be9e6229STiberiu Breana "0.023680 0.047360 0.094720 0.189440 0.378880 0.757760 1.515520 " \
54be9e6229STiberiu Breana "3.031040 6.062080"
55be9e6229STiberiu Breana
56be9e6229STiberiu Breana #define STK3310_REGFIELD(name) \
57be9e6229STiberiu Breana do { \
58be9e6229STiberiu Breana data->reg_##name = \
59be9e6229STiberiu Breana devm_regmap_field_alloc(&client->dev, regmap, \
60be9e6229STiberiu Breana stk3310_reg_field_##name); \
61be9e6229STiberiu Breana if (IS_ERR(data->reg_##name)) { \
62be9e6229STiberiu Breana dev_err(&client->dev, "reg field alloc failed.\n"); \
63be9e6229STiberiu Breana return PTR_ERR(data->reg_##name); \
64be9e6229STiberiu Breana } \
65be9e6229STiberiu Breana } while (0)
66be9e6229STiberiu Breana
67be9e6229STiberiu Breana static const struct reg_field stk3310_reg_field_state =
68be9e6229STiberiu Breana REG_FIELD(STK3310_REG_STATE, 0, 2);
69be9e6229STiberiu Breana static const struct reg_field stk3310_reg_field_als_gain =
70be9e6229STiberiu Breana REG_FIELD(STK3310_REG_ALSCTRL, 4, 5);
71be9e6229STiberiu Breana static const struct reg_field stk3310_reg_field_ps_gain =
72be9e6229STiberiu Breana REG_FIELD(STK3310_REG_PSCTRL, 4, 5);
73be9e6229STiberiu Breana static const struct reg_field stk3310_reg_field_als_it =
74be9e6229STiberiu Breana REG_FIELD(STK3310_REG_ALSCTRL, 0, 3);
75be9e6229STiberiu Breana static const struct reg_field stk3310_reg_field_ps_it =
76be9e6229STiberiu Breana REG_FIELD(STK3310_REG_PSCTRL, 0, 3);
773dd477acSTiberiu Breana static const struct reg_field stk3310_reg_field_int_ps =
783dd477acSTiberiu Breana REG_FIELD(STK3310_REG_INT, 0, 2);
793dd477acSTiberiu Breana static const struct reg_field stk3310_reg_field_flag_psint =
803dd477acSTiberiu Breana REG_FIELD(STK3310_REG_FLAG, 4, 4);
813dd477acSTiberiu Breana static const struct reg_field stk3310_reg_field_flag_nf =
823dd477acSTiberiu Breana REG_FIELD(STK3310_REG_FLAG, 0, 0);
830f16fc8bSTiberiu Breana
840f16fc8bSTiberiu Breana /* Estimate maximum proximity values with regard to measurement scale. */
85be9e6229STiberiu Breana static const int stk3310_ps_max[4] = {
860f16fc8bSTiberiu Breana STK3310_PS_MAX_VAL / 640,
870f16fc8bSTiberiu Breana STK3310_PS_MAX_VAL / 160,
880f16fc8bSTiberiu Breana STK3310_PS_MAX_VAL / 40,
890f16fc8bSTiberiu Breana STK3310_PS_MAX_VAL / 10
90be9e6229STiberiu Breana };
91be9e6229STiberiu Breana
92be9e6229STiberiu Breana static const int stk3310_scale_table[][2] = {
93be9e6229STiberiu Breana {6, 400000}, {1, 600000}, {0, 400000}, {0, 100000}
94be9e6229STiberiu Breana };
95be9e6229STiberiu Breana
96be9e6229STiberiu Breana /* Integration time in seconds, microseconds */
97be9e6229STiberiu Breana static const int stk3310_it_table[][2] = {
98be9e6229STiberiu Breana {0, 185}, {0, 370}, {0, 741}, {0, 1480},
99be9e6229STiberiu Breana {0, 2960}, {0, 5920}, {0, 11840}, {0, 23680},
100be9e6229STiberiu Breana {0, 47360}, {0, 94720}, {0, 189440}, {0, 378880},
101be9e6229STiberiu Breana {0, 757760}, {1, 515520}, {3, 31040}, {6, 62080},
102be9e6229STiberiu Breana };
103be9e6229STiberiu Breana
104be9e6229STiberiu Breana struct stk3310_data {
105be9e6229STiberiu Breana struct i2c_client *client;
106be9e6229STiberiu Breana struct mutex lock;
107be9e6229STiberiu Breana bool als_enabled;
108be9e6229STiberiu Breana bool ps_enabled;
109d6ecb015SArnaud Ferraris uint32_t ps_near_level;
1103dd477acSTiberiu Breana u64 timestamp;
111be9e6229STiberiu Breana struct regmap *regmap;
112be9e6229STiberiu Breana struct regmap_field *reg_state;
113be9e6229STiberiu Breana struct regmap_field *reg_als_gain;
114be9e6229STiberiu Breana struct regmap_field *reg_ps_gain;
115be9e6229STiberiu Breana struct regmap_field *reg_als_it;
116be9e6229STiberiu Breana struct regmap_field *reg_ps_it;
1173dd477acSTiberiu Breana struct regmap_field *reg_int_ps;
1183dd477acSTiberiu Breana struct regmap_field *reg_flag_psint;
1193dd477acSTiberiu Breana struct regmap_field *reg_flag_nf;
1203dd477acSTiberiu Breana };
1213dd477acSTiberiu Breana
1223dd477acSTiberiu Breana static const struct iio_event_spec stk3310_events[] = {
1233dd477acSTiberiu Breana /* Proximity event */
1243dd477acSTiberiu Breana {
1253dd477acSTiberiu Breana .type = IIO_EV_TYPE_THRESH,
1260f16fc8bSTiberiu Breana .dir = IIO_EV_DIR_RISING,
1273dd477acSTiberiu Breana .mask_separate = BIT(IIO_EV_INFO_VALUE) |
1283dd477acSTiberiu Breana BIT(IIO_EV_INFO_ENABLE),
1293dd477acSTiberiu Breana },
1303dd477acSTiberiu Breana /* Out-of-proximity event */
1313dd477acSTiberiu Breana {
1323dd477acSTiberiu Breana .type = IIO_EV_TYPE_THRESH,
1330f16fc8bSTiberiu Breana .dir = IIO_EV_DIR_FALLING,
1343dd477acSTiberiu Breana .mask_separate = BIT(IIO_EV_INFO_VALUE) |
1353dd477acSTiberiu Breana BIT(IIO_EV_INFO_ENABLE),
1363dd477acSTiberiu Breana },
137be9e6229STiberiu Breana };
138be9e6229STiberiu Breana
stk3310_read_near_level(struct iio_dev * indio_dev,uintptr_t priv,const struct iio_chan_spec * chan,char * buf)139d6ecb015SArnaud Ferraris static ssize_t stk3310_read_near_level(struct iio_dev *indio_dev,
140d6ecb015SArnaud Ferraris uintptr_t priv,
141d6ecb015SArnaud Ferraris const struct iio_chan_spec *chan,
142d6ecb015SArnaud Ferraris char *buf)
143d6ecb015SArnaud Ferraris {
144d6ecb015SArnaud Ferraris struct stk3310_data *data = iio_priv(indio_dev);
145d6ecb015SArnaud Ferraris
146d6ecb015SArnaud Ferraris return sprintf(buf, "%u\n", data->ps_near_level);
147d6ecb015SArnaud Ferraris }
148d6ecb015SArnaud Ferraris
149d6ecb015SArnaud Ferraris static const struct iio_chan_spec_ext_info stk3310_ext_info[] = {
150d6ecb015SArnaud Ferraris {
151d6ecb015SArnaud Ferraris .name = "nearlevel",
152d6ecb015SArnaud Ferraris .shared = IIO_SEPARATE,
153d6ecb015SArnaud Ferraris .read = stk3310_read_near_level,
154d6ecb015SArnaud Ferraris },
155d6ecb015SArnaud Ferraris { /* sentinel */ }
156d6ecb015SArnaud Ferraris };
157d6ecb015SArnaud Ferraris
158be9e6229STiberiu Breana static const struct iio_chan_spec stk3310_channels[] = {
159be9e6229STiberiu Breana {
160be9e6229STiberiu Breana .type = IIO_LIGHT,
161be9e6229STiberiu Breana .info_mask_separate =
162be9e6229STiberiu Breana BIT(IIO_CHAN_INFO_RAW) |
163be9e6229STiberiu Breana BIT(IIO_CHAN_INFO_SCALE) |
164be9e6229STiberiu Breana BIT(IIO_CHAN_INFO_INT_TIME),
165be9e6229STiberiu Breana },
166be9e6229STiberiu Breana {
167be9e6229STiberiu Breana .type = IIO_PROXIMITY,
168be9e6229STiberiu Breana .info_mask_separate =
169be9e6229STiberiu Breana BIT(IIO_CHAN_INFO_RAW) |
170be9e6229STiberiu Breana BIT(IIO_CHAN_INFO_SCALE) |
171be9e6229STiberiu Breana BIT(IIO_CHAN_INFO_INT_TIME),
1723dd477acSTiberiu Breana .event_spec = stk3310_events,
1733dd477acSTiberiu Breana .num_event_specs = ARRAY_SIZE(stk3310_events),
174d6ecb015SArnaud Ferraris .ext_info = stk3310_ext_info,
175be9e6229STiberiu Breana }
176be9e6229STiberiu Breana };
177be9e6229STiberiu Breana
178be9e6229STiberiu Breana static IIO_CONST_ATTR(in_illuminance_scale_available, STK3310_SCALE_AVAILABLE);
179be9e6229STiberiu Breana
180be9e6229STiberiu Breana static IIO_CONST_ATTR(in_proximity_scale_available, STK3310_SCALE_AVAILABLE);
181be9e6229STiberiu Breana
182be9e6229STiberiu Breana static IIO_CONST_ATTR(in_illuminance_integration_time_available,
183be9e6229STiberiu Breana STK3310_IT_AVAILABLE);
184be9e6229STiberiu Breana
185be9e6229STiberiu Breana static IIO_CONST_ATTR(in_proximity_integration_time_available,
186be9e6229STiberiu Breana STK3310_IT_AVAILABLE);
187be9e6229STiberiu Breana
188be9e6229STiberiu Breana static struct attribute *stk3310_attributes[] = {
189be9e6229STiberiu Breana &iio_const_attr_in_illuminance_scale_available.dev_attr.attr,
190be9e6229STiberiu Breana &iio_const_attr_in_proximity_scale_available.dev_attr.attr,
191be9e6229STiberiu Breana &iio_const_attr_in_illuminance_integration_time_available.dev_attr.attr,
192be9e6229STiberiu Breana &iio_const_attr_in_proximity_integration_time_available.dev_attr.attr,
193be9e6229STiberiu Breana NULL,
194be9e6229STiberiu Breana };
195be9e6229STiberiu Breana
196be9e6229STiberiu Breana static const struct attribute_group stk3310_attribute_group = {
197be9e6229STiberiu Breana .attrs = stk3310_attributes
198be9e6229STiberiu Breana };
199be9e6229STiberiu Breana
stk3310_get_index(const int table[][2],int table_size,int val,int val2)200be9e6229STiberiu Breana static int stk3310_get_index(const int table[][2], int table_size,
201be9e6229STiberiu Breana int val, int val2)
202be9e6229STiberiu Breana {
203be9e6229STiberiu Breana int i;
204be9e6229STiberiu Breana
205be9e6229STiberiu Breana for (i = 0; i < table_size; i++) {
206be9e6229STiberiu Breana if (val == table[i][0] && val2 == table[i][1])
207be9e6229STiberiu Breana return i;
208be9e6229STiberiu Breana }
209be9e6229STiberiu Breana
210be9e6229STiberiu Breana return -EINVAL;
211be9e6229STiberiu Breana }
212be9e6229STiberiu Breana
stk3310_read_event(struct iio_dev * indio_dev,const struct iio_chan_spec * chan,enum iio_event_type type,enum iio_event_direction dir,enum iio_event_info info,int * val,int * val2)2133dd477acSTiberiu Breana static int stk3310_read_event(struct iio_dev *indio_dev,
2143dd477acSTiberiu Breana const struct iio_chan_spec *chan,
2153dd477acSTiberiu Breana enum iio_event_type type,
2163dd477acSTiberiu Breana enum iio_event_direction dir,
2173dd477acSTiberiu Breana enum iio_event_info info,
2183dd477acSTiberiu Breana int *val, int *val2)
2193dd477acSTiberiu Breana {
2203dd477acSTiberiu Breana u8 reg;
221423ad0c4SHartmut Knaack __be16 buf;
2223dd477acSTiberiu Breana int ret;
2233dd477acSTiberiu Breana struct stk3310_data *data = iio_priv(indio_dev);
2243dd477acSTiberiu Breana
2253dd477acSTiberiu Breana if (info != IIO_EV_INFO_VALUE)
2263dd477acSTiberiu Breana return -EINVAL;
2273dd477acSTiberiu Breana
2280f16fc8bSTiberiu Breana /* Only proximity interrupts are implemented at the moment. */
2293dd477acSTiberiu Breana if (dir == IIO_EV_DIR_RISING)
2303dd477acSTiberiu Breana reg = STK3310_REG_THDH_PS;
2310f16fc8bSTiberiu Breana else if (dir == IIO_EV_DIR_FALLING)
2320f16fc8bSTiberiu Breana reg = STK3310_REG_THDL_PS;
2333dd477acSTiberiu Breana else
2343dd477acSTiberiu Breana return -EINVAL;
2353dd477acSTiberiu Breana
2363dd477acSTiberiu Breana mutex_lock(&data->lock);
2373dd477acSTiberiu Breana ret = regmap_bulk_read(data->regmap, reg, &buf, 2);
2383dd477acSTiberiu Breana mutex_unlock(&data->lock);
2393dd477acSTiberiu Breana if (ret < 0) {
2403dd477acSTiberiu Breana dev_err(&data->client->dev, "register read failed\n");
2413dd477acSTiberiu Breana return ret;
2423dd477acSTiberiu Breana }
243423ad0c4SHartmut Knaack *val = be16_to_cpu(buf);
2443dd477acSTiberiu Breana
2453dd477acSTiberiu Breana return IIO_VAL_INT;
2463dd477acSTiberiu Breana }
2473dd477acSTiberiu Breana
stk3310_write_event(struct iio_dev * indio_dev,const struct iio_chan_spec * chan,enum iio_event_type type,enum iio_event_direction dir,enum iio_event_info info,int val,int val2)2483dd477acSTiberiu Breana static int stk3310_write_event(struct iio_dev *indio_dev,
2493dd477acSTiberiu Breana const struct iio_chan_spec *chan,
2503dd477acSTiberiu Breana enum iio_event_type type,
2513dd477acSTiberiu Breana enum iio_event_direction dir,
2523dd477acSTiberiu Breana enum iio_event_info info,
2533dd477acSTiberiu Breana int val, int val2)
2543dd477acSTiberiu Breana {
2553dd477acSTiberiu Breana u8 reg;
256423ad0c4SHartmut Knaack __be16 buf;
2573dd477acSTiberiu Breana int ret;
2583dd477acSTiberiu Breana unsigned int index;
2593dd477acSTiberiu Breana struct stk3310_data *data = iio_priv(indio_dev);
2603dd477acSTiberiu Breana struct i2c_client *client = data->client;
2613dd477acSTiberiu Breana
2627c7a9eeaSHartmut Knaack ret = regmap_field_read(data->reg_ps_gain, &index);
2637c7a9eeaSHartmut Knaack if (ret < 0)
2647c7a9eeaSHartmut Knaack return ret;
2657c7a9eeaSHartmut Knaack
2667c7a9eeaSHartmut Knaack if (val < 0 || val > stk3310_ps_max[index])
2673dd477acSTiberiu Breana return -EINVAL;
2683dd477acSTiberiu Breana
2693dd477acSTiberiu Breana if (dir == IIO_EV_DIR_RISING)
2703dd477acSTiberiu Breana reg = STK3310_REG_THDH_PS;
2710f16fc8bSTiberiu Breana else if (dir == IIO_EV_DIR_FALLING)
2720f16fc8bSTiberiu Breana reg = STK3310_REG_THDL_PS;
2733dd477acSTiberiu Breana else
2743dd477acSTiberiu Breana return -EINVAL;
2753dd477acSTiberiu Breana
276423ad0c4SHartmut Knaack buf = cpu_to_be16(val);
2773dd477acSTiberiu Breana ret = regmap_bulk_write(data->regmap, reg, &buf, 2);
2783dd477acSTiberiu Breana if (ret < 0)
2793dd477acSTiberiu Breana dev_err(&client->dev, "failed to set PS threshold!\n");
2803dd477acSTiberiu Breana
2813dd477acSTiberiu Breana return ret;
2823dd477acSTiberiu Breana }
2833dd477acSTiberiu Breana
stk3310_read_event_config(struct iio_dev * indio_dev,const struct iio_chan_spec * chan,enum iio_event_type type,enum iio_event_direction dir)2843dd477acSTiberiu Breana static int stk3310_read_event_config(struct iio_dev *indio_dev,
2853dd477acSTiberiu Breana const struct iio_chan_spec *chan,
2863dd477acSTiberiu Breana enum iio_event_type type,
2873dd477acSTiberiu Breana enum iio_event_direction dir)
2883dd477acSTiberiu Breana {
2893dd477acSTiberiu Breana unsigned int event_val;
2907c7a9eeaSHartmut Knaack int ret;
2913dd477acSTiberiu Breana struct stk3310_data *data = iio_priv(indio_dev);
2923dd477acSTiberiu Breana
2937c7a9eeaSHartmut Knaack ret = regmap_field_read(data->reg_int_ps, &event_val);
2947c7a9eeaSHartmut Knaack if (ret < 0)
2957c7a9eeaSHartmut Knaack return ret;
2963dd477acSTiberiu Breana
2973dd477acSTiberiu Breana return event_val;
2983dd477acSTiberiu Breana }
2993dd477acSTiberiu Breana
stk3310_write_event_config(struct iio_dev * indio_dev,const struct iio_chan_spec * chan,enum iio_event_type type,enum iio_event_direction dir,int state)3003dd477acSTiberiu Breana static int stk3310_write_event_config(struct iio_dev *indio_dev,
3013dd477acSTiberiu Breana const struct iio_chan_spec *chan,
3023dd477acSTiberiu Breana enum iio_event_type type,
3033dd477acSTiberiu Breana enum iio_event_direction dir,
3043dd477acSTiberiu Breana int state)
3053dd477acSTiberiu Breana {
3063dd477acSTiberiu Breana int ret;
3073dd477acSTiberiu Breana struct stk3310_data *data = iio_priv(indio_dev);
3083dd477acSTiberiu Breana struct i2c_client *client = data->client;
3093dd477acSTiberiu Breana
3103dd477acSTiberiu Breana if (state < 0 || state > 7)
3113dd477acSTiberiu Breana return -EINVAL;
3123dd477acSTiberiu Breana
3133dd477acSTiberiu Breana /* Set INT_PS value */
3143dd477acSTiberiu Breana mutex_lock(&data->lock);
3153dd477acSTiberiu Breana ret = regmap_field_write(data->reg_int_ps, state);
3163dd477acSTiberiu Breana if (ret < 0)
3173dd477acSTiberiu Breana dev_err(&client->dev, "failed to set interrupt mode\n");
3183dd477acSTiberiu Breana mutex_unlock(&data->lock);
3193dd477acSTiberiu Breana
3203dd477acSTiberiu Breana return ret;
3213dd477acSTiberiu Breana }
3223dd477acSTiberiu Breana
stk3310_read_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,int * val,int * val2,long mask)323be9e6229STiberiu Breana static int stk3310_read_raw(struct iio_dev *indio_dev,
324be9e6229STiberiu Breana struct iio_chan_spec const *chan,
325be9e6229STiberiu Breana int *val, int *val2, long mask)
326be9e6229STiberiu Breana {
327be9e6229STiberiu Breana u8 reg;
328423ad0c4SHartmut Knaack __be16 buf;
329be9e6229STiberiu Breana int ret;
330be9e6229STiberiu Breana unsigned int index;
331be9e6229STiberiu Breana struct stk3310_data *data = iio_priv(indio_dev);
332be9e6229STiberiu Breana struct i2c_client *client = data->client;
333be9e6229STiberiu Breana
3347c7a9eeaSHartmut Knaack if (chan->type != IIO_LIGHT && chan->type != IIO_PROXIMITY)
3357c7a9eeaSHartmut Knaack return -EINVAL;
3367c7a9eeaSHartmut Knaack
337be9e6229STiberiu Breana switch (mask) {
338be9e6229STiberiu Breana case IIO_CHAN_INFO_RAW:
339be9e6229STiberiu Breana if (chan->type == IIO_LIGHT)
340be9e6229STiberiu Breana reg = STK3310_REG_ALS_DATA_MSB;
341be9e6229STiberiu Breana else
3427c7a9eeaSHartmut Knaack reg = STK3310_REG_PS_DATA_MSB;
3437c7a9eeaSHartmut Knaack
344be9e6229STiberiu Breana mutex_lock(&data->lock);
345be9e6229STiberiu Breana ret = regmap_bulk_read(data->regmap, reg, &buf, 2);
346be9e6229STiberiu Breana if (ret < 0) {
347be9e6229STiberiu Breana dev_err(&client->dev, "register read failed\n");
348be9e6229STiberiu Breana mutex_unlock(&data->lock);
349be9e6229STiberiu Breana return ret;
350be9e6229STiberiu Breana }
351423ad0c4SHartmut Knaack *val = be16_to_cpu(buf);
352be9e6229STiberiu Breana mutex_unlock(&data->lock);
353be9e6229STiberiu Breana return IIO_VAL_INT;
354be9e6229STiberiu Breana case IIO_CHAN_INFO_INT_TIME:
355be9e6229STiberiu Breana if (chan->type == IIO_LIGHT)
3567c7a9eeaSHartmut Knaack ret = regmap_field_read(data->reg_als_it, &index);
357be9e6229STiberiu Breana else
3587c7a9eeaSHartmut Knaack ret = regmap_field_read(data->reg_ps_it, &index);
3597c7a9eeaSHartmut Knaack if (ret < 0)
3607c7a9eeaSHartmut Knaack return ret;
3617c7a9eeaSHartmut Knaack
362be9e6229STiberiu Breana *val = stk3310_it_table[index][0];
363be9e6229STiberiu Breana *val2 = stk3310_it_table[index][1];
364be9e6229STiberiu Breana return IIO_VAL_INT_PLUS_MICRO;
365be9e6229STiberiu Breana case IIO_CHAN_INFO_SCALE:
366be9e6229STiberiu Breana if (chan->type == IIO_LIGHT)
3677c7a9eeaSHartmut Knaack ret = regmap_field_read(data->reg_als_gain, &index);
368be9e6229STiberiu Breana else
3697c7a9eeaSHartmut Knaack ret = regmap_field_read(data->reg_ps_gain, &index);
3707c7a9eeaSHartmut Knaack if (ret < 0)
3717c7a9eeaSHartmut Knaack return ret;
3727c7a9eeaSHartmut Knaack
373be9e6229STiberiu Breana *val = stk3310_scale_table[index][0];
374be9e6229STiberiu Breana *val2 = stk3310_scale_table[index][1];
375be9e6229STiberiu Breana return IIO_VAL_INT_PLUS_MICRO;
376be9e6229STiberiu Breana }
377be9e6229STiberiu Breana
378be9e6229STiberiu Breana return -EINVAL;
379be9e6229STiberiu Breana }
380be9e6229STiberiu Breana
stk3310_write_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,int val,int val2,long mask)381be9e6229STiberiu Breana static int stk3310_write_raw(struct iio_dev *indio_dev,
382be9e6229STiberiu Breana struct iio_chan_spec const *chan,
383be9e6229STiberiu Breana int val, int val2, long mask)
384be9e6229STiberiu Breana {
385be9e6229STiberiu Breana int ret;
386ed6e75c7SDan Carpenter int index;
387be9e6229STiberiu Breana struct stk3310_data *data = iio_priv(indio_dev);
388be9e6229STiberiu Breana
3897c7a9eeaSHartmut Knaack if (chan->type != IIO_LIGHT && chan->type != IIO_PROXIMITY)
3907c7a9eeaSHartmut Knaack return -EINVAL;
3917c7a9eeaSHartmut Knaack
392be9e6229STiberiu Breana switch (mask) {
393be9e6229STiberiu Breana case IIO_CHAN_INFO_INT_TIME:
394be9e6229STiberiu Breana index = stk3310_get_index(stk3310_it_table,
395be9e6229STiberiu Breana ARRAY_SIZE(stk3310_it_table),
396be9e6229STiberiu Breana val, val2);
397be9e6229STiberiu Breana if (index < 0)
398be9e6229STiberiu Breana return -EINVAL;
399be9e6229STiberiu Breana mutex_lock(&data->lock);
400be9e6229STiberiu Breana if (chan->type == IIO_LIGHT)
401be9e6229STiberiu Breana ret = regmap_field_write(data->reg_als_it, index);
402be9e6229STiberiu Breana else
403be9e6229STiberiu Breana ret = regmap_field_write(data->reg_ps_it, index);
404be9e6229STiberiu Breana if (ret < 0)
405be9e6229STiberiu Breana dev_err(&data->client->dev,
406be9e6229STiberiu Breana "sensor configuration failed\n");
407be9e6229STiberiu Breana mutex_unlock(&data->lock);
408be9e6229STiberiu Breana return ret;
409be9e6229STiberiu Breana
410be9e6229STiberiu Breana case IIO_CHAN_INFO_SCALE:
411be9e6229STiberiu Breana index = stk3310_get_index(stk3310_scale_table,
412be9e6229STiberiu Breana ARRAY_SIZE(stk3310_scale_table),
413be9e6229STiberiu Breana val, val2);
414be9e6229STiberiu Breana if (index < 0)
415be9e6229STiberiu Breana return -EINVAL;
416be9e6229STiberiu Breana mutex_lock(&data->lock);
417be9e6229STiberiu Breana if (chan->type == IIO_LIGHT)
418be9e6229STiberiu Breana ret = regmap_field_write(data->reg_als_gain, index);
419be9e6229STiberiu Breana else
420be9e6229STiberiu Breana ret = regmap_field_write(data->reg_ps_gain, index);
421be9e6229STiberiu Breana if (ret < 0)
422be9e6229STiberiu Breana dev_err(&data->client->dev,
423be9e6229STiberiu Breana "sensor configuration failed\n");
424be9e6229STiberiu Breana mutex_unlock(&data->lock);
425be9e6229STiberiu Breana return ret;
426be9e6229STiberiu Breana }
427be9e6229STiberiu Breana
428be9e6229STiberiu Breana return -EINVAL;
429be9e6229STiberiu Breana }
430be9e6229STiberiu Breana
431be9e6229STiberiu Breana static const struct iio_info stk3310_info = {
432be9e6229STiberiu Breana .read_raw = stk3310_read_raw,
433be9e6229STiberiu Breana .write_raw = stk3310_write_raw,
434be9e6229STiberiu Breana .attrs = &stk3310_attribute_group,
4353dd477acSTiberiu Breana .read_event_value = stk3310_read_event,
4363dd477acSTiberiu Breana .write_event_value = stk3310_write_event,
4373dd477acSTiberiu Breana .read_event_config = stk3310_read_event_config,
4383dd477acSTiberiu Breana .write_event_config = stk3310_write_event_config,
439be9e6229STiberiu Breana };
440be9e6229STiberiu Breana
stk3310_set_state(struct stk3310_data * data,u8 state)441be9e6229STiberiu Breana static int stk3310_set_state(struct stk3310_data *data, u8 state)
442be9e6229STiberiu Breana {
443be9e6229STiberiu Breana int ret;
444be9e6229STiberiu Breana struct i2c_client *client = data->client;
445be9e6229STiberiu Breana
446be9e6229STiberiu Breana /* 3-bit state; 0b100 is not supported. */
447be9e6229STiberiu Breana if (state > 7 || state == 4)
448be9e6229STiberiu Breana return -EINVAL;
449be9e6229STiberiu Breana
450be9e6229STiberiu Breana mutex_lock(&data->lock);
451be9e6229STiberiu Breana ret = regmap_field_write(data->reg_state, state);
452be9e6229STiberiu Breana if (ret < 0) {
453be9e6229STiberiu Breana dev_err(&client->dev, "failed to change sensor state\n");
454be9e6229STiberiu Breana } else if (state != STK3310_STATE_STANDBY) {
455be9e6229STiberiu Breana /* Don't reset the 'enabled' flags if we're going in standby */
456952c3aa3SHartmut Knaack data->ps_enabled = !!(state & STK3310_STATE_EN_PS);
457952c3aa3SHartmut Knaack data->als_enabled = !!(state & STK3310_STATE_EN_ALS);
458be9e6229STiberiu Breana }
459be9e6229STiberiu Breana mutex_unlock(&data->lock);
460be9e6229STiberiu Breana
461be9e6229STiberiu Breana return ret;
462be9e6229STiberiu Breana }
463be9e6229STiberiu Breana
stk3310_init(struct iio_dev * indio_dev)464be9e6229STiberiu Breana static int stk3310_init(struct iio_dev *indio_dev)
465be9e6229STiberiu Breana {
466be9e6229STiberiu Breana int ret;
467be9e6229STiberiu Breana int chipid;
468be9e6229STiberiu Breana u8 state;
469be9e6229STiberiu Breana struct stk3310_data *data = iio_priv(indio_dev);
470be9e6229STiberiu Breana struct i2c_client *client = data->client;
471be9e6229STiberiu Breana
4727c7a9eeaSHartmut Knaack ret = regmap_read(data->regmap, STK3310_REG_ID, &chipid);
4737c7a9eeaSHartmut Knaack if (ret < 0)
4747c7a9eeaSHartmut Knaack return ret;
4757c7a9eeaSHartmut Knaack
476be9e6229STiberiu Breana if (chipid != STK3310_CHIP_ID_VAL &&
477677f1681SMartijn Braam chipid != STK3311_CHIP_ID_VAL &&
4785ef8f84aSIcenowy Zheng chipid != STK3311X_CHIP_ID_VAL &&
479677f1681SMartijn Braam chipid != STK3335_CHIP_ID_VAL) {
480be9e6229STiberiu Breana dev_err(&client->dev, "invalid chip id: 0x%x\n", chipid);
481be9e6229STiberiu Breana return -ENODEV;
482be9e6229STiberiu Breana }
483be9e6229STiberiu Breana
484be9e6229STiberiu Breana state = STK3310_STATE_EN_ALS | STK3310_STATE_EN_PS;
485be9e6229STiberiu Breana ret = stk3310_set_state(data, state);
4863dd477acSTiberiu Breana if (ret < 0) {
487be9e6229STiberiu Breana dev_err(&client->dev, "failed to enable sensor");
4883dd477acSTiberiu Breana return ret;
4893dd477acSTiberiu Breana }
4903dd477acSTiberiu Breana
4913dd477acSTiberiu Breana /* Enable PS interrupts */
4923dd477acSTiberiu Breana ret = regmap_field_write(data->reg_int_ps, STK3310_PSINT_EN);
4933dd477acSTiberiu Breana if (ret < 0)
4943dd477acSTiberiu Breana dev_err(&client->dev, "failed to enable interrupts!\n");
4953dd477acSTiberiu Breana
4963dd477acSTiberiu Breana return ret;
4973dd477acSTiberiu Breana }
4983dd477acSTiberiu Breana
stk3310_is_volatile_reg(struct device * dev,unsigned int reg)499be9e6229STiberiu Breana static bool stk3310_is_volatile_reg(struct device *dev, unsigned int reg)
500be9e6229STiberiu Breana {
501be9e6229STiberiu Breana switch (reg) {
502be9e6229STiberiu Breana case STK3310_REG_ALS_DATA_MSB:
503be9e6229STiberiu Breana case STK3310_REG_ALS_DATA_LSB:
504be9e6229STiberiu Breana case STK3310_REG_PS_DATA_LSB:
505be9e6229STiberiu Breana case STK3310_REG_PS_DATA_MSB:
5063dd477acSTiberiu Breana case STK3310_REG_FLAG:
507be9e6229STiberiu Breana return true;
508be9e6229STiberiu Breana default:
509be9e6229STiberiu Breana return false;
510be9e6229STiberiu Breana }
511be9e6229STiberiu Breana }
512be9e6229STiberiu Breana
513893acabfSRikard Falkeborn static const struct regmap_config stk3310_regmap_config = {
514be9e6229STiberiu Breana .name = STK3310_REGMAP_NAME,
515be9e6229STiberiu Breana .reg_bits = 8,
516be9e6229STiberiu Breana .val_bits = 8,
517be9e6229STiberiu Breana .max_register = STK3310_MAX_REG,
518be9e6229STiberiu Breana .cache_type = REGCACHE_RBTREE,
519be9e6229STiberiu Breana .volatile_reg = stk3310_is_volatile_reg,
520be9e6229STiberiu Breana };
521be9e6229STiberiu Breana
stk3310_regmap_init(struct stk3310_data * data)522be9e6229STiberiu Breana static int stk3310_regmap_init(struct stk3310_data *data)
523be9e6229STiberiu Breana {
524be9e6229STiberiu Breana struct regmap *regmap;
525be9e6229STiberiu Breana struct i2c_client *client;
526be9e6229STiberiu Breana
527be9e6229STiberiu Breana client = data->client;
528be9e6229STiberiu Breana regmap = devm_regmap_init_i2c(client, &stk3310_regmap_config);
529be9e6229STiberiu Breana if (IS_ERR(regmap)) {
530be9e6229STiberiu Breana dev_err(&client->dev, "regmap initialization failed.\n");
531be9e6229STiberiu Breana return PTR_ERR(regmap);
532be9e6229STiberiu Breana }
533be9e6229STiberiu Breana data->regmap = regmap;
534be9e6229STiberiu Breana
535be9e6229STiberiu Breana STK3310_REGFIELD(state);
536be9e6229STiberiu Breana STK3310_REGFIELD(als_gain);
537be9e6229STiberiu Breana STK3310_REGFIELD(ps_gain);
538be9e6229STiberiu Breana STK3310_REGFIELD(als_it);
539be9e6229STiberiu Breana STK3310_REGFIELD(ps_it);
5403dd477acSTiberiu Breana STK3310_REGFIELD(int_ps);
5413dd477acSTiberiu Breana STK3310_REGFIELD(flag_psint);
5423dd477acSTiberiu Breana STK3310_REGFIELD(flag_nf);
543be9e6229STiberiu Breana
544be9e6229STiberiu Breana return 0;
545be9e6229STiberiu Breana }
546be9e6229STiberiu Breana
stk3310_irq_handler(int irq,void * private)5473dd477acSTiberiu Breana static irqreturn_t stk3310_irq_handler(int irq, void *private)
5483dd477acSTiberiu Breana {
5493dd477acSTiberiu Breana struct iio_dev *indio_dev = private;
5503dd477acSTiberiu Breana struct stk3310_data *data = iio_priv(indio_dev);
5513dd477acSTiberiu Breana
552bc2b7dabSGregor Boirie data->timestamp = iio_get_time_ns(indio_dev);
5533dd477acSTiberiu Breana
5543dd477acSTiberiu Breana return IRQ_WAKE_THREAD;
5553dd477acSTiberiu Breana }
5563dd477acSTiberiu Breana
stk3310_irq_event_handler(int irq,void * private)5573dd477acSTiberiu Breana static irqreturn_t stk3310_irq_event_handler(int irq, void *private)
5583dd477acSTiberiu Breana {
5593dd477acSTiberiu Breana int ret;
5603dd477acSTiberiu Breana unsigned int dir;
5613dd477acSTiberiu Breana u64 event;
5623dd477acSTiberiu Breana
5633dd477acSTiberiu Breana struct iio_dev *indio_dev = private;
5643dd477acSTiberiu Breana struct stk3310_data *data = iio_priv(indio_dev);
5653dd477acSTiberiu Breana
5663dd477acSTiberiu Breana /* Read FLAG_NF to figure out what threshold has been met. */
5673dd477acSTiberiu Breana mutex_lock(&data->lock);
5683dd477acSTiberiu Breana ret = regmap_field_read(data->reg_flag_nf, &dir);
5693dd477acSTiberiu Breana if (ret < 0) {
5708e1eeca5SLars-Peter Clausen dev_err(&data->client->dev, "register read failed: %d\n", ret);
5718e1eeca5SLars-Peter Clausen goto out;
5723dd477acSTiberiu Breana }
5733dd477acSTiberiu Breana event = IIO_UNMOD_EVENT_CODE(IIO_PROXIMITY, 1,
5743dd477acSTiberiu Breana IIO_EV_TYPE_THRESH,
5750f16fc8bSTiberiu Breana (dir ? IIO_EV_DIR_FALLING :
5760f16fc8bSTiberiu Breana IIO_EV_DIR_RISING));
5773dd477acSTiberiu Breana iio_push_event(indio_dev, event, data->timestamp);
5783dd477acSTiberiu Breana
5793dd477acSTiberiu Breana /* Reset the interrupt flag */
5803dd477acSTiberiu Breana ret = regmap_field_write(data->reg_flag_psint, 0);
5813dd477acSTiberiu Breana if (ret < 0)
5823dd477acSTiberiu Breana dev_err(&data->client->dev, "failed to reset interrupts\n");
5838e1eeca5SLars-Peter Clausen out:
5843dd477acSTiberiu Breana mutex_unlock(&data->lock);
5853dd477acSTiberiu Breana
5863dd477acSTiberiu Breana return IRQ_HANDLED;
5873dd477acSTiberiu Breana }
5883dd477acSTiberiu Breana
stk3310_probe(struct i2c_client * client)5899046d80dSUwe Kleine-König static int stk3310_probe(struct i2c_client *client)
590be9e6229STiberiu Breana {
591be9e6229STiberiu Breana int ret;
592be9e6229STiberiu Breana struct iio_dev *indio_dev;
593be9e6229STiberiu Breana struct stk3310_data *data;
594be9e6229STiberiu Breana
595be9e6229STiberiu Breana indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
596be9e6229STiberiu Breana if (!indio_dev) {
597be9e6229STiberiu Breana dev_err(&client->dev, "iio allocation failed!\n");
598be9e6229STiberiu Breana return -ENOMEM;
599be9e6229STiberiu Breana }
600be9e6229STiberiu Breana
601be9e6229STiberiu Breana data = iio_priv(indio_dev);
602be9e6229STiberiu Breana data->client = client;
603be9e6229STiberiu Breana i2c_set_clientdata(client, indio_dev);
604d6ecb015SArnaud Ferraris
605d6ecb015SArnaud Ferraris device_property_read_u32(&client->dev, "proximity-near-level",
606d6ecb015SArnaud Ferraris &data->ps_near_level);
607d6ecb015SArnaud Ferraris
608be9e6229STiberiu Breana mutex_init(&data->lock);
609be9e6229STiberiu Breana
610be9e6229STiberiu Breana ret = stk3310_regmap_init(data);
611be9e6229STiberiu Breana if (ret < 0)
612be9e6229STiberiu Breana return ret;
613be9e6229STiberiu Breana
614be9e6229STiberiu Breana indio_dev->info = &stk3310_info;
615be9e6229STiberiu Breana indio_dev->name = STK3310_DRIVER_NAME;
616be9e6229STiberiu Breana indio_dev->modes = INDIO_DIRECT_MODE;
617be9e6229STiberiu Breana indio_dev->channels = stk3310_channels;
618be9e6229STiberiu Breana indio_dev->num_channels = ARRAY_SIZE(stk3310_channels);
619be9e6229STiberiu Breana
620be9e6229STiberiu Breana ret = stk3310_init(indio_dev);
621be9e6229STiberiu Breana if (ret < 0)
622be9e6229STiberiu Breana return ret;
623be9e6229STiberiu Breana
6246839c1b0SOctavian Purdila if (client->irq > 0) {
6253dd477acSTiberiu Breana ret = devm_request_threaded_irq(&client->dev, client->irq,
6263dd477acSTiberiu Breana stk3310_irq_handler,
6273dd477acSTiberiu Breana stk3310_irq_event_handler,
6283dd477acSTiberiu Breana IRQF_TRIGGER_FALLING |
6293dd477acSTiberiu Breana IRQF_ONESHOT,
6303dd477acSTiberiu Breana STK3310_EVENT, indio_dev);
6317c7a9eeaSHartmut Knaack if (ret < 0) {
6323dd477acSTiberiu Breana dev_err(&client->dev, "request irq %d failed\n",
6333dd477acSTiberiu Breana client->irq);
6347c7a9eeaSHartmut Knaack goto err_standby;
6357c7a9eeaSHartmut Knaack }
6363dd477acSTiberiu Breana }
6373dd477acSTiberiu Breana
638037e966fSHartmut Knaack ret = iio_device_register(indio_dev);
639037e966fSHartmut Knaack if (ret < 0) {
640037e966fSHartmut Knaack dev_err(&client->dev, "device_register failed\n");
6417c7a9eeaSHartmut Knaack goto err_standby;
642037e966fSHartmut Knaack }
643037e966fSHartmut Knaack
6447c7a9eeaSHartmut Knaack return 0;
6457c7a9eeaSHartmut Knaack
6467c7a9eeaSHartmut Knaack err_standby:
6477c7a9eeaSHartmut Knaack stk3310_set_state(data, STK3310_STATE_STANDBY);
648be9e6229STiberiu Breana return ret;
649be9e6229STiberiu Breana }
650be9e6229STiberiu Breana
stk3310_remove(struct i2c_client * client)651ed5c2f5fSUwe Kleine-König static void stk3310_remove(struct i2c_client *client)
652be9e6229STiberiu Breana {
653be9e6229STiberiu Breana struct iio_dev *indio_dev = i2c_get_clientdata(client);
654be9e6229STiberiu Breana
655be9e6229STiberiu Breana iio_device_unregister(indio_dev);
65658a6df55SUwe Kleine-König stk3310_set_state(iio_priv(indio_dev), STK3310_STATE_STANDBY);
657be9e6229STiberiu Breana }
658be9e6229STiberiu Breana
stk3310_suspend(struct device * dev)659be9e6229STiberiu Breana static int stk3310_suspend(struct device *dev)
660be9e6229STiberiu Breana {
661be9e6229STiberiu Breana struct stk3310_data *data;
662be9e6229STiberiu Breana
663be9e6229STiberiu Breana data = iio_priv(i2c_get_clientdata(to_i2c_client(dev)));
664be9e6229STiberiu Breana
665be9e6229STiberiu Breana return stk3310_set_state(data, STK3310_STATE_STANDBY);
666be9e6229STiberiu Breana }
667be9e6229STiberiu Breana
stk3310_resume(struct device * dev)668be9e6229STiberiu Breana static int stk3310_resume(struct device *dev)
669be9e6229STiberiu Breana {
670952c3aa3SHartmut Knaack u8 state = 0;
671be9e6229STiberiu Breana struct stk3310_data *data;
672be9e6229STiberiu Breana
673be9e6229STiberiu Breana data = iio_priv(i2c_get_clientdata(to_i2c_client(dev)));
674be9e6229STiberiu Breana if (data->ps_enabled)
675be9e6229STiberiu Breana state |= STK3310_STATE_EN_PS;
676be9e6229STiberiu Breana if (data->als_enabled)
677be9e6229STiberiu Breana state |= STK3310_STATE_EN_ALS;
678be9e6229STiberiu Breana
679be9e6229STiberiu Breana return stk3310_set_state(data, state);
680be9e6229STiberiu Breana }
681be9e6229STiberiu Breana
68220cadda3SJonathan Cameron static DEFINE_SIMPLE_DEV_PM_OPS(stk3310_pm_ops, stk3310_suspend,
68320cadda3SJonathan Cameron stk3310_resume);
684be9e6229STiberiu Breana
685be9e6229STiberiu Breana static const struct i2c_device_id stk3310_i2c_id[] = {
686be9e6229STiberiu Breana {"STK3310", 0},
687be9e6229STiberiu Breana {"STK3311", 0},
688677f1681SMartijn Braam {"STK3335", 0},
689be9e6229STiberiu Breana {}
690be9e6229STiberiu Breana };
69158e446fcSJavier Martinez Canillas MODULE_DEVICE_TABLE(i2c, stk3310_i2c_id);
692be9e6229STiberiu Breana
693be9e6229STiberiu Breana static const struct acpi_device_id stk3310_acpi_id[] = {
694be9e6229STiberiu Breana {"STK3310", 0},
695be9e6229STiberiu Breana {"STK3311", 0},
696677f1681SMartijn Braam {"STK3335", 0},
697be9e6229STiberiu Breana {}
698be9e6229STiberiu Breana };
699be9e6229STiberiu Breana
700be9e6229STiberiu Breana MODULE_DEVICE_TABLE(acpi, stk3310_acpi_id);
701be9e6229STiberiu Breana
702c3a68607SLuca Weiss static const struct of_device_id stk3310_of_match[] = {
703c3a68607SLuca Weiss { .compatible = "sensortek,stk3310", },
704c3a68607SLuca Weiss { .compatible = "sensortek,stk3311", },
705c3a68607SLuca Weiss { .compatible = "sensortek,stk3335", },
706c3a68607SLuca Weiss {}
707c3a68607SLuca Weiss };
708c3a68607SLuca Weiss MODULE_DEVICE_TABLE(of, stk3310_of_match);
709c3a68607SLuca Weiss
710be9e6229STiberiu Breana static struct i2c_driver stk3310_driver = {
711be9e6229STiberiu Breana .driver = {
712be9e6229STiberiu Breana .name = "stk3310",
713c3a68607SLuca Weiss .of_match_table = stk3310_of_match,
71420cadda3SJonathan Cameron .pm = pm_sleep_ptr(&stk3310_pm_ops),
715be9e6229STiberiu Breana .acpi_match_table = ACPI_PTR(stk3310_acpi_id),
716be9e6229STiberiu Breana },
717*7cf15f42SUwe Kleine-König .probe = stk3310_probe,
718be9e6229STiberiu Breana .remove = stk3310_remove,
719be9e6229STiberiu Breana .id_table = stk3310_i2c_id,
720be9e6229STiberiu Breana };
721be9e6229STiberiu Breana
722be9e6229STiberiu Breana module_i2c_driver(stk3310_driver);
723be9e6229STiberiu Breana
724be9e6229STiberiu Breana MODULE_AUTHOR("Tiberiu Breana <tiberiu.a.breana@intel.com>");
725be9e6229STiberiu Breana MODULE_DESCRIPTION("STK3310 Ambient Light and Proximity Sensor driver");
726be9e6229STiberiu Breana MODULE_LICENSE("GPL v2");
727