Skip to content

Commit

Permalink
platform/x86: intel/pmc: Replace all the reg_map with init functions
Browse files Browse the repository at this point in the history
The current implementation of pmc core driver has the reg_map assigned
to the CPUID of each platform. Replace the reg_map with init functions
that are defined for each platform.

This is a preparatory patch for redesigning the pmc core driver.

Cc: David E Box <david.e.box@linux.intel.com>
Reviewed-by: "David E. Box" <david.e.box@linux.intel.com>
Signed-off-by: Gayatri Kammela <gayatri.kammela@linux.intel.com>
Signed-off-by: "David E. Box" <david.e.box@linux.intel.com>
Link: https://lore.kernel.org/r/20221114183257.2067662-2-gayatri.kammela@linux.intel.com
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
  • Loading branch information
Gayatri Kammela authored and Hans de Goede committed Nov 21, 2022
1 parent 260ad3d commit 284c01b
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 37 deletions.
114 changes: 77 additions & 37 deletions drivers/platform/x86/intel/pmc/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
#include <linux/io.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/suspend.h>
#include <linux/uaccess.h>
Expand Down Expand Up @@ -1895,27 +1894,73 @@ static void pmc_core_dbgfs_register(struct pmc_dev *pmcdev)
}
}

void spt_core_init(struct pmc_dev *pmcdev)
{
pmcdev->map = &spt_reg_map;
}

void cnp_core_init(struct pmc_dev *pmcdev)
{
pmcdev->map = &cnp_reg_map;
}

void icl_core_init(struct pmc_dev *pmcdev)
{
pmcdev->map = &icl_reg_map;
}

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

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

void adl_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);
}

void adl_core_init(struct pmc_dev *pmcdev)
{
pmcdev->map = &adl_reg_map;
pmcdev->core_configure = adl_core_configure;
}

static const struct x86_cpu_id intel_pmc_core_ids[] = {
X86_MATCH_INTEL_FAM6_MODEL(SKYLAKE_L, &spt_reg_map),
X86_MATCH_INTEL_FAM6_MODEL(SKYLAKE, &spt_reg_map),
X86_MATCH_INTEL_FAM6_MODEL(KABYLAKE_L, &spt_reg_map),
X86_MATCH_INTEL_FAM6_MODEL(KABYLAKE, &spt_reg_map),
X86_MATCH_INTEL_FAM6_MODEL(CANNONLAKE_L, &cnp_reg_map),
X86_MATCH_INTEL_FAM6_MODEL(ICELAKE_L, &icl_reg_map),
X86_MATCH_INTEL_FAM6_MODEL(ICELAKE_NNPI, &icl_reg_map),
X86_MATCH_INTEL_FAM6_MODEL(COMETLAKE, &cnp_reg_map),
X86_MATCH_INTEL_FAM6_MODEL(COMETLAKE_L, &cnp_reg_map),
X86_MATCH_INTEL_FAM6_MODEL(TIGERLAKE_L, &tgl_reg_map),
X86_MATCH_INTEL_FAM6_MODEL(TIGERLAKE, &tgl_reg_map),
X86_MATCH_INTEL_FAM6_MODEL(ATOM_TREMONT, &tgl_reg_map),
X86_MATCH_INTEL_FAM6_MODEL(ATOM_TREMONT_L, &icl_reg_map),
X86_MATCH_INTEL_FAM6_MODEL(ROCKETLAKE, &tgl_reg_map),
X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE_L, &tgl_reg_map),
X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE_N, &tgl_reg_map),
X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE, &adl_reg_map),
X86_MATCH_INTEL_FAM6_MODEL(RAPTORLAKE_P, &tgl_reg_map),
X86_MATCH_INTEL_FAM6_MODEL(RAPTORLAKE, &adl_reg_map),
X86_MATCH_INTEL_FAM6_MODEL(RAPTORLAKE_S, &adl_reg_map),
X86_MATCH_INTEL_FAM6_MODEL(SKYLAKE_L, spt_core_init),
X86_MATCH_INTEL_FAM6_MODEL(SKYLAKE, spt_core_init),
X86_MATCH_INTEL_FAM6_MODEL(KABYLAKE_L, spt_core_init),
X86_MATCH_INTEL_FAM6_MODEL(KABYLAKE, spt_core_init),
X86_MATCH_INTEL_FAM6_MODEL(CANNONLAKE_L, cnp_core_init),
X86_MATCH_INTEL_FAM6_MODEL(ICELAKE_L, icl_core_init),
X86_MATCH_INTEL_FAM6_MODEL(ICELAKE_NNPI, icl_core_init),
X86_MATCH_INTEL_FAM6_MODEL(COMETLAKE, cnp_core_init),
X86_MATCH_INTEL_FAM6_MODEL(COMETLAKE_L, cnp_core_init),
X86_MATCH_INTEL_FAM6_MODEL(TIGERLAKE_L, tgl_core_init),
X86_MATCH_INTEL_FAM6_MODEL(TIGERLAKE, tgl_core_init),
X86_MATCH_INTEL_FAM6_MODEL(ATOM_TREMONT, tgl_core_init),
X86_MATCH_INTEL_FAM6_MODEL(ATOM_TREMONT_L, icl_core_init),
X86_MATCH_INTEL_FAM6_MODEL(ROCKETLAKE, tgl_core_init),
X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE_L, tgl_core_init),
X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE_N, tgl_core_init),
X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE, adl_core_init),
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),
{}
};

