1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * Dollar Cove TI PMIC operation region driver |
4 | * Copyright (C) 2014 Intel Corporation. All rights reserved. |
5 | * |
6 | * Rewritten and cleaned up |
7 | * Copyright (C) 2017 Takashi Iwai <tiwai@suse.de> |
8 | */ |
9 | |
10 | #include <linux/acpi.h> |
11 | #include <linux/init.h> |
12 | #include <linux/mfd/intel_soc_pmic.h> |
13 | #include <linux/platform_device.h> |
14 | #include "intel_pmic.h" |
15 | |
16 | /* registers stored in 16bit BE (high:low, total 10bit) */ |
17 | #define CHTDC_TI_VBAT 0x54 |
18 | #define CHTDC_TI_DIETEMP 0x56 |
19 | #define CHTDC_TI_BPTHERM 0x58 |
20 | #define CHTDC_TI_GPADC 0x5a |
21 | |
22 | static struct pmic_table chtdc_ti_power_table[] = { |
23 | { .address = 0x00, .reg = 0x41 }, /* LDO1 */ |
24 | { .address = 0x04, .reg = 0x42 }, /* LDO2 */ |
25 | { .address = 0x08, .reg = 0x43 }, /* LDO3 */ |
26 | { .address = 0x0c, .reg = 0x45 }, /* LDO5 */ |
27 | { .address = 0x10, .reg = 0x46 }, /* LDO6 */ |
28 | { .address = 0x14, .reg = 0x47 }, /* LDO7 */ |
29 | { .address = 0x18, .reg = 0x48 }, /* LDO8 */ |
30 | { .address = 0x1c, .reg = 0x49 }, /* LDO9 */ |
31 | { .address = 0x20, .reg = 0x4a }, /* LD10 */ |
32 | { .address = 0x24, .reg = 0x4b }, /* LD11 */ |
33 | { .address = 0x28, .reg = 0x4c }, /* LD12 */ |
34 | { .address = 0x2c, .reg = 0x4d }, /* LD13 */ |
35 | { .address = 0x30, .reg = 0x4e }, /* LD14 */ |
36 | }; |
37 | |
38 | static struct pmic_table chtdc_ti_thermal_table[] = { |
39 | { |
40 | .address = 0x00, |
41 | .reg = CHTDC_TI_GPADC |
42 | }, |
43 | { |
44 | .address = 0x0c, |
45 | .reg = CHTDC_TI_GPADC |
46 | }, |
47 | /* TMP2 -> SYSTEMP */ |
48 | { |
49 | .address = 0x18, |
50 | .reg = CHTDC_TI_GPADC |
51 | }, |
52 | /* TMP3 -> BPTHERM */ |
53 | { |
54 | .address = 0x24, |
55 | .reg = CHTDC_TI_BPTHERM |
56 | }, |
57 | { |
58 | .address = 0x30, |
59 | .reg = CHTDC_TI_GPADC |
60 | }, |
61 | /* TMP5 -> DIETEMP */ |
62 | { |
63 | .address = 0x3c, |
64 | .reg = CHTDC_TI_DIETEMP |
65 | }, |
66 | }; |
67 | |
68 | static int chtdc_ti_pmic_get_power(struct regmap *regmap, int reg, int bit, |
69 | u64 *value) |
70 | { |
71 | int data; |
72 | |
73 | if (regmap_read(map: regmap, reg, val: &data)) |
74 | return -EIO; |
75 | |
76 | *value = data & 1; |
77 | return 0; |
78 | } |
79 | |
80 | static int chtdc_ti_pmic_update_power(struct regmap *regmap, int reg, int bit, |
81 | bool on) |
82 | { |
83 | return regmap_update_bits(map: regmap, reg, mask: 1, val: on); |
84 | } |
85 | |
86 | static int chtdc_ti_pmic_get_raw_temp(struct regmap *regmap, int reg) |
87 | { |
88 | u8 buf[2]; |
89 | |
90 | if (regmap_bulk_read(map: regmap, reg, val: buf, val_count: 2)) |
91 | return -EIO; |
92 | |
93 | /* stored in big-endian */ |
94 | return ((buf[0] & 0x03) << 8) | buf[1]; |
95 | } |
96 | |
97 | static const struct intel_pmic_opregion_data chtdc_ti_pmic_opregion_data = { |
98 | .get_power = chtdc_ti_pmic_get_power, |
99 | .update_power = chtdc_ti_pmic_update_power, |
100 | .get_raw_temp = chtdc_ti_pmic_get_raw_temp, |
101 | .lpat_raw_to_temp = acpi_lpat_raw_to_temp, |
102 | .power_table = chtdc_ti_power_table, |
103 | .power_table_count = ARRAY_SIZE(chtdc_ti_power_table), |
104 | .thermal_table = chtdc_ti_thermal_table, |
105 | .thermal_table_count = ARRAY_SIZE(chtdc_ti_thermal_table), |
106 | .pmic_i2c_address = 0x5e, |
107 | }; |
108 | |
109 | static int chtdc_ti_pmic_opregion_probe(struct platform_device *pdev) |
110 | { |
111 | struct intel_soc_pmic *pmic = dev_get_drvdata(dev: pdev->dev.parent); |
112 | int err; |
113 | |
114 | err = intel_pmic_install_opregion_handler(dev: &pdev->dev, |
115 | ACPI_HANDLE(pdev->dev.parent), regmap: pmic->regmap, |
116 | d: &chtdc_ti_pmic_opregion_data); |
117 | if (err < 0) |
118 | return err; |
119 | |
120 | /* Re-enumerate devices depending on PMIC */ |
121 | acpi_dev_clear_dependencies(ACPI_COMPANION(pdev->dev.parent)); |
122 | return 0; |
123 | } |
124 | |
125 | static const struct platform_device_id chtdc_ti_pmic_opregion_id_table[] = { |
126 | { .name = "chtdc_ti_region" }, |
127 | {}, |
128 | }; |
129 | |
130 | static struct platform_driver chtdc_ti_pmic_opregion_driver = { |
131 | .probe = chtdc_ti_pmic_opregion_probe, |
132 | .driver = { |
133 | .name = "cht_dollar_cove_ti_pmic" , |
134 | }, |
135 | .id_table = chtdc_ti_pmic_opregion_id_table, |
136 | }; |
137 | builtin_platform_driver(chtdc_ti_pmic_opregion_driver); |
138 | |