18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * ROHM BH1710/BH1715/BH1721/BH1750/BH1751 ambient light sensor driver 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (c) Tomasz Duszynski <tduszyns@gmail.com> 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Data sheets: 88c2ecf20Sopenharmony_ci * http://rohmfs.rohm.com/en/products/databook/datasheet/ic/sensor/light/bh1710fvc-e.pdf 98c2ecf20Sopenharmony_ci * http://rohmfs.rohm.com/en/products/databook/datasheet/ic/sensor/light/bh1715fvc-e.pdf 108c2ecf20Sopenharmony_ci * http://rohmfs.rohm.com/en/products/databook/datasheet/ic/sensor/light/bh1721fvc-e.pdf 118c2ecf20Sopenharmony_ci * http://rohmfs.rohm.com/en/products/databook/datasheet/ic/sensor/light/bh1750fvi-e.pdf 128c2ecf20Sopenharmony_ci * http://rohmfs.rohm.com/en/products/databook/datasheet/ic/sensor/light/bh1751fvi-e.pdf 138c2ecf20Sopenharmony_ci * 148c2ecf20Sopenharmony_ci * 7-bit I2C slave addresses: 158c2ecf20Sopenharmony_ci * 0x23 (ADDR pin low) 168c2ecf20Sopenharmony_ci * 0x5C (ADDR pin high) 178c2ecf20Sopenharmony_ci * 188c2ecf20Sopenharmony_ci */ 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_ci#include <linux/delay.h> 218c2ecf20Sopenharmony_ci#include <linux/i2c.h> 228c2ecf20Sopenharmony_ci#include <linux/iio/iio.h> 238c2ecf20Sopenharmony_ci#include <linux/iio/sysfs.h> 248c2ecf20Sopenharmony_ci#include <linux/module.h> 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ci#define BH1750_POWER_DOWN 0x00 278c2ecf20Sopenharmony_ci#define BH1750_ONE_TIME_H_RES_MODE 0x20 /* auto-mode for BH1721 */ 288c2ecf20Sopenharmony_ci#define BH1750_CHANGE_INT_TIME_H_BIT 0x40 298c2ecf20Sopenharmony_ci#define BH1750_CHANGE_INT_TIME_L_BIT 0x60 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_cienum { 328c2ecf20Sopenharmony_ci BH1710, 338c2ecf20Sopenharmony_ci BH1721, 348c2ecf20Sopenharmony_ci BH1750, 358c2ecf20Sopenharmony_ci}; 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_cistruct bh1750_chip_info; 388c2ecf20Sopenharmony_cistruct bh1750_data { 398c2ecf20Sopenharmony_ci struct i2c_client *client; 408c2ecf20Sopenharmony_ci struct mutex lock; 418c2ecf20Sopenharmony_ci const struct bh1750_chip_info *chip_info; 428c2ecf20Sopenharmony_ci u16 mtreg; 438c2ecf20Sopenharmony_ci}; 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_cistruct bh1750_chip_info { 468c2ecf20Sopenharmony_ci u16 mtreg_min; 478c2ecf20Sopenharmony_ci u16 mtreg_max; 488c2ecf20Sopenharmony_ci u16 mtreg_default; 498c2ecf20Sopenharmony_ci int mtreg_to_usec; 508c2ecf20Sopenharmony_ci int mtreg_to_scale; 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci /* 538c2ecf20Sopenharmony_ci * For BH1710/BH1721 all possible integration time values won't fit 548c2ecf20Sopenharmony_ci * into one page so displaying is limited to every second one. 558c2ecf20Sopenharmony_ci * Note, that user can still write proper values which were not 568c2ecf20Sopenharmony_ci * listed. 578c2ecf20Sopenharmony_ci */ 588c2ecf20Sopenharmony_ci int inc; 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_ci u16 int_time_low_mask; 618c2ecf20Sopenharmony_ci u16 int_time_high_mask; 628c2ecf20Sopenharmony_ci}; 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_cistatic const struct bh1750_chip_info bh1750_chip_info_tbl[] = { 658c2ecf20Sopenharmony_ci [BH1710] = { 140, 1022, 300, 400, 250000000, 2, 0x001F, 0x03E0 }, 668c2ecf20Sopenharmony_ci [BH1721] = { 140, 1020, 300, 400, 250000000, 2, 0x0010, 0x03E0 }, 678c2ecf20Sopenharmony_ci [BH1750] = { 31, 254, 69, 1740, 57500000, 1, 0x001F, 0x00E0 }, 688c2ecf20Sopenharmony_ci}; 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_cistatic int bh1750_change_int_time(struct bh1750_data *data, int usec) 718c2ecf20Sopenharmony_ci{ 728c2ecf20Sopenharmony_ci int ret; 738c2ecf20Sopenharmony_ci u16 val; 748c2ecf20Sopenharmony_ci u8 regval; 758c2ecf20Sopenharmony_ci const struct bh1750_chip_info *chip_info = data->chip_info; 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci if ((usec % chip_info->mtreg_to_usec) != 0) 788c2ecf20Sopenharmony_ci return -EINVAL; 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ci val = usec / chip_info->mtreg_to_usec; 818c2ecf20Sopenharmony_ci if (val < chip_info->mtreg_min || val > chip_info->mtreg_max) 828c2ecf20Sopenharmony_ci return -EINVAL; 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_ci ret = i2c_smbus_write_byte(data->client, BH1750_POWER_DOWN); 858c2ecf20Sopenharmony_ci if (ret < 0) 868c2ecf20Sopenharmony_ci return ret; 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ci regval = (val & chip_info->int_time_high_mask) >> 5; 898c2ecf20Sopenharmony_ci ret = i2c_smbus_write_byte(data->client, 908c2ecf20Sopenharmony_ci BH1750_CHANGE_INT_TIME_H_BIT | regval); 918c2ecf20Sopenharmony_ci if (ret < 0) 928c2ecf20Sopenharmony_ci return ret; 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_ci regval = val & chip_info->int_time_low_mask; 958c2ecf20Sopenharmony_ci ret = i2c_smbus_write_byte(data->client, 968c2ecf20Sopenharmony_ci BH1750_CHANGE_INT_TIME_L_BIT | regval); 978c2ecf20Sopenharmony_ci if (ret < 0) 988c2ecf20Sopenharmony_ci return ret; 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_ci data->mtreg = val; 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_ci return 0; 1038c2ecf20Sopenharmony_ci} 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_cistatic int bh1750_read(struct bh1750_data *data, int *val) 1068c2ecf20Sopenharmony_ci{ 1078c2ecf20Sopenharmony_ci int ret; 1088c2ecf20Sopenharmony_ci __be16 result; 1098c2ecf20Sopenharmony_ci const struct bh1750_chip_info *chip_info = data->chip_info; 1108c2ecf20Sopenharmony_ci unsigned long delay = chip_info->mtreg_to_usec * data->mtreg; 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci /* 1138c2ecf20Sopenharmony_ci * BH1721 will enter continuous mode on receiving this command. 1148c2ecf20Sopenharmony_ci * Note, that this eliminates need for bh1750_resume(). 1158c2ecf20Sopenharmony_ci */ 1168c2ecf20Sopenharmony_ci ret = i2c_smbus_write_byte(data->client, BH1750_ONE_TIME_H_RES_MODE); 1178c2ecf20Sopenharmony_ci if (ret < 0) 1188c2ecf20Sopenharmony_ci return ret; 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_ci usleep_range(delay + 15000, delay + 40000); 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_ci ret = i2c_master_recv(data->client, (char *)&result, 2); 1238c2ecf20Sopenharmony_ci if (ret < 0) 1248c2ecf20Sopenharmony_ci return ret; 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_ci *val = be16_to_cpu(result); 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci return 0; 1298c2ecf20Sopenharmony_ci} 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_cistatic int bh1750_read_raw(struct iio_dev *indio_dev, 1328c2ecf20Sopenharmony_ci struct iio_chan_spec const *chan, 1338c2ecf20Sopenharmony_ci int *val, int *val2, long mask) 1348c2ecf20Sopenharmony_ci{ 1358c2ecf20Sopenharmony_ci int ret, tmp; 1368c2ecf20Sopenharmony_ci struct bh1750_data *data = iio_priv(indio_dev); 1378c2ecf20Sopenharmony_ci const struct bh1750_chip_info *chip_info = data->chip_info; 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_ci switch (mask) { 1408c2ecf20Sopenharmony_ci case IIO_CHAN_INFO_RAW: 1418c2ecf20Sopenharmony_ci switch (chan->type) { 1428c2ecf20Sopenharmony_ci case IIO_LIGHT: 1438c2ecf20Sopenharmony_ci mutex_lock(&data->lock); 1448c2ecf20Sopenharmony_ci ret = bh1750_read(data, val); 1458c2ecf20Sopenharmony_ci mutex_unlock(&data->lock); 1468c2ecf20Sopenharmony_ci if (ret < 0) 1478c2ecf20Sopenharmony_ci return ret; 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_ci return IIO_VAL_INT; 1508c2ecf20Sopenharmony_ci default: 1518c2ecf20Sopenharmony_ci return -EINVAL; 1528c2ecf20Sopenharmony_ci } 1538c2ecf20Sopenharmony_ci case IIO_CHAN_INFO_SCALE: 1548c2ecf20Sopenharmony_ci tmp = chip_info->mtreg_to_scale / data->mtreg; 1558c2ecf20Sopenharmony_ci *val = tmp / 1000000; 1568c2ecf20Sopenharmony_ci *val2 = tmp % 1000000; 1578c2ecf20Sopenharmony_ci return IIO_VAL_INT_PLUS_MICRO; 1588c2ecf20Sopenharmony_ci case IIO_CHAN_INFO_INT_TIME: 1598c2ecf20Sopenharmony_ci *val = 0; 1608c2ecf20Sopenharmony_ci *val2 = chip_info->mtreg_to_usec * data->mtreg; 1618c2ecf20Sopenharmony_ci return IIO_VAL_INT_PLUS_MICRO; 1628c2ecf20Sopenharmony_ci default: 1638c2ecf20Sopenharmony_ci return -EINVAL; 1648c2ecf20Sopenharmony_ci } 1658c2ecf20Sopenharmony_ci} 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_cistatic int bh1750_write_raw(struct iio_dev *indio_dev, 1688c2ecf20Sopenharmony_ci struct iio_chan_spec const *chan, 1698c2ecf20Sopenharmony_ci int val, int val2, long mask) 1708c2ecf20Sopenharmony_ci{ 1718c2ecf20Sopenharmony_ci int ret; 1728c2ecf20Sopenharmony_ci struct bh1750_data *data = iio_priv(indio_dev); 1738c2ecf20Sopenharmony_ci 1748c2ecf20Sopenharmony_ci switch (mask) { 1758c2ecf20Sopenharmony_ci case IIO_CHAN_INFO_INT_TIME: 1768c2ecf20Sopenharmony_ci if (val != 0) 1778c2ecf20Sopenharmony_ci return -EINVAL; 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_ci mutex_lock(&data->lock); 1808c2ecf20Sopenharmony_ci ret = bh1750_change_int_time(data, val2); 1818c2ecf20Sopenharmony_ci mutex_unlock(&data->lock); 1828c2ecf20Sopenharmony_ci return ret; 1838c2ecf20Sopenharmony_ci default: 1848c2ecf20Sopenharmony_ci return -EINVAL; 1858c2ecf20Sopenharmony_ci } 1868c2ecf20Sopenharmony_ci} 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_cistatic ssize_t bh1750_show_int_time_available(struct device *dev, 1898c2ecf20Sopenharmony_ci struct device_attribute *attr, char *buf) 1908c2ecf20Sopenharmony_ci{ 1918c2ecf20Sopenharmony_ci int i; 1928c2ecf20Sopenharmony_ci size_t len = 0; 1938c2ecf20Sopenharmony_ci struct bh1750_data *data = iio_priv(dev_to_iio_dev(dev)); 1948c2ecf20Sopenharmony_ci const struct bh1750_chip_info *chip_info = data->chip_info; 1958c2ecf20Sopenharmony_ci 1968c2ecf20Sopenharmony_ci for (i = chip_info->mtreg_min; i <= chip_info->mtreg_max; i += chip_info->inc) 1978c2ecf20Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE - len, "0.%06d ", 1988c2ecf20Sopenharmony_ci chip_info->mtreg_to_usec * i); 1998c2ecf20Sopenharmony_ci 2008c2ecf20Sopenharmony_ci buf[len - 1] = '\n'; 2018c2ecf20Sopenharmony_ci 2028c2ecf20Sopenharmony_ci return len; 2038c2ecf20Sopenharmony_ci} 2048c2ecf20Sopenharmony_ci 2058c2ecf20Sopenharmony_cistatic IIO_DEV_ATTR_INT_TIME_AVAIL(bh1750_show_int_time_available); 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_cistatic struct attribute *bh1750_attributes[] = { 2088c2ecf20Sopenharmony_ci &iio_dev_attr_integration_time_available.dev_attr.attr, 2098c2ecf20Sopenharmony_ci NULL, 2108c2ecf20Sopenharmony_ci}; 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_cistatic const struct attribute_group bh1750_attribute_group = { 2138c2ecf20Sopenharmony_ci .attrs = bh1750_attributes, 2148c2ecf20Sopenharmony_ci}; 2158c2ecf20Sopenharmony_ci 2168c2ecf20Sopenharmony_cistatic const struct iio_info bh1750_info = { 2178c2ecf20Sopenharmony_ci .attrs = &bh1750_attribute_group, 2188c2ecf20Sopenharmony_ci .read_raw = bh1750_read_raw, 2198c2ecf20Sopenharmony_ci .write_raw = bh1750_write_raw, 2208c2ecf20Sopenharmony_ci}; 2218c2ecf20Sopenharmony_ci 2228c2ecf20Sopenharmony_cistatic const struct iio_chan_spec bh1750_channels[] = { 2238c2ecf20Sopenharmony_ci { 2248c2ecf20Sopenharmony_ci .type = IIO_LIGHT, 2258c2ecf20Sopenharmony_ci .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | 2268c2ecf20Sopenharmony_ci BIT(IIO_CHAN_INFO_SCALE) | 2278c2ecf20Sopenharmony_ci BIT(IIO_CHAN_INFO_INT_TIME) 2288c2ecf20Sopenharmony_ci } 2298c2ecf20Sopenharmony_ci}; 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_cistatic int bh1750_probe(struct i2c_client *client, 2328c2ecf20Sopenharmony_ci const struct i2c_device_id *id) 2338c2ecf20Sopenharmony_ci{ 2348c2ecf20Sopenharmony_ci int ret, usec; 2358c2ecf20Sopenharmony_ci struct bh1750_data *data; 2368c2ecf20Sopenharmony_ci struct iio_dev *indio_dev; 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_ci if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C | 2398c2ecf20Sopenharmony_ci I2C_FUNC_SMBUS_WRITE_BYTE)) 2408c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 2418c2ecf20Sopenharmony_ci 2428c2ecf20Sopenharmony_ci indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); 2438c2ecf20Sopenharmony_ci if (!indio_dev) 2448c2ecf20Sopenharmony_ci return -ENOMEM; 2458c2ecf20Sopenharmony_ci 2468c2ecf20Sopenharmony_ci data = iio_priv(indio_dev); 2478c2ecf20Sopenharmony_ci i2c_set_clientdata(client, indio_dev); 2488c2ecf20Sopenharmony_ci data->client = client; 2498c2ecf20Sopenharmony_ci data->chip_info = &bh1750_chip_info_tbl[id->driver_data]; 2508c2ecf20Sopenharmony_ci 2518c2ecf20Sopenharmony_ci usec = data->chip_info->mtreg_to_usec * data->chip_info->mtreg_default; 2528c2ecf20Sopenharmony_ci ret = bh1750_change_int_time(data, usec); 2538c2ecf20Sopenharmony_ci if (ret < 0) 2548c2ecf20Sopenharmony_ci return ret; 2558c2ecf20Sopenharmony_ci 2568c2ecf20Sopenharmony_ci mutex_init(&data->lock); 2578c2ecf20Sopenharmony_ci indio_dev->info = &bh1750_info; 2588c2ecf20Sopenharmony_ci indio_dev->name = id->name; 2598c2ecf20Sopenharmony_ci indio_dev->channels = bh1750_channels; 2608c2ecf20Sopenharmony_ci indio_dev->num_channels = ARRAY_SIZE(bh1750_channels); 2618c2ecf20Sopenharmony_ci indio_dev->modes = INDIO_DIRECT_MODE; 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_ci return iio_device_register(indio_dev); 2648c2ecf20Sopenharmony_ci} 2658c2ecf20Sopenharmony_ci 2668c2ecf20Sopenharmony_cistatic int bh1750_remove(struct i2c_client *client) 2678c2ecf20Sopenharmony_ci{ 2688c2ecf20Sopenharmony_ci struct iio_dev *indio_dev = i2c_get_clientdata(client); 2698c2ecf20Sopenharmony_ci struct bh1750_data *data = iio_priv(indio_dev); 2708c2ecf20Sopenharmony_ci 2718c2ecf20Sopenharmony_ci iio_device_unregister(indio_dev); 2728c2ecf20Sopenharmony_ci 2738c2ecf20Sopenharmony_ci mutex_lock(&data->lock); 2748c2ecf20Sopenharmony_ci i2c_smbus_write_byte(client, BH1750_POWER_DOWN); 2758c2ecf20Sopenharmony_ci mutex_unlock(&data->lock); 2768c2ecf20Sopenharmony_ci 2778c2ecf20Sopenharmony_ci return 0; 2788c2ecf20Sopenharmony_ci} 2798c2ecf20Sopenharmony_ci 2808c2ecf20Sopenharmony_cistatic int __maybe_unused bh1750_suspend(struct device *dev) 2818c2ecf20Sopenharmony_ci{ 2828c2ecf20Sopenharmony_ci int ret; 2838c2ecf20Sopenharmony_ci struct bh1750_data *data = 2848c2ecf20Sopenharmony_ci iio_priv(i2c_get_clientdata(to_i2c_client(dev))); 2858c2ecf20Sopenharmony_ci 2868c2ecf20Sopenharmony_ci /* 2878c2ecf20Sopenharmony_ci * This is mainly for BH1721 which doesn't enter power down 2888c2ecf20Sopenharmony_ci * mode automatically. 2898c2ecf20Sopenharmony_ci */ 2908c2ecf20Sopenharmony_ci mutex_lock(&data->lock); 2918c2ecf20Sopenharmony_ci ret = i2c_smbus_write_byte(data->client, BH1750_POWER_DOWN); 2928c2ecf20Sopenharmony_ci mutex_unlock(&data->lock); 2938c2ecf20Sopenharmony_ci 2948c2ecf20Sopenharmony_ci return ret; 2958c2ecf20Sopenharmony_ci} 2968c2ecf20Sopenharmony_ci 2978c2ecf20Sopenharmony_cistatic SIMPLE_DEV_PM_OPS(bh1750_pm_ops, bh1750_suspend, NULL); 2988c2ecf20Sopenharmony_ci 2998c2ecf20Sopenharmony_cistatic const struct i2c_device_id bh1750_id[] = { 3008c2ecf20Sopenharmony_ci { "bh1710", BH1710 }, 3018c2ecf20Sopenharmony_ci { "bh1715", BH1750 }, 3028c2ecf20Sopenharmony_ci { "bh1721", BH1721 }, 3038c2ecf20Sopenharmony_ci { "bh1750", BH1750 }, 3048c2ecf20Sopenharmony_ci { "bh1751", BH1750 }, 3058c2ecf20Sopenharmony_ci { } 3068c2ecf20Sopenharmony_ci}; 3078c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(i2c, bh1750_id); 3088c2ecf20Sopenharmony_ci 3098c2ecf20Sopenharmony_cistatic const struct of_device_id bh1750_of_match[] = { 3108c2ecf20Sopenharmony_ci { .compatible = "rohm,bh1710", }, 3118c2ecf20Sopenharmony_ci { .compatible = "rohm,bh1715", }, 3128c2ecf20Sopenharmony_ci { .compatible = "rohm,bh1721", }, 3138c2ecf20Sopenharmony_ci { .compatible = "rohm,bh1750", }, 3148c2ecf20Sopenharmony_ci { .compatible = "rohm,bh1751", }, 3158c2ecf20Sopenharmony_ci { } 3168c2ecf20Sopenharmony_ci}; 3178c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, bh1750_of_match); 3188c2ecf20Sopenharmony_ci 3198c2ecf20Sopenharmony_cistatic struct i2c_driver bh1750_driver = { 3208c2ecf20Sopenharmony_ci .driver = { 3218c2ecf20Sopenharmony_ci .name = "bh1750", 3228c2ecf20Sopenharmony_ci .of_match_table = bh1750_of_match, 3238c2ecf20Sopenharmony_ci .pm = &bh1750_pm_ops, 3248c2ecf20Sopenharmony_ci }, 3258c2ecf20Sopenharmony_ci .probe = bh1750_probe, 3268c2ecf20Sopenharmony_ci .remove = bh1750_remove, 3278c2ecf20Sopenharmony_ci .id_table = bh1750_id, 3288c2ecf20Sopenharmony_ci 3298c2ecf20Sopenharmony_ci}; 3308c2ecf20Sopenharmony_cimodule_i2c_driver(bh1750_driver); 3318c2ecf20Sopenharmony_ci 3328c2ecf20Sopenharmony_ciMODULE_AUTHOR("Tomasz Duszynski <tduszyns@gmail.com>"); 3338c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("ROHM BH1710/BH1715/BH1721/BH1750/BH1751 als driver"); 3348c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2"); 335