180a7581fSIrina Tirdea /* 280a7581fSIrina Tirdea * Intel Atom SOC Power Management Controller Driver 380a7581fSIrina Tirdea * Copyright (c) 2014, Intel Corporation. 480a7581fSIrina Tirdea * 580a7581fSIrina Tirdea * This program is free software; you can redistribute it and/or modify it 680a7581fSIrina Tirdea * under the terms and conditions of the GNU General Public License, 780a7581fSIrina Tirdea * version 2, as published by the Free Software Foundation. 880a7581fSIrina Tirdea * 980a7581fSIrina Tirdea * This program is distributed in the hope it will be useful, but WITHOUT 1080a7581fSIrina Tirdea * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1180a7581fSIrina Tirdea * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 1280a7581fSIrina Tirdea * more details. 1380a7581fSIrina Tirdea * 1480a7581fSIrina Tirdea */ 1580a7581fSIrina Tirdea 1680a7581fSIrina Tirdea #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 1780a7581fSIrina Tirdea 1880a7581fSIrina Tirdea #include <linux/debugfs.h> 1980a7581fSIrina Tirdea #include <linux/device.h> 2080a7581fSIrina Tirdea #include <linux/init.h> 2180a7581fSIrina Tirdea #include <linux/io.h> 2280a7581fSIrina Tirdea #include <linux/platform_data/x86/pmc_atom.h> 2380a7581fSIrina Tirdea #include <linux/pci.h> 2480a7581fSIrina Tirdea #include <linux/seq_file.h> 2580a7581fSIrina Tirdea 2680a7581fSIrina Tirdea struct pmc_bit_map { 2780a7581fSIrina Tirdea const char *name; 2880a7581fSIrina Tirdea u32 bit_mask; 2980a7581fSIrina Tirdea }; 3080a7581fSIrina Tirdea 3180a7581fSIrina Tirdea struct pmc_reg_map { 3280a7581fSIrina Tirdea const struct pmc_bit_map *d3_sts_0; 3380a7581fSIrina Tirdea const struct pmc_bit_map *d3_sts_1; 3480a7581fSIrina Tirdea const struct pmc_bit_map *func_dis; 3580a7581fSIrina Tirdea const struct pmc_bit_map *func_dis_2; 3680a7581fSIrina Tirdea const struct pmc_bit_map *pss; 3780a7581fSIrina Tirdea }; 3880a7581fSIrina Tirdea 3980a7581fSIrina Tirdea struct pmc_dev { 4080a7581fSIrina Tirdea u32 base_addr; 4180a7581fSIrina Tirdea void __iomem *regmap; 4280a7581fSIrina Tirdea const struct pmc_reg_map *map; 4380a7581fSIrina Tirdea #ifdef CONFIG_DEBUG_FS 4480a7581fSIrina Tirdea struct dentry *dbgfs_dir; 4580a7581fSIrina Tirdea #endif /* CONFIG_DEBUG_FS */ 4680a7581fSIrina Tirdea bool init; 4780a7581fSIrina Tirdea }; 4880a7581fSIrina Tirdea 4980a7581fSIrina Tirdea static struct pmc_dev pmc_device; 5080a7581fSIrina Tirdea static u32 acpi_base_addr; 5180a7581fSIrina Tirdea 5280a7581fSIrina Tirdea static const struct pmc_bit_map d3_sts_0_map[] = { 5380a7581fSIrina Tirdea {"LPSS1_F0_DMA", BIT_LPSS1_F0_DMA}, 5480a7581fSIrina Tirdea {"LPSS1_F1_PWM1", BIT_LPSS1_F1_PWM1}, 5580a7581fSIrina Tirdea {"LPSS1_F2_PWM2", BIT_LPSS1_F2_PWM2}, 5680a7581fSIrina Tirdea {"LPSS1_F3_HSUART1", BIT_LPSS1_F3_HSUART1}, 5780a7581fSIrina Tirdea {"LPSS1_F4_HSUART2", BIT_LPSS1_F4_HSUART2}, 5880a7581fSIrina Tirdea {"LPSS1_F5_SPI", BIT_LPSS1_F5_SPI}, 5980a7581fSIrina Tirdea {"LPSS1_F6_Reserved", BIT_LPSS1_F6_XXX}, 6080a7581fSIrina Tirdea {"LPSS1_F7_Reserved", BIT_LPSS1_F7_XXX}, 6180a7581fSIrina Tirdea {"SCC_EMMC", BIT_SCC_EMMC}, 6280a7581fSIrina Tirdea {"SCC_SDIO", BIT_SCC_SDIO}, 6380a7581fSIrina Tirdea {"SCC_SDCARD", BIT_SCC_SDCARD}, 6480a7581fSIrina Tirdea {"SCC_MIPI", BIT_SCC_MIPI}, 6580a7581fSIrina Tirdea {"HDA", BIT_HDA}, 6680a7581fSIrina Tirdea {"LPE", BIT_LPE}, 6780a7581fSIrina Tirdea {"OTG", BIT_OTG}, 6880a7581fSIrina Tirdea {"USH", BIT_USH}, 6980a7581fSIrina Tirdea {"GBE", BIT_GBE}, 7080a7581fSIrina Tirdea {"SATA", BIT_SATA}, 7180a7581fSIrina Tirdea {"USB_EHCI", BIT_USB_EHCI}, 7280a7581fSIrina Tirdea {"SEC", BIT_SEC}, 7380a7581fSIrina Tirdea {"PCIE_PORT0", BIT_PCIE_PORT0}, 7480a7581fSIrina Tirdea {"PCIE_PORT1", BIT_PCIE_PORT1}, 7580a7581fSIrina Tirdea {"PCIE_PORT2", BIT_PCIE_PORT2}, 7680a7581fSIrina Tirdea {"PCIE_PORT3", BIT_PCIE_PORT3}, 7780a7581fSIrina Tirdea {"LPSS2_F0_DMA", BIT_LPSS2_F0_DMA}, 7880a7581fSIrina Tirdea {"LPSS2_F1_I2C1", BIT_LPSS2_F1_I2C1}, 7980a7581fSIrina Tirdea {"LPSS2_F2_I2C2", BIT_LPSS2_F2_I2C2}, 8080a7581fSIrina Tirdea {"LPSS2_F3_I2C3", BIT_LPSS2_F3_I2C3}, 8180a7581fSIrina Tirdea {"LPSS2_F3_I2C4", BIT_LPSS2_F4_I2C4}, 8280a7581fSIrina Tirdea {"LPSS2_F5_I2C5", BIT_LPSS2_F5_I2C5}, 8380a7581fSIrina Tirdea {"LPSS2_F6_I2C6", BIT_LPSS2_F6_I2C6}, 8480a7581fSIrina Tirdea {"LPSS2_F7_I2C7", BIT_LPSS2_F7_I2C7}, 8580a7581fSIrina Tirdea {}, 8680a7581fSIrina Tirdea }; 8780a7581fSIrina Tirdea 8880a7581fSIrina Tirdea static struct pmc_bit_map byt_d3_sts_1_map[] = { 8980a7581fSIrina Tirdea {"SMB", BIT_SMB}, 9080a7581fSIrina Tirdea {"OTG_SS_PHY", BIT_OTG_SS_PHY}, 9180a7581fSIrina Tirdea {"USH_SS_PHY", BIT_USH_SS_PHY}, 9280a7581fSIrina Tirdea {"DFX", BIT_DFX}, 9380a7581fSIrina Tirdea {}, 9480a7581fSIrina Tirdea }; 9580a7581fSIrina Tirdea 9680a7581fSIrina Tirdea static struct pmc_bit_map cht_d3_sts_1_map[] = { 9780a7581fSIrina Tirdea {"SMB", BIT_SMB}, 9880a7581fSIrina Tirdea {"GMM", BIT_STS_GMM}, 9980a7581fSIrina Tirdea {"ISH", BIT_STS_ISH}, 10080a7581fSIrina Tirdea {}, 10180a7581fSIrina Tirdea }; 10280a7581fSIrina Tirdea 10380a7581fSIrina Tirdea static struct pmc_bit_map cht_func_dis_2_map[] = { 10480a7581fSIrina Tirdea {"SMB", BIT_SMB}, 10580a7581fSIrina Tirdea {"GMM", BIT_FD_GMM}, 10680a7581fSIrina Tirdea {"ISH", BIT_FD_ISH}, 10780a7581fSIrina Tirdea {}, 10880a7581fSIrina Tirdea }; 10980a7581fSIrina Tirdea 11080a7581fSIrina Tirdea static const struct pmc_bit_map byt_pss_map[] = { 11180a7581fSIrina Tirdea {"GBE", PMC_PSS_BIT_GBE}, 11280a7581fSIrina Tirdea {"SATA", PMC_PSS_BIT_SATA}, 11380a7581fSIrina Tirdea {"HDA", PMC_PSS_BIT_HDA}, 11480a7581fSIrina Tirdea {"SEC", PMC_PSS_BIT_SEC}, 11580a7581fSIrina Tirdea {"PCIE", PMC_PSS_BIT_PCIE}, 11680a7581fSIrina Tirdea {"LPSS", PMC_PSS_BIT_LPSS}, 11780a7581fSIrina Tirdea {"LPE", PMC_PSS_BIT_LPE}, 11880a7581fSIrina Tirdea {"DFX", PMC_PSS_BIT_DFX}, 11980a7581fSIrina Tirdea {"USH_CTRL", PMC_PSS_BIT_USH_CTRL}, 12080a7581fSIrina Tirdea {"USH_SUS", PMC_PSS_BIT_USH_SUS}, 12180a7581fSIrina Tirdea {"USH_VCCS", PMC_PSS_BIT_USH_VCCS}, 12280a7581fSIrina Tirdea {"USH_VCCA", PMC_PSS_BIT_USH_VCCA}, 12380a7581fSIrina Tirdea {"OTG_CTRL", PMC_PSS_BIT_OTG_CTRL}, 12480a7581fSIrina Tirdea {"OTG_VCCS", PMC_PSS_BIT_OTG_VCCS}, 12580a7581fSIrina Tirdea {"OTG_VCCA_CLK", PMC_PSS_BIT_OTG_VCCA_CLK}, 12680a7581fSIrina Tirdea {"OTG_VCCA", PMC_PSS_BIT_OTG_VCCA}, 12780a7581fSIrina Tirdea {"USB", PMC_PSS_BIT_USB}, 12880a7581fSIrina Tirdea {"USB_SUS", PMC_PSS_BIT_USB_SUS}, 12980a7581fSIrina Tirdea {}, 13080a7581fSIrina Tirdea }; 13180a7581fSIrina Tirdea 13280a7581fSIrina Tirdea static const struct pmc_bit_map cht_pss_map[] = { 13380a7581fSIrina Tirdea {"SATA", PMC_PSS_BIT_SATA}, 13480a7581fSIrina Tirdea {"HDA", PMC_PSS_BIT_HDA}, 13580a7581fSIrina Tirdea {"SEC", PMC_PSS_BIT_SEC}, 13680a7581fSIrina Tirdea {"PCIE", PMC_PSS_BIT_PCIE}, 13780a7581fSIrina Tirdea {"LPSS", PMC_PSS_BIT_LPSS}, 13880a7581fSIrina Tirdea {"LPE", PMC_PSS_BIT_LPE}, 13980a7581fSIrina Tirdea {"UFS", PMC_PSS_BIT_CHT_UFS}, 14080a7581fSIrina Tirdea {"UXD", PMC_PSS_BIT_CHT_UXD}, 14180a7581fSIrina Tirdea {"UXD_FD", PMC_PSS_BIT_CHT_UXD_FD}, 14280a7581fSIrina Tirdea {"UX_ENG", PMC_PSS_BIT_CHT_UX_ENG}, 14380a7581fSIrina Tirdea {"USB_SUS", PMC_PSS_BIT_CHT_USB_SUS}, 14480a7581fSIrina Tirdea {"GMM", PMC_PSS_BIT_CHT_GMM}, 14580a7581fSIrina Tirdea {"ISH", PMC_PSS_BIT_CHT_ISH}, 14680a7581fSIrina Tirdea {"DFX_MASTER", PMC_PSS_BIT_CHT_DFX_MASTER}, 14780a7581fSIrina Tirdea {"DFX_CLUSTER1", PMC_PSS_BIT_CHT_DFX_CLUSTER1}, 14880a7581fSIrina Tirdea {"DFX_CLUSTER2", PMC_PSS_BIT_CHT_DFX_CLUSTER2}, 14980a7581fSIrina Tirdea {"DFX_CLUSTER3", PMC_PSS_BIT_CHT_DFX_CLUSTER3}, 15080a7581fSIrina Tirdea {"DFX_CLUSTER4", PMC_PSS_BIT_CHT_DFX_CLUSTER4}, 15180a7581fSIrina Tirdea {"DFX_CLUSTER5", PMC_PSS_BIT_CHT_DFX_CLUSTER5}, 15280a7581fSIrina Tirdea {}, 15380a7581fSIrina Tirdea }; 15480a7581fSIrina Tirdea 15580a7581fSIrina Tirdea static const struct pmc_reg_map byt_reg_map = { 15680a7581fSIrina Tirdea .d3_sts_0 = d3_sts_0_map, 15780a7581fSIrina Tirdea .d3_sts_1 = byt_d3_sts_1_map, 15880a7581fSIrina Tirdea .func_dis = d3_sts_0_map, 15980a7581fSIrina Tirdea .func_dis_2 = byt_d3_sts_1_map, 16080a7581fSIrina Tirdea .pss = byt_pss_map, 16180a7581fSIrina Tirdea }; 16280a7581fSIrina Tirdea 16380a7581fSIrina Tirdea static const struct pmc_reg_map cht_reg_map = { 16480a7581fSIrina Tirdea .d3_sts_0 = d3_sts_0_map, 16580a7581fSIrina Tirdea .d3_sts_1 = cht_d3_sts_1_map, 16680a7581fSIrina Tirdea .func_dis = d3_sts_0_map, 16780a7581fSIrina Tirdea .func_dis_2 = cht_func_dis_2_map, 16880a7581fSIrina Tirdea .pss = cht_pss_map, 16980a7581fSIrina Tirdea }; 17080a7581fSIrina Tirdea 17180a7581fSIrina Tirdea static inline u32 pmc_reg_read(struct pmc_dev *pmc, int reg_offset) 17280a7581fSIrina Tirdea { 17380a7581fSIrina Tirdea return readl(pmc->regmap + reg_offset); 17480a7581fSIrina Tirdea } 17580a7581fSIrina Tirdea 17680a7581fSIrina Tirdea static inline void pmc_reg_write(struct pmc_dev *pmc, int reg_offset, u32 val) 17780a7581fSIrina Tirdea { 17880a7581fSIrina Tirdea writel(val, pmc->regmap + reg_offset); 17980a7581fSIrina Tirdea } 18080a7581fSIrina Tirdea 18180a7581fSIrina Tirdea int pmc_atom_read(int offset, u32 *value) 18280a7581fSIrina Tirdea { 18380a7581fSIrina Tirdea struct pmc_dev *pmc = &pmc_device; 18480a7581fSIrina Tirdea 18580a7581fSIrina Tirdea if (!pmc->init) 18680a7581fSIrina Tirdea return -ENODEV; 18780a7581fSIrina Tirdea 18880a7581fSIrina Tirdea *value = pmc_reg_read(pmc, offset); 18980a7581fSIrina Tirdea return 0; 19080a7581fSIrina Tirdea } 19180a7581fSIrina Tirdea EXPORT_SYMBOL_GPL(pmc_atom_read); 19280a7581fSIrina Tirdea 19380a7581fSIrina Tirdea int pmc_atom_write(int offset, u32 value) 19480a7581fSIrina Tirdea { 19580a7581fSIrina Tirdea struct pmc_dev *pmc = &pmc_device; 19680a7581fSIrina Tirdea 19780a7581fSIrina Tirdea if (!pmc->init) 19880a7581fSIrina Tirdea return -ENODEV; 19980a7581fSIrina Tirdea 20080a7581fSIrina Tirdea pmc_reg_write(pmc, offset, value); 20180a7581fSIrina Tirdea return 0; 20280a7581fSIrina Tirdea } 20380a7581fSIrina Tirdea EXPORT_SYMBOL_GPL(pmc_atom_write); 20480a7581fSIrina Tirdea 20580a7581fSIrina Tirdea static void pmc_power_off(void) 20680a7581fSIrina Tirdea { 20780a7581fSIrina Tirdea u16 pm1_cnt_port; 20880a7581fSIrina Tirdea u32 pm1_cnt_value; 20980a7581fSIrina Tirdea 21080a7581fSIrina Tirdea pr_info("Preparing to enter system sleep state S5\n"); 21180a7581fSIrina Tirdea 21280a7581fSIrina Tirdea pm1_cnt_port = acpi_base_addr + PM1_CNT; 21380a7581fSIrina Tirdea 21480a7581fSIrina Tirdea pm1_cnt_value = inl(pm1_cnt_port); 21580a7581fSIrina Tirdea pm1_cnt_value &= SLEEP_TYPE_MASK; 21680a7581fSIrina Tirdea pm1_cnt_value |= SLEEP_TYPE_S5; 21780a7581fSIrina Tirdea pm1_cnt_value |= SLEEP_ENABLE; 21880a7581fSIrina Tirdea 21980a7581fSIrina Tirdea outl(pm1_cnt_value, pm1_cnt_port); 22080a7581fSIrina Tirdea } 22180a7581fSIrina Tirdea 22280a7581fSIrina Tirdea static void pmc_hw_reg_setup(struct pmc_dev *pmc) 22380a7581fSIrina Tirdea { 22480a7581fSIrina Tirdea /* 22580a7581fSIrina Tirdea * Disable PMC S0IX_WAKE_EN events coming from: 22680a7581fSIrina Tirdea * - LPC clock run 22780a7581fSIrina Tirdea * - GPIO_SUS ored dedicated IRQs 22880a7581fSIrina Tirdea * - GPIO_SCORE ored dedicated IRQs 22980a7581fSIrina Tirdea * - GPIO_SUS shared IRQ 23080a7581fSIrina Tirdea * - GPIO_SCORE shared IRQ 23180a7581fSIrina Tirdea */ 23280a7581fSIrina Tirdea pmc_reg_write(pmc, PMC_S0IX_WAKE_EN, (u32)PMC_WAKE_EN_SETTING); 23380a7581fSIrina Tirdea } 23480a7581fSIrina Tirdea 23580a7581fSIrina Tirdea #ifdef CONFIG_DEBUG_FS 23680a7581fSIrina Tirdea static void pmc_dev_state_print(struct seq_file *s, int reg_index, 23780a7581fSIrina Tirdea u32 sts, const struct pmc_bit_map *sts_map, 23880a7581fSIrina Tirdea u32 fd, const struct pmc_bit_map *fd_map) 23980a7581fSIrina Tirdea { 24080a7581fSIrina Tirdea int offset = PMC_REG_BIT_WIDTH * reg_index; 24180a7581fSIrina Tirdea int index; 24280a7581fSIrina Tirdea 24380a7581fSIrina Tirdea for (index = 0; sts_map[index].name; index++) { 24480a7581fSIrina Tirdea seq_printf(s, "Dev: %-2d - %-32s\tState: %s [%s]\n", 24580a7581fSIrina Tirdea offset + index, sts_map[index].name, 24680a7581fSIrina Tirdea fd_map[index].bit_mask & fd ? "Disabled" : "Enabled ", 24780a7581fSIrina Tirdea sts_map[index].bit_mask & sts ? "D3" : "D0"); 24880a7581fSIrina Tirdea } 24980a7581fSIrina Tirdea } 25080a7581fSIrina Tirdea 25180a7581fSIrina Tirdea static int pmc_dev_state_show(struct seq_file *s, void *unused) 25280a7581fSIrina Tirdea { 25380a7581fSIrina Tirdea struct pmc_dev *pmc = s->private; 25480a7581fSIrina Tirdea const struct pmc_reg_map *m = pmc->map; 25580a7581fSIrina Tirdea u32 func_dis, func_dis_2; 25680a7581fSIrina Tirdea u32 d3_sts_0, d3_sts_1; 25780a7581fSIrina Tirdea 25880a7581fSIrina Tirdea func_dis = pmc_reg_read(pmc, PMC_FUNC_DIS); 25980a7581fSIrina Tirdea func_dis_2 = pmc_reg_read(pmc, PMC_FUNC_DIS_2); 26080a7581fSIrina Tirdea d3_sts_0 = pmc_reg_read(pmc, PMC_D3_STS_0); 26180a7581fSIrina Tirdea d3_sts_1 = pmc_reg_read(pmc, PMC_D3_STS_1); 26280a7581fSIrina Tirdea 26380a7581fSIrina Tirdea /* Low part */ 26480a7581fSIrina Tirdea pmc_dev_state_print(s, 0, d3_sts_0, m->d3_sts_0, func_dis, m->func_dis); 26580a7581fSIrina Tirdea 26680a7581fSIrina Tirdea /* High part */ 26780a7581fSIrina Tirdea pmc_dev_state_print(s, 1, d3_sts_1, m->d3_sts_1, func_dis_2, m->func_dis_2); 26880a7581fSIrina Tirdea 26980a7581fSIrina Tirdea return 0; 27080a7581fSIrina Tirdea } 27180a7581fSIrina Tirdea 27280a7581fSIrina Tirdea static int pmc_dev_state_open(struct inode *inode, struct file *file) 27380a7581fSIrina Tirdea { 27480a7581fSIrina Tirdea return single_open(file, pmc_dev_state_show, inode->i_private); 27580a7581fSIrina Tirdea } 27680a7581fSIrina Tirdea 27780a7581fSIrina Tirdea static const struct file_operations pmc_dev_state_ops = { 27880a7581fSIrina Tirdea .open = pmc_dev_state_open, 27980a7581fSIrina Tirdea .read = seq_read, 28080a7581fSIrina Tirdea .llseek = seq_lseek, 28180a7581fSIrina Tirdea .release = single_release, 28280a7581fSIrina Tirdea }; 28380a7581fSIrina Tirdea 28480a7581fSIrina Tirdea static int pmc_pss_state_show(struct seq_file *s, void *unused) 28580a7581fSIrina Tirdea { 28680a7581fSIrina Tirdea struct pmc_dev *pmc = s->private; 28780a7581fSIrina Tirdea const struct pmc_bit_map *map = pmc->map->pss; 28880a7581fSIrina Tirdea u32 pss = pmc_reg_read(pmc, PMC_PSS); 28980a7581fSIrina Tirdea int index; 29080a7581fSIrina Tirdea 29180a7581fSIrina Tirdea for (index = 0; map[index].name; index++) { 29280a7581fSIrina Tirdea seq_printf(s, "Island: %-2d - %-32s\tState: %s\n", 29380a7581fSIrina Tirdea index, map[index].name, 29480a7581fSIrina Tirdea map[index].bit_mask & pss ? "Off" : "On"); 29580a7581fSIrina Tirdea } 29680a7581fSIrina Tirdea return 0; 29780a7581fSIrina Tirdea } 29880a7581fSIrina Tirdea 29980a7581fSIrina Tirdea static int pmc_pss_state_open(struct inode *inode, struct file *file) 30080a7581fSIrina Tirdea { 30180a7581fSIrina Tirdea return single_open(file, pmc_pss_state_show, inode->i_private); 30280a7581fSIrina Tirdea } 30380a7581fSIrina Tirdea 30480a7581fSIrina Tirdea static const struct file_operations pmc_pss_state_ops = { 30580a7581fSIrina Tirdea .open = pmc_pss_state_open, 30680a7581fSIrina Tirdea .read = seq_read, 30780a7581fSIrina Tirdea .llseek = seq_lseek, 30880a7581fSIrina Tirdea .release = single_release, 30980a7581fSIrina Tirdea }; 31080a7581fSIrina Tirdea 31180a7581fSIrina Tirdea static int pmc_sleep_tmr_show(struct seq_file *s, void *unused) 31280a7581fSIrina Tirdea { 31380a7581fSIrina Tirdea struct pmc_dev *pmc = s->private; 31480a7581fSIrina Tirdea u64 s0ir_tmr, s0i1_tmr, s0i2_tmr, s0i3_tmr, s0_tmr; 31580a7581fSIrina Tirdea 31680a7581fSIrina Tirdea s0ir_tmr = (u64)pmc_reg_read(pmc, PMC_S0IR_TMR) << PMC_TMR_SHIFT; 31780a7581fSIrina Tirdea s0i1_tmr = (u64)pmc_reg_read(pmc, PMC_S0I1_TMR) << PMC_TMR_SHIFT; 31880a7581fSIrina Tirdea s0i2_tmr = (u64)pmc_reg_read(pmc, PMC_S0I2_TMR) << PMC_TMR_SHIFT; 31980a7581fSIrina Tirdea s0i3_tmr = (u64)pmc_reg_read(pmc, PMC_S0I3_TMR) << PMC_TMR_SHIFT; 32080a7581fSIrina Tirdea s0_tmr = (u64)pmc_reg_read(pmc, PMC_S0_TMR) << PMC_TMR_SHIFT; 32180a7581fSIrina Tirdea 32280a7581fSIrina Tirdea seq_printf(s, "S0IR Residency:\t%lldus\n", s0ir_tmr); 32380a7581fSIrina Tirdea seq_printf(s, "S0I1 Residency:\t%lldus\n", s0i1_tmr); 32480a7581fSIrina Tirdea seq_printf(s, "S0I2 Residency:\t%lldus\n", s0i2_tmr); 32580a7581fSIrina Tirdea seq_printf(s, "S0I3 Residency:\t%lldus\n", s0i3_tmr); 32680a7581fSIrina Tirdea seq_printf(s, "S0 Residency:\t%lldus\n", s0_tmr); 32780a7581fSIrina Tirdea return 0; 32880a7581fSIrina Tirdea } 32980a7581fSIrina Tirdea 33080a7581fSIrina Tirdea static int pmc_sleep_tmr_open(struct inode *inode, struct file *file) 33180a7581fSIrina Tirdea { 33280a7581fSIrina Tirdea return single_open(file, pmc_sleep_tmr_show, inode->i_private); 33380a7581fSIrina Tirdea } 33480a7581fSIrina Tirdea 33580a7581fSIrina Tirdea static const struct file_operations pmc_sleep_tmr_ops = { 33680a7581fSIrina Tirdea .open = pmc_sleep_tmr_open, 33780a7581fSIrina Tirdea .read = seq_read, 33880a7581fSIrina Tirdea .llseek = seq_lseek, 33980a7581fSIrina Tirdea .release = single_release, 34080a7581fSIrina Tirdea }; 34180a7581fSIrina Tirdea 34280a7581fSIrina Tirdea static void pmc_dbgfs_unregister(struct pmc_dev *pmc) 34380a7581fSIrina Tirdea { 34480a7581fSIrina Tirdea debugfs_remove_recursive(pmc->dbgfs_dir); 34580a7581fSIrina Tirdea } 34680a7581fSIrina Tirdea 34780a7581fSIrina Tirdea static int pmc_dbgfs_register(struct pmc_dev *pmc) 34880a7581fSIrina Tirdea { 34980a7581fSIrina Tirdea struct dentry *dir, *f; 35080a7581fSIrina Tirdea 35180a7581fSIrina Tirdea dir = debugfs_create_dir("pmc_atom", NULL); 35280a7581fSIrina Tirdea if (!dir) 35380a7581fSIrina Tirdea return -ENOMEM; 35480a7581fSIrina Tirdea 35580a7581fSIrina Tirdea pmc->dbgfs_dir = dir; 35680a7581fSIrina Tirdea 35780a7581fSIrina Tirdea f = debugfs_create_file("dev_state", S_IFREG | S_IRUGO, 35880a7581fSIrina Tirdea dir, pmc, &pmc_dev_state_ops); 35980a7581fSIrina Tirdea if (!f) 36080a7581fSIrina Tirdea goto err; 36180a7581fSIrina Tirdea 36280a7581fSIrina Tirdea f = debugfs_create_file("pss_state", S_IFREG | S_IRUGO, 36380a7581fSIrina Tirdea dir, pmc, &pmc_pss_state_ops); 36480a7581fSIrina Tirdea if (!f) 36580a7581fSIrina Tirdea goto err; 36680a7581fSIrina Tirdea 36780a7581fSIrina Tirdea f = debugfs_create_file("sleep_state", S_IFREG | S_IRUGO, 36880a7581fSIrina Tirdea dir, pmc, &pmc_sleep_tmr_ops); 36980a7581fSIrina Tirdea if (!f) 37080a7581fSIrina Tirdea goto err; 37180a7581fSIrina Tirdea 37280a7581fSIrina Tirdea return 0; 37380a7581fSIrina Tirdea err: 37480a7581fSIrina Tirdea pmc_dbgfs_unregister(pmc); 37580a7581fSIrina Tirdea return -ENODEV; 37680a7581fSIrina Tirdea } 37780a7581fSIrina Tirdea #else 37880a7581fSIrina Tirdea static int pmc_dbgfs_register(struct pmc_dev *pmc) 37980a7581fSIrina Tirdea { 38080a7581fSIrina Tirdea return 0; 38180a7581fSIrina Tirdea } 38280a7581fSIrina Tirdea #endif /* CONFIG_DEBUG_FS */ 38380a7581fSIrina Tirdea 38480a7581fSIrina Tirdea static int pmc_setup_dev(struct pci_dev *pdev, const struct pci_device_id *ent) 38580a7581fSIrina Tirdea { 38680a7581fSIrina Tirdea struct pmc_dev *pmc = &pmc_device; 38780a7581fSIrina Tirdea const struct pmc_reg_map *map = (struct pmc_reg_map *)ent->driver_data; 38880a7581fSIrina Tirdea int ret; 38980a7581fSIrina Tirdea 39080a7581fSIrina Tirdea /* Obtain ACPI base address */ 39180a7581fSIrina Tirdea pci_read_config_dword(pdev, ACPI_BASE_ADDR_OFFSET, &acpi_base_addr); 39280a7581fSIrina Tirdea acpi_base_addr &= ACPI_BASE_ADDR_MASK; 39380a7581fSIrina Tirdea 39480a7581fSIrina Tirdea /* Install power off function */ 39580a7581fSIrina Tirdea if (acpi_base_addr != 0 && pm_power_off == NULL) 39680a7581fSIrina Tirdea pm_power_off = pmc_power_off; 39780a7581fSIrina Tirdea 39880a7581fSIrina Tirdea pci_read_config_dword(pdev, PMC_BASE_ADDR_OFFSET, &pmc->base_addr); 39980a7581fSIrina Tirdea pmc->base_addr &= PMC_BASE_ADDR_MASK; 40080a7581fSIrina Tirdea 40180a7581fSIrina Tirdea pmc->regmap = ioremap_nocache(pmc->base_addr, PMC_MMIO_REG_LEN); 40280a7581fSIrina Tirdea if (!pmc->regmap) { 40380a7581fSIrina Tirdea dev_err(&pdev->dev, "error: ioremap failed\n"); 40480a7581fSIrina Tirdea return -ENOMEM; 40580a7581fSIrina Tirdea } 40680a7581fSIrina Tirdea 40780a7581fSIrina Tirdea pmc->map = map; 40880a7581fSIrina Tirdea 40980a7581fSIrina Tirdea /* PMC hardware registers setup */ 41080a7581fSIrina Tirdea pmc_hw_reg_setup(pmc); 41180a7581fSIrina Tirdea 41280a7581fSIrina Tirdea ret = pmc_dbgfs_register(pmc); 41380a7581fSIrina Tirdea if (ret) 41480a7581fSIrina Tirdea dev_warn(&pdev->dev, "debugfs register failed\n"); 41580a7581fSIrina Tirdea 41680a7581fSIrina Tirdea pmc->init = true; 41780a7581fSIrina Tirdea return ret; 41880a7581fSIrina Tirdea } 41980a7581fSIrina Tirdea 42080a7581fSIrina Tirdea /* 42180a7581fSIrina Tirdea * Data for PCI driver interface 42280a7581fSIrina Tirdea * 42380a7581fSIrina Tirdea * used by pci_match_id() call below. 42480a7581fSIrina Tirdea */ 42580a7581fSIrina Tirdea static const struct pci_device_id pmc_pci_ids[] = { 42680a7581fSIrina Tirdea { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_VLV_PMC), (kernel_ulong_t)&byt_reg_map }, 42780a7581fSIrina Tirdea { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_CHT_PMC), (kernel_ulong_t)&cht_reg_map }, 42880a7581fSIrina Tirdea { 0, }, 42980a7581fSIrina Tirdea }; 43080a7581fSIrina Tirdea 43180a7581fSIrina Tirdea static int __init pmc_atom_init(void) 43280a7581fSIrina Tirdea { 43380a7581fSIrina Tirdea struct pci_dev *pdev = NULL; 43480a7581fSIrina Tirdea const struct pci_device_id *ent; 43580a7581fSIrina Tirdea 43680a7581fSIrina Tirdea /* We look for our device - PCU PMC 43780a7581fSIrina Tirdea * we assume that there is max. one device. 43880a7581fSIrina Tirdea * 43980a7581fSIrina Tirdea * We can't use plain pci_driver mechanism, 44080a7581fSIrina Tirdea * as the device is really a multiple function device, 44180a7581fSIrina Tirdea * main driver that binds to the pci_device is lpc_ich 44280a7581fSIrina Tirdea * and have to find & bind to the device this way. 44380a7581fSIrina Tirdea */ 44480a7581fSIrina Tirdea for_each_pci_dev(pdev) { 44580a7581fSIrina Tirdea ent = pci_match_id(pmc_pci_ids, pdev); 44680a7581fSIrina Tirdea if (ent) 44780a7581fSIrina Tirdea return pmc_setup_dev(pdev, ent); 44880a7581fSIrina Tirdea } 44980a7581fSIrina Tirdea /* Device not found. */ 45080a7581fSIrina Tirdea return -ENODEV; 45180a7581fSIrina Tirdea } 45280a7581fSIrina Tirdea 45380a7581fSIrina Tirdea device_initcall(pmc_atom_init); 45480a7581fSIrina Tirdea 45580a7581fSIrina Tirdea /* 45680a7581fSIrina Tirdea MODULE_AUTHOR("Aubrey Li <aubrey.li@linux.intel.com>"); 45780a7581fSIrina Tirdea MODULE_DESCRIPTION("Intel Atom SOC Power Management Controller Interface"); 45880a7581fSIrina Tirdea MODULE_LICENSE("GPL v2"); 45980a7581fSIrina Tirdea */ 460