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

iqs62x-keys.c (8838B)


      1// SPDX-License-Identifier: GPL-2.0+
      2/*
      3 * Azoteq IQS620A/621/622/624/625 Keys and Switches
      4 *
      5 * Copyright (C) 2019 Jeff LaBundy <jeff@labundy.com>
      6 */
      7
      8#include <linux/device.h>
      9#include <linux/input.h>
     10#include <linux/kernel.h>
     11#include <linux/mfd/iqs62x.h>
     12#include <linux/module.h>
     13#include <linux/notifier.h>
     14#include <linux/platform_device.h>
     15#include <linux/property.h>
     16#include <linux/regmap.h>
     17#include <linux/slab.h>
     18
     19enum {
     20	IQS62X_SW_HALL_N,
     21	IQS62X_SW_HALL_S,
     22};
     23
     24static const char * const iqs62x_switch_names[] = {
     25	[IQS62X_SW_HALL_N] = "hall-switch-north",
     26	[IQS62X_SW_HALL_S] = "hall-switch-south",
     27};
     28
     29struct iqs62x_switch_desc {
     30	enum iqs62x_event_flag flag;
     31	unsigned int code;
     32	bool enabled;
     33};
     34
     35struct iqs62x_keys_private {
     36	struct iqs62x_core *iqs62x;
     37	struct input_dev *input;
     38	struct notifier_block notifier;
     39	struct iqs62x_switch_desc switches[ARRAY_SIZE(iqs62x_switch_names)];
     40	unsigned int keycode[IQS62X_NUM_KEYS];
     41	unsigned int keycodemax;
     42	u8 interval;
     43};
     44
     45static int iqs62x_keys_parse_prop(struct platform_device *pdev,
     46				  struct iqs62x_keys_private *iqs62x_keys)
     47{
     48	struct fwnode_handle *child;
     49	unsigned int val;
     50	int ret, i;
     51
     52	ret = device_property_count_u32(&pdev->dev, "linux,keycodes");
     53	if (ret > IQS62X_NUM_KEYS) {
     54		dev_err(&pdev->dev, "Too many keycodes present\n");
     55		return -EINVAL;
     56	} else if (ret < 0) {
     57		dev_err(&pdev->dev, "Failed to count keycodes: %d\n", ret);
     58		return ret;
     59	}
     60	iqs62x_keys->keycodemax = ret;
     61
     62	ret = device_property_read_u32_array(&pdev->dev, "linux,keycodes",
     63					     iqs62x_keys->keycode,
     64					     iqs62x_keys->keycodemax);
     65	if (ret) {
     66		dev_err(&pdev->dev, "Failed to read keycodes: %d\n", ret);
     67		return ret;
     68	}
     69
     70	for (i = 0; i < ARRAY_SIZE(iqs62x_keys->switches); i++) {
     71		child = device_get_named_child_node(&pdev->dev,
     72						    iqs62x_switch_names[i]);
     73		if (!child)
     74			continue;
     75
     76		ret = fwnode_property_read_u32(child, "linux,code", &val);
     77		if (ret) {
     78			dev_err(&pdev->dev, "Failed to read switch code: %d\n",
     79				ret);
     80			return ret;
     81		}
     82		iqs62x_keys->switches[i].code = val;
     83		iqs62x_keys->switches[i].enabled = true;
     84
     85		if (fwnode_property_present(child, "azoteq,use-prox"))
     86			iqs62x_keys->switches[i].flag = (i == IQS62X_SW_HALL_N ?
     87							 IQS62X_EVENT_HALL_N_P :
     88							 IQS62X_EVENT_HALL_S_P);
     89		else
     90			iqs62x_keys->switches[i].flag = (i == IQS62X_SW_HALL_N ?
     91							 IQS62X_EVENT_HALL_N_T :
     92							 IQS62X_EVENT_HALL_S_T);
     93	}
     94
     95	return 0;
     96}
     97
     98static int iqs62x_keys_init(struct iqs62x_keys_private *iqs62x_keys)
     99{
    100	struct iqs62x_core *iqs62x = iqs62x_keys->iqs62x;
    101	enum iqs62x_event_flag flag;
    102	unsigned int event_reg, val;
    103	unsigned int event_mask = 0;
    104	int ret, i;
    105
    106	switch (iqs62x->dev_desc->prod_num) {
    107	case IQS620_PROD_NUM:
    108	case IQS621_PROD_NUM:
    109	case IQS622_PROD_NUM:
    110		event_reg = IQS620_GLBL_EVENT_MASK;
    111
    112		/*
    113		 * Discreet button, hysteresis and SAR UI flags represent keys
    114		 * and are unmasked if mapped to a valid keycode.
    115		 */
    116		for (i = 0; i < iqs62x_keys->keycodemax; i++) {
    117			if (iqs62x_keys->keycode[i] == KEY_RESERVED)
    118				continue;
    119
    120			if (iqs62x_events[i].reg == IQS62X_EVENT_PROX)
    121				event_mask |= iqs62x->dev_desc->prox_mask;
    122			else if (iqs62x_events[i].reg == IQS62X_EVENT_HYST)
    123				event_mask |= (iqs62x->dev_desc->hyst_mask |
    124					       iqs62x->dev_desc->sar_mask);
    125		}
    126
    127		ret = regmap_read(iqs62x->regmap, iqs62x->dev_desc->hall_flags,
    128				  &val);
    129		if (ret)
    130			return ret;
    131
    132		/*
    133		 * Hall UI flags represent switches and are unmasked if their
    134		 * corresponding child nodes are present.
    135		 */
    136		for (i = 0; i < ARRAY_SIZE(iqs62x_keys->switches); i++) {
    137			if (!(iqs62x_keys->switches[i].enabled))
    138				continue;
    139
    140			flag = iqs62x_keys->switches[i].flag;
    141
    142			if (iqs62x_events[flag].reg != IQS62X_EVENT_HALL)
    143				continue;
    144
    145			event_mask |= iqs62x->dev_desc->hall_mask;
    146
    147			input_report_switch(iqs62x_keys->input,
    148					    iqs62x_keys->switches[i].code,
    149					    (val & iqs62x_events[flag].mask) ==
    150					    iqs62x_events[flag].val);
    151		}
    152
    153		input_sync(iqs62x_keys->input);
    154		break;
    155
    156	case IQS624_PROD_NUM:
    157		event_reg = IQS624_HALL_UI;
    158
    159		/*
    160		 * Interval change events represent keys and are unmasked if
    161		 * either wheel movement flag is mapped to a valid keycode.
    162		 */
    163		if (iqs62x_keys->keycode[IQS62X_EVENT_WHEEL_UP] != KEY_RESERVED)
    164			event_mask |= IQS624_HALL_UI_INT_EVENT;
    165
    166		if (iqs62x_keys->keycode[IQS62X_EVENT_WHEEL_DN] != KEY_RESERVED)
    167			event_mask |= IQS624_HALL_UI_INT_EVENT;
    168
    169		ret = regmap_read(iqs62x->regmap, iqs62x->dev_desc->interval,
    170				  &val);
    171		if (ret)
    172			return ret;
    173
    174		iqs62x_keys->interval = val;
    175		break;
    176
    177	default:
    178		return 0;
    179	}
    180
    181	return regmap_update_bits(iqs62x->regmap, event_reg, event_mask, 0);
    182}
    183
    184static int iqs62x_keys_notifier(struct notifier_block *notifier,
    185				unsigned long event_flags, void *context)
    186{
    187	struct iqs62x_event_data *event_data = context;
    188	struct iqs62x_keys_private *iqs62x_keys;
    189	int ret, i;
    190
    191	iqs62x_keys = container_of(notifier, struct iqs62x_keys_private,
    192				   notifier);
    193
    194	if (event_flags & BIT(IQS62X_EVENT_SYS_RESET)) {
    195		ret = iqs62x_keys_init(iqs62x_keys);
    196		if (ret) {
    197			dev_err(iqs62x_keys->input->dev.parent,
    198				"Failed to re-initialize device: %d\n", ret);
    199			return NOTIFY_BAD;
    200		}
    201
    202		return NOTIFY_OK;
    203	}
    204
    205	for (i = 0; i < iqs62x_keys->keycodemax; i++) {
    206		if (iqs62x_events[i].reg == IQS62X_EVENT_WHEEL &&
    207		    event_data->interval == iqs62x_keys->interval)
    208			continue;
    209
    210		input_report_key(iqs62x_keys->input, iqs62x_keys->keycode[i],
    211				 event_flags & BIT(i));
    212	}
    213
    214	for (i = 0; i < ARRAY_SIZE(iqs62x_keys->switches); i++)
    215		if (iqs62x_keys->switches[i].enabled)
    216			input_report_switch(iqs62x_keys->input,
    217					    iqs62x_keys->switches[i].code,
    218					    event_flags &
    219					    BIT(iqs62x_keys->switches[i].flag));
    220
    221	input_sync(iqs62x_keys->input);
    222
    223	if (event_data->interval == iqs62x_keys->interval)
    224		return NOTIFY_OK;
    225
    226	/*
    227	 * Each frame contains at most one wheel event (up or down), in which
    228	 * case a complementary release cycle is emulated.
    229	 */
    230	if (event_flags & BIT(IQS62X_EVENT_WHEEL_UP)) {
    231		input_report_key(iqs62x_keys->input,
    232				 iqs62x_keys->keycode[IQS62X_EVENT_WHEEL_UP],
    233				 0);
    234		input_sync(iqs62x_keys->input);
    235	} else if (event_flags & BIT(IQS62X_EVENT_WHEEL_DN)) {
    236		input_report_key(iqs62x_keys->input,
    237				 iqs62x_keys->keycode[IQS62X_EVENT_WHEEL_DN],
    238				 0);
    239		input_sync(iqs62x_keys->input);
    240	}
    241
    242	iqs62x_keys->interval = event_data->interval;
    243
    244	return NOTIFY_OK;
    245}
    246
    247static int iqs62x_keys_probe(struct platform_device *pdev)
    248{
    249	struct iqs62x_core *iqs62x = dev_get_drvdata(pdev->dev.parent);
    250	struct iqs62x_keys_private *iqs62x_keys;
    251	struct input_dev *input;
    252	int ret, i;
    253
    254	iqs62x_keys = devm_kzalloc(&pdev->dev, sizeof(*iqs62x_keys),
    255				   GFP_KERNEL);
    256	if (!iqs62x_keys)
    257		return -ENOMEM;
    258
    259	platform_set_drvdata(pdev, iqs62x_keys);
    260
    261	ret = iqs62x_keys_parse_prop(pdev, iqs62x_keys);
    262	if (ret)
    263		return ret;
    264
    265	input = devm_input_allocate_device(&pdev->dev);
    266	if (!input)
    267		return -ENOMEM;
    268
    269	input->keycodemax = iqs62x_keys->keycodemax;
    270	input->keycode = iqs62x_keys->keycode;
    271	input->keycodesize = sizeof(*iqs62x_keys->keycode);
    272
    273	input->name = iqs62x->dev_desc->dev_name;
    274	input->id.bustype = BUS_I2C;
    275
    276	for (i = 0; i < iqs62x_keys->keycodemax; i++)
    277		if (iqs62x_keys->keycode[i] != KEY_RESERVED)
    278			input_set_capability(input, EV_KEY,
    279					     iqs62x_keys->keycode[i]);
    280
    281	for (i = 0; i < ARRAY_SIZE(iqs62x_keys->switches); i++)
    282		if (iqs62x_keys->switches[i].enabled)
    283			input_set_capability(input, EV_SW,
    284					     iqs62x_keys->switches[i].code);
    285
    286	iqs62x_keys->iqs62x = iqs62x;
    287	iqs62x_keys->input = input;
    288
    289	ret = iqs62x_keys_init(iqs62x_keys);
    290	if (ret) {
    291		dev_err(&pdev->dev, "Failed to initialize device: %d\n", ret);
    292		return ret;
    293	}
    294
    295	ret = input_register_device(iqs62x_keys->input);
    296	if (ret) {
    297		dev_err(&pdev->dev, "Failed to register device: %d\n", ret);
    298		return ret;
    299	}
    300
    301	iqs62x_keys->notifier.notifier_call = iqs62x_keys_notifier;
    302	ret = blocking_notifier_chain_register(&iqs62x_keys->iqs62x->nh,
    303					       &iqs62x_keys->notifier);
    304	if (ret)
    305		dev_err(&pdev->dev, "Failed to register notifier: %d\n", ret);
    306
    307	return ret;
    308}
    309
    310static int iqs62x_keys_remove(struct platform_device *pdev)
    311{
    312	struct iqs62x_keys_private *iqs62x_keys = platform_get_drvdata(pdev);
    313	int ret;
    314
    315	ret = blocking_notifier_chain_unregister(&iqs62x_keys->iqs62x->nh,
    316						 &iqs62x_keys->notifier);
    317	if (ret)
    318		dev_err(&pdev->dev, "Failed to unregister notifier: %d\n", ret);
    319
    320	return ret;
    321}
    322
    323static struct platform_driver iqs62x_keys_platform_driver = {
    324	.driver = {
    325		.name = "iqs62x-keys",
    326	},
    327	.probe = iqs62x_keys_probe,
    328	.remove = iqs62x_keys_remove,
    329};
    330module_platform_driver(iqs62x_keys_platform_driver);
    331
    332MODULE_AUTHOR("Jeff LaBundy <jeff@labundy.com>");
    333MODULE_DESCRIPTION("Azoteq IQS620A/621/622/624/625 Keys and Switches");
    334MODULE_LICENSE("GPL");
    335MODULE_ALIAS("platform:iqs62x-keys");