linux/drivers/misc/apds9802als.c
<<
>>
Prefs
   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
  28struct als_data {
  29        struct mutex mutex;
  30};
  31
  32static 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
  47static 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
  66static 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);
 102failed:
 103        mutex_unlock(&data->mutex);
 104        pm_runtime_put_sync(dev);
 105        return ret_val;
 106}
 107
 108static 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        }
 153fail:
 154        mutex_unlock(&data->mutex);
 155        pm_runtime_put_sync(dev);
 156        return ret_val;
 157}
 158
 159static 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);
 173fail:
 174        mutex_unlock(&data->mutex);
 175        return ret_val;
 176}
 177
 178static DEVICE_ATTR(lux0_sensor_range, S_IRUGO | S_IWUSR,
 179        als_sensing_range_show, als_sensing_range_store);
 180static DEVICE_ATTR(lux0_input, S_IRUGO, als_lux0_input_data_show, NULL);
 181
 182static struct attribute *mid_att_als[] = {
 183        &dev_attr_lux0_sensor_range.attr,
 184        &dev_attr_lux0_input.attr,
 185        NULL
 186};
 187
 188static const struct attribute_group m_als_gr = {
 189        .name = "apds9802als",
 190        .attrs = mid_att_als
 191};
 192
 193static 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
 215static 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;
 240als_error1:
 241        kfree(data);
 242        return res;
 243}
 244
 245static 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
 264static 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
 272static 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
 280static 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
 289static const struct i2c_device_id apds9802als_id[] = {
 290        { DRIVER_NAME, 0 },
 291        { }
 292};
 293
 294MODULE_DEVICE_TABLE(i2c, apds9802als_id);
 295
 296static 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
 306module_i2c_driver(apds9802als_driver);
 307
 308MODULE_AUTHOR("Anantha Narayanan <Anantha.Narayanan@intel.com");
 309MODULE_DESCRIPTION("Avago apds9802als ALS Driver");
 310MODULE_LICENSE("GPL v2");
 311