Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c977b98b authored by Srinivas Pandruvada's avatar Srinivas Pandruvada Committed by Andy Shevchenko
Browse files

platform/x86: intel_pmc_core: Make the driver PCH family agnostic



Although this driver did pretty good job in abstracting PCH specific
interfaces, but still there are some loose ends. For example
SLP_S0 counter (for reading SLP_S0 residency), PM config offset (for
checking permissions to read XRAM) and PPFEAR offset (for reading IP
status) is still hardcoded for a specific family of PCH.

This change extended the struct pmc_reg_map to allow per family
configuration of offsets and bits.

No functional change is expected with this change. This change allows
seamless additions to new PCH and create a baseline for other platform
specific extensions.

Signed-off-by: default avatarSrinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
Signed-off-by: default avatarAndy Shevchenko <andriy.shevchenko@linux.intel.com>
parent 2cf7bdec
Loading
Loading
Loading
Loading
+21 −10
Original line number Original line Diff line number Diff line
@@ -110,6 +110,13 @@ static const struct pmc_reg_map spt_reg_map = {
	.pfear_sts = spt_pfear_map,
	.pfear_sts = spt_pfear_map,
	.mphy_sts = spt_mphy_map,
	.mphy_sts = spt_mphy_map,
	.pll_sts = spt_pll_map,
	.pll_sts = spt_pll_map,
	.slp_s0_offset = SPT_PMC_SLP_S0_RES_COUNTER_OFFSET,
	.ltr_ignore_offset = SPT_PMC_LTR_IGNORE_OFFSET,
	.regmap_length = SPT_PMC_MMIO_REG_LEN,
	.ppfear0_offset = SPT_PMC_XRAM_PPFEAR0A,
	.ppfear_buckets = SPT_PPFEAR_NUM_ENTRIES,
	.pm_cfg_offset = SPT_PMC_PM_CFG_OFFSET,
	.pm_read_disable_bit = SPT_PMC_READ_DISABLE_BIT,
};
};


