[PATCH 1/3] PMC driver: Add Cherrytrail PMC interface

From: Mahesh Kumar P
Date: Wed Nov 05 2014 - 11:41:42 EST


The patch adds CHT PMC interface. This exposes all the South IP
device power states and S0ix states for CHT.
The bit map of FUNC_DIS and D3_STS registers for SOCs are
consistent. The D3_STS1 and FUNC_DIS2 registers, however
are not aligned. This is fixed by adding an extra field,
fn_dis bit, in the dev_map. Any deviations in these registers
should be addressed in this manner.

Signed-off-by: Kumar P Mahesh <mahesh.kumar.p@xxxxxxxxx>
Signed-off-by: Aubrey Li <aubrey.li@xxxxxxxxx>
Acked-by: Alan Cox <alan@xxxxxxxxxxxxxxx>
---
arch/x86/include/asm/pmc_atom.h | 30 ++++++++++----
arch/x86/kernel/pmc_atom.c | 87 +++++++++++++++++++++++++++++++++------
2 files changed, 98 insertions(+), 19 deletions(-)

diff --git a/arch/x86/include/asm/pmc_atom.h b/arch/x86/include/asm/pmc_atom.h
index fc7a17c..581ad43 100644
--- a/arch/x86/include/asm/pmc_atom.h
+++ b/arch/x86/include/asm/pmc_atom.h
@@ -17,7 +17,10 @@
#define PMC_ATOM_H

/* ValleyView Power Control Unit PCI Device ID */
-#define PCI_DEVICE_ID_VLV_PMC 0x0F1C
+#define PCI_DEVICE_ID_BYT_PMC 0x0F1C
+/* CherryTrail Power Control Unit PCI Device ID */
+#define PCI_DEVICE_ID_CHT_PMC 0x229C
+

/* PMC Memory mapped IO registers */
#define PMC_BASE_ADDR_OFFSET 0x44
@@ -25,9 +28,6 @@
#define PMC_MMIO_REG_LEN 0x100
#define PMC_REG_BIT_WIDTH 32

-/* BIOS uses FUNC_DIS to disable specific function */
-#define PMC_FUNC_DIS 0x34
-#define PMC_FUNC_DIS_2 0x38

/* S0ix wake event control */
#define PMC_S0IX_WAKE_EN 0x3C
@@ -56,6 +56,7 @@
/* These registers reflect D3 status of functions */
#define PMC_D3_STS_0 0xA0

+/* common bit definition */
#define BIT_LPSS1_F0_DMA BIT(0)
#define BIT_LPSS1_F1_PWM1 BIT(1)
#define BIT_LPSS1_F2_PWM2 BIT(2)
@@ -91,9 +92,24 @@

#define PMC_D3_STS_1 0xA4
#define BIT_SMB BIT(0)
-#define BIT_OTG_SS_PHY BIT(1)
-#define BIT_USH_SS_PHY BIT(2)
-#define BIT_DFX BIT(3)
+
+/*BYT specific bits in PMC_D3_STS_1 register*/
+#define BIT_OTG_SS_PHY_BYT BIT(1)
+#define BIT_USH_SS_PHY_BYT BIT(2)
+#define BIT_DFX_BYT BIT(3)
+
+/*CHT specific bits in PMC_D3_STS_1 register*/
+#define BIT_GMM_CHT BIT(1)
+#define BIT_ISH_CHT BIT(2)
+
+/* BIOS uses FUNC_DIS to disable specific function */
+#define PMC_FUNC_DIS 0x34
+#define PMC_FUNC_DIS_2 0x38
+
+/*CHT specific bits in FUNC_DIS2 register*/
+#define BIT_GMM_FD_CHT BIT(3)
+#define BIT_ISH_FD_CHT BIT(4)
+

/* PMC I/O Registers */
#define ACPI_BASE_ADDR_OFFSET 0x40
diff --git a/arch/x86/kernel/pmc_atom.c b/arch/x86/kernel/pmc_atom.c
index 0c424a6..822fb6a 100644
--- a/arch/x86/kernel/pmc_atom.c
+++ b/arch/x86/kernel/pmc_atom.c
@@ -40,10 +40,13 @@ static u32 acpi_base_addr;

