Merge tag 'tpmdd-next-v5.14-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git...
[linux-2.6-microblaze.git] / drivers / acpi / pmic / intel_pmic_chtwc.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Intel CHT Whiskey Cove PMIC operation region driver
4  * Copyright (C) 2017 Hans de Goede <hdegoede@redhat.com>
5  *
6  * Based on various non upstream patches to support the CHT Whiskey Cove PMIC:
7  * Copyright (C) 2013-2015 Intel Corporation. All rights reserved.
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 <linux/regmap.h>
15 #include "intel_pmic.h"
16
17 #define CHT_WC_V1P05A_CTRL              0x6e3b
18 #define CHT_WC_V1P15_CTRL               0x6e3c
19 #define CHT_WC_V1P05A_VSEL              0x6e3d
20 #define CHT_WC_V1P15_VSEL               0x6e3e
21 #define CHT_WC_V1P8A_CTRL               0x6e56
22 #define CHT_WC_V1P8SX_CTRL              0x6e57
23 #define CHT_WC_VDDQ_CTRL                0x6e58
24 #define CHT_WC_V1P2A_CTRL               0x6e59
25 #define CHT_WC_V1P2SX_CTRL              0x6e5a
26 #define CHT_WC_V1P8A_VSEL               0x6e5b
27 #define CHT_WC_VDDQ_VSEL                0x6e5c
28 #define CHT_WC_V2P8SX_CTRL              0x6e5d
29 #define CHT_WC_V3P3A_CTRL               0x6e5e
30 #define CHT_WC_V3P3SD_CTRL              0x6e5f
31 #define CHT_WC_VSDIO_CTRL               0x6e67
32 #define CHT_WC_V3P3A_VSEL               0x6e68
33 #define CHT_WC_VPROG1A_CTRL             0x6e90
34 #define CHT_WC_VPROG1B_CTRL             0x6e91
35 #define CHT_WC_VPROG1F_CTRL             0x6e95
36 #define CHT_WC_VPROG2D_CTRL             0x6e99
37 #define CHT_WC_VPROG3A_CTRL             0x6e9a
38 #define CHT_WC_VPROG3B_CTRL             0x6e9b
39 #define CHT_WC_VPROG4A_CTRL             0x6e9c
40 #define CHT_WC_VPROG4B_CTRL             0x6e9d
41 #define CHT_WC_VPROG4C_CTRL             0x6e9e
42 #define CHT_WC_VPROG4D_CTRL             0x6e9f
43 #define CHT_WC_VPROG5A_CTRL             0x6ea0
44 #define CHT_WC_VPROG5B_CTRL             0x6ea1
45 #define CHT_WC_VPROG6A_CTRL             0x6ea2
46 #define CHT_WC_VPROG6B_CTRL             0x6ea3
47 #define CHT_WC_VPROG1A_VSEL             0x6ec0
48 #define CHT_WC_VPROG1B_VSEL             0x6ec1
49 #define CHT_WC_V1P8SX_VSEL              0x6ec2
50 #define CHT_WC_V1P2SX_VSEL              0x6ec3
51 #define CHT_WC_V1P2A_VSEL               0x6ec4
52 #define CHT_WC_VPROG1F_VSEL             0x6ec5
53 #define CHT_WC_VSDIO_VSEL               0x6ec6
54 #define CHT_WC_V2P8SX_VSEL              0x6ec7
55 #define CHT_WC_V3P3SD_VSEL              0x6ec8
56 #define CHT_WC_VPROG2D_VSEL             0x6ec9
57 #define CHT_WC_VPROG3A_VSEL             0x6eca
58 #define CHT_WC_VPROG3B_VSEL             0x6ecb
59 #define CHT_WC_VPROG4A_VSEL             0x6ecc
60 #define CHT_WC_VPROG4B_VSEL             0x6ecd
61 #define CHT_WC_VPROG4C_VSEL             0x6ece
62 #define CHT_WC_VPROG4D_VSEL             0x6ecf
63 #define CHT_WC_VPROG5A_VSEL             0x6ed0
64 #define CHT_WC_VPROG5B_VSEL             0x6ed1
65 #define CHT_WC_VPROG6A_VSEL             0x6ed2
66 #define CHT_WC_VPROG6B_VSEL             0x6ed3
67
68 /*
69  * Regulator support is based on the non upstream patch:
70  * "regulator: whiskey_cove: implements Whiskey Cove pmic VRF support"
71  * https://github.com/intel-aero/meta-intel-aero/blob/master/recipes-kernel/linux/linux-yocto/0019-regulator-whiskey_cove-implements-WhiskeyCove-pmic-V.patch
72  */
73 static struct pmic_table power_table[] = {
74         {
75                 .address = 0x0,
76                 .reg = CHT_WC_V1P8A_CTRL,
77                 .bit = 0x01,
78         }, /* V18A */
79         {
80                 .address = 0x04,
81                 .reg = CHT_WC_V1P8SX_CTRL,
82                 .bit = 0x07,
83         }, /* V18X */
84         {
85                 .address = 0x08,
86                 .reg = CHT_WC_VDDQ_CTRL,
87                 .bit = 0x01,
88         }, /* VDDQ */
89         {
90                 .address = 0x0c,
91                 .reg = CHT_WC_V1P2A_CTRL,
92                 .bit = 0x07,
93         }, /* V12A */
94         {
95                 .address = 0x10,
96                 .reg = CHT_WC_V1P2SX_CTRL,
97                 .bit = 0x07,
98         }, /* V12X */
99         {
100                 .address = 0x14,
101                 .reg = CHT_WC_V2P8SX_CTRL,
102                 .bit = 0x07,
103         }, /* V28X */
104         {
105                 .address = 0x18,
106                 .reg = CHT_WC_V3P3A_CTRL,
107                 .bit = 0x01,
108         }, /* V33A */
109         {
110                 .address = 0x1c,
111                 .reg = CHT_WC_V3P3SD_CTRL,
112                 .bit = 0x07,
113         }, /* V3SD */
114         {
115                 .address = 0x20,
116                 .reg = CHT_WC_VSDIO_CTRL,
117                 .bit = 0x07,
118         }, /* VSD */
119 /*      {
120                 .address = 0x24,
121                 .reg = ??,
122                 .bit = ??,
123         }, ** VSW2 */
124 /*      {
125                 .address = 0x28,
126                 .reg = ??,
127                 .bit = ??,
128         }, ** VSW1 */
129 /*      {
130                 .address = 0x2c,
131                 .reg = ??,
132                 .bit = ??,
133         }, ** VUPY */
134 /*      {
135                 .address = 0x30,
136                 .reg = ??,
137                 .bit = ??,
138         }, ** VRSO */
139         {
140                 .address = 0x34,
141                 .reg = CHT_WC_VPROG1A_CTRL,
142                 .bit = 0x07,
143         }, /* VP1A */
144         {
145                 .address = 0x38,
146                 .reg = CHT_WC_VPROG1B_CTRL,
147                 .bit = 0x07,
148         }, /* VP1B */
149         {
150                 .address = 0x3c,
151                 .reg = CHT_WC_VPROG1F_CTRL,
152                 .bit = 0x07,
153         }, /* VP1F */
154         {
155                 .address = 0x40,
156                 .reg = CHT_WC_VPROG2D_CTRL,
157                 .bit = 0x07,
158         }, /* VP2D */
159         {
160                 .address = 0x44,
161                 .reg = CHT_WC_VPROG3A_CTRL,
162                 .bit = 0x07,
163         }, /* VP3A */
164         {
165                 .address = 0x48,
166                 .reg = CHT_WC_VPROG3B_CTRL,
167                 .bit = 0x07,
168         }, /* VP3B */
169         {
170                 .address = 0x4c,
171                 .reg = CHT_WC_VPROG4A_CTRL,
172                 .bit = 0x07,
173         }, /* VP4A */
174         {
175                 .address = 0x50,
176                 .reg = CHT_WC_VPROG4B_CTRL,
177                 .bit = 0x07,
178         }, /* VP4B */
179         {
180                 .address = 0x54,
181                 .reg = CHT_WC_VPROG4C_CTRL,
182                 .bit = 0x07,
183         }, /* VP4C */
184         {
185                 .address = 0x58,
186                 .reg = CHT_WC_VPROG4D_CTRL,
187                 .bit = 0x07,
188         }, /* VP4D */
189         {
190                 .address = 0x5c,
191                 .reg = CHT_WC_VPROG5A_CTRL,
192                 .bit = 0x07,
193         }, /* VP5A */
194         {
195                 .address = 0x60,
196                 .reg = CHT_WC_VPROG5B_CTRL,
197                 .bit = 0x07,
198         }, /* VP5B */
199         {
200                 .address = 0x64,
201                 .reg = CHT_WC_VPROG6A_CTRL,
202                 .bit = 0x07,
203         }, /* VP6A */
204         {
205                 .address = 0x68,
206                 .reg = CHT_WC_VPROG6B_CTRL,
207                 .bit = 0x07,
208         }, /* VP6B */
209 /*      {
210                 .address = 0x6c,
211                 .reg = ??,
212                 .bit = ??,
213         }  ** VP7A */
214 };
215
216 static int intel_cht_wc_pmic_get_power(struct regmap *regmap, int reg,
217                 int bit, u64 *value)
218 {
219         int data;
220
221         if (regmap_read(regmap, reg, &data))
222                 return -EIO;
223
224         *value = (data & bit) ? 1 : 0;
225         return 0;
226 }
227
228 static int intel_cht_wc_pmic_update_power(struct regmap *regmap, int reg,
229                 int bitmask, bool on)
230 {
231         return regmap_update_bits(regmap, reg, bitmask, on ? 1 : 0);
232 }
233
234 static int intel_cht_wc_exec_mipi_pmic_seq_element(struct regmap *regmap,
235                                                    u16 i2c_client_address,
236                                                    u32 reg_address,
237                                                    u32 value, u32 mask)
238 {
239         u32 address;
240
241         if (i2c_client_address > 0xff || reg_address > 0xff) {
242                 pr_warn("%s warning addresses too big client 0x%x reg 0x%x\n",
243                         __func__, i2c_client_address, reg_address);
244                 return -ERANGE;
245         }
246
247         address = (i2c_client_address << 8) | reg_address;
248
249         return regmap_update_bits(regmap, address, mask, value);
250 }
251
252 /*
253  * The thermal table and ops are empty, we do not support the Thermal opregion
254  * (DPTF) due to lacking documentation.
255  */
256 static struct intel_pmic_opregion_data intel_cht_wc_pmic_opregion_data = {
257         .get_power              = intel_cht_wc_pmic_get_power,
258         .update_power           = intel_cht_wc_pmic_update_power,
259         .exec_mipi_pmic_seq_element = intel_cht_wc_exec_mipi_pmic_seq_element,
260         .power_table            = power_table,
261         .power_table_count      = ARRAY_SIZE(power_table),
262 };
263
264 static int intel_cht_wc_pmic_opregion_probe(struct platform_device *pdev)
265 {
266         struct intel_soc_pmic *pmic = dev_get_drvdata(pdev->dev.parent);
267
268         return intel_pmic_install_opregion_handler(&pdev->dev,
269                         ACPI_HANDLE(pdev->dev.parent),
270                         pmic->regmap,
271                         &intel_cht_wc_pmic_opregion_data);
272 }
273
274 static const struct platform_device_id cht_wc_opregion_id_table[] = {
275         { .name = "cht_wcove_region" },
276         {},
277 };
278
279 static struct platform_driver intel_cht_wc_pmic_opregion_driver = {
280         .probe = intel_cht_wc_pmic_opregion_probe,
281         .driver = {
282                 .name = "cht_whiskey_cove_pmic",
283         },
284         .id_table = cht_wc_opregion_id_table,
285 };
286 builtin_platform_driver(intel_cht_wc_pmic_opregion_driver);