diff options
Diffstat (limited to 'drivers/platform/x86/intel/pmc')
| -rw-r--r-- | drivers/platform/x86/intel/pmc/Makefile | 4 | ||||
| -rw-r--r-- | drivers/platform/x86/intel/pmc/adl.c | 16 | ||||
| -rw-r--r-- | drivers/platform/x86/intel/pmc/cnp.c | 18 | ||||
| -rw-r--r-- | drivers/platform/x86/intel/pmc/core.c | 485 | ||||
| -rw-r--r-- | drivers/platform/x86/intel/pmc/core.h | 128 | ||||
| -rw-r--r-- | drivers/platform/x86/intel/pmc/core_ssram.c | 133 | ||||
| -rw-r--r-- | drivers/platform/x86/intel/pmc/icl.c | 7 | ||||
| -rw-r--r-- | drivers/platform/x86/intel/pmc/mtl.c | 977 | ||||
| -rw-r--r-- | drivers/platform/x86/intel/pmc/spt.c | 7 | ||||
| -rw-r--r-- | drivers/platform/x86/intel/pmc/tgl.c | 21 | 
10 files changed, 1549 insertions, 247 deletions
diff --git a/drivers/platform/x86/intel/pmc/Makefile b/drivers/platform/x86/intel/pmc/Makefile index f96bc2e19503..3a4cf1cbc1ca 100644 --- a/drivers/platform/x86/intel/pmc/Makefile +++ b/drivers/platform/x86/intel/pmc/Makefile @@ -3,8 +3,8 @@  # Intel x86 Platform-Specific Drivers  # -intel_pmc_core-y			:= core.o spt.o cnp.o icl.o tgl.o \ -					   adl.o mtl.o +intel_pmc_core-y			:= core.o core_ssram.o spt.o cnp.o \ +					   icl.o tgl.o adl.o mtl.o  obj-$(CONFIG_INTEL_PMC_CORE)		+= intel_pmc_core.o  intel_pmc_core_pltdrv-y			:= pltdrv.o  obj-$(CONFIG_INTEL_PMC_CORE)		+= intel_pmc_core_pltdrv.o diff --git a/drivers/platform/x86/intel/pmc/adl.c b/drivers/platform/x86/intel/pmc/adl.c index 5cbd40979f2a..5006008e01be 100644 --- a/drivers/platform/x86/intel/pmc/adl.c +++ b/drivers/platform/x86/intel/pmc/adl.c @@ -309,17 +309,21 @@ const struct pmc_reg_map adl_reg_map = {  	.lpm_live_status_offset = ADL_LPM_LIVE_STATUS_OFFSET,  }; -void adl_core_configure(struct pmc_dev *pmcdev) +int adl_core_init(struct pmc_dev *pmcdev)  { +	struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN]; +	int ret; + +	pmc->map = &adl_reg_map; +	ret = get_primary_reg_base(pmc); +	if (ret) +		return ret; +  	/* 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 adl_core_init(struct pmc_dev *pmcdev) -{ -	pmcdev->map = &adl_reg_map; -	pmcdev->core_configure = adl_core_configure; +	return 0;  } diff --git a/drivers/platform/x86/intel/pmc/cnp.c b/drivers/platform/x86/intel/pmc/cnp.c index 7fb38815c4eb..420aaa1d7c76 100644 --- a/drivers/platform/x86/intel/pmc/cnp.c +++ b/drivers/platform/x86/intel/pmc/cnp.c @@ -204,7 +204,21 @@ const struct pmc_reg_map cnp_reg_map = {  	.etr3_offset = ETR3_OFFSET,  }; -void cnp_core_init(struct pmc_dev *pmcdev) +int cnp_core_init(struct pmc_dev *pmcdev)  { -	pmcdev->map = &cnp_reg_map; +	struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN]; +	int ret; + +	pmc->map = &cnp_reg_map; +	ret = get_primary_reg_base(pmc); +	if (ret) +		return ret; + +	/* 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); + +	return 0;  } diff --git a/drivers/platform/x86/intel/pmc/core.c b/drivers/platform/x86/intel/pmc/core.c index da6e7206d38b..5a36b3f77bc5 100644 --- a/drivers/platform/x86/intel/pmc/core.c +++ b/drivers/platform/x86/intel/pmc/core.c @@ -53,18 +53,18 @@ const struct pmc_bit_map msr_map[] = {  	{}  }; -static inline u32 pmc_core_reg_read(struct pmc_dev *pmcdev, int reg_offset) +static inline u32 pmc_core_reg_read(struct pmc *pmc, int reg_offset)  { -	return readl(pmcdev->regbase + reg_offset); +	return readl(pmc->regbase + reg_offset);  } -static inline void pmc_core_reg_write(struct pmc_dev *pmcdev, int reg_offset, +static inline void pmc_core_reg_write(struct pmc *pmc, int reg_offset,  				      u32 val)  { -	writel(val, pmcdev->regbase + reg_offset); +	writel(val, pmc->regbase + reg_offset);  } -static inline u64 pmc_core_adjust_slp_s0_step(struct pmc_dev *pmcdev, u32 value) +static inline u64 pmc_core_adjust_slp_s0_step(struct pmc *pmc, u32 value)  {  	/*  	 * ADL PCH does not have the SLP_S0 counter and LPM Residency counters are @@ -72,17 +72,18 @@ static inline u64 pmc_core_adjust_slp_s0_step(struct pmc_dev *pmcdev, u32 value)  	 * programs have the legacy SLP_S0 residency counter that is using the 122  	 * usec tick.  	 */ -	const int lpm_adj_x2 = pmcdev->map->lpm_res_counter_step_x2; +	const int lpm_adj_x2 = pmc->map->lpm_res_counter_step_x2; -	if (pmcdev->map == &adl_reg_map) +	if (pmc->map == &adl_reg_map)  		return (u64)value * GET_X2_COUNTER((u64)lpm_adj_x2);  	else -		return (u64)value * pmcdev->map->slp_s0_res_counter_step; +		return (u64)value * pmc->map->slp_s0_res_counter_step;  }  static int set_etr3(struct pmc_dev *pmcdev)  { -	const struct pmc_reg_map *map = pmcdev->map; +	struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN]; +	const struct pmc_reg_map *map = pmc->map;  	u32 reg;  	int err; @@ -92,7 +93,7 @@ static int set_etr3(struct pmc_dev *pmcdev)  	mutex_lock(&pmcdev->lock);  	/* check if CF9 is locked */ -	reg = pmc_core_reg_read(pmcdev, map->etr3_offset); +	reg = pmc_core_reg_read(pmc, map->etr3_offset);  	if (reg & ETR3_CF9LOCK) {  		err = -EACCES;  		goto out_unlock; @@ -100,9 +101,9 @@ static int set_etr3(struct pmc_dev *pmcdev)  	/* write CF9 global reset bit */  	reg |= ETR3_CF9GR; -	pmc_core_reg_write(pmcdev, map->etr3_offset, reg); +	pmc_core_reg_write(pmc, map->etr3_offset, reg); -	reg = pmc_core_reg_read(pmcdev, map->etr3_offset); +	reg = pmc_core_reg_read(pmc, map->etr3_offset);  	if (!(reg & ETR3_CF9GR)) {  		err = -EIO;  		goto out_unlock; @@ -120,11 +121,12 @@ static umode_t etr3_is_visible(struct kobject *kobj,  {  	struct device *dev = kobj_to_dev(kobj);  	struct pmc_dev *pmcdev = dev_get_drvdata(dev); -	const struct pmc_reg_map *map = pmcdev->map; +	struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN]; +	const struct pmc_reg_map *map = pmc->map;  	u32 reg;  	mutex_lock(&pmcdev->lock); -	reg = pmc_core_reg_read(pmcdev, map->etr3_offset); +	reg = pmc_core_reg_read(pmc, map->etr3_offset);  	mutex_unlock(&pmcdev->lock);  	return reg & ETR3_CF9LOCK ? attr->mode & (SYSFS_PREALLOC | 0444) : attr->mode; @@ -134,7 +136,8 @@ static ssize_t etr3_show(struct device *dev,  				 struct device_attribute *attr, char *buf)  {  	struct pmc_dev *pmcdev = dev_get_drvdata(dev); -	const struct pmc_reg_map *map = pmcdev->map; +	struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN]; +	const struct pmc_reg_map *map = pmc->map;  	u32 reg;  	if (!map->etr3_offset) @@ -142,7 +145,7 @@ static ssize_t etr3_show(struct device *dev,  	mutex_lock(&pmcdev->lock); -	reg = pmc_core_reg_read(pmcdev, map->etr3_offset); +	reg = pmc_core_reg_read(pmc, map->etr3_offset);  	reg &= ETR3_CF9GR | ETR3_CF9LOCK;  	mutex_unlock(&pmcdev->lock); @@ -191,37 +194,37 @@ static const struct attribute_group *pmc_dev_groups[] = {  static int pmc_core_dev_state_get(void *data, u64 *val)  { -	struct pmc_dev *pmcdev = data; -	const struct pmc_reg_map *map = pmcdev->map; +	struct pmc *pmc = data; +	const struct pmc_reg_map *map = pmc->map;  	u32 value; -	value = pmc_core_reg_read(pmcdev, map->slp_s0_offset); -	*val = pmc_core_adjust_slp_s0_step(pmcdev, value); +	value = pmc_core_reg_read(pmc, map->slp_s0_offset); +	*val = pmc_core_adjust_slp_s0_step(pmc, value);  	return 0;  }  DEFINE_DEBUGFS_ATTRIBUTE(pmc_core_dev_state, pmc_core_dev_state_get, NULL, "%llu\n"); -static int pmc_core_check_read_lock_bit(struct pmc_dev *pmcdev) +static int pmc_core_check_read_lock_bit(struct pmc *pmc)  {  	u32 value; -	value = pmc_core_reg_read(pmcdev, pmcdev->map->pm_cfg_offset); -	return value & BIT(pmcdev->map->pm_read_disable_bit); +	value = pmc_core_reg_read(pmc, pmc->map->pm_cfg_offset); +	return value & BIT(pmc->map->pm_read_disable_bit);  } -static void pmc_core_slps0_display(struct pmc_dev *pmcdev, struct device *dev, +static void pmc_core_slps0_display(struct pmc *pmc, struct device *dev,  				   struct seq_file *s)  { -	const struct pmc_bit_map **maps = pmcdev->map->slps0_dbg_maps; +	const struct pmc_bit_map **maps = pmc->map->slps0_dbg_maps;  	const struct pmc_bit_map *map; -	int offset = pmcdev->map->slps0_dbg_offset; +	int offset = pmc->map->slps0_dbg_offset;  	u32 data;  	while (*maps) {  		map = *maps; -		data = pmc_core_reg_read(pmcdev, offset); +		data = pmc_core_reg_read(pmc, offset);  		offset += 4;  		while (map->name) {  			if (dev) @@ -248,8 +251,8 @@ static int pmc_core_lpm_get_arr_size(const struct pmc_bit_map **maps)  	return idx;  } -static void pmc_core_lpm_display(struct pmc_dev *pmcdev, struct device *dev, -				 struct seq_file *s, u32 offset, +static void pmc_core_lpm_display(struct pmc *pmc, struct device *dev, +				 struct seq_file *s, u32 offset, int pmc_index,  				 const char *str,  				 const struct pmc_bit_map **maps)  { @@ -262,25 +265,25 @@ static void pmc_core_lpm_display(struct pmc_dev *pmcdev, struct device *dev,  		return;  	for (index = 0; index < arr_size; index++) { -		lpm_regs[index] = pmc_core_reg_read(pmcdev, offset); +		lpm_regs[index] = pmc_core_reg_read(pmc, offset);  		offset += 4;  	}  	for (idx = 0; idx < arr_size; idx++) {  		if (dev) -			dev_info(dev, "\nLPM_%s_%d:\t0x%x\n", str, idx, +			dev_info(dev, "\nPMC%d:LPM_%s_%d:\t0x%x\n", pmc_index, str, idx,  				lpm_regs[idx]);  		if (s) -			seq_printf(s, "\nLPM_%s_%d:\t0x%x\n", str, idx, +			seq_printf(s, "\nPMC%d:LPM_%s_%d:\t0x%x\n", pmc_index, str, idx,  				   lpm_regs[idx]);  		for (index = 0; maps[idx][index].name && index < len; index++) {  			bit_mask = maps[idx][index].bit_mask;  			if (dev) -				dev_info(dev, "%-30s %-30d\n", +				dev_info(dev, "PMC%d:%-30s %-30d\n", pmc_index,  					maps[idx][index].name,  					lpm_regs[idx] & bit_mask ? 1 : 0);  			if (s) -				seq_printf(s, "%-30s %-30d\n", +				seq_printf(s, "PMC%d:%-30s %-30d\n", pmc_index,  					   maps[idx][index].name,  					   lpm_regs[idx] & bit_mask ? 1 : 0);  		} @@ -291,37 +294,46 @@ static void pmc_core_lpm_display(struct pmc_dev *pmcdev, struct device *dev,  static bool slps0_dbg_latch; -static inline u8 pmc_core_reg_read_byte(struct pmc_dev *pmcdev, int offset) +static inline u8 pmc_core_reg_read_byte(struct pmc *pmc, int offset)  { -	return readb(pmcdev->regbase + offset); +	return readb(pmc->regbase + offset);  }  static void pmc_core_display_map(struct seq_file *s, int index, int idx, int ip, -				 u8 pf_reg, const struct pmc_bit_map **pf_map) +				 int pmc_index, u8 pf_reg, const struct pmc_bit_map **pf_map)  { -	seq_printf(s, "PCH IP: %-2d - %-32s\tState: %s\n", -		   ip, pf_map[idx][index].name, +	seq_printf(s, "PMC%d:PCH IP: %-2d - %-32s\tState: %s\n", +		   pmc_index, ip, pf_map[idx][index].name,  		   pf_map[idx][index].bit_mask & pf_reg ? "Off" : "On");  }  static int pmc_core_ppfear_show(struct seq_file *s, void *unused)  {  	struct pmc_dev *pmcdev = s->private; -	const struct pmc_bit_map **maps = pmcdev->map->pfear_sts; -	u8 pf_regs[PPFEAR_MAX_NUM_ENTRIES]; -	int index, iter, idx, ip = 0; +	int i; -	iter = pmcdev->map->ppfear0_offset; +	for (i = 0; i < ARRAY_SIZE(pmcdev->pmcs); ++i) { +		struct pmc *pmc = pmcdev->pmcs[i]; +		const struct pmc_bit_map **maps; +		u8 pf_regs[PPFEAR_MAX_NUM_ENTRIES]; +		int index, iter, idx, ip = 0; -	for (index = 0; index < pmcdev->map->ppfear_buckets && -	     index < PPFEAR_MAX_NUM_ENTRIES; index++, iter++) -		pf_regs[index] = pmc_core_reg_read_byte(pmcdev, iter); +		if (!pmc) +			continue; + +		maps = pmc->map->pfear_sts; +		iter = pmc->map->ppfear0_offset; + +		for (index = 0; index < pmc->map->ppfear_buckets && +		     index < PPFEAR_MAX_NUM_ENTRIES; index++, iter++) +			pf_regs[index] = pmc_core_reg_read_byte(pmc, iter); -	for (idx = 0; maps[idx]; idx++) { -		for (index = 0; maps[idx][index].name && -		     index < pmcdev->map->ppfear_buckets * 8; ip++, index++) -			pmc_core_display_map(s, index, idx, ip, -					     pf_regs[index / 8], maps); +		for (idx = 0; maps[idx]; idx++) { +			for (index = 0; maps[idx][index].name && +			     index < pmc->map->ppfear_buckets * 8; ip++, index++) +				pmc_core_display_map(s, index, idx, ip, i, +						     pf_regs[index / 8], maps); +		}  	}  	return 0; @@ -329,37 +341,38 @@ static int pmc_core_ppfear_show(struct seq_file *s, void *unused)  DEFINE_SHOW_ATTRIBUTE(pmc_core_ppfear);  /* This function should return link status, 0 means ready */ -static int pmc_core_mtpmc_link_status(struct pmc_dev *pmcdev) +static int pmc_core_mtpmc_link_status(struct pmc *pmc)  {  	u32 value; -	value = pmc_core_reg_read(pmcdev, SPT_PMC_PM_STS_OFFSET); +	value = pmc_core_reg_read(pmc, SPT_PMC_PM_STS_OFFSET);  	return value & BIT(SPT_PMC_MSG_FULL_STS_BIT);  } -static int pmc_core_send_msg(struct pmc_dev *pmcdev, u32 *addr_xram) +static int pmc_core_send_msg(struct pmc *pmc, u32 *addr_xram)  {  	u32 dest;  	int timeout;  	for (timeout = NUM_RETRIES; timeout > 0; timeout--) { -		if (pmc_core_mtpmc_link_status(pmcdev) == 0) +		if (pmc_core_mtpmc_link_status(pmc) == 0)  			break;  		msleep(5);  	} -	if (timeout <= 0 && pmc_core_mtpmc_link_status(pmcdev)) +	if (timeout <= 0 && pmc_core_mtpmc_link_status(pmc))  		return -EBUSY;  	dest = (*addr_xram & MTPMC_MASK) | (1U << 1); -	pmc_core_reg_write(pmcdev, SPT_PMC_MTPMC_OFFSET, dest); +	pmc_core_reg_write(pmc, SPT_PMC_MTPMC_OFFSET, dest);  	return 0;  }  static int pmc_core_mphy_pg_show(struct seq_file *s, void *unused)  {  	struct pmc_dev *pmcdev = s->private; -	const struct pmc_bit_map *map = pmcdev->map->mphy_sts; +	struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN]; +	const struct pmc_bit_map *map = pmc->map->mphy_sts;  	u32 mphy_core_reg_low, mphy_core_reg_high;  	u32 val_low, val_high;  	int index, err = 0; @@ -374,21 +387,21 @@ static int pmc_core_mphy_pg_show(struct seq_file *s, void *unused)  	mutex_lock(&pmcdev->lock); -	if (pmc_core_send_msg(pmcdev, &mphy_core_reg_low) != 0) { +	if (pmc_core_send_msg(pmc, &mphy_core_reg_low) != 0) {  		err = -EBUSY;  		goto out_unlock;  	}  	msleep(10); -	val_low = pmc_core_reg_read(pmcdev, SPT_PMC_MFPMC_OFFSET); +	val_low = pmc_core_reg_read(pmc, SPT_PMC_MFPMC_OFFSET); -	if (pmc_core_send_msg(pmcdev, &mphy_core_reg_high) != 0) { +	if (pmc_core_send_msg(pmc, &mphy_core_reg_high) != 0) {  		err = -EBUSY;  		goto out_unlock;  	}  	msleep(10); -	val_high = pmc_core_reg_read(pmcdev, SPT_PMC_MFPMC_OFFSET); +	val_high = pmc_core_reg_read(pmc, SPT_PMC_MFPMC_OFFSET);  	for (index = 0; index < 8 && map[index].name; index++) {  		seq_printf(s, "%-32s\tState: %s\n", @@ -413,7 +426,8 @@ DEFINE_SHOW_ATTRIBUTE(pmc_core_mphy_pg);  static int pmc_core_pll_show(struct seq_file *s, void *unused)  {  	struct pmc_dev *pmcdev = s->private; -	const struct pmc_bit_map *map = pmcdev->map->pll_sts; +	struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN]; +	const struct pmc_bit_map *map = pmc->map->pll_sts;  	u32 mphy_common_reg, val;  	int index, err = 0; @@ -425,14 +439,14 @@ static int pmc_core_pll_show(struct seq_file *s, void *unused)  	mphy_common_reg  = (SPT_PMC_MPHY_COM_STS_0 << 16);  	mutex_lock(&pmcdev->lock); -	if (pmc_core_send_msg(pmcdev, &mphy_common_reg) != 0) { +	if (pmc_core_send_msg(pmc, &mphy_common_reg) != 0) {  		err = -EBUSY;  		goto out_unlock;  	}  	/* Observed PMC HW response latency for MTPMC-MFPMC is ~10 ms */  	msleep(10); -	val = pmc_core_reg_read(pmcdev, SPT_PMC_MFPMC_OFFSET); +	val = pmc_core_reg_read(pmc, SPT_PMC_MFPMC_OFFSET);  	for (index = 0; map[index].name ; index++) {  		seq_printf(s, "%-32s\tState: %s\n", @@ -448,25 +462,48 @@ DEFINE_SHOW_ATTRIBUTE(pmc_core_pll);  int pmc_core_send_ltr_ignore(struct pmc_dev *pmcdev, u32 value)  { -	const struct pmc_reg_map *map = pmcdev->map; +	struct pmc *pmc; +	const struct pmc_reg_map *map;  	u32 reg; -	int err = 0; +	int pmc_index, ltr_index; -	mutex_lock(&pmcdev->lock); +	ltr_index = value; +	/* For platforms with multiple pmcs, ltr index value given by user +	 * is based on the contiguous indexes from ltr_show output. +	 * pmc index and ltr index needs to be calculated from it. +	 */ +	for (pmc_index = 0; pmc_index < ARRAY_SIZE(pmcdev->pmcs) && ltr_index > 0; pmc_index++) { +		pmc = pmcdev->pmcs[pmc_index]; -	if (value > map->ltr_ignore_max) { -		err = -EINVAL; -		goto out_unlock; +		if (!pmc) +			continue; + +		map = pmc->map; +		if (ltr_index <= map->ltr_ignore_max) +			break; + +		/* Along with IP names, ltr_show map includes CURRENT_PLATFORM +		 * and AGGREGATED_SYSTEM values per PMC. Take these two index +		 * values into account in ltr_index calculation. Also, to start +		 * ltr index from zero for next pmc, subtract it by 1. +		 */ +		ltr_index = ltr_index - (map->ltr_ignore_max + 2) - 1;  	} -	reg = pmc_core_reg_read(pmcdev, map->ltr_ignore_offset); -	reg |= BIT(value); -	pmc_core_reg_write(pmcdev, map->ltr_ignore_offset, reg); +	if (pmc_index >= ARRAY_SIZE(pmcdev->pmcs) || ltr_index < 0) +		return -EINVAL; + +	pr_debug("ltr_ignore for pmc%d: ltr_index:%d\n", pmc_index, ltr_index); + +	mutex_lock(&pmcdev->lock); + +	reg = pmc_core_reg_read(pmc, map->ltr_ignore_offset); +	reg |= BIT(ltr_index); +	pmc_core_reg_write(pmc, map->ltr_ignore_offset, reg); -out_unlock:  	mutex_unlock(&pmcdev->lock); -	return err; +	return 0;  }  static ssize_t pmc_core_ltr_ignore_write(struct file *file, @@ -509,7 +546,8 @@ static const struct file_operations pmc_core_ltr_ignore_ops = {  static void pmc_core_slps0_dbg_latch(struct pmc_dev *pmcdev, bool reset)  { -	const struct pmc_reg_map *map = pmcdev->map; +	struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN]; +	const struct pmc_reg_map *map = pmc->map;  	u32 fd;  	mutex_lock(&pmcdev->lock); @@ -517,12 +555,12 @@ static void pmc_core_slps0_dbg_latch(struct pmc_dev *pmcdev, bool reset)  	if (!reset && !slps0_dbg_latch)  		goto out_unlock; -	fd = pmc_core_reg_read(pmcdev, map->slps0_dbg_offset); +	fd = pmc_core_reg_read(pmc, map->slps0_dbg_offset);  	if (reset)  		fd &= ~CNP_PMC_LATCH_SLPS0_EVENTS;  	else  		fd |= CNP_PMC_LATCH_SLPS0_EVENTS; -	pmc_core_reg_write(pmcdev, map->slps0_dbg_offset, fd); +	pmc_core_reg_write(pmc, map->slps0_dbg_offset, fd);  	slps0_dbg_latch = false; @@ -535,7 +573,7 @@ static int pmc_core_slps0_dbg_show(struct seq_file *s, void *unused)  	struct pmc_dev *pmcdev = s->private;  	pmc_core_slps0_dbg_latch(pmcdev, false); -	pmc_core_slps0_display(pmcdev, NULL, s); +	pmc_core_slps0_display(pmcdev->pmcs[PMC_IDX_MAIN], NULL, s);  	pmc_core_slps0_dbg_latch(pmcdev, true);  	return 0; @@ -579,44 +617,52 @@ static u32 convert_ltr_scale(u32 val)  static int pmc_core_ltr_show(struct seq_file *s, void *unused)  {  	struct pmc_dev *pmcdev = s->private; -	const struct pmc_bit_map *map = pmcdev->map->ltr_show_sts;  	u64 decoded_snoop_ltr, decoded_non_snoop_ltr;  	u32 ltr_raw_data, scale, val;  	u16 snoop_ltr, nonsnoop_ltr; -	int index; +	int i, index, ltr_index = 0; -	for (index = 0; map[index].name ; index++) { -		decoded_snoop_ltr = decoded_non_snoop_ltr = 0; -		ltr_raw_data = pmc_core_reg_read(pmcdev, -						 map[index].bit_mask); -		snoop_ltr = ltr_raw_data & ~MTPMC_MASK; -		nonsnoop_ltr = (ltr_raw_data >> 0x10) & ~MTPMC_MASK; - -		if (FIELD_GET(LTR_REQ_NONSNOOP, ltr_raw_data)) { -			scale = FIELD_GET(LTR_DECODED_SCALE, nonsnoop_ltr); -			val = FIELD_GET(LTR_DECODED_VAL, nonsnoop_ltr); -			decoded_non_snoop_ltr = val * convert_ltr_scale(scale); -		} +	for (i = 0; i < ARRAY_SIZE(pmcdev->pmcs); ++i) { +		struct pmc *pmc = pmcdev->pmcs[i]; +		const struct pmc_bit_map *map; -		if (FIELD_GET(LTR_REQ_SNOOP, ltr_raw_data)) { -			scale = FIELD_GET(LTR_DECODED_SCALE, snoop_ltr); -			val = FIELD_GET(LTR_DECODED_VAL, snoop_ltr); -			decoded_snoop_ltr = val * convert_ltr_scale(scale); -		} +		if (!pmc) +			continue; + +		map = pmc->map->ltr_show_sts; +		for (index = 0; map[index].name; index++) { +			decoded_snoop_ltr = decoded_non_snoop_ltr = 0; +			ltr_raw_data = pmc_core_reg_read(pmc, +							 map[index].bit_mask); +			snoop_ltr = ltr_raw_data & ~MTPMC_MASK; +			nonsnoop_ltr = (ltr_raw_data >> 0x10) & ~MTPMC_MASK; + +			if (FIELD_GET(LTR_REQ_NONSNOOP, ltr_raw_data)) { +				scale = FIELD_GET(LTR_DECODED_SCALE, nonsnoop_ltr); +				val = FIELD_GET(LTR_DECODED_VAL, nonsnoop_ltr); +				decoded_non_snoop_ltr = val * convert_ltr_scale(scale); +			} +			if (FIELD_GET(LTR_REQ_SNOOP, ltr_raw_data)) { +				scale = FIELD_GET(LTR_DECODED_SCALE, snoop_ltr); +				val = FIELD_GET(LTR_DECODED_VAL, snoop_ltr); +				decoded_snoop_ltr = val * convert_ltr_scale(scale); +			} -		seq_printf(s, "%-32s\tLTR: RAW: 0x%-16x\tNon-Snoop(ns): %-16llu\tSnoop(ns): %-16llu\n", -			   map[index].name, ltr_raw_data, -			   decoded_non_snoop_ltr, -			   decoded_snoop_ltr); +			seq_printf(s, "%d\tPMC%d:%-32s\tLTR: RAW: 0x%-16x\tNon-Snoop(ns): %-16llu\tSnoop(ns): %-16llu\n", +				   ltr_index, i, map[index].name, ltr_raw_data, +				   decoded_non_snoop_ltr, +				   decoded_snoop_ltr); +			ltr_index++; +		}  	}  	return 0;  }  DEFINE_SHOW_ATTRIBUTE(pmc_core_ltr); -static inline u64 adjust_lpm_residency(struct pmc_dev *pmcdev, u32 offset, +static inline u64 adjust_lpm_residency(struct pmc *pmc, u32 offset,  				       const int lpm_adj_x2)  { -	u64 lpm_res = pmc_core_reg_read(pmcdev, offset); +	u64 lpm_res = pmc_core_reg_read(pmc, offset);  	return GET_X2_COUNTER((u64)lpm_adj_x2 * lpm_res);  } @@ -624,15 +670,16 @@ static inline u64 adjust_lpm_residency(struct pmc_dev *pmcdev, u32 offset,  static int pmc_core_substate_res_show(struct seq_file *s, void *unused)  {  	struct pmc_dev *pmcdev = s->private; -	const int lpm_adj_x2 = pmcdev->map->lpm_res_counter_step_x2; -	u32 offset = pmcdev->map->lpm_residency_offset; +	struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN]; +	const int lpm_adj_x2 = pmc->map->lpm_res_counter_step_x2; +	u32 offset = pmc->map->lpm_residency_offset;  	int i, mode;  	seq_printf(s, "%-10s %-15s\n", "Substate", "Residency");  	pmc_for_each_mode(i, mode, pmcdev) {  		seq_printf(s, "%-10s %-15llu\n", pmc_lpm_modes[mode], -			   adjust_lpm_residency(pmcdev, offset + (4 * mode), lpm_adj_x2)); +			   adjust_lpm_residency(pmc, offset + (4 * mode), lpm_adj_x2));  	}  	return 0; @@ -642,10 +689,19 @@ DEFINE_SHOW_ATTRIBUTE(pmc_core_substate_res);  static int pmc_core_substate_sts_regs_show(struct seq_file *s, void *unused)  {  	struct pmc_dev *pmcdev = s->private; -	const struct pmc_bit_map **maps = pmcdev->map->lpm_sts; -	u32 offset = pmcdev->map->lpm_status_offset; +	int i; -	pmc_core_lpm_display(pmcdev, NULL, s, offset, "STATUS", maps); +	for (i = 0; i < ARRAY_SIZE(pmcdev->pmcs); ++i) { +		struct pmc *pmc = pmcdev->pmcs[i]; +		const struct pmc_bit_map **maps; +		u32 offset; + +		if (!pmc) +			continue; +		maps = pmc->map->lpm_sts; +		offset = pmc->map->lpm_status_offset; +		pmc_core_lpm_display(pmc, NULL, s, offset, i, "STATUS", maps); +	}  	return 0;  } @@ -654,10 +710,19 @@ DEFINE_SHOW_ATTRIBUTE(pmc_core_substate_sts_regs);  static int pmc_core_substate_l_sts_regs_show(struct seq_file *s, void *unused)  {  	struct pmc_dev *pmcdev = s->private; -	const struct pmc_bit_map **maps = pmcdev->map->lpm_sts; -	u32 offset = pmcdev->map->lpm_live_status_offset; +	int i; -	pmc_core_lpm_display(pmcdev, NULL, s, offset, "LIVE_STATUS", maps); +	for (i = 0; i < ARRAY_SIZE(pmcdev->pmcs); ++i) { +		struct pmc *pmc = pmcdev->pmcs[i]; +		const struct pmc_bit_map **maps; +		u32 offset; + +		if (!pmc) +			continue; +		maps = pmc->map->lpm_sts; +		offset = pmc->map->lpm_live_status_offset; +		pmc_core_lpm_display(pmc, NULL, s, offset, i, "LIVE_STATUS", maps); +	}  	return 0;  } @@ -678,11 +743,12 @@ static void pmc_core_substate_req_header_show(struct seq_file *s)  static int pmc_core_substate_req_regs_show(struct seq_file *s, void *unused)  {  	struct pmc_dev *pmcdev = s->private; -	const struct pmc_bit_map **maps = pmcdev->map->lpm_sts; +	struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN]; +	const struct pmc_bit_map **maps = pmc->map->lpm_sts;  	const struct pmc_bit_map *map; -	const int num_maps = pmcdev->map->lpm_num_maps; -	u32 sts_offset = pmcdev->map->lpm_status_offset; -	u32 *lpm_req_regs = pmcdev->lpm_req_regs; +	const int num_maps = pmc->map->lpm_num_maps; +	u32 sts_offset = pmc->map->lpm_status_offset; +	u32 *lpm_req_regs = pmc->lpm_req_regs;  	int mp;  	/* Display the header */ @@ -703,7 +769,7 @@ static int pmc_core_substate_req_regs_show(struct seq_file *s, void *unused)  			req_mask |= lpm_req_regs[mp + (mode * num_maps)];  		/* Get the last latched status for this map */ -		lpm_status = pmc_core_reg_read(pmcdev, sts_offset + (mp * 4)); +		lpm_status = pmc_core_reg_read(pmc, sts_offset + (mp * 4));  		/*  Loop over elements in this map */  		map = maps[mp]; @@ -746,11 +812,12 @@ DEFINE_SHOW_ATTRIBUTE(pmc_core_substate_req_regs);  static int pmc_core_lpm_latch_mode_show(struct seq_file *s, void *unused)  {  	struct pmc_dev *pmcdev = s->private; +	struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN];  	bool c10;  	u32 reg;  	int idx, mode; -	reg = pmc_core_reg_read(pmcdev, pmcdev->map->lpm_sts_latch_en_offset); +	reg = pmc_core_reg_read(pmc, pmc->map->lpm_sts_latch_en_offset);  	if (reg & LPM_STS_LATCH_MODE) {  		seq_puts(s, "c10");  		c10 = false; @@ -777,6 +844,7 @@ static ssize_t pmc_core_lpm_latch_mode_write(struct file *file,  {  	struct seq_file *s = file->private_data;  	struct pmc_dev *pmcdev = s->private; +	struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN];  	bool clear = false, c10 = false;  	unsigned char buf[8];  	int idx, m, mode; @@ -813,9 +881,9 @@ static ssize_t pmc_core_lpm_latch_mode_write(struct file *file,  	if (clear) {  		mutex_lock(&pmcdev->lock); -		reg = pmc_core_reg_read(pmcdev, pmcdev->map->etr3_offset); +		reg = pmc_core_reg_read(pmc, pmc->map->etr3_offset);  		reg |= ETR3_CLEAR_LPM_EVENTS; -		pmc_core_reg_write(pmcdev, pmcdev->map->etr3_offset, reg); +		pmc_core_reg_write(pmc, pmc->map->etr3_offset, reg);  		mutex_unlock(&pmcdev->lock); @@ -825,9 +893,9 @@ static ssize_t pmc_core_lpm_latch_mode_write(struct file *file,  	if (c10) {  		mutex_lock(&pmcdev->lock); -		reg = pmc_core_reg_read(pmcdev, pmcdev->map->lpm_sts_latch_en_offset); +		reg = pmc_core_reg_read(pmc, pmc->map->lpm_sts_latch_en_offset);  		reg &= ~LPM_STS_LATCH_MODE; -		pmc_core_reg_write(pmcdev, pmcdev->map->lpm_sts_latch_en_offset, reg); +		pmc_core_reg_write(pmc, pmc->map->lpm_sts_latch_en_offset, reg);  		mutex_unlock(&pmcdev->lock); @@ -840,7 +908,7 @@ static ssize_t pmc_core_lpm_latch_mode_write(struct file *file,  	 */  	reg = LPM_STS_LATCH_MODE | BIT(mode);  	mutex_lock(&pmcdev->lock); -	pmc_core_reg_write(pmcdev, pmcdev->map->lpm_sts_latch_en_offset, reg); +	pmc_core_reg_write(pmc, pmc->map->lpm_sts_latch_en_offset, reg);  	mutex_unlock(&pmcdev->lock);  	return count; @@ -849,8 +917,8 @@ DEFINE_PMC_CORE_ATTR_WRITE(pmc_core_lpm_latch_mode);  static int pmc_core_pkgc_show(struct seq_file *s, void *unused)  { -	struct pmc_dev *pmcdev = s->private; -	const struct pmc_bit_map *map = pmcdev->map->msr_sts; +	struct pmc *pmc = s->private; +	const struct pmc_bit_map *map = pmc->map->msr_sts;  	u64 pcstate_count;  	int index; @@ -901,6 +969,7 @@ static bool pmc_core_pri_verify(u32 lpm_pri, u8 *mode_order)  static void pmc_core_get_low_power_modes(struct platform_device *pdev)  {  	struct pmc_dev *pmcdev = platform_get_drvdata(pdev); +	struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN];  	u8 pri_order[LPM_MAX_NUM_MODES] = LPM_DEFAULT_PRI;  	u8 mode_order[LPM_MAX_NUM_MODES];  	u32 lpm_pri; @@ -908,10 +977,10 @@ static void pmc_core_get_low_power_modes(struct platform_device *pdev)  	int mode, i, p;  	/* Use LPM Maps to indicate support for substates */ -	if (!pmcdev->map->lpm_num_maps) +	if (!pmc->map->lpm_num_maps)  		return; -	lpm_en = pmc_core_reg_read(pmcdev, pmcdev->map->lpm_en_offset); +	lpm_en = pmc_core_reg_read(pmc, pmc->map->lpm_en_offset);  	/* For MTL, BIT 31 is not an lpm mode but a enable bit.  	 * Lower byte is enough to cover the number of lpm modes for all  	 * platforms and hence mask the upper 3 bytes. @@ -919,7 +988,7 @@ static void pmc_core_get_low_power_modes(struct platform_device *pdev)  	pmcdev->num_lpm_modes = hweight32(lpm_en & 0xFF);  	/* Read 32 bit LPM_PRI register */ -	lpm_pri = pmc_core_reg_read(pmcdev, pmcdev->map->lpm_priority_offset); +	lpm_pri = pmc_core_reg_read(pmc, pmc->map->lpm_priority_offset);  	/* @@ -948,6 +1017,25 @@ static void pmc_core_get_low_power_modes(struct platform_device *pdev)  	}  } +int get_primary_reg_base(struct pmc *pmc) +{ +	u64 slp_s0_addr; + +	if (lpit_read_residency_count_address(&slp_s0_addr)) { +		pmc->base_addr = PMC_BASE_ADDR_DEFAULT; + +		if (page_is_ram(PHYS_PFN(pmc->base_addr))) +			return -ENODEV; +	} else { +		pmc->base_addr = slp_s0_addr - pmc->map->slp_s0_offset; +	} + +	pmc->regbase = ioremap(pmc->base_addr, pmc->map->regmap_length); +	if (!pmc->regbase) +		return -ENOMEM; +	return 0; +} +  static void pmc_core_dbgfs_unregister(struct pmc_dev *pmcdev)  {  	debugfs_remove_recursive(pmcdev->dbgfs_dir); @@ -955,15 +1043,16 @@ static void pmc_core_dbgfs_unregister(struct pmc_dev *pmcdev)  static void pmc_core_dbgfs_register(struct pmc_dev *pmcdev)  { +	struct pmc *primary_pmc = pmcdev->pmcs[PMC_IDX_MAIN];  	struct dentry *dir;  	dir = debugfs_create_dir("pmc_core", NULL);  	pmcdev->dbgfs_dir = dir; -	debugfs_create_file("slp_s0_residency_usec", 0444, dir, pmcdev, +	debugfs_create_file("slp_s0_residency_usec", 0444, dir, primary_pmc,  			    &pmc_core_dev_state); -	if (pmcdev->map->pfear_sts) +	if (primary_pmc->map->pfear_sts)  		debugfs_create_file("pch_ip_power_gating_status", 0444, dir,  				    pmcdev, &pmc_core_ppfear_fops); @@ -972,19 +1061,19 @@ static void pmc_core_dbgfs_register(struct pmc_dev *pmcdev)  	debugfs_create_file("ltr_show", 0444, dir, pmcdev, &pmc_core_ltr_fops); -	debugfs_create_file("package_cstate_show", 0444, dir, pmcdev, +	debugfs_create_file("package_cstate_show", 0444, dir, primary_pmc,  			    &pmc_core_pkgc_fops); -	if (pmcdev->map->pll_sts) +	if (primary_pmc->map->pll_sts)  		debugfs_create_file("pll_status", 0444, dir, pmcdev,  				    &pmc_core_pll_fops); -	if (pmcdev->map->mphy_sts) +	if (primary_pmc->map->mphy_sts)  		debugfs_create_file("mphy_core_lanes_power_gating_status",  				    0444, dir, pmcdev,  				    &pmc_core_mphy_pg_fops); -	if (pmcdev->map->slps0_dbg_maps) { +	if (primary_pmc->map->slps0_dbg_maps) {  		debugfs_create_file("slp_s0_debug_status", 0444,  				    dir, pmcdev,  				    &pmc_core_slps0_dbg_fops); @@ -993,13 +1082,13 @@ static void pmc_core_dbgfs_register(struct pmc_dev *pmcdev)  				    dir, &slps0_dbg_latch);  	} -	if (pmcdev->map->lpm_en_offset) { +	if (primary_pmc->map->lpm_en_offset) {  		debugfs_create_file("substate_residencies", 0444,  				    pmcdev->dbgfs_dir, pmcdev,  				    &pmc_core_substate_res_fops);  	} -	if (pmcdev->map->lpm_status_offset) { +	if (primary_pmc->map->lpm_status_offset) {  		debugfs_create_file("substate_status_registers", 0444,  				    pmcdev->dbgfs_dir, pmcdev,  				    &pmc_core_substate_sts_regs_fops); @@ -1011,7 +1100,7 @@ static void pmc_core_dbgfs_register(struct pmc_dev *pmcdev)  				    &pmc_core_lpm_latch_mode_fops);  	} -	if (pmcdev->lpm_req_regs) { +	if (primary_pmc->lpm_req_regs) {  		debugfs_create_file("substate_requirements", 0444,  				    pmcdev->dbgfs_dir, pmcdev,  				    &pmc_core_substate_req_regs_fops); @@ -1039,7 +1128,6 @@ static const struct x86_cpu_id intel_pmc_core_ids[] = {  	X86_MATCH_INTEL_FAM6_MODEL(RAPTORLAKE_P,        tgl_core_init),  	X86_MATCH_INTEL_FAM6_MODEL(RAPTORLAKE,		adl_core_init),  	X86_MATCH_INTEL_FAM6_MODEL(RAPTORLAKE_S,	adl_core_init), -	X86_MATCH_INTEL_FAM6_MODEL(METEORLAKE,          mtl_core_init),  	X86_MATCH_INTEL_FAM6_MODEL(METEORLAKE_L,	mtl_core_init),  	{}  }; @@ -1063,16 +1151,16 @@ static int quirk_xtal_ignore(const struct dmi_system_id *id)  	return 0;  } -static void pmc_core_xtal_ignore(struct pmc_dev *pmcdev) +static void pmc_core_xtal_ignore(struct pmc *pmc)  {  	u32 value; -	value = pmc_core_reg_read(pmcdev, pmcdev->map->pm_vric1_offset); +	value = pmc_core_reg_read(pmc, pmc->map->pm_vric1_offset);  	/* 24MHz Crystal Shutdown Qualification Disable */  	value |= SPT_PMC_VRIC1_XTALSDQDIS;  	/* Low Voltage Mode Enable */  	value &= ~SPT_PMC_VRIC1_SLPS0LVEN; -	pmc_core_reg_write(pmcdev, pmcdev->map->pm_vric1_offset, value); +	pmc_core_reg_write(pmc, pmc->map->pm_vric1_offset, value);  }  static const struct dmi_system_id pmc_core_dmi_table[]  = { @@ -1087,12 +1175,32 @@ static const struct dmi_system_id pmc_core_dmi_table[]  = {  	{}  }; -static void pmc_core_do_dmi_quirks(struct pmc_dev *pmcdev) +static void pmc_core_do_dmi_quirks(struct pmc *pmc)  {  	dmi_check_system(pmc_core_dmi_table);  	if (xtal_ignore) -		pmc_core_xtal_ignore(pmcdev); +		pmc_core_xtal_ignore(pmc); +} + +static void pmc_core_clean_structure(struct platform_device *pdev) +{ +	struct pmc_dev *pmcdev = platform_get_drvdata(pdev); +	int i; + +	for (i = 0; i < ARRAY_SIZE(pmcdev->pmcs); ++i) { +		struct pmc *pmc = pmcdev->pmcs[i]; + +		if (pmc) +			iounmap(pmc->regbase); +	} + +	if (pmcdev->ssram_pcidev) { +		pci_dev_put(pmcdev->ssram_pcidev); +		pci_disable_device(pmcdev->ssram_pcidev); +	} +	platform_set_drvdata(pdev, NULL); +	mutex_destroy(&pmcdev->lock);  }  static int pmc_core_probe(struct platform_device *pdev) @@ -1100,8 +1208,9 @@ static int pmc_core_probe(struct platform_device *pdev)  	static bool device_initialized;  	struct pmc_dev *pmcdev;  	const struct x86_cpu_id *cpu_id; -	void (*core_init)(struct pmc_dev *pmcdev); -	u64 slp_s0_addr; +	int (*core_init)(struct pmc_dev *pmcdev); +	struct pmc *primary_pmc; +	int ret;  	if (device_initialized)  		return -ENODEV; @@ -1117,7 +1226,13 @@ static int pmc_core_probe(struct platform_device *pdev)  	if (!cpu_id)  		return -ENODEV; -	core_init = (void  (*)(struct pmc_dev *))cpu_id->driver_data; +	core_init = (int (*)(struct pmc_dev *))cpu_id->driver_data; + +	/* Primary PMC */ +	primary_pmc = devm_kzalloc(&pdev->dev, sizeof(*primary_pmc), GFP_KERNEL); +	if (!primary_pmc) +		return -ENOMEM; +	pmcdev->pmcs[PMC_IDX_MAIN] = primary_pmc;  	/*  	 * Coffee Lake has CPU ID of Kaby Lake and Cannon Lake PCH. So here @@ -1128,33 +1243,19 @@ static int pmc_core_probe(struct platform_device *pdev)  		core_init = cnp_core_init;  	mutex_init(&pmcdev->lock); -	core_init(pmcdev); - - -	if (lpit_read_residency_count_address(&slp_s0_addr)) { -		pmcdev->base_addr = PMC_BASE_ADDR_DEFAULT; - -		if (page_is_ram(PHYS_PFN(pmcdev->base_addr))) -			return -ENODEV; -	} else { -		pmcdev->base_addr = slp_s0_addr - pmcdev->map->slp_s0_offset; +	ret = core_init(pmcdev); +	if (ret) { +		pmc_core_clean_structure(pdev); +		return ret;  	} -	pmcdev->regbase = ioremap(pmcdev->base_addr, -				  pmcdev->map->regmap_length); -	if (!pmcdev->regbase) -		return -ENOMEM; - -	if (pmcdev->core_configure) -		pmcdev->core_configure(pmcdev); - -	pmcdev->pmc_xram_read_bit = pmc_core_check_read_lock_bit(pmcdev); +	pmcdev->pmc_xram_read_bit = pmc_core_check_read_lock_bit(primary_pmc);  	pmc_core_get_low_power_modes(pdev); -	pmc_core_do_dmi_quirks(pmcdev); +	pmc_core_do_dmi_quirks(primary_pmc);  	pmc_core_dbgfs_register(pmcdev);  	pm_report_max_hw_sleep(FIELD_MAX(SLP_S0_RES_COUNTER_MASK) * -			       pmc_core_adjust_slp_s0_step(pmcdev, 1)); +			       pmc_core_adjust_slp_s0_step(primary_pmc, 1));  	device_initialized = true;  	dev_info(&pdev->dev, " initialized\n"); @@ -1165,11 +1266,8 @@ static int pmc_core_probe(struct platform_device *pdev)  static void pmc_core_remove(struct platform_device *pdev)  {  	struct pmc_dev *pmcdev = platform_get_drvdata(pdev); -  	pmc_core_dbgfs_unregister(pmcdev); -	platform_set_drvdata(pdev, NULL); -	mutex_destroy(&pmcdev->lock); -	iounmap(pmcdev->regbase); +	pmc_core_clean_structure(pdev);  }  static bool warn_on_s0ix_failures; @@ -1179,6 +1277,7 @@ MODULE_PARM_DESC(warn_on_s0ix_failures, "Check and warn for S0ix failures");  static __maybe_unused int pmc_core_suspend(struct device *dev)  {  	struct pmc_dev *pmcdev = dev_get_drvdata(dev); +	struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN];  	/* Check if the syspend will actually use S0ix */  	if (pm_suspend_via_firmware()) @@ -1189,7 +1288,7 @@ static __maybe_unused int pmc_core_suspend(struct device *dev)  		return -EIO;  	/* Save S0ix residency for checking later */ -	if (pmc_core_dev_state_get(pmcdev, &pmcdev->s0ix_counter)) +	if (pmc_core_dev_state_get(pmc, &pmcdev->s0ix_counter))  		return -EIO;  	return 0; @@ -1212,7 +1311,7 @@ static inline bool pmc_core_is_s0ix_failed(struct pmc_dev *pmcdev)  {  	u64 s0ix_counter; -	if (pmc_core_dev_state_get(pmcdev, &s0ix_counter)) +	if (pmc_core_dev_state_get(pmcdev->pmcs[PMC_IDX_MAIN], &s0ix_counter))  		return false;  	pm_report_hw_sleep_time((u32)(s0ix_counter - pmcdev->s0ix_counter)); @@ -1223,11 +1322,13 @@ static inline bool pmc_core_is_s0ix_failed(struct pmc_dev *pmcdev)  	return false;  } -static __maybe_unused int pmc_core_resume(struct device *dev) +int pmc_core_resume_common(struct pmc_dev *pmcdev)  { -	struct pmc_dev *pmcdev = dev_get_drvdata(dev); -	const struct pmc_bit_map **maps = pmcdev->map->lpm_sts; -	int offset = pmcdev->map->lpm_status_offset; +	struct device *dev = &pmcdev->pdev->dev; +	struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN]; +	const struct pmc_bit_map **maps = pmc->map->lpm_sts; +	int offset = pmc->map->lpm_status_offset; +	int i;  	/* Check if the syspend used S0ix */  	if (pm_suspend_via_firmware()) @@ -1249,14 +1350,32 @@ static __maybe_unused int pmc_core_resume(struct device *dev)  	/* The real interesting case - S0ix failed - lets ask PMC why. */  	dev_warn(dev, "CPU did not enter SLP_S0!!! (S0ix cnt=%llu)\n",  		 pmcdev->s0ix_counter); -	if (pmcdev->map->slps0_dbg_maps) -		pmc_core_slps0_display(pmcdev, dev, NULL); -	if (pmcdev->map->lpm_sts) -		pmc_core_lpm_display(pmcdev, dev, NULL, offset, "STATUS", maps); + +	if (pmc->map->slps0_dbg_maps) +		pmc_core_slps0_display(pmc, dev, NULL); + +	for (i = 0; i < ARRAY_SIZE(pmcdev->pmcs); ++i) { +		struct pmc *pmc = pmcdev->pmcs[i]; + +		if (!pmc) +			continue; +		if (pmc->map->lpm_sts) +			pmc_core_lpm_display(pmc, dev, NULL, offset, i, "STATUS", maps); +	}  	return 0;  } +static __maybe_unused int pmc_core_resume(struct device *dev) +{ +	struct pmc_dev *pmcdev = dev_get_drvdata(dev); + +	if (pmcdev->resume) +		return pmcdev->resume(pmcdev); + +	return pmc_core_resume_common(pmcdev); +} +  static const struct dev_pm_ops pmc_core_pm_ops = {  	SET_LATE_SYSTEM_SLEEP_PM_OPS(pmc_core_suspend, pmc_core_resume)  }; diff --git a/drivers/platform/x86/intel/pmc/core.h b/drivers/platform/x86/intel/pmc/core.h index 9ca9b9746719..0729f593c6a7 100644 --- a/drivers/platform/x86/intel/pmc/core.h +++ b/drivers/platform/x86/intel/pmc/core.h @@ -19,6 +19,7 @@  #define SLP_S0_RES_COUNTER_MASK			GENMASK(31, 0)  #define PMC_BASE_ADDR_DEFAULT			0xFE000000 +#define MAX_NUM_PMC			3  /* Sunrise Point Power Management Controller PCI Device ID */  #define SPT_PMC_PCI_DEVICE_ID			0x9d21 @@ -249,6 +250,17 @@ enum ppfear_regs {  #define MTL_LPM_STATUS_LATCH_EN_OFFSET		0x16F8  #define MTL_LPM_STATUS_OFFSET			0x1700  #define MTL_LPM_LIVE_STATUS_OFFSET		0x175C +#define MTL_PMC_LTR_IOE_PMC			0x1C0C +#define MTL_PMC_LTR_ESE				0x1BAC +#define MTL_PMC_LTR_RESERVED			0x1BA4 +#define MTL_IOE_PMC_MMIO_REG_LEN		0x23A4 +#define MTL_SOCM_NUM_IP_IGN_ALLOWED		25 +#define MTL_SOC_PMC_MMIO_REG_LEN		0x2708 +#define MTL_PMC_LTR_SPG				0x1B74 + +/* Meteor Lake PGD PFET Enable Ack Status */ +#define MTL_SOCM_PPFEAR_NUM_ENTRIES		8 +#define MTL_IOE_PPFEAR_NUM_ENTRIES		10  extern const char *pmc_lpm_modes[]; @@ -311,12 +323,38 @@ struct pmc_reg_map {  };  /** - * struct pmc_dev - pmc device structure + * struct pmc_info - Structure to keep pmc info + * @devid:		device id of the pmc device + * @map:		pointer to a pmc_reg_map struct that contains platform + *			specific attributes + */ +struct pmc_info { +	u16 devid; +	const struct pmc_reg_map *map; +}; + +/** + * struct pmc - pmc private info structure   * @base_addr:		contains pmc base address   * @regbase:		pointer to io-remapped memory location   * @map:		pointer to pmc_reg_map struct that contains platform   *			specific attributes + * @lpm_req_regs:	List of substate requirements + * + * pmc contains info about one power management controller device. + */ +struct pmc { +	u64 base_addr; +	void __iomem *regbase; +	const struct pmc_reg_map *map; +	u32 *lpm_req_regs; +}; + +/** + * struct pmc_dev - pmc device structure + * @devs:		pointer to an array of pmc pointers   * @pdev:		pointer to platform_device struct + * @ssram_pcidev:	pointer to pci device struct for the PMC SSRAM   * @dbgfs_dir:		path to debugfs interface   * @pmc_xram_read_bit:	flag to indicate whether PMC XRAM shadow registers   *			used to read MPHY PG and PLL status are available @@ -325,17 +363,15 @@ struct pmc_reg_map {   * @s0ix_counter:	S0ix residency (step adjusted)   * @num_lpm_modes:	Count of enabled modes   * @lpm_en_modes:	Array of enabled modes from lowest to highest priority - * @lpm_req_regs:	List of substate requirements - * @core_configure:	Function pointer to configure the platform + * @resume:		Function to perform platform specific resume   *   * pmc_dev contains info about power management controller device.   */  struct pmc_dev { -	u32 base_addr; -	void __iomem *regbase; -	const struct pmc_reg_map *map; +	struct pmc *pmcs[MAX_NUM_PMC];  	struct dentry *dbgfs_dir;  	struct platform_device *pdev; +	struct pci_dev *ssram_pcidev;  	int pmc_xram_read_bit;  	struct mutex lock; /* generic mutex lock for PMC Core */ @@ -343,8 +379,20 @@ struct pmc_dev {  	u64 s0ix_counter;  	int num_lpm_modes;  	int lpm_en_modes[LPM_MAX_NUM_MODES]; -	u32 *lpm_req_regs; -	void (*core_configure)(struct pmc_dev *pmcdev); +	int (*resume)(struct pmc_dev *pmcdev); + +	bool has_die_c6; +	u32 die_c6_offset; +	struct telem_endpoint *punit_ep; +	struct pmc_info *regmap_list; +}; + +enum pmc_index { +	PMC_IDX_MAIN, +	PMC_IDX_SOC = PMC_IDX_MAIN, +	PMC_IDX_IOE, +	PMC_IDX_PCH, +	PMC_IDX_MAX  };  extern const struct pmc_bit_map msr_map[]; @@ -393,20 +441,64 @@ extern const struct pmc_bit_map adl_vnn_req_status_3_map[];  extern const struct pmc_bit_map adl_vnn_misc_status_map[];  extern const struct pmc_bit_map *adl_lpm_maps[];  extern const struct pmc_reg_map adl_reg_map; -extern const struct pmc_reg_map mtl_reg_map; +extern const struct pmc_bit_map mtl_socm_pfear_map[]; +extern const struct pmc_bit_map *ext_mtl_socm_pfear_map[]; +extern const struct pmc_bit_map mtl_socm_ltr_show_map[]; +extern const struct pmc_bit_map mtl_socm_clocksource_status_map[]; +extern const struct pmc_bit_map mtl_socm_power_gating_status_0_map[]; +extern const struct pmc_bit_map mtl_socm_power_gating_status_1_map[]; +extern const struct pmc_bit_map mtl_socm_power_gating_status_2_map[]; +extern const struct pmc_bit_map mtl_socm_d3_status_0_map[]; +extern const struct pmc_bit_map mtl_socm_d3_status_1_map[]; +extern const struct pmc_bit_map mtl_socm_d3_status_2_map[]; +extern const struct pmc_bit_map mtl_socm_d3_status_3_map[]; +extern const struct pmc_bit_map mtl_socm_vnn_req_status_0_map[]; +extern const struct pmc_bit_map mtl_socm_vnn_req_status_1_map[]; +extern const struct pmc_bit_map mtl_socm_vnn_req_status_2_map[]; +extern const struct pmc_bit_map mtl_socm_vnn_req_status_3_map[]; +extern const struct pmc_bit_map mtl_socm_vnn_misc_status_map[]; +extern const struct pmc_bit_map mtl_socm_signal_status_map[]; +extern const struct pmc_bit_map *mtl_socm_lpm_maps[]; +extern const struct pmc_reg_map mtl_socm_reg_map; +extern const struct pmc_bit_map mtl_ioep_pfear_map[]; +extern const struct pmc_bit_map *ext_mtl_ioep_pfear_map[]; +extern const struct pmc_bit_map mtl_ioep_ltr_show_map[]; +extern const struct pmc_bit_map mtl_ioep_clocksource_status_map[]; +extern const struct pmc_bit_map mtl_ioep_power_gating_status_0_map[]; +extern const struct pmc_bit_map mtl_ioep_power_gating_status_1_map[]; +extern const struct pmc_bit_map mtl_ioep_power_gating_status_2_map[]; +extern const struct pmc_bit_map mtl_ioep_d3_status_0_map[]; +extern const struct pmc_bit_map mtl_ioep_d3_status_1_map[]; +extern const struct pmc_bit_map mtl_ioep_d3_status_2_map[]; +extern const struct pmc_bit_map mtl_ioep_d3_status_3_map[]; +extern const struct pmc_bit_map mtl_ioep_vnn_req_status_0_map[]; +extern const struct pmc_bit_map mtl_ioep_vnn_req_status_1_map[]; +extern const struct pmc_bit_map mtl_ioep_vnn_req_status_2_map[]; +extern const struct pmc_bit_map mtl_ioep_vnn_req_status_3_map[]; +extern const struct pmc_bit_map mtl_ioep_vnn_misc_status_map[]; +extern const struct pmc_bit_map *mtl_ioep_lpm_maps[]; +extern const struct pmc_reg_map mtl_ioep_reg_map; +extern const struct pmc_bit_map mtl_ioem_pfear_map[]; +extern const struct pmc_bit_map *ext_mtl_ioem_pfear_map[]; +extern const struct pmc_bit_map mtl_ioem_power_gating_status_1_map[]; +extern const struct pmc_bit_map mtl_ioem_vnn_req_status_1_map[]; +extern const struct pmc_bit_map *mtl_ioem_lpm_maps[]; +extern const struct pmc_reg_map mtl_ioem_reg_map;  extern void pmc_core_get_tgl_lpm_reqs(struct platform_device *pdev);  extern int pmc_core_send_ltr_ignore(struct pmc_dev *pmcdev, u32 value); -void spt_core_init(struct pmc_dev *pmcdev); -void cnp_core_init(struct pmc_dev *pmcdev); -void icl_core_init(struct pmc_dev *pmcdev); -void tgl_core_init(struct pmc_dev *pmcdev); -void adl_core_init(struct pmc_dev *pmcdev); -void mtl_core_init(struct pmc_dev *pmcdev); -void tgl_core_configure(struct pmc_dev *pmcdev); -void adl_core_configure(struct pmc_dev *pmcdev); -void mtl_core_configure(struct pmc_dev *pmcdev); +int pmc_core_resume_common(struct pmc_dev *pmcdev); +int get_primary_reg_base(struct pmc *pmc); + +extern void pmc_core_ssram_init(struct pmc_dev *pmcdev); + +int spt_core_init(struct pmc_dev *pmcdev); +int cnp_core_init(struct pmc_dev *pmcdev); +int icl_core_init(struct pmc_dev *pmcdev); +int tgl_core_init(struct pmc_dev *pmcdev); +int adl_core_init(struct pmc_dev *pmcdev); +int mtl_core_init(struct pmc_dev *pmcdev);  #define pmc_for_each_mode(i, mode, pmcdev)		\  	for (i = 0, mode = pmcdev->lpm_en_modes[i];	\ diff --git a/drivers/platform/x86/intel/pmc/core_ssram.c b/drivers/platform/x86/intel/pmc/core_ssram.c new file mode 100644 index 000000000000..13fa16f0d52e --- /dev/null +++ b/drivers/platform/x86/intel/pmc/core_ssram.c @@ -0,0 +1,133 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * This file contains functions to handle discovery of PMC metrics located + * in the PMC SSRAM PCI device. + * + * Copyright (c) 2023, Intel Corporation. + * All Rights Reserved. + * + */ + +#include <linux/pci.h> +#include <linux/io-64-nonatomic-lo-hi.h> + +#include "core.h" + +#define SSRAM_HDR_SIZE		0x100 +#define SSRAM_PWRM_OFFSET	0x14 +#define SSRAM_DVSEC_OFFSET	0x1C +#define SSRAM_DVSEC_SIZE	0x10 +#define SSRAM_PCH_OFFSET	0x60 +#define SSRAM_IOE_OFFSET	0x68 +#define SSRAM_DEVID_OFFSET	0x70 + +static const struct pmc_reg_map *pmc_core_find_regmap(struct pmc_info *list, u16 devid) +{ +	for (; list->map; ++list) +		if (devid == list->devid) +			return list->map; + +	return NULL; +} + +static inline u64 get_base(void __iomem *addr, u32 offset) +{ +	return lo_hi_readq(addr + offset) & GENMASK_ULL(63, 3); +} + +static void +pmc_core_pmc_add(struct pmc_dev *pmcdev, u64 pwrm_base, +		 const struct pmc_reg_map *reg_map, int pmc_index) +{ +	struct pmc *pmc = pmcdev->pmcs[pmc_index]; + +	if (!pwrm_base) +		return; + +	/* Memory for primary PMC has been allocated in core.c */ +	if (!pmc) { +		pmc = devm_kzalloc(&pmcdev->pdev->dev, sizeof(*pmc), GFP_KERNEL); +		if (!pmc) +			return; +	} + +	pmc->map = reg_map; +	pmc->base_addr = pwrm_base; +	pmc->regbase = ioremap(pmc->base_addr, pmc->map->regmap_length); + +	if (!pmc->regbase) { +		devm_kfree(&pmcdev->pdev->dev, pmc); +		return; +	} + +	pmcdev->pmcs[pmc_index] = pmc; +} + +static void +pmc_core_ssram_get_pmc(struct pmc_dev *pmcdev, void __iomem *ssram, u32 offset, +		       int pmc_idx) +{ +	u64 pwrm_base; +	u16 devid; + +	if (pmc_idx != PMC_IDX_SOC) { +		u64 ssram_base = get_base(ssram, offset); + +		if (!ssram_base) +			return; + +		ssram = ioremap(ssram_base, SSRAM_HDR_SIZE); +		if (!ssram) +			return; +	} + +	pwrm_base = get_base(ssram, SSRAM_PWRM_OFFSET); +	devid = readw(ssram + SSRAM_DEVID_OFFSET); + +	if (pmcdev->regmap_list) { +		const struct pmc_reg_map *map; + +		map = pmc_core_find_regmap(pmcdev->regmap_list, devid); +		if (map) +			pmc_core_pmc_add(pmcdev, pwrm_base, map, pmc_idx); +	} + +	if (pmc_idx != PMC_IDX_SOC) +		iounmap(ssram); +} + +void pmc_core_ssram_init(struct pmc_dev *pmcdev) +{ +	void __iomem *ssram; +	struct pci_dev *pcidev; +	u64 ssram_base; +	int ret; + +	pcidev = pci_get_domain_bus_and_slot(0, 0, PCI_DEVFN(20, 2)); +	if (!pcidev) +		goto out; + +	ret = pcim_enable_device(pcidev); +	if (ret) +		goto release_dev; + +	ssram_base = pcidev->resource[0].start; +	ssram = ioremap(ssram_base, SSRAM_HDR_SIZE); +	if (!ssram) +		goto disable_dev; + +	pmcdev->ssram_pcidev = pcidev; + +	pmc_core_ssram_get_pmc(pmcdev, ssram, 0, PMC_IDX_SOC); +	pmc_core_ssram_get_pmc(pmcdev, ssram, SSRAM_IOE_OFFSET, PMC_IDX_IOE); +	pmc_core_ssram_get_pmc(pmcdev, ssram, SSRAM_PCH_OFFSET, PMC_IDX_PCH); + +	iounmap(ssram); +out: +	return; + +disable_dev: +	pci_disable_device(pcidev); +release_dev: +	pci_dev_put(pcidev); +} diff --git a/drivers/platform/x86/intel/pmc/icl.c b/drivers/platform/x86/intel/pmc/icl.c index 2f11b1a6daeb..d08e3174230d 100644 --- a/drivers/platform/x86/intel/pmc/icl.c +++ b/drivers/platform/x86/intel/pmc/icl.c @@ -50,7 +50,10 @@ const struct pmc_reg_map icl_reg_map = {  	.etr3_offset = ETR3_OFFSET,  }; -void icl_core_init(struct pmc_dev *pmcdev) +int icl_core_init(struct pmc_dev *pmcdev)  { -	pmcdev->map = &icl_reg_map; +	struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN]; + +	pmc->map = &icl_reg_map; +	return get_primary_reg_base(pmc);  } diff --git a/drivers/platform/x86/intel/pmc/mtl.c b/drivers/platform/x86/intel/pmc/mtl.c index e8cc156412ce..2204bc666980 100644 --- a/drivers/platform/x86/intel/pmc/mtl.c +++ b/drivers/platform/x86/intel/pmc/mtl.c @@ -11,40 +11,937 @@  #include <linux/pci.h>  #include "core.h" -const struct pmc_reg_map mtl_reg_map = { -	.pfear_sts = ext_tgl_pfear_map, +/* + * Die Mapping to Product. + * Product SOCDie IOEDie PCHDie + * MTL-M   SOC-M  IOE-M  None + * MTL-P   SOC-M  IOE-P  None + * MTL-S   SOC-S  IOE-P  PCH-S + */ + +const struct pmc_bit_map mtl_socm_pfear_map[] = { +	{"PMC",                 BIT(0)}, +	{"OPI",                 BIT(1)}, +	{"SPI",                 BIT(2)}, +	{"XHCI",                BIT(3)}, +	{"SPA",                 BIT(4)}, +	{"SPB",                 BIT(5)}, +	{"SPC",                 BIT(6)}, +	{"GBE",                 BIT(7)}, + +	{"SATA",                BIT(0)}, +	{"DSP0",                BIT(1)}, +	{"DSP1",                BIT(2)}, +	{"DSP2",                BIT(3)}, +	{"DSP3",                BIT(4)}, +	{"SPD",                 BIT(5)}, +	{"LPSS",                BIT(6)}, +	{"LPC",                 BIT(7)}, + +	{"SMB",                 BIT(0)}, +	{"ISH",                 BIT(1)}, +	{"P2SB",                BIT(2)}, +	{"NPK_VNN",             BIT(3)}, +	{"SDX",                 BIT(4)}, +	{"SPE",                 BIT(5)}, +	{"FUSE",                BIT(6)}, +	{"SBR8",                BIT(7)}, + +	{"RSVD24",              BIT(0)}, +	{"OTG",                 BIT(1)}, +	{"EXI",                 BIT(2)}, +	{"CSE",                 BIT(3)}, +	{"CSME_KVM",            BIT(4)}, +	{"CSME_PMT",            BIT(5)}, +	{"CSME_CLINK",          BIT(6)}, +	{"CSME_PTIO",           BIT(7)}, + +	{"CSME_USBR",           BIT(0)}, +	{"CSME_SUSRAM",         BIT(1)}, +	{"CSME_SMT1",           BIT(2)}, +	{"RSVD35",              BIT(3)}, +	{"CSME_SMS2",           BIT(4)}, +	{"CSME_SMS",            BIT(5)}, +	{"CSME_RTC",            BIT(6)}, +	{"CSME_PSF",            BIT(7)}, + +	{"SBR0",                BIT(0)}, +	{"SBR1",                BIT(1)}, +	{"SBR2",                BIT(2)}, +	{"SBR3",                BIT(3)}, +	{"SBR4",                BIT(4)}, +	{"SBR5",                BIT(5)}, +	{"RSVD46",              BIT(6)}, +	{"PSF1",                BIT(7)}, + +	{"PSF2",                BIT(0)}, +	{"PSF3",                BIT(1)}, +	{"PSF4",                BIT(2)}, +	{"CNVI",                BIT(3)}, +	{"UFSX2",               BIT(4)}, +	{"EMMC",                BIT(5)}, +	{"SPF",                 BIT(6)}, +	{"SBR6",                BIT(7)}, + +	{"SBR7",                BIT(0)}, +	{"NPK_AON",             BIT(1)}, +	{"HDA4",                BIT(2)}, +	{"HDA5",                BIT(3)}, +	{"HDA6",                BIT(4)}, +	{"PSF6",                BIT(5)}, +	{"RSVD62",              BIT(6)}, +	{"RSVD63",              BIT(7)}, +	{} +}; + +const struct pmc_bit_map *ext_mtl_socm_pfear_map[] = { +	mtl_socm_pfear_map, +	NULL +}; + +const struct pmc_bit_map mtl_socm_ltr_show_map[] = { +	{"SOUTHPORT_A",		CNP_PMC_LTR_SPA}, +	{"SOUTHPORT_B",		CNP_PMC_LTR_SPB}, +	{"SATA",		CNP_PMC_LTR_SATA}, +	{"GIGABIT_ETHERNET",	CNP_PMC_LTR_GBE}, +	{"XHCI",		CNP_PMC_LTR_XHCI}, +	{"SOUTHPORT_F",		ADL_PMC_LTR_SPF}, +	{"ME",			CNP_PMC_LTR_ME}, +	{"SATA1",		CNP_PMC_LTR_EVA}, +	{"SOUTHPORT_C",		CNP_PMC_LTR_SPC}, +	{"HD_AUDIO",		CNP_PMC_LTR_AZ}, +	{"CNV",			CNP_PMC_LTR_CNV}, +	{"LPSS",		CNP_PMC_LTR_LPSS}, +	{"SOUTHPORT_D",		CNP_PMC_LTR_SPD}, +	{"SOUTHPORT_E",		CNP_PMC_LTR_SPE}, +	{"SATA2",		CNP_PMC_LTR_CAM}, +	{"ESPI",		CNP_PMC_LTR_ESPI}, +	{"SCC",			CNP_PMC_LTR_SCC}, +	{"ISH",                 CNP_PMC_LTR_ISH}, +	{"UFSX2",		CNP_PMC_LTR_UFSX2}, +	{"EMMC",		CNP_PMC_LTR_EMMC}, +	{"WIGIG",		ICL_PMC_LTR_WIGIG}, +	{"THC0",		TGL_PMC_LTR_THC0}, +	{"THC1",		TGL_PMC_LTR_THC1}, +	{"SOUTHPORT_G",		MTL_PMC_LTR_SPG}, +	{"ESE",                 MTL_PMC_LTR_ESE}, +	{"IOE_PMC",		MTL_PMC_LTR_IOE_PMC}, + +	/* Below two cannot be used for LTR_IGNORE */ +	{"CURRENT_PLATFORM",	CNP_PMC_LTR_CUR_PLT}, +	{"AGGREGATED_SYSTEM",	CNP_PMC_LTR_CUR_ASLT}, +	{} +}; + +const struct pmc_bit_map mtl_socm_clocksource_status_map[] = { +	{"AON2_OFF_STS",                 BIT(0)}, +	{"AON3_OFF_STS",                 BIT(1)}, +	{"AON4_OFF_STS",                 BIT(2)}, +	{"AON5_OFF_STS",                 BIT(3)}, +	{"AON1_OFF_STS",                 BIT(4)}, +	{"XTAL_LVM_OFF_STS",             BIT(5)}, +	{"MPFPW1_0_PLL_OFF_STS",         BIT(6)}, +	{"MPFPW1_1_PLL_OFF_STS",         BIT(7)}, +	{"USB3_PLL_OFF_STS",             BIT(8)}, +	{"AON3_SPL_OFF_STS",             BIT(9)}, +	{"MPFPW2_0_PLL_OFF_STS",         BIT(12)}, +	{"MPFPW3_0_PLL_OFF_STS",         BIT(13)}, +	{"XTAL_AGGR_OFF_STS",            BIT(17)}, +	{"USB2_PLL_OFF_STS",             BIT(18)}, +	{"FILTER_PLL_OFF_STS",           BIT(22)}, +	{"ACE_PLL_OFF_STS",              BIT(24)}, +	{"FABRIC_PLL_OFF_STS",           BIT(25)}, +	{"SOC_PLL_OFF_STS",              BIT(26)}, +	{"PCIFAB_PLL_OFF_STS",           BIT(27)}, +	{"REF_PLL_OFF_STS",              BIT(28)}, +	{"IMG_PLL_OFF_STS",              BIT(29)}, +	{"RTC_PLL_OFF_STS",              BIT(31)}, +	{} +}; + +const struct pmc_bit_map mtl_socm_power_gating_status_0_map[] = { +	{"PMC_PGD0_PG_STS",              BIT(0)}, +	{"DMI_PGD0_PG_STS",              BIT(1)}, +	{"ESPISPI_PGD0_PG_STS",          BIT(2)}, +	{"XHCI_PGD0_PG_STS",             BIT(3)}, +	{"SPA_PGD0_PG_STS",              BIT(4)}, +	{"SPB_PGD0_PG_STS",              BIT(5)}, +	{"SPC_PGD0_PG_STS",              BIT(6)}, +	{"GBE_PGD0_PG_STS",              BIT(7)}, +	{"SATA_PGD0_PG_STS",             BIT(8)}, +	{"PSF13_PGD0_PG_STS",            BIT(9)}, +	{"SOC_D2D_PGD3_PG_STS",          BIT(10)}, +	{"MPFPW3_PGD0_PG_STS",           BIT(11)}, +	{"ESE_PGD0_PG_STS",              BIT(12)}, +	{"SPD_PGD0_PG_STS",              BIT(13)}, +	{"LPSS_PGD0_PG_STS",             BIT(14)}, +	{"LPC_PGD0_PG_STS",              BIT(15)}, +	{"SMB_PGD0_PG_STS",              BIT(16)}, +	{"ISH_PGD0_PG_STS",              BIT(17)}, +	{"P2S_PGD0_PG_STS",              BIT(18)}, +	{"NPK_PGD0_PG_STS",              BIT(19)}, +	{"DBG_SBR_PGD0_PG_STS",          BIT(20)}, +	{"SBRG_PGD0_PG_STS",             BIT(21)}, +	{"FUSE_PGD0_PG_STS",             BIT(22)}, +	{"SBR8_PGD0_PG_STS",             BIT(23)}, +	{"SOC_D2D_PGD2_PG_STS",          BIT(24)}, +	{"XDCI_PGD0_PG_STS",             BIT(25)}, +	{"EXI_PGD0_PG_STS",              BIT(26)}, +	{"CSE_PGD0_PG_STS",              BIT(27)}, +	{"KVMCC_PGD0_PG_STS",            BIT(28)}, +	{"PMT_PGD0_PG_STS",              BIT(29)}, +	{"CLINK_PGD0_PG_STS",            BIT(30)}, +	{"PTIO_PGD0_PG_STS",             BIT(31)}, +	{} +}; + +const struct pmc_bit_map mtl_socm_power_gating_status_1_map[] = { +	{"USBR0_PGD0_PG_STS",            BIT(0)}, +	{"SUSRAM_PGD0_PG_STS",           BIT(1)}, +	{"SMT1_PGD0_PG_STS",             BIT(2)}, +	{"FIACPCB_U_PGD0_PG_STS",        BIT(3)}, +	{"SMS2_PGD0_PG_STS",             BIT(4)}, +	{"SMS1_PGD0_PG_STS",             BIT(5)}, +	{"CSMERTC_PGD0_PG_STS",          BIT(6)}, +	{"CSMEPSF_PGD0_PG_STS",          BIT(7)}, +	{"SBR0_PGD0_PG_STS",             BIT(8)}, +	{"SBR1_PGD0_PG_STS",             BIT(9)}, +	{"SBR2_PGD0_PG_STS",             BIT(10)}, +	{"SBR3_PGD0_PG_STS",             BIT(11)}, +	{"U3FPW1_PGD0_PG_STS",           BIT(12)}, +	{"SBR5_PGD0_PG_STS",             BIT(13)}, +	{"MPFPW1_PGD0_PG_STS",           BIT(14)}, +	{"UFSPW1_PGD0_PG_STS",           BIT(15)}, +	{"FIA_X_PGD0_PG_STS",            BIT(16)}, +	{"SOC_D2D_PGD0_PG_STS",          BIT(17)}, +	{"MPFPW2_PGD0_PG_STS",           BIT(18)}, +	{"CNVI_PGD0_PG_STS",             BIT(19)}, +	{"UFSX2_PGD0_PG_STS",            BIT(20)}, +	{"ENDBG_PGD0_PG_STS",            BIT(21)}, +	{"DBG_PSF_PGD0_PG_STS",          BIT(22)}, +	{"SBR6_PGD0_PG_STS",             BIT(23)}, +	{"SBR7_PGD0_PG_STS",             BIT(24)}, +	{"NPK_PGD1_PG_STS",              BIT(25)}, +	{"FIACPCB_X_PGD0_PG_STS",        BIT(26)}, +	{"DBC_PGD0_PG_STS",              BIT(27)}, +	{"FUSEGPSB_PGD0_PG_STS",         BIT(28)}, +	{"PSF6_PGD0_PG_STS",             BIT(29)}, +	{"PSF7_PGD0_PG_STS",             BIT(30)}, +	{"GBETSN1_PGD0_PG_STS",          BIT(31)}, +	{} +}; + +const struct pmc_bit_map mtl_socm_power_gating_status_2_map[] = { +	{"PSF8_PGD0_PG_STS",             BIT(0)}, +	{"FIA_PGD0_PG_STS",              BIT(1)}, +	{"SOC_D2D_PGD1_PG_STS",          BIT(2)}, +	{"FIA_U_PGD0_PG_STS",            BIT(3)}, +	{"TAM_PGD0_PG_STS",              BIT(4)}, +	{"GBETSN_PGD0_PG_STS",           BIT(5)}, +	{"TBTLSX_PGD0_PG_STS",           BIT(6)}, +	{"THC0_PGD0_PG_STS",             BIT(7)}, +	{"THC1_PGD0_PG_STS",             BIT(8)}, +	{"PMC_PGD1_PG_STS",              BIT(9)}, +	{"GNA_PGD0_PG_STS",              BIT(10)}, +	{"ACE_PGD0_PG_STS",              BIT(11)}, +	{"ACE_PGD1_PG_STS",              BIT(12)}, +	{"ACE_PGD2_PG_STS",              BIT(13)}, +	{"ACE_PGD3_PG_STS",              BIT(14)}, +	{"ACE_PGD4_PG_STS",              BIT(15)}, +	{"ACE_PGD5_PG_STS",              BIT(16)}, +	{"ACE_PGD6_PG_STS",              BIT(17)}, +	{"ACE_PGD7_PG_STS",              BIT(18)}, +	{"ACE_PGD8_PG_STS",              BIT(19)}, +	{"FIA_PGS_PGD0_PG_STS",          BIT(20)}, +	{"FIACPCB_PGS_PGD0_PG_STS",      BIT(21)}, +	{"FUSEPMSB_PGD0_PG_STS",         BIT(22)}, +	{} +}; + +const struct pmc_bit_map mtl_socm_d3_status_0_map[] = { +	{"LPSS_D3_STS",                  BIT(3)}, +	{"XDCI_D3_STS",                  BIT(4)}, +	{"XHCI_D3_STS",                  BIT(5)}, +	{"SPA_D3_STS",                   BIT(12)}, +	{"SPB_D3_STS",                   BIT(13)}, +	{"SPC_D3_STS",                   BIT(14)}, +	{"SPD_D3_STS",                   BIT(15)}, +	{"ESPISPI_D3_STS",               BIT(18)}, +	{"SATA_D3_STS",                  BIT(20)}, +	{"PSTH_D3_STS",                  BIT(21)}, +	{"DMI_D3_STS",                   BIT(22)}, +	{} +}; + +const struct pmc_bit_map mtl_socm_d3_status_1_map[] = { +	{"GBETSN1_D3_STS",               BIT(14)}, +	{"GBE_D3_STS",                   BIT(19)}, +	{"ITSS_D3_STS",                  BIT(23)}, +	{"P2S_D3_STS",                   BIT(24)}, +	{"CNVI_D3_STS",                  BIT(27)}, +	{"UFSX2_D3_STS",                 BIT(28)}, +	{} +}; + +const struct pmc_bit_map mtl_socm_d3_status_2_map[] = { +	{"GNA_D3_STS",                   BIT(0)}, +	{"CSMERTC_D3_STS",               BIT(1)}, +	{"SUSRAM_D3_STS",                BIT(2)}, +	{"CSE_D3_STS",                   BIT(4)}, +	{"KVMCC_D3_STS",                 BIT(5)}, +	{"USBR0_D3_STS",                 BIT(6)}, +	{"ISH_D3_STS",                   BIT(7)}, +	{"SMT1_D3_STS",                  BIT(8)}, +	{"SMT2_D3_STS",                  BIT(9)}, +	{"SMT3_D3_STS",                  BIT(10)}, +	{"CLINK_D3_STS",                 BIT(14)}, +	{"PTIO_D3_STS",                  BIT(16)}, +	{"PMT_D3_STS",                   BIT(17)}, +	{"SMS1_D3_STS",                  BIT(18)}, +	{"SMS2_D3_STS",                  BIT(19)}, +	{} +}; + +const struct pmc_bit_map mtl_socm_d3_status_3_map[] = { +	{"ESE_D3_STS",                   BIT(2)}, +	{"GBETSN_D3_STS",                BIT(13)}, +	{"THC0_D3_STS",                  BIT(14)}, +	{"THC1_D3_STS",                  BIT(15)}, +	{"ACE_D3_STS",                   BIT(23)}, +	{} +}; + +const struct pmc_bit_map mtl_socm_vnn_req_status_0_map[] = { +	{"LPSS_VNN_REQ_STS",             BIT(3)}, +	{"FIA_VNN_REQ_STS",              BIT(17)}, +	{"ESPISPI_VNN_REQ_STS",          BIT(18)}, +	{} +}; + +const struct pmc_bit_map mtl_socm_vnn_req_status_1_map[] = { +	{"NPK_VNN_REQ_STS",              BIT(4)}, +	{"DFXAGG_VNN_REQ_STS",           BIT(8)}, +	{"EXI_VNN_REQ_STS",              BIT(9)}, +	{"P2D_VNN_REQ_STS",              BIT(18)}, +	{"GBE_VNN_REQ_STS",              BIT(19)}, +	{"SMB_VNN_REQ_STS",              BIT(25)}, +	{"LPC_VNN_REQ_STS",              BIT(26)}, +	{} +}; + +const struct pmc_bit_map mtl_socm_vnn_req_status_2_map[] = { +	{"CSMERTC_VNN_REQ_STS",          BIT(1)}, +	{"CSE_VNN_REQ_STS",              BIT(4)}, +	{"ISH_VNN_REQ_STS",              BIT(7)}, +	{"SMT1_VNN_REQ_STS",             BIT(8)}, +	{"CLINK_VNN_REQ_STS",            BIT(14)}, +	{"SMS1_VNN_REQ_STS",             BIT(18)}, +	{"SMS2_VNN_REQ_STS",             BIT(19)}, +	{"GPIOCOM4_VNN_REQ_STS",         BIT(20)}, +	{"GPIOCOM3_VNN_REQ_STS",         BIT(21)}, +	{"GPIOCOM2_VNN_REQ_STS",         BIT(22)}, +	{"GPIOCOM1_VNN_REQ_STS",         BIT(23)}, +	{"GPIOCOM0_VNN_REQ_STS",         BIT(24)}, +	{} +}; + +const struct pmc_bit_map mtl_socm_vnn_req_status_3_map[] = { +	{"ESE_VNN_REQ_STS",              BIT(2)}, +	{"DTS0_VNN_REQ_STS",             BIT(7)}, +	{"GPIOCOM5_VNN_REQ_STS",         BIT(11)}, +	{} +}; + +const struct pmc_bit_map mtl_socm_vnn_misc_status_map[] = { +	{"CPU_C10_REQ_STS",              BIT(0)}, +	{"TS_OFF_REQ_STS",               BIT(1)}, +	{"PNDE_MET_REQ_STS",             BIT(2)}, +	{"PCIE_DEEP_PM_REQ_STS",         BIT(3)}, +	{"PMC_CLK_THROTTLE_EN_REQ_STS",  BIT(4)}, +	{"NPK_VNNAON_REQ_STS",           BIT(5)}, +	{"VNN_SOC_REQ_STS",              BIT(6)}, +	{"ISH_VNNAON_REQ_STS",           BIT(7)}, +	{"IOE_COND_MET_S02I2_0_REQ_STS", BIT(8)}, +	{"IOE_COND_MET_S02I2_1_REQ_STS", BIT(9)}, +	{"IOE_COND_MET_S02I2_2_REQ_STS", BIT(10)}, +	{"PLT_GREATER_REQ_STS",          BIT(11)}, +	{"PCIE_CLKREQ_REQ_STS",          BIT(12)}, +	{"PMC_IDLE_FB_OCP_REQ_STS",      BIT(13)}, +	{"PM_SYNC_STATES_REQ_STS",       BIT(14)}, +	{"EA_REQ_STS",                   BIT(15)}, +	{"MPHY_CORE_OFF_REQ_STS",        BIT(16)}, +	{"BRK_EV_EN_REQ_STS",            BIT(17)}, +	{"AUTO_DEMO_EN_REQ_STS",         BIT(18)}, +	{"ITSS_CLK_SRC_REQ_STS",         BIT(19)}, +	{"LPC_CLK_SRC_REQ_STS",          BIT(20)}, +	{"ARC_IDLE_REQ_STS",             BIT(21)}, +	{"MPHY_SUS_REQ_STS",             BIT(22)}, +	{"FIA_DEEP_PM_REQ_STS",          BIT(23)}, +	{"UXD_CONNECTED_REQ_STS",        BIT(24)}, +	{"ARC_INTERRUPT_WAKE_REQ_STS",   BIT(25)}, +	{"USB2_VNNAON_ACT_REQ_STS",      BIT(26)}, +	{"PRE_WAKE0_REQ_STS",            BIT(27)}, +	{"PRE_WAKE1_REQ_STS",            BIT(28)}, +	{"PRE_WAKE2_EN_REQ_STS",         BIT(29)}, +	{"WOV_REQ_STS",                  BIT(30)}, +	{"CNVI_V1P05_REQ_STS",           BIT(31)}, +	{} +}; + +const struct pmc_bit_map mtl_socm_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)}, +	{"LPSS_Wake0_En_STS",            BIT(16)}, +	{"LPSS_Wake0_Pol_STS",           BIT(17)}, +	{"LPSS_Wake1_En_STS",            BIT(18)}, +	{"LPSS_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 *mtl_socm_lpm_maps[] = { +	mtl_socm_clocksource_status_map, +	mtl_socm_power_gating_status_0_map, +	mtl_socm_power_gating_status_1_map, +	mtl_socm_power_gating_status_2_map, +	mtl_socm_d3_status_0_map, +	mtl_socm_d3_status_1_map, +	mtl_socm_d3_status_2_map, +	mtl_socm_d3_status_3_map, +	mtl_socm_vnn_req_status_0_map, +	mtl_socm_vnn_req_status_1_map, +	mtl_socm_vnn_req_status_2_map, +	mtl_socm_vnn_req_status_3_map, +	mtl_socm_vnn_misc_status_map, +	mtl_socm_signal_status_map, +	NULL +}; + +const struct pmc_reg_map mtl_socm_reg_map = { +	.pfear_sts = ext_mtl_socm_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 = adl_ltr_show_map, +	.ltr_show_sts = mtl_socm_ltr_show_map,  	.msr_sts = msr_map,  	.ltr_ignore_offset = CNP_PMC_LTR_IGNORE_OFFSET, -	.regmap_length = CNP_PMC_MMIO_REG_LEN, +	.regmap_length = MTL_SOC_PMC_MMIO_REG_LEN,  	.ppfear0_offset = CNP_PMC_HOST_PPFEAR0A, -	.ppfear_buckets = ICL_PPFEAR_NUM_ENTRIES, +	.ppfear_buckets = MTL_SOCM_PPFEAR_NUM_ENTRIES,  	.pm_cfg_offset = CNP_PMC_PM_CFG_OFFSET,  	.pm_read_disable_bit = CNP_PMC_READ_DISABLE_BIT, -	.ltr_ignore_max = ADL_NUM_IP_IGN_ALLOWED, -	.lpm_num_modes = ADL_LPM_NUM_MODES,  	.lpm_num_maps = ADL_LPM_NUM_MAPS, +	.ltr_ignore_max = MTL_SOCM_NUM_IP_IGN_ALLOWED,  	.lpm_res_counter_step_x2 = TGL_PMC_LPM_RES_COUNTER_STEP_X2,  	.etr3_offset = ETR3_OFFSET,  	.lpm_sts_latch_en_offset = MTL_LPM_STATUS_LATCH_EN_OFFSET,  	.lpm_priority_offset = MTL_LPM_PRI_OFFSET,  	.lpm_en_offset = MTL_LPM_EN_OFFSET,  	.lpm_residency_offset = MTL_LPM_RESIDENCY_OFFSET, -	.lpm_sts = adl_lpm_maps, +	.lpm_sts = mtl_socm_lpm_maps,  	.lpm_status_offset = MTL_LPM_STATUS_OFFSET,  	.lpm_live_status_offset = MTL_LPM_LIVE_STATUS_OFFSET,  }; -void mtl_core_configure(struct pmc_dev *pmcdev) -{ -	/* 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); -} +const struct pmc_bit_map mtl_ioep_pfear_map[] = { +	{"PMC_0",               BIT(0)}, +	{"OPI",                 BIT(1)}, +	{"TCSS",                BIT(2)}, +	{"RSVD3",               BIT(3)}, +	{"SPA",                 BIT(4)}, +	{"SPB",                 BIT(5)}, +	{"SPC",                 BIT(6)}, +	{"IOE_D2D_3",           BIT(7)}, + +	{"RSVD8",               BIT(0)}, +	{"RSVD9",               BIT(1)}, +	{"SPE",                 BIT(2)}, +	{"RSVD11",              BIT(3)}, +	{"RSVD12",              BIT(4)}, +	{"SPD",                 BIT(5)}, +	{"ACE_7",               BIT(6)}, +	{"RSVD15",              BIT(7)}, + +	{"ACE_0",               BIT(0)}, +	{"FIACPCB_P",           BIT(1)}, +	{"P2S",                 BIT(2)}, +	{"RSVD19",              BIT(3)}, +	{"ACE_8",               BIT(4)}, +	{"IOE_D2D_0",           BIT(5)}, +	{"FUSE",                BIT(6)}, +	{"RSVD23",              BIT(7)}, + +	{"FIACPCB_P5",          BIT(0)}, +	{"ACE_3",               BIT(1)}, +	{"RSF5",                BIT(2)}, +	{"ACE_2",               BIT(3)}, +	{"ACE_4",               BIT(4)}, +	{"RSVD29",              BIT(5)}, +	{"RSF10",               BIT(6)}, +	{"MPFPW5",              BIT(7)}, + +	{"PSF9",                BIT(0)}, +	{"MPFPW4",              BIT(1)}, +	{"RSVD34",              BIT(2)}, +	{"RSVD35",              BIT(3)}, +	{"RSVD36",              BIT(4)}, +	{"RSVD37",              BIT(5)}, +	{"RSVD38",              BIT(6)}, +	{"RSVD39",              BIT(7)}, + +	{"SBR0",                BIT(0)}, +	{"SBR1",                BIT(1)}, +	{"SBR2",                BIT(2)}, +	{"SBR3",                BIT(3)}, +	{"SBR4",                BIT(4)}, +	{"SBR5",                BIT(5)}, +	{"RSVD46",              BIT(6)}, +	{"RSVD47",              BIT(7)}, + +	{"RSVD48",              BIT(0)}, +	{"FIA_P5",              BIT(1)}, +	{"RSVD50",              BIT(2)}, +	{"RSVD51",              BIT(3)}, +	{"RSVD52",              BIT(4)}, +	{"RSVD53",              BIT(5)}, +	{"RSVD54",              BIT(6)}, +	{"ACE_1",               BIT(7)}, + +	{"RSVD56",              BIT(0)}, +	{"ACE_5",               BIT(1)}, +	{"RSVD58",              BIT(2)}, +	{"G5FPW1",              BIT(3)}, +	{"RSVD60",              BIT(4)}, +	{"ACE_6",               BIT(5)}, +	{"RSVD62",              BIT(6)}, +	{"GBETSN1",             BIT(7)}, + +	{"RSVD64",              BIT(0)}, +	{"FIA",                 BIT(1)}, +	{"RSVD66",              BIT(2)}, +	{"FIA_P",               BIT(3)}, +	{"TAM",                 BIT(4)}, +	{"GBETSN",              BIT(5)}, +	{"IOE_D2D_2",           BIT(6)}, +	{"IOE_D2D_1",           BIT(7)}, + +	{"SPF",                 BIT(0)}, +	{"PMC_1",               BIT(1)}, +	{} +}; + +const struct pmc_bit_map *ext_mtl_ioep_pfear_map[] = { +	mtl_ioep_pfear_map, +	NULL +}; + +const struct pmc_bit_map mtl_ioep_ltr_show_map[] = { +	{"SOUTHPORT_A",		CNP_PMC_LTR_SPA}, +	{"SOUTHPORT_B",		CNP_PMC_LTR_SPB}, +	{"SATA",		CNP_PMC_LTR_SATA}, +	{"GIGABIT_ETHERNET",	CNP_PMC_LTR_GBE}, +	{"XHCI",		CNP_PMC_LTR_XHCI}, +	{"SOUTHPORT_F",		ADL_PMC_LTR_SPF}, +	{"ME",			CNP_PMC_LTR_ME}, +	{"SATA1",		CNP_PMC_LTR_EVA}, +	{"SOUTHPORT_C",		CNP_PMC_LTR_SPC}, +	{"HD_AUDIO",		CNP_PMC_LTR_AZ}, +	{"CNV",			CNP_PMC_LTR_CNV}, +	{"LPSS",		CNP_PMC_LTR_LPSS}, +	{"SOUTHPORT_D",		CNP_PMC_LTR_SPD}, +	{"SOUTHPORT_E",		CNP_PMC_LTR_SPE}, +	{"SATA2",		CNP_PMC_LTR_CAM}, +	{"ESPI",		CNP_PMC_LTR_ESPI}, +	{"SCC",			CNP_PMC_LTR_SCC}, +	{"Reserved",		MTL_PMC_LTR_RESERVED}, +	{"UFSX2",		CNP_PMC_LTR_UFSX2}, +	{"EMMC",		CNP_PMC_LTR_EMMC}, +	{"WIGIG",		ICL_PMC_LTR_WIGIG}, +	{"THC0",		TGL_PMC_LTR_THC0}, +	{"THC1",		TGL_PMC_LTR_THC1}, +	{"SOUTHPORT_G",		MTL_PMC_LTR_SPG}, + +	/* Below two cannot be used for LTR_IGNORE */ +	{"CURRENT_PLATFORM",	CNP_PMC_LTR_CUR_PLT}, +	{"AGGREGATED_SYSTEM",	CNP_PMC_LTR_CUR_ASLT}, +	{} +}; + +const struct pmc_bit_map mtl_ioep_clocksource_status_map[] = { +	{"AON2_OFF_STS",                 BIT(0)}, +	{"AON3_OFF_STS",                 BIT(1)}, +	{"AON4_OFF_STS",                 BIT(2)}, +	{"AON5_OFF_STS",                 BIT(3)}, +	{"AON1_OFF_STS",                 BIT(4)}, +	{"TBT_PLL_OFF_STS",              BIT(5)}, +	{"TMU_PLL_OFF_STS",              BIT(6)}, +	{"BCLK_PLL_OFF_STS",             BIT(7)}, +	{"D2D_PLL_OFF_STS",              BIT(8)}, +	{"AON3_SPL_OFF_STS",             BIT(9)}, +	{"MPFPW4_0_PLL_OFF_STS",         BIT(12)}, +	{"MPFPW5_0_PLL_OFF_STS",         BIT(13)}, +	{"G5FPW_0_PLL_OFF_STS",          BIT(14)}, +	{"G5FPW_1_PLL_OFF_STS",          BIT(15)}, +	{"XTAL_AGGR_OFF_STS",            BIT(17)}, +	{"FABRIC_PLL_OFF_STS",           BIT(25)}, +	{"SOC_PLL_OFF_STS",              BIT(26)}, +	{"REF_PLL_OFF_STS",              BIT(28)}, +	{"RTC_PLL_OFF_STS",              BIT(31)}, +	{} +}; + +const struct pmc_bit_map mtl_ioep_power_gating_status_0_map[] = { +	{"PMC_PGD0_PG_STS",              BIT(0)}, +	{"DMI_PGD0_PG_STS",              BIT(1)}, +	{"TCSS_PGD0_PG_STS",             BIT(2)}, +	{"SPA_PGD0_PG_STS",              BIT(4)}, +	{"SPB_PGD0_PG_STS",              BIT(5)}, +	{"SPC_PGD0_PG_STS",              BIT(6)}, +	{"IOE_D2D_PGD3_PG_STS",          BIT(7)}, +	{"SPE_PGD0_PG_STS",              BIT(10)}, +	{"SPD_PGD0_PG_STS",              BIT(13)}, +	{"ACE_PGD7_PG_STS",              BIT(14)}, +	{"ACE_PGD0_PG_STS",              BIT(16)}, +	{"FIACPCB_P_PGD0_PG_STS",        BIT(17)}, +	{"P2S_PGD0_PG_STS",              BIT(18)}, +	{"ACE_PGD8_PG_STS",              BIT(20)}, +	{"IOE_D2D_PGD0_PG_STS",          BIT(21)}, +	{"FUSE_PGD0_PG_STS",             BIT(22)}, +	{"FIACPCB_P5_PGD0_PG_STS",       BIT(24)}, +	{"ACE_PGD3_PG_STS",              BIT(25)}, +	{"PSF5_PGD0_PG_STS",             BIT(26)}, +	{"ACE_PGD2_PG_STS",              BIT(27)}, +	{"ACE_PGD4_PG_STS",              BIT(28)}, +	{"PSF10_PGD0_PG_STS",            BIT(30)}, +	{"MPFPW5_PGD0_PG_STS",           BIT(31)}, +	{} +}; + +const struct pmc_bit_map mtl_ioep_power_gating_status_1_map[] = { +	{"PSF9_PGD0_PG_STS",             BIT(0)}, +	{"MPFPW4_PGD0_PG_STS",           BIT(1)}, +	{"SBR0_PGD0_PG_STS",             BIT(8)}, +	{"SBR1_PGD0_PG_STS",             BIT(9)}, +	{"SBR2_PGD0_PG_STS",             BIT(10)}, +	{"SBR3_PGD0_PG_STS",             BIT(11)}, +	{"SBR4_PGD0_PG_STS",             BIT(12)}, +	{"SBR5_PGD0_PG_STS",             BIT(13)}, +	{"FIA_P5_PGD0_PG_STS",           BIT(17)}, +	{"ACE_PGD1_PGD0_PG_STS",         BIT(23)}, +	{"ACE_PGD5_PGD1_PG_STS",         BIT(25)}, +	{"G5FPW1_PGD0_PG_STS",           BIT(27)}, +	{"ACE_PGD6_PG_STS",              BIT(29)}, +	{"GBETSN1_PGD0_PG_STS",          BIT(31)}, +	{} +}; + +const struct pmc_bit_map mtl_ioep_power_gating_status_2_map[] = { +	{"FIA_PGD0_PG_STS",              BIT(1)}, +	{"FIA_P_PGD0_PG_STS",            BIT(3)}, +	{"TAM_PGD0_PG_STS",              BIT(4)}, +	{"GBETSN_PGD0_PG_STS",           BIT(5)}, +	{"IOE_D2D_PGD2_PG_STS",          BIT(6)}, +	{"IOE_D2D_PGD1_PG_STS",          BIT(7)}, +	{"SPF_PGD0_PG_STS",              BIT(8)}, +	{"PMC_PGD1_PG_STS",              BIT(9)}, +	{} +}; + +const struct pmc_bit_map mtl_ioep_d3_status_0_map[] = { +	{"SPF_D3_STS",                   BIT(0)}, +	{"SPA_D3_STS",                   BIT(12)}, +	{"SPB_D3_STS",                   BIT(13)}, +	{"SPC_D3_STS",                   BIT(14)}, +	{"SPD_D3_STS",                   BIT(15)}, +	{"SPE_D3_STS",                   BIT(16)}, +	{"DMI_D3_STS",                   BIT(22)}, +	{} +}; + +const struct pmc_bit_map mtl_ioep_d3_status_1_map[] = { +	{"GBETSN1_D3_STS",               BIT(14)}, +	{"P2S_D3_STS",                   BIT(24)}, +	{} +}; + +const struct pmc_bit_map mtl_ioep_d3_status_2_map[] = { +	{} +}; + +const struct pmc_bit_map mtl_ioep_d3_status_3_map[] = { +	{"GBETSN_D3_STS",                BIT(13)}, +	{"ACE_D3_STS",                   BIT(23)}, +	{} +}; + +const struct pmc_bit_map mtl_ioep_vnn_req_status_0_map[] = { +	{"FIA_VNN_REQ_STS",              BIT(17)}, +	{} +}; + +const struct pmc_bit_map mtl_ioep_vnn_req_status_1_map[] = { +	{"DFXAGG_VNN_REQ_STS",           BIT(8)}, +	{} +}; + +const struct pmc_bit_map mtl_ioep_vnn_req_status_2_map[] = { +	{} +}; + +const struct pmc_bit_map mtl_ioep_vnn_req_status_3_map[] = { +	{"DTS0_VNN_REQ_STS",             BIT(7)}, +	{"DISP_VNN_REQ_STS",             BIT(19)}, +	{} +}; + +const struct pmc_bit_map mtl_ioep_vnn_misc_status_map[] = { +	{"CPU_C10_REQ_STS",              BIT(0)}, +	{"TS_OFF_REQ_STS",               BIT(1)}, +	{"PNDE_MET_REQ_STS",             BIT(2)}, +	{"PCIE_DEEP_PM_REQ_STS",         BIT(3)}, +	{"PMC_CLK_THROTTLE_EN_REQ_STS",  BIT(4)}, +	{"NPK_VNNAON_REQ_STS",           BIT(5)}, +	{"VNN_SOC_REQ_STS",              BIT(6)}, +	{"USB_DEVICE_ATTACHED_REQ_STS",  BIT(8)}, +	{"FIA_EXIT_REQ_STS",             BIT(9)}, +	{"USB2_SUS_PG_REQ_STS",          BIT(10)}, +	{"PLT_GREATER_REQ_STS",          BIT(11)}, +	{"PCIE_CLKREQ_REQ_STS",          BIT(12)}, +	{"PMC_IDLE_FB_OCP_REQ_STS",      BIT(13)}, +	{"PM_SYNC_STATES_REQ_STS",       BIT(14)}, +	{"EA_REQ_STS",                   BIT(15)}, +	{"MPHY_CORE_OFF_REQ_STS",        BIT(16)}, +	{"BRK_EV_EN_REQ_STS",            BIT(17)}, +	{"AUTO_DEMO_EN_REQ_STS",         BIT(18)}, +	{"ITSS_CLK_SRC_REQ_STS",         BIT(19)}, +	{"LPC_CLK_SRC_REQ_STS",          BIT(20)}, +	{"ARC_IDLE_REQ_STS",             BIT(21)}, +	{"MPHY_SUS_REQ_STS",             BIT(22)}, +	{"FIA_DEEP_PM_REQ_STS",          BIT(23)}, +	{"UXD_CONNECTED_REQ_STS",        BIT(24)}, +	{"ARC_INTERRUPT_WAKE_REQ_STS",   BIT(25)}, +	{"USB2_VNNAON_ACT_REQ_STS",      BIT(26)}, +	{"PRE_WAKE0_REQ_STS",            BIT(27)}, +	{"PRE_WAKE1_REQ_STS",            BIT(28)}, +	{"PRE_WAKE2_EN_REQ_STS",         BIT(29)}, +	{"WOV_REQ_STS",                  BIT(30)}, +	{"CNVI_V1P05_REQ_STS",           BIT(31)}, +	{} +}; + +const struct pmc_bit_map *mtl_ioep_lpm_maps[] = { +	mtl_ioep_clocksource_status_map, +	mtl_ioep_power_gating_status_0_map, +	mtl_ioep_power_gating_status_1_map, +	mtl_ioep_power_gating_status_2_map, +	mtl_ioep_d3_status_0_map, +	mtl_ioep_d3_status_1_map, +	mtl_ioep_d3_status_2_map, +	mtl_ioep_d3_status_3_map, +	mtl_ioep_vnn_req_status_0_map, +	mtl_ioep_vnn_req_status_1_map, +	mtl_ioep_vnn_req_status_2_map, +	mtl_ioep_vnn_req_status_3_map, +	mtl_ioep_vnn_misc_status_map, +	mtl_socm_signal_status_map, +	NULL +}; + +const struct pmc_reg_map mtl_ioep_reg_map = { +	.regmap_length = MTL_IOE_PMC_MMIO_REG_LEN, +	.pfear_sts = ext_mtl_ioep_pfear_map, +	.ppfear0_offset = CNP_PMC_HOST_PPFEAR0A, +	.ppfear_buckets = MTL_IOE_PPFEAR_NUM_ENTRIES, +	.lpm_status_offset = MTL_LPM_STATUS_OFFSET, +	.lpm_live_status_offset = MTL_LPM_LIVE_STATUS_OFFSET, +	.lpm_sts = mtl_ioep_lpm_maps, +	.ltr_show_sts = mtl_ioep_ltr_show_map, +	.ltr_ignore_offset = CNP_PMC_LTR_IGNORE_OFFSET, +	.ltr_ignore_max = ADL_NUM_IP_IGN_ALLOWED, +}; + +const struct pmc_bit_map mtl_ioem_pfear_map[] = { +	{"PMC_0",               BIT(0)}, +	{"OPI",                 BIT(1)}, +	{"TCSS",                BIT(2)}, +	{"RSVD3",               BIT(3)}, +	{"SPA",                 BIT(4)}, +	{"SPB",                 BIT(5)}, +	{"SPC",                 BIT(6)}, +	{"IOE_D2D_3",           BIT(7)}, + +	{"RSVD8",               BIT(0)}, +	{"RSVD9",               BIT(1)}, +	{"SPE",                 BIT(2)}, +	{"RSVD11",              BIT(3)}, +	{"RSVD12",              BIT(4)}, +	{"SPD",                 BIT(5)}, +	{"ACE_7",               BIT(6)}, +	{"RSVD15",              BIT(7)}, + +	{"ACE_0",               BIT(0)}, +	{"FIACPCB_P",           BIT(1)}, +	{"P2S",                 BIT(2)}, +	{"RSVD19",              BIT(3)}, +	{"ACE_8",               BIT(4)}, +	{"IOE_D2D_0",           BIT(5)}, +	{"FUSE",                BIT(6)}, +	{"RSVD23",              BIT(7)}, + +	{"FIACPCB_P5",          BIT(0)}, +	{"ACE_3",               BIT(1)}, +	{"RSF5",                BIT(2)}, +	{"ACE_2",               BIT(3)}, +	{"ACE_4",               BIT(4)}, +	{"RSVD29",              BIT(5)}, +	{"RSF10",               BIT(6)}, +	{"MPFPW5",              BIT(7)}, + +	{"PSF9",                BIT(0)}, +	{"MPFPW4",              BIT(1)}, +	{"RSVD34",              BIT(2)}, +	{"RSVD35",              BIT(3)}, +	{"RSVD36",              BIT(4)}, +	{"RSVD37",              BIT(5)}, +	{"RSVD38",              BIT(6)}, +	{"RSVD39",              BIT(7)}, + +	{"SBR0",                BIT(0)}, +	{"SBR1",                BIT(1)}, +	{"SBR2",                BIT(2)}, +	{"SBR3",                BIT(3)}, +	{"SBR4",                BIT(4)}, +	{"RSVD45",              BIT(5)}, +	{"RSVD46",              BIT(6)}, +	{"RSVD47",              BIT(7)}, + +	{"RSVD48",              BIT(0)}, +	{"FIA_P5",              BIT(1)}, +	{"RSVD50",              BIT(2)}, +	{"RSVD51",              BIT(3)}, +	{"RSVD52",              BIT(4)}, +	{"RSVD53",              BIT(5)}, +	{"RSVD54",              BIT(6)}, +	{"ACE_1",               BIT(7)}, + +	{"RSVD56",              BIT(0)}, +	{"ACE_5",               BIT(1)}, +	{"RSVD58",              BIT(2)}, +	{"G5FPW1",              BIT(3)}, +	{"RSVD60",              BIT(4)}, +	{"ACE_6",               BIT(5)}, +	{"RSVD62",              BIT(6)}, +	{"GBETSN1",             BIT(7)}, + +	{"RSVD64",              BIT(0)}, +	{"FIA",                 BIT(1)}, +	{"RSVD66",              BIT(2)}, +	{"FIA_P",               BIT(3)}, +	{"TAM",                 BIT(4)}, +	{"GBETSN",              BIT(5)}, +	{"IOE_D2D_2",           BIT(6)}, +	{"IOE_D2D_1",           BIT(7)}, + +	{"SPF",                 BIT(0)}, +	{"PMC_1",               BIT(1)}, +	{} +}; + +const struct pmc_bit_map *ext_mtl_ioem_pfear_map[] = { +	mtl_ioem_pfear_map, +	NULL +}; + +const struct pmc_bit_map mtl_ioem_power_gating_status_1_map[] = { +	{"PSF9_PGD0_PG_STS",                    BIT(0)}, +	{"MPFPW4_PGD0_PG_STS",                  BIT(1)}, +	{"SBR0_PGD0_PG_STS",                    BIT(8)}, +	{"SBR1_PGD0_PG_STS",                    BIT(9)}, +	{"SBR2_PGD0_PG_STS",                    BIT(10)}, +	{"SBR3_PGD0_PG_STS",                    BIT(11)}, +	{"SBR4_PGD0_PG_STS",                    BIT(12)}, +	{"FIA_P5_PGD0_PG_STS",                  BIT(17)}, +	{"ACE_PGD1_PGD0_PG_STS",                BIT(23)}, +	{"ACE_PGD5_PGD1_PG_STS",                BIT(25)}, +	{"G5FPW1_PGD0_PG_STS",                  BIT(27)}, +	{"ACE_PGD6_PG_STS",                     BIT(29)}, +	{"GBETSN1_PGD0_PG_STS",                 BIT(31)}, +	{} +}; + +const struct pmc_bit_map *mtl_ioem_lpm_maps[] = { +	mtl_ioep_clocksource_status_map, +	mtl_ioep_power_gating_status_0_map, +	mtl_ioem_power_gating_status_1_map, +	mtl_ioep_power_gating_status_2_map, +	mtl_ioep_d3_status_0_map, +	mtl_ioep_d3_status_1_map, +	mtl_ioep_d3_status_2_map, +	mtl_ioep_d3_status_3_map, +	mtl_ioep_vnn_req_status_0_map, +	mtl_ioep_vnn_req_status_1_map, +	mtl_ioep_vnn_req_status_2_map, +	mtl_ioep_vnn_req_status_3_map, +	mtl_ioep_vnn_misc_status_map, +	mtl_socm_signal_status_map, +	NULL +}; + +const struct pmc_reg_map mtl_ioem_reg_map = { +	.regmap_length = MTL_IOE_PMC_MMIO_REG_LEN, +	.pfear_sts = ext_mtl_ioem_pfear_map, +	.ppfear0_offset = CNP_PMC_HOST_PPFEAR0A, +	.ppfear_buckets = MTL_IOE_PPFEAR_NUM_ENTRIES, +	.lpm_status_offset = MTL_LPM_STATUS_OFFSET, +	.lpm_live_status_offset = MTL_LPM_LIVE_STATUS_OFFSET, +	.lpm_sts = mtl_ioem_lpm_maps, +	.ltr_show_sts = mtl_ioep_ltr_show_map, +	.ltr_ignore_offset = CNP_PMC_LTR_IGNORE_OFFSET, +	.ltr_ignore_max = ADL_NUM_IP_IGN_ALLOWED, +}; + +#define PMC_DEVID_SOCM	0x7e7f +#define PMC_DEVID_IOEP	0x7ecf +#define PMC_DEVID_IOEM	0x7ebf +static struct pmc_info mtl_pmc_info_list[] = { +	{ +		.devid = PMC_DEVID_SOCM, +		.map = &mtl_socm_reg_map, +	}, +	{ +		.devid = PMC_DEVID_IOEP, +		.map = &mtl_ioep_reg_map, +	}, +	{ +		.devid = PMC_DEVID_IOEM, +		.map = &mtl_ioem_reg_map +	}, +	{} +};  #define MTL_GNA_PCI_DEV	0x7e4c  #define MTL_IPU_PCI_DEV	0x7d19 @@ -68,16 +965,48 @@ static void mtl_set_device_d3(unsigned int device)  	}  } -void mtl_core_init(struct pmc_dev *pmcdev) +/* + * Set power state of select devices that do not have drivers to D3 + * so that they do not block Package C entry. + */ +static void mtl_d3_fixup(void)  { -	pmcdev->map = &mtl_reg_map; -	pmcdev->core_configure = mtl_core_configure; - -	/* -	 * Set power state of select devices that do not have drivers to D3 -	 * so that they do not block Package C entry. -	 */  	mtl_set_device_d3(MTL_GNA_PCI_DEV);  	mtl_set_device_d3(MTL_IPU_PCI_DEV);  	mtl_set_device_d3(MTL_VPU_PCI_DEV);  } + +static int mtl_resume(struct pmc_dev *pmcdev) +{ +	mtl_d3_fixup(); +	return pmc_core_resume_common(pmcdev); +} + +int mtl_core_init(struct pmc_dev *pmcdev) +{ +	struct pmc *pmc = pmcdev->pmcs[PMC_IDX_SOC]; +	int ret = 0; + +	mtl_d3_fixup(); + +	pmcdev->resume = mtl_resume; + +	pmcdev->regmap_list = mtl_pmc_info_list; +	pmc_core_ssram_init(pmcdev); + +	/* If regbase not assigned, set map and discover using legacy method */ +	if (!pmc->regbase) { +		pmc->map = &mtl_socm_reg_map; +		ret = get_primary_reg_base(pmc); +		if (ret) +			return ret; +	} + +	/* 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); + +	return 0; +} diff --git a/drivers/platform/x86/intel/pmc/spt.c b/drivers/platform/x86/intel/pmc/spt.c index e16982236778..4b6f5cbda16c 100644 --- a/drivers/platform/x86/intel/pmc/spt.c +++ b/drivers/platform/x86/intel/pmc/spt.c @@ -134,7 +134,10 @@ const struct pmc_reg_map spt_reg_map = {  	.pm_vric1_offset = SPT_PMC_VRIC1_OFFSET,  }; -void spt_core_init(struct pmc_dev *pmcdev) +int spt_core_init(struct pmc_dev *pmcdev)  { -	pmcdev->map = &spt_reg_map; +	struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN]; + +	pmc->map = &spt_reg_map; +	return get_primary_reg_base(pmc);  } diff --git a/drivers/platform/x86/intel/pmc/tgl.c b/drivers/platform/x86/intel/pmc/tgl.c index c245ada849d0..2449940102db 100644 --- a/drivers/platform/x86/intel/pmc/tgl.c +++ b/drivers/platform/x86/intel/pmc/tgl.c @@ -208,7 +208,8 @@ const struct pmc_reg_map tgl_reg_map = {  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; +	struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN]; +	const int num_maps = pmc->map->lpm_num_maps;  	u32 lpm_size = LPM_MAX_NUM_MODES * num_maps * 4;  	union acpi_object *out_obj;  	struct acpi_device *adev; @@ -246,24 +247,28 @@ void pmc_core_get_tgl_lpm_reqs(struct platform_device *pdev)  		goto free_acpi_obj;  	memcpy(lpm_req_regs, addr, lpm_size); -	pmcdev->lpm_req_regs = lpm_req_regs; +	pmc->lpm_req_regs = lpm_req_regs;  free_acpi_obj:  	ACPI_FREE(out_obj);  } -void tgl_core_configure(struct pmc_dev *pmcdev) +int tgl_core_init(struct pmc_dev *pmcdev)  { +	struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN]; +	int ret; + +	pmc->map = &tgl_reg_map; +	ret = get_primary_reg_base(pmc); +	if (ret) +		return ret; +  	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; +	return 0;  }  |