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_bytcrc.c (5729B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Intel Bay Trail Crystal Cove PMIC operation region driver
      4 *
      5 * Copyright (C) 2014 Intel Corporation. All rights reserved.
      6 */
      7
      8#include <linux/acpi.h>
      9#include <linux/init.h>
     10#include <linux/mfd/intel_soc_pmic.h>
     11#include <linux/platform_device.h>
     12#include <linux/regmap.h>
     13#include "intel_pmic.h"
     14
     15#define PWR_SOURCE_SELECT	BIT(1)
     16
     17#define PMIC_A0LOCK_REG		0xc5
     18
     19static struct pmic_table power_table[] = {
     20/*	{
     21		.address = 0x00,
     22		.reg = ??,
     23		.bit = ??,
     24	}, ** VSYS */
     25	{
     26		.address = 0x04,
     27		.reg = 0x63,
     28		.bit = 0x00,
     29	}, /* SYSX -> VSYS_SX */
     30	{
     31		.address = 0x08,
     32		.reg = 0x62,
     33		.bit = 0x00,
     34	}, /* SYSU -> VSYS_U */
     35	{
     36		.address = 0x0c,
     37		.reg = 0x64,
     38		.bit = 0x00,
     39	}, /* SYSS -> VSYS_S */
     40	{
     41		.address = 0x10,
     42		.reg = 0x6a,
     43		.bit = 0x00,
     44	}, /* V50S -> V5P0S */
     45	{
     46		.address = 0x14,
     47		.reg = 0x6b,
     48		.bit = 0x00,
     49	}, /* HOST -> VHOST, USB2/3 host */
     50	{
     51		.address = 0x18,
     52		.reg = 0x6c,
     53		.bit = 0x00,
     54	}, /* VBUS -> VBUS, USB2/3 OTG */
     55	{
     56		.address = 0x1c,
     57		.reg = 0x6d,
     58		.bit = 0x00,
     59	}, /* HDMI -> VHDMI */
     60/*	{
     61		.address = 0x20,
     62		.reg = ??,
     63		.bit = ??,
     64	}, ** S285 */
     65	{
     66		.address = 0x24,
     67		.reg = 0x66,
     68		.bit = 0x00,
     69	}, /* X285 -> V2P85SX, camera */
     70/*	{
     71		.address = 0x28,
     72		.reg = ??,
     73		.bit = ??,
     74	}, ** V33A */
     75	{
     76		.address = 0x2c,
     77		.reg = 0x69,
     78		.bit = 0x00,
     79	}, /* V33S -> V3P3S, display/ssd/audio */
     80	{
     81		.address = 0x30,
     82		.reg = 0x68,
     83		.bit = 0x00,
     84	}, /* V33U -> V3P3U, SDIO wifi&bt */
     85/*	{
     86		.address = 0x34 .. 0x40,
     87		.reg = ??,
     88		.bit = ??,
     89	}, ** V33I, V18A, REFQ, V12A */
     90	{
     91		.address = 0x44,
     92		.reg = 0x5c,
     93		.bit = 0x00,
     94	}, /* V18S -> V1P8S, SOC/USB PHY/SIM */
     95	{
     96		.address = 0x48,
     97		.reg = 0x5d,
     98		.bit = 0x00,
     99	}, /* V18X -> V1P8SX, eMMC/camara/audio */
    100	{
    101		.address = 0x4c,
    102		.reg = 0x5b,
    103		.bit = 0x00,
    104	}, /* V18U -> V1P8U, LPDDR */
    105	{
    106		.address = 0x50,
    107		.reg = 0x61,
    108		.bit = 0x00,
    109	}, /* V12X -> V1P2SX, SOC SFR */
    110	{
    111		.address = 0x54,
    112		.reg = 0x60,
    113		.bit = 0x00,
    114	}, /* V12S -> V1P2S, MIPI */
    115/*	{
    116		.address = 0x58,
    117		.reg = ??,
    118		.bit = ??,
    119	}, ** V10A */
    120	{
    121		.address = 0x5c,
    122		.reg = 0x56,
    123		.bit = 0x00,
    124	}, /* V10S -> V1P0S, SOC GFX */
    125	{
    126		.address = 0x60,
    127		.reg = 0x57,
    128		.bit = 0x00,
    129	}, /* V10X -> V1P0SX, SOC display/DDR IO/PCIe */
    130	{
    131		.address = 0x64,
    132		.reg = 0x59,
    133		.bit = 0x00,
    134	}, /* V105 -> V1P05S, L2 SRAM */
    135};
    136
    137static struct pmic_table thermal_table[] = {
    138	{
    139		.address = 0x00,
    140		.reg = 0x75
    141	},
    142	{
    143		.address = 0x04,
    144		.reg = 0x95
    145	},
    146	{
    147		.address = 0x08,
    148		.reg = 0x97
    149	},
    150	{
    151		.address = 0x0c,
    152		.reg = 0x77
    153	},
    154	{
    155		.address = 0x10,
    156		.reg = 0x9a
    157	},
    158	{
    159		.address = 0x14,
    160		.reg = 0x9c
    161	},
    162	{
    163		.address = 0x18,
    164		.reg = 0x79
    165	},
    166	{
    167		.address = 0x1c,
    168		.reg = 0x9f
    169	},
    170	{
    171		.address = 0x20,
    172		.reg = 0xa1
    173	},
    174	{
    175		.address = 0x48,
    176		.reg = 0x94
    177	},
    178	{
    179		.address = 0x4c,
    180		.reg = 0x99
    181	},
    182	{
    183		.address = 0x50,
    184		.reg = 0x9e
    185	},
    186};
    187
    188static int intel_crc_pmic_get_power(struct regmap *regmap, int reg,
    189				    int bit, u64 *value)
    190{
    191	int data;
    192
    193	if (regmap_read(regmap, reg, &data))
    194		return -EIO;
    195
    196	*value = (data & PWR_SOURCE_SELECT) && (data & BIT(bit)) ? 1 : 0;
    197	return 0;
    198}
    199
    200static int intel_crc_pmic_update_power(struct regmap *regmap, int reg,
    201				       int bit, bool on)
    202{
    203	int data;
    204
    205	if (regmap_read(regmap, reg, &data))
    206		return -EIO;
    207
    208	if (on) {
    209		data |= PWR_SOURCE_SELECT | BIT(bit);
    210	} else {
    211		data &= ~BIT(bit);
    212		data |= PWR_SOURCE_SELECT;
    213	}
    214
    215	if (regmap_write(regmap, reg, data))
    216		return -EIO;
    217	return 0;
    218}
    219
    220static int intel_crc_pmic_get_raw_temp(struct regmap *regmap, int reg)
    221{
    222	int temp_l, temp_h;
    223
    224	/*
    225	 * Raw temperature value is 10bits: 8bits in reg
    226	 * and 2bits in reg-1: bit0,1
    227	 */
    228	if (regmap_read(regmap, reg, &temp_l) ||
    229	    regmap_read(regmap, reg - 1, &temp_h))
    230		return -EIO;
    231
    232	return temp_l | (temp_h & 0x3) << 8;
    233}
    234
    235static int intel_crc_pmic_update_aux(struct regmap *regmap, int reg, int raw)
    236{
    237	return regmap_write(regmap, reg, raw) ||
    238		regmap_update_bits(regmap, reg - 1, 0x3, raw >> 8) ? -EIO : 0;
    239}
    240
    241static int intel_crc_pmic_get_policy(struct regmap *regmap,
    242					int reg, int bit, u64 *value)
    243{
    244	int pen;
    245
    246	if (regmap_read(regmap, reg, &pen))
    247		return -EIO;
    248	*value = pen >> 7;
    249	return 0;
    250}
    251
    252static int intel_crc_pmic_update_policy(struct regmap *regmap,
    253					int reg, int bit, int enable)
    254{
    255	int alert0;
    256
    257	/* Update to policy enable bit requires unlocking a0lock */
    258	if (regmap_read(regmap, PMIC_A0LOCK_REG, &alert0))
    259		return -EIO;
    260
    261	if (regmap_update_bits(regmap, PMIC_A0LOCK_REG, 0x01, 0))
    262		return -EIO;
    263
    264	if (regmap_update_bits(regmap, reg, 0x80, enable << 7))
    265		return -EIO;
    266
    267	/* restore alert0 */
    268	if (regmap_write(regmap, PMIC_A0LOCK_REG, alert0))
    269		return -EIO;
    270
    271	return 0;
    272}
    273
    274static const struct intel_pmic_opregion_data intel_crc_pmic_opregion_data = {
    275	.get_power	= intel_crc_pmic_get_power,
    276	.update_power	= intel_crc_pmic_update_power,
    277	.get_raw_temp	= intel_crc_pmic_get_raw_temp,
    278	.update_aux	= intel_crc_pmic_update_aux,
    279	.get_policy	= intel_crc_pmic_get_policy,
    280	.update_policy	= intel_crc_pmic_update_policy,
    281	.lpat_raw_to_temp = acpi_lpat_raw_to_temp,
    282	.power_table	= power_table,
    283	.power_table_count= ARRAY_SIZE(power_table),
    284	.thermal_table	= thermal_table,
    285	.thermal_table_count = ARRAY_SIZE(thermal_table),
    286};
    287
    288static int intel_crc_pmic_opregion_probe(struct platform_device *pdev)
    289{
    290	struct intel_soc_pmic *pmic = dev_get_drvdata(pdev->dev.parent);
    291	return intel_pmic_install_opregion_handler(&pdev->dev,
    292			ACPI_HANDLE(pdev->dev.parent), pmic->regmap,
    293			&intel_crc_pmic_opregion_data);
    294}
    295
    296static struct platform_driver intel_crc_pmic_opregion_driver = {
    297	.probe = intel_crc_pmic_opregion_probe,
    298	.driver = {
    299		.name = "byt_crystal_cove_pmic",
    300	},
    301};
    302builtin_platform_driver(intel_crc_pmic_opregion_driver);