struct pmc_dev_map {
const char *name;
- u32 bit_mask;
+ u32 d3_sts_bit;
+ u32 fn_dis_bit;
};

-static const struct pmc_dev_map dev_map[] = {
+static struct pmc_dev_map *dev_map;
+static int dev_num;
+static struct pmc_dev_map byt_dev_map[] = {
{"0 - LPSS1_F0_DMA", BIT_LPSS1_F0_DMA},
{"1 - LPSS1_F1_PWM1", BIT_LPSS1_F1_PWM1},
{"2 - LPSS1_F2_PWM2", BIT_LPSS1_F2_PWM2},
@@ -77,9 +80,47 @@ static const struct pmc_dev_map dev_map[] = {
{"30 - LPSS2_F6_I2C6", BIT_LPSS2_F6_I2C6},
{"31 - LPSS2_F7_I2C7", BIT_LPSS2_F7_I2C7},
{"32 - SMB", BIT_SMB},
- {"33 - OTG_SS_PHY", BIT_OTG_SS_PHY},
- {"34 - USH_SS_PHY", BIT_USH_SS_PHY},
- {"35 - DFX", BIT_DFX},
+ {"33 - OTG_SS_PHY", BIT_OTG_SS_PHY_BYT},
+ {"34 - USH_SS_PHY", BIT_USH_SS_PHY_BYT},
+ {"35 - DFX", BIT_DFX_BYT},
+};
+
+static struct pmc_dev_map cht_dev_map[] = {
+ {"0 - LPSS1_F0_DMA", BIT_LPSS1_F0_DMA},
+ {"1 - LPSS1_F1_PWM1", BIT_LPSS1_F1_PWM1},
+ {"2 - LPSS1_F2_PWM2", BIT_LPSS1_F2_PWM2},
+ {"3 - LPSS1_F3_HSUART1", BIT_LPSS1_F3_HSUART1},
+ {"4 - LPSS1_F4_HSUART2", BIT_LPSS1_F4_HSUART2},
+ {"5 - LPSS1_F5_SPI", BIT_LPSS1_F5_SPI},
+ {"6 - LPSS1_F6_Reserved", BIT_LPSS1_F6_XXX},
+ {"7 - LPSS1_F7_Reserved", BIT_LPSS1_F7_XXX},
+ {"8 - SCC_EMMC", BIT_SCC_EMMC},
+ {"9 - SCC_SDIO", BIT_SCC_SDIO},
+ {"10 - SCC_SDCARD", BIT_SCC_SDCARD},
+ {"11 - SCC_MIPI", BIT_SCC_MIPI},
+ {"12 - HDA", BIT_HDA},
+ {"13 - LPE", BIT_LPE},
+ {"14 - OTG", BIT_OTG},
+ {"15 - USH", BIT_USH},
+ {"16 - GBE", BIT_GBE},
+ {"17 - SATA", BIT_SATA},
+ {"18 - USB_XHCI", BIT_USB_EHCI},
+ {"19 - SEC", BIT_SEC},
+ {"20 - PCIE_PORT0", BIT_PCIE_PORT0},
+ {"21 - PCIE_PORT1", BIT_PCIE_PORT1},
+ {"22 - PCIE_PORT2", BIT_PCIE_PORT2},
+ {"23 - PCIE_PORT3", BIT_PCIE_PORT3},
+ {"24 - LPSS2_F0_DMA", BIT_LPSS2_F0_DMA},
+ {"25 - LPSS2_F1_I2C1", BIT_LPSS2_F1_I2C1},
+ {"26 - LPSS2_F2_I2C2", BIT_LPSS2_F2_I2C2},
+ {"27 - LPSS2_F3_I2C3", BIT_LPSS2_F3_I2C3},
+ {"28 - LPSS2_F3_I2C4", BIT_LPSS2_F4_I2C4},
+ {"29 - LPSS2_F5_I2C5", BIT_LPSS2_F5_I2C5},
+ {"30 - LPSS2_F6_I2C6", BIT_LPSS2_F6_I2C6},
+ {"31 - LPSS2_F7_I2C7", BIT_LPSS2_F7_I2C7},
+ {"32 - SMB", BIT_SMB},
+ {"33 - GMM", BIT_GMM_CHT, BIT_GMM_FD_CHT},
+ {"34 - ISH", BIT_ISH_CHT, BIT_ISH_FD_CHT},
};

static inline u32 pmc_reg_read(struct pmc_dev *pmc, int reg_offset)
@@ -128,30 +169,33 @@ static int pmc_dev_state_show(struct seq_file *s, void *unused)
struct pmc_dev *pmc = s->private;
u32 func_dis, func_dis_2, func_dis_index;
u32 d3_sts_0, d3_sts_1, d3_sts_index;
- int dev_num, dev_index, reg_index;
+ int dev_index, reg_index;

func_dis = pmc_reg_read(pmc, PMC_FUNC_DIS);
func_dis_2 = pmc_reg_read(pmc, PMC_FUNC_DIS_2);
d3_sts_0 = pmc_reg_read(pmc, PMC_D3_STS_0);
d3_sts_1 = pmc_reg_read(pmc, PMC_D3_STS_1);

- dev_num = ARRAY_SIZE(dev_map);

for (dev_index = 0; dev_index < dev_num; dev_index++) {
reg_index = dev_index / PMC_REG_BIT_WIDTH;
+
+
if (reg_index) {
- func_dis_index = func_dis_2;
+ func_dis_index =
+ (func_dis_2 & dev_map[dev_index].fn_dis_bit);
d3_sts_index = d3_sts_1;
} else {
- func_dis_index = func_dis;
+ func_dis_index =
+ func_dis & dev_map[dev_index].fn_dis_bit;
d3_sts_index = d3_sts_0;
}

seq_printf(s, "Dev: %-32s\tState: %s [%s]\n",
dev_map[dev_index].name,
- dev_map[dev_index].bit_mask & func_dis_index ?
+ func_dis_index ?
"Disabled" : "Enabled ",
- dev_map[dev_index].bit_mask & d3_sts_index ?
+ dev_map[dev_index].d3_sts_bit & d3_sts_index ?
"D3" : "D0");
}
return 0;
@@ -241,6 +285,7 @@ static int pmc_setup_dev(struct pci_dev *pdev)
{
struct pmc_dev *pmc = &pmc_device;
int ret;
+ int dev_index, reg_index;

/* Obtain ACPI base address */
pci_read_config_dword(pdev, ACPI_BASE_ADDR_OFFSET, &acpi_base_addr);
@@ -262,6 +307,13 @@ static int pmc_setup_dev(struct pci_dev *pdev)
/* PMC hardware registers setup */
pmc_hw_reg_setup(pmc);

+ for (dev_index = 0; dev_index < dev_num; dev_index++) {
+ reg_index = dev_index / PMC_REG_BIT_WIDTH;
+ if (!dev_map[dev_index].fn_dis_bit)
+ dev_map[dev_index].fn_dis_bit =
+ dev_map[dev_index].d3_sts_bit;
+ }
+
#ifdef CONFIG_DEBUG_FS
ret = pmc_dbgfs_register(pmc, pdev);
if (ret) {
@@ -281,7 +333,8 @@ static int pmc_setup_dev(struct pci_dev *pdev)
* a driver on the same PCI id.
*/
static const struct pci_device_id pmc_pci_ids[] = {
- { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_VLV_PMC) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_BYT_PMC) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_CHT_PMC) },
{ 0, },
};

@@ -304,6 +357,16 @@ static int __init pmc_atom_init(void)
for_each_pci_dev(pdev) {
ent = pci_match_id(pmc_pci_ids, pdev);
if (ent) {
+ switch (ent->device) {
+ case PCI_DEVICE_ID_BYT_PMC:
+ dev_map = byt_dev_map;
+ dev_num = ARRAY_SIZE(byt_dev_map);
+ break;
+ case PCI_DEVICE_ID_CHT_PMC:
+ dev_map = cht_dev_map;
+ dev_num = ARRAY_SIZE(cht_dev_map);
+ break;
+ }
err = pmc_setup_dev(pdev);
goto out;
}
--
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/