Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Intel CHT Whiskey Cove PMIC operation region driver
0004  * Copyright (C) 2017 Hans de Goede <hdegoede@redhat.com>
0005  *
0006  * Based on various non upstream patches to support the CHT Whiskey Cove PMIC:
0007  * Copyright (C) 2013-2015 Intel Corporation. All rights reserved.
0008  */
0009 
0010 #include <linux/acpi.h>
0011 #include <linux/init.h>
0012 #include <linux/mfd/intel_soc_pmic.h>
0013 #include <linux/platform_device.h>
0014 #include <linux/regmap.h>
0015 #include "intel_pmic.h"
0016 
0017 #define CHT_WC_V1P05A_CTRL      0x6e3b
0018 #define CHT_WC_V1P15_CTRL       0x6e3c
0019 #define CHT_WC_V1P05A_VSEL      0x6e3d
0020 #define CHT_WC_V1P15_VSEL       0x6e3e
0021 #define CHT_WC_V1P8A_CTRL       0x6e56
0022 #define CHT_WC_V1P8SX_CTRL      0x6e57
0023 #define CHT_WC_VDDQ_CTRL        0x6e58
0024 #define CHT_WC_V1P2A_CTRL       0x6e59
0025 #define CHT_WC_V1P2SX_CTRL      0x6e5a
0026 #define CHT_WC_V1P8A_VSEL       0x6e5b
0027 #define CHT_WC_VDDQ_VSEL        0x6e5c
0028 #define CHT_WC_V2P8SX_CTRL      0x6e5d
0029 #define CHT_WC_V3P3A_CTRL       0x6e5e
0030 #define CHT_WC_V3P3SD_CTRL      0x6e5f
0031 #define CHT_WC_VSDIO_CTRL       0x6e67
0032 #define CHT_WC_V3P3A_VSEL       0x6e68
0033 #define CHT_WC_VPROG1A_CTRL     0x6e90
0034 #define CHT_WC_VPROG1B_CTRL     0x6e91
0035 #define CHT_WC_VPROG1F_CTRL     0x6e95
0036 #define CHT_WC_VPROG2D_CTRL     0x6e99
0037 #define CHT_WC_VPROG3A_CTRL     0x6e9a
0038 #define CHT_WC_VPROG3B_CTRL     0x6e9b
0039 #define CHT_WC_VPROG4A_CTRL     0x6e9c
0040 #define CHT_WC_VPROG4B_CTRL     0x6e9d
0041 #define CHT_WC_VPROG4C_CTRL     0x6e9e
0042 #define CHT_WC_VPROG4D_CTRL     0x6e9f
0043 #define CHT_WC_VPROG5A_CTRL     0x6ea0
0044 #define CHT_WC_VPROG5B_CTRL     0x6ea1
0045 #define CHT_WC_VPROG6A_CTRL     0x6ea2
0046 #define CHT_WC_VPROG6B_CTRL     0x6ea3
0047 #define CHT_WC_VPROG1A_VSEL     0x6ec0
0048 #define CHT_WC_VPROG1B_VSEL     0x6ec1
0049 #define CHT_WC_V1P8SX_VSEL      0x6ec2
0050 #define CHT_WC_V1P2SX_VSEL      0x6ec3
0051 #define CHT_WC_V1P2A_VSEL       0x6ec4
0052 #define CHT_WC_VPROG1F_VSEL     0x6ec5
0053 #define CHT_WC_VSDIO_VSEL       0x6ec6
0054 #define CHT_WC_V2P8SX_VSEL      0x6ec7
0055 #define CHT_WC_V3P3SD_VSEL      0x6ec8
0056 #define CHT_WC_VPROG2D_VSEL     0x6ec9
0057 #define CHT_WC_VPROG3A_VSEL     0x6eca
0058 #define CHT_WC_VPROG3B_VSEL     0x6ecb
0059 #define CHT_WC_VPROG4A_VSEL     0x6ecc
0060 #define CHT_WC_VPROG4B_VSEL     0x6ecd
0061 #define CHT_WC_VPROG4C_VSEL     0x6ece
0062 #define CHT_WC_VPROG4D_VSEL     0x6ecf
0063 #define CHT_WC_VPROG5A_VSEL     0x6ed0
0064 #define CHT_WC_VPROG5B_VSEL     0x6ed1
0065 #define CHT_WC_VPROG6A_VSEL     0x6ed2
0066 #define CHT_WC_VPROG6B_VSEL     0x6ed3
0067 
0068 /*
0069  * Regulator support is based on the non upstream patch:
0070  * "regulator: whiskey_cove: implements Whiskey Cove pmic VRF support"
0071  * https://github.com/intel-aero/meta-intel-aero/blob/master/recipes-kernel/linux/linux-yocto/0019-regulator-whiskey_cove-implements-WhiskeyCove-pmic-V.patch
0072  */
0073 static struct pmic_table power_table[] = {
0074     {
0075         .address = 0x0,
0076         .reg = CHT_WC_V1P8A_CTRL,
0077         .bit = 0x01,
0078     }, /* V18A */
0079     {
0080         .address = 0x04,
0081         .reg = CHT_WC_V1P8SX_CTRL,
0082         .bit = 0x07,
0083     }, /* V18X */
0084     {
0085         .address = 0x08,
0086         .reg = CHT_WC_VDDQ_CTRL,
0087         .bit = 0x01,
0088     }, /* VDDQ */
0089     {
0090         .address = 0x0c,
0091         .reg = CHT_WC_V1P2A_CTRL,
0092         .bit = 0x07,
0093     }, /* V12A */
0094     {
0095         .address = 0x10,
0096         .reg = CHT_WC_V1P2SX_CTRL,
0097         .bit = 0x07,
0098     }, /* V12X */
0099     {
0100         .address = 0x14,
0101         .reg = CHT_WC_V2P8SX_CTRL,
0102         .bit = 0x07,
0103     }, /* V28X */
0104     {
0105         .address = 0x18,
0106         .reg = CHT_WC_V3P3A_CTRL,
0107         .bit = 0x01,
0108     }, /* V33A */
0109     {
0110         .address = 0x1c,
0111         .reg = CHT_WC_V3P3SD_CTRL,
0112         .bit = 0x07,
0113     }, /* V3SD */
0114     {
0115         .address = 0x20,
0116         .reg = CHT_WC_VSDIO_CTRL,
0117         .bit = 0x07,
0118     }, /* VSD */
0119 /*  {
0120         .address = 0x24,
0121         .reg = ??,
0122         .bit = ??,
0123     }, ** VSW2 */
0124 /*  {
0125         .address = 0x28,
0126         .reg = ??,
0127         .bit = ??,
0128     }, ** VSW1 */
0129 /*  {
0130         .address = 0x2c,
0131         .reg = ??,
0132         .bit = ??,
0133     }, ** VUPY */
0134 /*  {
0135         .address = 0x30,
0136         .reg = ??,
0137         .bit = ??,
0138     }, ** VRSO */
0139     {
0140         .address = 0x34,
0141         .reg = CHT_WC_VPROG1A_CTRL,
0142         .bit = 0x07,
0143     }, /* VP1A */
0144     {
0145         .address = 0x38,
0146         .reg = CHT_WC_VPROG1B_CTRL,
0147         .bit = 0x07,
0148     }, /* VP1B */
0149     {
0150         .address = 0x3c,
0151         .reg = CHT_WC_VPROG1F_CTRL,
0152         .bit = 0x07,
0153     }, /* VP1F */
0154     {
0155         .address = 0x40,
0156         .reg = CHT_WC_VPROG2D_CTRL,
0157         .bit = 0x07,
0158     }, /* VP2D */
0159     {
0160         .address = 0x44,
0161         .reg = CHT_WC_VPROG3A_CTRL,
0162         .bit = 0x07,
0163     }, /* VP3A */
0164     {
0165         .address = 0x48,
0166         .reg = CHT_WC_VPROG3B_CTRL,
0167         .bit = 0x07,
0168     }, /* VP3B */
0169     {
0170         .address = 0x4c,
0171         .reg = CHT_WC_VPROG4A_CTRL,
0172         .bit = 0x07,
0173     }, /* VP4A */
0174     {
0175         .address = 0x50,
0176         .reg = CHT_WC_VPROG4B_CTRL,
0177         .bit = 0x07,
0178     }, /* VP4B */
0179     {
0180         .address = 0x54,
0181         .reg = CHT_WC_VPROG4C_CTRL,
0182         .bit = 0x07,
0183     }, /* VP4C */
0184     {
0185         .address = 0x58,
0186         .reg = CHT_WC_VPROG4D_CTRL,
0187         .bit = 0x07,
0188     }, /* VP4D */
0189     {
0190         .address = 0x5c,
0191         .reg = CHT_WC_VPROG5A_CTRL,
0192         .bit = 0x07,
0193     }, /* VP5A */
0194     {
0195         .address = 0x60,
0196         .reg = CHT_WC_VPROG5B_CTRL,
0197         .bit = 0x07,
0198     }, /* VP5B */
0199     {
0200         .address = 0x64,
0201         .reg = CHT_WC_VPROG6A_CTRL,
0202         .bit = 0x07,
0203     }, /* VP6A */
0204     {
0205         .address = 0x68,
0206         .reg = CHT_WC_VPROG6B_CTRL,
0207         .bit = 0x07,
0208     }, /* VP6B */
0209 /*  {
0210         .address = 0x6c,
0211         .reg = ??,
0212         .bit = ??,
0213     }  ** VP7A */
0214 };
0215 
0216 static int intel_cht_wc_pmic_get_power(struct regmap *regmap, int reg,
0217         int bit, u64 *value)
0218 {
0219     int data;
0220 
0221     if (regmap_read(regmap, reg, &data))
0222         return -EIO;
0223 
0224     *value = (data & bit) ? 1 : 0;
0225     return 0;
0226 }
0227 
0228 static int intel_cht_wc_pmic_update_power(struct regmap *regmap, int reg,
0229         int bitmask, bool on)
0230 {
0231     return regmap_update_bits(regmap, reg, bitmask, on ? 1 : 0);
0232 }
0233 
0234 static int intel_cht_wc_exec_mipi_pmic_seq_element(struct regmap *regmap,
0235                            u16 i2c_client_address,
0236                            u32 reg_address,
0237                            u32 value, u32 mask)
0238 {
0239     u32 address;
0240 
0241     if (i2c_client_address > 0xff || reg_address > 0xff) {
0242         pr_warn("%s warning addresses too big client 0x%x reg 0x%x\n",
0243             __func__, i2c_client_address, reg_address);
0244         return -ERANGE;
0245     }
0246 
0247     address = (i2c_client_address << 8) | reg_address;
0248 
0249     return regmap_update_bits(regmap, address, mask, value);
0250 }
0251 
0252 /*
0253  * The thermal table and ops are empty, we do not support the Thermal opregion
0254  * (DPTF) due to lacking documentation.
0255  */
0256 static const struct intel_pmic_opregion_data intel_cht_wc_pmic_opregion_data = {
0257     .get_power      = intel_cht_wc_pmic_get_power,
0258     .update_power       = intel_cht_wc_pmic_update_power,
0259     .exec_mipi_pmic_seq_element = intel_cht_wc_exec_mipi_pmic_seq_element,
0260     .lpat_raw_to_temp   = acpi_lpat_raw_to_temp,
0261     .power_table        = power_table,
0262     .power_table_count  = ARRAY_SIZE(power_table),
0263 };
0264 
0265 static int intel_cht_wc_pmic_opregion_probe(struct platform_device *pdev)
0266 {
0267     struct intel_soc_pmic *pmic = dev_get_drvdata(pdev->dev.parent);
0268 
0269     return intel_pmic_install_opregion_handler(&pdev->dev,
0270             ACPI_HANDLE(pdev->dev.parent),
0271             pmic->regmap,
0272             &intel_cht_wc_pmic_opregion_data);
0273 }
0274 
0275 static const struct platform_device_id cht_wc_opregion_id_table[] = {
0276     { .name = "cht_wcove_region" },
0277     {},
0278 };
0279 
0280 static struct platform_driver intel_cht_wc_pmic_opregion_driver = {
0281     .probe = intel_cht_wc_pmic_opregion_probe,
0282     .driver = {
0283         .name = "cht_whiskey_cove_pmic",
0284     },
0285     .id_table = cht_wc_opregion_id_table,
0286 };
0287 builtin_platform_driver(intel_cht_wc_pmic_opregion_driver);