brintos

brintos / linux-shallow public Read only

0
0
Text · 5.6 KiB · b4c21a7 Raw
304 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Intel Bay Trail Crystal Cove PMIC operation region driver4 *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		0xc518 19static const 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 const struct pmic_table thermal_table[] = {138	{139		.address = 0x00,140		.reg = 0x75141	},142	{143		.address = 0x04,144		.reg = 0x95145	},146	{147		.address = 0x08,148		.reg = 0x97149	},150	{151		.address = 0x0c,152		.reg = 0x77153	},154	{155		.address = 0x10,156		.reg = 0x9a157	},158	{159		.address = 0x14,160		.reg = 0x9c161	},162	{163		.address = 0x18,164		.reg = 0x79165	},166	{167		.address = 0x1c,168		.reg = 0x9f169	},170	{171		.address = 0x20,172		.reg = 0xa1173	},174	{175		.address = 0x48,176		.reg = 0x94177	},178	{179		.address = 0x4c,180		.reg = 0x99181	},182	{183		.address = 0x50,184		.reg = 0x9e185	},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 reg226	 * and 2bits in reg-1: bit0,1227	 */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	.pmic_i2c_address = 0x6e,287};288 289static int intel_crc_pmic_opregion_probe(struct platform_device *pdev)290{291	struct intel_soc_pmic *pmic = dev_get_drvdata(pdev->dev.parent);292	return intel_pmic_install_opregion_handler(&pdev->dev,293			ACPI_HANDLE(pdev->dev.parent), pmic->regmap,294			&intel_crc_pmic_opregion_data);295}296 297static struct platform_driver intel_crc_pmic_opregion_driver = {298	.probe = intel_crc_pmic_opregion_probe,299	.driver = {300		.name = "byt_crystal_cove_pmic",301	},302};303builtin_platform_driver(intel_crc_pmic_opregion_driver);304