Expand Down Expand Up @@ -1975,6 +2020,7 @@ 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;

if (device_initialized)
Expand All @@ -1985,20 +2031,25 @@ static int pmc_core_probe(struct platform_device *pdev)
return -ENOMEM;

platform_set_drvdata(pdev, pmcdev);
pmcdev->pdev = pdev;

cpu_id = x86_match_cpu(intel_pmc_core_ids);
if (!cpu_id)
return -ENODEV;

pmcdev->map = (struct pmc_reg_map *)cpu_id->driver_data;
core_init = (void (*)(struct pmc_dev *))cpu_id->driver_data;

/*
* Coffee Lake has CPU ID of Kaby Lake and Cannon Lake PCH. So here
* Sunrisepoint PCH regmap can't be used. Use Cannon Lake PCH regmap
* in this case.
*/
if (pmcdev->map == &spt_reg_map && !pci_dev_present(pmc_pci_ids))
pmcdev->map = &cnp_reg_map;
if (core_init == spt_core_init && !pci_dev_present(pmc_pci_ids))
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;
Expand All @@ -2014,24 +2065,13 @@ static int pmc_core_probe(struct platform_device *pdev)
if (!pmcdev->regbase)
return -ENOMEM;

mutex_init(&pmcdev->lock);
if (pmcdev->core_configure)
pmcdev->core_configure(pmcdev);

pmcdev->pmc_xram_read_bit = pmc_core_check_read_lock_bit(pmcdev);
pmc_core_get_low_power_modes(pdev);
pmc_core_do_dmi_quirks(pmcdev);

if (pmcdev->map == &tgl_reg_map)
pmc_core_get_tgl_lpm_reqs(pdev);

/*
* On TGL and ADL, due to a hardware limitation, the GBE LTR blocks PC10
* when a cable is attached. Tell the PMC to ignore it.
*/
if (pmcdev->map == &tgl_reg_map || pmcdev->map == &adl_reg_map) {
dev_dbg(&pdev->dev, "ignoring GBE LTR\n");
pmc_core_send_ltr_ignore(pmcdev, 3);
}

pmc_core_dbgfs_register(pmcdev);

device_initialized = true;
Expand Down
13 changes: 13 additions & 0 deletions drivers/platform/x86/intel/pmc/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#define PMC_CORE_H

#include <linux/bits.h>
#include <linux/platform_device.h>

#define PMC_BASE_ADDR_DEFAULT 0xFE000000

Expand Down Expand Up @@ -312,6 +313,7 @@ struct pmc_reg_map {
* @regbase: pointer to io-remapped memory location
* @map: pointer to pmc_reg_map struct that contains platform
* specific attributes
* @pdev: pointer to platform_device struct
* @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
Expand All @@ -322,6 +324,7 @@ struct pmc_reg_map {
* @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
*
* pmc_dev contains info about power management controller device.
*/
Expand All @@ -330,6 +333,7 @@ struct pmc_dev {
void __iomem *regbase;
const struct pmc_reg_map *map;
struct dentry *dbgfs_dir;
struct platform_device *pdev;
int pmc_xram_read_bit;
struct mutex lock; /* generic mutex lock for PMC Core */

Expand All @@ -339,8 +343,17 @@ struct pmc_dev {
int num_lpm_modes;
int lpm_en_modes[LPM_MAX_NUM_MODES];
u32 *lpm_req_regs;
void (*core_configure)(struct pmc_dev *pmcdev);
};

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 tgl_core_configure(struct pmc_dev *pmcdev);
void adl_core_configure(struct pmc_dev *pmcdev);

#define pmc_for_each_mode(i, mode, pmcdev) \
for (i = 0, mode = pmcdev->lpm_en_modes[i]; \
i < pmcdev->num_lpm_modes; \
Expand Down

0 comments on commit 284c01b

Please sign in to comment.