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 struct device *dev = &data->client->dev; 84 85 ret = i2c_smbus_read_word_data(data->client, CM3323_CMD_CONF); 86 if (ret < 0) 87 return dev_err_probe(dev, ret, "Error reading reg_conf\n"); 88 89 /* enable sensor and set auto force mode */ 90 ret &= ~(CM3323_CONF_SD_BIT | CM3323_CONF_AF_BIT); 91 data->reg_conf = ret; 92 93 ret = i2c_smbus_write_word_data(data->client, CM3323_CMD_CONF, data->reg_conf); 94 if (ret < 0) 95 return dev_err_probe(dev, ret, "Error writing reg_conf\n"); 96 97 return 0; 98 } 99 100 static void cm3323_disable(void *data) 101 { 102 int ret; 103 struct iio_dev *indio_dev = data; 104 struct cm3323_data *cm_data = iio_priv(indio_dev); 105 106 ret = i2c_smbus_write_word_data(cm_data->client, CM3323_CMD_CONF, 107 CM3323_CONF_SD_BIT); 108 if (ret < 0) 109 dev_err(&cm_data->client->dev, "Error writing reg_conf\n"); 110 } 111 112 static int cm3323_set_it_bits(struct cm3323_data *data, int val, int val2) 113 { 114 int i, ret; 115 u16 reg_conf; 116 117 for (i = 0; i < ARRAY_SIZE(cm3323_int_time); i++) { 118 if (val == cm3323_int_time[i].val && 119 val2 == cm3323_int_time[i].val2) { 120 reg_conf = data->reg_conf & ~CM3323_CONF_IT_MASK; 121 reg_conf |= i << CM3323_CONF_IT_SHIFT; 122 123 ret = i2c_smbus_write_word_data(data->client, 124 CM3323_CMD_CONF, 125 reg_conf); 126 if (ret < 0) 127 return ret; 128 129 data->reg_conf = reg_conf; 130 131 return 0; 132 } 133 } 134 135 return -EINVAL; 136 } 137 138 static int cm3323_get_it_bits(struct cm3323_data *data) 139 { 140 int bits; 141 142 bits = (data->reg_conf & CM3323_CONF_IT_MASK) >> 143 CM3323_CONF_IT_SHIFT; 144 145 if (bits >= ARRAY_SIZE(cm3323_int_time)) 146 return -EINVAL; 147 148 return bits; 149 } 150 151 static int cm3323_read_raw(struct iio_dev *indio_dev, 152 struct iio_chan_spec const *chan, int *val, 153 int *val2, long mask) 154 { 155 int ret; 156 struct cm3323_data *data = iio_priv(indio_dev); 157 158 switch (mask) { 159 case IIO_CHAN_INFO_RAW: 160 mutex_lock(&data->mutex); 161 ret = i2c_smbus_read_word_data(data->client, chan->address); 162 if (ret < 0) { 163 mutex_unlock(&data->mutex); 164 return ret; 165 } 166 *val = ret; 167 mutex_unlock(&data->mutex); 168 169 return IIO_VAL_INT; 170 case IIO_CHAN_INFO_INT_TIME: 171 mutex_lock(&data->mutex); 172 ret = cm3323_get_it_bits(data); 173 if (ret < 0) { 174 mutex_unlock(&data->mutex); 175 return ret; 176 } 177 178 *val = cm3323_int_time[ret].val; 179 *val2 = cm3323_int_time[ret].val2; 180 mutex_unlock(&data->mutex); 181 182 return IIO_VAL_INT_PLUS_MICRO; 183 default: 184 return -EINVAL; 185 } 186 } 187 188 static int cm3323_write_raw(struct iio_dev *indio_dev, 189 struct iio_chan_spec const *chan, int val, 190 int val2, long mask) 191 { 192 struct cm3323_data *data = iio_priv(indio_dev); 193 int ret; 194 195 switch (mask) { 196 case IIO_CHAN_INFO_INT_TIME: 197 mutex_lock(&data->mutex); 198 ret = cm3323_set_it_bits(data, val, val2); 199 mutex_unlock(&data->mutex); 200 201 return ret; 202 default: 203 return -EINVAL; 204 } 205 } 206 207 static const struct iio_info cm3323_info = { 208 .read_raw = cm3323_read_raw, 209 .write_raw = cm3323_write_raw, 210 .attrs = &cm3323_attribute_group, 211 }; 212 213 static int cm3323_probe(struct i2c_client *client) 214 { 215 struct cm3323_data *data; 216 struct iio_dev *indio_dev; 217 int ret; 218 219 indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); 220 if (!indio_dev) 221 return -ENOMEM; 222 223 data = iio_priv(indio_dev); 224 i2c_set_clientdata(client, indio_dev); 225 data->client = client; 226 227 mutex_init(&data->mutex); 228 229 indio_dev->info = &cm3323_info; 230 indio_dev->name = CM3323_DRV_NAME; 231 indio_dev->channels = cm3323_channels; 232 indio_dev->num_channels = ARRAY_SIZE(cm3323_channels); 233 indio_dev->modes = INDIO_DIRECT_MODE; 234 235 ret = cm3323_init(indio_dev); 236 if (ret < 0) 237 return ret; 238 239 ret = devm_add_action_or_reset(&client->dev, cm3323_disable, indio_dev); 240 if (ret < 0) 241 return ret; 242 243 return devm_iio_device_register(&client->dev, indio_dev); 244 } 245 246 static const struct i2c_device_id cm3323_id[] = { 247 { .name = "cm3323" }, 248 { } 249 }; 250 MODULE_DEVICE_TABLE(i2c, cm3323_id); 251 252 static const struct of_device_id cm3323_of_match[] = { 253 { .compatible = "capella,cm3323", }, 254 { } 255 }; 256 MODULE_DEVICE_TABLE(of, cm3323_of_match); 257 258 static struct i2c_driver cm3323_driver = { 259 .driver = { 260 .name = CM3323_DRV_NAME, 261 .of_match_table = cm3323_of_match, 262 }, 263 .probe = cm3323_probe, 264 .id_table = cm3323_id, 265 }; 266 267 module_i2c_driver(cm3323_driver); 268 269 MODULE_AUTHOR("Daniel Baluta <daniel.baluta@intel.com>"); 270 MODULE_DESCRIPTION("Capella CM3323 Color Light Sensor driver"); 271 MODULE_LICENSE("GPL v2"); 272