diff options
-rw-r--r-- | drivers/acpi/sleep.c | 13 | ||||
-rw-r--r-- | drivers/cpufreq/Kconfig.arm | 10 | ||||
-rw-r--r-- | drivers/cpufreq/brcmstb-avs-cpufreq.c | 323 | ||||
-rw-r--r-- | drivers/pci/pci-driver.c | 5 |
4 files changed, 17 insertions, 334 deletions
diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index 99a1a650326d..974e58457697 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c | |||
@@ -364,6 +364,19 @@ static const struct dmi_system_id acpisleep_dmi_table[] __initconst = { | |||
364 | DMI_MATCH(DMI_PRODUCT_NAME, "XPS 13 9360"), | 364 | DMI_MATCH(DMI_PRODUCT_NAME, "XPS 13 9360"), |
365 | }, | 365 | }, |
366 | }, | 366 | }, |
367 | /* | ||
368 | * ThinkPad X1 Tablet(2016) cannot do suspend-to-idle using | ||
369 | * the Low Power S0 Idle firmware interface (see | ||
370 | * https://bugzilla.kernel.org/show_bug.cgi?id=199057). | ||
371 | */ | ||
372 | { | ||
373 | .callback = init_no_lps0, | ||
374 | .ident = "ThinkPad X1 Tablet(2016)", | ||
375 | .matches = { | ||
376 | DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), | ||
377 | DMI_MATCH(DMI_PRODUCT_NAME, "20GGA00L00"), | ||
378 | }, | ||
379 | }, | ||
367 | {}, | 380 | {}, |
368 | }; | 381 | }; |
369 | 382 | ||
diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm index 7f56fe5183f2..de55c7d57438 100644 --- a/drivers/cpufreq/Kconfig.arm +++ b/drivers/cpufreq/Kconfig.arm | |||
@@ -71,16 +71,6 @@ config ARM_BRCMSTB_AVS_CPUFREQ | |||
71 | 71 | ||
72 | Say Y, if you have a Broadcom SoC with AVS support for DFS or DVFS. | 72 | Say Y, if you have a Broadcom SoC with AVS support for DFS or DVFS. |
73 | 73 | ||
74 | config ARM_BRCMSTB_AVS_CPUFREQ_DEBUG | ||
75 | bool "Broadcom STB AVS CPUfreq driver sysfs debug capability" | ||
76 | depends on ARM_BRCMSTB_AVS_CPUFREQ | ||
77 | help | ||
78 | Enabling this option turns on debug support via sysfs under | ||
79 | /sys/kernel/debug/brcmstb-avs-cpufreq. It is possible to read all and | ||
80 | write some AVS mailbox registers through sysfs entries. | ||
81 | |||
82 | If in doubt, say N. | ||
83 | |||
84 | config ARM_EXYNOS5440_CPUFREQ | 74 | config ARM_EXYNOS5440_CPUFREQ |
85 | tristate "SAMSUNG EXYNOS5440" | 75 | tristate "SAMSUNG EXYNOS5440" |
86 | depends on SOC_EXYNOS5440 | 76 | depends on SOC_EXYNOS5440 |
diff --git a/drivers/cpufreq/brcmstb-avs-cpufreq.c b/drivers/cpufreq/brcmstb-avs-cpufreq.c index 6cdac1aaf23c..b07559b9ed99 100644 --- a/drivers/cpufreq/brcmstb-avs-cpufreq.c +++ b/drivers/cpufreq/brcmstb-avs-cpufreq.c | |||
@@ -49,13 +49,6 @@ | |||
49 | #include <linux/platform_device.h> | 49 | #include <linux/platform_device.h> |
50 | #include <linux/semaphore.h> | 50 | #include <linux/semaphore.h> |
51 | 51 | ||
52 | #ifdef CONFIG_ARM_BRCMSTB_AVS_CPUFREQ_DEBUG | ||
53 | #include <linux/ctype.h> | ||
54 | #include <linux/debugfs.h> | ||
55 | #include <linux/slab.h> | ||
56 | #include <linux/uaccess.h> | ||
57 | #endif | ||
58 | |||
59 | /* Max number of arguments AVS calls take */ | 52 | /* Max number of arguments AVS calls take */ |
60 | #define AVS_MAX_CMD_ARGS 4 | 53 | #define AVS_MAX_CMD_ARGS 4 |
61 | /* | 54 | /* |
@@ -182,88 +175,11 @@ struct private_data { | |||
182 | void __iomem *base; | 175 | void __iomem *base; |
183 | void __iomem *avs_intr_base; | 176 | void __iomem *avs_intr_base; |
184 | struct device *dev; | 177 | struct device *dev; |
185 | #ifdef CONFIG_ARM_BRCMSTB_AVS_CPUFREQ_DEBUG | ||
186 | struct dentry *debugfs; | ||
187 | #endif | ||
188 | struct completion done; | 178 | struct completion done; |
189 | struct semaphore sem; | 179 | struct semaphore sem; |
190 | struct pmap pmap; | 180 | struct pmap pmap; |
191 | }; | 181 | }; |
192 | 182 | ||
193 | #ifdef CONFIG_ARM_BRCMSTB_AVS_CPUFREQ_DEBUG | ||
194 | |||
195 | enum debugfs_format { | ||
196 | DEBUGFS_NORMAL, | ||
197 | DEBUGFS_FLOAT, | ||
198 | DEBUGFS_REV, | ||
199 | }; | ||
200 | |||
201 | struct debugfs_data { | ||
202 | struct debugfs_entry *entry; | ||
203 | struct private_data *priv; | ||
204 | }; | ||
205 | |||
206 | struct debugfs_entry { | ||
207 | char *name; | ||
208 | u32 offset; | ||
209 | fmode_t mode; | ||
210 | enum debugfs_format format; | ||
211 | }; | ||
212 | |||
213 | #define DEBUGFS_ENTRY(name, mode, format) { \ | ||
214 | #name, AVS_MBOX_##name, mode, format \ | ||
215 | } | ||
216 | |||
217 | /* | ||
218 | * These are used for debugfs only. Otherwise we use AVS_MBOX_PARAM() directly. | ||
219 | */ | ||
220 | #define AVS_MBOX_PARAM1 AVS_MBOX_PARAM(0) | ||
221 | #define AVS_MBOX_PARAM2 AVS_MBOX_PARAM(1) | ||
222 | #define AVS_MBOX_PARAM3 AVS_MBOX_PARAM(2) | ||
223 | #define AVS_MBOX_PARAM4 AVS_MBOX_PARAM(3) | ||
224 | |||
225 | /* | ||
226 | * This table stores the name, access permissions and offset for each hardware | ||
227 | * register and is used to generate debugfs entries. | ||
228 | */ | ||
229 | static struct debugfs_entry debugfs_entries[] = { | ||
230 | DEBUGFS_ENTRY(COMMAND, S_IWUSR, DEBUGFS_NORMAL), | ||
231 | DEBUGFS_ENTRY(STATUS, S_IWUSR, DEBUGFS_NORMAL), | ||
232 | DEBUGFS_ENTRY(VOLTAGE0, 0, DEBUGFS_FLOAT), | ||
233 | DEBUGFS_ENTRY(TEMP0, 0, DEBUGFS_FLOAT), | ||
234 | DEBUGFS_ENTRY(PV0, 0, DEBUGFS_FLOAT), | ||
235 | DEBUGFS_ENTRY(MV0, 0, DEBUGFS_FLOAT), | ||
236 | DEBUGFS_ENTRY(PARAM1, S_IWUSR, DEBUGFS_NORMAL), | ||
237 | DEBUGFS_ENTRY(PARAM2, S_IWUSR, DEBUGFS_NORMAL), | ||
238 | DEBUGFS_ENTRY(PARAM3, S_IWUSR, DEBUGFS_NORMAL), | ||
239 | DEBUGFS_ENTRY(PARAM4, S_IWUSR, DEBUGFS_NORMAL), | ||
240 | DEBUGFS_ENTRY(REVISION, 0, DEBUGFS_REV), | ||
241 | DEBUGFS_ENTRY(PSTATE, 0, DEBUGFS_NORMAL), | ||
242 | DEBUGFS_ENTRY(HEARTBEAT, 0, DEBUGFS_NORMAL), | ||
243 | DEBUGFS_ENTRY(MAGIC, S_IWUSR, DEBUGFS_NORMAL), | ||
244 | DEBUGFS_ENTRY(SIGMA_HVT, 0, DEBUGFS_NORMAL), | ||
245 | DEBUGFS_ENTRY(SIGMA_SVT, 0, DEBUGFS_NORMAL), | ||
246 | DEBUGFS_ENTRY(VOLTAGE1, 0, DEBUGFS_FLOAT), | ||
247 | DEBUGFS_ENTRY(TEMP1, 0, DEBUGFS_FLOAT), | ||
248 | DEBUGFS_ENTRY(PV1, 0, DEBUGFS_FLOAT), | ||
249 | DEBUGFS_ENTRY(MV1, 0, DEBUGFS_FLOAT), | ||
250 | DEBUGFS_ENTRY(FREQUENCY, 0, DEBUGFS_NORMAL), | ||
251 | }; | ||
252 | |||
253 | static int brcm_avs_target_index(struct cpufreq_policy *, unsigned int); | ||
254 | |||
255 | static char *__strtolower(char *s) | ||
256 | { | ||
257 | char *p; | ||
258 | |||
259 | for (p = s; *p; p++) | ||
260 | *p = tolower(*p); | ||
261 | |||
262 | return s; | ||
263 | } | ||
264 | |||
265 | #endif /* CONFIG_ARM_BRCMSTB_AVS_CPUFREQ_DEBUG */ | ||
266 | |||
267 | static void __iomem *__map_region(const char *name) | 183 | static void __iomem *__map_region(const char *name) |
268 | { | 184 | { |
269 | struct device_node *np; | 185 | struct device_node *np; |
@@ -516,238 +432,6 @@ brcm_avs_get_freq_table(struct device *dev, struct private_data *priv) | |||
516 | return table; | 432 | return table; |
517 | } | 433 | } |
518 | 434 | ||
519 | #ifdef CONFIG_ARM_BRCMSTB_AVS_CPUFREQ_DEBUG | ||
520 | |||
521 | #define MANT(x) (unsigned int)(abs((x)) / 1000) | ||
522 | #define FRAC(x) (unsigned int)(abs((x)) - abs((x)) / 1000 * 1000) | ||
523 | |||
524 | static int brcm_avs_debug_show(struct seq_file *s, void *data) | ||
525 | { | ||
526 | struct debugfs_data *dbgfs = s->private; | ||
527 | void __iomem *base; | ||
528 | u32 val, offset; | ||
529 | |||
530 | if (!dbgfs) { | ||
531 | seq_puts(s, "No device pointer\n"); | ||
532 | return 0; | ||
533 | } | ||
534 | |||
535 | base = dbgfs->priv->base; | ||
536 | offset = dbgfs->entry->offset; | ||
537 | val = readl(base + offset); | ||
538 | switch (dbgfs->entry->format) { | ||
539 | case DEBUGFS_NORMAL: | ||
540 | seq_printf(s, "%u\n", val); | ||
541 | break; | ||
542 | case DEBUGFS_FLOAT: | ||
543 | seq_printf(s, "%d.%03d\n", MANT(val), FRAC(val)); | ||
544 | break; | ||
545 | case DEBUGFS_REV: | ||
546 | seq_printf(s, "%c.%c.%c.%c\n", (val >> 24 & 0xff), | ||
547 | (val >> 16 & 0xff), (val >> 8 & 0xff), | ||
548 | val & 0xff); | ||
549 | break; | ||
550 | } | ||
551 | seq_printf(s, "0x%08x\n", val); | ||
552 | |||
553 | return 0; | ||
554 | } | ||
555 | |||
556 | #undef MANT | ||
557 | #undef FRAC | ||
558 | |||
559 | static ssize_t brcm_avs_seq_write(struct file *file, const char __user *buf, | ||
560 | size_t size, loff_t *ppos) | ||
561 | { | ||
562 | struct seq_file *s = file->private_data; | ||
563 | struct debugfs_data *dbgfs = s->private; | ||
564 | struct private_data *priv = dbgfs->priv; | ||
565 | void __iomem *base, *avs_intr_base; | ||
566 | bool use_issue_command = false; | ||
567 | unsigned long val, offset; | ||
568 | char str[128]; | ||
569 | int ret; | ||
570 | char *str_ptr = str; | ||
571 | |||
572 | if (size >= sizeof(str)) | ||
573 | return -E2BIG; | ||
574 | |||
575 | memset(str, 0, sizeof(str)); | ||
576 | ret = copy_from_user(str, buf, size); | ||
577 | if (ret) | ||
578 | return ret; | ||
579 | |||
580 | base = priv->base; | ||
581 | avs_intr_base = priv->avs_intr_base; | ||
582 | offset = dbgfs->entry->offset; | ||
583 | /* | ||
584 | * Special case writing to "command" entry only: if the string starts | ||
585 | * with a 'c', we use the driver's __issue_avs_command() function. | ||
586 | * Otherwise, we perform a raw write. This should allow testing of raw | ||
587 | * access as well as using the higher level function. (Raw access | ||
588 | * doesn't clear the firmware return status after issuing the command.) | ||
589 | */ | ||
590 | if (str_ptr[0] == 'c' && offset == AVS_MBOX_COMMAND) { | ||
591 | use_issue_command = true; | ||
592 | str_ptr++; | ||
593 | } | ||
594 | if (kstrtoul(str_ptr, 0, &val) != 0) | ||
595 | return -EINVAL; | ||
596 | |||
597 | /* | ||
598 | * Setting the P-state is a special case. We need to update the CPU | ||
599 | * frequency we report. | ||
600 | */ | ||
601 | if (val == AVS_CMD_SET_PSTATE) { | ||
602 | struct cpufreq_policy *policy; | ||
603 | unsigned int pstate; | ||
604 | |||
605 | policy = cpufreq_cpu_get(smp_processor_id()); | ||
606 | /* Read back the P-state we are about to set */ | ||
607 | pstate = readl(base + AVS_MBOX_PARAM(0)); | ||
608 | if (use_issue_command) { | ||
609 | ret = brcm_avs_target_index(policy, pstate); | ||
610 | return ret ? ret : size; | ||
611 | } | ||
612 | policy->cur = policy->freq_table[pstate].frequency; | ||
613 | } | ||
614 | |||
615 | if (use_issue_command) { | ||
616 | ret = __issue_avs_command(priv, val, false, NULL); | ||
617 | } else { | ||
618 | /* Locking here is not perfect, but is only for debug. */ | ||
619 | ret = down_interruptible(&priv->sem); | ||
620 | if (ret) | ||
621 | return ret; | ||
622 | |||
623 | writel(val, base + offset); | ||
624 | /* We have to wake up the firmware to process a command. */ | ||
625 | if (offset == AVS_MBOX_COMMAND) | ||
626 | writel(AVS_CPU_L2_INT_MASK, | ||
627 | avs_intr_base + AVS_CPU_L2_SET0); | ||
628 | up(&priv->sem); | ||
629 | } | ||
630 | |||
631 | return ret ? ret : size; | ||
632 | } | ||
633 | |||
634 | static struct debugfs_entry *__find_debugfs_entry(const char *name) | ||
635 | { | ||
636 | int i; | ||
637 | |||
638 | for (i = 0; i < ARRAY_SIZE(debugfs_entries); i++) | ||
639 | if (strcasecmp(debugfs_entries[i].name, name) == 0) | ||
640 | return &debugfs_entries[i]; | ||
641 | |||
642 | return NULL; | ||
643 | } | ||
644 | |||
645 | static int brcm_avs_debug_open(struct inode *inode, struct file *file) | ||
646 | { | ||
647 | struct debugfs_data *data; | ||
648 | fmode_t fmode; | ||
649 | int ret; | ||
650 | |||
651 | /* | ||
652 | * seq_open(), which is called by single_open(), clears "write" access. | ||
653 | * We need write access to some files, so we preserve our access mode | ||
654 | * and restore it. | ||
655 | */ | ||
656 | fmode = file->f_mode; | ||
657 | /* | ||
658 | * Check access permissions even for root. We don't want to be writing | ||
659 | * to read-only registers. Access for regular users has already been | ||
660 | * checked by the VFS layer. | ||
661 | */ | ||
662 | if ((fmode & FMODE_WRITER) && !(inode->i_mode & S_IWUSR)) | ||
663 | return -EACCES; | ||
664 | |||
665 | data = kmalloc(sizeof(*data), GFP_KERNEL); | ||
666 | if (!data) | ||
667 | return -ENOMEM; | ||
668 | /* | ||
669 | * We use the same file system operations for all our debug files. To | ||
670 | * produce specific output, we look up the file name upon opening a | ||
671 | * debugfs entry and map it to a memory offset. This offset is then used | ||
672 | * in the generic "show" function to read a specific register. | ||
673 | */ | ||
674 | data->entry = __find_debugfs_entry(file->f_path.dentry->d_iname); | ||
675 | data->priv = inode->i_private; | ||
676 | |||
677 | ret = single_open(file, brcm_avs_debug_show, data); | ||
678 | if (ret) | ||
679 | kfree(data); | ||
680 | file->f_mode = fmode; | ||
681 | |||
682 | return ret; | ||
683 | } | ||
684 | |||
685 | static int brcm_avs_debug_release(struct inode *inode, struct file *file) | ||
686 | { | ||
687 | struct seq_file *seq_priv = file->private_data; | ||
688 | struct debugfs_data *data = seq_priv->private; | ||
689 | |||
690 | kfree(data); | ||
691 | return single_release(inode, file); | ||
692 | } | ||
693 | |||
694 | static const struct file_operations brcm_avs_debug_ops = { | ||
695 | .open = brcm_avs_debug_open, | ||
696 | .read = seq_read, | ||
697 | .write = brcm_avs_seq_write, | ||
698 | .llseek = seq_lseek, | ||
699 | .release = brcm_avs_debug_release, | ||
700 | }; | ||
701 | |||
702 | static void brcm_avs_cpufreq_debug_init(struct platform_device *pdev) | ||
703 | { | ||
704 | struct private_data *priv = platform_get_drvdata(pdev); | ||
705 | struct dentry *dir; | ||
706 | int i; | ||
707 | |||
708 | if (!priv) | ||
709 | return; | ||
710 | |||
711 | dir = debugfs_create_dir(BRCM_AVS_CPUFREQ_NAME, NULL); | ||
712 | if (IS_ERR_OR_NULL(dir)) | ||
713 | return; | ||
714 | priv->debugfs = dir; | ||
715 | |||
716 | for (i = 0; i < ARRAY_SIZE(debugfs_entries); i++) { | ||
717 | /* | ||
718 | * The DEBUGFS_ENTRY macro generates uppercase strings. We | ||
719 | * convert them to lowercase before creating the debugfs | ||
720 | * entries. | ||
721 | */ | ||
722 | char *entry = __strtolower(debugfs_entries[i].name); | ||
723 | fmode_t mode = debugfs_entries[i].mode; | ||
724 | |||
725 | if (!debugfs_create_file(entry, S_IFREG | S_IRUGO | mode, | ||
726 | dir, priv, &brcm_avs_debug_ops)) { | ||
727 | priv->debugfs = NULL; | ||
728 | debugfs_remove_recursive(dir); | ||
729 | break; | ||
730 | } | ||
731 | } | ||
732 | } | ||
733 | |||
734 | static void brcm_avs_cpufreq_debug_exit(struct platform_device *pdev) | ||
735 | { | ||
736 | struct private_data *priv = platform_get_drvdata(pdev); | ||
737 | |||
738 | if (priv && priv->debugfs) { | ||
739 | debugfs_remove_recursive(priv->debugfs); | ||
740 | priv->debugfs = NULL; | ||
741 | } | ||
742 | } | ||
743 | |||
744 | #else | ||
745 | |||
746 | static void brcm_avs_cpufreq_debug_init(struct platform_device *pdev) {} | ||
747 | static void brcm_avs_cpufreq_debug_exit(struct platform_device *pdev) {} | ||
748 | |||
749 | #endif /* CONFIG_ARM_BRCMSTB_AVS_CPUFREQ_DEBUG */ | ||
750 | |||
751 | /* | 435 | /* |
752 | * To ensure the right firmware is running we need to | 436 | * To ensure the right firmware is running we need to |
753 | * - check the MAGIC matches what we expect | 437 | * - check the MAGIC matches what we expect |
@@ -1016,11 +700,8 @@ static int brcm_avs_cpufreq_probe(struct platform_device *pdev) | |||
1016 | return ret; | 700 | return ret; |
1017 | 701 | ||
1018 | brcm_avs_driver.driver_data = pdev; | 702 | brcm_avs_driver.driver_data = pdev; |
1019 | ret = cpufreq_register_driver(&brcm_avs_driver); | ||
1020 | if (!ret) | ||
1021 | brcm_avs_cpufreq_debug_init(pdev); | ||
1022 | 703 | ||
1023 | return ret; | 704 | return cpufreq_register_driver(&brcm_avs_driver); |
1024 | } | 705 | } |
1025 | 706 | ||
1026 | static int brcm_avs_cpufreq_remove(struct platform_device *pdev) | 707 | static int brcm_avs_cpufreq_remove(struct platform_device *pdev) |
@@ -1032,8 +713,6 @@ static int brcm_avs_cpufreq_remove(struct platform_device *pdev) | |||
1032 | if (ret) | 713 | if (ret) |
1033 | return ret; | 714 | return ret; |
1034 | 715 | ||
1035 | brcm_avs_cpufreq_debug_exit(pdev); | ||
1036 | |||
1037 | priv = platform_get_drvdata(pdev); | 716 | priv = platform_get_drvdata(pdev); |
1038 | iounmap(priv->base); | 717 | iounmap(priv->base); |
1039 | iounmap(priv->avs_intr_base); | 718 | iounmap(priv->avs_intr_base); |
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index 6ace47099fc5..b9a131137e64 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c | |||
@@ -958,10 +958,11 @@ static int pci_pm_freeze(struct device *dev) | |||
958 | * devices should not be touched during freeze/thaw transitions, | 958 | * devices should not be touched during freeze/thaw transitions, |
959 | * however. | 959 | * however. |
960 | */ | 960 | */ |
961 | if (!dev_pm_test_driver_flags(dev, DPM_FLAG_SMART_SUSPEND)) | 961 | if (!dev_pm_smart_suspend_and_suspended(dev)) { |
962 | pm_runtime_resume(dev); | 962 | pm_runtime_resume(dev); |
963 | pci_dev->state_saved = false; | ||
964 | } | ||
963 | 965 | ||
964 | pci_dev->state_saved = false; | ||
965 | if (pm->freeze) { | 966 | if (pm->freeze) { |
966 | int error; | 967 | int error; |
967 | 968 | ||