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_bxtwc.c (7895B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Intel BXT WhiskeyCove PMIC operation region driver
      4 *
      5 * Copyright (C) 2015 Intel Corporation. All rights reserved.
      6 */
      7
      8#include <linux/init.h>
      9#include <linux/acpi.h>
     10#include <linux/mfd/intel_soc_pmic.h>
     11#include <linux/regmap.h>
     12#include <linux/platform_device.h>
     13#include "intel_pmic.h"
     14
     15#define WHISKEY_COVE_ALRT_HIGH_BIT_MASK 0x0F
     16#define WHISKEY_COVE_ADC_HIGH_BIT(x)	(((x & 0x0F) << 8))
     17#define WHISKEY_COVE_ADC_CURSRC(x)	(((x & 0xF0) >> 4))
     18#define VR_MODE_DISABLED        0
     19#define VR_MODE_AUTO            BIT(0)
     20#define VR_MODE_NORMAL          BIT(1)
     21#define VR_MODE_SWITCH          BIT(2)
     22#define VR_MODE_ECO             (BIT(0)|BIT(1))
     23#define VSWITCH2_OUTPUT         BIT(5)
     24#define VSWITCH1_OUTPUT         BIT(4)
     25#define VUSBPHY_CHARGE          BIT(1)
     26
     27static struct pmic_table power_table[] = {
     28	{
     29		.address = 0x0,
     30		.reg = 0x63,
     31		.bit = VR_MODE_AUTO,
     32	}, /* VDD1 -> VDD1CNT */
     33	{
     34		.address = 0x04,
     35		.reg = 0x65,
     36		.bit = VR_MODE_AUTO,
     37	}, /* VDD2 -> VDD2CNT */
     38	{
     39		.address = 0x08,
     40		.reg = 0x67,
     41		.bit = VR_MODE_AUTO,
     42	}, /* VDD3 -> VDD3CNT */
     43	{
     44		.address = 0x0c,
     45		.reg = 0x6d,
     46		.bit = VR_MODE_AUTO,
     47	}, /* VLFX -> VFLEXCNT */
     48	{
     49		.address = 0x10,
     50		.reg = 0x6f,
     51		.bit = VR_MODE_NORMAL,
     52	}, /* VP1A -> VPROG1ACNT */
     53	{
     54		.address = 0x14,
     55		.reg = 0x70,
     56		.bit = VR_MODE_NORMAL,
     57	}, /* VP1B -> VPROG1BCNT */
     58	{
     59		.address = 0x18,
     60		.reg = 0x71,
     61		.bit = VR_MODE_NORMAL,
     62	}, /* VP1C -> VPROG1CCNT */
     63	{
     64		.address = 0x1c,
     65		.reg = 0x72,
     66		.bit = VR_MODE_NORMAL,
     67	}, /* VP1D -> VPROG1DCNT */
     68	{
     69		.address = 0x20,
     70		.reg = 0x73,
     71		.bit = VR_MODE_NORMAL,
     72	}, /* VP2A -> VPROG2ACNT */
     73	{
     74		.address = 0x24,
     75		.reg = 0x74,
     76		.bit = VR_MODE_NORMAL,
     77	}, /* VP2B -> VPROG2BCNT */
     78	{
     79		.address = 0x28,
     80		.reg = 0x75,
     81		.bit = VR_MODE_NORMAL,
     82	}, /* VP2C -> VPROG2CCNT */
     83	{
     84		.address = 0x2c,
     85		.reg = 0x76,
     86		.bit = VR_MODE_NORMAL,
     87	}, /* VP3A -> VPROG3ACNT */
     88	{
     89		.address = 0x30,
     90		.reg = 0x77,
     91		.bit = VR_MODE_NORMAL,
     92	}, /* VP3B -> VPROG3BCNT */
     93	{
     94		.address = 0x34,
     95		.reg = 0x78,
     96		.bit = VSWITCH2_OUTPUT,
     97	}, /* VSW2 -> VLD0CNT Bit 5*/
     98	{
     99		.address = 0x38,
    100		.reg = 0x78,
    101		.bit = VSWITCH1_OUTPUT,
    102	}, /* VSW1 -> VLD0CNT Bit 4 */
    103	{
    104		.address = 0x3c,
    105		.reg = 0x78,
    106		.bit = VUSBPHY_CHARGE,
    107	}, /* VUPY -> VLDOCNT Bit 1 */
    108	{
    109		.address = 0x40,
    110		.reg = 0x7b,
    111		.bit = VR_MODE_NORMAL,
    112	}, /* VRSO -> VREFSOCCNT*/
    113	{
    114		.address = 0x44,
    115		.reg = 0xA0,
    116		.bit = VR_MODE_NORMAL,
    117	}, /* VP1E -> VPROG1ECNT */
    118	{
    119		.address = 0x48,
    120		.reg = 0xA1,
    121		.bit = VR_MODE_NORMAL,
    122	}, /* VP1F -> VPROG1FCNT */
    123	{
    124		.address = 0x4c,
    125		.reg = 0xA2,
    126		.bit = VR_MODE_NORMAL,
    127	}, /* VP2D -> VPROG2DCNT */
    128	{
    129		.address = 0x50,
    130		.reg = 0xA3,
    131		.bit = VR_MODE_NORMAL,
    132	}, /* VP4A -> VPROG4ACNT */
    133	{
    134		.address = 0x54,
    135		.reg = 0xA4,
    136		.bit = VR_MODE_NORMAL,
    137	}, /* VP4B -> VPROG4BCNT */
    138	{
    139		.address = 0x58,
    140		.reg = 0xA5,
    141		.bit = VR_MODE_NORMAL,
    142	}, /* VP4C -> VPROG4CCNT */
    143	{
    144		.address = 0x5c,
    145		.reg = 0xA6,
    146		.bit = VR_MODE_NORMAL,
    147	}, /* VP4D -> VPROG4DCNT */
    148	{
    149		.address = 0x60,
    150		.reg = 0xA7,
    151		.bit = VR_MODE_NORMAL,
    152	}, /* VP5A -> VPROG5ACNT */
    153	{
    154		.address = 0x64,
    155		.reg = 0xA8,
    156		.bit = VR_MODE_NORMAL,
    157	}, /* VP5B -> VPROG5BCNT */
    158	{
    159		.address = 0x68,
    160		.reg = 0xA9,
    161		.bit = VR_MODE_NORMAL,
    162	}, /* VP6A -> VPROG6ACNT */
    163	{
    164		.address = 0x6c,
    165		.reg = 0xAA,
    166		.bit = VR_MODE_NORMAL,
    167	}, /* VP6B -> VPROG6BCNT */
    168	{
    169		.address = 0x70,
    170		.reg = 0x36,
    171		.bit = BIT(2),
    172	}, /* SDWN_N -> MODEMCTRL Bit 2 */
    173	{
    174		.address = 0x74,
    175		.reg = 0x36,
    176		.bit = BIT(0),
    177	} /* MOFF -> MODEMCTRL Bit 0 */
    178};
    179
    180static struct pmic_table thermal_table[] = {
    181	{
    182		.address = 0x00,
    183		.reg = 0x4F39
    184	},
    185	{
    186		.address = 0x04,
    187		.reg = 0x4F24
    188	},
    189	{
    190		.address = 0x08,
    191		.reg = 0x4F26
    192	},
    193	{
    194		.address = 0x0c,
    195		.reg = 0x4F3B
    196	},
    197	{
    198		.address = 0x10,
    199		.reg = 0x4F28
    200	},
    201	{
    202		.address = 0x14,
    203		.reg = 0x4F2A
    204	},
    205	{
    206		.address = 0x18,
    207		.reg = 0x4F3D
    208	},
    209	{
    210		.address = 0x1c,
    211		.reg = 0x4F2C
    212	},
    213	{
    214		.address = 0x20,
    215		.reg = 0x4F2E
    216	},
    217	{
    218		.address = 0x24,
    219		.reg = 0x4F3F
    220	},
    221	{
    222		.address = 0x28,
    223		.reg = 0x4F30
    224	},
    225	{
    226		.address = 0x30,
    227		.reg = 0x4F41
    228	},
    229	{
    230		.address = 0x34,
    231		.reg = 0x4F32
    232	},
    233	{
    234		.address = 0x3c,
    235		.reg = 0x4F43
    236	},
    237	{
    238		.address = 0x40,
    239		.reg = 0x4F34
    240	},
    241	{
    242		.address = 0x48,
    243		.reg = 0x4F6A,
    244		.bit = 0,
    245	},
    246	{
    247		.address = 0x4C,
    248		.reg = 0x4F6A,
    249		.bit = 1
    250	},
    251	{
    252		.address = 0x50,
    253		.reg = 0x4F6A,
    254		.bit = 2
    255	},
    256	{
    257		.address = 0x54,
    258		.reg = 0x4F6A,
    259		.bit = 4
    260	},
    261	{
    262		.address = 0x58,
    263		.reg = 0x4F6A,
    264		.bit = 5
    265	},
    266	{
    267		.address = 0x5C,
    268		.reg = 0x4F6A,
    269		.bit = 3
    270	},
    271};
    272
    273static int intel_bxtwc_pmic_get_power(struct regmap *regmap, int reg,
    274		int bit, u64 *value)
    275{
    276	int data;
    277
    278	if (regmap_read(regmap, reg, &data))
    279		return -EIO;
    280
    281	*value = (data & bit) ? 1 : 0;
    282	return 0;
    283}
    284
    285static int intel_bxtwc_pmic_update_power(struct regmap *regmap, int reg,
    286		int bit, bool on)
    287{
    288	u8 val, mask = bit;
    289
    290	if (on)
    291		val = 0xFF;
    292	else
    293		val = 0x0;
    294
    295	return regmap_update_bits(regmap, reg, mask, val);
    296}
    297
    298static int intel_bxtwc_pmic_get_raw_temp(struct regmap *regmap, int reg)
    299{
    300	unsigned int val, adc_val, reg_val;
    301	u8 temp_l, temp_h, cursrc;
    302	unsigned long rlsb;
    303	static const unsigned long rlsb_array[] = {
    304		0, 260420, 130210, 65100, 32550, 16280,
    305		8140, 4070, 2030, 0, 260420, 130210 };
    306
    307	if (regmap_read(regmap, reg, &val))
    308		return -EIO;
    309	temp_l = (u8) val;
    310
    311	if (regmap_read(regmap, (reg - 1), &val))
    312		return -EIO;
    313	temp_h = (u8) val;
    314
    315	reg_val = temp_l | WHISKEY_COVE_ADC_HIGH_BIT(temp_h);
    316	cursrc = WHISKEY_COVE_ADC_CURSRC(temp_h);
    317	rlsb = rlsb_array[cursrc];
    318	adc_val = reg_val * rlsb / 1000;
    319
    320	return adc_val;
    321}
    322
    323static int
    324intel_bxtwc_pmic_update_aux(struct regmap *regmap, int reg, int raw)
    325{
    326	u32 bsr_num;
    327	u16 resi_val, count = 0, thrsh = 0;
    328	u8 alrt_h, alrt_l, cursel = 0;
    329
    330	bsr_num = raw;
    331	bsr_num /= (1 << 5);
    332
    333	count = fls(bsr_num) - 1;
    334
    335	cursel = clamp_t(s8, (count - 7), 0, 7);
    336	thrsh = raw / (1 << (4 + cursel));
    337
    338	resi_val = (cursel << 9) | thrsh;
    339	alrt_h = (resi_val >> 8) & WHISKEY_COVE_ALRT_HIGH_BIT_MASK;
    340	if (regmap_update_bits(regmap,
    341				reg - 1,
    342				WHISKEY_COVE_ALRT_HIGH_BIT_MASK,
    343				alrt_h))
    344		return -EIO;
    345
    346	alrt_l = (u8)resi_val;
    347	return regmap_write(regmap, reg, alrt_l);
    348}
    349
    350static int
    351intel_bxtwc_pmic_get_policy(struct regmap *regmap, int reg, int bit, u64 *value)
    352{
    353	u8 mask = BIT(bit);
    354	unsigned int val;
    355
    356	if (regmap_read(regmap, reg, &val))
    357		return -EIO;
    358
    359	*value = (val & mask) >> bit;
    360	return 0;
    361}
    362
    363static int
    364intel_bxtwc_pmic_update_policy(struct regmap *regmap,
    365				int reg, int bit, int enable)
    366{
    367	u8 mask = BIT(bit), val = enable << bit;
    368
    369	return regmap_update_bits(regmap, reg, mask, val);
    370}
    371
    372static const struct intel_pmic_opregion_data intel_bxtwc_pmic_opregion_data = {
    373	.get_power      = intel_bxtwc_pmic_get_power,
    374	.update_power   = intel_bxtwc_pmic_update_power,
    375	.get_raw_temp   = intel_bxtwc_pmic_get_raw_temp,
    376	.update_aux     = intel_bxtwc_pmic_update_aux,
    377	.get_policy     = intel_bxtwc_pmic_get_policy,
    378	.update_policy  = intel_bxtwc_pmic_update_policy,
    379	.lpat_raw_to_temp = acpi_lpat_raw_to_temp,
    380	.power_table      = power_table,
    381	.power_table_count = ARRAY_SIZE(power_table),
    382	.thermal_table     = thermal_table,
    383	.thermal_table_count = ARRAY_SIZE(thermal_table),
    384};
    385
    386static int intel_bxtwc_pmic_opregion_probe(struct platform_device *pdev)
    387{
    388	struct intel_soc_pmic *pmic = dev_get_drvdata(pdev->dev.parent);
    389
    390	return intel_pmic_install_opregion_handler(&pdev->dev,
    391			ACPI_HANDLE(pdev->dev.parent),
    392			pmic->regmap,
    393			&intel_bxtwc_pmic_opregion_data);
    394}
    395
    396static const struct platform_device_id bxt_wc_opregion_id_table[] = {
    397	{ .name = "bxt_wcove_region" },
    398	{},
    399};
    400
    401static struct platform_driver intel_bxtwc_pmic_opregion_driver = {
    402	.probe = intel_bxtwc_pmic_opregion_probe,
    403	.driver = {
    404		.name = "bxt_whiskey_cove_pmic",
    405	},
    406	.id_table = bxt_wc_opregion_id_table,
    407};
    408builtin_platform_driver(intel_bxtwc_pmic_opregion_driver);