brintos

brintos / linux-shallow public Read only

0
0
Text · 7.7 KiB · c332afb Raw
409 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Intel BXT WhiskeyCove PMIC operation region driver4 *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 0x0F16#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        019#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 const 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 const struct pmic_table thermal_table[] = {181	{182		.address = 0x00,183		.reg = 0x4F39184	},185	{186		.address = 0x04,187		.reg = 0x4F24188	},189	{190		.address = 0x08,191		.reg = 0x4F26192	},193	{194		.address = 0x0c,195		.reg = 0x4F3B196	},197	{198		.address = 0x10,199		.reg = 0x4F28200	},201	{202		.address = 0x14,203		.reg = 0x4F2A204	},205	{206		.address = 0x18,207		.reg = 0x4F3D208	},209	{210		.address = 0x1c,211		.reg = 0x4F2C212	},213	{214		.address = 0x20,215		.reg = 0x4F2E216	},217	{218		.address = 0x24,219		.reg = 0x4F3F220	},221	{222		.address = 0x28,223		.reg = 0x4F30224	},225	{226		.address = 0x30,227		.reg = 0x4F41228	},229	{230		.address = 0x34,231		.reg = 0x4F32232	},233	{234		.address = 0x3c,235		.reg = 0x4F43236	},237	{238		.address = 0x40,239		.reg = 0x4F34240	},241	{242		.address = 0x48,243		.reg = 0x4F6A,244		.bit = 0,245	},246	{247		.address = 0x4C,248		.reg = 0x4F6A,249		.bit = 1250	},251	{252		.address = 0x50,253		.reg = 0x4F6A,254		.bit = 2255	},256	{257		.address = 0x54,258		.reg = 0x4F6A,259		.bit = 4260	},261	{262		.address = 0x58,263		.reg = 0x4F6A,264		.bit = 5265	},266	{267		.address = 0x5C,268		.reg = 0x4F6A,269		.bit = 3270	},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	else293		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 int324intel_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 int351intel_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 int364intel_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);409