// SPDX-License-Identifier: GPL-2.0
/*
 * This file contains platform specific structure definitions
 * and init function used by Tiger Lake PCH.
 *
 * Copyright (c) 2022, Intel Corporation.
 * All Rights Reserved.
 *
 */

#include "core.h"

#define ACPI_S0IX_DSM_UUID		"57a6512e-3979-4e9d-9708-ff13b2508972"
#define ACPI_GET_LOW_MODE_REGISTERS	1

const struct pmc_bit_map tgl_pfear_map[] = {
	{"PSF9",		BIT(0)},
	{"RES_66",		BIT(1)},
	{"RES_67",		BIT(2)},
	{"RES_68",		BIT(3)},
	{"RES_69",		BIT(4)},
	{"RES_70",		BIT(5)},
	{"TBTLSX",		BIT(6)},
	{}
};

const struct pmc_bit_map *ext_tgl_pfear_map[] = {
	/*
	 * Check intel_pmc_core_ids[] users of tgl_reg_map for
	 * a list of core SoCs using this.
	 */
	cnp_pfear_map,
	tgl_pfear_map,
	NULL
};

const struct pmc_bit_map tgl_clocksource_status_map[] = {
	{"USB2PLL_OFF_STS",			BIT(18)},
	{"PCIe/USB3.1_Gen2PLL_OFF_STS",		BIT(19)},
	{"PCIe_Gen3PLL_OFF_STS",		BIT(20)},
	{"OPIOPLL_OFF_STS",			BIT(21)},
	{"OCPLL_OFF_STS",			BIT(22)},
	{"MainPLL_OFF_STS",			BIT(23)},
	{"MIPIPLL_OFF_STS",			BIT(24)},
	{"Fast_XTAL_Osc_OFF_STS",		BIT(25)},
	{"AC_Ring_Osc_OFF_STS",			BIT(26)},
	{"MC_Ring_Osc_OFF_STS",			BIT(27)},
	{"SATAPLL_OFF_STS",			BIT(29)},
	{"XTAL_USB2PLL_OFF_STS",		BIT(31)},
	{}
};

const struct pmc_bit_map tgl_power_gating_status_map[] = {
	{"CSME_PG_STS",				BIT(0)},
	{"SATA_PG_STS",				BIT(1)},
	{"xHCI_PG_STS",				BIT(2)},
	{"UFSX2_PG_STS",			BIT(3)},
	{"OTG_PG_STS",				BIT(5)},
	{"SPA_PG_STS",				BIT(6)},
	{"SPB_PG_STS",				BIT(7)},
	{"SPC_PG_STS",				BIT(8)},
	{"SPD_PG_STS",				BIT(9)},
	{"SPE_PG_STS",				BIT(10)},
	{"SPF_PG_STS",				BIT(11)},
	{"LSX_PG_STS",				BIT(13)},
	{"P2SB_PG_STS",				BIT(14)},
	{"PSF_PG_STS",				BIT(15)},
	{"SBR_PG_STS",				BIT(16)},
	{"OPIDMI_PG_STS",			BIT(17)},
	{"THC0_PG_STS",				BIT(18)},
	{"THC1_PG_STS",				BIT(19)},
	{"GBETSN_PG_STS",			BIT(20)},
	{"GBE_PG_STS",				BIT(21)},
	{"LPSS_PG_STS",				BIT(22)},
	{"MMP_UFSX2_PG_STS",			BIT(23)},
	{"MMP_UFSX2B_PG_STS",			BIT(24)},
	{"FIA_PG_STS",				BIT(25)},
	{}
};

const struct pmc_bit_map tgl_d3_status_map[] = {
	{"ADSP_D3_STS",				BIT(0)},
	{"SATA_D3_STS",				BIT(1)},
	{"xHCI0_D3_STS",			BIT(2)},
	{"xDCI1_D3_STS",			BIT(5)},
	{"SDX_D3_STS",				BIT(6)},
	{"EMMC_D3_STS",				BIT(7)},
	{"IS_D3_STS",				BIT(8)},
	{"THC0_D3_STS",				BIT(9)},
	{"THC1_D3_STS",				BIT(10)},
	{"GBE_D3_STS",				BIT(11)},
	{"GBE_TSN_D3_STS",			BIT(12)},
	{}
};

