1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * CM3323 - Capella Color Light Sensor 4 * 5 * Copyright (c) 2015, Intel Corporation. 6 * 7 * IIO driver for CM3323 (7-bit I2C slave address 0x10) 8 * 9 * TODO: calibscale to correct the lens factor 10 */ 11 #include <linux/module.h> 12 #include <linux/init.h> 13 #include <linux/i2c.h> 14 #include <linux/mutex.h> 15 16 #include <linux/iio/iio.h> 17 #include <linux/iio/sysfs.h> 18 19 #define CM3323_DRV_NAME "cm3323" 20 21 #define CM3323_CMD_CONF 0x00 22 #define CM3323_CMD_RED_DATA 0x08 23 #define CM3323_CMD_GREEN_DATA 0x09 24 #define CM3323_CMD_BLUE_DATA 0x0A 25 #define CM3323_CMD_CLEAR_DATA 0x0B 26 27 #define CM3323_CONF_SD_BIT BIT(0) /* sensor disable */ 28 #define CM3323_CONF_AF_BIT BIT(1) /* auto/manual force mode */ 29 #define CM3323_CONF_IT_MASK GENMASK(6, 4) 30 #define CM3323_CONF_IT_SHIFT 4 31 32 #define CM3323_INT_TIME_AVAILABLE "0.04 0.08 0.16 0.32 0.64 1.28" 33 34 static const struct { 35 int val; 36 int val2; 37 } cm3323_int_time[] = { 38 {0, 40000}, /* 40 ms */ 39 {0, 80000}, /* 80 ms */ 40 {0, 160000}, /* 160 ms */ 41 {0, 320000}, /* 320 ms */ 42 {0, 640000}, /* 640 ms */ 43 {1, 280000}, /* 1280 ms */ 44 }; 45 46 struct cm3323_data { 47 struct i2c_client *client; 48 u16 reg_conf; 49 struct mutex mutex; 50 }; 51 52 #define CM3323_COLOR_CHANNEL(_color, _addr) { \ 53 .type = IIO_INTENSITY, \ 54 .modified = 1, \ 55 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ 56 .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_INT_TIME), \ 57 .channel2 = IIO_MOD_LIGHT_##_color, \ 58 .address = _addr, \ 59 } 60 61 static const struct iio_chan_spec cm3323_channels[] = { 62 CM3323_COLOR_CHANNEL(RED, CM3323_CMD_RED_DATA), 63 CM3323_COLOR_CHANNEL(GREEN, CM3323_CMD_GREEN_DATA), 64 CM3323_COLOR_CHANNEL(BLUE, CM3323_CMD_BLUE_DATA), 65 CM3323_COLOR_CHANNEL(CLEAR, CM3323_CMD_CLEAR_DATA), 66 }; 67 68 static IIO_CONST_ATTR_INT_TIME_AVAIL(CM3323_INT_TIME_AVAILABLE); 69 70 static struct attribute *cm3323_attributes[] = { 71 &iio_const_attr_integration_time_available.dev_attr.attr, 72 NULL 73 }; 74 75 static const struct attribute_group cm3323_attribute_group = { 76 .attrs = cm3323_attributes, 77 }; 78 79 static int cm3323_init(struct iio_dev *indio_dev) 80 { 81 int ret; 82 struct cm3323_data *data = iio_priv(indio_dev); 83 84 ret = i2c_smbus_read_word_data(data->client, CM3323_CMD_CONF); 85 if (ret < 0) { 86 dev_err(&data->client->dev, "Error reading reg_conf\n"); 87 return ret; 88 } 89 90 /* enable sensor and set auto force mode */ 91 ret &= ~(CM3323_CONF_SD_BIT | CM3323_CONF_AF_BIT); 92 93 ret = i2c_smbus_write_word_data(data->client, CM3323_CMD_CONF, ret); 94 if (ret < 0) { 95 dev_err(&data->client->dev, "Error writing reg_conf\n"); 96 return ret; 97 } 98 99 data->reg_conf = ret; 100 101 return 0; 102 } 103 104 static void cm3323_disable(struct iio_dev *indio_dev) 105 { 106 int ret; 107 struct cm3323_data *data = iio_priv(indio_dev); 108 109 ret = i2c_smbus_write_word_data(data->client, CM3323_CMD_CONF, 110 CM3323_CONF_SD_BIT); 111 if (ret < 0) 112 dev_err(&data->client->dev, "Error writing reg_conf\n"); 113 } 114 115 static int cm3323_set_it_bits(struct cm3323_data *data, int val, int val2) 116 { 117 int i, ret; 118 u16 reg_conf; 119 120 for (i = 0; i < ARRAY_SIZE(cm3323_int_time); i++) { 121 if (val == cm3323_int_time[i].val && 122 val2 == cm3323_int_time[i].val2) { 123 reg_conf = data->reg_conf & ~CM3323_CONF_IT_MASK; 124 reg_conf |= i << CM3323_CONF_IT_SHIFT; 125 126 ret = i2c_smbus_write_word_data(data->client, 127 CM3323_CMD_CONF, 128 reg_conf); 129 if (ret < 0) 130 return ret; 131 132 data->reg_conf = reg_conf; 133 134 return 0; 135 } 136 } 137 138 return -EINVAL; 139 } 140 141 static int cm3323_get_it_bits(struct cm3323_data *data) 142 { 143 int bits; 144 145 bits = (data->reg_conf & CM3323_CONF_IT_MASK) >> 146 CM3323_CONF_IT_SHIFT; 147 148 if (bits >= ARRAY_SIZE(cm3323_int_time)) 149 return -EINVAL; 150 151 return bits; 152 } 153 154 static int cm3323_read_raw(struct iio_dev *indio_dev, 155 struct iio_chan_spec const *chan, int *val, 156 int *val2, long mask) 157 { 158 int ret; 159 struct cm3323_data *data = iio_priv(indio_dev); 160 161 switch (mask) { 162 case IIO_CHAN_INFO_RAW: 163 mutex_lock(&data->mutex); 164 ret = i2c_smbus_read_word_data(data->client, chan->address); 165 if (ret < 0) { 166 mutex_unlock(&data->mutex); 167 return ret; 168 } 169 *val = ret; 170 mutex_unlock(&data->mutex); 171 172 return IIO_VAL_INT; 173 case IIO_CHAN_INFO_INT_TIME: 174 mutex_lock(&data->mutex); 175 ret = cm3323_get_it_bits(data); 176 if (ret < 0) { 177 mutex_unlock(&data->mutex); 178 return ret; 179 } 180 181 *val = cm3323_int_time[ret].val; 182 *val2 = cm3323_int_time[ret].val2; 183 mutex_unlock(&data->mutex); 184 185 return IIO_VAL_INT_PLUS_MICRO; 186 default: 187 return -EINVAL; 188 } 189 } 190 191 static int cm3323_write_raw(struct iio_dev *indio_dev, 192 struct iio_chan_spec const *chan, int val, 193 int val2, long mask) 194 { 195 struct cm3323_data *data = iio_priv(indio_dev); 196 int ret; 197 198 switch (mask) { 199 case IIO_CHAN_INFO_INT_TIME: 200 mutex_lock(&data->mutex); 201 ret = cm3323_set_it_bits(data, val, val2); 202 mutex_unlock(&data->mutex); 203 204 return ret; 205 default: 206 return -EINVAL; 207 } 208 } 209 210 static const struct iio_info cm3323_info = { 211 .read_raw = cm3323_read_raw, 212 .write_raw = cm3323_write_raw, 213 .attrs = &cm3323_attribute_group, 214 }; 215 216 static int cm3323_probe(struct i2c_client *client, 217 const struct i2c_device_id *id) 218 { 219 struct cm3323_data *data; 220 struct iio_dev *indio_dev; 221 int ret; 222 223 indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); 224 if (!indio_dev) 225 return -ENOMEM; 226 227 data = iio_priv(indio_dev); 228 i2c_set_clientdata(client, indio_dev); 229 data->client = client; 230 231 mutex_init(&data->mutex); 232 233 indio_dev->dev.parent = &client->dev; 234 indio_dev->info = &cm3323_info; 235 indio_dev->name = CM3323_DRV_NAME; 236 indio_dev->channels = cm3323_channels; 237 indio_dev->num_channels = ARRAY_SIZE(cm3323_channels); 238 indio_dev->modes = INDIO_DIRECT_MODE; 239 240 ret = cm3323_init(indio_dev); 241 if (ret < 0) { 242 dev_err(&client->dev, "cm3323 chip init failed\n"); 243 return ret; 244 } 245 246 ret = iio_device_register(indio_dev); 247 if (ret < 0) { 248 dev_err(&client->dev, "failed to register iio dev\n"); 249 goto err_init; 250 } 251 252 return 0; 253 err_init: 254 cm3323_disable(indio_dev); 255 return ret; 256 } 257 258 static int cm3323_remove(struct i2c_client *client) 259 { 260 struct iio_dev *indio_dev = i2c_get_clientdata(client); 261 262 iio_device_unregister(indio_dev); 263 cm3323_disable(indio_dev); 264 265 return 0; 266 } 267 268 static const struct i2c_device_id cm3323_id[] = { 269 {"cm3323", 0}, 270 {} 271 }; 272 MODULE_DEVICE_TABLE(i2c, cm3323_id); 273 274 static struct i2c_driver cm3323_driver = { 275 .driver = { 276 .name = CM3323_DRV_NAME, 277 }, 278 .probe = cm3323_probe, 279 .remove = cm3323_remove, 280 .id_table = cm3323_id, 281 }; 282 283 module_i2c_driver(cm3323_driver); 284 285 MODULE_AUTHOR("Daniel Baluta <daniel.baluta@intel.com>"); 286 MODULE_DESCRIPTION("Capella CM3323 Color Light Sensor driver"); 287 MODULE_LICENSE("GPL v2"); 288