197fb5e8dSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
268c581d5SCourtney Cavin /*
3*2fcbda9aSDavid Collins  * Copyright (c) 2010-2011, 2020-2021, The Linux Foundation. All rights reserved.
468c581d5SCourtney Cavin  * Copyright (c) 2014, Sony Mobile Communications Inc.
568c581d5SCourtney Cavin  */
668c581d5SCourtney Cavin 
768c581d5SCourtney Cavin #include <linux/delay.h>
868c581d5SCourtney Cavin #include <linux/errno.h>
968c581d5SCourtney Cavin #include <linux/input.h>
1068c581d5SCourtney Cavin #include <linux/interrupt.h>
1168c581d5SCourtney Cavin #include <linux/kernel.h>
1268c581d5SCourtney Cavin #include <linux/log2.h>
1368c581d5SCourtney Cavin #include <linux/module.h>
1468c581d5SCourtney Cavin #include <linux/of.h>
152049a9e5SVinod Koul #include <linux/of_device.h>
1668c581d5SCourtney Cavin #include <linux/platform_device.h>
1768c581d5SCourtney Cavin #include <linux/reboot.h>
1868c581d5SCourtney Cavin #include <linux/regmap.h>
1968c581d5SCourtney Cavin 
2068c581d5SCourtney Cavin #define PON_REV2			0x01
2168c581d5SCourtney Cavin 
2268c581d5SCourtney Cavin #define PON_RT_STS			0x10
2368c581d5SCourtney Cavin #define  PON_KPDPWR_N_SET		BIT(0)
24955c594eSVinod Koul #define  PON_RESIN_N_SET		BIT(1)
25*2fcbda9aSDavid Collins #define  PON_GEN3_RESIN_N_SET		BIT(6)
26*2fcbda9aSDavid Collins #define  PON_GEN3_KPDPWR_N_SET		BIT(7)
2768c581d5SCourtney Cavin 
2868c581d5SCourtney Cavin #define PON_PS_HOLD_RST_CTL		0x5a
2968c581d5SCourtney Cavin #define PON_PS_HOLD_RST_CTL2		0x5b
3068c581d5SCourtney Cavin #define  PON_PS_HOLD_ENABLE		BIT(7)
3168c581d5SCourtney Cavin #define  PON_PS_HOLD_TYPE_MASK		0x0f
3268c581d5SCourtney Cavin #define  PON_PS_HOLD_TYPE_SHUTDOWN	4
3368c581d5SCourtney Cavin #define  PON_PS_HOLD_TYPE_HARD_RESET	7
3468c581d5SCourtney Cavin 
3568c581d5SCourtney Cavin #define PON_PULL_CTL			0x70
3668c581d5SCourtney Cavin #define  PON_KPDPWR_PULL_UP		BIT(1)
37955c594eSVinod Koul #define  PON_RESIN_PULL_UP		BIT(0)
3868c581d5SCourtney Cavin 
3968c581d5SCourtney Cavin #define PON_DBC_CTL			0x71
4068c581d5SCourtney Cavin #define  PON_DBC_DELAY_MASK		0x7
4168c581d5SCourtney Cavin 
422049a9e5SVinod Koul struct pm8941_data {
432049a9e5SVinod Koul 	unsigned int	pull_up_bit;
442049a9e5SVinod Koul 	unsigned int	status_bit;
45*2fcbda9aSDavid Collins 	bool		supports_ps_hold_poff_config;
46*2fcbda9aSDavid Collins 	bool		supports_debounce_config;
47*2fcbda9aSDavid Collins 	const char	*name;
48*2fcbda9aSDavid Collins 	const char	*phys;
492049a9e5SVinod Koul };
5068c581d5SCourtney Cavin 
5168c581d5SCourtney Cavin struct pm8941_pwrkey {
5268c581d5SCourtney Cavin 	struct device *dev;
5368c581d5SCourtney Cavin 	int irq;
5468c581d5SCourtney Cavin 	u32 baseaddr;
5568c581d5SCourtney Cavin 	struct regmap *regmap;
5668c581d5SCourtney Cavin 	struct input_dev *input;
5768c581d5SCourtney Cavin 
5868c581d5SCourtney Cavin 	unsigned int revision;
5968c581d5SCourtney Cavin 	struct notifier_block reboot_notifier;
602049a9e5SVinod Koul 
612049a9e5SVinod Koul 	u32 code;
622049a9e5SVinod Koul 	const struct pm8941_data *data;
6368c581d5SCourtney Cavin };
6468c581d5SCourtney Cavin 
6568c581d5SCourtney Cavin static int pm8941_reboot_notify(struct notifier_block *nb,
6668c581d5SCourtney Cavin 				unsigned long code, void *unused)
6768c581d5SCourtney Cavin {
6868c581d5SCourtney Cavin 	struct pm8941_pwrkey *pwrkey = container_of(nb, struct pm8941_pwrkey,
6968c581d5SCourtney Cavin 						    reboot_notifier);
7068c581d5SCourtney Cavin 	unsigned int enable_reg;
7168c581d5SCourtney Cavin 	unsigned int reset_type;
7268c581d5SCourtney Cavin 	int error;
7368c581d5SCourtney Cavin 
7468c581d5SCourtney Cavin 	/* PMICs with revision 0 have the enable bit in same register as ctrl */
7568c581d5SCourtney Cavin 	if (pwrkey->revision == 0)
7668c581d5SCourtney Cavin 		enable_reg = PON_PS_HOLD_RST_CTL;
7768c581d5SCourtney Cavin 	else
7868c581d5SCourtney Cavin 		enable_reg = PON_PS_HOLD_RST_CTL2;
7968c581d5SCourtney Cavin 
8068c581d5SCourtney Cavin 	error = regmap_update_bits(pwrkey->regmap,
8168c581d5SCourtney Cavin 				   pwrkey->baseaddr + enable_reg,
8268c581d5SCourtney Cavin 				   PON_PS_HOLD_ENABLE,
8368c581d5SCourtney Cavin 				   0);
8468c581d5SCourtney Cavin 	if (error)
8568c581d5SCourtney Cavin 		dev_err(pwrkey->dev,
8668c581d5SCourtney Cavin 			"unable to clear ps hold reset enable: %d\n",
8768c581d5SCourtney Cavin 			error);
8868c581d5SCourtney Cavin 
8968c581d5SCourtney Cavin 	/*
9068c581d5SCourtney Cavin 	 * Updates of PON_PS_HOLD_ENABLE requires 3 sleep cycles between
9168c581d5SCourtney Cavin 	 * writes.
9268c581d5SCourtney Cavin 	 */
9368c581d5SCourtney Cavin 	usleep_range(100, 1000);
9468c581d5SCourtney Cavin 
9568c581d5SCourtney Cavin 	switch (code) {
9668c581d5SCourtney Cavin 	case SYS_HALT:
9768c581d5SCourtney Cavin 	case SYS_POWER_OFF:
9868c581d5SCourtney Cavin 		reset_type = PON_PS_HOLD_TYPE_SHUTDOWN;
9968c581d5SCourtney Cavin 		break;
10068c581d5SCourtney Cavin 	case SYS_RESTART:
10168c581d5SCourtney Cavin 	default:
10268c581d5SCourtney Cavin 		reset_type = PON_PS_HOLD_TYPE_HARD_RESET;
10368c581d5SCourtney Cavin 		break;
104b9ab471bSJavier Martinez Canillas 	}
10568c581d5SCourtney Cavin 
10668c581d5SCourtney Cavin 	error = regmap_update_bits(pwrkey->regmap,
10768c581d5SCourtney Cavin 				   pwrkey->baseaddr + PON_PS_HOLD_RST_CTL,
10868c581d5SCourtney Cavin 				   PON_PS_HOLD_TYPE_MASK,
10968c581d5SCourtney Cavin 				   reset_type);
11068c581d5SCourtney Cavin 	if (error)
11168c581d5SCourtney Cavin 		dev_err(pwrkey->dev, "unable to set ps hold reset type: %d\n",
11268c581d5SCourtney Cavin 			error);
11368c581d5SCourtney Cavin 
11468c581d5SCourtney Cavin 	error = regmap_update_bits(pwrkey->regmap,
11568c581d5SCourtney Cavin 				   pwrkey->baseaddr + enable_reg,
11668c581d5SCourtney Cavin 				   PON_PS_HOLD_ENABLE,
11768c581d5SCourtney Cavin 				   PON_PS_HOLD_ENABLE);
11868c581d5SCourtney Cavin 	if (error)
11968c581d5SCourtney Cavin 		dev_err(pwrkey->dev, "unable to re-set enable: %d\n", error);
12068c581d5SCourtney Cavin 
12168c581d5SCourtney Cavin 	return NOTIFY_DONE;
12268c581d5SCourtney Cavin }
12368c581d5SCourtney Cavin 
12468c581d5SCourtney Cavin static irqreturn_t pm8941_pwrkey_irq(int irq, void *_data)
12568c581d5SCourtney Cavin {
12668c581d5SCourtney Cavin 	struct pm8941_pwrkey *pwrkey = _data;
12768c581d5SCourtney Cavin 	unsigned int sts;
12868c581d5SCourtney Cavin 	int error;
12968c581d5SCourtney Cavin 
13068c581d5SCourtney Cavin 	error = regmap_read(pwrkey->regmap,
13168c581d5SCourtney Cavin 			    pwrkey->baseaddr + PON_RT_STS, &sts);
13268c581d5SCourtney Cavin 	if (error)
13368c581d5SCourtney Cavin 		return IRQ_HANDLED;
13468c581d5SCourtney Cavin 
1352049a9e5SVinod Koul 	input_report_key(pwrkey->input, pwrkey->code,
1362049a9e5SVinod Koul 			 sts & pwrkey->data->status_bit);
13768c581d5SCourtney Cavin 	input_sync(pwrkey->input);
13868c581d5SCourtney Cavin 
13968c581d5SCourtney Cavin 	return IRQ_HANDLED;
14068c581d5SCourtney Cavin }
14168c581d5SCourtney Cavin 
14268c581d5SCourtney Cavin static int __maybe_unused pm8941_pwrkey_suspend(struct device *dev)
14368c581d5SCourtney Cavin {
14468c581d5SCourtney Cavin 	struct pm8941_pwrkey *pwrkey = dev_get_drvdata(dev);
14568c581d5SCourtney Cavin 
14668c581d5SCourtney Cavin 	if (device_may_wakeup(dev))
14768c581d5SCourtney Cavin 		enable_irq_wake(pwrkey->irq);
14868c581d5SCourtney Cavin 
14968c581d5SCourtney Cavin 	return 0;
15068c581d5SCourtney Cavin }
15168c581d5SCourtney Cavin 
15268c581d5SCourtney Cavin static int __maybe_unused pm8941_pwrkey_resume(struct device *dev)
15368c581d5SCourtney Cavin {
15468c581d5SCourtney Cavin 	struct pm8941_pwrkey *pwrkey = dev_get_drvdata(dev);
15568c581d5SCourtney Cavin 
15668c581d5SCourtney Cavin 	if (device_may_wakeup(dev))
15768c581d5SCourtney Cavin 		disable_irq_wake(pwrkey->irq);
15868c581d5SCourtney Cavin 
15968c581d5SCourtney Cavin 	return 0;
16068c581d5SCourtney Cavin }
16168c581d5SCourtney Cavin 
16268c581d5SCourtney Cavin static SIMPLE_DEV_PM_OPS(pm8941_pwr_key_pm_ops,
16368c581d5SCourtney Cavin 			 pm8941_pwrkey_suspend, pm8941_pwrkey_resume);
16468c581d5SCourtney Cavin 
16568c581d5SCourtney Cavin static int pm8941_pwrkey_probe(struct platform_device *pdev)
16668c581d5SCourtney Cavin {
16768c581d5SCourtney Cavin 	struct pm8941_pwrkey *pwrkey;
16868c581d5SCourtney Cavin 	bool pull_up;
1692049a9e5SVinod Koul 	struct device *parent;
17068c581d5SCourtney Cavin 	u32 req_delay;
17168c581d5SCourtney Cavin 	int error;
17268c581d5SCourtney Cavin 
17368c581d5SCourtney Cavin 	if (of_property_read_u32(pdev->dev.of_node, "debounce", &req_delay))
17468c581d5SCourtney Cavin 		req_delay = 15625;
17568c581d5SCourtney Cavin 
17668c581d5SCourtney Cavin 	if (req_delay > 2000000 || req_delay == 0) {
17768c581d5SCourtney Cavin 		dev_err(&pdev->dev, "invalid debounce time: %u\n", req_delay);
17868c581d5SCourtney Cavin 		return -EINVAL;
17968c581d5SCourtney Cavin 	}
18068c581d5SCourtney Cavin 
18168c581d5SCourtney Cavin 	pull_up = of_property_read_bool(pdev->dev.of_node, "bias-pull-up");
18268c581d5SCourtney Cavin 
18368c581d5SCourtney Cavin 	pwrkey = devm_kzalloc(&pdev->dev, sizeof(*pwrkey), GFP_KERNEL);
18468c581d5SCourtney Cavin 	if (!pwrkey)
18568c581d5SCourtney Cavin 		return -ENOMEM;
18668c581d5SCourtney Cavin 
18768c581d5SCourtney Cavin 	pwrkey->dev = &pdev->dev;
1882049a9e5SVinod Koul 	pwrkey->data = of_device_get_match_data(&pdev->dev);
18968c581d5SCourtney Cavin 
1902049a9e5SVinod Koul 	parent = pdev->dev.parent;
1912049a9e5SVinod Koul 	pwrkey->regmap = dev_get_regmap(parent, NULL);
1922049a9e5SVinod Koul 	if (!pwrkey->regmap) {
1932049a9e5SVinod Koul 		/*
1942049a9e5SVinod Koul 		 * We failed to get regmap for parent. Let's see if we are
1952049a9e5SVinod Koul 		 * a child of pon node and read regmap and reg from its
1962049a9e5SVinod Koul 		 * parent.
1972049a9e5SVinod Koul 		 */
1982049a9e5SVinod Koul 		pwrkey->regmap = dev_get_regmap(parent->parent, NULL);
19968c581d5SCourtney Cavin 		if (!pwrkey->regmap) {
20068c581d5SCourtney Cavin 			dev_err(&pdev->dev, "failed to locate regmap\n");
20168c581d5SCourtney Cavin 			return -ENODEV;
20268c581d5SCourtney Cavin 		}
20368c581d5SCourtney Cavin 
2042049a9e5SVinod Koul 		error = of_property_read_u32(parent->of_node,
2052049a9e5SVinod Koul 					     "reg", &pwrkey->baseaddr);
2062049a9e5SVinod Koul 	} else {
2072049a9e5SVinod Koul 		error = of_property_read_u32(pdev->dev.of_node, "reg",
2082049a9e5SVinod Koul 					     &pwrkey->baseaddr);
2092049a9e5SVinod Koul 	}
2102049a9e5SVinod Koul 	if (error)
2112049a9e5SVinod Koul 		return error;
2122049a9e5SVinod Koul 
21368c581d5SCourtney Cavin 	pwrkey->irq = platform_get_irq(pdev, 0);
2140bec8b7eSStephen Boyd 	if (pwrkey->irq < 0)
21568c581d5SCourtney Cavin 		return pwrkey->irq;
21668c581d5SCourtney Cavin 
21768c581d5SCourtney Cavin 	error = regmap_read(pwrkey->regmap, pwrkey->baseaddr + PON_REV2,
21868c581d5SCourtney Cavin 			    &pwrkey->revision);
21968c581d5SCourtney Cavin 	if (error) {
22068c581d5SCourtney Cavin 		dev_err(&pdev->dev, "failed to set debounce: %d\n", error);
22168c581d5SCourtney Cavin 		return error;
22268c581d5SCourtney Cavin 	}
22368c581d5SCourtney Cavin 
2242049a9e5SVinod Koul 	error = of_property_read_u32(pdev->dev.of_node, "linux,code",
2252049a9e5SVinod Koul 				     &pwrkey->code);
2262049a9e5SVinod Koul 	if (error) {
2272049a9e5SVinod Koul 		dev_dbg(&pdev->dev,
2282049a9e5SVinod Koul 			"no linux,code assuming power (%d)\n", error);
2292049a9e5SVinod Koul 		pwrkey->code = KEY_POWER;
2302049a9e5SVinod Koul 	}
2312049a9e5SVinod Koul 
23268c581d5SCourtney Cavin 	pwrkey->input = devm_input_allocate_device(&pdev->dev);
23368c581d5SCourtney Cavin 	if (!pwrkey->input) {
23468c581d5SCourtney Cavin 		dev_dbg(&pdev->dev, "unable to allocate input device\n");
23568c581d5SCourtney Cavin 		return -ENOMEM;
23668c581d5SCourtney Cavin 	}
23768c581d5SCourtney Cavin 
2382049a9e5SVinod Koul 	input_set_capability(pwrkey->input, EV_KEY, pwrkey->code);
23968c581d5SCourtney Cavin 
240*2fcbda9aSDavid Collins 	pwrkey->input->name = pwrkey->data->name;
241*2fcbda9aSDavid Collins 	pwrkey->input->phys = pwrkey->data->phys;
24268c581d5SCourtney Cavin 
243*2fcbda9aSDavid Collins 	if (pwrkey->data->supports_debounce_config) {
24468c581d5SCourtney Cavin 		req_delay = (req_delay << 6) / USEC_PER_SEC;
24568c581d5SCourtney Cavin 		req_delay = ilog2(req_delay);
24668c581d5SCourtney Cavin 
24768c581d5SCourtney Cavin 		error = regmap_update_bits(pwrkey->regmap,
24868c581d5SCourtney Cavin 					   pwrkey->baseaddr + PON_DBC_CTL,
24968c581d5SCourtney Cavin 					   PON_DBC_DELAY_MASK,
25068c581d5SCourtney Cavin 					   req_delay);
25168c581d5SCourtney Cavin 		if (error) {
252*2fcbda9aSDavid Collins 			dev_err(&pdev->dev, "failed to set debounce: %d\n",
253*2fcbda9aSDavid Collins 				error);
25468c581d5SCourtney Cavin 			return error;
25568c581d5SCourtney Cavin 		}
256*2fcbda9aSDavid Collins 	}
25768c581d5SCourtney Cavin 
258*2fcbda9aSDavid Collins 	if (pwrkey->data->pull_up_bit) {
25968c581d5SCourtney Cavin 		error = regmap_update_bits(pwrkey->regmap,
26068c581d5SCourtney Cavin 					   pwrkey->baseaddr + PON_PULL_CTL,
2612049a9e5SVinod Koul 					   pwrkey->data->pull_up_bit,
262*2fcbda9aSDavid Collins 					   pull_up ? pwrkey->data->pull_up_bit :
263*2fcbda9aSDavid Collins 						     0);
26468c581d5SCourtney Cavin 		if (error) {
26568c581d5SCourtney Cavin 			dev_err(&pdev->dev, "failed to set pull: %d\n", error);
26668c581d5SCourtney Cavin 			return error;
26768c581d5SCourtney Cavin 		}
268*2fcbda9aSDavid Collins 	}
26968c581d5SCourtney Cavin 
27068c581d5SCourtney Cavin 	error = devm_request_threaded_irq(&pdev->dev, pwrkey->irq,
27168c581d5SCourtney Cavin 					  NULL, pm8941_pwrkey_irq,
27268c581d5SCourtney Cavin 					  IRQF_ONESHOT,
273*2fcbda9aSDavid Collins 					  pwrkey->data->name, pwrkey);
27468c581d5SCourtney Cavin 	if (error) {
27568c581d5SCourtney Cavin 		dev_err(&pdev->dev, "failed requesting IRQ: %d\n", error);
27668c581d5SCourtney Cavin 		return error;
27768c581d5SCourtney Cavin 	}
27868c581d5SCourtney Cavin 
27968c581d5SCourtney Cavin 	error = input_register_device(pwrkey->input);
28068c581d5SCourtney Cavin 	if (error) {
28168c581d5SCourtney Cavin 		dev_err(&pdev->dev, "failed to register input device: %d\n",
28268c581d5SCourtney Cavin 			error);
28368c581d5SCourtney Cavin 		return error;
28468c581d5SCourtney Cavin 	}
28568c581d5SCourtney Cavin 
286*2fcbda9aSDavid Collins 	if (pwrkey->data->supports_ps_hold_poff_config) {
28768c581d5SCourtney Cavin 		pwrkey->reboot_notifier.notifier_call = pm8941_reboot_notify,
28868c581d5SCourtney Cavin 		error = register_reboot_notifier(&pwrkey->reboot_notifier);
28968c581d5SCourtney Cavin 		if (error) {
29068c581d5SCourtney Cavin 			dev_err(&pdev->dev, "failed to register reboot notifier: %d\n",
29168c581d5SCourtney Cavin 				error);
29268c581d5SCourtney Cavin 			return error;
29368c581d5SCourtney Cavin 		}
294*2fcbda9aSDavid Collins 	}
29568c581d5SCourtney Cavin 
29668c581d5SCourtney Cavin 	platform_set_drvdata(pdev, pwrkey);
29768c581d5SCourtney Cavin 	device_init_wakeup(&pdev->dev, 1);
29868c581d5SCourtney Cavin 
29968c581d5SCourtney Cavin 	return 0;
30068c581d5SCourtney Cavin }
30168c581d5SCourtney Cavin 
30268c581d5SCourtney Cavin static int pm8941_pwrkey_remove(struct platform_device *pdev)
30368c581d5SCourtney Cavin {
30468c581d5SCourtney Cavin 	struct pm8941_pwrkey *pwrkey = platform_get_drvdata(pdev);
30568c581d5SCourtney Cavin 
306*2fcbda9aSDavid Collins 	if (pwrkey->data->supports_ps_hold_poff_config)
30768c581d5SCourtney Cavin 		unregister_reboot_notifier(&pwrkey->reboot_notifier);
30868c581d5SCourtney Cavin 
30968c581d5SCourtney Cavin 	return 0;
31068c581d5SCourtney Cavin }
31168c581d5SCourtney Cavin 
3122049a9e5SVinod Koul static const struct pm8941_data pwrkey_data = {
3132049a9e5SVinod Koul 	.pull_up_bit = PON_KPDPWR_PULL_UP,
3142049a9e5SVinod Koul 	.status_bit = PON_KPDPWR_N_SET,
315*2fcbda9aSDavid Collins 	.name = "pm8941_pwrkey",
316*2fcbda9aSDavid Collins 	.phys = "pm8941_pwrkey/input0",
317*2fcbda9aSDavid Collins 	.supports_ps_hold_poff_config = true,
318*2fcbda9aSDavid Collins 	.supports_debounce_config = true,
3192049a9e5SVinod Koul };
3202049a9e5SVinod Koul 
321955c594eSVinod Koul static const struct pm8941_data resin_data = {
322955c594eSVinod Koul 	.pull_up_bit = PON_RESIN_PULL_UP,
323955c594eSVinod Koul 	.status_bit = PON_RESIN_N_SET,
324*2fcbda9aSDavid Collins 	.name = "pm8941_resin",
325*2fcbda9aSDavid Collins 	.phys = "pm8941_resin/input0",
326*2fcbda9aSDavid Collins 	.supports_ps_hold_poff_config = true,
327*2fcbda9aSDavid Collins 	.supports_debounce_config = true,
328*2fcbda9aSDavid Collins };
329*2fcbda9aSDavid Collins 
330*2fcbda9aSDavid Collins static const struct pm8941_data pon_gen3_pwrkey_data = {
331*2fcbda9aSDavid Collins 	.status_bit = PON_GEN3_KPDPWR_N_SET,
332*2fcbda9aSDavid Collins 	.name = "pmic_pwrkey",
333*2fcbda9aSDavid Collins 	.phys = "pmic_pwrkey/input0",
334*2fcbda9aSDavid Collins 	.supports_ps_hold_poff_config = false,
335*2fcbda9aSDavid Collins 	.supports_debounce_config = false,
336*2fcbda9aSDavid Collins };
337*2fcbda9aSDavid Collins 
338*2fcbda9aSDavid Collins static const struct pm8941_data pon_gen3_resin_data = {
339*2fcbda9aSDavid Collins 	.status_bit = PON_GEN3_RESIN_N_SET,
340*2fcbda9aSDavid Collins 	.name = "pmic_resin",
341*2fcbda9aSDavid Collins 	.phys = "pmic_resin/input0",
342*2fcbda9aSDavid Collins 	.supports_ps_hold_poff_config = false,
343*2fcbda9aSDavid Collins 	.supports_debounce_config = false,
344955c594eSVinod Koul };
345955c594eSVinod Koul 
34668c581d5SCourtney Cavin static const struct of_device_id pm8941_pwr_key_id_table[] = {
3472049a9e5SVinod Koul 	{ .compatible = "qcom,pm8941-pwrkey", .data = &pwrkey_data },
348955c594eSVinod Koul 	{ .compatible = "qcom,pm8941-resin", .data = &resin_data },
349*2fcbda9aSDavid Collins 	{ .compatible = "qcom,pmk8350-pwrkey", .data = &pon_gen3_pwrkey_data },
350*2fcbda9aSDavid Collins 	{ .compatible = "qcom,pmk8350-resin", .data = &pon_gen3_resin_data },
35168c581d5SCourtney Cavin 	{ }
35268c581d5SCourtney Cavin };
35368c581d5SCourtney Cavin MODULE_DEVICE_TABLE(of, pm8941_pwr_key_id_table);
35468c581d5SCourtney Cavin 
35568c581d5SCourtney Cavin static struct platform_driver pm8941_pwrkey_driver = {
35668c581d5SCourtney Cavin 	.probe = pm8941_pwrkey_probe,
35768c581d5SCourtney Cavin 	.remove = pm8941_pwrkey_remove,
35868c581d5SCourtney Cavin 	.driver = {
35968c581d5SCourtney Cavin 		.name = "pm8941-pwrkey",
36068c581d5SCourtney Cavin 		.pm = &pm8941_pwr_key_pm_ops,
36168c581d5SCourtney Cavin 		.of_match_table = of_match_ptr(pm8941_pwr_key_id_table),
36268c581d5SCourtney Cavin 	},
36368c581d5SCourtney Cavin };
36468c581d5SCourtney Cavin module_platform_driver(pm8941_pwrkey_driver);
36568c581d5SCourtney Cavin 
36668c581d5SCourtney Cavin MODULE_DESCRIPTION("PM8941 Power Key driver");
36768c581d5SCourtney Cavin MODULE_LICENSE("GPL v2");
368