static const struct pci_device_id pmc_pci_ids[] = {
static const struct pci_device_id pmc_pci_ids[] = {
@@ -157,12 +164,13 @@ static inline u32 pmc_core_adjust_slp_s0_step(u32 value)
int intel_pmc_slp_s0_counter_read(u32 *data)
int intel_pmc_slp_s0_counter_read(u32 *data)
{
{
	struct pmc_dev *pmcdev = &pmc;
	struct pmc_dev *pmcdev = &pmc;
	const struct pmc_reg_map *map = pmcdev->map;
	u32 value;
	u32 value;


	if (!pmcdev->has_slp_s0_res)
	if (!pmcdev->has_slp_s0_res)
		return -EACCES;
		return -EACCES;


	value = pmc_core_reg_read(pmcdev, SPT_PMC_SLP_S0_RES_COUNTER_OFFSET);
	value = pmc_core_reg_read(pmcdev, map->slp_s0_offset);
	*data = pmc_core_adjust_slp_s0_step(value);
	*data = pmc_core_adjust_slp_s0_step(value);


	return 0;
	return 0;
@@ -172,9 +180,10 @@ EXPORT_SYMBOL_GPL(intel_pmc_slp_s0_counter_read);
static int pmc_core_dev_state_get(void *data, u64 *val)
static int pmc_core_dev_state_get(void *data, u64 *val)
{
{
	struct pmc_dev *pmcdev = data;
	struct pmc_dev *pmcdev = data;
	const struct pmc_reg_map *map = pmcdev->map;
	u32 value;
	u32 value;


	value = pmc_core_reg_read(pmcdev, SPT_PMC_SLP_S0_RES_COUNTER_OFFSET);
	value = pmc_core_reg_read(pmcdev, map->slp_s0_offset);
	*val = pmc_core_adjust_slp_s0_step(value);
	*val = pmc_core_adjust_slp_s0_step(value);


	return 0;
	return 0;
@@ -187,8 +196,8 @@ static int pmc_core_check_read_lock_bit(void)
	struct pmc_dev *pmcdev = &pmc;
	struct pmc_dev *pmcdev = &pmc;
	u32 value;
	u32 value;


	value = pmc_core_reg_read(pmcdev, SPT_PMC_PM_CFG_OFFSET);
	value = pmc_core_reg_read(pmcdev, pmcdev->map->pm_cfg_offset);
	return value & BIT(SPT_PMC_READ_DISABLE_BIT);
	return value & BIT(pmcdev->map->pm_read_disable_bit);
}
}


#if IS_ENABLED(CONFIG_DEBUG_FS)
#if IS_ENABLED(CONFIG_DEBUG_FS)
@@ -204,12 +213,13 @@ static int pmc_core_ppfear_sts_show(struct seq_file *s, void *unused)
{
{
	struct pmc_dev *pmcdev = s->private;
	struct pmc_dev *pmcdev = s->private;
	const struct pmc_bit_map *map = pmcdev->map->pfear_sts;
	const struct pmc_bit_map *map = pmcdev->map->pfear_sts;
	u8 pf_regs[NUM_ENTRIES];
	u8 pf_regs[PPFEAR_MAX_NUM_ENTRIES];
	int index, iter;
	int index, iter;


	iter = SPT_PMC_XRAM_PPFEAR0A;
	iter = pmcdev->map->ppfear0_offset;


	for (index = 0; index < NUM_ENTRIES; index++, iter++)
	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);
		pf_regs[index] = pmc_core_reg_read_byte(pmcdev, iter);


	for (index = 0; map[index].name; index++)
	for (index = 0; map[index].name; index++)
@@ -376,6 +386,7 @@ static ssize_t pmc_core_ltr_ignore_write(struct file *file, const char __user
*userbuf, size_t count, loff_t *ppos)
*userbuf, size_t count, loff_t *ppos)
{
{
	struct pmc_dev *pmcdev = &pmc;
	struct pmc_dev *pmcdev = &pmc;
	const struct pmc_reg_map *map = pmcdev->map;
	u32 val, buf_size, fd;
	u32 val, buf_size, fd;
	int err = 0;
	int err = 0;


@@ -392,9 +403,9 @@ static ssize_t pmc_core_ltr_ignore_write(struct file *file, const char __user
		goto out_unlock;
		goto out_unlock;
	}
	}


	fd = pmc_core_reg_read(pmcdev, SPT_PMC_LTR_IGNORE_OFFSET);
	fd = pmc_core_reg_read(pmcdev, map->ltr_ignore_offset);
	fd |= (1U << val);
	fd |= (1U << val);
	pmc_core_reg_write(pmcdev, SPT_PMC_LTR_IGNORE_OFFSET, fd);
	pmc_core_reg_write(pmcdev, map->ltr_ignore_offset, fd);


out_unlock:
out_unlock:
	mutex_unlock(&pmcdev->lock);
	mutex_unlock(&pmcdev->lock);
@@ -530,8 +541,8 @@ static int pmc_core_probe(struct pci_dev *dev, const struct pci_device_id *id)
	}
	}


	mutex_init(&pmcdev->lock);
	mutex_init(&pmcdev->lock);
	pmcdev->pmc_xram_read_bit = pmc_core_check_read_lock_bit();
	pmcdev->map = map;
	pmcdev->map = map;
	pmcdev->pmc_xram_read_bit = pmc_core_check_read_lock_bit();


	err = pmc_core_dbgfs_register(pmcdev);
	err = pmc_core_dbgfs_register(pmcdev);
	if (err < 0)
	if (err < 0)
+29 −1
Original line number Original line Diff line number Diff line
@@ -38,7 +38,8 @@
#define SPT_PMC_SLP_S0_RES_COUNTER_STEP		0x64
#define SPT_PMC_SLP_S0_RES_COUNTER_STEP		0x64
#define PMC_BASE_ADDR_MASK			~(SPT_PMC_MMIO_REG_LEN - 1)
#define PMC_BASE_ADDR_MASK			~(SPT_PMC_MMIO_REG_LEN - 1)
#define MTPMC_MASK				0xffff0000
#define MTPMC_MASK				0xffff0000
#define NUM_ENTRIES				5
#define PPFEAR_MAX_NUM_ENTRIES			5
#define SPT_PPFEAR_NUM_ENTRIES			5
#define SPT_PMC_READ_DISABLE_BIT		0x16
#define SPT_PMC_READ_DISABLE_BIT		0x16
#define SPT_PMC_MSG_FULL_STS_BIT		0x18
#define SPT_PMC_MSG_FULL_STS_BIT		0x18
#define NUM_RETRIES				100
#define NUM_RETRIES				100
@@ -126,10 +127,37 @@ struct pmc_bit_map {
	u32 bit_mask;
	u32 bit_mask;
};
};


/**
 * struct pmc_reg_map - Structure used to define parameter unique to a
			PCH family
 * @pfear_sts:		Maps name of IP block to PPFEAR* bit
 * @mphy_sts:		Maps name of MPHY lane to MPHY status lane status bit
 * @pll_sts:		Maps name of PLL to corresponding bit status
 * @slp_s0_offset:	PWRMBASE offset to read SLP_S0 residency
 * @ltr_ignore_offset:	PWRMBASE offset to read/write LTR ignore bit
 * @base_address:	Base address of PWRMBASE defined in BIOS writer guide
 * @regmap_length:	Length of memory to map from PWRMBASE address to access
 * @ppfear0_offset:	PWRMBASE offset to to read PPFEAR*
 * @ppfear_buckets:	Number of 8 bits blocks to read all IP blocks from
 *			PPFEAR
 * @pm_cfg_offset:	PWRMBASE offset to PM_CFG register
 * @pm_read_disable_bit: Bit index to read PMC_READ_DISABLE
 *
 * Each PCH has unique set of register offsets and bit indexes. This structure
 * captures them to have a common implementation.
 */
struct pmc_reg_map {
struct pmc_reg_map {
	const struct pmc_bit_map *pfear_sts;
	const struct pmc_bit_map *pfear_sts;
	const struct pmc_bit_map *mphy_sts;
	const struct pmc_bit_map *mphy_sts;
	const struct pmc_bit_map *pll_sts;
	const struct pmc_bit_map *pll_sts;
	const u32 slp_s0_offset;
	const u32 ltr_ignore_offset;
	const u32 base_address;
	const int regmap_length;
	const u32 ppfear0_offset;
	const int ppfear_buckets;
	const u32 pm_cfg_offset;
	const int pm_read_disable_bit;
};
};


/**
/**