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 data->reg_conf = ret; 93 94 ret = i2c_smbus_write_word_data(data->client, CM3323_CMD_CONF, data->reg_conf); 95 if (ret < 0) { 96 dev_err(&data->client->dev, "Error writing reg_conf\n"); 97 return ret; 98 } 99 100 return 0; 101 } 102 103 static void cm3323_disable(void *data) 104 { 105 int ret; 106 struct iio_dev *indio_dev = data; 107 struct cm3323_data *cm_data = iio_priv(indio_dev); 108 109 ret = i2c_smbus_write_word_data(cm_data->client, CM3323_CMD_CONF, 110 CM3323_CONF_SD_BIT); 111 if (ret < 0) 112 dev_err(&cm_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 { 218 struct cm3323_data *data; 219 struct iio_dev *indio_dev; 220 int ret; 221 222 indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); 223 if (!indio_dev) 224 return -ENOMEM; 225 226 data = iio_priv(indio_dev); 227 i2c_set_clientdata(client, indio_dev); 228 data->client = client; 229 230 mutex_init(&data->mutex); 231 232 indio_dev->info = &cm3323_info; 233 indio_dev->name = CM3323_DRV_NAME; 234 indio_dev->channels = cm3323_channels; 235 indio_dev->num_channels = ARRAY_SIZE(cm3323_channels); 236 indio_dev->modes = INDIO_DIRECT_MODE; 237 238 ret = cm3323_init(indio_dev); 239 if (ret < 0) { 240 dev_err(&client->dev, "cm3323 chip init failed\n"); 241 return ret; 242 } 243 244 ret = devm_add_action_or_reset(&client->dev, cm3323_disable, indio_dev); 245 if (ret < 0) 246 return ret; 247 248 return devm_iio_device_register(&client->dev, indio_dev); 249 } 250 251 static const struct i2c_device_id cm3323_id[] = { 252 { "cm3323" }, 253 { } 254 }; 255 MODULE_DEVICE_TABLE(i2c, cm3323_id); 256 257 static const struct of_device_id cm3323_of_match[] = { 258 { .compatible = "capella,cm3323", }, 259 { } 260 }; 261 MODULE_DEVICE_TABLE(of, cm3323_of_match); 262 263 static struct i2c_driver cm3323_driver = { 264 .driver = { 265 .name = CM3323_DRV_NAME, 266 .of_match_table = cm3323_of_match, 267 }, 268 .probe = cm3323_probe, 269 .id_table = cm3323_id, 270 }; 271 272 module_i2c_driver(cm3323_driver); 273 274 MODULE_AUTHOR("Daniel Baluta <daniel.baluta@intel.com>"); 275 MODULE_DESCRIPTION("Capella CM3323 Color Light Sensor driver"); 276 MODULE_LICENSE("GPL v2"); 277