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