cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

intel_pmic_chtwc.c (6801B)


      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 const 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	.lpat_raw_to_temp	= acpi_lpat_raw_to_temp,
    261	.power_table		= power_table,
    262	.power_table_count	= ARRAY_SIZE(power_table),
    263};
    264
    265static int intel_cht_wc_pmic_opregion_probe(struct platform_device *pdev)
    266{
    267	struct intel_soc_pmic *pmic = dev_get_drvdata(pdev->dev.parent);
    268
    269	return intel_pmic_install_opregion_handler(&pdev->dev,
    270			ACPI_HANDLE(pdev->dev.parent),
    271			pmic->regmap,
    272			&intel_cht_wc_pmic_opregion_data);
    273}
    274
    275static const struct platform_device_id cht_wc_opregion_id_table[] = {
    276	{ .name = "cht_wcove_region" },
    277	{},
    278};
    279
    280static struct platform_driver intel_cht_wc_pmic_opregion_driver = {
    281	.probe = intel_cht_wc_pmic_opregion_probe,
    282	.driver = {
    283		.name = "cht_whiskey_cove_pmic",
    284	},
    285	.id_table = cht_wc_opregion_id_table,
    286};
    287builtin_platform_driver(intel_cht_wc_pmic_opregion_driver);