cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

pa12203001.c (11365B)


      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_resume_and_get(&data->client->dev);
    190
    191	} else {
    192		pm_runtime_mark_last_busy(&data->client->dev);
    193		ret = pm_runtime_put_autosuspend(&data->client->dev);
    194	}
    195
    196	return ret;
    197
    198err:
    199	mutex_unlock(&data->lock);
    200	return ret;
    201
    202#endif
    203	return 0;
    204}
    205
    206static int pa12203001_read_raw(struct iio_dev *indio_dev,
    207			       struct iio_chan_spec const *chan, int *val,
    208			       int *val2, long mask)
    209{
    210	struct pa12203001_data *data = iio_priv(indio_dev);
    211	int ret;
    212	u8 dev_mask;
    213	unsigned int reg_byte;
    214	__le16 reg_word;
    215
    216	switch (mask) {
    217	case IIO_CHAN_INFO_RAW:
    218		switch (chan->type) {
    219		case IIO_LIGHT:
    220			dev_mask = PA12203001_ALS_EN_MASK;
    221			ret = pa12203001_set_power_state(data, true, dev_mask);
    222			if (ret < 0)
    223				return ret;
    224			/*
    225			 * ALS ADC value is stored in registers
    226			 * PA12203001_REG_ADL and in PA12203001_REG_ADL + 1.
    227			 */
    228			ret = regmap_bulk_read(data->map, PA12203001_REG_ADL,
    229					       &reg_word, 2);
    230			if (ret < 0)
    231				goto reg_err;
    232
    233			*val = le16_to_cpu(reg_word);
    234			ret = pa12203001_set_power_state(data, false, dev_mask);
    235			if (ret < 0)
    236				return ret;
    237			break;
    238		case IIO_PROXIMITY:
    239			dev_mask = PA12203001_PX_EN_MASK;
    240			ret = pa12203001_set_power_state(data, true, dev_mask);
    241			if (ret < 0)
    242				return ret;
    243			ret = regmap_read(data->map, PA12203001_REG_PDH,
    244					  &reg_byte);
    245			if (ret < 0)
    246				goto reg_err;
    247
    248			*val = reg_byte;
    249			ret = pa12203001_set_power_state(data, false, dev_mask);
    250			if (ret < 0)
    251				return ret;
    252			break;
    253		default:
    254			return -EINVAL;
    255		}
    256		return IIO_VAL_INT;
    257	case IIO_CHAN_INFO_SCALE:
    258		ret = regmap_read(data->map, PA12203001_REG_CFG0, &reg_byte);
    259		if (ret < 0)
    260			return ret;
    261		*val = 0;
    262		reg_byte = (reg_byte & PA12203001_AFSR_MASK);
    263		*val2 = pa12203001_scales[reg_byte >> 4];
    264		return IIO_VAL_INT_PLUS_MICRO;
    265	default:
    266		return -EINVAL;
    267	}
    268
    269reg_err:
    270	pa12203001_set_power_state(data, false, dev_mask);
    271	return ret;
    272}
    273
    274static int pa12203001_write_raw(struct iio_dev *indio_dev,
    275				struct iio_chan_spec const *chan, int val,
    276				int val2, long mask)
    277{
    278	struct pa12203001_data *data = iio_priv(indio_dev);
    279	int i, ret, new_val;
    280	unsigned int reg_byte;
    281
    282	switch (mask) {
    283	case IIO_CHAN_INFO_SCALE:
    284		ret = regmap_read(data->map, PA12203001_REG_CFG0, &reg_byte);
    285		if (val != 0 || ret < 0)
    286			return -EINVAL;
    287		for (i = 0; i < ARRAY_SIZE(pa12203001_scales); i++) {
    288			if (val2 == pa12203001_scales[i]) {
    289				new_val = i << PA12203001_AFSR_SHIFT;
    290				return regmap_update_bits(data->map,
    291							  PA12203001_REG_CFG0,
    292							  PA12203001_AFSR_MASK,
    293							  new_val);
    294			}
    295		}
    296		break;
    297	default:
    298		break;
    299	}
    300
    301	return -EINVAL;
    302}
    303
    304static const struct iio_info pa12203001_info = {
    305	.read_raw = pa12203001_read_raw,
    306	.write_raw = pa12203001_write_raw,
    307	.attrs = &pa12203001_attr_group,
    308};
    309
    310static int pa12203001_init(struct iio_dev *indio_dev)
    311{
    312	struct pa12203001_data *data = iio_priv(indio_dev);
    313	int i, ret;
    314
    315	for (i = 0; i < ARRAY_SIZE(regvals); i++) {
    316		ret = regmap_write(data->map, regvals[i].reg, regvals[i].val);
    317		if (ret < 0)
    318			return ret;
    319	}
    320
    321	return 0;
    322}
    323
    324static int pa12203001_power_chip(struct iio_dev *indio_dev, u8 state)
    325{
    326	struct pa12203001_data *data = iio_priv(indio_dev);
    327	int ret;
    328
    329	mutex_lock(&data->lock);
    330	ret = pa12203001_als_enable(data, state);
    331	if (ret < 0)
    332		goto out;
    333
    334	ret = pa12203001_px_enable(data, state);
    335
    336out:
    337	mutex_unlock(&data->lock);
    338	return ret;
    339}
    340
    341static int pa12203001_probe(struct i2c_client *client,
    342			    const struct i2c_device_id *id)
    343{
    344	struct pa12203001_data *data;
    345	struct iio_dev *indio_dev;
    346	int ret;
    347
    348	indio_dev = devm_iio_device_alloc(&client->dev,
    349					  sizeof(struct pa12203001_data));
    350	if (!indio_dev)
    351		return -ENOMEM;
    352
    353	data = iio_priv(indio_dev);
    354	i2c_set_clientdata(client, indio_dev);
    355	data->client = client;
    356
    357	data->map = devm_regmap_init_i2c(client, &pa12203001_regmap_config);
    358	if (IS_ERR(data->map))
    359		return PTR_ERR(data->map);
    360
    361	mutex_init(&data->lock);
    362
    363	indio_dev->info = &pa12203001_info;
    364	indio_dev->name = PA12203001_DRIVER_NAME;
    365	indio_dev->channels = pa12203001_channels;
    366	indio_dev->num_channels = ARRAY_SIZE(pa12203001_channels);
    367	indio_dev->modes = INDIO_DIRECT_MODE;
    368
    369	ret = pa12203001_init(indio_dev);
    370	if (ret < 0)
    371		return ret;
    372
    373	ret = pa12203001_power_chip(indio_dev, PA12203001_CHIP_ENABLE);
    374	if (ret < 0)
    375		return ret;
    376
    377	ret = pm_runtime_set_active(&client->dev);
    378	if (ret < 0)
    379		goto out_err;
    380
    381	pm_runtime_enable(&client->dev);
    382	pm_runtime_set_autosuspend_delay(&client->dev,
    383					 PA12203001_SLEEP_DELAY_MS);
    384	pm_runtime_use_autosuspend(&client->dev);
    385
    386	ret = iio_device_register(indio_dev);
    387	if (ret < 0)
    388		goto out_err;
    389
    390	return 0;
    391
    392out_err:
    393	pa12203001_power_chip(indio_dev, PA12203001_CHIP_DISABLE);
    394	return ret;
    395}
    396
    397static int pa12203001_remove(struct i2c_client *client)
    398{
    399	struct iio_dev *indio_dev = i2c_get_clientdata(client);
    400
    401	iio_device_unregister(indio_dev);
    402
    403	pm_runtime_disable(&client->dev);
    404	pm_runtime_set_suspended(&client->dev);
    405
    406	return pa12203001_power_chip(indio_dev, PA12203001_CHIP_DISABLE);
    407}
    408
    409#if defined(CONFIG_PM_SLEEP) || defined(CONFIG_PM)
    410static int pa12203001_suspend(struct device *dev)
    411{
    412	struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
    413
    414	return pa12203001_power_chip(indio_dev, PA12203001_CHIP_DISABLE);
    415}
    416#endif
    417
    418#ifdef CONFIG_PM_SLEEP
    419static int pa12203001_resume(struct device *dev)
    420{
    421	struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
    422
    423	return pa12203001_power_chip(indio_dev, PA12203001_CHIP_ENABLE);
    424}
    425#endif
    426
    427#ifdef CONFIG_PM
    428static int pa12203001_runtime_resume(struct device *dev)
    429{
    430	struct pa12203001_data *data;
    431
    432	data = iio_priv(i2c_get_clientdata(to_i2c_client(dev)));
    433
    434	mutex_lock(&data->lock);
    435	if (data->als_needs_enable) {
    436		pa12203001_als_enable(data, PA12203001_ALS_EN_MASK);
    437		data->als_needs_enable = false;
    438	}
    439	if (data->px_needs_enable) {
    440		pa12203001_px_enable(data, PA12203001_PX_EN_MASK);
    441		data->px_needs_enable = false;
    442	}
    443	mutex_unlock(&data->lock);
    444
    445	return 0;
    446}
    447#endif
    448
    449static const struct dev_pm_ops pa12203001_pm_ops = {
    450	SET_SYSTEM_SLEEP_PM_OPS(pa12203001_suspend, pa12203001_resume)
    451	SET_RUNTIME_PM_OPS(pa12203001_suspend, pa12203001_runtime_resume, NULL)
    452};
    453
    454static const struct acpi_device_id pa12203001_acpi_match[] = {
    455	{ "TXCPA122", 0 },
    456	{}
    457};
    458
    459MODULE_DEVICE_TABLE(acpi, pa12203001_acpi_match);
    460
    461static const struct i2c_device_id pa12203001_id[] = {
    462		{ "txcpa122", 0 },
    463		{}
    464};
    465
    466MODULE_DEVICE_TABLE(i2c, pa12203001_id);
    467
    468static struct i2c_driver pa12203001_driver = {
    469	.driver = {
    470		.name = PA12203001_DRIVER_NAME,
    471		.pm = &pa12203001_pm_ops,
    472		.acpi_match_table = ACPI_PTR(pa12203001_acpi_match),
    473	},
    474	.probe = pa12203001_probe,
    475	.remove = pa12203001_remove,
    476	.id_table = pa12203001_id,
    477
    478};
    479module_i2c_driver(pa12203001_driver);
    480
    481MODULE_AUTHOR("Adriana Reus <adriana.reus@intel.com>");
    482MODULE_DESCRIPTION("Driver for TXC PA12203001 Proximity and Light Sensor");
    483MODULE_LICENSE("GPL v2");