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