1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * ROHM 1780GLI Ambient Light Sensor Driver 4 * 5 * Copyright (C) 2016 Linaro Ltd. 6 * Author: Linus Walleij <linus.walleij@linaro.org> 7 * Loosely based on the previous BH1780 ALS misc driver 8 * Copyright (C) 2010 Texas Instruments 9 * Author: Hemanth V <hemanthv@ti.com> 10 */ 11 #include <linux/i2c.h> 12 #include <linux/slab.h> 13 #include <linux/platform_device.h> 14 #include <linux/delay.h> 15 #include <linux/module.h> 16 #include <linux/mod_devicetable.h> 17 #include <linux/pm_runtime.h> 18 #include <linux/iio/iio.h> 19 #include <linux/iio/sysfs.h> 20 #include <linux/bitops.h> 21 22 #define BH1780_CMD_BIT BIT(7) 23 #define BH1780_REG_CONTROL 0x00 24 #define BH1780_REG_PARTID 0x0A 25 #define BH1780_REG_MANFID 0x0B 26 #define BH1780_REG_DLOW 0x0C 27 #define BH1780_REG_DHIGH 0x0D 28 29 #define BH1780_REVMASK GENMASK(3,0) 30 #define BH1780_POWMASK GENMASK(1,0) 31 #define BH1780_POFF (0x0) 32 #define BH1780_PON (0x3) 33 34 /* power on settling time in ms */ 35 #define BH1780_PON_DELAY 2 36 /* max time before value available in ms */ 37 #define BH1780_INTERVAL 250 38 39 struct bh1780_data { 40 struct i2c_client *client; 41 }; 42 43 static int bh1780_write(struct bh1780_data *bh1780, u8 reg, u8 val) 44 { 45 int ret = i2c_smbus_write_byte_data(bh1780->client, 46 BH1780_CMD_BIT | reg, 47 val); 48 if (ret < 0) 49 dev_err(&bh1780->client->dev, 50 "i2c_smbus_write_byte_data failed error " 51 "%d, register %01x\n", 52 ret, reg); 53 return ret; 54 } 55 56 static int bh1780_read(struct bh1780_data *bh1780, u8 reg) 57 { 58 int ret = i2c_smbus_read_byte_data(bh1780->client, 59 BH1780_CMD_BIT | reg); 60 if (ret < 0) 61 dev_err(&bh1780->client->dev, 62 "i2c_smbus_read_byte_data failed error " 63 "%d, register %01x\n", 64 ret, reg); 65 return ret; 66 } 67 68 static int bh1780_read_word(struct bh1780_data *bh1780, u8 reg) 69 { 70 int ret = i2c_smbus_read_word_data(bh1780->client, 71 BH1780_CMD_BIT | reg); 72 if (ret < 0) 73 dev_err(&bh1780->client->dev, 74 "i2c_smbus_read_word_data failed error " 75 "%d, register %01x\n", 76 ret, reg); 77 return ret; 78 } 79 80 static int bh1780_debugfs_reg_access(struct iio_dev *indio_dev, 81 unsigned int reg, unsigned int writeval, 82 unsigned int *readval) 83 { 84 struct bh1780_data *bh1780 = iio_priv(indio_dev); 85 int ret; 86 87 if (!readval) 88 return bh1780_write(bh1780, (u8)reg, (u8)writeval); 89 90 ret = bh1780_read(bh1780, (u8)reg); 91 if (ret < 0) 92 return ret; 93 94 *readval = ret; 95 96 return 0; 97 } 98 99 static int bh1780_read_raw(struct iio_dev *indio_dev, 100 struct iio_chan_spec const *chan, 101 int *val, int *val2, long mask) 102 { 103 struct bh1780_data *bh1780 = iio_priv(indio_dev); 104 int value; 105 106 switch (mask) { 107 case IIO_CHAN_INFO_RAW: 108 switch (chan->type) { 109 case IIO_LIGHT: 110 pm_runtime_get_sync(&bh1780->client->dev); 111 value = bh1780_read_word(bh1780, BH1780_REG_DLOW); 112 if (value < 0) 113 return value; 114 pm_runtime_mark_last_busy(&bh1780->client->dev); 115 pm_runtime_put_autosuspend(&bh1780->client->dev); 116 *val = value; 117 118 return IIO_VAL_INT; 119 default: 120 return -EINVAL; 121 } 122 case IIO_CHAN_INFO_INT_TIME: 123 *val = 0; 124 *val2 = BH1780_INTERVAL * 1000; 125 return IIO_VAL_INT_PLUS_MICRO; 126 default: 127 return -EINVAL; 128 } 129 } 130 131 static const struct iio_info bh1780_info = { 132 .read_raw = bh1780_read_raw, 133 .debugfs_reg_access = bh1780_debugfs_reg_access, 134 }; 135 136 static const struct iio_chan_spec bh1780_channels[] = { 137 { 138 .type = IIO_LIGHT, 139 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | 140 BIT(IIO_CHAN_INFO_INT_TIME) 141 } 142 }; 143 144 static int bh1780_probe(struct i2c_client *client) 145 { 146 int ret; 147 struct bh1780_data *bh1780; 148 struct i2c_adapter *adapter = client->adapter; 149 struct iio_dev *indio_dev; 150 151 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE)) 152 return -EIO; 153 154 indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*bh1780)); 155 if (!indio_dev) 156 return -ENOMEM; 157 158 bh1780 = iio_priv(indio_dev); 159 bh1780->client = client; 160 i2c_set_clientdata(client, indio_dev); 161 162 /* Power up the device */ 163 ret = bh1780_write(bh1780, BH1780_REG_CONTROL, BH1780_PON); 164 if (ret < 0) 165 return ret; 166 msleep(BH1780_PON_DELAY); 167 pm_runtime_get_noresume(&client->dev); 168 pm_runtime_set_active(&client->dev); 169 pm_runtime_enable(&client->dev); 170 171 ret = bh1780_read(bh1780, BH1780_REG_PARTID); 172 if (ret < 0) 173 goto out_disable_pm; 174 dev_info(&client->dev, 175 "Ambient Light Sensor, Rev : %lu\n", 176 (ret & BH1780_REVMASK)); 177 178 /* 179 * As the device takes 250 ms to even come up with a fresh 180 * measurement after power-on, do not shut it down unnecessarily. 181 * Set autosuspend to a five seconds. 182 */ 183 pm_runtime_set_autosuspend_delay(&client->dev, 5000); 184 pm_runtime_use_autosuspend(&client->dev); 185 pm_runtime_put(&client->dev); 186 187 indio_dev->info = &bh1780_info; 188 indio_dev->name = "bh1780"; 189 indio_dev->channels = bh1780_channels; 190 indio_dev->num_channels = ARRAY_SIZE(bh1780_channels); 191 indio_dev->modes = INDIO_DIRECT_MODE; 192 193 ret = iio_device_register(indio_dev); 194 if (ret) 195 goto out_disable_pm; 196 return 0; 197 198 out_disable_pm: 199 pm_runtime_put_noidle(&client->dev); 200 pm_runtime_disable(&client->dev); 201 return ret; 202 } 203 204 static void bh1780_remove(struct i2c_client *client) 205 { 206 struct iio_dev *indio_dev = i2c_get_clientdata(client); 207 struct bh1780_data *bh1780 = iio_priv(indio_dev); 208 int ret; 209 210 iio_device_unregister(indio_dev); 211 pm_runtime_get_sync(&client->dev); 212 pm_runtime_put_noidle(&client->dev); 213 pm_runtime_disable(&client->dev); 214 ret = bh1780_write(bh1780, BH1780_REG_CONTROL, BH1780_POFF); 215 if (ret < 0) 216 dev_err(&client->dev, "failed to power off (%pe)\n", 217 ERR_PTR(ret)); 218 } 219 220 static int bh1780_runtime_suspend(struct device *dev) 221 { 222 struct i2c_client *client = to_i2c_client(dev); 223 struct iio_dev *indio_dev = i2c_get_clientdata(client); 224 struct bh1780_data *bh1780 = iio_priv(indio_dev); 225 int ret; 226 227 ret = bh1780_write(bh1780, BH1780_REG_CONTROL, BH1780_POFF); 228 if (ret < 0) { 229 dev_err(dev, "failed to runtime suspend\n"); 230 return ret; 231 } 232 233 return 0; 234 } 235 236 static int bh1780_runtime_resume(struct device *dev) 237 { 238 struct i2c_client *client = to_i2c_client(dev); 239 struct iio_dev *indio_dev = i2c_get_clientdata(client); 240 struct bh1780_data *bh1780 = iio_priv(indio_dev); 241 int ret; 242 243 ret = bh1780_write(bh1780, BH1780_REG_CONTROL, BH1780_PON); 244 if (ret < 0) { 245 dev_err(dev, "failed to runtime resume\n"); 246 return ret; 247 } 248 249 /* Wait for power on, then for a value to be available */ 250 msleep(BH1780_PON_DELAY + BH1780_INTERVAL); 251 252 return 0; 253 } 254 255 static DEFINE_RUNTIME_DEV_PM_OPS(bh1780_dev_pm_ops, bh1780_runtime_suspend, 256 bh1780_runtime_resume, NULL); 257 258 static const struct i2c_device_id bh1780_id[] = { 259 { "bh1780" }, 260 { } 261 }; 262 263 MODULE_DEVICE_TABLE(i2c, bh1780_id); 264 265 static const struct of_device_id of_bh1780_match[] = { 266 { .compatible = "rohm,bh1780gli", }, 267 {}, 268 }; 269 MODULE_DEVICE_TABLE(of, of_bh1780_match); 270 271 static struct i2c_driver bh1780_driver = { 272 .probe = bh1780_probe, 273 .remove = bh1780_remove, 274 .id_table = bh1780_id, 275 .driver = { 276 .name = "bh1780", 277 .pm = pm_ptr(&bh1780_dev_pm_ops), 278 .of_match_table = of_bh1780_match, 279 }, 280 }; 281 282 module_i2c_driver(bh1780_driver); 283 284 MODULE_DESCRIPTION("ROHM BH1780GLI Ambient Light Sensor Driver"); 285 MODULE_LICENSE("GPL"); 286 MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>"); 287