hc
2023-12-11 d2ccde1c8e90d38cee87a1b0309ad2827f3fd30d
kernel/drivers/acpi/pmic/intel_pmic.c
....@@ -1,20 +1,13 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * intel_pmic.c - Intel PMIC operation region driver
34 *
45 * Copyright (C) 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.
146 */
157
168 #include <linux/export.h>
179 #include <linux/acpi.h>
10
+#include <linux/mfd/intel_soc_pmic.h>
1811 #include <linux/regmap.h>
1912 #include <acpi/acpi_lpat.h>
2013 #include "intel_pmic.h"
....@@ -35,6 +28,8 @@
3528 struct intel_pmic_opregion_data *data;
3629 struct intel_pmic_regs_handler_ctx ctx;
3730 };
31
+
32
+static struct intel_pmic_opregion *intel_pmic_opregion;
3833
3934 static int pmic_get_reg_bit(int address, struct pmic_table *table,
4035 int count, int *reg, int *bit)
....@@ -262,7 +257,7 @@
262257 struct regmap *regmap,
263258 struct intel_pmic_opregion_data *d)
264259 {
265
- acpi_status status;
260
+ acpi_status status = AE_OK;
266261 struct intel_pmic_opregion *opregion;
267262 int ret;
268263
....@@ -280,7 +275,8 @@
280275 opregion->regmap = regmap;
281276 opregion->lpat_table = acpi_lpat_get_conversion_table(handle);
282277
283
- status = acpi_install_address_space_handler(handle,
278
+ if (d->power_table_count)
279
+ status = acpi_install_address_space_handler(handle,
284280 PMIC_POWER_OPREGION_ID,
285281 intel_pmic_power_handler,
286282 NULL, opregion);
....@@ -289,13 +285,12 @@
289285 goto out_error;
290286 }
291287
292
- status = acpi_install_address_space_handler(handle,
288
+ if (d->thermal_table_count)
289
+ status = acpi_install_address_space_handler(handle,
293290 PMIC_THERMAL_OPREGION_ID,
294291 intel_pmic_thermal_handler,
295292 NULL, opregion);
296293 if (ACPI_FAILURE(status)) {
297
- acpi_remove_address_space_handler(handle, PMIC_POWER_OPREGION_ID,
298
- intel_pmic_power_handler);
299294 ret = -ENODEV;
300295 goto out_remove_power_handler;
301296 }
....@@ -309,18 +304,80 @@
309304 }
310305
311306 opregion->data = d;
307
+ intel_pmic_opregion = opregion;
312308 return 0;
313309
314310 out_remove_thermal_handler:
315
- acpi_remove_address_space_handler(handle, PMIC_THERMAL_OPREGION_ID,
316
- intel_pmic_thermal_handler);
311
+ if (d->thermal_table_count)
312
+ acpi_remove_address_space_handler(handle,
313
+ PMIC_THERMAL_OPREGION_ID,
314
+ intel_pmic_thermal_handler);
317315
318316 out_remove_power_handler:
319
- acpi_remove_address_space_handler(handle, PMIC_POWER_OPREGION_ID,
320
- intel_pmic_power_handler);
317
+ if (d->power_table_count)
318
+ acpi_remove_address_space_handler(handle,
319
+ PMIC_POWER_OPREGION_ID,
320
+ intel_pmic_power_handler);
321321
322322 out_error:
323323 acpi_lpat_free_conversion_table(opregion->lpat_table);
324324 return ret;
325325 }
326326 EXPORT_SYMBOL_GPL(intel_pmic_install_opregion_handler);
327
+
328
+/**
329
+ * intel_soc_pmic_exec_mipi_pmic_seq_element - Execute PMIC MIPI sequence
330
+ * @i2c_address: I2C client address for the PMIC
331
+ * @reg_address: PMIC register address
332
+ * @value: New value for the register bits to change
333
+ * @mask: Mask indicating which register bits to change
334
+ *
335
+ * DSI LCD panels describe an initialization sequence in the i915 VBT (Video
336
+ * BIOS Tables) using so called MIPI sequences. One possible element in these
337
+ * sequences is a PMIC specific element of 15 bytes.
338
+ *
339
+ * This function executes these PMIC specific elements sending the embedded
340
+ * commands to the PMIC.
341
+ *
342
+ * Return 0 on success, < 0 on failure.
343
+ */
344
+int intel_soc_pmic_exec_mipi_pmic_seq_element(u16 i2c_address, u32 reg_address,
345
+ u32 value, u32 mask)
346
+{
347
+ struct intel_pmic_opregion_data *d;
348
+ int ret;
349
+
350
+ if (!intel_pmic_opregion) {
351
+ pr_warn("%s: No PMIC registered\n", __func__);
352
+ return -ENXIO;
353
+ }
354
+
355
+ d = intel_pmic_opregion->data;
356
+
357
+ mutex_lock(&intel_pmic_opregion->lock);
358
+
359
+ if (d->exec_mipi_pmic_seq_element) {
360
+ ret = d->exec_mipi_pmic_seq_element(intel_pmic_opregion->regmap,
361
+ i2c_address, reg_address,
362
+ value, mask);
363
+ } else if (d->pmic_i2c_address) {
364
+ if (i2c_address == d->pmic_i2c_address) {
365
+ ret = regmap_update_bits(intel_pmic_opregion->regmap,
366
+ reg_address, mask, value);
367
+ } else {
368
+ pr_err("%s: Unexpected i2c-addr: 0x%02x (reg-addr 0x%x value 0x%x mask 0x%x)\n",
369
+ __func__, i2c_address, reg_address, value, mask);
370
+ ret = -ENXIO;
371
+ }
372
+ } else {
373
+ pr_warn("%s: Not implemented\n", __func__);
374
+ pr_warn("%s: i2c-addr: 0x%x reg-addr 0x%x value 0x%x mask 0x%x\n",
375
+ __func__, i2c_address, reg_address, value, mask);
376
+ ret = -EOPNOTSUPP;
377
+ }
378
+
379
+ mutex_unlock(&intel_pmic_opregion->lock);
380
+
381
+ return ret;
382
+}
383
+EXPORT_SYMBOL_GPL(intel_soc_pmic_exec_mipi_pmic_seq_element);