1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Device access for Crystal Cove PMIC 4 * 5 * Copyright (C) 2012-2014 Intel Corporation. All rights reserved. 6 * 7 * Author: Yang, Bin <bin.yang@intel.com> 8 * Author: Zhu, Lejun <lejun.zhu@linux.intel.com> 9 */ 10 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> 20 21 #define CRYSTAL_COVE_MAX_REGISTER 0xC6 22 23 #define CRYSTAL_COVE_REG_IRQLVL1 0x02 24 #define CRYSTAL_COVE_REG_MIRQLVL1 0x0E 25 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 33 34 static const struct resource pwrsrc_resources[] = { 35 DEFINE_RES_IRQ_NAMED(CRYSTAL_COVE_IRQ_PWRSRC, "PWRSRC"), 36 }; 37 38 static const struct resource thermal_resources[] = { 39 DEFINE_RES_IRQ_NAMED(CRYSTAL_COVE_IRQ_THRM, "THERMAL"), 40 }; 41 42 static const struct resource bcu_resources[] = { 43 DEFINE_RES_IRQ_NAMED(CRYSTAL_COVE_IRQ_BCU, "BCU"), 44 }; 45 46 static const struct resource adc_resources[] = { 47 DEFINE_RES_IRQ_NAMED(CRYSTAL_COVE_IRQ_ADC, "ADC"), 48 }; 49 50 static const struct resource charger_resources[] = { 51 DEFINE_RES_IRQ_NAMED(CRYSTAL_COVE_IRQ_CHGR, "CHGR"), 52 }; 53 54 static const struct resource gpio_resources[] = { 55 DEFINE_RES_IRQ_NAMED(CRYSTAL_COVE_IRQ_GPIO, "GPIO"), 56 }; 57 58 static struct mfd_cell crystal_cove_byt_dev[] = { 59 { 60 .name = "crystal_cove_pwrsrc", 61 .num_resources = ARRAY_SIZE(pwrsrc_resources), 62 .resources = pwrsrc_resources, 63 }, 64 { 65 .name = "crystal_cove_thermal", 66 .num_resources = ARRAY_SIZE(thermal_resources), 67 .resources = thermal_resources, 68 }, 69 { 70 .name = "crystal_cove_bcu", 71 .num_resources = ARRAY_SIZE(bcu_resources), 72 .resources = bcu_resources, 73 }, 74 { 75 .name = "crystal_cove_adc", 76 .num_resources = ARRAY_SIZE(adc_resources), 77 .resources = adc_resources, 78 }, 79 { 80 .name = "crystal_cove_charger", 81 .num_resources = ARRAY_SIZE(charger_resources), 82 .resources = charger_resources, 83 }, 84 { 85 .name = "crystal_cove_gpio", 86 .num_resources = ARRAY_SIZE(gpio_resources), 87 .resources = gpio_resources, 88 }, 89 { 90 .name = "byt_crystal_cove_pmic", 91 }, 92 { 93 .name = "crystal_cove_pwm", 94 }, 95 }; 96 97 static struct mfd_cell crystal_cove_cht_dev[] = { 98 { 99 .name = "crystal_cove_gpio", 100 .num_resources = ARRAY_SIZE(gpio_resources), 101 .resources = gpio_resources, 102 }, 103 { 104 .name = "cht_crystal_cove_pmic", 105 }, 106 { 107 .name = "crystal_cove_pwm", 108 }, 109 }; 110 111 static const struct regmap_config crystal_cove_regmap_config = { 112 .reg_bits = 8, 113 .val_bits = 8, 114 115 .max_register = CRYSTAL_COVE_MAX_REGISTER, 116 .cache_type = REGCACHE_NONE, 117 }; 118 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)), 127 }; 128 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), 133 .num_regs = 1, 134 .status_base = CRYSTAL_COVE_REG_IRQLVL1, 135 .mask_base = CRYSTAL_COVE_REG_MIRQLVL1, 136 }; 137 138 /* PWM consumed by the Intel GFX */ 139 static struct pwm_lookup crc_pwm_lookup[] = { 140 PWM_LOOKUP("crystal_cove_pwm", 0, "0000:00:02.0", "pwm_pmic_backlight", 0, PWM_POLARITY_NORMAL), 141 }; 142 143 struct intel_soc_pmic_config { 144 unsigned long irq_flags; 145 struct mfd_cell *cell_dev; 146 int n_cell_devs; 147 const struct regmap_config *regmap_config; 148 const struct regmap_irq_chip *irq_chip; 149 }; 150 151 static const struct intel_soc_pmic_config intel_soc_pmic_config_byt_crc = { 152 .irq_flags = IRQF_TRIGGER_RISING, 153 .cell_dev = crystal_cove_byt_dev, 154 .n_cell_devs = ARRAY_SIZE(crystal_cove_byt_dev), 155 .regmap_config = &crystal_cove_regmap_config, 156 .irq_chip = &crystal_cove_irq_chip, 157 }; 158 159 static const struct intel_soc_pmic_config intel_soc_pmic_config_cht_crc = { 160 .irq_flags = IRQF_TRIGGER_RISING, 161 .cell_dev = crystal_cove_cht_dev, 162 .n_cell_devs = ARRAY_SIZE(crystal_cove_cht_dev), 163 .regmap_config = &crystal_cove_regmap_config, 164 .irq_chip = &crystal_cove_irq_chip, 165 }; 166 167 static int intel_soc_pmic_i2c_probe(struct i2c_client *i2c, 168 const struct i2c_device_id *i2c_id) 169 { 170 const struct intel_soc_pmic_config *config; 171 struct device *dev = &i2c->dev; 172 struct intel_soc_pmic *pmic; 173 int ret; 174 175 if (soc_intel_is_byt()) 176 config = &intel_soc_pmic_config_byt_crc; 177 else 178 config = &intel_soc_pmic_config_cht_crc; 179 180 pmic = devm_kzalloc(dev, sizeof(*pmic), GFP_KERNEL); 181 if (!pmic) 182 return -ENOMEM; 183 184 i2c_set_clientdata(i2c, pmic); 185 186 pmic->regmap = devm_regmap_init_i2c(i2c, config->regmap_config); 187 if (IS_ERR(pmic->regmap)) 188 return PTR_ERR(pmic->regmap); 189 190 pmic->irq = i2c->irq; 191 192 ret = devm_regmap_add_irq_chip(dev, pmic->regmap, pmic->irq, 193 config->irq_flags | IRQF_ONESHOT, 194 0, config->irq_chip, &pmic->irq_chip_data); 195 if (ret) 196 return ret; 197 198 ret = enable_irq_wake(pmic->irq); 199 if (ret) 200 dev_warn(dev, "Can't enable IRQ as wake source: %d\n", ret); 201 202 /* Add lookup table for crc-pwm */ 203 pwm_add_table(crc_pwm_lookup, ARRAY_SIZE(crc_pwm_lookup)); 204 205 /* To distuingish this domain from the GPIO/charger's irqchip domains */ 206 irq_domain_update_bus_token(regmap_irq_get_domain(pmic->irq_chip_data), 207 DOMAIN_BUS_NEXUS); 208 209 ret = mfd_add_devices(dev, PLATFORM_DEVID_NONE, config->cell_dev, 210 config->n_cell_devs, NULL, 0, 211 regmap_irq_get_domain(pmic->irq_chip_data)); 212 if (ret) 213 pwm_remove_table(crc_pwm_lookup, ARRAY_SIZE(crc_pwm_lookup)); 214 215 return ret; 216 } 217 218 static int intel_soc_pmic_i2c_remove(struct i2c_client *i2c) 219 { 220 /* remove crc-pwm lookup table */ 221 pwm_remove_table(crc_pwm_lookup, ARRAY_SIZE(crc_pwm_lookup)); 222 223 mfd_remove_devices(&i2c->dev); 224 225 return 0; 226 } 227 228 static void intel_soc_pmic_shutdown(struct i2c_client *i2c) 229 { 230 struct intel_soc_pmic *pmic = i2c_get_clientdata(i2c); 231 232 disable_irq(pmic->irq); 233 234 return; 235 } 236 237 static int intel_soc_pmic_suspend(struct device *dev) 238 { 239 struct intel_soc_pmic *pmic = dev_get_drvdata(dev); 240 241 disable_irq(pmic->irq); 242 243 return 0; 244 } 245 246 static int intel_soc_pmic_resume(struct device *dev) 247 { 248 struct intel_soc_pmic *pmic = dev_get_drvdata(dev); 249 250 enable_irq(pmic->irq); 251 252 return 0; 253 } 254 255 static DEFINE_SIMPLE_DEV_PM_OPS(crystal_cove_pm_ops, intel_soc_pmic_suspend, intel_soc_pmic_resume); 256 257 static const struct i2c_device_id intel_soc_pmic_i2c_id[] = { 258 { } 259 }; 260 MODULE_DEVICE_TABLE(i2c, intel_soc_pmic_i2c_id); 261 262 static const struct acpi_device_id intel_soc_pmic_acpi_match[] = { 263 { "INT33FD" }, 264 { }, 265 }; 266 MODULE_DEVICE_TABLE(acpi, intel_soc_pmic_acpi_match); 267 268 static struct i2c_driver intel_soc_pmic_i2c_driver = { 269 .driver = { 270 .name = "intel_soc_pmic_i2c", 271 .pm = pm_sleep_ptr(&crystal_cove_pm_ops), 272 .acpi_match_table = intel_soc_pmic_acpi_match, 273 }, 274 .probe = intel_soc_pmic_i2c_probe, 275 .remove = intel_soc_pmic_i2c_remove, 276 .id_table = intel_soc_pmic_i2c_id, 277 .shutdown = intel_soc_pmic_shutdown, 278 }; 279 280 module_i2c_driver(intel_soc_pmic_i2c_driver); 281 282 MODULE_DESCRIPTION("I2C driver for Intel SoC PMIC"); 283 MODULE_LICENSE("GPL v2"); 284 MODULE_AUTHOR("Yang, Bin <bin.yang@intel.com>"); 285 MODULE_AUTHOR("Zhu, Lejun <lejun.zhu@linux.intel.com>"); 286