1 // SPDX-License-Identifier: GPL-2.0
3 * Intel SoC PMIC MFD Driver
5 * Copyright (C) 2013, 2014 Intel Corporation. All rights reserved.
7 * Author: Yang, Bin <bin.yang@intel.com>
8 * Author: Zhu, Lejun <lejun.zhu@linux.intel.com>
11 #include <linux/acpi.h>
12 #include <linux/i2c.h>
13 #include <linux/interrupt.h>
14 #include <linux/module.h>
15 #include <linux/mfd/core.h>
16 #include <linux/mfd/intel_soc_pmic.h>
17 #include <linux/pwm.h>
18 #include <linux/regmap.h>
20 #include "intel_soc_pmic_core.h"
22 /* Crystal Cove PMIC shares same ACPI ID between different platforms */
26 /* PWM consumed by the Intel GFX */
27 static struct pwm_lookup crc_pwm_lookup
[] = {
28 PWM_LOOKUP("crystal_cove_pwm", 0, "0000:00:02.0", "pwm_pmic_backlight", 0, PWM_POLARITY_NORMAL
),
31 static int intel_soc_pmic_i2c_probe(struct i2c_client
*i2c
,
32 const struct i2c_device_id
*i2c_id
)
34 struct device
*dev
= &i2c
->dev
;
35 struct intel_soc_pmic_config
*config
;
36 struct intel_soc_pmic
*pmic
;
37 unsigned long long hrv
;
42 * There are 2 different Crystal Cove PMICs a Bay Trail and Cherry
43 * Trail version, use _HRV to differentiate between the 2.
45 status
= acpi_evaluate_integer(ACPI_HANDLE(dev
), "_HRV", NULL
, &hrv
);
46 if (ACPI_FAILURE(status
)) {
47 dev_err(dev
, "Failed to get PMIC hardware revision\n");
53 config
= &intel_soc_pmic_config_byt_crc
;
56 config
= &intel_soc_pmic_config_cht_crc
;
59 dev_warn(dev
, "Unknown hardware rev %llu, assuming BYT\n", hrv
);
60 config
= &intel_soc_pmic_config_byt_crc
;
63 pmic
= devm_kzalloc(dev
, sizeof(*pmic
), GFP_KERNEL
);
67 dev_set_drvdata(dev
, pmic
);
69 pmic
->regmap
= devm_regmap_init_i2c(i2c
, config
->regmap_config
);
70 if (IS_ERR(pmic
->regmap
))
71 return PTR_ERR(pmic
->regmap
);
75 ret
= regmap_add_irq_chip(pmic
->regmap
, pmic
->irq
,
76 config
->irq_flags
| IRQF_ONESHOT
,
78 &pmic
->irq_chip_data
);
82 ret
= enable_irq_wake(pmic
->irq
);
84 dev_warn(dev
, "Can't enable IRQ as wake source: %d\n", ret
);
86 /* Add lookup table for crc-pwm */
87 pwm_add_table(crc_pwm_lookup
, ARRAY_SIZE(crc_pwm_lookup
));
89 ret
= mfd_add_devices(dev
, -1, config
->cell_dev
,
90 config
->n_cell_devs
, NULL
, 0,
91 regmap_irq_get_domain(pmic
->irq_chip_data
));
93 goto err_del_irq_chip
;
98 regmap_del_irq_chip(pmic
->irq
, pmic
->irq_chip_data
);
102 static int intel_soc_pmic_i2c_remove(struct i2c_client
*i2c
)
104 struct intel_soc_pmic
*pmic
= dev_get_drvdata(&i2c
->dev
);
106 regmap_del_irq_chip(pmic
->irq
, pmic
->irq_chip_data
);
108 /* remove crc-pwm lookup table */
109 pwm_remove_table(crc_pwm_lookup
, ARRAY_SIZE(crc_pwm_lookup
));
111 mfd_remove_devices(&i2c
->dev
);
116 static void intel_soc_pmic_shutdown(struct i2c_client
*i2c
)
118 struct intel_soc_pmic
*pmic
= dev_get_drvdata(&i2c
->dev
);
120 disable_irq(pmic
->irq
);
125 #if defined(CONFIG_PM_SLEEP)
126 static int intel_soc_pmic_suspend(struct device
*dev
)
128 struct intel_soc_pmic
*pmic
= dev_get_drvdata(dev
);
130 disable_irq(pmic
->irq
);
135 static int intel_soc_pmic_resume(struct device
*dev
)
137 struct intel_soc_pmic
*pmic
= dev_get_drvdata(dev
);
139 enable_irq(pmic
->irq
);
145 static SIMPLE_DEV_PM_OPS(intel_soc_pmic_pm_ops
, intel_soc_pmic_suspend
,
146 intel_soc_pmic_resume
);
148 static const struct i2c_device_id intel_soc_pmic_i2c_id
[] = {
151 MODULE_DEVICE_TABLE(i2c
, intel_soc_pmic_i2c_id
);
153 #if defined(CONFIG_ACPI)
154 static const struct acpi_device_id intel_soc_pmic_acpi_match
[] = {
158 MODULE_DEVICE_TABLE(acpi
, intel_soc_pmic_acpi_match
);
161 static struct i2c_driver intel_soc_pmic_i2c_driver
= {
163 .name
= "intel_soc_pmic_i2c",
164 .pm
= &intel_soc_pmic_pm_ops
,
165 .acpi_match_table
= ACPI_PTR(intel_soc_pmic_acpi_match
),
167 .probe
= intel_soc_pmic_i2c_probe
,
168 .remove
= intel_soc_pmic_i2c_remove
,
169 .id_table
= intel_soc_pmic_i2c_id
,
170 .shutdown
= intel_soc_pmic_shutdown
,
173 module_i2c_driver(intel_soc_pmic_i2c_driver
);
175 MODULE_DESCRIPTION("I2C driver for Intel SoC PMIC");
176 MODULE_LICENSE("GPL v2");
177 MODULE_AUTHOR("Yang, Bin <bin.yang@intel.com>");
178 MODULE_AUTHOR("Zhu, Lejun <lejun.zhu@linux.intel.com>");