root/drivers/misc/apds9802als.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. als_sensing_range_show
  2. als_wait_for_data_ready
  3. als_lux0_input_data_show
  4. als_sensing_range_store
  5. als_set_power_state
  6. als_set_default_config
  7. apds9802als_probe
  8. apds9802als_remove
  9. apds9802als_suspend
  10. apds9802als_resume

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * apds9802als.c - apds9802  ALS Driver
   4  *
   5  * Copyright (C) 2009 Intel Corp
   6  *
   7  *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   8  *
   9  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  10  */
  11 
  12 #include <linux/module.h>
  13 #include <linux/slab.h>
  14 #include <linux/i2c.h>
  15 #include <linux/err.h>
  16 #include <linux/delay.h>
  17 #include <linux/mutex.h>
  18 #include <linux/sysfs.h>
  19 #include <linux/pm_runtime.h>
  20 
  21 #define ALS_MIN_RANGE_VAL 1
  22 #define ALS_MAX_RANGE_VAL 2
  23 #define POWER_STA_ENABLE 1
  24 #define POWER_STA_DISABLE 0
  25 
  26 #define DRIVER_NAME "apds9802als"
  27 
  28 struct als_data {
  29         struct mutex mutex;
  30 };
  31 
  32 static ssize_t als_sensing_range_show(struct device *dev,
  33                         struct device_attribute *attr,  char *buf)
  34 {
  35         struct i2c_client *client = to_i2c_client(dev);
  36         int  val;
  37 
  38         val = i2c_smbus_read_byte_data(client, 0x81);
  39         if (val < 0)
  40                 return val;
  41         if (val & 1)
  42                 return sprintf(buf, "4095\n");
  43         else
  44                 return sprintf(buf, "65535\n");
  45 }
  46 
  47 static int als_wait_for_data_ready(struct device *dev)
  48 {
  49         struct i2c_client *client = to_i2c_client(dev);
  50         int ret;
  51         int retry = 10;
  52 
  53         do {
  54                 msleep(30);
  55                 ret = i2c_smbus_read_byte_data(client, 0x86);
  56         } while (!(ret & 0x80) && retry--);
  57 
  58         if (retry < 0) {
  59                 dev_warn(dev, "timeout waiting for data ready\n");
  60                 return -ETIMEDOUT;
  61         }
  62 
  63         return 0;
  64 }
  65 
  66 static ssize_t als_lux0_input_data_show(struct device *dev,
  67                         struct device_attribute *attr, char *buf)
  68 {
  69         struct i2c_client *client = to_i2c_client(dev);
  70         struct als_data *data = i2c_get_clientdata(client);
  71         int ret_val;
  72         int temp;
  73 
  74         /* Protect against parallel reads */
  75         pm_runtime_get_sync(dev);
  76         mutex_lock(&data->mutex);
  77 
  78         /* clear EOC interrupt status */
  79         i2c_smbus_write_byte(client, 0x40);
  80         /* start measurement */
  81         temp = i2c_smbus_read_byte_data(client, 0x81);
  82         i2c_smbus_write_byte_data(client, 0x81, temp | 0x08);
  83 
  84         ret_val = als_wait_for_data_ready(dev);
  85         if (ret_val < 0)
  86                 goto failed;
  87 
  88         temp = i2c_smbus_read_byte_data(client, 0x8C); /* LSB data */
  89         if (temp < 0) {
  90                 ret_val = temp;
  91                 goto failed;
  92         }
  93         ret_val = i2c_smbus_read_byte_data(client, 0x8D); /* MSB data */
  94         if (ret_val < 0)
  95                 goto failed;
  96 
  97         mutex_unlock(&data->mutex);
  98         pm_runtime_put_sync(dev);
  99 
 100         temp = (ret_val << 8) | temp;
 101         return sprintf(buf, "%d\n", temp);
 102 failed:
 103         mutex_unlock(&data->mutex);
 104         pm_runtime_put_sync(dev);
 105         return ret_val;
 106 }
 107 
 108 static ssize_t als_sensing_range_store(struct device *dev,
 109                 struct device_attribute *attr, const  char *buf, size_t count)
 110 {
 111         struct i2c_client *client = to_i2c_client(dev);
 112         struct als_data *data = i2c_get_clientdata(client);
 113         int ret_val;
 114         unsigned long val;
 115 
 116         ret_val = kstrtoul(buf, 10, &val);
 117         if (ret_val)
 118                 return ret_val;
 119 
 120         if (val < 4096)
 121                 val = 1;
 122         else if (val < 65536)
 123                 val = 2;
 124         else
 125                 return -ERANGE;
 126 
 127         pm_runtime_get_sync(dev);
 128 
 129         /* Make sure nobody else reads/modifies/writes 0x81 while we
 130            are active */
 131         mutex_lock(&data->mutex);
 132 
 133         ret_val = i2c_smbus_read_byte_data(client, 0x81);
 134         if (ret_val < 0)
 135                 goto fail;
 136 
 137         /* Reset the bits before setting them */
 138         ret_val = ret_val & 0xFA;
 139 
 140         if (val == 1) /* Setting detection range up to 4k LUX */
 141                 ret_val = (ret_val | 0x01);
 142         else /* Setting detection range up to 64k LUX*/
 143                 ret_val = (ret_val | 0x00);
 144 
 145         ret_val = i2c_smbus_write_byte_data(client, 0x81, ret_val);
 146 
 147         if (ret_val >= 0) {
 148                 /* All OK */
 149                 mutex_unlock(&data->mutex);
 150                 pm_runtime_put_sync(dev);
 151                 return count;
 152         }
 153 fail:
 154         mutex_unlock(&data->mutex);
 155         pm_runtime_put_sync(dev);
 156         return ret_val;
 157 }
 158 
 159 static int als_set_power_state(struct i2c_client *client, bool on_off)
 160 {
 161         int ret_val;
 162         struct als_data *data = i2c_get_clientdata(client);
 163 
 164         mutex_lock(&data->mutex);
 165         ret_val = i2c_smbus_read_byte_data(client, 0x80);
 166         if (ret_val < 0)
 167                 goto fail;
 168         if (on_off)
 169                 ret_val = ret_val | 0x01;
 170         else
 171                 ret_val = ret_val & 0xFE;
 172         ret_val = i2c_smbus_write_byte_data(client, 0x80, ret_val);
 173 fail:
 174         mutex_unlock(&data->mutex);
 175         return ret_val;
 176 }
 177 
 178 static DEVICE_ATTR(lux0_sensor_range, S_IRUGO | S_IWUSR,
 179         als_sensing_range_show, als_sensing_range_store);
 180 static DEVICE_ATTR(lux0_input, S_IRUGO, als_lux0_input_data_show, NULL);
 181 
 182 static struct attribute *mid_att_als[] = {
 183         &dev_attr_lux0_sensor_range.attr,
 184         &dev_attr_lux0_input.attr,
 185         NULL
 186 };
 187 
 188 static const struct attribute_group m_als_gr = {
 189         .name = "apds9802als",
 190         .attrs = mid_att_als
 191 };
 192 
 193 static int als_set_default_config(struct i2c_client *client)
 194 {
 195         int ret_val;
 196         /* Write the command and then switch on */
 197         ret_val = i2c_smbus_write_byte_data(client, 0x80, 0x01);
 198         if (ret_val < 0) {
 199                 dev_err(&client->dev, "failed default switch on write\n");
 200                 return ret_val;
 201         }
 202         /* detection range: 1~64K Lux, maunal measurement */
 203         ret_val = i2c_smbus_write_byte_data(client, 0x81, 0x08);
 204         if (ret_val < 0)
 205                 dev_err(&client->dev, "failed default LUX on write\n");
 206 
 207         /*  We always get 0 for the 1st measurement after system power on,
 208          *  so make sure it is finished before user asks for data.
 209          */
 210         als_wait_for_data_ready(&client->dev);
 211 
 212         return ret_val;
 213 }
 214 
 215 static int apds9802als_probe(struct i2c_client *client,
 216                              const struct i2c_device_id *id)
 217 {
 218         int res;
 219         struct als_data *data;
 220 
 221         data = kzalloc(sizeof(struct als_data), GFP_KERNEL);
 222         if (data == NULL) {
 223                 dev_err(&client->dev, "Memory allocation failed\n");
 224                 return -ENOMEM;
 225         }
 226         i2c_set_clientdata(client, data);
 227         res = sysfs_create_group(&client->dev.kobj, &m_als_gr);
 228         if (res) {
 229                 dev_err(&client->dev, "device create file failed\n");
 230                 goto als_error1;
 231         }
 232         dev_info(&client->dev, "ALS chip found\n");
 233         als_set_default_config(client);
 234         mutex_init(&data->mutex);
 235 
 236         pm_runtime_set_active(&client->dev);
 237         pm_runtime_enable(&client->dev);
 238 
 239         return res;
 240 als_error1:
 241         kfree(data);
 242         return res;
 243 }
 244 
 245 static int apds9802als_remove(struct i2c_client *client)
 246 {
 247         struct als_data *data = i2c_get_clientdata(client);
 248 
 249         pm_runtime_get_sync(&client->dev);
 250 
 251         als_set_power_state(client, false);
 252         sysfs_remove_group(&client->dev.kobj, &m_als_gr);
 253 
 254         pm_runtime_disable(&client->dev);
 255         pm_runtime_set_suspended(&client->dev);
 256         pm_runtime_put_noidle(&client->dev);
 257 
 258         kfree(data);
 259         return 0;
 260 }
 261 
 262 #ifdef CONFIG_PM
 263 
 264 static int apds9802als_suspend(struct device *dev)
 265 {
 266         struct i2c_client *client = to_i2c_client(dev);
 267 
 268         als_set_power_state(client, false);
 269         return 0;
 270 }
 271 
 272 static int apds9802als_resume(struct device *dev)
 273 {
 274         struct i2c_client *client = to_i2c_client(dev);
 275 
 276         als_set_power_state(client, true);
 277         return 0;
 278 }
 279 
 280 static UNIVERSAL_DEV_PM_OPS(apds9802als_pm_ops, apds9802als_suspend,
 281         apds9802als_resume, NULL);
 282 
 283 #define APDS9802ALS_PM_OPS (&apds9802als_pm_ops)
 284 
 285 #else   /* CONFIG_PM */
 286 #define APDS9802ALS_PM_OPS NULL
 287 #endif  /* CONFIG_PM */
 288 
 289 static const struct i2c_device_id apds9802als_id[] = {
 290         { DRIVER_NAME, 0 },
 291         { }
 292 };
 293 
 294 MODULE_DEVICE_TABLE(i2c, apds9802als_id);
 295 
 296 static struct i2c_driver apds9802als_driver = {
 297         .driver = {
 298                 .name = DRIVER_NAME,
 299                 .pm = APDS9802ALS_PM_OPS,
 300         },
 301         .probe = apds9802als_probe,
 302         .remove = apds9802als_remove,
 303         .id_table = apds9802als_id,
 304 };
 305 
 306 module_i2c_driver(apds9802als_driver);
 307 
 308 MODULE_AUTHOR("Anantha Narayanan <Anantha.Narayanan@intel.com");
 309 MODULE_DESCRIPTION("Avago apds9802als ALS Driver");
 310 MODULE_LICENSE("GPL v2");

/* [<][>][^][v][top][bottom][index][help] */