brintos

brintos / linux-shallow public Read only

0
0
Text · 15.3 KiB · 0aa7076 Raw
608 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Intel Atom SoC Power Management Controller Driver4 * Copyright (c) 2014-2015,2017,2022 Intel Corporation.5 */6 7#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt8 9#include <linux/acpi.h>10#include <linux/debugfs.h>11#include <linux/device.h>12#include <linux/dmi.h>13#include <linux/init.h>14#include <linux/io.h>15#include <linux/platform_data/x86/clk-pmc-atom.h>16#include <linux/platform_data/x86/pmc_atom.h>17#include <linux/platform_data/x86/simatic-ipc.h>18#include <linux/platform_device.h>19#include <linux/pci.h>20#include <linux/seq_file.h>21#include <linux/suspend.h>22 23struct pmc_bit_map {24	const char *name;25	u32 bit_mask;26};27 28struct pmc_reg_map {29	const struct pmc_bit_map *d3_sts_0;30	const struct pmc_bit_map *d3_sts_1;31	const struct pmc_bit_map *func_dis;32	const struct pmc_bit_map *func_dis_2;33	const struct pmc_bit_map *pss;34};35 36struct pmc_data {37	const struct pmc_reg_map *map;38	const struct pmc_clk *clks;39};40 41struct pmc_dev {42	u32 base_addr;43	void __iomem *regmap;44	const struct pmc_reg_map *map;45#ifdef CONFIG_DEBUG_FS46	struct dentry *dbgfs_dir;47#endif /* CONFIG_DEBUG_FS */48	bool init;49};50 51static struct pmc_dev pmc_device;52static u32 acpi_base_addr;53 54static const struct pmc_clk byt_clks[] = {55	{56		.name = "xtal",57		.freq = 25000000,58		.parent_name = NULL,59	},60	{61		.name = "pll",62		.freq = 19200000,63		.parent_name = "xtal",64	},65	{}66};67 68static const struct pmc_clk cht_clks[] = {69	{70		.name = "xtal",71		.freq = 19200000,72		.parent_name = NULL,73	},74	{}75};76 77static const struct pmc_bit_map d3_sts_0_map[] = {78	{"LPSS1_F0_DMA",	BIT_LPSS1_F0_DMA},79	{"LPSS1_F1_PWM1",	BIT_LPSS1_F1_PWM1},80	{"LPSS1_F2_PWM2",	BIT_LPSS1_F2_PWM2},81	{"LPSS1_F3_HSUART1",	BIT_LPSS1_F3_HSUART1},82	{"LPSS1_F4_HSUART2",	BIT_LPSS1_F4_HSUART2},83	{"LPSS1_F5_SPI",	BIT_LPSS1_F5_SPI},84	{"LPSS1_F6_Reserved",	BIT_LPSS1_F6_XXX},85	{"LPSS1_F7_Reserved",	BIT_LPSS1_F7_XXX},86	{"SCC_EMMC",		BIT_SCC_EMMC},87	{"SCC_SDIO",		BIT_SCC_SDIO},88	{"SCC_SDCARD",		BIT_SCC_SDCARD},89	{"SCC_MIPI",		BIT_SCC_MIPI},90	{"HDA",			BIT_HDA},91	{"LPE",			BIT_LPE},92	{"OTG",			BIT_OTG},93	{"USH",			BIT_USH},94	{"GBE",			BIT_GBE},95	{"SATA",		BIT_SATA},96	{"USB_EHCI",		BIT_USB_EHCI},97	{"SEC",			BIT_SEC},98	{"PCIE_PORT0",		BIT_PCIE_PORT0},99	{"PCIE_PORT1",		BIT_PCIE_PORT1},100	{"PCIE_PORT2",		BIT_PCIE_PORT2},101	{"PCIE_PORT3",		BIT_PCIE_PORT3},102	{"LPSS2_F0_DMA",	BIT_LPSS2_F0_DMA},103	{"LPSS2_F1_I2C1",	BIT_LPSS2_F1_I2C1},104	{"LPSS2_F2_I2C2",	BIT_LPSS2_F2_I2C2},105	{"LPSS2_F3_I2C3",	BIT_LPSS2_F3_I2C3},106	{"LPSS2_F3_I2C4",	BIT_LPSS2_F4_I2C4},107	{"LPSS2_F5_I2C5",	BIT_LPSS2_F5_I2C5},108	{"LPSS2_F6_I2C6",	BIT_LPSS2_F6_I2C6},109	{"LPSS2_F7_I2C7",	BIT_LPSS2_F7_I2C7},110	{}111};112 113static struct pmc_bit_map byt_d3_sts_1_map[] = {114	{"SMB",			BIT_SMB},115	{"OTG_SS_PHY",		BIT_OTG_SS_PHY},116	{"USH_SS_PHY",		BIT_USH_SS_PHY},117	{"DFX",			BIT_DFX},118	{}119};120 121static struct pmc_bit_map cht_d3_sts_1_map[] = {122	{"SMB",			BIT_SMB},123	{"GMM",			BIT_STS_GMM},124	{"ISH",			BIT_STS_ISH},125	{}126};127 128static struct pmc_bit_map cht_func_dis_2_map[] = {129	{"SMB",			BIT_SMB},130	{"GMM",			BIT_FD_GMM},131	{"ISH",			BIT_FD_ISH},132	{}133};134 135static const struct pmc_bit_map byt_pss_map[] = {136	{"GBE",			PMC_PSS_BIT_GBE},137	{"SATA",		PMC_PSS_BIT_SATA},138	{"HDA",			PMC_PSS_BIT_HDA},139	{"SEC",			PMC_PSS_BIT_SEC},140	{"PCIE",		PMC_PSS_BIT_PCIE},141	{"LPSS",		PMC_PSS_BIT_LPSS},142	{"LPE",			PMC_PSS_BIT_LPE},143	{"DFX",			PMC_PSS_BIT_DFX},144	{"USH_CTRL",		PMC_PSS_BIT_USH_CTRL},145	{"USH_SUS",		PMC_PSS_BIT_USH_SUS},146	{"USH_VCCS",		PMC_PSS_BIT_USH_VCCS},147	{"USH_VCCA",		PMC_PSS_BIT_USH_VCCA},148	{"OTG_CTRL",		PMC_PSS_BIT_OTG_CTRL},149	{"OTG_VCCS",		PMC_PSS_BIT_OTG_VCCS},150	{"OTG_VCCA_CLK",	PMC_PSS_BIT_OTG_VCCA_CLK},151	{"OTG_VCCA",		PMC_PSS_BIT_OTG_VCCA},152	{"USB",			PMC_PSS_BIT_USB},153	{"USB_SUS",		PMC_PSS_BIT_USB_SUS},154	{}155};156 157static const struct pmc_bit_map cht_pss_map[] = {158	{"SATA",		PMC_PSS_BIT_SATA},159	{"HDA",			PMC_PSS_BIT_HDA},160	{"SEC",			PMC_PSS_BIT_SEC},161	{"PCIE",		PMC_PSS_BIT_PCIE},162	{"LPSS",		PMC_PSS_BIT_LPSS},163	{"LPE",			PMC_PSS_BIT_LPE},164	{"UFS",			PMC_PSS_BIT_CHT_UFS},165	{"UXD",			PMC_PSS_BIT_CHT_UXD},166	{"UXD_FD",		PMC_PSS_BIT_CHT_UXD_FD},167	{"UX_ENG",		PMC_PSS_BIT_CHT_UX_ENG},168	{"USB_SUS",		PMC_PSS_BIT_CHT_USB_SUS},169	{"GMM",			PMC_PSS_BIT_CHT_GMM},170	{"ISH",			PMC_PSS_BIT_CHT_ISH},171	{"DFX_MASTER",		PMC_PSS_BIT_CHT_DFX_MASTER},172	{"DFX_CLUSTER1",	PMC_PSS_BIT_CHT_DFX_CLUSTER1},173	{"DFX_CLUSTER2",	PMC_PSS_BIT_CHT_DFX_CLUSTER2},174	{"DFX_CLUSTER3",	PMC_PSS_BIT_CHT_DFX_CLUSTER3},175	{"DFX_CLUSTER4",	PMC_PSS_BIT_CHT_DFX_CLUSTER4},176	{"DFX_CLUSTER5",	PMC_PSS_BIT_CHT_DFX_CLUSTER5},177	{}178};179 180static const struct pmc_reg_map byt_reg_map = {181	.d3_sts_0	= d3_sts_0_map,182	.d3_sts_1	= byt_d3_sts_1_map,183	.func_dis	= d3_sts_0_map,184	.func_dis_2	= byt_d3_sts_1_map,185	.pss		= byt_pss_map,186};187 188static const struct pmc_reg_map cht_reg_map = {189	.d3_sts_0	= d3_sts_0_map,190	.d3_sts_1	= cht_d3_sts_1_map,191	.func_dis	= d3_sts_0_map,192	.func_dis_2	= cht_func_dis_2_map,193	.pss		= cht_pss_map,194};195 196static const struct pmc_data byt_data = {197	.map = &byt_reg_map,198	.clks = byt_clks,199};200 201static const struct pmc_data cht_data = {202	.map = &cht_reg_map,203	.clks = cht_clks,204};205 206static inline u32 pmc_reg_read(struct pmc_dev *pmc, int reg_offset)207{208	return readl(pmc->regmap + reg_offset);209}210 211static inline void pmc_reg_write(struct pmc_dev *pmc, int reg_offset, u32 val)212{213	writel(val, pmc->regmap + reg_offset);214}215 216int pmc_atom_read(int offset, u32 *value)217{218	struct pmc_dev *pmc = &pmc_device;219 220	if (!pmc->init)221		return -ENODEV;222 223	*value = pmc_reg_read(pmc, offset);224	return 0;225}226 227static void pmc_power_off(void)228{229	u16	pm1_cnt_port;230	u32	pm1_cnt_value;231 232	pr_info("Preparing to enter system sleep state S5\n");233 234	pm1_cnt_port = acpi_base_addr + PM1_CNT;235 236	pm1_cnt_value = inl(pm1_cnt_port);237	pm1_cnt_value &= ~SLEEP_TYPE_MASK;238	pm1_cnt_value |= SLEEP_TYPE_S5;239	pm1_cnt_value |= SLEEP_ENABLE;240 241	outl(pm1_cnt_value, pm1_cnt_port);242}243 244static void pmc_hw_reg_setup(struct pmc_dev *pmc)245{246	/*247	 * Disable PMC S0IX_WAKE_EN events coming from:248	 * - LPC clock run249	 * - GPIO_SUS ored dedicated IRQs250	 * - GPIO_SCORE ored dedicated IRQs251	 * - GPIO_SUS shared IRQ252	 * - GPIO_SCORE shared IRQ253	 */254	pmc_reg_write(pmc, PMC_S0IX_WAKE_EN, (u32)PMC_WAKE_EN_SETTING);255}256 257#ifdef CONFIG_DEBUG_FS258static void pmc_dev_state_print(struct seq_file *s, int reg_index,259				u32 sts, const struct pmc_bit_map *sts_map,260				u32 fd, const struct pmc_bit_map *fd_map)261{262	int offset = PMC_REG_BIT_WIDTH * reg_index;263	int index;264 265	for (index = 0; sts_map[index].name; index++) {266		seq_printf(s, "Dev: %-2d - %-32s\tState: %s [%s]\n",267			offset + index, sts_map[index].name,268			fd_map[index].bit_mask & fd ?  "Disabled" : "Enabled ",269			sts_map[index].bit_mask & sts ?  "D3" : "D0");270	}271}272 273static int pmc_dev_state_show(struct seq_file *s, void *unused)274{275	struct pmc_dev *pmc = s->private;276	const struct pmc_reg_map *m = pmc->map;277	u32 func_dis, func_dis_2;278	u32 d3_sts_0, d3_sts_1;279 280	func_dis = pmc_reg_read(pmc, PMC_FUNC_DIS);281	func_dis_2 = pmc_reg_read(pmc, PMC_FUNC_DIS_2);282	d3_sts_0 = pmc_reg_read(pmc, PMC_D3_STS_0);283	d3_sts_1 = pmc_reg_read(pmc, PMC_D3_STS_1);284 285	/* Low part */286	pmc_dev_state_print(s, 0, d3_sts_0, m->d3_sts_0, func_dis, m->func_dis);287 288	/* High part */289	pmc_dev_state_print(s, 1, d3_sts_1, m->d3_sts_1, func_dis_2, m->func_dis_2);290 291	return 0;292}293 294DEFINE_SHOW_ATTRIBUTE(pmc_dev_state);295 296static int pmc_pss_state_show(struct seq_file *s, void *unused)297{298	struct pmc_dev *pmc = s->private;299	const struct pmc_bit_map *map = pmc->map->pss;300	u32 pss = pmc_reg_read(pmc, PMC_PSS);301	int index;302 303	for (index = 0; map[index].name; index++) {304		seq_printf(s, "Island: %-2d - %-32s\tState: %s\n",305			index, map[index].name,306			map[index].bit_mask & pss ? "Off" : "On");307	}308	return 0;309}310 311DEFINE_SHOW_ATTRIBUTE(pmc_pss_state);312 313static int pmc_sleep_tmr_show(struct seq_file *s, void *unused)314{315	struct pmc_dev *pmc = s->private;316	u64 s0ir_tmr, s0i1_tmr, s0i2_tmr, s0i3_tmr, s0_tmr;317 318	s0ir_tmr = (u64)pmc_reg_read(pmc, PMC_S0IR_TMR) << PMC_TMR_SHIFT;319	s0i1_tmr = (u64)pmc_reg_read(pmc, PMC_S0I1_TMR) << PMC_TMR_SHIFT;320	s0i2_tmr = (u64)pmc_reg_read(pmc, PMC_S0I2_TMR) << PMC_TMR_SHIFT;321	s0i3_tmr = (u64)pmc_reg_read(pmc, PMC_S0I3_TMR) << PMC_TMR_SHIFT;322	s0_tmr = (u64)pmc_reg_read(pmc, PMC_S0_TMR) << PMC_TMR_SHIFT;323 324	seq_printf(s, "S0IR Residency:\t%lldus\n", s0ir_tmr);325	seq_printf(s, "S0I1 Residency:\t%lldus\n", s0i1_tmr);326	seq_printf(s, "S0I2 Residency:\t%lldus\n", s0i2_tmr);327	seq_printf(s, "S0I3 Residency:\t%lldus\n", s0i3_tmr);328	seq_printf(s, "S0   Residency:\t%lldus\n", s0_tmr);329	return 0;330}331 332DEFINE_SHOW_ATTRIBUTE(pmc_sleep_tmr);333 334static void pmc_dbgfs_register(struct pmc_dev *pmc)335{336	struct dentry *dir;337 338	dir = debugfs_create_dir("pmc_atom", NULL);339 340	pmc->dbgfs_dir = dir;341 342	debugfs_create_file("dev_state", S_IFREG | S_IRUGO, dir, pmc,343			    &pmc_dev_state_fops);344	debugfs_create_file("pss_state", S_IFREG | S_IRUGO, dir, pmc,345			    &pmc_pss_state_fops);346	debugfs_create_file("sleep_state", S_IFREG | S_IRUGO, dir, pmc,347			    &pmc_sleep_tmr_fops);348}349#else350static void pmc_dbgfs_register(struct pmc_dev *pmc)351{352}353#endif /* CONFIG_DEBUG_FS */354 355static bool pmc_clk_is_critical = true;356 357static int dmi_callback(const struct dmi_system_id *d)358{359	pr_info("%s: PMC critical clocks quirk enabled\n", d->ident);360 361	return 1;362}363 364static int dmi_callback_siemens(const struct dmi_system_id *d)365{366	u32 st_id;367 368	if (dmi_walk(simatic_ipc_find_dmi_entry_helper, &st_id))369		goto out;370 371	if (st_id == SIMATIC_IPC_IPC227E || st_id == SIMATIC_IPC_IPC277E)372		return dmi_callback(d);373 374out:375	pmc_clk_is_critical = false;376	return 1;377}378 379/*380 * Some systems need one or more of their pmc_plt_clks to be381 * marked as critical.382 */383static const struct dmi_system_id critclk_systems[] = {384	{385		/* pmc_plt_clk0 is used for an external HSIC USB HUB */386		.ident = "MPL CEC1x",387		.callback = dmi_callback,388		.matches = {389			DMI_MATCH(DMI_SYS_VENDOR, "MPL AG"),390			DMI_MATCH(DMI_PRODUCT_NAME, "CEC10 Family"),391		},392	},393	{394		/*395		 * Lex System / Lex Computech Co. makes a lot of Bay Trail396		 * based embedded boards which often come with multiple397		 * ethernet controllers using multiple pmc_plt_clks. See:398		 * https://www.lex.com.tw/products/embedded-ipc-board/399		 */400		.ident = "Lex BayTrail",401		.callback = dmi_callback,402		.matches = {403			DMI_MATCH(DMI_SYS_VENDOR, "Lex BayTrail"),404		},405	},406	{407		/* pmc_plt_clk* - are used for ethernet controllers */408		.ident = "Beckhoff Baytrail",409		.callback = dmi_callback,410		.matches = {411			DMI_MATCH(DMI_SYS_VENDOR, "Beckhoff Automation"),412			DMI_MATCH(DMI_PRODUCT_FAMILY, "CBxx63"),413		},414	},415	{416		.ident = "SIEMENS AG",417		.callback = dmi_callback_siemens,418		.matches = {419			DMI_MATCH(DMI_SYS_VENDOR, "SIEMENS AG"),420		},421	},422	{}423};424 425static int pmc_setup_clks(struct pci_dev *pdev, void __iomem *pmc_regmap,426			  const struct pmc_data *pmc_data)427{428	struct platform_device *clkdev;429	struct pmc_clk_data *clk_data;430 431	clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);432	if (!clk_data)433		return -ENOMEM;434 435	clk_data->base = pmc_regmap; /* offset is added by client */436	clk_data->clks = pmc_data->clks;437	if (dmi_check_system(critclk_systems))438		clk_data->critical = pmc_clk_is_critical;439 440	clkdev = platform_device_register_data(&pdev->dev, "clk-pmc-atom",441					       PLATFORM_DEVID_NONE,442					       clk_data, sizeof(*clk_data));443	if (IS_ERR(clkdev)) {444		kfree(clk_data);445		return PTR_ERR(clkdev);446	}447 448	kfree(clk_data);449 450	return 0;451}452 453#ifdef CONFIG_SUSPEND454static void pmc_dev_state_check(u32 sts, const struct pmc_bit_map *sts_map,455				u32 fd, const struct pmc_bit_map *fd_map,456				u32 sts_possible_false_pos)457{458	int index;459 460	for (index = 0; sts_map[index].name; index++) {461		if (!(fd_map[index].bit_mask & fd) &&462		    !(sts_map[index].bit_mask & sts)) {463			if (sts_map[index].bit_mask & sts_possible_false_pos)464				pm_pr_dbg("%s is in D0 prior to s2idle\n",465					  sts_map[index].name);466			else467				pr_err("%s is in D0 prior to s2idle\n",468				       sts_map[index].name);469		}470	}471}472 473static void pmc_s2idle_check(void)474{475	struct pmc_dev *pmc = &pmc_device;476	const struct pmc_reg_map *m = pmc->map;477	u32 func_dis, func_dis_2;478	u32 d3_sts_0, d3_sts_1;479	u32 false_pos_sts_0, false_pos_sts_1;480	int i;481 482	func_dis = pmc_reg_read(pmc, PMC_FUNC_DIS);483	func_dis_2 = pmc_reg_read(pmc, PMC_FUNC_DIS_2);484	d3_sts_0 = pmc_reg_read(pmc, PMC_D3_STS_0);485	d3_sts_1 = pmc_reg_read(pmc, PMC_D3_STS_1);486 487	/*488	 * Some blocks are not used on lower-featured versions of the SoC and489	 * always report D0, add these to false_pos mask to log at debug level.490	 */491	if (m->d3_sts_1	== byt_d3_sts_1_map) {492		/* Bay Trail */493		false_pos_sts_0 = BIT_GBE | BIT_SATA | BIT_PCIE_PORT0 |494			BIT_PCIE_PORT1 | BIT_PCIE_PORT2 | BIT_PCIE_PORT3 |495			BIT_LPSS2_F5_I2C5;496		false_pos_sts_1 = BIT_SMB | BIT_USH_SS_PHY | BIT_DFX;497	} else {498		/* Cherry Trail */499		false_pos_sts_0 = BIT_GBE | BIT_SATA | BIT_LPSS2_F7_I2C7;500		false_pos_sts_1 = BIT_SMB | BIT_STS_ISH;501	}502 503	pmc_dev_state_check(d3_sts_0, m->d3_sts_0, func_dis, m->func_dis, false_pos_sts_0);504	pmc_dev_state_check(d3_sts_1, m->d3_sts_1, func_dis_2, m->func_dis_2, false_pos_sts_1);505 506	/* Forced-on PMC clocks prevent S0i3 */507	for (i = 0; i < PMC_CLK_NUM; i++) {508		u32 ctl = pmc_reg_read(pmc, PMC_CLK_CTL_OFFSET + 4 * i);509 510		if ((ctl & PMC_MASK_CLK_CTL) != PMC_CLK_CTL_FORCE_ON)511			continue;512 513		pr_err("clock %d is ON prior to freeze (ctl 0x%08x)\n", i, ctl);514	}515}516 517static struct acpi_s2idle_dev_ops pmc_s2idle_ops = {518	.check = pmc_s2idle_check,519};520 521static void pmc_s2idle_check_register(void)522{523	acpi_register_lps0_dev(&pmc_s2idle_ops);524}525#else526static void pmc_s2idle_check_register(void) {}527#endif528 529static int pmc_setup_dev(struct pci_dev *pdev, const struct pci_device_id *ent)530{531	struct pmc_dev *pmc = &pmc_device;532	const struct pmc_data *data = (struct pmc_data *)ent->driver_data;533	const struct pmc_reg_map *map = data->map;534	int ret;535 536	/* Obtain ACPI base address */537	pci_read_config_dword(pdev, ACPI_BASE_ADDR_OFFSET, &acpi_base_addr);538	acpi_base_addr &= ACPI_BASE_ADDR_MASK;539 540	/* Install power off function */541	if (acpi_base_addr != 0 && pm_power_off == NULL)542		pm_power_off = pmc_power_off;543 544	pci_read_config_dword(pdev, PMC_BASE_ADDR_OFFSET, &pmc->base_addr);545	pmc->base_addr &= PMC_BASE_ADDR_MASK;546 547	pmc->regmap = ioremap(pmc->base_addr, PMC_MMIO_REG_LEN);548	if (!pmc->regmap) {549		dev_err(&pdev->dev, "error: ioremap failed\n");550		return -ENOMEM;551	}552 553	pmc->map = map;554 555	/* PMC hardware registers setup */556	pmc_hw_reg_setup(pmc);557 558	pmc_dbgfs_register(pmc);559 560	/* Register platform clocks - PMC_PLT_CLK [0..5] */561	ret = pmc_setup_clks(pdev, pmc->regmap, data);562	if (ret)563		dev_warn(&pdev->dev, "platform clocks register failed: %d\n",564			 ret);565 566	pmc_s2idle_check_register();567	pmc->init = true;568	return ret;569}570 571/* Data for PCI driver interface used by pci_match_id() call below */572static const struct pci_device_id pmc_pci_ids[] = {573	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_VLV_PMC), (kernel_ulong_t)&byt_data },574	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_CHT_PMC), (kernel_ulong_t)&cht_data },575	{}576};577 578static int __init pmc_atom_init(void)579{580	struct pci_dev *pdev = NULL;581	const struct pci_device_id *ent;582 583	/*584	 * We look for our device - PCU PMC.585	 * We assume that there is maximum one device.586	 *587	 * We can't use plain pci_driver mechanism,588	 * as the device is really a multiple function device,589	 * main driver that binds to the pci_device is lpc_ich590	 * and have to find & bind to the device this way.591	 */592	for_each_pci_dev(pdev) {593		ent = pci_match_id(pmc_pci_ids, pdev);594		if (ent)595			return pmc_setup_dev(pdev, ent);596	}597	/* Device not found */598	return -ENODEV;599}600 601device_initcall(pmc_atom_init);602 603/*604MODULE_AUTHOR("Aubrey Li <aubrey.li@linux.intel.com>");605MODULE_DESCRIPTION("Intel Atom SoC Power Management Controller Interface");606MODULE_LICENSE("GPL v2");607*/608