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 v4.14-rc2 205 lines 5.4 kB view raw
1/* 2 * intel_soc_pmic_core.c - Intel SoC PMIC MFD Driver 3 * 4 * Copyright (C) 2013, 2014 Intel Corporation. All rights reserved. 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License version 8 * 2 as published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * Author: Yang, Bin <bin.yang@intel.com> 16 * Author: Zhu, Lejun <lejun.zhu@linux.intel.com> 17 */ 18 19#include <linux/acpi.h> 20#include <linux/module.h> 21#include <linux/mfd/core.h> 22#include <linux/i2c.h> 23#include <linux/interrupt.h> 24#include <linux/gpio/consumer.h> 25#include <linux/acpi.h> 26#include <linux/regmap.h> 27#include <linux/mfd/intel_soc_pmic.h> 28#include <linux/gpio/machine.h> 29#include <linux/pwm.h> 30#include "intel_soc_pmic_core.h" 31 32/* Crystal Cove PMIC shares same ACPI ID between different platforms */ 33#define BYT_CRC_HRV 2 34#define CHT_CRC_HRV 3 35 36/* Lookup table for the Panel Enable/Disable line as GPIO signals */ 37static struct gpiod_lookup_table panel_gpio_table = { 38 /* Intel GFX is consumer */ 39 .dev_id = "0000:00:02.0", 40 .table = { 41 /* Panel EN/DISABLE */ 42 GPIO_LOOKUP("gpio_crystalcove", 94, "panel", GPIO_ACTIVE_HIGH), 43 { }, 44 }, 45}; 46 47/* PWM consumed by the Intel GFX */ 48static struct pwm_lookup crc_pwm_lookup[] = { 49 PWM_LOOKUP("crystal_cove_pwm", 0, "0000:00:02.0", "pwm_backlight", 0, PWM_POLARITY_NORMAL), 50}; 51 52static int intel_soc_pmic_i2c_probe(struct i2c_client *i2c, 53 const struct i2c_device_id *i2c_id) 54{ 55 struct device *dev = &i2c->dev; 56 struct intel_soc_pmic_config *config; 57 struct intel_soc_pmic *pmic; 58 unsigned long long hrv; 59 acpi_status status; 60 int ret; 61 62 /* 63 * There are 2 different Crystal Cove PMICs a Bay Trail and Cherry 64 * Trail version, use _HRV to differentiate between the 2. 65 */ 66 status = acpi_evaluate_integer(ACPI_HANDLE(dev), "_HRV", NULL, &hrv); 67 if (ACPI_FAILURE(status)) { 68 dev_err(dev, "Failed to get PMIC hardware revision\n"); 69 return -ENODEV; 70 } 71 72 switch (hrv) { 73 case BYT_CRC_HRV: 74 config = &intel_soc_pmic_config_byt_crc; 75 break; 76 case CHT_CRC_HRV: 77 config = &intel_soc_pmic_config_cht_crc; 78 break; 79 default: 80 dev_warn(dev, "Unknown hardware rev %llu, assuming BYT\n", hrv); 81 config = &intel_soc_pmic_config_byt_crc; 82 } 83 84 pmic = devm_kzalloc(dev, sizeof(*pmic), GFP_KERNEL); 85 if (!pmic) 86 return -ENOMEM; 87 88 dev_set_drvdata(dev, pmic); 89 90 pmic->regmap = devm_regmap_init_i2c(i2c, config->regmap_config); 91 if (IS_ERR(pmic->regmap)) 92 return PTR_ERR(pmic->regmap); 93 94 pmic->irq = i2c->irq; 95 96 ret = regmap_add_irq_chip(pmic->regmap, pmic->irq, 97 config->irq_flags | IRQF_ONESHOT, 98 0, config->irq_chip, 99 &pmic->irq_chip_data); 100 if (ret) 101 return ret; 102 103 ret = enable_irq_wake(pmic->irq); 104 if (ret) 105 dev_warn(dev, "Can't enable IRQ as wake source: %d\n", ret); 106 107 /* Add lookup table binding for Panel Control to the GPIO Chip */ 108 gpiod_add_lookup_table(&panel_gpio_table); 109 110 /* Add lookup table for crc-pwm */ 111 pwm_add_table(crc_pwm_lookup, ARRAY_SIZE(crc_pwm_lookup)); 112 113 ret = mfd_add_devices(dev, -1, config->cell_dev, 114 config->n_cell_devs, NULL, 0, 115 regmap_irq_get_domain(pmic->irq_chip_data)); 116 if (ret) 117 goto err_del_irq_chip; 118 119 return 0; 120 121err_del_irq_chip: 122 regmap_del_irq_chip(pmic->irq, pmic->irq_chip_data); 123 return ret; 124} 125 126static int intel_soc_pmic_i2c_remove(struct i2c_client *i2c) 127{ 128 struct intel_soc_pmic *pmic = dev_get_drvdata(&i2c->dev); 129 130 regmap_del_irq_chip(pmic->irq, pmic->irq_chip_data); 131 132 /* Remove lookup table for Panel Control from the GPIO Chip */ 133 gpiod_remove_lookup_table(&panel_gpio_table); 134 135 /* remove crc-pwm lookup table */ 136 pwm_remove_table(crc_pwm_lookup, ARRAY_SIZE(crc_pwm_lookup)); 137 138 mfd_remove_devices(&i2c->dev); 139 140 return 0; 141} 142 143static void intel_soc_pmic_shutdown(struct i2c_client *i2c) 144{ 145 struct intel_soc_pmic *pmic = dev_get_drvdata(&i2c->dev); 146 147 disable_irq(pmic->irq); 148 149 return; 150} 151 152#if defined(CONFIG_PM_SLEEP) 153static int intel_soc_pmic_suspend(struct device *dev) 154{ 155 struct intel_soc_pmic *pmic = dev_get_drvdata(dev); 156 157 disable_irq(pmic->irq); 158 159 return 0; 160} 161 162static int intel_soc_pmic_resume(struct device *dev) 163{ 164 struct intel_soc_pmic *pmic = dev_get_drvdata(dev); 165 166 enable_irq(pmic->irq); 167 168 return 0; 169} 170#endif 171 172static SIMPLE_DEV_PM_OPS(intel_soc_pmic_pm_ops, intel_soc_pmic_suspend, 173 intel_soc_pmic_resume); 174 175static const struct i2c_device_id intel_soc_pmic_i2c_id[] = { 176 { } 177}; 178MODULE_DEVICE_TABLE(i2c, intel_soc_pmic_i2c_id); 179 180#if defined(CONFIG_ACPI) 181static const struct acpi_device_id intel_soc_pmic_acpi_match[] = { 182 { "INT33FD" }, 183 { }, 184}; 185MODULE_DEVICE_TABLE(acpi, intel_soc_pmic_acpi_match); 186#endif 187 188static struct i2c_driver intel_soc_pmic_i2c_driver = { 189 .driver = { 190 .name = "intel_soc_pmic_i2c", 191 .pm = &intel_soc_pmic_pm_ops, 192 .acpi_match_table = ACPI_PTR(intel_soc_pmic_acpi_match), 193 }, 194 .probe = intel_soc_pmic_i2c_probe, 195 .remove = intel_soc_pmic_i2c_remove, 196 .id_table = intel_soc_pmic_i2c_id, 197 .shutdown = intel_soc_pmic_shutdown, 198}; 199 200module_i2c_driver(intel_soc_pmic_i2c_driver); 201 202MODULE_DESCRIPTION("I2C driver for Intel SoC PMIC"); 203MODULE_LICENSE("GPL v2"); 204MODULE_AUTHOR("Yang, Bin <bin.yang@intel.com>"); 205MODULE_AUTHOR("Zhu, Lejun <lejun.zhu@linux.intel.com>");