File Index
Files and directories
Sign in
FILE

intel_soc_pmic_bxtwc.c

File preview with syntax highlighting.

linux-6.19.14/drivers/mfd/intel_soc_pmic_bxtwc.c C
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * MFD core driver for Intel Broxton Whiskey Cove PMIC
  4 *
  5 * Copyright (C) 2015-2017, 2022 Intel Corporation. All rights reserved.
  6 */
  7
  8#include <linux/acpi.h>
  9#include <linux/array_size.h>
 10#include <linux/bits.h>
 11#include <linux/delay.h>
 12#include <linux/device.h>
 13#include <linux/err.h>
 14#include <linux/errno.h>
 15#include <linux/gfp_types.h>
 16#include <linux/interrupt.h>
 17#include <linux/ioport.h>
 18#include <linux/kstrtox.h>
 19#include <linux/mfd/core.h>
 20#include <linux/mfd/intel_soc_pmic.h>
 21#include <linux/mfd/intel_soc_pmic_bxtwc.h>
 22#include <linux/mod_devicetable.h>
 23#include <linux/module.h>
 24#include <linux/platform_data/x86/intel_scu_ipc.h>
 25#include <linux/platform_device.h>
 26#include <linux/pm.h>
 27#include <linux/regmap.h>
 28#include <linux/sysfs.h>
 29#include <linux/types.h>
 30
 31/* PMIC device registers */
 32#define REG_ADDR_MASK		GENMASK(15, 8)
 33#define REG_ADDR_SHIFT		8
 34#define REG_OFFSET_MASK		GENMASK(7, 0)
 35
 36/* Interrupt Status Registers */
 37#define BXTWC_IRQLVL1		0x4E02
 38
 39#define BXTWC_PWRBTNIRQ		0x4E03
 40#define BXTWC_THRM0IRQ		0x4E04
 41#define BXTWC_THRM1IRQ		0x4E05
 42#define BXTWC_THRM2IRQ		0x4E06
 43#define BXTWC_BCUIRQ		0x4E07
 44#define BXTWC_ADCIRQ		0x4E08
 45#define BXTWC_CHGR0IRQ		0x4E09
 46#define BXTWC_CHGR1IRQ		0x4E0A
 47#define BXTWC_GPIOIRQ0		0x4E0B
 48#define BXTWC_GPIOIRQ1		0x4E0C
 49#define BXTWC_CRITIRQ		0x4E0D
 50#define BXTWC_TMUIRQ		0x4FB6
 51
 52/* Interrupt MASK Registers */
 53#define BXTWC_MIRQLVL1		0x4E0E
 54#define BXTWC_MIRQLVL1_MCHGR	BIT(5)
 55
 56#define BXTWC_MPWRBTNIRQ	0x4E0F
 57#define BXTWC_MTHRM0IRQ		0x4E12
 58#define BXTWC_MTHRM1IRQ		0x4E13
 59#define BXTWC_MTHRM2IRQ		0x4E14
 60#define BXTWC_MBCUIRQ		0x4E15
 61#define BXTWC_MADCIRQ		0x4E16
 62#define BXTWC_MCHGR0IRQ		0x4E17
 63#define BXTWC_MCHGR1IRQ		0x4E18
 64#define BXTWC_MGPIO0IRQ		0x4E19
 65#define BXTWC_MGPIO1IRQ		0x4E1A
 66#define BXTWC_MCRITIRQ		0x4E1B
 67#define BXTWC_MTMUIRQ		0x4FB7
 68
 69/* Whiskey Cove PMIC share same ACPI ID between different platforms */
 70#define BROXTON_PMIC_WC_HRV	4
 71
 72#define PMC_PMIC_ACCESS		0xFF
 73#define PMC_PMIC_READ		0x0
 74#define PMC_PMIC_WRITE		0x1
 75
 76enum bxtwc_irqs {
 77	BXTWC_PWRBTN_LVL1_IRQ = 0,
 78	BXTWC_TMU_LVL1_IRQ,
 79	BXTWC_THRM_LVL1_IRQ,
 80	BXTWC_BCU_LVL1_IRQ,
 81	BXTWC_ADC_LVL1_IRQ,
 82	BXTWC_CHGR_LVL1_IRQ,
 83	BXTWC_GPIO_LVL1_IRQ,
 84	BXTWC_CRIT_LVL1_IRQ,
 85};
 86
 87enum bxtwc_irqs_pwrbtn {
 88	BXTWC_PWRBTN_IRQ = 0,
 89	BXTWC_UIBTN_IRQ,
 90};
 91
 92enum bxtwc_irqs_bcu {
 93	BXTWC_BCU_IRQ = 0,
 94};
 95
 96enum bxtwc_irqs_adc {
 97	BXTWC_ADC_IRQ = 0,
 98};
 99
