0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/acpi.h>
0009 #include <linux/init.h>
0010 #include <linux/mfd/intel_soc_pmic.h>
0011 #include <linux/platform_device.h>
0012 #include <linux/regmap.h>
0013 #include "intel_pmic.h"
0014
0015 #define PWR_SOURCE_SELECT BIT(1)
0016
0017 #define PMIC_A0LOCK_REG 0xc5
0018
0019 static struct pmic_table power_table[] = {
0020
0021
0022
0023
0024
0025 {
0026 .address = 0x04,
0027 .reg = 0x63,
0028 .bit = 0x00,
0029 },
0030 {
0031 .address = 0x08,
0032 .reg = 0x62,
0033 .bit = 0x00,
0034 },
0035 {
0036 .address = 0x0c,
0037 .reg = 0x64,
0038 .bit = 0x00,
0039 },
0040 {
0041 .address = 0x10,
0042 .reg = 0x6a,
0043 .bit = 0x00,
0044 },
0045 {
0046 .address = 0x14,
0047 .reg = 0x6b,
0048 .bit = 0x00,
0049 },
0050 {
0051 .address = 0x18,
0052 .reg = 0x6c,
0053 .bit = 0x00,
0054 },
0055 {
0056 .address = 0x1c,
0057 .reg = 0x6d,
0058 .bit = 0x00,
0059 },
0060
0061
0062
0063
0064
0065 {
0066 .address = 0x24,
0067 .reg = 0x66,
0068 .bit = 0x00,
0069 },
0070
0071
0072
0073
0074
0075 {
0076 .address = 0x2c,
0077 .reg = 0x69,
0078 .bit = 0x00,
0079 },
0080 {
0081 .address = 0x30,
0082 .reg = 0x68,
0083 .bit = 0x00,
0084 },
0085
0086
0087
0088
0089
0090 {
0091 .address = 0x44,
0092 .reg = 0x5c,
0093 .bit = 0x00,
0094 },
0095 {
0096 .address = 0x48,
0097 .reg = 0x5d,
0098 .bit = 0x00,
0099 },
0100 {
0101 .address = 0x4c,
0102 .reg = 0x5b,
0103 .bit = 0x00,
0104 },
0105 {
0106 .address = 0x50,
0107 .reg = 0x61,
0108 .bit = 0x00,
0109 },
0110 {
0111 .address = 0x54,
0112 .reg = 0x60,
0113 .bit = 0x00,
0114 },
0115
0116
0117
0118
0119
0120 {
0121 .address = 0x5c,
0122 .reg = 0x56,
0123 .bit = 0x00,
0124 },
0125 {
0126 .address = 0x60,
0127 .reg = 0x57,
0128 .bit = 0x00,
0129 },
0130 {
0131 .address = 0x64,
0132 .reg = 0x59,
0133 .bit = 0x00,
0134 },
0135 };
0136
0137 static struct pmic_table thermal_table[] = {
0138 {
0139 .address = 0x00,
0140 .reg = 0x75
0141 },
0142 {
0143 .address = 0x04,
0144 .reg = 0x95
0145 },
0146 {
0147 .address = 0x08,
0148 .reg = 0x97
0149 },
0150 {
0151 .address = 0x0c,
0152 .reg = 0x77
0153 },
0154 {
0155 .address = 0x10,
0156 .reg = 0x9a
0157 },
0158 {
0159 .address = 0x14,
0160 .reg = 0x9c
0161 },
0162 {
0163 .address = 0x18,
0164 .reg = 0x79
0165 },
0166 {
0167 .address = 0x1c,
0168 .reg = 0x9f
0169 },
0170 {
0171 .address = 0x20,
0172 .reg = 0xa1
0173 },
0174 {
0175 .address = 0x48,
0176 .reg = 0x94
0177 },
0178 {
0179 .address = 0x4c,
0180 .reg = 0x99
0181 },
0182 {
0183 .address = 0x50,
0184 .reg = 0x9e
0185 },
0186 };
0187
0188 static int intel_crc_pmic_get_power(struct regmap *regmap, int reg,
0189 int bit, u64 *value)
0190 {
0191 int data;
0192
0193 if (regmap_read(regmap, reg, &data))
0194 return -EIO;
0195
0196 *value = (data & PWR_SOURCE_SELECT) && (data & BIT(bit)) ? 1 : 0;
0197 return 0;
0198 }
0199
0200 static int intel_crc_pmic_update_power(struct regmap *regmap, int reg,
0201 int bit, bool on)
0202 {
0203 int data;
0204
0205 if (regmap_read(regmap, reg, &data))
0206 return -EIO;
0207
0208 if (on) {
0209 data |= PWR_SOURCE_SELECT | BIT(bit);
0210 } else {
0211 data &= ~BIT(bit);
0212 data |= PWR_SOURCE_SELECT;
0213 }
0214
0215 if (regmap_write(regmap, reg, data))
0216 return -EIO;
0217 return 0;
0218 }
0219
0220 static int intel_crc_pmic_get_raw_temp(struct regmap *regmap, int reg)
0221 {
0222 int temp_l, temp_h;
0223
0224
0225
0226
0227
0228 if (regmap_read(regmap, reg, &temp_l) ||
0229 regmap_read(regmap, reg - 1, &temp_h))
0230 return -EIO;
0231
0232 return temp_l | (temp_h & 0x3) << 8;
0233 }
0234
0235 static int intel_crc_pmic_update_aux(struct regmap *regmap, int reg, int raw)
0236 {
0237 return regmap_write(regmap, reg, raw) ||
0238 regmap_update_bits(regmap, reg - 1, 0x3, raw >> 8) ? -EIO : 0;
0239 }
0240
0241 static int intel_crc_pmic_get_policy(struct regmap *regmap,
0242 int reg, int bit, u64 *value)
0243 {
0244 int pen;
0245
0246 if (regmap_read(regmap, reg, &pen))
0247 return -EIO;
0248 *value = pen >> 7;
0249 return 0;
0250 }
0251
0252 static int intel_crc_pmic_update_policy(struct regmap *regmap,
0253 int reg, int bit, int enable)
0254 {
0255 int alert0;
0256
0257
0258 if (regmap_read(regmap, PMIC_A0LOCK_REG, &alert0))
0259 return -EIO;
0260
0261 if (regmap_update_bits(regmap, PMIC_A0LOCK_REG, 0x01, 0))
0262 return -EIO;
0263
0264 if (regmap_update_bits(regmap, reg, 0x80, enable << 7))
0265 return -EIO;
0266
0267
0268 if (regmap_write(regmap, PMIC_A0LOCK_REG, alert0))
0269 return -EIO;
0270
0271 return 0;
0272 }
0273
0274 static const struct intel_pmic_opregion_data intel_crc_pmic_opregion_data = {
0275 .get_power = intel_crc_pmic_get_power,
0276 .update_power = intel_crc_pmic_update_power,
0277 .get_raw_temp = intel_crc_pmic_get_raw_temp,
0278 .update_aux = intel_crc_pmic_update_aux,
0279 .get_policy = intel_crc_pmic_get_policy,
0280 .update_policy = intel_crc_pmic_update_policy,
0281 .lpat_raw_to_temp = acpi_lpat_raw_to_temp,
0282 .power_table = power_table,
0283 .power_table_count= ARRAY_SIZE(power_table),
0284 .thermal_table = thermal_table,
0285 .thermal_table_count = ARRAY_SIZE(thermal_table),
0286 };
0287
0288 static int intel_crc_pmic_opregion_probe(struct platform_device *pdev)
0289 {
0290 struct intel_soc_pmic *pmic = dev_get_drvdata(pdev->dev.parent);
0291 return intel_pmic_install_opregion_handler(&pdev->dev,
0292 ACPI_HANDLE(pdev->dev.parent), pmic->regmap,
0293 &intel_crc_pmic_opregion_data);
0294 }
0295
0296 static struct platform_driver intel_crc_pmic_opregion_driver = {
0297 .probe = intel_crc_pmic_opregion_probe,
0298 .driver = {
0299 .name = "byt_crystal_cove_pmic",
0300 },
0301 };
0302 builtin_platform_driver(intel_crc_pmic_opregion_driver);