X-Git-Url: https://gerrit.automotivelinux.org/gerrit/gitweb?a=blobdiff_plain;f=meta-agl-bsp%2Fmeta-renesas%2Frecipes-kernel%2Flinux%2Flinux%2Fhibernation%2F0011-Add-rcar-pci-hibernation-code.patch;fp=meta-agl-bsp%2Fmeta-renesas%2Frecipes-kernel%2Flinux%2Flinux%2Fhibernation%2F0011-Add-rcar-pci-hibernation-code.patch;h=bdc9555c86d4e68072ef704ed7d26ef690123367;hb=a14e289caaae4c342c2bc686bd5d327ed612b0fc;hp=0000000000000000000000000000000000000000;hpb=5b5a54b60f45e67d647cf6cc0fe2b879b2bb8229;p=AGL%2Fmeta-agl.git diff --git a/meta-agl-bsp/meta-renesas/recipes-kernel/linux/linux/hibernation/0011-Add-rcar-pci-hibernation-code.patch b/meta-agl-bsp/meta-renesas/recipes-kernel/linux/linux/hibernation/0011-Add-rcar-pci-hibernation-code.patch new file mode 100755 index 000000000..bdc9555c8 --- /dev/null +++ b/meta-agl-bsp/meta-renesas/recipes-kernel/linux/linux/hibernation/0011-Add-rcar-pci-hibernation-code.patch @@ -0,0 +1,375 @@ +From f8691a62199319d9e37cd451a9b8364aa640c4cb Mon Sep 17 00:00:00 2001 +From: Yuichi Kusakabe +Date: Thu, 18 May 2017 17:45:19 +0900 +Subject: [PATCH 11/15] Add rcar-pci hibernation code + +Signed-off-by: Yuichi Kusakabe +--- + drivers/pci/host/pci-rcar-gen2.c | 281 ++++++++++++++++++++++++++++++++++++--- + 1 file changed, 266 insertions(+), 15 deletions(-) + +diff --git a/drivers/pci/host/pci-rcar-gen2.c b/drivers/pci/host/pci-rcar-gen2.c +index 57b6572..4cb9693 100644 +--- a/drivers/pci/host/pci-rcar-gen2.c ++++ b/drivers/pci/host/pci-rcar-gen2.c +@@ -23,9 +23,12 @@ + #include + #include + #include ++#include + + /* AHB-PCI Bridge PCI communication registers */ + #define RCAR_AHBPCI_PCICOM_OFFSET 0x800 ++#define RCAR_PCICONF_OHCI 0x0 ++#define RCAR_PCICONF_EHCI 0x100 + + #define RCAR_PCIAHB_WIN1_CTR_REG (RCAR_AHBPCI_PCICOM_OFFSET + 0x00) + #define RCAR_PCIAHB_WIN2_CTR_REG (RCAR_AHBPCI_PCICOM_OFFSET + 0x04) +@@ -104,6 +107,14 @@ struct rcar_pci_priv { + int domain; + int irq; + unsigned long window_size; ++ void __iomem *ohci_memdata; ++ void __iomem *ehci_memdata; ++#ifndef MCCILDK_CHANGE_DISABLE ++ u32 store_cfg[12]; ++#else ++ u32 store_cfg[9]; ++#endif ++ struct usb_phy *phy; + }; + + /* PCI configuration space operations */ +@@ -276,12 +287,6 @@ static int rcar_pci_setup(int nr, struct pci_sys_data *sys) + /* Configure AHB master and slave modes */ + iowrite32(RCAR_AHB_BUS_MODE, reg + RCAR_AHB_BUS_CTR_REG); + +- /* Configure PCI arbiter */ +- val = ioread32(reg + RCAR_PCI_ARBITER_CTR_REG); +- val |= RCAR_PCI_ARBITER_PCIREQ0 | RCAR_PCI_ARBITER_PCIREQ1 | +- RCAR_PCI_ARBITER_PCIBP_MODE; +- iowrite32(val, reg + RCAR_PCI_ARBITER_CTR_REG); +- + /* PCI-AHB mapping: 0x40000000 base */ + iowrite32(0x40000000 | RCAR_PCIAHB_PREFETCH16, + reg + RCAR_PCIAHB_WIN1_CTR_REG); +@@ -290,9 +295,25 @@ static int rcar_pci_setup(int nr, struct pci_sys_data *sys) + val = priv->mem_res.start | RCAR_AHBPCI_WIN_CTR_MEM; + iowrite32(val, reg + RCAR_AHBPCI_WIN2_CTR_REG); + ++ /* Enable PCI interrupts */ ++ iowrite32(RCAR_PCI_INT_A | RCAR_PCI_INT_B | RCAR_PCI_INT_PME, ++ reg + RCAR_PCI_INT_ENABLE_REG); ++ ++ /* Configure PCI arbiter */ ++ val = ioread32(reg + RCAR_PCI_ARBITER_CTR_REG); ++ val |= RCAR_PCI_ARBITER_PCIREQ0 | RCAR_PCI_ARBITER_PCIREQ1 | ++ RCAR_PCI_ARBITER_PCIBP_MODE; ++ iowrite32(val, reg + RCAR_PCI_ARBITER_CTR_REG); ++ + /* Enable AHB-PCI bridge PCI configuration access */ + iowrite32(RCAR_AHBPCI_WIN1_HOST | RCAR_AHBPCI_WIN_CTR_CFG, + reg + RCAR_AHBPCI_WIN1_CTR_REG); ++ val = ioread32(reg + PCI_COMMAND); ++ ++ val |= PCI_COMMAND_SERR | PCI_COMMAND_PARITY | ++ PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; ++ iowrite32(val, reg + PCI_COMMAND); ++ + /* Set PCI-AHB Window1 address */ + iowrite32(0x40000000 | PCI_BASE_ADDRESS_MEM_PREFETCH, + reg + PCI_BASE_ADDRESS_1); +@@ -300,15 +321,6 @@ static int rcar_pci_setup(int nr, struct pci_sys_data *sys) + val = priv->cfg_res->start + RCAR_AHBPCI_PCICOM_OFFSET; + iowrite32(val, reg + PCI_BASE_ADDRESS_0); + +- val = ioread32(reg + PCI_COMMAND); +- val |= PCI_COMMAND_SERR | PCI_COMMAND_PARITY | +- PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; +- iowrite32(val, reg + PCI_COMMAND); +- +- /* Enable PCI interrupts */ +- iowrite32(RCAR_PCI_INT_A | RCAR_PCI_INT_B | RCAR_PCI_INT_PME, +- reg + RCAR_PCI_INT_ENABLE_REG); +- + if (priv->irq > 0) + rcar_pci_setup_errirq(priv); + +@@ -326,6 +338,8 @@ static struct pci_ops rcar_pci_ops = { + .write = rcar_pci_write_config, + }; + ++#define RCAR_MAX_PCI_HOSTS 2 ++static struct rcar_pci_priv *keep_priv[RCAR_MAX_PCI_HOSTS]; + static int rcar_pci_probe(struct platform_device *pdev) + { + struct resource *cfg_res, *mem_res; +@@ -350,6 +364,7 @@ static int rcar_pci_probe(struct platform_device *pdev) + return -ENOMEM; + + priv->mem_res = *mem_res; ++ keep_priv[pdev->id] = priv; + /* + * The controller does not support/use port I/O, + * so setup a dummy port I/O region here. +@@ -378,6 +393,7 @@ static int rcar_pci_probe(struct platform_device *pdev) + return PTR_ERR(phy); + + usb_phy_init(phy); ++ priv->phy = phy; + + hw_private[0] = priv; + memset(&hw, 0, sizeof(hw)); +@@ -390,14 +406,249 @@ static int rcar_pci_probe(struct platform_device *pdev) + hw.domain = priv->domain; + #endif + pci_common_init_dev(&pdev->dev, &hw); ++ priv->ohci_memdata = ioremap(cfg_res->start - 0x10000, 0x1000); ++ priv->ehci_memdata = ioremap(cfg_res->start - 0x10000 + 0x1000, 0x1000); ++ return 0; ++} ++ ++static int rcar_pci_suspend(struct device *dev) ++{ ++ struct clk *clk; ++ clk = clk_get(NULL, "ehci"); ++ clk_disable_unprepare(clk); ++ clk_put(clk); ++ return 0; ++} ++static int rcar_pci_resume(struct device *dev) ++{ ++ struct clk *clk; ++ clk = clk_get(NULL, "ehci"); ++ clk_prepare_enable(clk); ++ clk_put(clk); ++ return 0; ++} ++static u32 rcar_pci_get_conf(struct rcar_pci_priv *priv, int id, int offset) ++{ ++ u32 val, kpt; ++ void __iomem *data; ++ kpt = ioread32(priv->reg + RCAR_AHBPCI_WIN1_CTR_REG); ++ val = id ? RCAR_AHBPCI_WIN1_DEVICE | RCAR_AHBPCI_WIN_CTR_CFG : ++ RCAR_AHBPCI_WIN1_HOST | RCAR_AHBPCI_WIN_CTR_CFG; ++ ++ iowrite32(val, priv->reg + RCAR_AHBPCI_WIN1_CTR_REG); ++ data = priv->reg + (id >> 1) * 0x100; ++ val = ioread32(data + offset); ++ iowrite32(kpt, priv->reg + RCAR_AHBPCI_WIN1_CTR_REG); ++ return val; ++} ++ ++static void rcar_pci_set_conf(struct rcar_pci_priv *priv, ++ int id, int offset, u32 d) ++{ ++ u32 val, kpt; ++ void __iomem *data; ++ kpt = ioread32(priv->reg + RCAR_AHBPCI_WIN1_CTR_REG); ++ val = id ? RCAR_AHBPCI_WIN1_DEVICE | RCAR_AHBPCI_WIN_CTR_CFG : ++ RCAR_AHBPCI_WIN1_HOST | RCAR_AHBPCI_WIN_CTR_CFG; ++ ++ iowrite32(val, priv->reg + RCAR_AHBPCI_WIN1_CTR_REG); ++ data = priv->reg + (id >> 1) * 0x100; ++ iowrite32(d, data + offset); ++ iowrite32(kpt, priv->reg + RCAR_AHBPCI_WIN1_CTR_REG); ++} ++ ++ ++static int rcar_pci_freeze(struct device *dev) ++{ ++ struct rcar_pci_priv *priv = keep_priv[to_platform_device(dev)->id]; ++ struct clk *clk; ++ clk = clk_get(NULL, "ehci"); ++ clk_disable_unprepare(clk); ++ clk_put(clk); ++ ++#ifndef MCCILDK_CHANGE_DISABLE ++ priv->store_cfg[0] = rcar_pci_get_conf(priv, 0, PCI_COMMAND); ++ priv->store_cfg[1] = rcar_pci_get_conf(priv, 1, PCI_COMMAND); ++ priv->store_cfg[2] = rcar_pci_get_conf(priv, 2, PCI_COMMAND); ++ priv->store_cfg[3] = rcar_pci_get_conf(priv, 0, PCI_CACHE_LINE_SIZE); ++ priv->store_cfg[4] = rcar_pci_get_conf(priv, 1, PCI_CACHE_LINE_SIZE); ++ priv->store_cfg[5] = rcar_pci_get_conf(priv, 2, PCI_CACHE_LINE_SIZE); ++ priv->store_cfg[6] = rcar_pci_get_conf(priv, 0, PCI_INTERRUPT_LINE); ++ priv->store_cfg[7] = rcar_pci_get_conf(priv, 1, PCI_INTERRUPT_LINE); ++ priv->store_cfg[8] = rcar_pci_get_conf(priv, 2, PCI_INTERRUPT_LINE); ++ priv->store_cfg[9] = rcar_pci_get_conf(priv, 0, PCI_BASE_ADDRESS_0); ++ priv->store_cfg[10] = rcar_pci_get_conf(priv, 1, PCI_BASE_ADDRESS_0); ++ priv->store_cfg[11] = rcar_pci_get_conf(priv, 2, PCI_BASE_ADDRESS_0); ++#else ++ priv->store_cfg[0] = rcar_pci_get_conf(priv, 0, 0x04); ++ priv->store_cfg[1] = rcar_pci_get_conf(priv, 1, 0x04); ++ priv->store_cfg[2] = rcar_pci_get_conf(priv, 2, 0x04); ++ priv->store_cfg[3] = rcar_pci_get_conf(priv, 0, 0x0c); ++ priv->store_cfg[4] = rcar_pci_get_conf(priv, 1, 0x0c); ++ priv->store_cfg[5] = rcar_pci_get_conf(priv, 2, 0x0c); ++ priv->store_cfg[6] = rcar_pci_get_conf(priv, 0, 0x3c); ++ priv->store_cfg[7] = rcar_pci_get_conf(priv, 1, 0x3c); ++ priv->store_cfg[8] = rcar_pci_get_conf(priv, 2, 0x3c); ++#endif ++ pm_runtime_disable(priv->dev); ++ return 0; ++} ++ ++static int rcar_pci_restore(struct device *dev) ++{ ++ struct clk *clk; ++ void *m; ++ u32 val; ++ struct rcar_pci_priv *priv = keep_priv[to_platform_device(dev)->id]; ++ void __iomem *reg = priv->reg; ++ int id = to_platform_device(dev)->id; ++ ++ pm_runtime_enable(priv->dev); ++ pm_runtime_get_sync(priv->dev); ++ ++ clk = clk_get(NULL, "ehci"); ++ clk_prepare_enable(clk); ++ clk_put(clk); ++ clk = clk_get(NULL, "hsusb"); ++ clk_prepare_enable(clk); ++ clk_put(clk); ++ usb_phy_set_suspend(priv->phy, 0); ++ m = ioremap(0xe61501c4, 4); ++ val = readl(m); ++ iounmap(m); ++ m = ioremap(0xe615014c, 4); ++ writel(val & ~(3 << 3), m); ++ iounmap(m); ++ val = ioread32(reg + RCAR_PCI_UNIT_REV_REG); ++ dev_info(priv->dev, "PCI: bus%u revision %x\n", id, val); ++ ++ /* Disable Direct Power Down State and assert reset */ ++ val = ioread32(reg + RCAR_USBCTR_REG) & ~RCAR_USBCTR_DIRPD; ++#ifndef MCCILDK_CHANGE_DISABLE ++ val |= RCAR_USBCTR_USBH_RST | RCAR_USBCTR_PLL_RST; ++#else ++ val |= RCAR_USBCTR_USBH_RST; ++#endif ++ iowrite32(val, reg + RCAR_USBCTR_REG); ++ udelay(4); ++ /* De-assert reset */ ++#ifndef MCCILDK_CHANGE_DISABLE ++ val &= ~(RCAR_USBCTR_USBH_RST | RCAR_USBCTR_PLL_RST ++ | RCAR_USBCTR_PCICLK_MASK); ++ iowrite32(val, reg + RCAR_USBCTR_REG); ++ /* reset PCIAHB window size */ ++ val &= ~RCAR_USBCTR_PCIAHB_WIN1_MASK; ++ val |= RCAR_USBCTR_PCIAHB_WIN1_1G; ++ iowrite32(val, reg + RCAR_USBCTR_REG); ++#else ++ val &= RCAR_USBCTR_USBH_RST | RCAR_USBCTR_PLL_RST ++ | RCAR_USBCTR_PCICLK_MASK; ++ iowrite32(val, reg + RCAR_USBCTR_REG); ++ val &= RCAR_USBCTR_USBH_RST | RCAR_USBCTR_PLL_RST ++ | RCAR_USBCTR_PCICLK_MASK; ++ iowrite32(val, reg + RCAR_USBCTR_REG); ++ /* reset PCIAHB window size */ ++ val &= RCAR_USBCTR_PCIAHB_WIN1_MASK; ++ val |= RCAR_USBCTR_PCIAHB_WIN1_1G; ++ iowrite32(val, reg + RCAR_USBCTR_REG); ++#endif ++ ++ /* Configure AHB master and slave modes */ ++ iowrite32(RCAR_AHB_BUS_MODE, reg + RCAR_AHB_BUS_CTR_REG); ++ ++ /* PCI-AHB mapping: 0x40000000 base */ ++ iowrite32(0x40000000 | RCAR_PCIAHB_PREFETCH16, ++ reg + RCAR_PCIAHB_WIN1_CTR_REG); ++ ++ /* AHB-PCI mapping: OHCI/EHCI registers */ ++ val = priv->mem_res.start | RCAR_AHBPCI_WIN_CTR_MEM; ++ iowrite32(val, reg + RCAR_AHBPCI_WIN2_CTR_REG); ++ ++ /* Enable PCI interrupts */ ++ iowrite32(RCAR_PCI_INT_A | RCAR_PCI_INT_B | RCAR_PCI_INT_PME, ++ reg + RCAR_PCI_INT_ENABLE_REG); ++ ++ /* Configure PCI arbiter */ ++ val = ioread32(reg + RCAR_PCI_ARBITER_CTR_REG); ++ val |= RCAR_PCI_ARBITER_PCIREQ0 | RCAR_PCI_ARBITER_PCIREQ1 | ++ RCAR_PCI_ARBITER_PCIBP_MODE; ++ iowrite32(val, reg + RCAR_PCI_ARBITER_CTR_REG); ++ ++ /* Enable AHB-PCI bridge PCI configuration access */ ++ iowrite32(RCAR_AHBPCI_WIN1_HOST | RCAR_AHBPCI_WIN_CTR_CFG, ++ reg + RCAR_AHBPCI_WIN1_CTR_REG); ++ ++ val = ioread32(reg + PCI_COMMAND); ++ val |= PCI_COMMAND_SERR | PCI_COMMAND_PARITY | ++ PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; ++ iowrite32(val, reg + PCI_COMMAND); ++ ++ /* Set PCI-AHB Window1 address */ ++ iowrite32(0x40000000 | PCI_BASE_ADDRESS_MEM_PREFETCH, ++ reg + PCI_BASE_ADDRESS_1); ++ /* Set AHB-PCI bridge PCI communication area address */ ++ val = priv->cfg_res->start + RCAR_AHBPCI_PCICOM_OFFSET; ++ iowrite32(val, reg + PCI_BASE_ADDRESS_0); ++ ++ if (priv->irq > 0) ++ rcar_pci_setup_errirq(priv); ++#ifndef MCCILDK_CHANGE_DISABLE ++ rcar_pci_set_conf(priv, 0, PCI_COMMAND, priv->store_cfg[0]); ++ rcar_pci_set_conf(priv, 1, PCI_COMMAND, priv->store_cfg[1]); ++ rcar_pci_set_conf(priv, 2, PCI_COMMAND, priv->store_cfg[2]); ++ rcar_pci_set_conf(priv, 0, PCI_CACHE_LINE_SIZE, priv->store_cfg[3]); ++ rcar_pci_set_conf(priv, 1, PCI_CACHE_LINE_SIZE, priv->store_cfg[4]); ++ rcar_pci_set_conf(priv, 2, PCI_CACHE_LINE_SIZE, priv->store_cfg[5]); ++ rcar_pci_set_conf(priv, 0, PCI_INTERRUPT_LINE, priv->store_cfg[6]); ++ rcar_pci_set_conf(priv, 1, PCI_INTERRUPT_LINE, priv->store_cfg[7]); ++ rcar_pci_set_conf(priv, 2, PCI_INTERRUPT_LINE, priv->store_cfg[8]); ++ rcar_pci_set_conf(priv, 1, PCI_BASE_ADDRESS_0, priv->store_cfg[10]); ++ rcar_pci_set_conf(priv, 2, PCI_BASE_ADDRESS_0, priv->store_cfg[11]); ++#else ++ rcar_pci_set_conf(priv, 1, PCI_COMMAND, PCI_COMMAND_SERR ++ | PCI_COMMAND_PARITY | PCI_COMMAND_MEMORY ++ | PCI_COMMAND_MASTER); ++ rcar_pci_set_conf(priv, 1, PCI_BASE_ADDRESS_0 ++ priv->cfg_res->start - 0x10000); ++ rcar_pci_set_conf(priv, 2, PCI_COMMAND, PCI_COMMAND_SERR ++ | PCI_COMMAND_PARITY | PCI_COMMAND_MEMORY ++ | PCI_COMMAND_MASTER); ++ rcar_pci_set_conf(priv, 2, PCI_BASE_ADDRESS_0, ++ priv->cfg_res->start - 0x10000 + 0x1000); ++ rcar_pci_set_conf(priv, 0, PCI_CACHE_LINE_SIZE, priv->store_cfg[3]); ++ rcar_pci_set_conf(priv, 1, PCI_CACHE_LINE_SIZE, priv->store_cfg[4]); ++ rcar_pci_set_conf(priv, 2, PCI_CACHE_LINE_SIZE, priv->store_cfg[5]); ++ rcar_pci_set_conf(priv, 0, PCI_INTERRUPT_LINE, 0x00020100); ++ rcar_pci_set_conf(priv, 1, PCI_INTERRUPT_LINE, 0x2a010100); ++ rcar_pci_set_conf(priv, 2, PCI_INTERRUPT_LINE, 0x22100200); ++ val = RCAR_AHBPCI_WIN1_DEVICE | RCAR_AHBPCI_WIN_CTR_CFG; ++ iowrite32(val, priv->reg + RCAR_AHBPCI_WIN1_CTR_REG); ++ val = ioread32(priv->reg + 0x04); ++ iowrite32(val | (1 << 1), priv->reg + 0x04); ++ val = ioread32(priv->reg + 0x104); ++ iowrite32(val | (1 << 1), priv->reg + 0x104); ++ ++ val = RCAR_AHBPCI_WIN1_HOST | RCAR_AHBPCI_WIN_CTR_CFG; ++ iowrite32(val, priv->reg + RCAR_AHBPCI_WIN1_CTR_REG); ++#endif + return 0; + } + ++static const struct dev_pm_ops rcar_pci_pm_ops = { ++ .suspend = rcar_pci_suspend, ++ .resume = rcar_pci_resume, ++ .freeze_noirq = rcar_pci_freeze, ++ .restore_noirq = rcar_pci_restore, ++ .thaw = rcar_pci_resume, ++ .poweroff = rcar_pci_suspend ++}; ++ + static struct platform_driver rcar_pci_driver = { + .driver = { + .name = "pci-rcar-gen2", + .owner = THIS_MODULE, + .suppress_bind_attrs = true, ++ .pm = &rcar_pci_pm_ops, + }, + .probe = rcar_pci_probe, + }; +-- +1.8.3.1 +