0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017 #include <linux/bitfield.h>
0018 #include <linux/i2c.h>
0019 #include <linux/module.h>
0020 #include <linux/of.h>
0021
0022 #include <linux/iio/iio.h>
0023 #include <linux/iio/sysfs.h>
0024
0025 #define AL3010_DRV_NAME "al3010"
0026
0027 #define AL3010_REG_SYSTEM 0x00
0028 #define AL3010_REG_DATA_LOW 0x0c
0029 #define AL3010_REG_CONFIG 0x10
0030
0031 #define AL3010_CONFIG_DISABLE 0x00
0032 #define AL3010_CONFIG_ENABLE 0x01
0033
0034 #define AL3010_GAIN_MASK GENMASK(6,4)
0035
0036 #define AL3010_SCALE_AVAILABLE "1.1872 0.2968 0.0742 0.018"
0037
0038 enum al3xxxx_range {
0039 AL3XXX_RANGE_1,
0040 AL3XXX_RANGE_2,
0041 AL3XXX_RANGE_3,
0042 AL3XXX_RANGE_4
0043 };
0044
0045 static const int al3010_scales[][2] = {
0046 {0, 1187200}, {0, 296800}, {0, 74200}, {0, 18600}
0047 };
0048
0049 struct al3010_data {
0050 struct i2c_client *client;
0051 };
0052
0053 static const struct iio_chan_spec al3010_channels[] = {
0054 {
0055 .type = IIO_LIGHT,
0056 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
0057 BIT(IIO_CHAN_INFO_SCALE),
0058 }
0059 };
0060
0061 static IIO_CONST_ATTR(in_illuminance_scale_available, AL3010_SCALE_AVAILABLE);
0062
0063 static struct attribute *al3010_attributes[] = {
0064 &iio_const_attr_in_illuminance_scale_available.dev_attr.attr,
0065 NULL,
0066 };
0067
0068 static const struct attribute_group al3010_attribute_group = {
0069 .attrs = al3010_attributes,
0070 };
0071
0072 static int al3010_set_pwr(struct i2c_client *client, bool pwr)
0073 {
0074 u8 val = pwr ? AL3010_CONFIG_ENABLE : AL3010_CONFIG_DISABLE;
0075 return i2c_smbus_write_byte_data(client, AL3010_REG_SYSTEM, val);
0076 }
0077
0078 static void al3010_set_pwr_off(void *_data)
0079 {
0080 struct al3010_data *data = _data;
0081
0082 al3010_set_pwr(data->client, false);
0083 }
0084
0085 static int al3010_init(struct al3010_data *data)
0086 {
0087 int ret;
0088
0089 ret = al3010_set_pwr(data->client, true);
0090
0091 if (ret < 0)
0092 return ret;
0093
0094 ret = i2c_smbus_write_byte_data(data->client, AL3010_REG_CONFIG,
0095 FIELD_PREP(AL3010_GAIN_MASK,
0096 AL3XXX_RANGE_3));
0097 if (ret < 0)
0098 return ret;
0099
0100 return 0;
0101 }
0102
0103 static int al3010_read_raw(struct iio_dev *indio_dev,
0104 struct iio_chan_spec const *chan, int *val,
0105 int *val2, long mask)
0106 {
0107 struct al3010_data *data = iio_priv(indio_dev);
0108 int ret;
0109
0110 switch (mask) {
0111 case IIO_CHAN_INFO_RAW:
0112
0113
0114
0115
0116
0117 ret = i2c_smbus_read_word_data(data->client,
0118 AL3010_REG_DATA_LOW);
0119 if (ret < 0)
0120 return ret;
0121 *val = ret;
0122 return IIO_VAL_INT;
0123 case IIO_CHAN_INFO_SCALE:
0124 ret = i2c_smbus_read_byte_data(data->client,
0125 AL3010_REG_CONFIG);
0126 if (ret < 0)
0127 return ret;
0128
0129 ret = FIELD_GET(AL3010_GAIN_MASK, ret);
0130 *val = al3010_scales[ret][0];
0131 *val2 = al3010_scales[ret][1];
0132
0133 return IIO_VAL_INT_PLUS_MICRO;
0134 }
0135 return -EINVAL;
0136 }
0137
0138 static int al3010_write_raw(struct iio_dev *indio_dev,
0139 struct iio_chan_spec const *chan, int val,
0140 int val2, long mask)
0141 {
0142 struct al3010_data *data = iio_priv(indio_dev);
0143 int i;
0144
0145 switch (mask) {
0146 case IIO_CHAN_INFO_SCALE:
0147 for (i = 0; i < ARRAY_SIZE(al3010_scales); i++) {
0148 if (val != al3010_scales[i][0] ||
0149 val2 != al3010_scales[i][1])
0150 continue;
0151
0152 return i2c_smbus_write_byte_data(data->client,
0153 AL3010_REG_CONFIG,
0154 FIELD_PREP(AL3010_GAIN_MASK, i));
0155 }
0156 break;
0157 }
0158 return -EINVAL;
0159 }
0160
0161 static const struct iio_info al3010_info = {
0162 .read_raw = al3010_read_raw,
0163 .write_raw = al3010_write_raw,
0164 .attrs = &al3010_attribute_group,
0165 };
0166
0167 static int al3010_probe(struct i2c_client *client,
0168 const struct i2c_device_id *id)
0169 {
0170 struct al3010_data *data;
0171 struct iio_dev *indio_dev;
0172 int ret;
0173
0174 indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
0175 if (!indio_dev)
0176 return -ENOMEM;
0177
0178 data = iio_priv(indio_dev);
0179 i2c_set_clientdata(client, indio_dev);
0180 data->client = client;
0181
0182 indio_dev->info = &al3010_info;
0183 indio_dev->name = AL3010_DRV_NAME;
0184 indio_dev->channels = al3010_channels;
0185 indio_dev->num_channels = ARRAY_SIZE(al3010_channels);
0186 indio_dev->modes = INDIO_DIRECT_MODE;
0187
0188 ret = al3010_init(data);
0189 if (ret < 0) {
0190 dev_err(&client->dev, "al3010 chip init failed\n");
0191 return ret;
0192 }
0193
0194 ret = devm_add_action_or_reset(&client->dev,
0195 al3010_set_pwr_off,
0196 data);
0197 if (ret < 0)
0198 return ret;
0199
0200 return devm_iio_device_register(&client->dev, indio_dev);
0201 }
0202
0203 static int al3010_suspend(struct device *dev)
0204 {
0205 return al3010_set_pwr(to_i2c_client(dev), false);
0206 }
0207
0208 static int al3010_resume(struct device *dev)
0209 {
0210 return al3010_set_pwr(to_i2c_client(dev), true);
0211 }
0212
0213 static DEFINE_SIMPLE_DEV_PM_OPS(al3010_pm_ops, al3010_suspend, al3010_resume);
0214
0215 static const struct i2c_device_id al3010_id[] = {
0216 {"al3010", },
0217 {}
0218 };
0219 MODULE_DEVICE_TABLE(i2c, al3010_id);
0220
0221 static const struct of_device_id al3010_of_match[] = {
0222 { .compatible = "dynaimage,al3010", },
0223 {},
0224 };
0225 MODULE_DEVICE_TABLE(of, al3010_of_match);
0226
0227 static struct i2c_driver al3010_driver = {
0228 .driver = {
0229 .name = AL3010_DRV_NAME,
0230 .of_match_table = al3010_of_match,
0231 .pm = pm_sleep_ptr(&al3010_pm_ops),
0232 },
0233 .probe = al3010_probe,
0234 .id_table = al3010_id,
0235 };
0236 module_i2c_driver(al3010_driver);
0237
0238 MODULE_AUTHOR("Daniel Baluta <daniel.baluta@nxp.com>");
0239 MODULE_AUTHOR("David Heidelberg <david@ixit.cz>");
0240 MODULE_DESCRIPTION("AL3010 Ambient Light Sensor driver");
0241 MODULE_LICENSE("GPL v2");