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

Configure Feed

Select the types of activity you want to include in your feed.

at v5.12 485 lines 11 kB view raw
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * Copyright (c) 2015 Intel Corporation 4 * 5 * Driver for TXC PA12203001 Proximity and Ambient Light Sensor. 6 * 7 * To do: Interrupt support. 8 */ 9 10#include <linux/kernel.h> 11#include <linux/module.h> 12#include <linux/acpi.h> 13#include <linux/delay.h> 14#include <linux/i2c.h> 15#include <linux/iio/iio.h> 16#include <linux/iio/sysfs.h> 17#include <linux/mutex.h> 18#include <linux/pm.h> 19#include <linux/pm_runtime.h> 20#include <linux/regmap.h> 21 22#define PA12203001_DRIVER_NAME "pa12203001" 23 24#define PA12203001_REG_CFG0 0x00 25#define PA12203001_REG_CFG1 0x01 26#define PA12203001_REG_CFG2 0x02 27#define PA12203001_REG_CFG3 0x03 28 29#define PA12203001_REG_ADL 0x0b 30#define PA12203001_REG_PDH 0x0e 31 32#define PA12203001_REG_POFS 0x10 33#define PA12203001_REG_PSET 0x11 34 35#define PA12203001_ALS_EN_MASK BIT(0) 36#define PA12203001_PX_EN_MASK BIT(1) 37#define PA12203001_PX_NORMAL_MODE_MASK GENMASK(7, 6) 38#define PA12203001_AFSR_MASK GENMASK(5, 4) 39#define PA12203001_AFSR_SHIFT 4 40 41#define PA12203001_PSCAN 0x03 42 43/* als range 31000, ps, als disabled */ 44#define PA12203001_REG_CFG0_DEFAULT 0x30 45 46/* led current: 100 mA */ 47#define PA12203001_REG_CFG1_DEFAULT 0x20 48 49/* ps mode: normal, interrupts not active */ 50#define PA12203001_REG_CFG2_DEFAULT 0xcc 51 52#define PA12203001_REG_CFG3_DEFAULT 0x00 53 54#define PA12203001_SLEEP_DELAY_MS 3000 55 56#define PA12203001_CHIP_ENABLE 0xff 57#define PA12203001_CHIP_DISABLE 0x00 58 59/* available scales: corresponding to [500, 4000, 7000, 31000] lux */ 60static const int pa12203001_scales[] = { 7629, 61036, 106813, 473029}; 61 62struct pa12203001_data { 63 struct i2c_client *client; 64 65 /* protect device states */ 66 struct mutex lock; 67 68 bool als_enabled; 69 bool px_enabled; 70 bool als_needs_enable; 71 bool px_needs_enable; 72 73 struct regmap *map; 74}; 75 76static const struct { 77 u8 reg; 78 u8 val; 79} regvals[] = { 80 {PA12203001_REG_CFG0, PA12203001_REG_CFG0_DEFAULT}, 81 {PA12203001_REG_CFG1, PA12203001_REG_CFG1_DEFAULT}, 82 {PA12203001_REG_CFG2, PA12203001_REG_CFG2_DEFAULT}, 83 {PA12203001_REG_CFG3, PA12203001_REG_CFG3_DEFAULT}, 84 {PA12203001_REG_PSET, PA12203001_PSCAN}, 85}; 86 87static IIO_CONST_ATTR(in_illuminance_scale_available, 88 "0.007629 0.061036 0.106813 0.473029"); 89 90static struct attribute *pa12203001_attrs[] = { 91 &iio_const_attr_in_illuminance_scale_available.dev_attr.attr, 92 NULL 93}; 94 95static const struct attribute_group pa12203001_attr_group = { 96 .attrs = pa12203001_attrs, 97}; 98 99static const struct iio_chan_spec pa12203001_channels[] = { 100 { 101 .type = IIO_LIGHT, 102 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | 103 BIT(IIO_CHAN_INFO_SCALE), 104 }, 105 { 106 .type = IIO_PROXIMITY, 107 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), 108 } 109}; 110 111static const struct regmap_range pa12203001_volatile_regs_ranges[] = { 112 regmap_reg_range(PA12203001_REG_ADL, PA12203001_REG_ADL + 1), 113 regmap_reg_range(PA12203001_REG_PDH, PA12203001_REG_PDH), 114}; 115 116static const struct regmap_access_table pa12203001_volatile_regs = { 117 .yes_ranges = pa12203001_volatile_regs_ranges, 118 .n_yes_ranges = ARRAY_SIZE(pa12203001_volatile_regs_ranges), 119}; 120 121static const struct regmap_config pa12203001_regmap_config = { 122 .reg_bits = 8, 123 .val_bits = 8, 124 .max_register = PA12203001_REG_PSET, 125 .cache_type = REGCACHE_RBTREE, 126 .volatile_table = &pa12203001_volatile_regs, 127}; 128 129static inline int pa12203001_als_enable(struct pa12203001_data *data, u8 enable) 130{ 131 int ret; 132 133 ret = regmap_update_bits(data->map, PA12203001_REG_CFG0, 134 PA12203001_ALS_EN_MASK, enable); 135 if (ret < 0) 136 return ret; 137 138 data->als_enabled = !!enable; 139 140 return 0; 141} 142 143static inline int pa12203001_px_enable(struct pa12203001_data *data, u8 enable) 144{ 145 int ret; 146 147 ret = regmap_update_bits(data->map, PA12203001_REG_CFG0, 148 PA12203001_PX_EN_MASK, enable); 149 if (ret < 0) 150 return ret; 151 152 data->px_enabled = !!enable; 153 154 return 0; 155} 156 157static int pa12203001_set_power_state(struct pa12203001_data *data, bool on, 158 u8 mask) 159{ 160#ifdef CONFIG_PM 161 int ret; 162 163 if (on && (mask & PA12203001_ALS_EN_MASK)) { 164 mutex_lock(&data->lock); 165 if (data->px_enabled) { 166 ret = pa12203001_als_enable(data, 167 PA12203001_ALS_EN_MASK); 168 if (ret < 0) 169 goto err; 170 } else { 171 data->als_needs_enable = true; 172 } 173 mutex_unlock(&data->lock); 174 } 175 176 if (on && (mask & PA12203001_PX_EN_MASK)) { 177 mutex_lock(&data->lock); 178 if (data->als_enabled) { 179 ret = pa12203001_px_enable(data, PA12203001_PX_EN_MASK); 180 if (ret < 0) 181 goto err; 182 } else { 183 data->px_needs_enable = true; 184 } 185 mutex_unlock(&data->lock); 186 } 187 188 if (on) { 189 ret = pm_runtime_get_sync(&data->client->dev); 190 if (ret < 0) 191 pm_runtime_put_noidle(&data->client->dev); 192 193 } else { 194 pm_runtime_mark_last_busy(&data->client->dev); 195 ret = pm_runtime_put_autosuspend(&data->client->dev); 196 } 197 198 return ret; 199 200err: 201 mutex_unlock(&data->lock); 202 return ret; 203 204#endif 205 return 0; 206} 207 208static int pa12203001_read_raw(struct iio_dev *indio_dev, 209 struct iio_chan_spec const *chan, int *val, 210 int *val2, long mask) 211{ 212 struct pa12203001_data *data = iio_priv(indio_dev); 213 int ret; 214 u8 dev_mask; 215 unsigned int reg_byte; 216 __le16 reg_word; 217 218 switch (mask) { 219 case IIO_CHAN_INFO_RAW: 220 switch (chan->type) { 221 case IIO_LIGHT: 222 dev_mask = PA12203001_ALS_EN_MASK; 223 ret = pa12203001_set_power_state(data, true, dev_mask); 224 if (ret < 0) 225 return ret; 226 /* 227 * ALS ADC value is stored in registers 228 * PA12203001_REG_ADL and in PA12203001_REG_ADL + 1. 229 */ 230 ret = regmap_bulk_read(data->map, PA12203001_REG_ADL, 231 &reg_word, 2); 232 if (ret < 0) 233 goto reg_err; 234 235 *val = le16_to_cpu(reg_word); 236 ret = pa12203001_set_power_state(data, false, dev_mask); 237 if (ret < 0) 238 return ret; 239 break; 240 case IIO_PROXIMITY: 241 dev_mask = PA12203001_PX_EN_MASK; 242 ret = pa12203001_set_power_state(data, true, dev_mask); 243 if (ret < 0) 244 return ret; 245 ret = regmap_read(data->map, PA12203001_REG_PDH, 246 &reg_byte); 247 if (ret < 0) 248 goto reg_err; 249 250 *val = reg_byte; 251 ret = pa12203001_set_power_state(data, false, dev_mask); 252 if (ret < 0) 253 return ret; 254 break; 255 default: 256 return -EINVAL; 257 } 258 return IIO_VAL_INT; 259 case IIO_CHAN_INFO_SCALE: 260 ret = regmap_read(data->map, PA12203001_REG_CFG0, &reg_byte); 261 if (ret < 0) 262 return ret; 263 *val = 0; 264 reg_byte = (reg_byte & PA12203001_AFSR_MASK); 265 *val2 = pa12203001_scales[reg_byte >> 4]; 266 return IIO_VAL_INT_PLUS_MICRO; 267 default: 268 return -EINVAL; 269 } 270 271reg_err: 272 pa12203001_set_power_state(data, false, dev_mask); 273 return ret; 274} 275 276static int pa12203001_write_raw(struct iio_dev *indio_dev, 277 struct iio_chan_spec const *chan, int val, 278 int val2, long mask) 279{ 280 struct pa12203001_data *data = iio_priv(indio_dev); 281 int i, ret, new_val; 282 unsigned int reg_byte; 283 284 switch (mask) { 285 case IIO_CHAN_INFO_SCALE: 286 ret = regmap_read(data->map, PA12203001_REG_CFG0, &reg_byte); 287 if (val != 0 || ret < 0) 288 return -EINVAL; 289 for (i = 0; i < ARRAY_SIZE(pa12203001_scales); i++) { 290 if (val2 == pa12203001_scales[i]) { 291 new_val = i << PA12203001_AFSR_SHIFT; 292 return regmap_update_bits(data->map, 293 PA12203001_REG_CFG0, 294 PA12203001_AFSR_MASK, 295 new_val); 296 } 297 } 298 break; 299 default: 300 break; 301 } 302 303 return -EINVAL; 304} 305 306static const struct iio_info pa12203001_info = { 307 .read_raw = pa12203001_read_raw, 308 .write_raw = pa12203001_write_raw, 309 .attrs = &pa12203001_attr_group, 310}; 311 312static int pa12203001_init(struct iio_dev *indio_dev) 313{ 314 struct pa12203001_data *data = iio_priv(indio_dev); 315 int i, ret; 316 317 for (i = 0; i < ARRAY_SIZE(regvals); i++) { 318 ret = regmap_write(data->map, regvals[i].reg, regvals[i].val); 319 if (ret < 0) 320 return ret; 321 } 322 323 return 0; 324} 325 326static int pa12203001_power_chip(struct iio_dev *indio_dev, u8 state) 327{ 328 struct pa12203001_data *data = iio_priv(indio_dev); 329 int ret; 330 331 mutex_lock(&data->lock); 332 ret = pa12203001_als_enable(data, state); 333 if (ret < 0) 334 goto out; 335 336 ret = pa12203001_px_enable(data, state); 337 338out: 339 mutex_unlock(&data->lock); 340 return ret; 341} 342 343static int pa12203001_probe(struct i2c_client *client, 344 const struct i2c_device_id *id) 345{ 346 struct pa12203001_data *data; 347 struct iio_dev *indio_dev; 348 int ret; 349 350 indio_dev = devm_iio_device_alloc(&client->dev, 351 sizeof(struct pa12203001_data)); 352 if (!indio_dev) 353 return -ENOMEM; 354 355 data = iio_priv(indio_dev); 356 i2c_set_clientdata(client, indio_dev); 357 data->client = client; 358 359 data->map = devm_regmap_init_i2c(client, &pa12203001_regmap_config); 360 if (IS_ERR(data->map)) 361 return PTR_ERR(data->map); 362 363 mutex_init(&data->lock); 364 365 indio_dev->info = &pa12203001_info; 366 indio_dev->name = PA12203001_DRIVER_NAME; 367 indio_dev->channels = pa12203001_channels; 368 indio_dev->num_channels = ARRAY_SIZE(pa12203001_channels); 369 indio_dev->modes = INDIO_DIRECT_MODE; 370 371 ret = pa12203001_init(indio_dev); 372 if (ret < 0) 373 return ret; 374 375 ret = pa12203001_power_chip(indio_dev, PA12203001_CHIP_ENABLE); 376 if (ret < 0) 377 return ret; 378 379 ret = pm_runtime_set_active(&client->dev); 380 if (ret < 0) 381 goto out_err; 382 383 pm_runtime_enable(&client->dev); 384 pm_runtime_set_autosuspend_delay(&client->dev, 385 PA12203001_SLEEP_DELAY_MS); 386 pm_runtime_use_autosuspend(&client->dev); 387 388 ret = iio_device_register(indio_dev); 389 if (ret < 0) 390 goto out_err; 391 392 return 0; 393 394out_err: 395 pa12203001_power_chip(indio_dev, PA12203001_CHIP_DISABLE); 396 return ret; 397} 398 399static int pa12203001_remove(struct i2c_client *client) 400{ 401 struct iio_dev *indio_dev = i2c_get_clientdata(client); 402 403 iio_device_unregister(indio_dev); 404 405 pm_runtime_disable(&client->dev); 406 pm_runtime_set_suspended(&client->dev); 407 408 return pa12203001_power_chip(indio_dev, PA12203001_CHIP_DISABLE); 409} 410 411#if defined(CONFIG_PM_SLEEP) || defined(CONFIG_PM) 412static int pa12203001_suspend(struct device *dev) 413{ 414 struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); 415 416 return pa12203001_power_chip(indio_dev, PA12203001_CHIP_DISABLE); 417} 418#endif 419 420#ifdef CONFIG_PM_SLEEP 421static int pa12203001_resume(struct device *dev) 422{ 423 struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); 424 425 return pa12203001_power_chip(indio_dev, PA12203001_CHIP_ENABLE); 426} 427#endif 428 429#ifdef CONFIG_PM 430static int pa12203001_runtime_resume(struct device *dev) 431{ 432 struct pa12203001_data *data; 433 434 data = iio_priv(i2c_get_clientdata(to_i2c_client(dev))); 435 436 mutex_lock(&data->lock); 437 if (data->als_needs_enable) { 438 pa12203001_als_enable(data, PA12203001_ALS_EN_MASK); 439 data->als_needs_enable = false; 440 } 441 if (data->px_needs_enable) { 442 pa12203001_px_enable(data, PA12203001_PX_EN_MASK); 443 data->px_needs_enable = false; 444 } 445 mutex_unlock(&data->lock); 446 447 return 0; 448} 449#endif 450 451static const struct dev_pm_ops pa12203001_pm_ops = { 452 SET_SYSTEM_SLEEP_PM_OPS(pa12203001_suspend, pa12203001_resume) 453 SET_RUNTIME_PM_OPS(pa12203001_suspend, pa12203001_runtime_resume, NULL) 454}; 455 456static const struct acpi_device_id pa12203001_acpi_match[] = { 457 { "TXCPA122", 0}, 458 {} 459}; 460 461MODULE_DEVICE_TABLE(acpi, pa12203001_acpi_match); 462 463static const struct i2c_device_id pa12203001_id[] = { 464 {"txcpa122", 0}, 465 {} 466}; 467 468MODULE_DEVICE_TABLE(i2c, pa12203001_id); 469 470static struct i2c_driver pa12203001_driver = { 471 .driver = { 472 .name = PA12203001_DRIVER_NAME, 473 .pm = &pa12203001_pm_ops, 474 .acpi_match_table = ACPI_PTR(pa12203001_acpi_match), 475 }, 476 .probe = pa12203001_probe, 477 .remove = pa12203001_remove, 478 .id_table = pa12203001_id, 479 480}; 481module_i2c_driver(pa12203001_driver); 482 483MODULE_AUTHOR("Adriana Reus <adriana.reus@intel.com>"); 484MODULE_DESCRIPTION("Driver for TXC PA12203001 Proximity and Light Sensor"); 485MODULE_LICENSE("GPL v2");