1 // SPDX-License-Identifier: GPL-2.0
3 * Device access for Crystal Cove PMIC
5 * Copyright (C) 2012-2014, 2022 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/i2c.h>
12 #include <linux/interrupt.h>
13 #include <linux/mod_devicetable.h>
14 #include <linux/module.h>
15 #include <linux/mfd/core.h>
16 #include <linux/mfd/intel_soc_pmic.h>
17 #include <linux/platform_data/x86/soc.h>
18 #include <linux/pwm.h>
19 #include <linux/regmap.h>
21 #define CRYSTAL_COVE_MAX_REGISTER 0xC6
23 #define CRYSTAL_COVE_REG_IRQLVL1 0x02
24 #define CRYSTAL_COVE_REG_MIRQLVL1 0x0E
26 #define CRYSTAL_COVE_IRQ_PWRSRC 0
27 #define CRYSTAL_COVE_IRQ_THRM 1
28 #define CRYSTAL_COVE_IRQ_BCU 2
29 #define CRYSTAL_COVE_IRQ_ADC 3
30 #define CRYSTAL_COVE_IRQ_CHGR 4
31 #define CRYSTAL_COVE_IRQ_GPIO 5
32 #define CRYSTAL_COVE_IRQ_VHDMIOCP 6
34 static const struct resource pwrsrc_resources
[] = {
35 DEFINE_RES_IRQ_NAMED(CRYSTAL_COVE_IRQ_PWRSRC
, "PWRSRC"),
38 static const struct resource thermal_resources
[] = {
39 DEFINE_RES_IRQ_NAMED(CRYSTAL_COVE_IRQ_THRM
, "THERMAL"),
42 static const struct resource bcu_resources
[] = {
43 DEFINE_RES_IRQ_NAMED(CRYSTAL_COVE_IRQ_BCU
, "BCU"),
46 static const struct resource adc_resources
[] = {
47 DEFINE_RES_IRQ_NAMED(CRYSTAL_COVE_IRQ_ADC
, "ADC"),
50 static const struct resource charger_resources
[] = {
51 DEFINE_RES_IRQ_NAMED(CRYSTAL_COVE_IRQ_CHGR
, "CHGR"),
54 static const struct resource gpio_resources
[] = {
55 DEFINE_RES_IRQ_NAMED(CRYSTAL_COVE_IRQ_GPIO
, "GPIO"),
58 static struct mfd_cell crystal_cove_byt_dev
[] = {
60 .name
= "crystal_cove_pwrsrc",
61 .num_resources
= ARRAY_SIZE(pwrsrc_resources
),
62 .resources
= pwrsrc_resources
,
65 .name
= "crystal_cove_thermal",
66 .num_resources
= ARRAY_SIZE(thermal_resources
),
67 .resources
= thermal_resources
,
70 .name
= "crystal_cove_bcu",
71 .num_resources
= ARRAY_SIZE(bcu_resources
),
72 .resources
= bcu_resources
,
75 .name
= "crystal_cove_adc",
76 .num_resources
= ARRAY_SIZE(adc_resources
),
77 .resources
= adc_resources
,
80 .name
= "crystal_cove_charger",
81 .num_resources
= ARRAY_SIZE(charger_resources
),
82 .resources
= charger_resources
,
85 .name
= "crystal_cove_gpio",
86 .num_resources
= ARRAY_SIZE(gpio_resources
),
87 .resources
= gpio_resources
,
90 .name
= "byt_crystal_cove_pmic",
93 .name
= "crystal_cove_pwm",
97 static struct mfd_cell crystal_cove_cht_dev
[] = {
99 .name
= "crystal_cove_gpio",
100 .num_resources
= ARRAY_SIZE(gpio_resources
),
101 .resources
= gpio_resources
,
104 .name
= "cht_crystal_cove_pmic",
107 .name
= "crystal_cove_pwm",
111 static const struct regmap_config crystal_cove_regmap_config
= {
115 .max_register
= CRYSTAL_COVE_MAX_REGISTER
,
116 .cache_type
= REGCACHE_NONE
,
119 static const struct regmap_irq crystal_cove_irqs
[] = {
120 REGMAP_IRQ_REG(CRYSTAL_COVE_IRQ_PWRSRC
, 0, BIT(CRYSTAL_COVE_IRQ_PWRSRC
)),
121 REGMAP_IRQ_REG(CRYSTAL_COVE_IRQ_THRM
, 0, BIT(CRYSTAL_COVE_IRQ_THRM
)),
122 REGMAP_IRQ_REG(CRYSTAL_COVE_IRQ_BCU
, 0, BIT(CRYSTAL_COVE_IRQ_BCU
)),
123 REGMAP_IRQ_REG(CRYSTAL_COVE_IRQ_ADC
, 0, BIT(CRYSTAL_COVE_IRQ_ADC
)),
124 REGMAP_IRQ_REG(CRYSTAL_COVE_IRQ_CHGR
, 0, BIT(CRYSTAL_COVE_IRQ_CHGR
)),
125 REGMAP_IRQ_REG(CRYSTAL_COVE_IRQ_GPIO
, 0, BIT(CRYSTAL_COVE_IRQ_GPIO
)),
126 REGMAP_IRQ_REG(CRYSTAL_COVE_IRQ_VHDMIOCP
, 0, BIT(CRYSTAL_COVE_IRQ_VHDMIOCP
)),
129 static const struct regmap_irq_chip crystal_cove_irq_chip
= {
130 .name
= "Crystal Cove",
131 .irqs
= crystal_cove_irqs
,
132 .num_irqs
= ARRAY_SIZE(crystal_cove_irqs
),
134 .status_base
= CRYSTAL_COVE_REG_IRQLVL1
,
135 .mask_base
= CRYSTAL_COVE_REG_MIRQLVL1
,
138 /* PWM consumed by the Intel GFX */
139 static struct pwm_lookup crc_pwm_lookup
[] = {
140 PWM_LOOKUP_WITH_MODULE("crystal_cove_pwm", 0, "0000:00:02.0",
141 "pwm_pmic_backlight", 0, PWM_POLARITY_NORMAL
,
145 struct crystal_cove_config
{
146 unsigned long irq_flags
;
147 struct mfd_cell
*cell_dev
;
149 const struct regmap_config
*regmap_config
;
150 const struct regmap_irq_chip
*irq_chip
;
153 static const struct crystal_cove_config crystal_cove_config_byt_crc
= {
154 .irq_flags
= IRQF_TRIGGER_RISING
,
155 .cell_dev
= crystal_cove_byt_dev
,
156 .n_cell_devs
= ARRAY_SIZE(crystal_cove_byt_dev
),
157 .regmap_config
= &crystal_cove_regmap_config
,
158 .irq_chip
= &crystal_cove_irq_chip
,
161 static const struct crystal_cove_config crystal_cove_config_cht_crc
= {
162 .irq_flags
= IRQF_TRIGGER_RISING
,
163 .cell_dev
= crystal_cove_cht_dev
,
164 .n_cell_devs
= ARRAY_SIZE(crystal_cove_cht_dev
),
165 .regmap_config
= &crystal_cove_regmap_config
,
166 .irq_chip
= &crystal_cove_irq_chip
,
169 static int crystal_cove_i2c_probe(struct i2c_client
*i2c
)
171 const struct crystal_cove_config
*config
;
172 struct device
*dev
= &i2c
->dev
;
173 struct intel_soc_pmic
*pmic
;
176 if (soc_intel_is_byt())
177 config
= &crystal_cove_config_byt_crc
;
179 config
= &crystal_cove_config_cht_crc
;
181 pmic
= devm_kzalloc(dev
, sizeof(*pmic
), GFP_KERNEL
);
185 i2c_set_clientdata(i2c
, pmic
);
187 pmic
->regmap
= devm_regmap_init_i2c(i2c
, config
->regmap_config
);
188 if (IS_ERR(pmic
->regmap
))
189 return PTR_ERR(pmic
->regmap
);
191 pmic
->irq
= i2c
->irq
;
193 ret
= devm_regmap_add_irq_chip(dev
, pmic
->regmap
, pmic
->irq
,
194 config
->irq_flags
| IRQF_ONESHOT
,
195 0, config
->irq_chip
, &pmic
->irq_chip_data
);
199 ret
= enable_irq_wake(pmic
->irq
);
201 dev_warn(dev
, "Can't enable IRQ as wake source: %d\n", ret
);
203 /* Add lookup table for crc-pwm */
204 pwm_add_table(crc_pwm_lookup
, ARRAY_SIZE(crc_pwm_lookup
));
206 /* To distuingish this domain from the GPIO/charger's irqchip domains */
207 irq_domain_update_bus_token(regmap_irq_get_domain(pmic
->irq_chip_data
),
210 ret
= mfd_add_devices(dev
, PLATFORM_DEVID_NONE
, config
->cell_dev
,
211 config
->n_cell_devs
, NULL
, 0,
212 regmap_irq_get_domain(pmic
->irq_chip_data
));
214 pwm_remove_table(crc_pwm_lookup
, ARRAY_SIZE(crc_pwm_lookup
));
219 static void crystal_cove_i2c_remove(struct i2c_client
*i2c
)
221 /* remove crc-pwm lookup table */
222 pwm_remove_table(crc_pwm_lookup
, ARRAY_SIZE(crc_pwm_lookup
));
224 mfd_remove_devices(&i2c
->dev
);
227 static void crystal_cove_shutdown(struct i2c_client
*i2c
)
229 struct intel_soc_pmic
*pmic
= i2c_get_clientdata(i2c
);
231 disable_irq(pmic
->irq
);
236 static int crystal_cove_suspend(struct device
*dev
)
238 struct intel_soc_pmic
*pmic
= dev_get_drvdata(dev
);
240 disable_irq(pmic
->irq
);
245 static int crystal_cove_resume(struct device
*dev
)
247 struct intel_soc_pmic
*pmic
= dev_get_drvdata(dev
);
249 enable_irq(pmic
->irq
);
254 static DEFINE_SIMPLE_DEV_PM_OPS(crystal_cove_pm_ops
, crystal_cove_suspend
, crystal_cove_resume
);
256 static const struct acpi_device_id crystal_cove_acpi_match
[] = {
260 MODULE_DEVICE_TABLE(acpi
, crystal_cove_acpi_match
);
262 static struct i2c_driver crystal_cove_i2c_driver
= {
264 .name
= "crystal_cove_i2c",
265 .pm
= pm_sleep_ptr(&crystal_cove_pm_ops
),
266 .acpi_match_table
= crystal_cove_acpi_match
,
268 .probe
= crystal_cove_i2c_probe
,
269 .remove
= crystal_cove_i2c_remove
,
270 .shutdown
= crystal_cove_shutdown
,
273 module_i2c_driver(crystal_cove_i2c_driver
);
275 MODULE_DESCRIPTION("I2C driver for Intel SoC PMIC");
276 MODULE_AUTHOR("Yang, Bin <bin.yang@intel.com>");
277 MODULE_AUTHOR("Zhu, Lejun <lejun.zhu@linux.intel.com>");