Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v5.7-rc6 178 lines 4.4 kB view raw
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Intel SoC PMIC MFD Driver 4 * 5 * Copyright (C) 2013, 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/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> 19 20#include "intel_soc_pmic_core.h" 21 22/* Crystal Cove PMIC shares same ACPI ID between different platforms */ 23#define BYT_CRC_HRV 2 24#define CHT_CRC_HRV 3 25 26/* PWM consumed by the Intel GFX */ 27static struct pwm_lookup crc_pwm_lookup[] = { 28 PWM_LOOKUP("crystal_cove_pwm", 0, "0000:00:02.0", "pwm_pmic_backlight", 0, PWM_POLARITY_NORMAL), 29}; 30 31static int intel_soc_pmic_i2c_probe(struct i2c_client *i2c, 32 const struct i2c_device_id *i2c_id) 33{ 34 struct device *dev = &i2c->dev; 35 struct intel_soc_pmic_config *config; 36 struct intel_soc_pmic *pmic; 37 unsigned long long hrv; 38 acpi_status status; 39 int ret; 40 41 /* 42 * There are 2 different Crystal Cove PMICs a Bay Trail and Cherry 43 * Trail version, use _HRV to differentiate between the 2. 44 */ 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"); 48 return -ENODEV; 49 } 50 51 switch (hrv) { 52 case BYT_CRC_HRV: 53 config = &intel_soc_pmic_config_byt_crc; 54 break; 55 case CHT_CRC_HRV: 56 config = &intel_soc_pmic_config_cht_crc; 57 break; 58 default: 59 dev_warn(dev, "Unknown hardware rev %llu, assuming BYT\n", hrv); 60 config = &intel_soc_pmic_config_byt_crc; 61 } 62 63 pmic = devm_kzalloc(dev, sizeof(*pmic), GFP_KERNEL); 64 if (!pmic) 65 return -ENOMEM; 66 67 dev_set_drvdata(dev, pmic); 68 69 pmic->regmap = devm_regmap_init_i2c(i2c, config->regmap_config); 70 if (IS_ERR(pmic->regmap)) 71 return PTR_ERR(pmic->regmap); 72 73 pmic->irq = i2c->irq; 74 75 ret = regmap_add_irq_chip(pmic->regmap, pmic->irq, 76 config->irq_flags | IRQF_ONESHOT, 77 0, config->irq_chip, 78 &pmic->irq_chip_data); 79 if (ret) 80 return ret; 81 82 ret = enable_irq_wake(pmic->irq); 83 if (ret) 84 dev_warn(dev, "Can't enable IRQ as wake source: %d\n", ret); 85 86 /* Add lookup table for crc-pwm */ 87 pwm_add_table(crc_pwm_lookup, ARRAY_SIZE(crc_pwm_lookup)); 88 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)); 92 if (ret) 93 goto err_del_irq_chip; 94 95 return 0; 96 97err_del_irq_chip: 98 regmap_del_irq_chip(pmic->irq, pmic->irq_chip_data); 99 return ret; 100} 101 102static int intel_soc_pmic_i2c_remove(struct i2c_client *i2c) 103{ 104 struct intel_soc_pmic *pmic = dev_get_drvdata(&i2c->dev); 105 106 regmap_del_irq_chip(pmic->irq, pmic->irq_chip_data); 107 108 /* remove crc-pwm lookup table */ 109 pwm_remove_table(crc_pwm_lookup, ARRAY_SIZE(crc_pwm_lookup)); 110 111 mfd_remove_devices(&i2c->dev); 112 113 return 0; 114} 115 116static void intel_soc_pmic_shutdown(struct i2c_client *i2c) 117{ 118 struct intel_soc_pmic *pmic = dev_get_drvdata(&i2c->dev); 119 120 disable_irq(pmic->irq); 121 122 return; 123} 124 125#if defined(CONFIG_PM_SLEEP) 126static int intel_soc_pmic_suspend(struct device *dev) 127{ 128 struct intel_soc_pmic *pmic = dev_get_drvdata(dev); 129 130 disable_irq(pmic->irq); 131 132 return 0; 133} 134 135static int intel_soc_pmic_resume(struct device *dev) 136{ 137 struct intel_soc_pmic *pmic = dev_get_drvdata(dev); 138 139 enable_irq(pmic->irq); 140 141 return 0; 142} 143#endif 144 145static SIMPLE_DEV_PM_OPS(intel_soc_pmic_pm_ops, intel_soc_pmic_suspend, 146 intel_soc_pmic_resume); 147 148static const struct i2c_device_id intel_soc_pmic_i2c_id[] = { 149 { } 150}; 151MODULE_DEVICE_TABLE(i2c, intel_soc_pmic_i2c_id); 152 153#if defined(CONFIG_ACPI) 154static const struct acpi_device_id intel_soc_pmic_acpi_match[] = { 155 { "INT33FD" }, 156 { }, 157}; 158MODULE_DEVICE_TABLE(acpi, intel_soc_pmic_acpi_match); 159#endif 160 161static struct i2c_driver intel_soc_pmic_i2c_driver = { 162 .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), 166 }, 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, 171}; 172 173module_i2c_driver(intel_soc_pmic_i2c_driver); 174 175MODULE_DESCRIPTION("I2C driver for Intel SoC PMIC"); 176MODULE_LICENSE("GPL v2"); 177MODULE_AUTHOR("Yang, Bin <bin.yang@intel.com>"); 178MODULE_AUTHOR("Zhu, Lejun <lejun.zhu@linux.intel.com>");