const struct pmc_bit_map tgl_vnn_req_status_map[] = {
	{"GPIO_COM0_VNN_REQ_STS",		BIT(1)},
	{"GPIO_COM1_VNN_REQ_STS",		BIT(2)},
	{"GPIO_COM2_VNN_REQ_STS",		BIT(3)},
	{"GPIO_COM3_VNN_REQ_STS",		BIT(4)},
	{"GPIO_COM4_VNN_REQ_STS",		BIT(5)},
	{"GPIO_COM5_VNN_REQ_STS",		BIT(6)},
	{"Audio_VNN_REQ_STS",			BIT(7)},
	{"ISH_VNN_REQ_STS",			BIT(8)},
	{"CNVI_VNN_REQ_STS",			BIT(9)},
	{"eSPI_VNN_REQ_STS",			BIT(10)},
	{"Display_VNN_REQ_STS",			BIT(11)},
	{"DTS_VNN_REQ_STS",			BIT(12)},
	{"SMBUS_VNN_REQ_STS",			BIT(14)},
	{"CSME_VNN_REQ_STS",			BIT(15)},
	{"SMLINK0_VNN_REQ_STS",			BIT(16)},
	{"SMLINK1_VNN_REQ_STS",			BIT(17)},
	{"CLINK_VNN_REQ_STS",			BIT(20)},
	{"DCI_VNN_REQ_STS",			BIT(21)},
	{"ITH_VNN_REQ_STS",			BIT(22)},
	{"CSME_VNN_REQ_STS",			BIT(24)},
	{"GBE_VNN_REQ_STS",			BIT(25)},
	{}
};

const struct pmc_bit_map tgl_vnn_misc_status_map[] = {
	{"CPU_C10_REQ_STS_0",			BIT(0)},
	{"PCIe_LPM_En_REQ_STS_3",		BIT(3)},
	{"ITH_REQ_STS_5",			BIT(5)},
	{"CNVI_REQ_STS_6",			BIT(6)},
	{"ISH_REQ_STS_7",			BIT(7)},
	{"USB2_SUS_PG_Sys_REQ_STS_10",		BIT(10)},
	{"PCIe_Clk_REQ_STS_12",			BIT(12)},
	{"MPHY_Core_DL_REQ_STS_16",		BIT(16)},
	{"Break-even_En_REQ_STS_17",		BIT(17)},
	{"Auto-demo_En_REQ_STS_18",		BIT(18)},
	{"MPHY_SUS_REQ_STS_22",			BIT(22)},
	{"xDCI_attached_REQ_STS_24",		BIT(24)},
	{}
};

const struct pmc_bit_map tgl_signal_status_map[] = {
	{"LSX_Wake0_En_STS",			BIT(0)},
	{"LSX_Wake0_Pol_STS",			BIT(1)},
	{"LSX_Wake1_En_STS",			BIT(2)},
	{"LSX_Wake1_Pol_STS",			BIT(3)},
	{"LSX_Wake2_En_STS",			BIT(4)},
	{"LSX_Wake2_Pol_STS",			BIT(5)},
	{"LSX_Wake3_En_STS",			BIT(6)},
	{"LSX_Wake3_Pol_STS",			BIT(7)},
	{"LSX_Wake4_En_STS",			BIT(8)},
	{"LSX_Wake4_Pol_STS",			BIT(9)},
	{"LSX_Wake5_En_STS",			BIT(10)},
	{"LSX_Wake5_Pol_STS",			BIT(11)},
	{"LSX_Wake6_En_STS",			BIT(12)},
	{"LSX_Wake6_Pol_STS",			BIT(13)},
	{"LSX_Wake7_En_STS",			BIT(14)},
	{"LSX_Wake7_Pol_STS",			BIT(15)},
	{"Intel_Se_IO_Wake0_En_STS",		BIT(16)},
	{"Intel_Se_IO_Wake0_Pol_STS",		BIT(17)},
	{"Intel_Se_IO_Wake1_En_STS",		BIT(18)},
	{"Intel_Se_IO_Wake1_Pol_STS",		BIT(19)},
	{"Int_Timer_SS_Wake0_En_STS",		BIT(20)},
	{"Int_Timer_SS_Wake0_Pol_STS",		BIT(21)},
	{"Int_Timer_SS_Wake1_En_STS",		BIT(22)},
	{"Int_Timer_SS_Wake1_Pol_STS",		BIT(23)},
	{"Int_Timer_SS_Wake2_En_STS",		BIT(24)},
	{"Int_Timer_SS_Wake2_Pol_STS",		BIT(25)},
	{"Int_Timer_SS_Wake3_En_STS",		BIT(26)},
	{"Int_Timer_SS_Wake3_Pol_STS",		BIT(27)},
	{"Int_Timer_SS_Wake4_En_STS",		BIT(28)},
	{"Int_Timer_SS_Wake4_Pol_STS",		BIT(29)},
	{"Int_Timer_SS_Wake5_En_STS",		BIT(30)},
	{"Int_Timer_SS_Wake5_Pol_STS",		BIT(31)},
	{}
};

