linux/drivers/acpi/pmic/intel_pmic_chtwc.c
<<
>>
Prefs
   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 */
  73static 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
 216static 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
 228static 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
 234static 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 */
 256static 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
 264static 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
 274static const struct platform_device_id cht_wc_opregion_id_table[] = {
 275        { .name = "cht_wcove_region" },
 276        {},
 277};
 278
 279static 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};
 286builtin_platform_driver(intel_cht_wc_pmic_opregion_driver);
 287