xref: /OK3568_Linux_fs/kernel/drivers/iio/light/bh1750.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * ROHM BH1710/BH1715/BH1721/BH1750/BH1751 ambient light sensor driver
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Copyright (c) Tomasz Duszynski <tduszyns@gmail.com>
6*4882a593Smuzhiyun  *
7*4882a593Smuzhiyun  * Data sheets:
8*4882a593Smuzhiyun  *  http://rohmfs.rohm.com/en/products/databook/datasheet/ic/sensor/light/bh1710fvc-e.pdf
9*4882a593Smuzhiyun  *  http://rohmfs.rohm.com/en/products/databook/datasheet/ic/sensor/light/bh1715fvc-e.pdf
10*4882a593Smuzhiyun  *  http://rohmfs.rohm.com/en/products/databook/datasheet/ic/sensor/light/bh1721fvc-e.pdf
11*4882a593Smuzhiyun  *  http://rohmfs.rohm.com/en/products/databook/datasheet/ic/sensor/light/bh1750fvi-e.pdf
12*4882a593Smuzhiyun  *  http://rohmfs.rohm.com/en/products/databook/datasheet/ic/sensor/light/bh1751fvi-e.pdf
13*4882a593Smuzhiyun  *
14*4882a593Smuzhiyun  * 7-bit I2C slave addresses:
15*4882a593Smuzhiyun  *  0x23 (ADDR pin low)
16*4882a593Smuzhiyun  *  0x5C (ADDR pin high)
17*4882a593Smuzhiyun  *
18*4882a593Smuzhiyun  */
19*4882a593Smuzhiyun 
20*4882a593Smuzhiyun #include <linux/delay.h>
21*4882a593Smuzhiyun #include <linux/i2c.h>
22*4882a593Smuzhiyun #include <linux/iio/iio.h>
23*4882a593Smuzhiyun #include <linux/iio/sysfs.h>
24*4882a593Smuzhiyun #include <linux/module.h>
25*4882a593Smuzhiyun 
26*4882a593Smuzhiyun #define BH1750_POWER_DOWN		0x00
27*4882a593Smuzhiyun #define BH1750_ONE_TIME_H_RES_MODE	0x20 /* auto-mode for BH1721 */
28*4882a593Smuzhiyun #define BH1750_CHANGE_INT_TIME_H_BIT	0x40
29*4882a593Smuzhiyun #define BH1750_CHANGE_INT_TIME_L_BIT	0x60
30*4882a593Smuzhiyun 
31*4882a593Smuzhiyun enum {
32*4882a593Smuzhiyun 	BH1710,
33*4882a593Smuzhiyun 	BH1721,
34*4882a593Smuzhiyun 	BH1750,
35*4882a593Smuzhiyun };
36*4882a593Smuzhiyun 
37*4882a593Smuzhiyun struct bh1750_chip_info;
38*4882a593Smuzhiyun struct bh1750_data {
39*4882a593Smuzhiyun 	struct i2c_client *client;
40*4882a593Smuzhiyun 	struct mutex lock;
41*4882a593Smuzhiyun 	const struct bh1750_chip_info *chip_info;
42*4882a593Smuzhiyun 	u16 mtreg;
43*4882a593Smuzhiyun };
44*4882a593Smuzhiyun 
45*4882a593Smuzhiyun struct bh1750_chip_info {
46*4882a593Smuzhiyun 	u16 mtreg_min;
47*4882a593Smuzhiyun 	u16 mtreg_max;
48*4882a593Smuzhiyun 	u16 mtreg_default;
49*4882a593Smuzhiyun 	int mtreg_to_usec;
50*4882a593Smuzhiyun 	int mtreg_to_scale;
51*4882a593Smuzhiyun 
52*4882a593Smuzhiyun 	/*
53*4882a593Smuzhiyun 	 * For BH1710/BH1721 all possible integration time values won't fit
54*4882a593Smuzhiyun 	 * into one page so displaying is limited to every second one.
55*4882a593Smuzhiyun 	 * Note, that user can still write proper values which were not
56*4882a593Smuzhiyun 	 * listed.
57*4882a593Smuzhiyun 	 */
58*4882a593Smuzhiyun 	int inc;
59*4882a593Smuzhiyun 
60*4882a593Smuzhiyun 	u16 int_time_low_mask;
61*4882a593Smuzhiyun 	u16 int_time_high_mask;
62*4882a593Smuzhiyun };
63*4882a593Smuzhiyun 
64*4882a593Smuzhiyun static const struct bh1750_chip_info bh1750_chip_info_tbl[] = {
65*4882a593Smuzhiyun 	[BH1710] = { 140, 1022, 300, 400,  250000000, 2, 0x001F, 0x03E0 },
66*4882a593Smuzhiyun 	[BH1721] = { 140, 1020, 300, 400,  250000000, 2, 0x0010, 0x03E0 },
67*4882a593Smuzhiyun 	[BH1750] = { 31,  254,  69,  1740, 57500000,  1, 0x001F, 0x00E0 },
68*4882a593Smuzhiyun };
69*4882a593Smuzhiyun 
bh1750_change_int_time(struct bh1750_data * data,int usec)70*4882a593Smuzhiyun static int bh1750_change_int_time(struct bh1750_data *data, int usec)
71*4882a593Smuzhiyun {
72*4882a593Smuzhiyun 	int ret;
73*4882a593Smuzhiyun 	u16 val;
74*4882a593Smuzhiyun 	u8 regval;
75*4882a593Smuzhiyun 	const struct bh1750_chip_info *chip_info = data->chip_info;
76*4882a593Smuzhiyun 
77*4882a593Smuzhiyun 	if ((usec % chip_info->mtreg_to_usec) != 0)
78*4882a593Smuzhiyun 		return -EINVAL;
79*4882a593Smuzhiyun 
80*4882a593Smuzhiyun 	val = usec / chip_info->mtreg_to_usec;
81*4882a593Smuzhiyun 	if (val < chip_info->mtreg_min || val > chip_info->mtreg_max)
82*4882a593Smuzhiyun 		return -EINVAL;
83*4882a593Smuzhiyun 
84*4882a593Smuzhiyun 	ret = i2c_smbus_write_byte(data->client, BH1750_POWER_DOWN);
85*4882a593Smuzhiyun 	if (ret < 0)
86*4882a593Smuzhiyun 		return ret;
87*4882a593Smuzhiyun 
88*4882a593Smuzhiyun 	regval = (val & chip_info->int_time_high_mask) >> 5;
89*4882a593Smuzhiyun 	ret = i2c_smbus_write_byte(data->client,
90*4882a593Smuzhiyun 				   BH1750_CHANGE_INT_TIME_H_BIT | regval);
91*4882a593Smuzhiyun 	if (ret < 0)
92*4882a593Smuzhiyun 		return ret;
93*4882a593Smuzhiyun 
94*4882a593Smuzhiyun 	regval = val & chip_info->int_time_low_mask;
95*4882a593Smuzhiyun 	ret = i2c_smbus_write_byte(data->client,
96*4882a593Smuzhiyun 				   BH1750_CHANGE_INT_TIME_L_BIT | regval);
97*4882a593Smuzhiyun 	if (ret < 0)
98*4882a593Smuzhiyun 		return ret;
99*4882a593Smuzhiyun 
100*4882a593Smuzhiyun 	data->mtreg = val;
101*4882a593Smuzhiyun 
102*4882a593Smuzhiyun 	return 0;
103*4882a593Smuzhiyun }
104*4882a593Smuzhiyun 
bh1750_read(struct bh1750_data * data,int * val)105*4882a593Smuzhiyun static int bh1750_read(struct bh1750_data *data, int *val)
106*4882a593Smuzhiyun {
107*4882a593Smuzhiyun 	int ret;
108*4882a593Smuzhiyun 	__be16 result;
109*4882a593Smuzhiyun 	const struct bh1750_chip_info *chip_info = data->chip_info;
110*4882a593Smuzhiyun 	unsigned long delay = chip_info->mtreg_to_usec * data->mtreg;
111*4882a593Smuzhiyun 
112*4882a593Smuzhiyun 	/*
113*4882a593Smuzhiyun 	 * BH1721 will enter continuous mode on receiving this command.
114*4882a593Smuzhiyun 	 * Note, that this eliminates need for bh1750_resume().
115*4882a593Smuzhiyun 	 */
116*4882a593Smuzhiyun 	ret = i2c_smbus_write_byte(data->client, BH1750_ONE_TIME_H_RES_MODE);
117*4882a593Smuzhiyun 	if (ret < 0)
118*4882a593Smuzhiyun 		return ret;
119*4882a593Smuzhiyun 
120*4882a593Smuzhiyun 	usleep_range(delay + 15000, delay + 40000);
121*4882a593Smuzhiyun 
122*4882a593Smuzhiyun 	ret = i2c_master_recv(data->client, (char *)&result, 2);
123*4882a593Smuzhiyun 	if (ret < 0)
124*4882a593Smuzhiyun 		return ret;
125*4882a593Smuzhiyun 
126*4882a593Smuzhiyun 	*val = be16_to_cpu(result);
127*4882a593Smuzhiyun 
128*4882a593Smuzhiyun 	return 0;
129*4882a593Smuzhiyun }
130*4882a593Smuzhiyun 
bh1750_read_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,int * val,int * val2,long mask)131*4882a593Smuzhiyun static int bh1750_read_raw(struct iio_dev *indio_dev,
132*4882a593Smuzhiyun 			   struct iio_chan_spec const *chan,
133*4882a593Smuzhiyun 			   int *val, int *val2, long mask)
134*4882a593Smuzhiyun {
135*4882a593Smuzhiyun 	int ret, tmp;
136*4882a593Smuzhiyun 	struct bh1750_data *data = iio_priv(indio_dev);
137*4882a593Smuzhiyun 	const struct bh1750_chip_info *chip_info = data->chip_info;
138*4882a593Smuzhiyun 
139*4882a593Smuzhiyun 	switch (mask) {
140*4882a593Smuzhiyun 	case IIO_CHAN_INFO_RAW:
141*4882a593Smuzhiyun 		switch (chan->type) {
142*4882a593Smuzhiyun 		case IIO_LIGHT:
143*4882a593Smuzhiyun 			mutex_lock(&data->lock);
144*4882a593Smuzhiyun 			ret = bh1750_read(data, val);
145*4882a593Smuzhiyun 			mutex_unlock(&data->lock);
146*4882a593Smuzhiyun 			if (ret < 0)
147*4882a593Smuzhiyun 				return ret;
148*4882a593Smuzhiyun 
149*4882a593Smuzhiyun 			return IIO_VAL_INT;
150*4882a593Smuzhiyun 		default:
151*4882a593Smuzhiyun 			return -EINVAL;
152*4882a593Smuzhiyun 		}
153*4882a593Smuzhiyun 	case IIO_CHAN_INFO_SCALE:
154*4882a593Smuzhiyun 		tmp = chip_info->mtreg_to_scale / data->mtreg;
155*4882a593Smuzhiyun 		*val = tmp / 1000000;
156*4882a593Smuzhiyun 		*val2 = tmp % 1000000;
157*4882a593Smuzhiyun 		return IIO_VAL_INT_PLUS_MICRO;
158*4882a593Smuzhiyun 	case IIO_CHAN_INFO_INT_TIME:
159*4882a593Smuzhiyun 		*val = 0;
160*4882a593Smuzhiyun 		*val2 = chip_info->mtreg_to_usec * data->mtreg;
161*4882a593Smuzhiyun 		return IIO_VAL_INT_PLUS_MICRO;
162*4882a593Smuzhiyun 	default:
163*4882a593Smuzhiyun 		return -EINVAL;
164*4882a593Smuzhiyun 	}
165*4882a593Smuzhiyun }
166*4882a593Smuzhiyun 
bh1750_write_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,int val,int val2,long mask)167*4882a593Smuzhiyun static int bh1750_write_raw(struct iio_dev *indio_dev,
168*4882a593Smuzhiyun 			    struct iio_chan_spec const *chan,
169*4882a593Smuzhiyun 			    int val, int val2, long mask)
170*4882a593Smuzhiyun {
171*4882a593Smuzhiyun 	int ret;
172*4882a593Smuzhiyun 	struct bh1750_data *data = iio_priv(indio_dev);
173*4882a593Smuzhiyun 
174*4882a593Smuzhiyun 	switch (mask) {
175*4882a593Smuzhiyun 	case IIO_CHAN_INFO_INT_TIME:
176*4882a593Smuzhiyun 		if (val != 0)
177*4882a593Smuzhiyun 			return -EINVAL;
178*4882a593Smuzhiyun 
179*4882a593Smuzhiyun 		mutex_lock(&data->lock);
180*4882a593Smuzhiyun 		ret = bh1750_change_int_time(data, val2);
181*4882a593Smuzhiyun 		mutex_unlock(&data->lock);
182*4882a593Smuzhiyun 		return ret;
183*4882a593Smuzhiyun 	default:
184*4882a593Smuzhiyun 		return -EINVAL;
185*4882a593Smuzhiyun 	}
186*4882a593Smuzhiyun }
187*4882a593Smuzhiyun 
bh1750_show_int_time_available(struct device * dev,struct device_attribute * attr,char * buf)188*4882a593Smuzhiyun static ssize_t bh1750_show_int_time_available(struct device *dev,
189*4882a593Smuzhiyun 		struct device_attribute *attr, char *buf)
190*4882a593Smuzhiyun {
191*4882a593Smuzhiyun 	int i;
192*4882a593Smuzhiyun 	size_t len = 0;
193*4882a593Smuzhiyun 	struct bh1750_data *data = iio_priv(dev_to_iio_dev(dev));
194*4882a593Smuzhiyun 	const struct bh1750_chip_info *chip_info = data->chip_info;
195*4882a593Smuzhiyun 
196*4882a593Smuzhiyun 	for (i = chip_info->mtreg_min; i <= chip_info->mtreg_max; i += chip_info->inc)
197*4882a593Smuzhiyun 		len += scnprintf(buf + len, PAGE_SIZE - len, "0.%06d ",
198*4882a593Smuzhiyun 				 chip_info->mtreg_to_usec * i);
199*4882a593Smuzhiyun 
200*4882a593Smuzhiyun 	buf[len - 1] = '\n';
201*4882a593Smuzhiyun 
202*4882a593Smuzhiyun 	return len;
203*4882a593Smuzhiyun }
204*4882a593Smuzhiyun 
205*4882a593Smuzhiyun static IIO_DEV_ATTR_INT_TIME_AVAIL(bh1750_show_int_time_available);
206*4882a593Smuzhiyun 
207*4882a593Smuzhiyun static struct attribute *bh1750_attributes[] = {
208*4882a593Smuzhiyun 	&iio_dev_attr_integration_time_available.dev_attr.attr,
209*4882a593Smuzhiyun 	NULL,
210*4882a593Smuzhiyun };
211*4882a593Smuzhiyun 
212*4882a593Smuzhiyun static const struct attribute_group bh1750_attribute_group = {
213*4882a593Smuzhiyun 	.attrs = bh1750_attributes,
214*4882a593Smuzhiyun };
215*4882a593Smuzhiyun 
216*4882a593Smuzhiyun static const struct iio_info bh1750_info = {
217*4882a593Smuzhiyun 	.attrs = &bh1750_attribute_group,
218*4882a593Smuzhiyun 	.read_raw = bh1750_read_raw,
219*4882a593Smuzhiyun 	.write_raw = bh1750_write_raw,
220*4882a593Smuzhiyun };
221*4882a593Smuzhiyun 
222*4882a593Smuzhiyun static const struct iio_chan_spec bh1750_channels[] = {
223*4882a593Smuzhiyun 	{
224*4882a593Smuzhiyun 		.type = IIO_LIGHT,
225*4882a593Smuzhiyun 		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
226*4882a593Smuzhiyun 				      BIT(IIO_CHAN_INFO_SCALE) |
227*4882a593Smuzhiyun 				      BIT(IIO_CHAN_INFO_INT_TIME)
228*4882a593Smuzhiyun 	}
229*4882a593Smuzhiyun };
230*4882a593Smuzhiyun 
bh1750_probe(struct i2c_client * client,const struct i2c_device_id * id)231*4882a593Smuzhiyun static int bh1750_probe(struct i2c_client *client,
232*4882a593Smuzhiyun 			const struct i2c_device_id *id)
233*4882a593Smuzhiyun {
234*4882a593Smuzhiyun 	int ret, usec;
235*4882a593Smuzhiyun 	struct bh1750_data *data;
236*4882a593Smuzhiyun 	struct iio_dev *indio_dev;
237*4882a593Smuzhiyun 
238*4882a593Smuzhiyun 	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C |
239*4882a593Smuzhiyun 				I2C_FUNC_SMBUS_WRITE_BYTE))
240*4882a593Smuzhiyun 		return -EOPNOTSUPP;
241*4882a593Smuzhiyun 
242*4882a593Smuzhiyun 	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
243*4882a593Smuzhiyun 	if (!indio_dev)
244*4882a593Smuzhiyun 		return -ENOMEM;
245*4882a593Smuzhiyun 
246*4882a593Smuzhiyun 	data = iio_priv(indio_dev);
247*4882a593Smuzhiyun 	i2c_set_clientdata(client, indio_dev);
248*4882a593Smuzhiyun 	data->client = client;
249*4882a593Smuzhiyun 	data->chip_info = &bh1750_chip_info_tbl[id->driver_data];
250*4882a593Smuzhiyun 
251*4882a593Smuzhiyun 	usec = data->chip_info->mtreg_to_usec * data->chip_info->mtreg_default;
252*4882a593Smuzhiyun 	ret = bh1750_change_int_time(data, usec);
253*4882a593Smuzhiyun 	if (ret < 0)
254*4882a593Smuzhiyun 		return ret;
255*4882a593Smuzhiyun 
256*4882a593Smuzhiyun 	mutex_init(&data->lock);
257*4882a593Smuzhiyun 	indio_dev->info = &bh1750_info;
258*4882a593Smuzhiyun 	indio_dev->name = id->name;
259*4882a593Smuzhiyun 	indio_dev->channels = bh1750_channels;
260*4882a593Smuzhiyun 	indio_dev->num_channels = ARRAY_SIZE(bh1750_channels);
261*4882a593Smuzhiyun 	indio_dev->modes = INDIO_DIRECT_MODE;
262*4882a593Smuzhiyun 
263*4882a593Smuzhiyun 	return iio_device_register(indio_dev);
264*4882a593Smuzhiyun }
265*4882a593Smuzhiyun 
bh1750_remove(struct i2c_client * client)266*4882a593Smuzhiyun static int bh1750_remove(struct i2c_client *client)
267*4882a593Smuzhiyun {
268*4882a593Smuzhiyun 	struct iio_dev *indio_dev = i2c_get_clientdata(client);
269*4882a593Smuzhiyun 	struct bh1750_data *data = iio_priv(indio_dev);
270*4882a593Smuzhiyun 
271*4882a593Smuzhiyun 	iio_device_unregister(indio_dev);
272*4882a593Smuzhiyun 
273*4882a593Smuzhiyun 	mutex_lock(&data->lock);
274*4882a593Smuzhiyun 	i2c_smbus_write_byte(client, BH1750_POWER_DOWN);
275*4882a593Smuzhiyun 	mutex_unlock(&data->lock);
276*4882a593Smuzhiyun 
277*4882a593Smuzhiyun 	return 0;
278*4882a593Smuzhiyun }
279*4882a593Smuzhiyun 
bh1750_suspend(struct device * dev)280*4882a593Smuzhiyun static int __maybe_unused bh1750_suspend(struct device *dev)
281*4882a593Smuzhiyun {
282*4882a593Smuzhiyun 	int ret;
283*4882a593Smuzhiyun 	struct bh1750_data *data =
284*4882a593Smuzhiyun 		iio_priv(i2c_get_clientdata(to_i2c_client(dev)));
285*4882a593Smuzhiyun 
286*4882a593Smuzhiyun 	/*
287*4882a593Smuzhiyun 	 * This is mainly for BH1721 which doesn't enter power down
288*4882a593Smuzhiyun 	 * mode automatically.
289*4882a593Smuzhiyun 	 */
290*4882a593Smuzhiyun 	mutex_lock(&data->lock);
291*4882a593Smuzhiyun 	ret = i2c_smbus_write_byte(data->client, BH1750_POWER_DOWN);
292*4882a593Smuzhiyun 	mutex_unlock(&data->lock);
293*4882a593Smuzhiyun 
294*4882a593Smuzhiyun 	return ret;
295*4882a593Smuzhiyun }
296*4882a593Smuzhiyun 
297*4882a593Smuzhiyun static SIMPLE_DEV_PM_OPS(bh1750_pm_ops, bh1750_suspend, NULL);
298*4882a593Smuzhiyun 
299*4882a593Smuzhiyun static const struct i2c_device_id bh1750_id[] = {
300*4882a593Smuzhiyun 	{ "bh1710", BH1710 },
301*4882a593Smuzhiyun 	{ "bh1715", BH1750 },
302*4882a593Smuzhiyun 	{ "bh1721", BH1721 },
303*4882a593Smuzhiyun 	{ "bh1750", BH1750 },
304*4882a593Smuzhiyun 	{ "bh1751", BH1750 },
305*4882a593Smuzhiyun 	{ }
306*4882a593Smuzhiyun };
307*4882a593Smuzhiyun MODULE_DEVICE_TABLE(i2c, bh1750_id);
308*4882a593Smuzhiyun 
309*4882a593Smuzhiyun static const struct of_device_id bh1750_of_match[] = {
310*4882a593Smuzhiyun 	{ .compatible = "rohm,bh1710", },
311*4882a593Smuzhiyun 	{ .compatible = "rohm,bh1715", },
312*4882a593Smuzhiyun 	{ .compatible = "rohm,bh1721", },
313*4882a593Smuzhiyun 	{ .compatible = "rohm,bh1750", },
314*4882a593Smuzhiyun 	{ .compatible = "rohm,bh1751", },
315*4882a593Smuzhiyun 	{ }
316*4882a593Smuzhiyun };
317*4882a593Smuzhiyun MODULE_DEVICE_TABLE(of, bh1750_of_match);
318*4882a593Smuzhiyun 
319*4882a593Smuzhiyun static struct i2c_driver bh1750_driver = {
320*4882a593Smuzhiyun 	.driver = {
321*4882a593Smuzhiyun 		.name = "bh1750",
322*4882a593Smuzhiyun 		.of_match_table = bh1750_of_match,
323*4882a593Smuzhiyun 		.pm = &bh1750_pm_ops,
324*4882a593Smuzhiyun 	},
325*4882a593Smuzhiyun 	.probe = bh1750_probe,
326*4882a593Smuzhiyun 	.remove = bh1750_remove,
327*4882a593Smuzhiyun 	.id_table = bh1750_id,
328*4882a593Smuzhiyun 
329*4882a593Smuzhiyun };
330*4882a593Smuzhiyun module_i2c_driver(bh1750_driver);
331*4882a593Smuzhiyun 
332*4882a593Smuzhiyun MODULE_AUTHOR("Tomasz Duszynski <tduszyns@gmail.com>");
333*4882a593Smuzhiyun MODULE_DESCRIPTION("ROHM BH1710/BH1715/BH1721/BH1750/BH1751 als driver");
334*4882a593Smuzhiyun MODULE_LICENSE("GPL v2");
335