mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-05 00:26:41 +07:00
48b16180d0
If we do nothing in suspend/resume, some platform PCIe ip-block can't guarantee the link back to L0 state from sleep, then, when we read the EP device will hang. Only we send pme turnoff message in pci controller suspend, and send pme exit message in resume, the link state will be normal. When we send pme turnoff message in pci controller suspend, the links will into l2/l3 ready, then, host cannot communicate with ep device, but pci-driver will call back EP device to save them state. So we need to change platform_driver->suspend/resume to syscore->suspend/resume. So the new suspend/resume implementation, send pme turnoff message in suspend, and send pme exit message in resume. And add a PME handler, to response PME & message interrupt. Change platform_driver->suspend/resume to syscore->suspend/resume. pci-driver will call back EP device, to save EP state in pci_pm_suspend_noirq, so we need to keep the link, until pci_pm_suspend_noirq finish. Signed-off-by: Wang Dongsheng <dongsheng.wang@freescale.com> Signed-off-by: Scott Wood <scottwood@freescale.com>
157 lines
3.7 KiB
C
157 lines
3.7 KiB
C
/*
|
|
* P1022 RDK board specific routines
|
|
*
|
|
* Copyright 2012 Freescale Semiconductor, Inc.
|
|
*
|
|
* Author: Timur Tabi <timur@freescale.com>
|
|
*
|
|
* Based on p1022_ds.c
|
|
*
|
|
* This file is licensed under the terms of the GNU General Public License
|
|
* version 2. This program is licensed "as is" without any warranty of any
|
|
* kind, whether express or implied.
|
|
*/
|
|
|
|
#include <linux/pci.h>
|
|
#include <linux/of_platform.h>
|
|
#include <asm/div64.h>
|
|
#include <asm/mpic.h>
|
|
#include <asm/swiotlb.h>
|
|
|
|
#include <sysdev/fsl_soc.h>
|
|
#include <sysdev/fsl_pci.h>
|
|
#include <asm/udbg.h>
|
|
#include <asm/fsl_guts.h>
|
|
#include "smp.h"
|
|
|
|
#include "mpc85xx.h"
|
|
|
|
#if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE)
|
|
|
|
/* DIU Pixel Clock bits of the CLKDVDR Global Utilities register */
|
|
#define CLKDVDR_PXCKEN 0x80000000
|
|
#define CLKDVDR_PXCKINV 0x10000000
|
|
#define CLKDVDR_PXCKDLY 0x06000000
|
|
#define CLKDVDR_PXCLK_MASK 0x00FF0000
|
|
|
|
/**
|
|
* p1022rdk_set_pixel_clock: program the DIU's clock
|
|
*
|
|
* @pixclock: the wavelength, in picoseconds, of the clock
|
|
*/
|
|
void p1022rdk_set_pixel_clock(unsigned int pixclock)
|
|
{
|
|
struct device_node *guts_np = NULL;
|
|
struct ccsr_guts __iomem *guts;
|
|
unsigned long freq;
|
|
u64 temp;
|
|
u32 pxclk;
|
|
|
|
/* Map the global utilities registers. */
|
|
guts_np = of_find_compatible_node(NULL, NULL, "fsl,p1022-guts");
|
|
if (!guts_np) {
|
|
pr_err("p1022rdk: missing global utilties device node\n");
|
|
return;
|
|
}
|
|
|
|
guts = of_iomap(guts_np, 0);
|
|
of_node_put(guts_np);
|
|
if (!guts) {
|
|
pr_err("p1022rdk: could not map global utilties device\n");
|
|
return;
|
|
}
|
|
|
|
/* Convert pixclock from a wavelength to a frequency */
|
|
temp = 1000000000000ULL;
|
|
do_div(temp, pixclock);
|
|
freq = temp;
|
|
|
|
/*
|
|
* 'pxclk' is the ratio of the platform clock to the pixel clock.
|
|
* This number is programmed into the CLKDVDR register, and the valid
|
|
* range of values is 2-255.
|
|
*/
|
|
pxclk = DIV_ROUND_CLOSEST(fsl_get_sys_freq(), freq);
|
|
pxclk = clamp_t(u32, pxclk, 2, 255);
|
|
|
|
/* Disable the pixel clock, and set it to non-inverted and no delay */
|
|
clrbits32(&guts->clkdvdr,
|
|
CLKDVDR_PXCKEN | CLKDVDR_PXCKDLY | CLKDVDR_PXCLK_MASK);
|
|
|
|
/* Enable the clock and set the pxclk */
|
|
setbits32(&guts->clkdvdr, CLKDVDR_PXCKEN | (pxclk << 16));
|
|
|
|
iounmap(guts);
|
|
}
|
|
|
|
/**
|
|
* p1022rdk_valid_monitor_port: set the monitor port for sysfs
|
|
*/
|
|
enum fsl_diu_monitor_port
|
|
p1022rdk_valid_monitor_port(enum fsl_diu_monitor_port port)
|
|
{
|
|
return FSL_DIU_PORT_DVI;
|
|
}
|
|
|
|
#endif
|
|
|
|
void __init p1022_rdk_pic_init(void)
|
|
{
|
|
struct mpic *mpic = mpic_alloc(NULL, 0, MPIC_BIG_ENDIAN |
|
|
MPIC_SINGLE_DEST_CPU,
|
|
0, 256, " OpenPIC ");
|
|
BUG_ON(mpic == NULL);
|
|
mpic_init(mpic);
|
|
}
|
|
|
|
/*
|
|
* Setup the architecture
|
|
*/
|
|
static void __init p1022_rdk_setup_arch(void)
|
|
{
|
|
if (ppc_md.progress)
|
|
ppc_md.progress("p1022_rdk_setup_arch()", 0);
|
|
|
|
#if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE)
|
|
diu_ops.set_pixel_clock = p1022rdk_set_pixel_clock;
|
|
diu_ops.valid_monitor_port = p1022rdk_valid_monitor_port;
|
|
#endif
|
|
|
|
mpc85xx_smp_init();
|
|
|
|
fsl_pci_assign_primary();
|
|
|
|
swiotlb_detect_4g();
|
|
|
|
pr_info("Freescale / iVeia P1022 RDK reference board\n");
|
|
}
|
|
|
|
machine_arch_initcall(p1022_rdk, mpc85xx_common_publish_devices);
|
|
|
|
machine_arch_initcall(p1022_rdk, swiotlb_setup_bus_notifier);
|
|
|
|
/*
|
|
* Called very early, device-tree isn't unflattened
|
|
*/
|
|
static int __init p1022_rdk_probe(void)
|
|
{
|
|
unsigned long root = of_get_flat_dt_root();
|
|
|
|
return of_flat_dt_is_compatible(root, "fsl,p1022rdk");
|
|
}
|
|
|
|
define_machine(p1022_rdk) {
|
|
.name = "P1022 RDK",
|
|
.probe = p1022_rdk_probe,
|
|
.setup_arch = p1022_rdk_setup_arch,
|
|
.init_IRQ = p1022_rdk_pic_init,
|
|
#ifdef CONFIG_PCI
|
|
.pcibios_fixup_bus = fsl_pcibios_fixup_bus,
|
|
.pcibios_fixup_phb = fsl_pcibios_fixup_phb,
|
|
#endif
|
|
.get_irq = mpic_get_irq,
|
|
.restart = fsl_rstcr_restart,
|
|
.calibrate_decr = generic_calibrate_decr,
|
|
.progress = udbg_progress,
|
|
};
|