From c982ffa6a0a34023ab4a8072471974428c439445 Mon Sep 17 00:00:00 2001 From: Hou Zhiqiang Date: Fri, 5 Jun 2015 18:19:29 +0800 Subject: spi: fsl-espi: Workaround for the deep sleep issue when boot from SPI On T1042D4RDB, system can't resume and warm reset to uboot prompt sometimes. Disable eSPI controller hardware before enter deep sleep, and enable it after resume. Signed-off-by: Hou Zhiqiang Change-Id: I0f091890ef3e3219697ff7f5bbf4a02809e6e45b Reviewed-on: http://git.am.freescale.net:8181/37469 Tested-by: Review Code-CDREVIEW Reviewed-by: Honghua Yin diff --git a/drivers/spi/spi-fsl-espi.c b/drivers/spi/spi-fsl-espi.c index a7fdb87..0b03ae3 100644 --- a/drivers/spi/spi-fsl-espi.c +++ b/drivers/spi/spi-fsl-espi.c @@ -739,6 +739,35 @@ static int of_fsl_espi_remove(struct platform_device *dev) } #ifdef CONFIG_PM_SLEEP +#define DCFG_CCSR_DEVDISR4_OFF 0x7c +#define ESPI_BIT (1 << 27) + +static int hw_disable_espi(int disable) +{ + struct device_node *np; + void __iomem *gut_addr = NULL; /* Local Access Control registers */ + u32 regval; + + np = of_find_compatible_node(NULL, NULL, "fsl,t1040-device-config"); + if (!np) { + pr_err("could not find a guts node\n"); + return -ENODEV; + } + gut_addr = of_iomap(np, 0); + if (!gut_addr) + return -ENODEV; + + regval = in_be32(gut_addr + DCFG_CCSR_DEVDISR4_OFF); + if (disable == true) + regval |= ESPI_BIT; + else + regval &= ~ESPI_BIT; + + out_be32(gut_addr + DCFG_CCSR_DEVDISR4_OFF, regval); + + return 0; +} + static int of_fsl_espi_suspend(struct device *dev) { struct spi_master *master = dev_get_drvdata(dev); @@ -760,6 +789,8 @@ static int of_fsl_espi_suspend(struct device *dev) regval &= ~SPMODE_ENABLE; mpc8xxx_spi_write_reg(®_base->mode, regval); + hw_disable_espi(true); + return 0; } @@ -772,6 +803,8 @@ static int of_fsl_espi_resume(struct device *dev) u32 regval; int i; + hw_disable_espi(false); + mpc8xxx_spi = spi_master_get_devdata(master); reg_base = mpc8xxx_spi->reg_base; -- cgit v0.10.2