summaryrefslogtreecommitdiff
path: root/arch/powerpc/sysdev
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/sysdev')
-rw-r--r--arch/powerpc/sysdev/Makefile1
-rw-r--r--arch/powerpc/sysdev/ehv_pic.c10
-rw-r--r--arch/powerpc/sysdev/fsl_ifc.c305
-rw-r--r--arch/powerpc/sysdev/fsl_pci.c178
-rw-r--r--arch/powerpc/sysdev/fsl_pci.h8
5 files changed, 164 insertions, 338 deletions
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile
index f67ac900d870..afbcc37aa094 100644
--- a/arch/powerpc/sysdev/Makefile
+++ b/arch/powerpc/sysdev/Makefile
@@ -21,7 +21,6 @@ obj-$(CONFIG_FSL_SOC) += fsl_soc.o fsl_mpic_err.o
obj-$(CONFIG_FSL_PCI) += fsl_pci.o $(fsl-msi-obj-y)
obj-$(CONFIG_FSL_PMC) += fsl_pmc.o
obj-$(CONFIG_FSL_LBC) += fsl_lbc.o
-obj-$(CONFIG_FSL_IFC) += fsl_ifc.o
obj-$(CONFIG_FSL_GTM) += fsl_gtm.o
obj-$(CONFIG_FSL_85XX_CACHE_SRAM) += fsl_85xx_l2ctlr.o fsl_85xx_cache_sram.o
obj-$(CONFIG_SIMPLE_GPIO) += simple_gpio.o
diff --git a/arch/powerpc/sysdev/ehv_pic.c b/arch/powerpc/sysdev/ehv_pic.c
index b74085cea1af..2d20f10a4203 100644
--- a/arch/powerpc/sysdev/ehv_pic.c
+++ b/arch/powerpc/sysdev/ehv_pic.c
@@ -28,8 +28,6 @@
#include <asm/ehv_pic.h>
#include <asm/fsl_hcalls.h>
-#include "../../../kernel/irq/settings.h"
-
static struct ehv_pic *global_ehv_pic;
static DEFINE_SPINLOCK(ehv_pic_lock);
@@ -113,17 +111,13 @@ static unsigned int ehv_pic_type_to_vecpri(unsigned int type)
int ehv_pic_set_irq_type(struct irq_data *d, unsigned int flow_type)
{
unsigned int src = virq_to_hw(d->irq);
- struct irq_desc *desc = irq_to_desc(d->irq);
unsigned int vecpri, vold, vnew, prio, cpu_dest;
unsigned long flags;
if (flow_type == IRQ_TYPE_NONE)
flow_type = IRQ_TYPE_LEVEL_LOW;
- irq_settings_clr_level(desc);
- irq_settings_set_trigger_mask(desc, flow_type);
- if (flow_type & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW))
- irq_settings_set_level(desc);
+ irqd_set_trigger_type(d, flow_type);
vecpri = ehv_pic_type_to_vecpri(flow_type);
@@ -144,7 +138,7 @@ int ehv_pic_set_irq_type(struct irq_data *d, unsigned int flow_type)
ev_int_set_config(src, vecpri, prio, cpu_dest);
spin_unlock_irqrestore(&ehv_pic_lock, flags);
- return 0;
+ return IRQ_SET_MASK_OK_NOCOPY;
}
static struct irq_chip ehv_pic_irq_chip = {
diff --git a/arch/powerpc/sysdev/fsl_ifc.c b/arch/powerpc/sysdev/fsl_ifc.c
deleted file mode 100644
index fbc885b31946..000000000000
--- a/arch/powerpc/sysdev/fsl_ifc.c
+++ /dev/null
@@ -1,305 +0,0 @@
-/*
- * Copyright 2011 Freescale Semiconductor, Inc
- *
- * Freescale Integrated Flash Controller
- *
- * Author: Dipen Dudhat <Dipen.Dudhat@freescale.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/compiler.h>
-#include <linux/spinlock.h>
-#include <linux/types.h>
-#include <linux/slab.h>
-#include <linux/io.h>
-#include <linux/of.h>
-#include <linux/of_device.h>
-#include <linux/platform_device.h>
-#include <asm/prom.h>
-#include <asm/fsl_ifc.h>
-
-struct fsl_ifc_ctrl *fsl_ifc_ctrl_dev;
-EXPORT_SYMBOL(fsl_ifc_ctrl_dev);
-
-/*
- * convert_ifc_address - convert the base address
- * @addr_base: base address of the memory bank
- */
-unsigned int convert_ifc_address(phys_addr_t addr_base)
-{
- return addr_base & CSPR_BA;
-}
-EXPORT_SYMBOL(convert_ifc_address);
-
-/*
- * fsl_ifc_find - find IFC bank
- * @addr_base: base address of the memory bank
- *
- * This function walks IFC banks comparing "Base address" field of the CSPR
- * registers with the supplied addr_base argument. When bases match this
- * function returns bank number (starting with 0), otherwise it returns
- * appropriate errno value.
- */
-int fsl_ifc_find(phys_addr_t addr_base)
-{
- int i = 0;
-
- if (!fsl_ifc_ctrl_dev || !fsl_ifc_ctrl_dev->regs)
- return -ENODEV;
-
- for (i = 0; i < ARRAY_SIZE(fsl_ifc_ctrl_dev->regs->cspr_cs); i++) {
- u32 cspr = in_be32(&fsl_ifc_ctrl_dev->regs->cspr_cs[i].cspr);
- if (cspr & CSPR_V && (cspr & CSPR_BA) ==
- convert_ifc_address(addr_base))
- return i;
- }
-
- return -ENOENT;
-}
-EXPORT_SYMBOL(fsl_ifc_find);
-
-static int fsl_ifc_ctrl_init(struct fsl_ifc_ctrl *ctrl)
-{
- struct fsl_ifc_regs __iomem *ifc = ctrl->regs;
-
- /*
- * Clear all the common status and event registers
- */
- if (in_be32(&ifc->cm_evter_stat) & IFC_CM_EVTER_STAT_CSER)
- out_be32(&ifc->cm_evter_stat, IFC_CM_EVTER_STAT_CSER);
-
- /* enable all error and events */
- out_be32(&ifc->cm_evter_en, IFC_CM_EVTER_EN_CSEREN);
-
- /* enable all error and event interrupts */
- out_be32(&ifc->cm_evter_intr_en, IFC_CM_EVTER_INTR_EN_CSERIREN);
- out_be32(&ifc->cm_erattr0, 0x0);
- out_be32(&ifc->cm_erattr1, 0x0);
-
- return 0;
-}
-
-static int fsl_ifc_ctrl_remove(struct platform_device *dev)
-{
- struct fsl_ifc_ctrl *ctrl = dev_get_drvdata(&dev->dev);
-
- free_irq(ctrl->nand_irq, ctrl);
- free_irq(ctrl->irq, ctrl);
-
- irq_dispose_mapping(ctrl->nand_irq);
- irq_dispose_mapping(ctrl->irq);
-
- iounmap(ctrl->regs);
-
- dev_set_drvdata(&dev->dev, NULL);
- kfree(ctrl);
-
- return 0;
-}
-
-/*
- * NAND events are split between an operational interrupt which only
- * receives OPC, and an error interrupt that receives everything else,
- * including non-NAND errors. Whichever interrupt gets to it first
- * records the status and wakes the wait queue.
- */
-static DEFINE_SPINLOCK(nand_irq_lock);
-
-static u32 check_nand_stat(struct fsl_ifc_ctrl *ctrl)
-{
- struct fsl_ifc_regs __iomem *ifc = ctrl->regs;
- unsigned long flags;
- u32 stat;
-
- spin_lock_irqsave(&nand_irq_lock, flags);
-
- stat = in_be32(&ifc->ifc_nand.nand_evter_stat);
- if (stat) {
- out_be32(&ifc->ifc_nand.nand_evter_stat, stat);
- ctrl->nand_stat = stat;
- wake_up(&ctrl->nand_wait);
- }
-
- spin_unlock_irqrestore(&nand_irq_lock, flags);
-
- return stat;
-}
-
-static irqreturn_t fsl_ifc_nand_irq(int irqno, void *data)
-{
- struct fsl_ifc_ctrl *ctrl = data;
-
- if (check_nand_stat(ctrl))
- return IRQ_HANDLED;
-
- return IRQ_NONE;
-}
-
-/*
- * NOTE: This interrupt is used to report ifc events of various kinds,
- * such as transaction errors on the chipselects.
- */
-static irqreturn_t fsl_ifc_ctrl_irq(int irqno, void *data)
-{
- struct fsl_ifc_ctrl *ctrl = data;
- struct fsl_ifc_regs __iomem *ifc = ctrl->regs;
- u32 err_axiid, err_srcid, status, cs_err, err_addr;
- irqreturn_t ret = IRQ_NONE;
-
- /* read for chip select error */
- cs_err = in_be32(&ifc->cm_evter_stat);
- if (cs_err) {
- dev_err(ctrl->dev, "transaction sent to IFC is not mapped to"
- "any memory bank 0x%08X\n", cs_err);
- /* clear the chip select error */
- out_be32(&ifc->cm_evter_stat, IFC_CM_EVTER_STAT_CSER);
-
- /* read error attribute registers print the error information */
- status = in_be32(&ifc->cm_erattr0);
- err_addr = in_be32(&ifc->cm_erattr1);
-
- if (status & IFC_CM_ERATTR0_ERTYP_READ)
- dev_err(ctrl->dev, "Read transaction error"
- "CM_ERATTR0 0x%08X\n", status);
- else
- dev_err(ctrl->dev, "Write transaction error"
- "CM_ERATTR0 0x%08X\n", status);
-
- err_axiid = (status & IFC_CM_ERATTR0_ERAID) >>
- IFC_CM_ERATTR0_ERAID_SHIFT;
- dev_err(ctrl->dev, "AXI ID of the error"
- "transaction 0x%08X\n", err_axiid);
-
- err_srcid = (status & IFC_CM_ERATTR0_ESRCID) >>
- IFC_CM_ERATTR0_ESRCID_SHIFT;
- dev_err(ctrl->dev, "SRC ID of the error"
- "transaction 0x%08X\n", err_srcid);
-
- dev_err(ctrl->dev, "Transaction Address corresponding to error"
- "ERADDR 0x%08X\n", err_addr);
-
- ret = IRQ_HANDLED;
- }
-
- if (check_nand_stat(ctrl))
- ret = IRQ_HANDLED;
-
- return ret;
-}
-
-/*
- * fsl_ifc_ctrl_probe
- *
- * called by device layer when it finds a device matching
- * one our driver can handled. This code allocates all of
- * the resources needed for the controller only. The
- * resources for the NAND banks themselves are allocated
- * in the chip probe function.
-*/
-static int fsl_ifc_ctrl_probe(struct platform_device *dev)
-{
- int ret = 0;
-
-
- dev_info(&dev->dev, "Freescale Integrated Flash Controller\n");
-
- fsl_ifc_ctrl_dev = kzalloc(sizeof(*fsl_ifc_ctrl_dev), GFP_KERNEL);
- if (!fsl_ifc_ctrl_dev)
- return -ENOMEM;
-
- dev_set_drvdata(&dev->dev, fsl_ifc_ctrl_dev);
-
- /* IOMAP the entire IFC region */
- fsl_ifc_ctrl_dev->regs = of_iomap(dev->dev.of_node, 0);
- if (!fsl_ifc_ctrl_dev->regs) {
- dev_err(&dev->dev, "failed to get memory region\n");
- ret = -ENODEV;
- goto err;
- }
-
- /* get the Controller level irq */
- fsl_ifc_ctrl_dev->irq = irq_of_parse_and_map(dev->dev.of_node, 0);
- if (fsl_ifc_ctrl_dev->irq == NO_IRQ) {
- dev_err(&dev->dev, "failed to get irq resource "
- "for IFC\n");
- ret = -ENODEV;
- goto err;
- }
-
- /* get the nand machine irq */
- fsl_ifc_ctrl_dev->nand_irq =
- irq_of_parse_and_map(dev->dev.of_node, 1);
-
- fsl_ifc_ctrl_dev->dev = &dev->dev;
-
- ret = fsl_ifc_ctrl_init(fsl_ifc_ctrl_dev);
- if (ret < 0)
- goto err;
-
- init_waitqueue_head(&fsl_ifc_ctrl_dev->nand_wait);
-
- ret = request_irq(fsl_ifc_ctrl_dev->irq, fsl_ifc_ctrl_irq, IRQF_SHARED,
- "fsl-ifc", fsl_ifc_ctrl_dev);
- if (ret != 0) {
- dev_err(&dev->dev, "failed to install irq (%d)\n",
- fsl_ifc_ctrl_dev->irq);
- goto err_irq;
- }
-
- if (fsl_ifc_ctrl_dev->nand_irq) {
- ret = request_irq(fsl_ifc_ctrl_dev->nand_irq, fsl_ifc_nand_irq,
- 0, "fsl-ifc-nand", fsl_ifc_ctrl_dev);
- if (ret != 0) {
- dev_err(&dev->dev, "failed to install irq (%d)\n",
- fsl_ifc_ctrl_dev->nand_irq);
- goto err_nandirq;
- }
- }
-
- return 0;
-
-err_nandirq:
- free_irq(fsl_ifc_ctrl_dev->nand_irq, fsl_ifc_ctrl_dev);
- irq_dispose_mapping(fsl_ifc_ctrl_dev->nand_irq);
-err_irq:
- free_irq(fsl_ifc_ctrl_dev->irq, fsl_ifc_ctrl_dev);
- irq_dispose_mapping(fsl_ifc_ctrl_dev->irq);
-err:
- return ret;
-}
-
-static const struct of_device_id fsl_ifc_match[] = {
- {
- .compatible = "fsl,ifc",
- },
- {},
-};
-
-static struct platform_driver fsl_ifc_ctrl_driver = {
- .driver = {
- .name = "fsl-ifc",
- .of_match_table = fsl_ifc_match,
- },
- .probe = fsl_ifc_ctrl_probe,
- .remove = fsl_ifc_ctrl_remove,
-};
-
-module_platform_driver(fsl_ifc_ctrl_driver);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Freescale Semiconductor");
-MODULE_DESCRIPTION("Freescale Integrated Flash Controller driver");
diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c
index a625dcf26b2b..3f415e252ea5 100644
--- a/arch/powerpc/sysdev/fsl_pci.c
+++ b/arch/powerpc/sysdev/fsl_pci.c
@@ -22,10 +22,13 @@
#include <linux/delay.h>
#include <linux/string.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/bootmem.h>
#include <linux/memblock.h>
#include <linux/log2.h>
#include <linux/slab.h>
+#include <linux/suspend.h>
+#include <linux/syscore_ops.h>
#include <linux/uaccess.h>
#include <asm/io.h>
@@ -868,6 +871,14 @@ u64 fsl_pci_immrbar_base(struct pci_controller *hose)
pci_bus_read_config_dword(hose->bus,
PCI_DEVFN(0, 0), PCI_BASE_ADDRESS_0, &base);
+
+ /*
+ * For PEXCSRBAR, bit 3-0 indicate prefetchable and
+ * address type. So when getting base address, these
+ * bits should be masked
+ */
+ base &= PCI_BASE_ADDRESS_MEM_MASK;
+
return base;
}
#endif
@@ -1086,55 +1097,171 @@ void fsl_pci_assign_primary(void)
}
}
-static int fsl_pci_probe(struct platform_device *pdev)
+#ifdef CONFIG_PM_SLEEP
+static irqreturn_t fsl_pci_pme_handle(int irq, void *dev_id)
{
- int ret;
- struct device_node *node;
+ struct pci_controller *hose = dev_id;
+ struct ccsr_pci __iomem *pci = hose->private_data;
+ u32 dr;
- node = pdev->dev.of_node;
- ret = fsl_add_bridge(pdev, fsl_pci_primary == node);
+ dr = in_be32(&pci->pex_pme_mes_dr);
+ if (!dr)
+ return IRQ_NONE;
- mpc85xx_pci_err_probe(pdev);
+ out_be32(&pci->pex_pme_mes_dr, dr);
- return 0;
+ return IRQ_HANDLED;
}
-#ifdef CONFIG_PM
-static int fsl_pci_resume(struct device *dev)
+static int fsl_pci_pme_probe(struct pci_controller *hose)
{
- struct pci_controller *hose;
- struct resource pci_rsrc;
+ struct ccsr_pci __iomem *pci;
+ struct pci_dev *dev;
+ int pme_irq;
+ int res;
+ u16 pms;
- hose = pci_find_hose_for_OF_device(dev->of_node);
- if (!hose)
- return -ENODEV;
+ /* Get hose's pci_dev */
+ dev = list_first_entry(&hose->bus->devices, typeof(*dev), bus_list);
+
+ /* PME Disable */
+ pci_read_config_word(dev, dev->pm_cap + PCI_PM_CTRL, &pms);
+ pms &= ~PCI_PM_CTRL_PME_ENABLE;
+ pci_write_config_word(dev, dev->pm_cap + PCI_PM_CTRL, pms);
+
+ pme_irq = irq_of_parse_and_map(hose->dn, 0);
+ if (!pme_irq) {
+ dev_err(&dev->dev, "Failed to map PME interrupt.\n");
+
+ return -ENXIO;
+ }
+
+ res = devm_request_irq(hose->parent, pme_irq,
+ fsl_pci_pme_handle,
+ IRQF_SHARED,
+ "[PCI] PME", hose);
+ if (res < 0) {
+ dev_err(&dev->dev, "Unable to requiest irq %d for PME\n", pme_irq);
+ irq_dispose_mapping(pme_irq);
- if (of_address_to_resource(dev->of_node, 0, &pci_rsrc)) {
- dev_err(dev, "Get pci register base failed.");
return -ENODEV;
}
- setup_pci_atmu(hose);
+ pci = hose->private_data;
+
+ /* Enable PTOD, ENL23D & EXL23D */
+ out_be32(&pci->pex_pme_mes_disr, 0);
+ setbits32(&pci->pex_pme_mes_disr,
+ PME_DISR_EN_PTOD | PME_DISR_EN_ENL23D | PME_DISR_EN_EXL23D);
+
+ out_be32(&pci->pex_pme_mes_ier, 0);
+ setbits32(&pci->pex_pme_mes_ier,
+ PME_DISR_EN_PTOD | PME_DISR_EN_ENL23D | PME_DISR_EN_EXL23D);
+
+ /* PME Enable */
+ pci_read_config_word(dev, dev->pm_cap + PCI_PM_CTRL, &pms);
+ pms |= PCI_PM_CTRL_PME_ENABLE;
+ pci_write_config_word(dev, dev->pm_cap + PCI_PM_CTRL, pms);
return 0;
}
-static const struct dev_pm_ops pci_pm_ops = {
- .resume = fsl_pci_resume,
-};
+static void send_pme_turnoff_message(struct pci_controller *hose)
+{
+ struct ccsr_pci __iomem *pci = hose->private_data;
+ u32 dr;
+ int i;
-#define PCI_PM_OPS (&pci_pm_ops)
+ /* Send PME_Turn_Off Message Request */
+ setbits32(&pci->pex_pmcr, PEX_PMCR_PTOMR);
-#else
+ /* Wait trun off done */
+ for (i = 0; i < 150; i++) {
+ dr = in_be32(&pci->pex_pme_mes_dr);
+ if (dr) {
+ out_be32(&pci->pex_pme_mes_dr, dr);
+ break;
+ }
+
+ udelay(1000);
+ }
+}
+
+static void fsl_pci_syscore_do_suspend(struct pci_controller *hose)
+{
+ send_pme_turnoff_message(hose);
+}
+
+static int fsl_pci_syscore_suspend(void)
+{
+ struct pci_controller *hose, *tmp;
-#define PCI_PM_OPS NULL
+ list_for_each_entry_safe(hose, tmp, &hose_list, list_node)
+ fsl_pci_syscore_do_suspend(hose);
+ return 0;
+}
+
+static void fsl_pci_syscore_do_resume(struct pci_controller *hose)
+{
+ struct ccsr_pci __iomem *pci = hose->private_data;
+ u32 dr;
+ int i;
+
+ /* Send Exit L2 State Message */
+ setbits32(&pci->pex_pmcr, PEX_PMCR_EXL2S);
+
+ /* Wait exit done */
+ for (i = 0; i < 150; i++) {
+ dr = in_be32(&pci->pex_pme_mes_dr);
+ if (dr) {
+ out_be32(&pci->pex_pme_mes_dr, dr);
+ break;
+ }
+
+ udelay(1000);
+ }
+
+ setup_pci_atmu(hose);
+}
+
+static void fsl_pci_syscore_resume(void)
+{
+ struct pci_controller *hose, *tmp;
+
+ list_for_each_entry_safe(hose, tmp, &hose_list, list_node)
+ fsl_pci_syscore_do_resume(hose);
+}
+
+static struct syscore_ops pci_syscore_pm_ops = {
+ .suspend = fsl_pci_syscore_suspend,
+ .resume = fsl_pci_syscore_resume,
+};
#endif
+void fsl_pcibios_fixup_phb(struct pci_controller *phb)
+{
+#ifdef CONFIG_PM_SLEEP
+ fsl_pci_pme_probe(phb);
+#endif
+}
+
+static int fsl_pci_probe(struct platform_device *pdev)
+{
+ struct device_node *node;
+ int ret;
+
+ node = pdev->dev.of_node;
+ ret = fsl_add_bridge(pdev, fsl_pci_primary == node);
+
+ mpc85xx_pci_err_probe(pdev);
+
+ return 0;
+}
+
static struct platform_driver fsl_pci_driver = {
.driver = {
.name = "fsl-pci",
- .pm = PCI_PM_OPS,
.of_match_table = pci_ids,
},
.probe = fsl_pci_probe,
@@ -1142,6 +1269,9 @@ static struct platform_driver fsl_pci_driver = {
static int __init fsl_pci_init(void)
{
+#ifdef CONFIG_PM_SLEEP
+ register_syscore_ops(&pci_syscore_pm_ops);
+#endif
return platform_driver_register(&fsl_pci_driver);
}
arch_initcall(fsl_pci_init);
diff --git a/arch/powerpc/sysdev/fsl_pci.h b/arch/powerpc/sysdev/fsl_pci.h
index 8d455df58471..c1cec771d5ea 100644
--- a/arch/powerpc/sysdev/fsl_pci.h
+++ b/arch/powerpc/sysdev/fsl_pci.h
@@ -32,6 +32,13 @@ struct platform_device;
#define PIWAR_WRITE_SNOOP 0x00005000
#define PIWAR_SZ_MASK 0x0000003f
+#define PEX_PMCR_PTOMR 0x1
+#define PEX_PMCR_EXL2S 0x2
+
+#define PME_DISR_EN_PTOD 0x00008000
+#define PME_DISR_EN_ENL23D 0x00002000
+#define PME_DISR_EN_EXL23D 0x00001000
+
/* PCI/PCI Express outbound window reg */
struct pci_outbound_window_regs {
__be32 potar; /* 0x.0 - Outbound translation address register */
@@ -111,6 +118,7 @@ struct ccsr_pci {
extern int fsl_add_bridge(struct platform_device *pdev, int is_primary);
extern void fsl_pcibios_fixup_bus(struct pci_bus *bus);
+extern void fsl_pcibios_fixup_phb(struct pci_controller *phb);
extern int mpc83xx_add_bridge(struct device_node *dev);
u64 fsl_pci_immrbar_base(struct pci_controller *hose);