const struct pmc_bit_map *tgl_lpm_maps[] = {
	tgl_clocksource_status_map,
	tgl_power_gating_status_map,
	tgl_d3_status_map,
	tgl_vnn_req_status_map,
	tgl_vnn_misc_status_map,
	tgl_signal_status_map,
	NULL
};

const struct pmc_reg_map tgl_reg_map = {
	.pfear_sts = ext_tgl_pfear_map,
	.slp_s0_offset = CNP_PMC_SLP_S0_RES_COUNTER_OFFSET,
	.slp_s0_res_counter_step = TGL_PMC_SLP_S0_RES_COUNTER_STEP,
	.ltr_show_sts = cnp_ltr_show_map,
	.msr_sts = msr_map,
	.ltr_ignore_offset = CNP_PMC_LTR_IGNORE_OFFSET,
	.regmap_length = CNP_PMC_MMIO_REG_LEN,
	.ppfear0_offset = CNP_PMC_HOST_PPFEAR0A,
	.ppfear_buckets = ICL_PPFEAR_NUM_ENTRIES,
	.pm_cfg_offset = CNP_PMC_PM_CFG_OFFSET,
	.pm_read_disable_bit = CNP_PMC_READ_DISABLE_BIT,
	.ltr_ignore_max = TGL_NUM_IP_IGN_ALLOWED,
	.lpm_num_maps = TGL_LPM_NUM_MAPS,
	.lpm_res_counter_step_x2 = TGL_PMC_LPM_RES_COUNTER_STEP_X2,
	.lpm_sts_latch_en_offset = TGL_LPM_STS_LATCH_EN_OFFSET,
	.lpm_en_offset = TGL_LPM_EN_OFFSET,
	.lpm_priority_offset = TGL_LPM_PRI_OFFSET,
	.lpm_residency_offset = TGL_LPM_RESIDENCY_OFFSET,
	.lpm_sts = tgl_lpm_maps,
	.lpm_status_offset = TGL_LPM_STATUS_OFFSET,
	.lpm_live_status_offset = TGL_LPM_LIVE_STATUS_OFFSET,
	.etr3_offset = ETR3_OFFSET,
};

void pmc_core_get_tgl_lpm_reqs(struct platform_device *pdev)
{
	struct pmc_dev *pmcdev = platform_get_drvdata(pdev);
	const int num_maps = pmcdev->map->lpm_num_maps;
	u32 lpm_size = LPM_MAX_NUM_MODES * num_maps * 4;
	union acpi_object *out_obj;
	struct acpi_device *adev;
	guid_t s0ix_dsm_guid;
	u32 *lpm_req_regs, *addr;

	adev = ACPI_COMPANION(&pdev->dev);
	if (!adev)
		return;

	guid_parse(ACPI_S0IX_DSM_UUID, &s0ix_dsm_guid);

	out_obj = acpi_evaluate_dsm(adev->handle, &s0ix_dsm_guid, 0,
				    ACPI_GET_LOW_MODE_REGISTERS, NULL);
	if (out_obj && out_obj->type == ACPI_TYPE_BUFFER) {
		u32 size = out_obj->buffer.length;

		if (size != lpm_size) {
			acpi_handle_debug(adev->handle,
				"_DSM returned unexpected buffer size, have %u, expect %u\n",
				size, lpm_size);
			goto free_acpi_obj;
		}
	} else {
		acpi_handle_debug(adev->handle,
				  "_DSM function 0 evaluation failed\n");
		goto free_acpi_obj;
	}

	addr = (u32 *)out_obj->buffer.pointer;

	lpm_req_regs = devm_kzalloc(&pdev->dev, lpm_size * sizeof(u32),
				     GFP_KERNEL);
	if (!lpm_req_regs)
		goto free_acpi_obj;

	memcpy(lpm_req_regs, addr, lpm_size);
	pmcdev->lpm_req_regs = lpm_req_regs;

free_acpi_obj:
	ACPI_FREE(out_obj);
}

void tgl_core_configure(struct pmc_dev *pmcdev)
{
	pmc_core_get_tgl_lpm_reqs(pmcdev->pdev);
	/* Due to a hardware limitation, the GBE LTR blocks PC10
	 * when a cable is attached. Tell the PMC to ignore it.
	 */
	dev_dbg(&pmcdev->pdev->dev, "ignoring GBE LTR\n");
	pmc_core_send_ltr_ignore(pmcdev, 3);
}

void tgl_core_init(struct pmc_dev *pmcdev)
{
	pmcdev->map = &tgl_reg_map;
	pmcdev->core_configure = tgl_core_configure;
}