100enum bxtwc_irqs_chgr {
101	BXTWC_USBC_IRQ = 0,
102	BXTWC_CHGR0_IRQ,
103	BXTWC_CHGR1_IRQ,
104};
105
106enum bxtwc_irqs_tmu {
107	BXTWC_TMU_IRQ = 0,
108};
109
110enum bxtwc_irqs_crit {
111	BXTWC_CRIT_IRQ = 0,
112};
113
114static const struct regmap_irq bxtwc_regmap_irqs[] = {
115	REGMAP_IRQ_REG(BXTWC_PWRBTN_LVL1_IRQ, 0, BIT(0)),
116	REGMAP_IRQ_REG(BXTWC_TMU_LVL1_IRQ, 0, BIT(1)),
117	REGMAP_IRQ_REG(BXTWC_THRM_LVL1_IRQ, 0, BIT(2)),
118	REGMAP_IRQ_REG(BXTWC_BCU_LVL1_IRQ, 0, BIT(3)),
119	REGMAP_IRQ_REG(BXTWC_ADC_LVL1_IRQ, 0, BIT(4)),
120	REGMAP_IRQ_REG(BXTWC_CHGR_LVL1_IRQ, 0, BIT(5)),
121	REGMAP_IRQ_REG(BXTWC_GPIO_LVL1_IRQ, 0, BIT(6)),
122	REGMAP_IRQ_REG(BXTWC_CRIT_LVL1_IRQ, 0, BIT(7)),
123};
124
125static const struct regmap_irq bxtwc_regmap_irqs_pwrbtn[] = {
126	REGMAP_IRQ_REG(BXTWC_PWRBTN_IRQ, 0, BIT(0)),
127};
128
129static const struct regmap_irq bxtwc_regmap_irqs_bcu[] = {
130	REGMAP_IRQ_REG(BXTWC_BCU_IRQ, 0, GENMASK(4, 0)),
131};
132
133static const struct regmap_irq bxtwc_regmap_irqs_adc[] = {
134	REGMAP_IRQ_REG(BXTWC_ADC_IRQ, 0, GENMASK(7, 0)),
135};
136
137static const struct regmap_irq bxtwc_regmap_irqs_chgr[] = {
138	REGMAP_IRQ_REG(BXTWC_USBC_IRQ, 0, BIT(5)),
139	REGMAP_IRQ_REG(BXTWC_CHGR0_IRQ, 0, GENMASK(4, 0)),
140	REGMAP_IRQ_REG(BXTWC_CHGR1_IRQ, 1, GENMASK(4, 0)),
141};
142
143static const struct regmap_irq bxtwc_regmap_irqs_tmu[] = {
144	REGMAP_IRQ_REG(BXTWC_TMU_IRQ, 0, GENMASK(2, 1)),
145};
146
147static const struct regmap_irq bxtwc_regmap_irqs_crit[] = {
148	REGMAP_IRQ_REG(BXTWC_CRIT_IRQ, 0, GENMASK(1, 0)),
149};
150
151static const struct regmap_irq_chip bxtwc_regmap_irq_chip = {
152	.name = "bxtwc_irq_chip",
153	.status_base = BXTWC_IRQLVL1,
154	.mask_base = BXTWC_MIRQLVL1,
155	.irqs = bxtwc_regmap_irqs,
156	.num_irqs = ARRAY_SIZE(bxtwc_regmap_irqs),
157	.num_regs = 1,
158};
159
160static const struct regmap_irq_chip bxtwc_regmap_irq_chip_pwrbtn = {
161	.name = "bxtwc_irq_chip_pwrbtn",
162	.domain_suffix = "PWRBTN",
163	.status_base = BXTWC_PWRBTNIRQ,
164	.mask_base = BXTWC_MPWRBTNIRQ,
165	.irqs = bxtwc_regmap_irqs_pwrbtn,
166	.num_irqs = ARRAY_SIZE(bxtwc_regmap_irqs_pwrbtn),
167	.num_regs = 1,
168};
169
170static const struct regmap_irq_chip bxtwc_regmap_irq_chip_tmu = {
171	.name = "bxtwc_irq_chip_tmu",
172	.domain_suffix = "TMU",
173	.status_base = BXTWC_TMUIRQ,
174	.mask_base = BXTWC_MTMUIRQ,
175	.irqs = bxtwc_regmap_irqs_tmu,
176	.num_irqs = ARRAY_SIZE(bxtwc_regmap_irqs_tmu),
177	.num_regs = 1,
178};
179
180static const struct regmap_irq_chip bxtwc_regmap_irq_chip_bcu = {
181	.name = "bxtwc_irq_chip_bcu",
182	.domain_suffix = "BCU",
183	.status_base = BXTWC_BCUIRQ,
184	.mask_base = BXTWC_MBCUIRQ,
185	.irqs = bxtwc_regmap_irqs_bcu,
186	.num_irqs = ARRAY_SIZE(bxtwc_regmap_irqs_bcu),
187	.num_regs = 1,
188};
189
190static const struct regmap_irq_chip bxtwc_regmap_irq_chip_adc = {
191	.name = "bxtwc_irq_chip_adc",
192	.domain_suffix = "ADC",
193	.status_base = BXTWC_ADCIRQ,
194	.mask_base = BXTWC_MADCIRQ,
195	.irqs = bxtwc_regmap_irqs_adc,
196	.num_irqs = ARRAY_SIZE(bxtwc_regmap_irqs_adc),
197	.num_regs = 1,
198};
199
200static const struct regmap_irq_chip bxtwc_regmap_irq_chip_chgr = {
201	.name = "bxtwc_irq_chip_chgr",
202	.domain_suffix = "CHGR",
203	.status_base = BXTWC_CHGR0IRQ,
204	.mask_base = BXTWC_MCHGR0IRQ,
205	.irqs = bxtwc_regmap_irqs_chgr,
206	.num_irqs = ARRAY_SIZE(bxtwc_regmap_irqs_chgr),
207	.num_regs = 2,
208};
209
210static const struct regmap_irq_chip bxtwc_regmap_irq_chip_crit = {
211	.name = "bxtwc_irq_chip_crit",
212	.domain_suffix = "CRIT",
213	.status_base = BXTWC_CRITIRQ,
214	.mask_base = BXTWC_MCRITIRQ,
215	.irqs = bxtwc_regmap_irqs_crit,
216	.num_irqs = ARRAY_SIZE(bxtwc_regmap_irqs_crit),
217	.num_regs = 1,
218};
219
220static const struct resource gpio_resources[] = {
221	DEFINE_RES_IRQ_NAMED(BXTWC_GPIO_LVL1_IRQ, "GPIO"),
222};
223
224static const struct resource adc_resources[] = {
225	DEFINE_RES_IRQ_NAMED(BXTWC_ADC_IRQ, "ADC"),
226};
227
228static const struct resource usbc_resources[] = {
229	DEFINE_RES_IRQ(BXTWC_USBC_IRQ),
230};
231
232static const struct resource charger_resources[] = {
233	DEFINE_RES_IRQ_NAMED(BXTWC_CHGR0_IRQ, "CHARGER"),
234	DEFINE_RES_IRQ_NAMED(BXTWC_CHGR1_IRQ, "CHARGER1"),
235};
236
237static const struct resource thermal_resources[] = {
238	DEFINE_RES_IRQ(BXTWC_THRM_LVL1_IRQ),
239};
240
241static const struct resource bcu_resources[] = {
242	DEFINE_RES_IRQ_NAMED(BXTWC_BCU_IRQ, "BCU"),
243};
244
245static const struct resource tmu_resources[] = {
246	DEFINE_RES_IRQ_NAMED(BXTWC_TMU_IRQ, "TMU"),
247};
248
249static struct mfd_cell bxt_wc_dev[] = {
250	{
251		.name = "bxt_wcove_thermal",
252		.num_resources = ARRAY_SIZE(thermal_resources),
253		.resources = thermal_resources,
254	},
255	{
256		.name = "bxt_wcove_gpio",
257		.num_resources = ARRAY_SIZE(gpio_resources),
258		.resources = gpio_resources,
259	},
260	{
261		.name = "bxt_wcove_region",
262	},
263};
264
265static const struct mfd_cell bxt_wc_tmu_dev[] = {
266	{
267		.name = "bxt_wcove_tmu",
268		.num_resources = ARRAY_SIZE(tmu_resources),
269		.resources = tmu_resources,
270	},
271};
272
273static const struct mfd_cell bxt_wc_bcu_dev[] = {
274	{
275		.name = "bxt_wcove_bcu",
276		.num_resources = ARRAY_SIZE(bcu_resources),
277		.resources = bcu_resources,
278	},
279};
280
281static const struct mfd_cell bxt_wc_adc_dev[] = {
282	{
283		.name = "bxt_wcove_gpadc",
284		.num_resources = ARRAY_SIZE(adc_resources),
285		.resources = adc_resources,
286	},
287};
288
289static struct mfd_cell bxt_wc_chgr_dev[] = {
290	{
291		.name = "bxt_wcove_usbc",
292		.num_resources = ARRAY_SIZE(usbc_resources),
293		.resources = usbc_resources,
294	},
295	{
296		.name = "bxt_wcove_ext_charger",
297		.num_resources = ARRAY_SIZE(charger_resources),
298		.resources = charger_resources,
299	},
300};
301
302static int regmap_ipc_byte_reg_read(void *context, unsigned int reg,
303				    unsigned int *val)
304{
305	int ret;
306	int i2c_addr;
307	u8 ipc_in[2];
308	u8 ipc_out[4];
309	struct intel_soc_pmic *pmic = context;
310
311	if (!pmic)
312		return -EINVAL;
313
314	if (reg & REG_ADDR_MASK)
315		i2c_addr = (reg & REG_ADDR_MASK) >> REG_ADDR_SHIFT;
316	else
317		i2c_addr = BXTWC_DEVICE1_ADDR;
318
319	reg &= REG_OFFSET_MASK;
320
321	ipc_in[0] = reg;
322	ipc_in[1] = i2c_addr;
323	ret = intel_scu_ipc_dev_command(pmic->scu, PMC_PMIC_ACCESS,
324					PMC_PMIC_READ, ipc_in, sizeof(ipc_in),
325					ipc_out, sizeof(ipc_out));
326	if (ret)
327		return ret;
328
329	*val = ipc_out[0];
330
331	return 0;
332}
333
334static int regmap_ipc_byte_reg_write(void *context, unsigned int reg,
335				       unsigned int val)
336{
337	int i2c_addr;
338	u8 ipc_in[3];
339	struct intel_soc_pmic *pmic = context;
340
341	if (!pmic)
342		return -EINVAL;
343
344	if (reg & REG_ADDR_MASK)
345		i2c_addr = (reg & REG_ADDR_MASK) >> REG_ADDR_SHIFT;
346	else
347		i2c_addr = BXTWC_DEVICE1_ADDR;
348
349	reg &= REG_OFFSET_MASK;
350
351	ipc_in[0] = reg;
352	ipc_in[1] = i2c_addr;
353	ipc_in[2] = val;
354	return intel_scu_ipc_dev_command(pmic->scu, PMC_PMIC_ACCESS,
355					 PMC_PMIC_WRITE, ipc_in, sizeof(ipc_in),
356					 NULL, 0);
357}
358
359/* sysfs interfaces to r/w PMIC registers, required by initial script */
360static unsigned long bxtwc_reg_addr;
361static ssize_t addr_show(struct device *dev,
362			 struct device_attribute *attr, char *buf)
363{
364	return sysfs_emit(buf, "0x%lx\n", bxtwc_reg_addr);
365}
366
367static ssize_t addr_store(struct device *dev,
368			  struct device_attribute *attr, const char *buf, size_t count)
369{
370	int ret;
371
372	ret = kstrtoul(buf, 0, &bxtwc_reg_addr);
373	if (ret)
374		return ret;
375
376	return count;
377}
378static DEVICE_ATTR_ADMIN_RW(addr);
379
380static ssize_t val_show(struct device *dev,
381			struct device_attribute *attr, char *buf)
382{
383	int ret;
384	unsigned int val;
385	struct intel_soc_pmic *pmic = dev_get_drvdata(dev);
386
387	ret = regmap_read(pmic->regmap, bxtwc_reg_addr, &val);
388	if (ret) {
389		dev_err(dev, "Failed to read 0x%lx\n", bxtwc_reg_addr);
390		return ret;
391	}
392
393	return sysfs_emit(buf, "0x%02x\n", val);
394}
395
396static ssize_t val_store(struct device *dev,
397			 struct device_attribute *attr, const char *buf, size_t count)
398{
399	int ret;
400	unsigned int val;
401	struct intel_soc_pmic *pmic = dev_get_drvdata(dev);
402
403	ret = kstrtouint(buf, 0, &val);
404	if (ret)
405		return ret;
406
407	ret = regmap_write(pmic->regmap, bxtwc_reg_addr, val);
408	if (ret) {
409		dev_err(dev, "Failed to write value 0x%02x to address 0x%lx",
410			val, bxtwc_reg_addr);
411		return ret;
412	}
413	return count;
414}
415static DEVICE_ATTR_ADMIN_RW(val);
416
417static struct attribute *bxtwc_attrs[] = {
418	&dev_attr_addr.attr,
419	&dev_attr_val.attr,
420	NULL
421};
422ATTRIBUTE_GROUPS(bxtwc);
423
424static const struct regmap_config bxtwc_regmap_config = {
425	.reg_bits = 16,
426	.val_bits = 8,
427	.reg_write = regmap_ipc_byte_reg_write,
428	.reg_read = regmap_ipc_byte_reg_read,
429};
430
431static int bxtwc_add_chained_irq_chip(struct intel_soc_pmic *pmic,
432				struct regmap_irq_chip_data *pdata,
433				int pirq, int irq_flags,
434				const struct regmap_irq_chip *chip,
435				struct regmap_irq_chip_data **data)
436{
437	struct device *dev = pmic->dev;
438	int irq, ret;
439
440	irq = regmap_irq_get_virq(pdata, pirq);
441	if (irq < 0)
442		return dev_err_probe(dev, irq, "Failed to get parent vIRQ(%d) for chip %s\n",
443				     pirq, chip->name);
444
445	ret = devm_regmap_add_irq_chip(dev, pmic->regmap, irq, irq_flags, 0, chip, data);
446	if (ret)
447		return dev_err_probe(dev, ret, "Failed to add %s IRQ chip\n", chip->name);
448
449	return 0;
450}
451
452static int bxtwc_add_chained_devices(struct intel_soc_pmic *pmic,
453				     const struct mfd_cell *cells, int n_devs,
454				     struct regmap_irq_chip_data *pdata,
455				     int pirq, int irq_flags,
456				     const struct regmap_irq_chip *chip,
457				     struct regmap_irq_chip_data **data)
458{
459	struct device *dev = pmic->dev;
460	struct irq_domain *domain;
461	int ret;
462
463	ret = bxtwc_add_chained_irq_chip(pmic, pdata, pirq, irq_flags, chip, data);
464	if (ret)
465		return ret;
466
467	domain = regmap_irq_get_domain(*data);
468
469	return devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE, cells, n_devs, NULL, 0, domain);
470}
471
472static int bxtwc_probe(struct platform_device *pdev)
473{
474	struct device *dev = &pdev->dev;
475	int ret;
476	acpi_status status;
477	unsigned long long hrv;
478	struct intel_soc_pmic *pmic;
479
480	status = acpi_evaluate_integer(ACPI_HANDLE(dev), "_HRV", NULL, &hrv);
481	if (ACPI_FAILURE(status))
482		return dev_err_probe(dev, -ENODEV, "Failed to get PMIC hardware revision\n");
483	if (hrv != BROXTON_PMIC_WC_HRV)
484		return dev_err_probe(dev, -ENODEV, "Invalid PMIC hardware revision: %llu\n", hrv);
485
486	pmic = devm_kzalloc(dev, sizeof(*pmic), GFP_KERNEL);
487	if (!pmic)
488		return -ENOMEM;
489
490	ret = platform_get_irq(pdev, 0);
491	if (ret < 0)
492		return ret;
493	pmic->irq = ret;
494
495	platform_set_drvdata(pdev, pmic);
496	pmic->dev = dev;
497
498	pmic->scu = devm_intel_scu_ipc_dev_get(dev);
499	if (!pmic->scu)
500		return -EPROBE_DEFER;
501
502	pmic->regmap = devm_regmap_init(dev, NULL, pmic, &bxtwc_regmap_config);
503	if (IS_ERR(pmic->regmap))
504		return dev_err_probe(dev, PTR_ERR(pmic->regmap), "Failed to initialise regmap\n");
505
506	ret = devm_regmap_add_irq_chip(dev, pmic->regmap, pmic->irq,
507				       IRQF_ONESHOT | IRQF_SHARED,
508				       0, &bxtwc_regmap_irq_chip,
509				       &pmic->irq_chip_data);
510	if (ret)
511		return dev_err_probe(dev, ret, "Failed to add IRQ chip\n");
512
513	ret = bxtwc_add_chained_devices(pmic, bxt_wc_tmu_dev, ARRAY_SIZE(bxt_wc_tmu_dev),
514					pmic->irq_chip_data,
515					BXTWC_TMU_LVL1_IRQ,
516					IRQF_ONESHOT,
517					&bxtwc_regmap_irq_chip_tmu,
518					&pmic->irq_chip_data_tmu);
519	if (ret)
520		return ret;
521
522	ret = bxtwc_add_chained_irq_chip(pmic, pmic->irq_chip_data,
523					 BXTWC_PWRBTN_LVL1_IRQ,
524					 IRQF_ONESHOT,
525					 &bxtwc_regmap_irq_chip_pwrbtn,
526					 &pmic->irq_chip_data_pwrbtn);
527	if (ret)
528		return ret;
529
530	ret = bxtwc_add_chained_devices(pmic, bxt_wc_bcu_dev, ARRAY_SIZE(bxt_wc_bcu_dev),
531					pmic->irq_chip_data,
532					BXTWC_BCU_LVL1_IRQ,
533					IRQF_ONESHOT,
534					&bxtwc_regmap_irq_chip_bcu,
535					&pmic->irq_chip_data_bcu);
536	if (ret)
537		return ret;
538
539	ret = bxtwc_add_chained_devices(pmic, bxt_wc_adc_dev, ARRAY_SIZE(bxt_wc_adc_dev),
540					pmic->irq_chip_data,
541					BXTWC_ADC_LVL1_IRQ,
542					IRQF_ONESHOT,
543					&bxtwc_regmap_irq_chip_adc,
544					&pmic->irq_chip_data_adc);
545	if (ret)
546		return ret;
547
548	ret = bxtwc_add_chained_devices(pmic, bxt_wc_chgr_dev, ARRAY_SIZE(bxt_wc_chgr_dev),
549					pmic->irq_chip_data,
550					BXTWC_CHGR_LVL1_IRQ,
551					IRQF_ONESHOT,
552					&bxtwc_regmap_irq_chip_chgr,
553					&pmic->irq_chip_data_chgr);
554	if (ret)
555		return ret;
556
557	/* Add chained IRQ handler for CRIT IRQs */
558	ret = bxtwc_add_chained_irq_chip(pmic, pmic->irq_chip_data,
559					 BXTWC_CRIT_LVL1_IRQ,
560					 IRQF_ONESHOT,
561					 &bxtwc_regmap_irq_chip_crit,
562					 &pmic->irq_chip_data_crit);
563	if (ret)
564		return ret;
565
566	ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE, bxt_wc_dev, ARRAY_SIZE(bxt_wc_dev),
567				   NULL, 0, NULL);
568	if (ret)
569		return dev_err_probe(dev, ret, "Failed to add devices\n");
570
571	/*
572	 * There is a known H/W bug. Upon reset, BIT 5 of register
573	 * BXTWC_CHGR_LVL1_IRQ is 0 which is the expected value. However,
574	 * later it's set to 1(masked) automatically by hardware. So we
575	 * place the software workaround here to unmask it again in order
576	 * to re-enable the charger interrupt.
577	 */
578	regmap_update_bits(pmic->regmap, BXTWC_MIRQLVL1, BXTWC_MIRQLVL1_MCHGR, 0);
579
580	return 0;
581}
582
583static void bxtwc_shutdown(struct platform_device *pdev)
584{
585	struct intel_soc_pmic *pmic = platform_get_drvdata(pdev);
586
587	disable_irq(pmic->irq);
588}
589
590static int bxtwc_suspend(struct device *dev)
591{
592	struct intel_soc_pmic *pmic = dev_get_drvdata(dev);
593
594	disable_irq(pmic->irq);
595
596	return 0;
597}
598
599static int bxtwc_resume(struct device *dev)
600{
601	struct intel_soc_pmic *pmic = dev_get_drvdata(dev);
602
603	enable_irq(pmic->irq);
604	return 0;
605}
606
607static DEFINE_SIMPLE_DEV_PM_OPS(bxtwc_pm_ops, bxtwc_suspend, bxtwc_resume);
608
609static const struct acpi_device_id bxtwc_acpi_ids[] = {
610	{ "INT34D3", },
611	{ }
612};
613MODULE_DEVICE_TABLE(acpi, bxtwc_acpi_ids);
614
615static struct platform_driver bxtwc_driver = {
616	.probe = bxtwc_probe,
617	.shutdown = bxtwc_shutdown,
618	.driver	= {
619		.name	= "intel_soc_pmic_bxtwc",
620		.pm     = pm_sleep_ptr(&bxtwc_pm_ops),
621		.acpi_match_table = bxtwc_acpi_ids,
622		.dev_groups = bxtwc_groups,
623	},
624};
625
626module_platform_driver(bxtwc_driver);
627
628MODULE_DESCRIPTION("Intel Broxton Whiskey Cove PMIC MFD core driver");
629MODULE_LICENSE("GPL v2");
630MODULE_AUTHOR("Qipeng Zha <qipeng.zha@intel.com>");
~/ Read-only file preview.