Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drivers/misc/apds9802als.c: add runtime PM support

Update the driver for the needed runtime power features. Remove the old
user controlled power functions.

[akpm@linux-foundation.org: put PM code under CONFIG_PM]
Signed-off-by: Hong Liu <hong.liu@intel.com>
Signed-off-by: Alan Cox <alan@linux.intel.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Hong Liu and committed by
Linus Torvalds
f0cfec11 22d96aa5

+103 -64
+103 -64
drivers/misc/apds9802als.c
··· 29 29 #include <linux/delay.h> 30 30 #include <linux/mutex.h> 31 31 #include <linux/sysfs.h> 32 - #include <linux/hwmon-sysfs.h> 32 + #include <linux/pm_runtime.h> 33 33 34 34 #define ALS_MIN_RANGE_VAL 1 35 35 #define ALS_MAX_RANGE_VAL 2 36 36 #define POWER_STA_ENABLE 1 37 37 #define POWER_STA_DISABLE 0 38 - #define APDS9802ALS_I2C_ADDR 0x29 39 38 40 39 #define DRIVER_NAME "apds9802als" 41 40 42 41 struct als_data { 43 - struct device *hwmon_dev; 44 - bool needresume; 45 42 struct mutex mutex; 46 43 }; 47 44 ··· 57 60 return sprintf(buf, "65535\n"); 58 61 } 59 62 63 + static int als_wait_for_data_ready(struct device *dev) 64 + { 65 + struct i2c_client *client = to_i2c_client(dev); 66 + int ret; 67 + int retry = 10; 68 + 69 + do { 70 + msleep(30); 71 + ret = i2c_smbus_read_byte_data(client, 0x86); 72 + } while (!(ret & 0x80) && retry--); 73 + 74 + if (!retry) { 75 + dev_warn(dev, "timeout waiting for data ready\n"); 76 + return -ETIMEDOUT; 77 + } 78 + 79 + return 0; 80 + } 81 + 60 82 static ssize_t als_lux0_input_data_show(struct device *dev, 61 83 struct device_attribute *attr, char *buf) 62 84 { 63 85 struct i2c_client *client = to_i2c_client(dev); 64 86 struct als_data *data = i2c_get_clientdata(client); 65 - unsigned int ret_val; 87 + int ret_val; 66 88 int temp; 67 89 68 90 /* Protect against parallel reads */ 91 + pm_runtime_get_sync(dev); 69 92 mutex_lock(&data->mutex); 70 - temp = i2c_smbus_read_byte_data(client, 0x8C);/*LSB data*/ 93 + 94 + /* clear EOC interrupt status */ 95 + i2c_smbus_write_byte(client, 0x40); 96 + /* start measurement */ 97 + temp = i2c_smbus_read_byte_data(client, 0x81); 98 + i2c_smbus_write_byte_data(client, 0x81, temp | 0x08); 99 + 100 + ret_val = als_wait_for_data_ready(dev); 101 + if (ret_val < 0) 102 + goto failed; 103 + 104 + temp = i2c_smbus_read_byte_data(client, 0x8C); /* LSB data */ 71 105 if (temp < 0) { 72 106 ret_val = temp; 73 107 goto failed; 74 108 } 75 - ret_val = i2c_smbus_read_byte_data(client, 0x8D);/*MSB data*/ 109 + ret_val = i2c_smbus_read_byte_data(client, 0x8D); /* MSB data */ 76 110 if (ret_val < 0) 77 111 goto failed; 112 + 78 113 mutex_unlock(&data->mutex); 79 - ret_val = (ret_val << 8) | temp; 80 - return sprintf(buf, "%d\n", ret_val); 114 + pm_runtime_put_sync(dev); 115 + 116 + temp = (ret_val << 8) | temp; 117 + return sprintf(buf, "%d\n", temp); 81 118 failed: 82 119 mutex_unlock(&data->mutex); 120 + pm_runtime_put_sync(dev); 83 121 return ret_val; 84 122 } 85 123 ··· 136 104 else 137 105 return -ERANGE; 138 106 107 + pm_runtime_get_sync(dev); 108 + 139 109 /* Make sure nobody else reads/modifies/writes 0x81 while we 140 110 are active */ 141 - 142 111 mutex_lock(&data->mutex); 143 112 144 113 ret_val = i2c_smbus_read_byte_data(client, 0x81); ··· 149 116 /* Reset the bits before setting them */ 150 117 ret_val = ret_val & 0xFA; 151 118 152 - if (val == 1) /* Setting the continous measurement up to 4k LUX */ 153 - ret_val = (ret_val | 0x05); 154 - else /* Setting the continous measurement up to 64k LUX*/ 155 - ret_val = (ret_val | 0x04); 119 + if (val == 1) /* Setting detection range up to 4k LUX */ 120 + ret_val = (ret_val | 0x01); 121 + else /* Setting detection range up to 64k LUX*/ 122 + ret_val = (ret_val | 0x00); 156 123 157 124 ret_val = i2c_smbus_write_byte_data(client, 0x81, ret_val); 125 + 158 126 if (ret_val >= 0) { 159 127 /* All OK */ 160 128 mutex_unlock(&data->mutex); 129 + pm_runtime_put_sync(dev); 161 130 return count; 162 131 } 163 132 fail: 164 133 mutex_unlock(&data->mutex); 134 + pm_runtime_put_sync(dev); 165 135 return ret_val; 166 - } 167 - 168 - static ssize_t als_power_status_show(struct device *dev, 169 - struct device_attribute *attr, char *buf) 170 - { 171 - struct i2c_client *client = to_i2c_client(dev); 172 - int ret_val; 173 - ret_val = i2c_smbus_read_byte_data(client, 0x80); 174 - if (ret_val < 0) 175 - return ret_val; 176 - ret_val = ret_val & 0x01; 177 - return sprintf(buf, "%d\n", ret_val); 178 136 } 179 137 180 138 static int als_set_power_state(struct i2c_client *client, bool on_off) ··· 187 163 return ret_val; 188 164 } 189 165 190 - static ssize_t als_power_status_store(struct device *dev, 191 - struct device_attribute *attr, const char *buf, size_t count) 192 - { 193 - struct i2c_client *client = to_i2c_client(dev); 194 - struct als_data *data = i2c_get_clientdata(client); 195 - unsigned long val; 196 - int ret_val; 197 - 198 - if (strict_strtoul(buf, 10, &val)) 199 - return -EINVAL; 200 - if (val == POWER_STA_ENABLE) { 201 - ret_val = als_set_power_state(client, true); 202 - data->needresume = true; 203 - } else if (val == POWER_STA_DISABLE) { 204 - ret_val = als_set_power_state(client, false); 205 - data->needresume = false; 206 - } else 207 - return -EINVAL; 208 - if (ret_val < 0) 209 - return ret_val; 210 - return count; 211 - } 212 - 213 166 static DEVICE_ATTR(lux0_sensor_range, S_IRUGO | S_IWUSR, 214 167 als_sensing_range_show, als_sensing_range_store); 215 168 static DEVICE_ATTR(lux0_input, S_IRUGO, als_lux0_input_data_show, NULL); 216 - static DEVICE_ATTR(power_state, S_IRUGO | S_IWUSR, 217 - als_power_status_show, als_power_status_store); 218 169 219 170 static struct attribute *mid_att_als[] = { 220 171 &dev_attr_lux0_sensor_range.attr, 221 172 &dev_attr_lux0_input.attr, 222 - &dev_attr_power_state.attr, 223 173 NULL 224 174 }; 225 175 ··· 211 213 dev_err(&client->dev, "failed default switch on write\n"); 212 214 return ret_val; 213 215 } 214 - /* Continous from 1Lux to 64k Lux */ 215 - ret_val = i2c_smbus_write_byte_data(client, 0x81, 0x04); 216 + /* detection range: 1~64K Lux, maunal measurement */ 217 + ret_val = i2c_smbus_write_byte_data(client, 0x81, 0x08); 216 218 if (ret_val < 0) 217 219 dev_err(&client->dev, "failed default LUX on write\n"); 220 + 221 + /* We always get 0 for the 1st measurement after system power on, 222 + * so make sure it is finished before user asks for data. 223 + */ 224 + als_wait_for_data_ready(&client->dev); 225 + 218 226 return ret_val; 219 227 } 220 228 221 - static int apds9802als_probe(struct i2c_client *client, 222 - const struct i2c_device_id *id) 229 + static int apds9802als_probe(struct i2c_client *client, 230 + const struct i2c_device_id *id) 223 231 { 224 232 int res; 225 233 struct als_data *data; ··· 241 237 dev_err(&client->dev, "device create file failed\n"); 242 238 goto als_error1; 243 239 } 244 - dev_info(&client->dev, 245 - "%s apds9802als: ALS chip found\n", client->name); 240 + dev_info(&client->dev, "ALS chip found\n"); 246 241 als_set_default_config(client); 247 - data->needresume = true; 248 242 mutex_init(&data->mutex); 243 + 244 + pm_runtime_enable(&client->dev); 245 + pm_runtime_get(&client->dev); 246 + pm_runtime_put(&client->dev); 247 + 249 248 return res; 250 249 als_error1: 251 250 i2c_set_clientdata(client, NULL); ··· 259 252 static int apds9802als_remove(struct i2c_client *client) 260 253 { 261 254 struct als_data *data = i2c_get_clientdata(client); 255 + 256 + als_set_power_state(client, false); 262 257 sysfs_remove_group(&client->dev.kobj, &m_als_gr); 263 258 kfree(data); 264 259 return 0; 265 260 } 266 261 262 + #ifdef CONFIG_PM 267 263 static int apds9802als_suspend(struct i2c_client *client, pm_message_t mesg) 268 264 { 269 265 als_set_power_state(client, false); ··· 275 265 276 266 static int apds9802als_resume(struct i2c_client *client) 277 267 { 278 - struct als_data *data = i2c_get_clientdata(client); 268 + als_set_default_config(client); 279 269 280 - if (data->needresume == true) 281 - als_set_power_state(client, true); 270 + pm_runtime_get(&client->dev); 271 + pm_runtime_put(&client->dev); 282 272 return 0; 283 273 } 274 + 275 + static int apds9802als_runtime_suspend(struct device *dev) 276 + { 277 + struct i2c_client *client = to_i2c_client(dev); 278 + 279 + als_set_power_state(client, false); 280 + return 0; 281 + } 282 + 283 + static int apds9802als_runtime_resume(struct device *dev) 284 + { 285 + struct i2c_client *client = to_i2c_client(dev); 286 + 287 + als_set_power_state(client, true); 288 + return 0; 289 + } 290 + 291 + static const struct dev_pm_ops apds9802als_pm_ops = { 292 + .runtime_suspend = apds9802als_runtime_suspend, 293 + .runtime_resume = apds9802als_runtime_resume, 294 + }; 295 + 296 + #define APDS9802ALS_PM_OPS (&apds9802als_pm_ops) 297 + 298 + #else /* CONFIG_PM */ 299 + #define apds9802als_suspend NULL 300 + #define apds9802als_resume NULL 301 + #define APDS9802ALS_PM_OPS NULL 302 + #endif /* CONFIG_PM */ 284 303 285 304 static struct i2c_device_id apds9802als_id[] = { 286 305 { DRIVER_NAME, 0 }, ··· 320 281 321 282 static struct i2c_driver apds9802als_driver = { 322 283 .driver = { 323 - .name = DRIVER_NAME, 324 - .owner = THIS_MODULE, 284 + .name = DRIVER_NAME, 285 + .pm = APDS9802ALS_PM_OPS, 325 286 }, 326 287 .probe = apds9802als_probe, 327 288 .remove = apds9802als_remove,