aboutsummaryrefslogtreecommitdiff
path: root/arch/powerpc/sysdev
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/sysdev')
-rw-r--r--arch/powerpc/sysdev/Kconfig9
-rw-r--r--arch/powerpc/sysdev/Makefile10
-rw-r--r--arch/powerpc/sysdev/axonram.c21
-rw-r--r--arch/powerpc/sysdev/bestcomm/Kconfig36
-rw-r--r--arch/powerpc/sysdev/bestcomm/Makefile14
-rw-r--r--arch/powerpc/sysdev/bestcomm/ata.c157
-rw-r--r--arch/powerpc/sysdev/bestcomm/ata.h30
-rw-r--r--arch/powerpc/sysdev/bestcomm/bcom_ata_task.c67
-rw-r--r--arch/powerpc/sysdev/bestcomm/bcom_fec_rx_task.c78
-rw-r--r--arch/powerpc/sysdev/bestcomm/bcom_fec_tx_task.c91
-rw-r--r--arch/powerpc/sysdev/bestcomm/bcom_gen_bd_rx_task.c63
-rw-r--r--arch/powerpc/sysdev/bestcomm/bcom_gen_bd_tx_task.c69
-rw-r--r--arch/powerpc/sysdev/bestcomm/bestcomm.c531
-rw-r--r--arch/powerpc/sysdev/bestcomm/bestcomm.h213
-rw-r--r--arch/powerpc/sysdev/bestcomm/bestcomm_priv.h350
-rw-r--r--arch/powerpc/sysdev/bestcomm/fec.c270
-rw-r--r--arch/powerpc/sysdev/bestcomm/fec.h61
-rw-r--r--arch/powerpc/sysdev/bestcomm/gen_bd.c354
-rw-r--r--arch/powerpc/sysdev/bestcomm/gen_bd.h53
-rw-r--r--arch/powerpc/sysdev/bestcomm/sram.c178
-rw-r--r--arch/powerpc/sysdev/bestcomm/sram.h54
-rw-r--r--arch/powerpc/sysdev/cpm1.c1
-rw-r--r--arch/powerpc/sysdev/cpm2_pic.c1
-rw-r--r--arch/powerpc/sysdev/cpm_common.c1
-rw-r--r--arch/powerpc/sysdev/dart_iommu.c6
-rw-r--r--arch/powerpc/sysdev/dcr.c6
-rw-r--r--arch/powerpc/sysdev/ehv_pic.c13
-rw-r--r--arch/powerpc/sysdev/fsl_85xx_l2ctlr.c1
-rw-r--r--arch/powerpc/sysdev/fsl_gtm.c11
-rw-r--r--arch/powerpc/sysdev/fsl_ifc.c306
-rw-r--r--arch/powerpc/sysdev/fsl_lbc.c37
-rw-r--r--arch/powerpc/sysdev/fsl_mpic_timer_wakeup.c161
-rw-r--r--arch/powerpc/sysdev/fsl_msi.c145
-rw-r--r--arch/powerpc/sysdev/fsl_msi.h10
-rw-r--r--arch/powerpc/sysdev/fsl_pci.c498
-rw-r--r--arch/powerpc/sysdev/fsl_pci.h34
-rw-r--r--arch/powerpc/sysdev/fsl_pmc.c1
-rw-r--r--arch/powerpc/sysdev/fsl_rio.c13
-rw-r--r--arch/powerpc/sysdev/fsl_rmu.c7
-rw-r--r--arch/powerpc/sysdev/fsl_soc.c36
-rw-r--r--arch/powerpc/sysdev/fsl_soc.h3
-rw-r--r--arch/powerpc/sysdev/ge/ge_pic.h1
-rw-r--r--arch/powerpc/sysdev/i8259.c1
-rw-r--r--arch/powerpc/sysdev/indirect_pci.c16
-rw-r--r--arch/powerpc/sysdev/mpc5xxx_clocks.c4
-rw-r--r--arch/powerpc/sysdev/mpc8xx_pic.c1
-rw-r--r--arch/powerpc/sysdev/mpic.c160
-rw-r--r--arch/powerpc/sysdev/mpic_msgr.c6
-rw-r--r--arch/powerpc/sysdev/mpic_msi.c8
-rw-r--r--arch/powerpc/sysdev/mpic_timer.c601
-rw-r--r--arch/powerpc/sysdev/msi_bitmap.c2
-rw-r--r--arch/powerpc/sysdev/mv64x60_dev.c18
-rw-r--r--arch/powerpc/sysdev/mv64x60_udbg.c2
-rw-r--r--arch/powerpc/sysdev/of_rtc.c1
-rw-r--r--arch/powerpc/sysdev/ppc4xx_hsta_msi.c215
-rw-r--r--arch/powerpc/sysdev/ppc4xx_ocm.c416
-rw-r--r--arch/powerpc/sysdev/ppc4xx_pci.c38
-rw-r--r--arch/powerpc/sysdev/ppc4xx_soc.c1
-rw-r--r--arch/powerpc/sysdev/qe_lib/Kconfig2
-rw-r--r--arch/powerpc/sysdev/qe_lib/qe_io.c1
-rw-r--r--arch/powerpc/sysdev/qe_lib/ucc.c1
-rw-r--r--arch/powerpc/sysdev/qe_lib/ucc_fast.c1
-rw-r--r--arch/powerpc/sysdev/qe_lib/ucc_slow.c1
-rw-r--r--arch/powerpc/sysdev/rtc_cmos_setup.c5
-rw-r--r--arch/powerpc/sysdev/scom.c168
-rw-r--r--arch/powerpc/sysdev/udbg_memcons.c104
-rw-r--r--arch/powerpc/sysdev/xics/icp-hv.c1
-rw-r--r--arch/powerpc/sysdev/xics/icp-native.c21
-rw-r--r--arch/powerpc/sysdev/xics/ics-opal.c19
-rw-r--r--arch/powerpc/sysdev/xics/ics-rtas.c2
-rw-r--r--arch/powerpc/sysdev/xics/xics-common.c10
-rw-r--r--arch/powerpc/sysdev/xilinx_intc.c2
72 files changed, 2466 insertions, 3363 deletions
diff --git a/arch/powerpc/sysdev/Kconfig b/arch/powerpc/sysdev/Kconfig
index a84fecf63c4..a19332a3871 100644
--- a/arch/powerpc/sysdev/Kconfig
+++ b/arch/powerpc/sysdev/Kconfig
@@ -7,6 +7,12 @@ config PPC4xx_PCI_EXPRESS
depends on PCI && 4xx
default n
+config PPC4xx_HSTA_MSI
+ bool
+ depends on PCI_MSI
+ depends on PCI && 4xx
+ default n
+
config PPC4xx_MSI
bool
depends on PCI_MSI
@@ -19,6 +25,7 @@ config PPC_MSI_BITMAP
default y if MPIC
default y if FSL_PCI
default y if PPC4xx_MSI
+ default y if PPC_POWERNV
source "arch/powerpc/sysdev/xics/Kconfig"
@@ -27,7 +34,7 @@ config PPC_SCOM
config SCOM_DEBUGFS
bool "Expose SCOM controllers via debugfs"
- depends on PPC_SCOM
+ depends on PPC_SCOM && DEBUG_FS
default n
config GE_FPGA
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile
index a57600b3a4e..f7cb2a1b01f 100644
--- a/arch/powerpc/sysdev/Makefile
+++ b/arch/powerpc/sysdev/Makefile
@@ -1,9 +1,11 @@
subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror
-ccflags-$(CONFIG_PPC64) := -mno-minimal-toc
+ccflags-$(CONFIG_PPC64) := $(NO_MINIMAL_TOC)
mpic-msi-obj-$(CONFIG_PCI_MSI) += mpic_msi.o mpic_u3msi.o mpic_pasemi_msi.o
obj-$(CONFIG_MPIC) += mpic.o $(mpic-msi-obj-y)
+obj-$(CONFIG_MPIC_TIMER) += mpic_timer.o
+obj-$(CONFIG_FSL_MPIC_TIMER_WAKEUP) += fsl_mpic_timer_wakeup.o
mpic-msgr-obj-$(CONFIG_MPIC_MSGR) += mpic_msgr.o
obj-$(CONFIG_MPIC) += mpic.o $(mpic-msi-obj-y) $(mpic-msgr-obj-y)
obj-$(CONFIG_PPC_EPAPR_HV_PIC) += ehv_pic.o
@@ -19,14 +21,12 @@ 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
obj-$(CONFIG_FSL_RIO) += fsl_rio.o fsl_rmu.o
obj-$(CONFIG_TSI108_BRIDGE) += tsi108_pci.o tsi108_dev.o
obj-$(CONFIG_QUICC_ENGINE) += qe_lib/
-obj-$(CONFIG_PPC_BESTCOMM) += bestcomm/
mv64x60-$(CONFIG_PCI) += mv64x60_pci.o
obj-$(CONFIG_MV64X60) += $(mv64x60-y) mv64x60_pic.o mv64x60_dev.o \
mv64x60_udbg.o
@@ -37,6 +37,7 @@ obj-$(CONFIG_PPC_INDIRECT_PCI) += indirect_pci.o
obj-$(CONFIG_PPC_I8259) += i8259.o
obj-$(CONFIG_IPIC) += ipic.o
obj-$(CONFIG_4xx) += uic.o
+obj-$(CONFIG_PPC4xx_OCM) += ppc4xx_ocm.o
obj-$(CONFIG_4xx_SOC) += ppc4xx_soc.o
obj-$(CONFIG_XILINX_VIRTEX) += xilinx_intc.o
obj-$(CONFIG_XILINX_PCI) += xilinx_pci.o
@@ -44,6 +45,7 @@ obj-$(CONFIG_OF_RTC) += of_rtc.o
ifeq ($(CONFIG_PCI),y)
obj-$(CONFIG_4xx) += ppc4xx_pci.o
endif
+obj-$(CONFIG_PPC4xx_HSTA_MSI) += ppc4xx_hsta_msi.o
obj-$(CONFIG_PPC4xx_MSI) += ppc4xx_msi.o
obj-$(CONFIG_PPC4xx_CPM) += ppc4xx_cpm.o
obj-$(CONFIG_PPC4xx_GPIO) += ppc4xx_gpio.o
@@ -64,6 +66,8 @@ endif
obj-$(CONFIG_PPC_SCOM) += scom.o
+obj-$(CONFIG_PPC_EARLY_DEBUG_MEMCONS) += udbg_memcons.o
+
subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror
obj-$(CONFIG_PPC_XICS) += xics/
diff --git a/arch/powerpc/sysdev/axonram.c b/arch/powerpc/sysdev/axonram.c
index 1c16141c031..47b6b9f81d4 100644
--- a/arch/powerpc/sysdev/axonram.c
+++ b/arch/powerpc/sysdev/axonram.c
@@ -109,27 +109,28 @@ axon_ram_make_request(struct request_queue *queue, struct bio *bio)
struct axon_ram_bank *bank = bio->bi_bdev->bd_disk->private_data;
unsigned long phys_mem, phys_end;
void *user_mem;
- struct bio_vec *vec;
+ struct bio_vec vec;
unsigned int transfered;
- unsigned short idx;
+ struct bvec_iter iter;
- phys_mem = bank->io_addr + (bio->bi_sector << AXON_RAM_SECTOR_SHIFT);
+ phys_mem = bank->io_addr + (bio->bi_iter.bi_sector <<
+ AXON_RAM_SECTOR_SHIFT);
phys_end = bank->io_addr + bank->size;
transfered = 0;
- bio_for_each_segment(vec, bio, idx) {
- if (unlikely(phys_mem + vec->bv_len > phys_end)) {
+ bio_for_each_segment(vec, bio, iter) {
+ if (unlikely(phys_mem + vec.bv_len > phys_end)) {
bio_io_error(bio);
return;
}
- user_mem = page_address(vec->bv_page) + vec->bv_offset;
+ user_mem = page_address(vec.bv_page) + vec.bv_offset;
if (bio_data_dir(bio) == READ)
- memcpy(user_mem, (void *) phys_mem, vec->bv_len);
+ memcpy(user_mem, (void *) phys_mem, vec.bv_len);
else
- memcpy((void *) phys_mem, user_mem, vec->bv_len);
+ memcpy((void *) phys_mem, user_mem, vec.bv_len);
- phys_mem += vec->bv_len;
- transfered += vec->bv_len;
+ phys_mem += vec.bv_len;
+ transfered += vec.bv_len;
}
bio_endio(bio, 0);
}
diff --git a/arch/powerpc/sysdev/bestcomm/Kconfig b/arch/powerpc/sysdev/bestcomm/Kconfig
deleted file mode 100644
index 29e427085ef..00000000000
--- a/arch/powerpc/sysdev/bestcomm/Kconfig
+++ /dev/null
@@ -1,36 +0,0 @@
-#
-# Kconfig options for Bestcomm
-#
-
-config PPC_BESTCOMM
- tristate "Bestcomm DMA engine support"
- depends on PPC_MPC52xx
- default n
- select PPC_LIB_RHEAP
- help
- BestComm is the name of the communication coprocessor found
- on the Freescale MPC5200 family of processor. Its usage is
- optional for some drivers (like ATA), but required for
- others (like FEC).
-
- If you want to use drivers that require DMA operations,
- answer Y or M. Otherwise say N.
-
-config PPC_BESTCOMM_ATA
- tristate
- depends on PPC_BESTCOMM
- help
- This option enables the support for the ATA task.
-
-config PPC_BESTCOMM_FEC
- tristate
- depends on PPC_BESTCOMM
- help
- This option enables the support for the FEC tasks.
-
-config PPC_BESTCOMM_GEN_BD
- tristate
- depends on PPC_BESTCOMM
- help
- This option enables the support for the GenBD tasks.
-
diff --git a/arch/powerpc/sysdev/bestcomm/Makefile b/arch/powerpc/sysdev/bestcomm/Makefile
deleted file mode 100644
index aed2df2a658..00000000000
--- a/arch/powerpc/sysdev/bestcomm/Makefile
+++ /dev/null
@@ -1,14 +0,0 @@
-#
-# Makefile for BestComm & co
-#
-
-bestcomm-core-objs := bestcomm.o sram.o
-bestcomm-ata-objs := ata.o bcom_ata_task.o
-bestcomm-fec-objs := fec.o bcom_fec_rx_task.o bcom_fec_tx_task.o
-bestcomm-gen-bd-objs := gen_bd.o bcom_gen_bd_rx_task.o bcom_gen_bd_tx_task.o
-
-obj-$(CONFIG_PPC_BESTCOMM) += bestcomm-core.o
-obj-$(CONFIG_PPC_BESTCOMM_ATA) += bestcomm-ata.o
-obj-$(CONFIG_PPC_BESTCOMM_FEC) += bestcomm-fec.o
-obj-$(CONFIG_PPC_BESTCOMM_GEN_BD) += bestcomm-gen-bd.o
-
diff --git a/arch/powerpc/sysdev/bestcomm/ata.c b/arch/powerpc/sysdev/bestcomm/ata.c
deleted file mode 100644
index 901c9f91e5d..00000000000
--- a/arch/powerpc/sysdev/bestcomm/ata.c
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * Bestcomm ATA task driver
- *
- *
- * Patterned after bestcomm/fec.c by Dale Farnsworth <dfarnsworth@mvista.com>
- * 2003-2004 (c) MontaVista, Software, Inc.
- *
- * Copyright (C) 2006-2007 Sylvain Munaut <tnt@246tNt.com>
- * Copyright (C) 2006 Freescale - John Rigby
- *
- * 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/kernel.h>
-#include <linux/module.h>
-#include <linux/types.h>
-#include <asm/io.h>
-
-#include "bestcomm.h"
-#include "bestcomm_priv.h"
-#include "ata.h"
-
-
-/* ======================================================================== */
-/* Task image/var/inc */
-/* ======================================================================== */
-
-/* ata task image */
-extern u32 bcom_ata_task[];
-
-/* ata task vars that need to be set before enabling the task */
-struct bcom_ata_var {
- u32 enable; /* (u16*) address of task's control register */
- u32 bd_base; /* (struct bcom_bd*) beginning of ring buffer */
- u32 bd_last; /* (struct bcom_bd*) end of ring buffer */
- u32 bd_start; /* (struct bcom_bd*) current bd */
- u32 buffer_size; /* size of receive buffer */
-};
-
-/* ata task incs that need to be set before enabling the task */
-struct bcom_ata_inc {
- u16 pad0;
- s16 incr_bytes;
- u16 pad1;
- s16 incr_dst;
- u16 pad2;
- s16 incr_src;
-};
-
-
-/* ======================================================================== */
-/* Task support code */
-/* ======================================================================== */
-
-struct bcom_task *
-bcom_ata_init(int queue_len, int maxbufsize)
-{
- struct bcom_task *tsk;
- struct bcom_ata_var *var;
- struct bcom_ata_inc *inc;
-
- /* Prefetch breaks ATA DMA. Turn it off for ATA DMA */
- bcom_disable_prefetch();
-
- tsk = bcom_task_alloc(queue_len, sizeof(struct bcom_ata_bd), 0);
- if (!tsk)
- return NULL;
-
- tsk->flags = BCOM_FLAGS_NONE;
-
- bcom_ata_reset_bd(tsk);
-
- var = (struct bcom_ata_var *) bcom_task_var(tsk->tasknum);
- inc = (struct bcom_ata_inc *) bcom_task_inc(tsk->tasknum);
-
- if (bcom_load_image(tsk->tasknum, bcom_ata_task)) {
- bcom_task_free(tsk);
- return NULL;
- }
-
- var->enable = bcom_eng->regs_base +
- offsetof(struct mpc52xx_sdma, tcr[tsk->tasknum]);
- var->bd_base = tsk->bd_pa;
- var->bd_last = tsk->bd_pa + ((tsk->num_bd-1) * tsk->bd_size);
- var->bd_start = tsk->bd_pa;
- var->buffer_size = maxbufsize;
-
- /* Configure some stuff */
- bcom_set_task_pragma(tsk->tasknum, BCOM_ATA_PRAGMA);
- bcom_set_task_auto_start(tsk->tasknum, tsk->tasknum);
-
- out_8(&bcom_eng->regs->ipr[BCOM_INITIATOR_ATA_RX], BCOM_IPR_ATA_RX);
- out_8(&bcom_eng->regs->ipr[BCOM_INITIATOR_ATA_TX], BCOM_IPR_ATA_TX);
-
- out_be32(&bcom_eng->regs->IntPend, 1<<tsk->tasknum); /* Clear ints */
-
- return tsk;
-}
-EXPORT_SYMBOL_GPL(bcom_ata_init);
-
-void bcom_ata_rx_prepare(struct bcom_task *tsk)
-{
- struct bcom_ata_inc *inc;
-
- inc = (struct bcom_ata_inc *) bcom_task_inc(tsk->tasknum);
-
- inc->incr_bytes = -(s16)sizeof(u32);
- inc->incr_src = 0;
- inc->incr_dst = sizeof(u32);
-
- bcom_set_initiator(tsk->tasknum, BCOM_INITIATOR_ATA_RX);
-}
-EXPORT_SYMBOL_GPL(bcom_ata_rx_prepare);
-
-void bcom_ata_tx_prepare(struct bcom_task *tsk)
-{
- struct bcom_ata_inc *inc;
-
- inc = (struct bcom_ata_inc *) bcom_task_inc(tsk->tasknum);
-
- inc->incr_bytes = -(s16)sizeof(u32);
- inc->incr_src = sizeof(u32);
- inc->incr_dst = 0;
-
- bcom_set_initiator(tsk->tasknum, BCOM_INITIATOR_ATA_TX);
-}
-EXPORT_SYMBOL_GPL(bcom_ata_tx_prepare);
-
-void bcom_ata_reset_bd(struct bcom_task *tsk)
-{
- struct bcom_ata_var *var;
-
- /* Reset all BD */
- memset(tsk->bd, 0x00, tsk->num_bd * tsk->bd_size);
-
- tsk->index = 0;
- tsk->outdex = 0;
-
- var = (struct bcom_ata_var *) bcom_task_var(tsk->tasknum);
- var->bd_start = var->bd_base;
-}
-EXPORT_SYMBOL_GPL(bcom_ata_reset_bd);
-
-void bcom_ata_release(struct bcom_task *tsk)
-{
- /* Nothing special for the ATA tasks */
- bcom_task_free(tsk);
-}
-EXPORT_SYMBOL_GPL(bcom_ata_release);
-
-
-MODULE_DESCRIPTION("BestComm ATA task driver");
-MODULE_AUTHOR("John Rigby");
-MODULE_LICENSE("GPL v2");
-
diff --git a/arch/powerpc/sysdev/bestcomm/ata.h b/arch/powerpc/sysdev/bestcomm/ata.h
deleted file mode 100644
index 0b237181133..00000000000
--- a/arch/powerpc/sysdev/bestcomm/ata.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Header for Bestcomm ATA task driver
- *
- *
- * Copyright (C) 2006 Freescale - John Rigby
- * Copyright (C) 2006 Sylvain Munaut <tnt@246tNt.com>
- *
- * 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.
- */
-
-#ifndef __BESTCOMM_ATA_H__
-#define __BESTCOMM_ATA_H__
-
-
-struct bcom_ata_bd {
- u32 status;
- u32 src_pa;
- u32 dst_pa;
-};
-
-extern struct bcom_task * bcom_ata_init(int queue_len, int maxbufsize);
-extern void bcom_ata_rx_prepare(struct bcom_task *tsk);
-extern void bcom_ata_tx_prepare(struct bcom_task *tsk);
-extern void bcom_ata_reset_bd(struct bcom_task *tsk);
-extern void bcom_ata_release(struct bcom_task *tsk);
-
-#endif /* __BESTCOMM_ATA_H__ */
-
diff --git a/arch/powerpc/sysdev/bestcomm/bcom_ata_task.c b/arch/powerpc/sysdev/bestcomm/bcom_ata_task.c
deleted file mode 100644
index cc6049a4e46..00000000000
--- a/arch/powerpc/sysdev/bestcomm/bcom_ata_task.c
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Bestcomm ATA task microcode
- *
- * Copyright (c) 2004 Freescale Semiconductor, Inc.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published
- * by the Free Software Foundation.
- *
- * Created based on bestcom/code_dma/image_rtos1/dma_image.hex
- */
-
-#include <asm/types.h>
-
-/*
- * The header consists of the following fields:
- * u32 magic;
- * u8 desc_size;
- * u8 var_size;
- * u8 inc_size;
- * u8 first_var;
- * u8 reserved[8];
- *
- * The size fields contain the number of 32-bit words.
- */
-
-u32 bcom_ata_task[] = {
- /* header */
- 0x4243544b,
- 0x0e060709,
- 0x00000000,
- 0x00000000,
-
- /* Task descriptors */
- 0x8198009b, /* LCD: idx0 = var3; idx0 <= var2; idx0 += inc3 */
- 0x13e00c08, /* DRD1A: var3 = var1; FN=0 MORE init=31 WS=0 RS=0 */
- 0xb8000264, /* LCD: idx1 = *idx0, idx2 = var0; idx1 < var9; idx1 += inc4, idx2 += inc4 */
- 0x10000f00, /* DRD1A: var3 = idx0; FN=0 MORE init=0 WS=0 RS=0 */
- 0x60140002, /* DRD2A: EU0=0 EU1=0 EU2=0 EU3=2 EXT init=0 WS=2 RS=2 */
- 0x0c8cfc8a, /* DRD2B1: *idx2 = EU3(); EU3(*idx2,var10) */
- 0xd8988240, /* LCDEXT: idx1 = idx1; idx1 > var9; idx1 += inc0 */
- 0xf845e011, /* LCDEXT: idx2 = *(idx0 + var00000015); ; idx2 += inc2 */
- 0xb845e00a, /* LCD: idx3 = *(idx0 + var00000019); ; idx3 += inc1 */
- 0x0bfecf90, /* DRD1A: *idx3 = *idx2; FN=0 TFD init=31 WS=3 RS=3 */
- 0x9898802d, /* LCD: idx1 = idx1; idx1 once var0; idx1 += inc5 */
- 0x64000005, /* DRD2A: EU0=0 EU1=0 EU2=0 EU3=5 INT EXT init=0 WS=0 RS=0 */
- 0x0c0cf849, /* DRD2B1: *idx0 = EU3(); EU3(idx1,var9) */
- 0x000001f8, /* NOP */
-
- /* VAR[9]-VAR[14] */
- 0x40000000,
- 0x7fff7fff,
- 0x00000000,
- 0x00000000,
- 0x00000000,
- 0x00000000,
-
- /* INC[0]-INC[6] */
- 0x40000000,
- 0xe0000000,
- 0xe0000000,
- 0xa000000c,
- 0x20000000,
- 0x00000000,
- 0x00000000,
-};
-
diff --git a/arch/powerpc/sysdev/bestcomm/bcom_fec_rx_task.c b/arch/powerpc/sysdev/bestcomm/bcom_fec_rx_task.c
deleted file mode 100644
index a1ad6a02fce..00000000000
--- a/arch/powerpc/sysdev/bestcomm/bcom_fec_rx_task.c
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Bestcomm FEC RX task microcode
- *
- * Copyright (c) 2004 Freescale Semiconductor, Inc.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published
- * by the Free Software Foundation.
- *
- * Automatically created based on BestCommAPI-2.2/code_dma/image_rtos1/dma_image.hex
- * on Tue Mar 22 11:19:38 2005 GMT
- */
-
-#include <asm/types.h>
-
-/*
- * The header consists of the following fields:
- * u32 magic;
- * u8 desc_size;
- * u8 var_size;
- * u8 inc_size;
- * u8 first_var;
- * u8 reserved[8];
- *
- * The size fields contain the number of 32-bit words.
- */
-
-u32 bcom_fec_rx_task[] = {
- /* header */
- 0x4243544b,
- 0x18060709,
- 0x00000000,
- 0x00000000,
-
- /* Task descriptors */
- 0x808220e3, /* LCD: idx0 = var1, idx1 = var4; idx1 <= var3; idx0 += inc4, idx1 += inc3 */
- 0x10601010, /* DRD1A: var4 = var2; FN=0 MORE init=3 WS=0 RS=0 */
- 0xb8800264, /* LCD: idx2 = *idx1, idx3 = var0; idx2 < var9; idx2 += inc4, idx3 += inc4 */
- 0x10001308, /* DRD1A: var4 = idx1; FN=0 MORE init=0 WS=0 RS=0 */
- 0x60140002, /* DRD2A: EU0=0 EU1=0 EU2=0 EU3=2 EXT init=0 WS=2 RS=2 */
- 0x0cccfcca, /* DRD2B1: *idx3 = EU3(); EU3(*idx3,var10) */
- 0x80004000, /* LCDEXT: idx2 = 0x00000000; ; */
- 0xb8c58029, /* LCD: idx3 = *(idx1 + var00000015); idx3 once var0; idx3 += inc5 */
- 0x60000002, /* DRD2A: EU0=0 EU1=0 EU2=0 EU3=2 EXT init=0 WS=0 RS=0 */
- 0x088cf8cc, /* DRD2B1: idx2 = EU3(); EU3(idx3,var12) */
- 0x991982f2, /* LCD: idx2 = idx2, idx3 = idx3; idx2 > var11; idx2 += inc6, idx3 += inc2 */
- 0x006acf80, /* DRD1A: *idx3 = *idx0; FN=0 init=3 WS=1 RS=1 */
- 0x80004000, /* LCDEXT: idx2 = 0x00000000; ; */
- 0x9999802d, /* LCD: idx3 = idx3; idx3 once var0; idx3 += inc5 */
- 0x70000002, /* DRD2A: EU0=0 EU1=0 EU2=0 EU3=2 EXT MORE init=0 WS=0 RS=0 */
- 0x034cfc4e, /* DRD2B1: var13 = EU3(); EU3(*idx1,var14) */
- 0x00008868, /* DRD1A: idx2 = var13; FN=0 init=0 WS=0 RS=0 */
- 0x99198341, /* LCD: idx2 = idx2, idx3 = idx3; idx2 > var13; idx2 += inc0, idx3 += inc1 */
- 0x007ecf80, /* DRD1A: *idx3 = *idx0; FN=0 init=3 WS=3 RS=3 */
- 0x99198272, /* LCD: idx2 = idx2, idx3 = idx3; idx2 > var9; idx2 += inc6, idx3 += inc2 */
- 0x046acf80, /* DRD1A: *idx3 = *idx0; FN=0 INT init=3 WS=1 RS=1 */
- 0x9819002d, /* LCD: idx2 = idx0; idx2 once var0; idx2 += inc5 */
- 0x0060c790, /* DRD1A: *idx1 = *idx2; FN=0 init=3 WS=0 RS=0 */
- 0x000001f8, /* NOP */
-
- /* VAR[9]-VAR[14] */
- 0x40000000,
- 0x7fff7fff,
- 0x00000000,
- 0x00000003,
- 0x40000008,
- 0x43ffffff,
-
- /* INC[0]-INC[6] */
- 0x40000000,
- 0xe0000000,
- 0xe0000000,
- 0xa0000008,
- 0x20000000,
- 0x00000000,
- 0x4000ffff,
-};
-
diff --git a/arch/powerpc/sysdev/bestcomm/bcom_fec_tx_task.c b/arch/powerpc/sysdev/bestcomm/bcom_fec_tx_task.c
deleted file mode 100644
index b1c495c3a65..00000000000
--- a/arch/powerpc/sysdev/bestcomm/bcom_fec_tx_task.c
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Bestcomm FEC TX task microcode
- *
- * Copyright (c) 2004 Freescale Semiconductor, Inc.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published
- * by the Free Software Foundation.
- *
- * Automatically created based on BestCommAPI-2.2/code_dma/image_rtos1/dma_image.hex
- * on Tue Mar 22 11:19:29 2005 GMT
- */
-
-#include <asm/types.h>
-
-/*
- * The header consists of the following fields:
- * u32 magic;
- * u8 desc_size;
- * u8 var_size;
- * u8 inc_size;
- * u8 first_var;
- * u8 reserved[8];
- *
- * The size fields contain the number of 32-bit words.
- */
-
-u32 bcom_fec_tx_task[] = {
- /* header */
- 0x4243544b,
- 0x2407070d,
- 0x00000000,
- 0x00000000,
-
- /* Task descriptors */
- 0x8018001b, /* LCD: idx0 = var0; idx0 <= var0; idx0 += inc3 */
- 0x60000005, /* DRD2A: EU0=0 EU1=0 EU2=0 EU3=5 EXT init=0 WS=0 RS=0 */
- 0x01ccfc0d, /* DRD2B1: var7 = EU3(); EU3(*idx0,var13) */
- 0x8082a123, /* LCD: idx0 = var1, idx1 = var5; idx1 <= var4; idx0 += inc4, idx1 += inc3 */
- 0x10801418, /* DRD1A: var5 = var3; FN=0 MORE init=4 WS=0 RS=0 */
- 0xf88103a4, /* LCDEXT: idx2 = *idx1, idx3 = var2; idx2 < var14; idx2 += inc4, idx3 += inc4 */
- 0x801a6024, /* LCD: idx4 = var0; ; idx4 += inc4 */
- 0x10001708, /* DRD1A: var5 = idx1; FN=0 MORE init=0 WS=0 RS=0 */
- 0x60140002, /* DRD2A: EU0=0 EU1=0 EU2=0 EU3=2 EXT init=0 WS=2 RS=2 */
- 0x0cccfccf, /* DRD2B1: *idx3 = EU3(); EU3(*idx3,var15) */
- 0x991a002c, /* LCD: idx2 = idx2, idx3 = idx4; idx2 once var0; idx2 += inc5, idx3 += inc4 */
- 0x70000002, /* DRD2A: EU0=0 EU1=0 EU2=0 EU3=2 EXT MORE init=0 WS=0 RS=0 */
- 0x024cfc4d, /* DRD2B1: var9 = EU3(); EU3(*idx1,var13) */
- 0x60000003, /* DRD2A: EU0=0 EU1=0 EU2=0 EU3=3 EXT init=0 WS=0 RS=0 */
- 0x0cccf247, /* DRD2B1: *idx3 = EU3(); EU3(var9,var7) */
- 0x80004000, /* LCDEXT: idx2 = 0x00000000; ; */
- 0xb8c80029, /* LCD: idx3 = *(idx1 + var0000001a); idx3 once var0; idx3 += inc5 */
- 0x70000002, /* DRD2A: EU0=0 EU1=0 EU2=0 EU3=2 EXT MORE init=0 WS=0 RS=0 */
- 0x088cf8d1, /* DRD2B1: idx2 = EU3(); EU3(idx3,var17) */
- 0x00002f10, /* DRD1A: var11 = idx2; FN=0 init=0 WS=0 RS=0 */
- 0x99198432, /* LCD: idx2 = idx2, idx3 = idx3; idx2 > var16; idx2 += inc6, idx3 += inc2 */
- 0x008ac398, /* DRD1A: *idx0 = *idx3; FN=0 init=4 WS=1 RS=1 */
- 0x80004000, /* LCDEXT: idx2 = 0x00000000; ; */
- 0x9999802d, /* LCD: idx3 = idx3; idx3 once var0; idx3 += inc5 */
- 0x70000002, /* DRD2A: EU0=0 EU1=0 EU2=0 EU3=2 EXT MORE init=0 WS=0 RS=0 */
- 0x048cfc53, /* DRD2B1: var18 = EU3(); EU3(*idx1,var19) */
- 0x60000008, /* DRD2A: EU0=0 EU1=0 EU2=0 EU3=8 EXT init=0 WS=0 RS=0 */
- 0x088cf48b, /* DRD2B1: idx2 = EU3(); EU3(var18,var11) */
- 0x99198481, /* LCD: idx2 = idx2, idx3 = idx3; idx2 > var18; idx2 += inc0, idx3 += inc1 */
- 0x009ec398, /* DRD1A: *idx0 = *idx3; FN=0 init=4 WS=3 RS=3 */
- 0x991983b2, /* LCD: idx2 = idx2, idx3 = idx3; idx2 > var14; idx2 += inc6, idx3 += inc2 */
- 0x088ac398, /* DRD1A: *idx0 = *idx3; FN=0 TFD init=4 WS=1 RS=1 */
- 0x9919002d, /* LCD: idx2 = idx2; idx2 once var0; idx2 += inc5 */
- 0x60000005, /* DRD2A: EU0=0 EU1=0 EU2=0 EU3=5 EXT init=0 WS=0 RS=0 */
- 0x0c4cf88e, /* DRD2B1: *idx1 = EU3(); EU3(idx2,var14) */
- 0x000001f8, /* NOP */
-
- /* VAR[13]-VAR[19] */
- 0x0c000000,
- 0x40000000,
- 0x7fff7fff,
- 0x00000000,
- 0x00000003,
- 0x40000004,
- 0x43ffffff,
-
- /* INC[0]-INC[6] */
- 0x40000000,
- 0xe0000000,
- 0xe0000000,
- 0xa0000008,
- 0x20000000,
- 0x00000000,
- 0x4000ffff,
-};
-
diff --git a/arch/powerpc/sysdev/bestcomm/bcom_gen_bd_rx_task.c b/arch/powerpc/sysdev/bestcomm/bcom_gen_bd_rx_task.c
deleted file mode 100644
index efee022b025..00000000000
--- a/arch/powerpc/sysdev/bestcomm/bcom_gen_bd_rx_task.c
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Bestcomm GenBD RX task microcode
- *
- * Copyright (C) 2006 AppSpec Computer Technologies Corp.
- * Jeff Gibbons <jeff.gibbons@appspec.com>
- * Copyright (c) 2004 Freescale Semiconductor, Inc.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published
- * by the Free Software Foundation.
- *
- * Based on BestCommAPI-2.2/code_dma/image_rtos1/dma_image.hex
- * on Tue Mar 4 10:14:12 2006 GMT
- *
- */
-
-#include <asm/types.h>
-
-/*
- * The header consists of the following fields:
- * u32 magic;
- * u8 desc_size;
- * u8 var_size;
- * u8 inc_size;
- * u8 first_var;
- * u8 reserved[8];
- *
- * The size fields contain the number of 32-bit words.
- */
-
-u32 bcom_gen_bd_rx_task[] = {
- /* header */
- 0x4243544b,
- 0x0d020409,
- 0x00000000,
- 0x00000000,
-
- /* Task descriptors */
- 0x808220da, /* LCD: idx0 = var1, idx1 = var4; idx1 <= var3; idx0 += inc3, idx1 += inc2 */
- 0x13e01010, /* DRD1A: var4 = var2; FN=0 MORE init=31 WS=0 RS=0 */
- 0xb880025b, /* LCD: idx2 = *idx1, idx3 = var0; idx2 < var9; idx2 += inc3, idx3 += inc3 */
- 0x10001308, /* DRD1A: var4 = idx1; FN=0 MORE init=0 WS=0 RS=0 */
- 0x60140002, /* DRD2A: EU0=0 EU1=0 EU2=0 EU3=2 EXT init=0 WS=2 RS=2 */
- 0x0cccfcca, /* DRD2B1: *idx3 = EU3(); EU3(*idx3,var10) */
- 0xd9190240, /* LCDEXT: idx2 = idx2; idx2 > var9; idx2 += inc0 */
- 0xb8c5e009, /* LCD: idx3 = *(idx1 + var00000015); ; idx3 += inc1 */
- 0x07fecf80, /* DRD1A: *idx3 = *idx0; FN=0 INT init=31 WS=3 RS=3 */
- 0x99190024, /* LCD: idx2 = idx2; idx2 once var0; idx2 += inc4 */
- 0x60000005, /* DRD2A: EU0=0 EU1=0 EU2=0 EU3=5 EXT init=0 WS=0 RS=0 */
- 0x0c4cf889, /* DRD2B1: *idx1 = EU3(); EU3(idx2,var9) */
- 0x000001f8, /* NOP */
-
- /* VAR[9]-VAR[10] */
- 0x40000000,
- 0x7fff7fff,
-
- /* INC[0]-INC[3] */
- 0x40000000,
- 0xe0000000,
- 0xa0000008,
- 0x20000000,
-};
-
diff --git a/arch/powerpc/sysdev/bestcomm/bcom_gen_bd_tx_task.c b/arch/powerpc/sysdev/bestcomm/bcom_gen_bd_tx_task.c
deleted file mode 100644
index c605aa42ecb..00000000000
--- a/arch/powerpc/sysdev/bestcomm/bcom_gen_bd_tx_task.c
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Bestcomm GenBD TX task microcode
- *
- * Copyright (C) 2006 AppSpec Computer Technologies Corp.
- * Jeff Gibbons <jeff.gibbons@appspec.com>
- * Copyright (c) 2004 Freescale Semiconductor, Inc.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published
- * by the Free Software Foundation.
- *
- * Based on BestCommAPI-2.2/code_dma/image_rtos1/dma_image.hex
- * on Tue Mar 4 10:14:12 2006 GMT
- *
- */
-
-#include <asm/types.h>
-
-/*
- * The header consists of the following fields:
- * u32 magic;
- * u8 desc_size;
- * u8 var_size;
- * u8 inc_size;
- * u8 first_var;
- * u8 reserved[8];
- *
- * The size fields contain the number of 32-bit words.
- */
-
-u32 bcom_gen_bd_tx_task[] = {
- /* header */
- 0x4243544b,
- 0x0f040609,
- 0x00000000,
- 0x00000000,
-
- /* Task descriptors */
- 0x800220e3, /* LCD: idx0 = var0, idx1 = var4; idx1 <= var3; idx0 += inc4, idx1 += inc3 */
- 0x13e01010, /* DRD1A: var4 = var2; FN=0 MORE init=31 WS=0 RS=0 */
- 0xb8808264, /* LCD: idx2 = *idx1, idx3 = var1; idx2 < var9; idx2 += inc4, idx3 += inc4 */
- 0x10001308, /* DRD1A: var4 = idx1; FN=0 MORE init=0 WS=0 RS=0 */
- 0x60140002, /* DRD2A: EU0=0 EU1=0 EU2=0 EU3=2 EXT init=0 WS=2 RS=2 */
- 0x0cccfcca, /* DRD2B1: *idx3 = EU3(); EU3(*idx3,var10) */
- 0xd9190300, /* LCDEXT: idx2 = idx2; idx2 > var12; idx2 += inc0 */
- 0xb8c5e009, /* LCD: idx3 = *(idx1 + var00000015); ; idx3 += inc1 */
- 0x03fec398, /* DRD1A: *idx0 = *idx3; FN=0 init=31 WS=3 RS=3 */
- 0x9919826a, /* LCD: idx2 = idx2, idx3 = idx3; idx2 > var9; idx2 += inc5, idx3 += inc2 */
- 0x0feac398, /* DRD1A: *idx0 = *idx3; FN=0 TFD INT init=31 WS=1 RS=1 */
- 0x99190036, /* LCD: idx2 = idx2; idx2 once var0; idx2 += inc6 */
- 0x60000005, /* DRD2A: EU0=0 EU1=0 EU2=0 EU3=5 EXT init=0 WS=0 RS=0 */
- 0x0c4cf889, /* DRD2B1: *idx1 = EU3(); EU3(idx2,var9) */
- 0x000001f8, /* NOP */
-
- /* VAR[9]-VAR[12] */
- 0x40000000,
- 0x7fff7fff,
- 0x00000000,
- 0x40000004,
-
- /* INC[0]-INC[5] */
- 0x40000000,
- 0xe0000000,
- 0xe0000000,
- 0xa0000008,
- 0x20000000,
- 0x4000ffff,
-};
-
diff --git a/arch/powerpc/sysdev/bestcomm/bestcomm.c b/arch/powerpc/sysdev/bestcomm/bestcomm.c
deleted file mode 100644
index d9130630f7e..00000000000
--- a/arch/powerpc/sysdev/bestcomm/bestcomm.c
+++ /dev/null
@@ -1,531 +0,0 @@
-/*
- * Driver for MPC52xx processor BestComm peripheral controller
- *
- *
- * Copyright (C) 2006-2007 Sylvain Munaut <tnt@246tNt.com>
- * Copyright (C) 2005 Varma Electronics Oy,
- * ( by Andrey Volkov <avolkov@varma-el.com> )
- * Copyright (C) 2003-2004 MontaVista, Software, Inc.
- * ( by Dale Farnsworth <dfarnsworth@mvista.com> )
- *
- * 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/module.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/of.h>
-#include <linux/of_device.h>
-#include <linux/of_platform.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/mpc52xx.h>
-
-#include "sram.h"
-#include "bestcomm_priv.h"
-#include "bestcomm.h"
-
-#define DRIVER_NAME "bestcomm-core"
-
-/* MPC5200 device tree match tables */
-static struct of_device_id mpc52xx_sram_ids[] = {
- { .compatible = "fsl,mpc5200-sram", },
- { .compatible = "mpc5200-sram", },
- {}
-};
-
-
-struct bcom_engine *bcom_eng = NULL;
-EXPORT_SYMBOL_GPL(bcom_eng); /* needed for inline functions */
-
-/* ======================================================================== */
-/* Public and private API */
-/* ======================================================================== */
-
-/* Private API */
-
-struct bcom_task *
-bcom_task_alloc(int bd_count, int bd_size, int priv_size)
-{
- int i, tasknum = -1;
- struct bcom_task *tsk;
-
- /* Don't try to do anything if bestcomm init failed */
- if (!bcom_eng)
- return NULL;
-
- /* Get and reserve a task num */
- spin_lock(&bcom_eng->lock);
-
- for (i=0; i<BCOM_MAX_TASKS; i++)
- if (!bcom_eng->tdt[i].stop) { /* we use stop as a marker */
- bcom_eng->tdt[i].stop = 0xfffffffful; /* dummy addr */
- tasknum = i;
- break;
- }
-
- spin_unlock(&bcom_eng->lock);
-
- if (tasknum < 0)
- return NULL;
-
- /* Allocate our structure */
- tsk = kzalloc(sizeof(struct bcom_task) + priv_size, GFP_KERNEL);
- if (!tsk)
- goto error;
-
- tsk->tasknum = tasknum;
- if (priv_size)
- tsk->priv = (void*)tsk + sizeof(struct bcom_task);
-
- /* Get IRQ of that task */
- tsk->irq = irq_of_parse_and_map(bcom_eng->ofnode, tsk->tasknum);
- if (tsk->irq == NO_IRQ)
- goto error;
-
- /* Init the BDs, if needed */
- if (bd_count) {
- tsk->cookie = kmalloc(sizeof(void*) * bd_count, GFP_KERNEL);
- if (!tsk->cookie)
- goto error;
-
- tsk->bd = bcom_sram_alloc(bd_count * bd_size, 4, &tsk->bd_pa);
- if (!tsk->bd)
- goto error;
- memset(tsk->bd, 0x00, bd_count * bd_size);
-
- tsk->num_bd = bd_count;
- tsk->bd_size = bd_size;
- }
-
- return tsk;
-
-error:
- if (tsk) {
- if (tsk->irq != NO_IRQ)
- irq_dispose_mapping(tsk->irq);
- bcom_sram_free(tsk->bd);
- kfree(tsk->cookie);
- kfree(tsk);
- }
-
- bcom_eng->tdt[tasknum].stop = 0;
-
- return NULL;
-}
-EXPORT_SYMBOL_GPL(bcom_task_alloc);
-
-void
-bcom_task_free(struct bcom_task *tsk)
-{
- /* Stop the task */
- bcom_disable_task(tsk->tasknum);
-
- /* Clear TDT */
- bcom_eng->tdt[tsk->tasknum].start = 0;
- bcom_eng->tdt[tsk->tasknum].stop = 0;
-
- /* Free everything */
- irq_dispose_mapping(tsk->irq);
- bcom_sram_free(tsk->bd);
- kfree(tsk->cookie);
- kfree(tsk);
-}
-EXPORT_SYMBOL_GPL(bcom_task_free);
-
-int
-bcom_load_image(int task, u32 *task_image)
-{
- struct bcom_task_header *hdr = (struct bcom_task_header *)task_image;
- struct bcom_tdt *tdt;
- u32 *desc, *var, *inc;
- u32 *desc_src, *var_src, *inc_src;
-
- /* Safety checks */
- if (hdr->magic != BCOM_TASK_MAGIC) {
- printk(KERN_ERR DRIVER_NAME
- ": Trying to load invalid microcode\n");
- return -EINVAL;
- }
-
- if ((task < 0) || (task >= BCOM_MAX_TASKS)) {
- printk(KERN_ERR DRIVER_NAME
- ": Trying to load invalid task %d\n", task);
- return -EINVAL;
- }
-
- /* Initial load or reload */
- tdt = &bcom_eng->tdt[task];
-
- if (tdt->start) {
- desc = bcom_task_desc(task);
- if (hdr->desc_size != bcom_task_num_descs(task)) {
- printk(KERN_ERR DRIVER_NAME
- ": Trying to reload wrong task image "
- "(%d size %d/%d)!\n",
- task,
- hdr->desc_size,
- bcom_task_num_descs(task));
- return -EINVAL;
- }
- } else {
- phys_addr_t start_pa;
-
- desc = bcom_sram_alloc(hdr->desc_size * sizeof(u32), 4, &start_pa);
- if (!desc)
- return -ENOMEM;
-
- tdt->start = start_pa;
- tdt->stop = start_pa + ((hdr->desc_size-1) * sizeof(u32));
- }
-
- var = bcom_task_var(task);
- inc = bcom_task_inc(task);
-
- /* Clear & copy */
- memset(var, 0x00, BCOM_VAR_SIZE);
- memset(inc, 0x00, BCOM_INC_SIZE);
-
- desc_src = (u32 *)(hdr + 1);
- var_src = desc_src + hdr->desc_size;
- inc_src = var_src + hdr->var_size;
-
- memcpy(desc, desc_src, hdr->desc_size * sizeof(u32));
- memcpy(var + hdr->first_var, var_src, hdr->var_size * sizeof(u32));
- memcpy(inc, inc_src, hdr->inc_size * sizeof(u32));
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(bcom_load_image);
-
-void
-bcom_set_initiator(int task, int initiator)
-{
- int i;
- int num_descs;
- u32 *desc;
- int next_drd_has_initiator;
-
- bcom_set_tcr_initiator(task, initiator);
-
- /* Just setting tcr is apparently not enough due to some problem */
- /* with it. So we just go thru all the microcode and replace in */
- /* the DRD directly */
-
- desc = bcom_task_desc(task);
- next_drd_has_initiator = 1;
- num_descs = bcom_task_num_descs(task);
-
- for (i=0; i<num_descs; i++, desc++) {
- if (!bcom_desc_is_drd(*desc))
- continue;
- if (next_drd_has_initiator)
- if (bcom_desc_initiator(*desc) != BCOM_INITIATOR_ALWAYS)
- bcom_set_desc_initiator(desc, initiator);
- next_drd_has_initiator = !bcom_drd_is_extended(*desc);
- }
-}
-EXPORT_SYMBOL_GPL(bcom_set_initiator);
-
-
-/* Public API */
-
-void
-bcom_enable(struct bcom_task *tsk)
-{
- bcom_enable_task(tsk->tasknum);
-}
-EXPORT_SYMBOL_GPL(bcom_enable);
-
-void
-bcom_disable(struct bcom_task *tsk)
-{
- bcom_disable_task(tsk->tasknum);
-}
-EXPORT_SYMBOL_GPL(bcom_disable);
-
-
-/* ======================================================================== */
-/* Engine init/cleanup */
-/* ======================================================================== */
-
-/* Function Descriptor table */
-/* this will need to be updated if Freescale changes their task code FDT */
-static u32 fdt_ops[] = {
- 0xa0045670, /* FDT[48] - load_acc() */
- 0x80045670, /* FDT[49] - unload_acc() */
- 0x21800000, /* FDT[50] - and() */
- 0x21e00000, /* FDT[51] - or() */
- 0x21500000, /* FDT[52] - xor() */
- 0x21400000, /* FDT[53] - andn() */
- 0x21500000, /* FDT[54] - not() */
- 0x20400000, /* FDT[55] - add() */
- 0x20500000, /* FDT[56] - sub() */
- 0x20800000, /* FDT[57] - lsh() */
- 0x20a00000, /* FDT[58] - rsh() */
- 0xc0170000, /* FDT[59] - crc8() */
- 0xc0145670, /* FDT[60] - crc16() */
- 0xc0345670, /* FDT[61] - crc32() */
- 0xa0076540, /* FDT[62] - endian32() */
- 0xa0000760, /* FDT[63] - endian16() */
-};
-
-
-static int bcom_engine_init(void)
-{
- int task;
- phys_addr_t tdt_pa, ctx_pa, var_pa, fdt_pa;
- unsigned int tdt_size, ctx_size, var_size, fdt_size;
-
- /* Allocate & clear SRAM zones for FDT, TDTs, contexts and vars/incs */
- tdt_size = BCOM_MAX_TASKS * sizeof(struct bcom_tdt);
- ctx_size = BCOM_MAX_TASKS * BCOM_CTX_SIZE;
- var_size = BCOM_MAX_TASKS * (BCOM_VAR_SIZE + BCOM_INC_SIZE);
- fdt_size = BCOM_FDT_SIZE;
-
- bcom_eng->tdt = bcom_sram_alloc(tdt_size, sizeof(u32), &tdt_pa);
- bcom_eng->ctx = bcom_sram_alloc(ctx_size, BCOM_CTX_ALIGN, &ctx_pa);
- bcom_eng->var = bcom_sram_alloc(var_size, BCOM_VAR_ALIGN, &var_pa);
- bcom_eng->fdt = bcom_sram_alloc(fdt_size, BCOM_FDT_ALIGN, &fdt_pa);
-
- if (!bcom_eng->tdt || !bcom_eng->ctx || !bcom_eng->var || !bcom_eng->fdt) {
- printk(KERN_ERR "DMA: SRAM alloc failed in engine init !\n");
-
- bcom_sram_free(bcom_eng->tdt);
- bcom_sram_free(bcom_eng->ctx);
- bcom_sram_free(bcom_eng->var);
- bcom_sram_free(bcom_eng->fdt);
-
- return -ENOMEM;
- }
-
- memset(bcom_eng->tdt, 0x00, tdt_size);
- memset(bcom_eng->ctx, 0x00, ctx_size);
- memset(bcom_eng->var, 0x00, var_size);
- memset(bcom_eng->fdt, 0x00, fdt_size);
-
- /* Copy the FDT for the EU#3 */
- memcpy(&bcom_eng->fdt[48], fdt_ops, sizeof(fdt_ops));
-
- /* Initialize Task base structure */
- for (task=0; task<BCOM_MAX_TASKS; task++)
- {
- out_be16(&bcom_eng->regs->tcr[task], 0);
- out_8(&bcom_eng->regs->ipr[task], 0);
-
- bcom_eng->tdt[task].context = ctx_pa;
- bcom_eng->tdt[task].var = var_pa;
- bcom_eng->tdt[task].fdt = fdt_pa;
-
- var_pa += BCOM_VAR_SIZE + BCOM_INC_SIZE;
- ctx_pa += BCOM_CTX_SIZE;
- }
-
- out_be32(&bcom_eng->regs->taskBar, tdt_pa);
-
- /* Init 'always' initiator */
- out_8(&bcom_eng->regs->ipr[BCOM_INITIATOR_ALWAYS], BCOM_IPR_ALWAYS);
-
- /* Disable COMM Bus Prefetch on the original 5200; it's broken */
- if ((mfspr(SPRN_SVR) & MPC5200_SVR_MASK) == MPC5200_SVR)
- bcom_disable_prefetch();
-
- /* Init lock */
- spin_lock_init(&bcom_eng->lock);
-
- return 0;
-}
-
-static void
-bcom_engine_cleanup(void)
-{
- int task;
-
- /* Stop all tasks */
- for (task=0; task<BCOM_MAX_TASKS; task++)
- {
- out_be16(&bcom_eng->regs->tcr[task], 0);
- out_8(&bcom_eng->regs->ipr[task], 0);
- }
-
- out_be32(&bcom_eng->regs->taskBar, 0ul);
-
- /* Release the SRAM zones */
- bcom_sram_free(bcom_eng->tdt);
- bcom_sram_free(bcom_eng->ctx);
- bcom_sram_free(bcom_eng->var);
- bcom_sram_free(bcom_eng->fdt);
-}
-
-
-/* ======================================================================== */
-/* OF platform driver */
-/* ======================================================================== */
-
-static int mpc52xx_bcom_probe(struct platform_device *op)
-{
- struct device_node *ofn_sram;
- struct resource res_bcom;
-
- int rv;
-
- /* Inform user we're ok so far */
- printk(KERN_INFO "DMA: MPC52xx BestComm driver\n");
-
- /* Get the bestcomm node */
- of_node_get(op->dev.of_node);
-
- /* Prepare SRAM */
- ofn_sram = of_find_matching_node(NULL, mpc52xx_sram_ids);
- if (!ofn_sram) {
- printk(KERN_ERR DRIVER_NAME ": "
- "No SRAM found in device tree\n");
- rv = -ENODEV;
- goto error_ofput;
- }
- rv = bcom_sram_init(ofn_sram, DRIVER_NAME);
- of_node_put(ofn_sram);
-
- if (rv) {
- printk(KERN_ERR DRIVER_NAME ": "
- "Error in SRAM init\n");
- goto error_ofput;
- }
-
- /* Get a clean struct */
- bcom_eng = kzalloc(sizeof(struct bcom_engine), GFP_KERNEL);
- if (!bcom_eng) {
- printk(KERN_ERR DRIVER_NAME ": "
- "Can't allocate state structure\n");
- rv = -ENOMEM;
- goto error_sramclean;
- }
-
- /* Save the node */
- bcom_eng->ofnode = op->dev.of_node;
-
- /* Get, reserve & map io */
- if (of_address_to_resource(op->dev.of_node, 0, &res_bcom)) {
- printk(KERN_ERR DRIVER_NAME ": "
- "Can't get resource\n");
- rv = -EINVAL;
- goto error_sramclean;
- }
-
- if (!request_mem_region(res_bcom.start, sizeof(struct mpc52xx_sdma),
- DRIVER_NAME)) {
- printk(KERN_ERR DRIVER_NAME ": "
- "Can't request registers region\n");
- rv = -EBUSY;
- goto error_sramclean;
- }
-
- bcom_eng->regs_base = res_bcom.start;
- bcom_eng->regs = ioremap(res_bcom.start, sizeof(struct mpc52xx_sdma));
- if (!bcom_eng->regs) {
- printk(KERN_ERR DRIVER_NAME ": "
- "Can't map registers\n");
- rv = -ENOMEM;
- goto error_release;
- }
-
- /* Now, do the real init */
- rv = bcom_engine_init();
- if (rv)
- goto error_unmap;
-
- /* Done ! */
- printk(KERN_INFO "DMA: MPC52xx BestComm engine @%08lx ok !\n",
- (long)bcom_eng->regs_base);
-
- return 0;
-
- /* Error path */
-error_unmap:
- iounmap(bcom_eng->regs);
-error_release:
- release_mem_region(res_bcom.start, sizeof(struct mpc52xx_sdma));
-error_sramclean:
- kfree(bcom_eng);
- bcom_sram_cleanup();
-error_ofput:
- of_node_put(op->dev.of_node);
-
- printk(KERN_ERR "DMA: MPC52xx BestComm init failed !\n");
-
- return rv;
-}
-
-
-static int mpc52xx_bcom_remove(struct platform_device *op)
-{
- /* Clean up the engine */
- bcom_engine_cleanup();
-
- /* Cleanup SRAM */
- bcom_sram_cleanup();
-
- /* Release regs */
- iounmap(bcom_eng->regs);
- release_mem_region(bcom_eng->regs_base, sizeof(struct mpc52xx_sdma));
-
- /* Release the node */
- of_node_put(bcom_eng->ofnode);
-
- /* Release memory */
- kfree(bcom_eng);
- bcom_eng = NULL;
-
- return 0;
-}
-
-static struct of_device_id mpc52xx_bcom_of_match[] = {
- { .compatible = "fsl,mpc5200-bestcomm", },
- { .compatible = "mpc5200-bestcomm", },
- {},
-};
-
-MODULE_DEVICE_TABLE(of, mpc52xx_bcom_of_match);
-
-
-static struct platform_driver mpc52xx_bcom_of_platform_driver = {
- .probe = mpc52xx_bcom_probe,
- .remove = mpc52xx_bcom_remove,
- .driver = {
- .name = DRIVER_NAME,
- .owner = THIS_MODULE,
- .of_match_table = mpc52xx_bcom_of_match,
- },
-};
-
-
-/* ======================================================================== */
-/* Module */
-/* ======================================================================== */
-
-static int __init
-mpc52xx_bcom_init(void)
-{
- return platform_driver_register(&mpc52xx_bcom_of_platform_driver);
-}
-
-static void __exit
-mpc52xx_bcom_exit(void)
-{
- platform_driver_unregister(&mpc52xx_bcom_of_platform_driver);
-}
-
-/* If we're not a module, we must make sure everything is setup before */
-/* anyone tries to use us ... that's why we use subsys_initcall instead */
-/* of module_init. */
-subsys_initcall(mpc52xx_bcom_init);
-module_exit(mpc52xx_bcom_exit);
-
-MODULE_DESCRIPTION("Freescale MPC52xx BestComm DMA");
-MODULE_AUTHOR("Sylvain Munaut <tnt@246tNt.com>");
-MODULE_AUTHOR("Andrey Volkov <avolkov@varma-el.com>");
-MODULE_AUTHOR("Dale Farnsworth <dfarnsworth@mvista.com>");
-MODULE_LICENSE("GPL v2");
-
diff --git a/arch/powerpc/sysdev/bestcomm/bestcomm.h b/arch/powerpc/sysdev/bestcomm/bestcomm.h
deleted file mode 100644
index a0e2e6b19b5..00000000000
--- a/arch/powerpc/sysdev/bestcomm/bestcomm.h
+++ /dev/null
@@ -1,213 +0,0 @@
-/*
- * Public header for the MPC52xx processor BestComm driver
- *
- *
- * Copyright (C) 2006 Sylvain Munaut <tnt@246tNt.com>
- * Copyright (C) 2005 Varma Electronics Oy,
- * ( by Andrey Volkov <avolkov@varma-el.com> )
- * Copyright (C) 2003-2004 MontaVista, Software, Inc.
- * ( by Dale Farnsworth <dfarnsworth@mvista.com> )
- *
- * 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.
- */
-
-#ifndef __BESTCOMM_H__
-#define __BESTCOMM_H__
-
-/**
- * struct bcom_bd - Structure describing a generic BestComm buffer descriptor
- * @status: The current status of this buffer. Exact meaning depends on the
- * task type
- * @data: An array of u32 extra data. Size of array is task dependent.
- *
- * Note: Don't dereference a bcom_bd pointer as an array. The size of the
- * bcom_bd is variable. Use bcom_get_bd() instead.
- */
-struct bcom_bd {
- u32 status;
- u32 data[0]; /* variable payload size */
-};
-
-/* ======================================================================== */
-/* Generic task management */
-/* ======================================================================== */
-
-/**
- * struct bcom_task - Structure describing a loaded BestComm task
- *
- * This structure is never built by the driver it self. It's built and
- * filled the intermediate layer of the BestComm API, the task dependent
- * support code.
- *
- * Most likely you don't need to poke around inside this structure. The
- * fields are exposed in the header just for the sake of inline functions
- */
-struct bcom_task {
- unsigned int tasknum;
- unsigned int flags;
- int irq;
-
- struct bcom_bd *bd;
- phys_addr_t bd_pa;
- void **cookie;
- unsigned short index;
- unsigned short outdex;
- unsigned int num_bd;
- unsigned int bd_size;
-
- void* priv;
-};
-
-#define BCOM_FLAGS_NONE 0x00000000ul
-#define BCOM_FLAGS_ENABLE_TASK (1ul << 0)
-
-/**
- * bcom_enable - Enable a BestComm task
- * @tsk: The BestComm task structure
- *
- * This function makes sure the given task is enabled and can be run
- * by the BestComm engine as needed
- */
-extern void bcom_enable(struct bcom_task *tsk);
-
-/**
- * bcom_disable - Disable a BestComm task
- * @tsk: The BestComm task structure
- *
- * This function disable a given task, making sure it's not executed
- * by the BestComm engine.
- */
-extern void bcom_disable(struct bcom_task *tsk);
-
-
-/**
- * bcom_get_task_irq - Returns the irq number of a BestComm task
- * @tsk: The BestComm task structure
- */
-static inline int
-bcom_get_task_irq(struct bcom_task *tsk) {
- return tsk->irq;
-}
-
-/* ======================================================================== */
-/* BD based tasks helpers */
-/* ======================================================================== */
-
-#define BCOM_BD_READY 0x40000000ul
-
-/** _bcom_next_index - Get next input index.
- * @tsk: pointer to task structure
- *
- * Support function; Device drivers should not call this
- */
-static inline int
-_bcom_next_index(struct bcom_task *tsk)
-{
- return ((tsk->index + 1) == tsk->num_bd) ? 0 : tsk->index + 1;
-}
-
-/** _bcom_next_outdex - Get next output index.
- * @tsk: pointer to task structure
- *
- * Support function; Device drivers should not call this
- */
-static inline int
-_bcom_next_outdex(struct bcom_task *tsk)
-{
- return ((tsk->outdex + 1) == tsk->num_bd) ? 0 : tsk->outdex + 1;
-}
-
-/**
- * bcom_queue_empty - Checks if a BestComm task BD queue is empty
- * @tsk: The BestComm task structure
- */
-static inline int
-bcom_queue_empty(struct bcom_task *tsk)
-{
- return tsk->index == tsk->outdex;
-}
-
-/**
- * bcom_queue_full - Checks if a BestComm task BD queue is full
- * @tsk: The BestComm task structure
- */
-static inline int
-bcom_queue_full(struct bcom_task *tsk)
-{
- return tsk->outdex == _bcom_next_index(tsk);
-}
-
-/**
- * bcom_get_bd - Get a BD from the queue
- * @tsk: The BestComm task structure
- * index: Index of the BD to fetch
- */
-static inline struct bcom_bd
-*bcom_get_bd(struct bcom_task *tsk, unsigned int index)
-{
- /* A cast to (void*) so the address can be incremented by the
- * real size instead of by sizeof(struct bcom_bd) */
- return ((void *)tsk->bd) + (index * tsk->bd_size);
-}
-
-/**
- * bcom_buffer_done - Checks if a BestComm
- * @tsk: The BestComm task structure
- */
-static inline int
-bcom_buffer_done(struct bcom_task *tsk)
-{
- struct bcom_bd *bd;
- if (bcom_queue_empty(tsk))
- return 0;
-
- bd = bcom_get_bd(tsk, tsk->outdex);
- return !(bd->status & BCOM_BD_READY);
-}
-
-/**
- * bcom_prepare_next_buffer - clear status of next available buffer.
- * @tsk: The BestComm task structure
- *
- * Returns pointer to next buffer descriptor
- */
-static inline struct bcom_bd *
-bcom_prepare_next_buffer(struct bcom_task *tsk)
-{
- struct bcom_bd *bd;
-
- bd = bcom_get_bd(tsk, tsk->index);
- bd->status = 0; /* cleanup last status */
- return bd;
-}
-
-static inline void
-bcom_submit_next_buffer(struct bcom_task *tsk, void *cookie)
-{
- struct bcom_bd *bd = bcom_get_bd(tsk, tsk->index);
-
- tsk->cookie[tsk->index] = cookie;
- mb(); /* ensure the bd is really up-to-date */
- bd->status |= BCOM_BD_READY;
- tsk->index = _bcom_next_index(tsk);
- if (tsk->flags & BCOM_FLAGS_ENABLE_TASK)
- bcom_enable(tsk);
-}
-
-static inline void *
-bcom_retrieve_buffer(struct bcom_task *tsk, u32 *p_status, struct bcom_bd **p_bd)
-{
- void *cookie = tsk->cookie[tsk->outdex];
- struct bcom_bd *bd = bcom_get_bd(tsk, tsk->outdex);
-
- if (p_status)
- *p_status = bd->status;
- if (p_bd)
- *p_bd = bd;
- tsk->outdex = _bcom_next_outdex(tsk);
- return cookie;
-}
-
-#endif /* __BESTCOMM_H__ */
diff --git a/arch/powerpc/sysdev/bestcomm/bestcomm_priv.h b/arch/powerpc/sysdev/bestcomm/bestcomm_priv.h
deleted file mode 100644
index 3b52f3ffbdf..00000000000
--- a/arch/powerpc/sysdev/bestcomm/bestcomm_priv.h
+++ /dev/null
@@ -1,350 +0,0 @@
-/*
- * Private header for the MPC52xx processor BestComm driver
- *
- * By private, we mean that driver should not use it directly. It's meant
- * to be used by the BestComm engine driver itself and by the intermediate
- * layer between the core and the drivers.
- *
- * Copyright (C) 2006 Sylvain Munaut <tnt@246tNt.com>
- * Copyright (C) 2005 Varma Electronics Oy,
- * ( by Andrey Volkov <avolkov@varma-el.com> )
- * Copyright (C) 2003-2004 MontaVista, Software, Inc.
- * ( by Dale Farnsworth <dfarnsworth@mvista.com> )
- *
- * 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.
- */
-
-#ifndef __BESTCOMM_PRIV_H__
-#define __BESTCOMM_PRIV_H__
-
-#include <linux/spinlock.h>
-#include <linux/of.h>
-#include <asm/io.h>
-#include <asm/mpc52xx.h>
-
-#include "sram.h"
-
-
-/* ======================================================================== */
-/* Engine related stuff */
-/* ======================================================================== */
-
-/* Zones sizes and needed alignments */
-#define BCOM_MAX_TASKS 16
-#define BCOM_MAX_VAR 24
-#define BCOM_MAX_INC 8
-#define BCOM_MAX_FDT 64
-#define BCOM_MAX_CTX 20
-#define BCOM_CTX_SIZE (BCOM_MAX_CTX * sizeof(u32))
-#define BCOM_CTX_ALIGN 0x100
-#define BCOM_VAR_SIZE (BCOM_MAX_VAR * sizeof(u32))
-#define BCOM_INC_SIZE (BCOM_MAX_INC * sizeof(u32))
-#define BCOM_VAR_ALIGN 0x80
-#define BCOM_FDT_SIZE (BCOM_MAX_FDT * sizeof(u32))
-#define BCOM_FDT_ALIGN 0x100
-
-/**
- * struct bcom_tdt - Task Descriptor Table Entry
- *
- */
-struct bcom_tdt {
- u32 start;
- u32 stop;
- u32 var;
- u32 fdt;
- u32 exec_status; /* used internally by BestComm engine */
- u32 mvtp; /* used internally by BestComm engine */
- u32 context;
- u32 litbase;
-};
-
-/**
- * struct bcom_engine
- *
- * This holds all info needed globaly to handle the engine
- */
-struct bcom_engine {
- struct device_node *ofnode;
- struct mpc52xx_sdma __iomem *regs;
- phys_addr_t regs_base;
-
- struct bcom_tdt *tdt;
- u32 *ctx;
- u32 *var;
- u32 *fdt;
-
- spinlock_t lock;
-};
-
-extern struct bcom_engine *bcom_eng;
-
-
-/* ======================================================================== */
-/* Tasks related stuff */
-/* ======================================================================== */
-
-/* Tasks image header */
-#define BCOM_TASK_MAGIC 0x4243544B /* 'BCTK' */
-
-struct bcom_task_header {
- u32 magic;
- u8 desc_size; /* the size fields */
- u8 var_size; /* are given in number */
- u8 inc_size; /* of 32-bits words */
- u8 first_var;
- u8 reserved[8];
-};
-
-/* Descriptors structure & co */
-#define BCOM_DESC_NOP 0x000001f8
-#define BCOM_LCD_MASK 0x80000000
-#define BCOM_DRD_EXTENDED 0x40000000
-#define BCOM_DRD_INITIATOR_SHIFT 21
-
-/* Tasks pragma */
-#define BCOM_PRAGMA_BIT_RSV 7 /* reserved pragma bit */
-#define BCOM_PRAGMA_BIT_PRECISE_INC 6 /* increment 0=when possible, */
- /* 1=iter end */
-#define BCOM_PRAGMA_BIT_RST_ERROR_NO 5 /* don't reset errors on */
- /* task enable */
-#define BCOM_PRAGMA_BIT_PACK 4 /* pack data enable */
-#define BCOM_PRAGMA_BIT_INTEGER 3 /* data alignment */
- /* 0=frac(msb), 1=int(lsb) */
-#define BCOM_PRAGMA_BIT_SPECREAD 2 /* XLB speculative read */
-#define BCOM_PRAGMA_BIT_CW 1 /* write line buffer enable */
-#define BCOM_PRAGMA_BIT_RL 0 /* read line buffer enable */
-
- /* Looks like XLB speculative read generates XLB errors when a buffer
- * is at the end of the physical memory. i.e. when accessing the
- * lasts words, the engine tries to prefetch the next but there is no
- * next ...
- */
-#define BCOM_STD_PRAGMA ((0 << BCOM_PRAGMA_BIT_RSV) | \
- (0 << BCOM_PRAGMA_BIT_PRECISE_INC) | \
- (0 << BCOM_PRAGMA_BIT_RST_ERROR_NO) | \
- (0 << BCOM_PRAGMA_BIT_PACK) | \
- (0 << BCOM_PRAGMA_BIT_INTEGER) | \
- (0 << BCOM_PRAGMA_BIT_SPECREAD) | \
- (1 << BCOM_PRAGMA_BIT_CW) | \
- (1 << BCOM_PRAGMA_BIT_RL))
-
-#define BCOM_PCI_PRAGMA ((0 << BCOM_PRAGMA_BIT_RSV) | \
- (0 << BCOM_PRAGMA_BIT_PRECISE_INC) | \
- (0 << BCOM_PRAGMA_BIT_RST_ERROR_NO) | \
- (0 << BCOM_PRAGMA_BIT_PACK) | \
- (1 << BCOM_PRAGMA_BIT_INTEGER) | \
- (0 << BCOM_PRAGMA_BIT_SPECREAD) | \
- (1 << BCOM_PRAGMA_BIT_CW) | \
- (1 << BCOM_PRAGMA_BIT_RL))
-
-#define BCOM_ATA_PRAGMA BCOM_STD_PRAGMA
-#define BCOM_CRC16_DP_0_PRAGMA BCOM_STD_PRAGMA
-#define BCOM_CRC16_DP_1_PRAGMA BCOM_STD_PRAGMA
-#define BCOM_FEC_RX_BD_PRAGMA BCOM_STD_PRAGMA
-#define BCOM_FEC_TX_BD_PRAGMA BCOM_STD_PRAGMA
-#define BCOM_GEN_DP_0_PRAGMA BCOM_STD_PRAGMA
-#define BCOM_GEN_DP_1_PRAGMA BCOM_STD_PRAGMA
-#define BCOM_GEN_DP_2_PRAGMA BCOM_STD_PRAGMA
-#define BCOM_GEN_DP_3_PRAGMA BCOM_STD_PRAGMA
-#define BCOM_GEN_DP_BD_0_PRAGMA BCOM_STD_PRAGMA
-#define BCOM_GEN_DP_BD_1_PRAGMA BCOM_STD_PRAGMA
-#define BCOM_GEN_RX_BD_PRAGMA BCOM_STD_PRAGMA
-#define BCOM_GEN_TX_BD_PRAGMA BCOM_STD_PRAGMA
-#define BCOM_GEN_LPC_PRAGMA BCOM_STD_PRAGMA
-#define BCOM_PCI_RX_PRAGMA BCOM_PCI_PRAGMA
-#define BCOM_PCI_TX_PRAGMA BCOM_PCI_PRAGMA
-
-/* Initiators number */
-#define BCOM_INITIATOR_ALWAYS 0
-#define BCOM_INITIATOR_SCTMR_0 1
-#define BCOM_INITIATOR_SCTMR_1 2
-#define BCOM_INITIATOR_FEC_RX 3
-#define BCOM_INITIATOR_FEC_TX 4
-#define BCOM_INITIATOR_ATA_RX 5
-#define BCOM_INITIATOR_ATA_TX 6
-#define BCOM_INITIATOR_SCPCI_RX 7
-#define BCOM_INITIATOR_SCPCI_TX 8
-#define BCOM_INITIATOR_PSC3_RX 9
-#define BCOM_INITIATOR_PSC3_TX 10
-#define BCOM_INITIATOR_PSC2_RX 11
-#define BCOM_INITIATOR_PSC2_TX 12
-#define BCOM_INITIATOR_PSC1_RX 13
-#define BCOM_INITIATOR_PSC1_TX 14
-#define BCOM_INITIATOR_SCTMR_2 15
-#define BCOM_INITIATOR_SCLPC 16
-#define BCOM_INITIATOR_PSC5_RX 17
-#define BCOM_INITIATOR_PSC5_TX 18
-#define BCOM_INITIATOR_PSC4_RX 19
-#define BCOM_INITIATOR_PSC4_TX 20
-#define BCOM_INITIATOR_I2C2_RX 21
-#define BCOM_INITIATOR_I2C2_TX 22
-#define BCOM_INITIATOR_I2C1_RX 23
-#define BCOM_INITIATOR_I2C1_TX 24
-#define BCOM_INITIATOR_PSC6_RX 25
-#define BCOM_INITIATOR_PSC6_TX 26
-#define BCOM_INITIATOR_IRDA_RX 25
-#define BCOM_INITIATOR_IRDA_TX 26
-#define BCOM_INITIATOR_SCTMR_3 27
-#define BCOM_INITIATOR_SCTMR_4 28
-#define BCOM_INITIATOR_SCTMR_5 29
-#define BCOM_INITIATOR_SCTMR_6 30
-#define BCOM_INITIATOR_SCTMR_7 31
-
-/* Initiators priorities */
-#define BCOM_IPR_ALWAYS 7
-#define BCOM_IPR_SCTMR_0 2
-#define BCOM_IPR_SCTMR_1 2
-#define BCOM_IPR_FEC_RX 6
-#define BCOM_IPR_FEC_TX 5
-#define BCOM_IPR_ATA_RX 7
-#define BCOM_IPR_ATA_TX 7
-#define BCOM_IPR_SCPCI_RX 2
-#define BCOM_IPR_SCPCI_TX 2
-#define BCOM_IPR_PSC3_RX 2
-#define BCOM_IPR_PSC3_TX 2
-#define BCOM_IPR_PSC2_RX 2
-#define BCOM_IPR_PSC2_TX 2
-#define BCOM_IPR_PSC1_RX 2
-#define BCOM_IPR_PSC1_TX 2
-#define BCOM_IPR_SCTMR_2 2
-#define BCOM_IPR_SCLPC 2
-#define BCOM_IPR_PSC5_RX 2
-#define BCOM_IPR_PSC5_TX 2
-#define BCOM_IPR_PSC4_RX 2
-#define BCOM_IPR_PSC4_TX 2
-#define BCOM_IPR_I2C2_RX 2
-#define BCOM_IPR_I2C2_TX 2
-#define BCOM_IPR_I2C1_RX 2
-#define BCOM_IPR_I2C1_TX 2
-#define BCOM_IPR_PSC6_RX 2
-#define BCOM_IPR_PSC6_TX 2
-#define BCOM_IPR_IRDA_RX 2
-#define BCOM_IPR_IRDA_TX 2
-#define BCOM_IPR_SCTMR_3 2
-#define BCOM_IPR_SCTMR_4 2
-#define BCOM_IPR_SCTMR_5 2
-#define BCOM_IPR_SCTMR_6 2
-#define BCOM_IPR_SCTMR_7 2
-
-
-/* ======================================================================== */
-/* API */
-/* ======================================================================== */
-
-extern struct bcom_task *bcom_task_alloc(int bd_count, int bd_size, int priv_size);
-extern void bcom_task_free(struct bcom_task *tsk);
-extern int bcom_load_image(int task, u32 *task_image);
-extern void bcom_set_initiator(int task, int initiator);
-
-
-#define TASK_ENABLE 0x8000
-
-/**
- * bcom_disable_prefetch - Hook to disable bus prefetching
- *
- * ATA DMA and the original MPC5200 need this due to silicon bugs. At the
- * moment disabling prefetch is a one-way street. There is no mechanism
- * in place to turn prefetch back on after it has been disabled. There is
- * no reason it couldn't be done, it would just be more complex to implement.
- */
-static inline void bcom_disable_prefetch(void)
-{
- u16 regval;
-
- regval = in_be16(&bcom_eng->regs->PtdCntrl);
- out_be16(&bcom_eng->regs->PtdCntrl, regval | 1);
-};
-
-static inline void
-bcom_enable_task(int task)
-{
- u16 reg;
- reg = in_be16(&bcom_eng->regs->tcr[task]);
- out_be16(&bcom_eng->regs->tcr[task], reg | TASK_ENABLE);
-}
-
-static inline void
-bcom_disable_task(int task)
-{
- u16 reg = in_be16(&bcom_eng->regs->tcr[task]);
- out_be16(&bcom_eng->regs->tcr[task], reg & ~TASK_ENABLE);
-}
-
-
-static inline u32 *
-bcom_task_desc(int task)
-{
- return bcom_sram_pa2va(bcom_eng->tdt[task].start);
-}
-
-static inline int
-bcom_task_num_descs(int task)
-{
- return (bcom_eng->tdt[task].stop - bcom_eng->tdt[task].start)/sizeof(u32) + 1;
-}
-
-static inline u32 *
-bcom_task_var(int task)
-{
- return bcom_sram_pa2va(bcom_eng->tdt[task].var);
-}
-
-static inline u32 *
-bcom_task_inc(int task)
-{
- return &bcom_task_var(task)[BCOM_MAX_VAR];
-}
-
-
-static inline int
-bcom_drd_is_extended(u32 desc)
-{
- return (desc) & BCOM_DRD_EXTENDED;
-}
-
-static inline int
-bcom_desc_is_drd(u32 desc)
-{
- return !(desc & BCOM_LCD_MASK) && desc != BCOM_DESC_NOP;
-}
-
-static inline int
-bcom_desc_initiator(u32 desc)
-{
- return (desc >> BCOM_DRD_INITIATOR_SHIFT) & 0x1f;
-}
-
-static inline void
-bcom_set_desc_initiator(u32 *desc, int initiator)
-{
- *desc = (*desc & ~(0x1f << BCOM_DRD_INITIATOR_SHIFT)) |
- ((initiator & 0x1f) << BCOM_DRD_INITIATOR_SHIFT);
-}
-
-
-static inline void
-bcom_set_task_pragma(int task, int pragma)
-{
- u32 *fdt = &bcom_eng->tdt[task].fdt;
- *fdt = (*fdt & ~0xff) | pragma;
-}
-
-static inline void
-bcom_set_task_auto_start(int task, int next_task)
-{
- u16 __iomem *tcr = &bcom_eng->regs->tcr[task];
- out_be16(tcr, (in_be16(tcr) & ~0xff) | 0x00c0 | next_task);
-}
-
-static inline void
-bcom_set_tcr_initiator(int task, int initiator)
-{
- u16 __iomem *tcr = &bcom_eng->regs->tcr[task];
- out_be16(tcr, (in_be16(tcr) & ~0x1f00) | ((initiator & 0x1f) << 8));
-}
-
-
-#endif /* __BESTCOMM_PRIV_H__ */
-
diff --git a/arch/powerpc/sysdev/bestcomm/fec.c b/arch/powerpc/sysdev/bestcomm/fec.c
deleted file mode 100644
index 957a988d23e..00000000000
--- a/arch/powerpc/sysdev/bestcomm/fec.c
+++ /dev/null
@@ -1,270 +0,0 @@
-/*
- * Bestcomm FEC tasks driver
- *
- *
- * Copyright (C) 2006-2007 Sylvain Munaut <tnt@246tNt.com>
- * Copyright (C) 2003-2004 MontaVista, Software, Inc.
- * ( by Dale Farnsworth <dfarnsworth@mvista.com> )
- *
- * 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/kernel.h>
-#include <linux/module.h>
-#include <linux/types.h>
-#include <asm/io.h>
-
-#include "bestcomm.h"
-#include "bestcomm_priv.h"
-#include "fec.h"
-
-
-/* ======================================================================== */
-/* Task image/var/inc */
-/* ======================================================================== */
-
-/* fec tasks images */
-extern u32 bcom_fec_rx_task[];
-extern u32 bcom_fec_tx_task[];
-
-/* rx task vars that need to be set before enabling the task */
-struct bcom_fec_rx_var {
- u32 enable; /* (u16*) address of task's control register */
- u32 fifo; /* (u32*) address of fec's fifo */
- u32 bd_base; /* (struct bcom_bd*) beginning of ring buffer */
- u32 bd_last; /* (struct bcom_bd*) end of ring buffer */
- u32 bd_start; /* (struct bcom_bd*) current bd */
- u32 buffer_size; /* size of receive buffer */
-};
-
-/* rx task incs that need to be set before enabling the task */
-struct bcom_fec_rx_inc {
- u16 pad0;
- s16 incr_bytes;
- u16 pad1;
- s16 incr_dst;
- u16 pad2;
- s16 incr_dst_ma;
-};
-
-/* tx task vars that need to be set before enabling the task */
-struct bcom_fec_tx_var {
- u32 DRD; /* (u32*) address of self-modified DRD */
- u32 fifo; /* (u32*) address of fec's fifo */
- u32 enable; /* (u16*) address of task's control register */
- u32 bd_base; /* (struct bcom_bd*) beginning of ring buffer */
- u32 bd_last; /* (struct bcom_bd*) end of ring buffer */
- u32 bd_start; /* (struct bcom_bd*) current bd */
- u32 buffer_size; /* set by uCode for each packet */
-};
-
-/* tx task incs that need to be set before enabling the task */
-struct bcom_fec_tx_inc {
- u16 pad0;
- s16 incr_bytes;
- u16 pad1;
- s16 incr_src;
- u16 pad2;
- s16 incr_src_ma;
-};
-
-/* private structure in the task */
-struct bcom_fec_priv {
- phys_addr_t fifo;
- int maxbufsize;
-};
-
-
-/* ======================================================================== */
-/* Task support code */
-/* ======================================================================== */
-
-struct bcom_task *
-bcom_fec_rx_init(int queue_len, phys_addr_t fifo, int maxbufsize)
-{
- struct bcom_task *tsk;
- struct bcom_fec_priv *priv;
-
- tsk = bcom_task_alloc(queue_len, sizeof(struct bcom_fec_bd),
- sizeof(struct bcom_fec_priv));
- if (!tsk)
- return NULL;
-
- tsk->flags = BCOM_FLAGS_NONE;
-
- priv = tsk->priv;
- priv->fifo = fifo;
- priv->maxbufsize = maxbufsize;
-
- if (bcom_fec_rx_reset(tsk)) {
- bcom_task_free(tsk);
- return NULL;
- }
-
- return tsk;
-}
-EXPORT_SYMBOL_GPL(bcom_fec_rx_init);
-
-int
-bcom_fec_rx_reset(struct bcom_task *tsk)
-{
- struct bcom_fec_priv *priv = tsk->priv;
- struct bcom_fec_rx_var *var;
- struct bcom_fec_rx_inc *inc;
-
- /* Shutdown the task */
- bcom_disable_task(tsk->tasknum);
-
- /* Reset the microcode */
- var = (struct bcom_fec_rx_var *) bcom_task_var(tsk->tasknum);
- inc = (struct bcom_fec_rx_inc *) bcom_task_inc(tsk->tasknum);
-
- if (bcom_load_image(tsk->tasknum, bcom_fec_rx_task))
- return -1;
-
- var->enable = bcom_eng->regs_base +
- offsetof(struct mpc52xx_sdma, tcr[tsk->tasknum]);
- var->fifo = (u32) priv->fifo;
- var->bd_base = tsk->bd_pa;
- var->bd_last = tsk->bd_pa + ((tsk->num_bd-1) * tsk->bd_size);
- var->bd_start = tsk->bd_pa;
- var->buffer_size = priv->maxbufsize;
-
- inc->incr_bytes = -(s16)sizeof(u32); /* These should be in the */
- inc->incr_dst = sizeof(u32); /* task image, but we stick */
- inc->incr_dst_ma= sizeof(u8); /* to the official ones */
-
- /* Reset the BDs */
- tsk->index = 0;
- tsk->outdex = 0;
-
- memset(tsk->bd, 0x00, tsk->num_bd * tsk->bd_size);
-
- /* Configure some stuff */
- bcom_set_task_pragma(tsk->tasknum, BCOM_FEC_RX_BD_PRAGMA);
- bcom_set_task_auto_start(tsk->tasknum, tsk->tasknum);
-
- out_8(&bcom_eng->regs->ipr[BCOM_INITIATOR_FEC_RX], BCOM_IPR_FEC_RX);
-
- out_be32(&bcom_eng->regs->IntPend, 1<<tsk->tasknum); /* Clear ints */
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(bcom_fec_rx_reset);
-
-void
-bcom_fec_rx_release(struct bcom_task *tsk)
-{
- /* Nothing special for the FEC tasks */
- bcom_task_free(tsk);
-}
-EXPORT_SYMBOL_GPL(bcom_fec_rx_release);
-
-
-
- /* Return 2nd to last DRD */
- /* This is an ugly hack, but at least it's only done
- once at initialization */
-static u32 *self_modified_drd(int tasknum)
-{
- u32 *desc;
- int num_descs;
- int drd_count;
- int i;
-
- num_descs = bcom_task_num_descs(tasknum);
- desc = bcom_task_desc(tasknum) + num_descs - 1;
- drd_count = 0;
- for (i=0; i<num_descs; i++, desc--)
- if (bcom_desc_is_drd(*desc) && ++drd_count == 3)
- break;
- return desc;
-}
-
-struct bcom_task *
-bcom_fec_tx_init(int queue_len, phys_addr_t fifo)
-{
- struct bcom_task *tsk;
- struct bcom_fec_priv *priv;
-
- tsk = bcom_task_alloc(queue_len, sizeof(struct bcom_fec_bd),
- sizeof(struct bcom_fec_priv));
- if (!tsk)
- return NULL;
-
- tsk->flags = BCOM_FLAGS_ENABLE_TASK;
-
- priv = tsk->priv;
- priv->fifo = fifo;
-
- if (bcom_fec_tx_reset(tsk)) {
- bcom_task_free(tsk);
- return NULL;
- }
-
- return tsk;
-}
-EXPORT_SYMBOL_GPL(bcom_fec_tx_init);
-
-int
-bcom_fec_tx_reset(struct bcom_task *tsk)
-{
- struct bcom_fec_priv *priv = tsk->priv;
- struct bcom_fec_tx_var *var;
- struct bcom_fec_tx_inc *inc;
-
- /* Shutdown the task */
- bcom_disable_task(tsk->tasknum);
-
- /* Reset the microcode */
- var = (struct bcom_fec_tx_var *) bcom_task_var(tsk->tasknum);
- inc = (struct bcom_fec_tx_inc *) bcom_task_inc(tsk->tasknum);
-
- if (bcom_load_image(tsk->tasknum, bcom_fec_tx_task))
- return -1;
-
- var->enable = bcom_eng->regs_base +
- offsetof(struct mpc52xx_sdma, tcr[tsk->tasknum]);
- var->fifo = (u32) priv->fifo;
- var->DRD = bcom_sram_va2pa(self_modified_drd(tsk->tasknum));
- var->bd_base = tsk->bd_pa;
- var->bd_last = tsk->bd_pa + ((tsk->num_bd-1) * tsk->bd_size);
- var->bd_start = tsk->bd_pa;
-
- inc->incr_bytes = -(s16)sizeof(u32); /* These should be in the */
- inc->incr_src = sizeof(u32); /* task image, but we stick */
- inc->incr_src_ma= sizeof(u8); /* to the official ones */
-
- /* Reset the BDs */
- tsk->index = 0;
- tsk->outdex = 0;
-
- memset(tsk->bd, 0x00, tsk->num_bd * tsk->bd_size);
-
- /* Configure some stuff */
- bcom_set_task_pragma(tsk->tasknum, BCOM_FEC_TX_BD_PRAGMA);
- bcom_set_task_auto_start(tsk->tasknum, tsk->tasknum);
-
- out_8(&bcom_eng->regs->ipr[BCOM_INITIATOR_FEC_TX], BCOM_IPR_FEC_TX);
-
- out_be32(&bcom_eng->regs->IntPend, 1<<tsk->tasknum); /* Clear ints */
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(bcom_fec_tx_reset);
-
-void
-bcom_fec_tx_release(struct bcom_task *tsk)
-{
- /* Nothing special for the FEC tasks */
- bcom_task_free(tsk);
-}
-EXPORT_SYMBOL_GPL(bcom_fec_tx_release);
-
-
-MODULE_DESCRIPTION("BestComm FEC tasks driver");
-MODULE_AUTHOR("Dale Farnsworth <dfarnsworth@mvista.com>");
-MODULE_LICENSE("GPL v2");
-
diff --git a/arch/powerpc/sysdev/bestcomm/fec.h b/arch/powerpc/sysdev/bestcomm/fec.h
deleted file mode 100644
index ee565d94d50..00000000000
--- a/arch/powerpc/sysdev/bestcomm/fec.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Header for Bestcomm FEC tasks driver
- *
- *
- * Copyright (C) 2006-2007 Sylvain Munaut <tnt@246tNt.com>
- * Copyright (C) 2003-2004 MontaVista, Software, Inc.
- * ( by Dale Farnsworth <dfarnsworth@mvista.com> )
- *
- * 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.
- */
-
-#ifndef __BESTCOMM_FEC_H__
-#define __BESTCOMM_FEC_H__
-
-
-struct bcom_fec_bd {
- u32 status;
- u32 skb_pa;
-};
-
-#define BCOM_FEC_TX_BD_TFD 0x08000000ul /* transmit frame done */
-#define BCOM_FEC_TX_BD_TC 0x04000000ul /* transmit CRC */
-#define BCOM_FEC_TX_BD_ABC 0x02000000ul /* append bad CRC */
-
-#define BCOM_FEC_RX_BD_L 0x08000000ul /* buffer is last in frame */
-#define BCOM_FEC_RX_BD_BC 0x00800000ul /* DA is broadcast */
-#define BCOM_FEC_RX_BD_MC 0x00400000ul /* DA is multicast and not broadcast */
-#define BCOM_FEC_RX_BD_LG 0x00200000ul /* Rx frame length violation */
-#define BCOM_FEC_RX_BD_NO 0x00100000ul /* Rx non-octet aligned frame */
-#define BCOM_FEC_RX_BD_CR 0x00040000ul /* Rx CRC error */
-#define BCOM_FEC_RX_BD_OV 0x00020000ul /* overrun */
-#define BCOM_FEC_RX_BD_TR 0x00010000ul /* Rx frame truncated */
-#define BCOM_FEC_RX_BD_LEN_MASK 0x000007fful /* mask for length of received frame */
-#define BCOM_FEC_RX_BD_ERRORS (BCOM_FEC_RX_BD_LG | BCOM_FEC_RX_BD_NO | \
- BCOM_FEC_RX_BD_CR | BCOM_FEC_RX_BD_OV | BCOM_FEC_RX_BD_TR)
-
-
-extern struct bcom_task *
-bcom_fec_rx_init(int queue_len, phys_addr_t fifo, int maxbufsize);
-
-extern int
-bcom_fec_rx_reset(struct bcom_task *tsk);
-
-extern void
-bcom_fec_rx_release(struct bcom_task *tsk);
-
-
-extern struct bcom_task *
-bcom_fec_tx_init(int queue_len, phys_addr_t fifo);
-
-extern int
-bcom_fec_tx_reset(struct bcom_task *tsk);
-
-extern void
-bcom_fec_tx_release(struct bcom_task *tsk);
-
-
-#endif /* __BESTCOMM_FEC_H__ */
-
diff --git a/arch/powerpc/sysdev/bestcomm/gen_bd.c b/arch/powerpc/sysdev/bestcomm/gen_bd.c
deleted file mode 100644
index e0a53e3147b..00000000000
--- a/arch/powerpc/sysdev/bestcomm/gen_bd.c
+++ /dev/null
@@ -1,354 +0,0 @@
-/*
- * Driver for MPC52xx processor BestComm General Buffer Descriptor
- *
- * Copyright (C) 2007 Sylvain Munaut <tnt@246tNt.com>
- * Copyright (C) 2006 AppSpec Computer Technologies Corp.
- * Jeff Gibbons <jeff.gibbons@appspec.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published
- * by the Free Software Foundation.
- *
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/types.h>
-#include <asm/errno.h>
-#include <asm/io.h>
-
-#include <asm/mpc52xx.h>
-#include <asm/mpc52xx_psc.h>
-
-#include "bestcomm.h"
-#include "bestcomm_priv.h"
-#include "gen_bd.h"
-
-
-/* ======================================================================== */
-/* Task image/var/inc */
-/* ======================================================================== */
-
-/* gen_bd tasks images */
-extern u32 bcom_gen_bd_rx_task[];
-extern u32 bcom_gen_bd_tx_task[];
-
-/* rx task vars that need to be set before enabling the task */
-struct bcom_gen_bd_rx_var {
- u32 enable; /* (u16*) address of task's control register */
- u32 fifo; /* (u32*) address of gen_bd's fifo */
- u32 bd_base; /* (struct bcom_bd*) beginning of ring buffer */
- u32 bd_last; /* (struct bcom_bd*) end of ring buffer */
- u32 bd_start; /* (struct bcom_bd*) current bd */
- u32 buffer_size; /* size of receive buffer */
-};
-
-/* rx task incs that need to be set before enabling the task */
-struct bcom_gen_bd_rx_inc {
- u16 pad0;
- s16 incr_bytes;
- u16 pad1;
- s16 incr_dst;
-};
-
-/* tx task vars that need to be set before enabling the task */
-struct bcom_gen_bd_tx_var {
- u32 fifo; /* (u32*) address of gen_bd's fifo */
- u32 enable; /* (u16*) address of task's control register */
- u32 bd_base; /* (struct bcom_bd*) beginning of ring buffer */
- u32 bd_last; /* (struct bcom_bd*) end of ring buffer */
- u32 bd_start; /* (struct bcom_bd*) current bd */
- u32 buffer_size; /* set by uCode for each packet */
-};
-
-/* tx task incs that need to be set before enabling the task */
-struct bcom_gen_bd_tx_inc {
- u16 pad0;
- s16 incr_bytes;
- u16 pad1;
- s16 incr_src;
- u16 pad2;
- s16 incr_src_ma;
-};
-
-/* private structure */
-struct bcom_gen_bd_priv {
- phys_addr_t fifo;
- int initiator;
- int ipr;
- int maxbufsize;
-};
-
-
-/* ======================================================================== */
-/* Task support code */
-/* ======================================================================== */
-
-struct bcom_task *
-bcom_gen_bd_rx_init(int queue_len, phys_addr_t fifo,
- int initiator, int ipr, int maxbufsize)
-{
- struct bcom_task *tsk;
- struct bcom_gen_bd_priv *priv;
-
- tsk = bcom_task_alloc(queue_len, sizeof(struct bcom_gen_bd),
- sizeof(struct bcom_gen_bd_priv));
- if (!tsk)
- return NULL;
-
- tsk->flags = BCOM_FLAGS_NONE;
-
- priv = tsk->priv;
- priv->fifo = fifo;
- priv->initiator = initiator;
- priv->ipr = ipr;
- priv->maxbufsize = maxbufsize;
-
- if (bcom_gen_bd_rx_reset(tsk)) {
- bcom_task_free(tsk);
- return NULL;
- }
-
- return tsk;
-}
-EXPORT_SYMBOL_GPL(bcom_gen_bd_rx_init);
-
-int
-bcom_gen_bd_rx_reset(struct bcom_task *tsk)
-{
- struct bcom_gen_bd_priv *priv = tsk->priv;
- struct bcom_gen_bd_rx_var *var;
- struct bcom_gen_bd_rx_inc *inc;
-
- /* Shutdown the task */
- bcom_disable_task(tsk->tasknum);
-
- /* Reset the microcode */
- var = (struct bcom_gen_bd_rx_var *) bcom_task_var(tsk->tasknum);
- inc = (struct bcom_gen_bd_rx_inc *) bcom_task_inc(tsk->tasknum);
-
- if (bcom_load_image(tsk->tasknum, bcom_gen_bd_rx_task))
- return -1;
-
- var->enable = bcom_eng->regs_base +
- offsetof(struct mpc52xx_sdma, tcr[tsk->tasknum]);
- var->fifo = (u32) priv->fifo;
- var->bd_base = tsk->bd_pa;
- var->bd_last = tsk->bd_pa + ((tsk->num_bd-1) * tsk->bd_size);
- var->bd_start = tsk->bd_pa;
- var->buffer_size = priv->maxbufsize;
-
- inc->incr_bytes = -(s16)sizeof(u32);
- inc->incr_dst = sizeof(u32);
-
- /* Reset the BDs */
- tsk->index = 0;
- tsk->outdex = 0;
-
- memset(tsk->bd, 0x00, tsk->num_bd * tsk->bd_size);
-
- /* Configure some stuff */
- bcom_set_task_pragma(tsk->tasknum, BCOM_GEN_RX_BD_PRAGMA);
- bcom_set_task_auto_start(tsk->tasknum, tsk->tasknum);
-
- out_8(&bcom_eng->regs->ipr[priv->initiator], priv->ipr);
- bcom_set_initiator(tsk->tasknum, priv->initiator);
-
- out_be32(&bcom_eng->regs->IntPend, 1<<tsk->tasknum); /* Clear ints */
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(bcom_gen_bd_rx_reset);
-
-void
-bcom_gen_bd_rx_release(struct bcom_task *tsk)
-{
- /* Nothing special for the GenBD tasks */
- bcom_task_free(tsk);
-}
-EXPORT_SYMBOL_GPL(bcom_gen_bd_rx_release);
-
-
-extern struct bcom_task *
-bcom_gen_bd_tx_init(int queue_len, phys_addr_t fifo,
- int initiator, int ipr)
-{
- struct bcom_task *tsk;
- struct bcom_gen_bd_priv *priv;
-
- tsk = bcom_task_alloc(queue_len, sizeof(struct bcom_gen_bd),
- sizeof(struct bcom_gen_bd_priv));
- if (!tsk)
- return NULL;
-
- tsk->flags = BCOM_FLAGS_NONE;
-
- priv = tsk->priv;
- priv->fifo = fifo;
- priv->initiator = initiator;
- priv->ipr = ipr;
-
- if (bcom_gen_bd_tx_reset(tsk)) {
- bcom_task_free(tsk);
- return NULL;
- }
-
- return tsk;
-}
-EXPORT_SYMBOL_GPL(bcom_gen_bd_tx_init);
-
-int
-bcom_gen_bd_tx_reset(struct bcom_task *tsk)
-{
- struct bcom_gen_bd_priv *priv = tsk->priv;
- struct bcom_gen_bd_tx_var *var;
- struct bcom_gen_bd_tx_inc *inc;
-
- /* Shutdown the task */
- bcom_disable_task(tsk->tasknum);
-
- /* Reset the microcode */
- var = (struct bcom_gen_bd_tx_var *) bcom_task_var(tsk->tasknum);
- inc = (struct bcom_gen_bd_tx_inc *) bcom_task_inc(tsk->tasknum);
-
- if (bcom_load_image(tsk->tasknum, bcom_gen_bd_tx_task))
- return -1;
-
- var->enable = bcom_eng->regs_base +
- offsetof(struct mpc52xx_sdma, tcr[tsk->tasknum]);
- var->fifo = (u32) priv->fifo;
- var->bd_base = tsk->bd_pa;
- var->bd_last = tsk->bd_pa + ((tsk->num_bd-1) * tsk->bd_size);
- var->bd_start = tsk->bd_pa;
-
- inc->incr_bytes = -(s16)sizeof(u32);
- inc->incr_src = sizeof(u32);
- inc->incr_src_ma = sizeof(u8);
-
- /* Reset the BDs */
- tsk->index = 0;
- tsk->outdex = 0;
-
- memset(tsk->bd, 0x00, tsk->num_bd * tsk->bd_size);
-
- /* Configure some stuff */
- bcom_set_task_pragma(tsk->tasknum, BCOM_GEN_TX_BD_PRAGMA);
- bcom_set_task_auto_start(tsk->tasknum, tsk->tasknum);
-
- out_8(&bcom_eng->regs->ipr[priv->initiator], priv->ipr);
- bcom_set_initiator(tsk->tasknum, priv->initiator);
-
- out_be32(&bcom_eng->regs->IntPend, 1<<tsk->tasknum); /* Clear ints */
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(bcom_gen_bd_tx_reset);
-
-void
-bcom_gen_bd_tx_release(struct bcom_task *tsk)
-{
- /* Nothing special for the GenBD tasks */
- bcom_task_free(tsk);
-}
-EXPORT_SYMBOL_GPL(bcom_gen_bd_tx_release);
-
-/* ---------------------------------------------------------------------
- * PSC support code
- */
-
-/**
- * bcom_psc_parameters - Bestcomm initialization value table for PSC devices
- *
- * This structure is only used internally. It is a lookup table for PSC
- * specific parameters to bestcomm tasks.
- */
-static struct bcom_psc_params {
- int rx_initiator;
- int rx_ipr;
- int tx_initiator;
- int tx_ipr;
-} bcom_psc_params[] = {
- [0] = {
- .rx_initiator = BCOM_INITIATOR_PSC1_RX,
- .rx_ipr = BCOM_IPR_PSC1_RX,
- .tx_initiator = BCOM_INITIATOR_PSC1_TX,
- .tx_ipr = BCOM_IPR_PSC1_TX,
- },
- [1] = {
- .rx_initiator = BCOM_INITIATOR_PSC2_RX,
- .rx_ipr = BCOM_IPR_PSC2_RX,
- .tx_initiator = BCOM_INITIATOR_PSC2_TX,
- .tx_ipr = BCOM_IPR_PSC2_TX,
- },
- [2] = {
- .rx_initiator = BCOM_INITIATOR_PSC3_RX,
- .rx_ipr = BCOM_IPR_PSC3_RX,
- .tx_initiator = BCOM_INITIATOR_PSC3_TX,
- .tx_ipr = BCOM_IPR_PSC3_TX,
- },
- [3] = {
- .rx_initiator = BCOM_INITIATOR_PSC4_RX,
- .rx_ipr = BCOM_IPR_PSC4_RX,
- .tx_initiator = BCOM_INITIATOR_PSC4_TX,
- .tx_ipr = BCOM_IPR_PSC4_TX,
- },
- [4] = {
- .rx_initiator = BCOM_INITIATOR_PSC5_RX,
- .rx_ipr = BCOM_IPR_PSC5_RX,
- .tx_initiator = BCOM_INITIATOR_PSC5_TX,
- .tx_ipr = BCOM_IPR_PSC5_TX,
- },
- [5] = {
- .rx_initiator = BCOM_INITIATOR_PSC6_RX,
- .rx_ipr = BCOM_IPR_PSC6_RX,
- .tx_initiator = BCOM_INITIATOR_PSC6_TX,
- .tx_ipr = BCOM_IPR_PSC6_TX,
- },
-};
-
-/**
- * bcom_psc_gen_bd_rx_init - Allocate a receive bcom_task for a PSC port
- * @psc_num: Number of the PSC to allocate a task for
- * @queue_len: number of buffer descriptors to allocate for the task
- * @fifo: physical address of FIFO register
- * @maxbufsize: Maximum receive data size in bytes.
- *
- * Allocate a bestcomm task structure for receiving data from a PSC.
- */
-struct bcom_task * bcom_psc_gen_bd_rx_init(unsigned psc_num, int queue_len,
- phys_addr_t fifo, int maxbufsize)
-{
- if (psc_num >= MPC52xx_PSC_MAXNUM)
- return NULL;
-
- return bcom_gen_bd_rx_init(queue_len, fifo,
- bcom_psc_params[psc_num].rx_initiator,
- bcom_psc_params[psc_num].rx_ipr,
- maxbufsize);
-}
-EXPORT_SYMBOL_GPL(bcom_psc_gen_bd_rx_init);
-
-/**
- * bcom_psc_gen_bd_tx_init - Allocate a transmit bcom_task for a PSC port
- * @psc_num: Number of the PSC to allocate a task for
- * @queue_len: number of buffer descriptors to allocate for the task
- * @fifo: physical address of FIFO register
- *
- * Allocate a bestcomm task structure for transmitting data to a PSC.
- */
-struct bcom_task *
-bcom_psc_gen_bd_tx_init(unsigned psc_num, int queue_len, phys_addr_t fifo)
-{
- struct psc;
- return bcom_gen_bd_tx_init(queue_len, fifo,
- bcom_psc_params[psc_num].tx_initiator,
- bcom_psc_params[psc_num].tx_ipr);
-}
-EXPORT_SYMBOL_GPL(bcom_psc_gen_bd_tx_init);
-
-
-MODULE_DESCRIPTION("BestComm General Buffer Descriptor tasks driver");
-MODULE_AUTHOR("Jeff Gibbons <jeff.gibbons@appspec.com>");
-MODULE_LICENSE("GPL v2");
-
diff --git a/arch/powerpc/sysdev/bestcomm/gen_bd.h b/arch/powerpc/sysdev/bestcomm/gen_bd.h
deleted file mode 100644
index de47260e69d..00000000000
--- a/arch/powerpc/sysdev/bestcomm/gen_bd.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Header for Bestcomm General Buffer Descriptor tasks driver
- *
- *
- * Copyright (C) 2007 Sylvain Munaut <tnt@246tNt.com>
- * Copyright (C) 2006 AppSpec Computer Technologies Corp.
- * Jeff Gibbons <jeff.gibbons@appspec.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published
- * by the Free Software Foundation.
- *
- *
- */
-
-#ifndef __BESTCOMM_GEN_BD_H__
-#define __BESTCOMM_GEN_BD_H__
-
-struct bcom_gen_bd {
- u32 status;
- u32 buf_pa;
-};
-
-
-extern struct bcom_task *
-bcom_gen_bd_rx_init(int queue_len, phys_addr_t fifo,
- int initiator, int ipr, int maxbufsize);
-
-extern int
-bcom_gen_bd_rx_reset(struct bcom_task *tsk);
-
-extern void
-bcom_gen_bd_rx_release(struct bcom_task *tsk);
-
-
-extern struct bcom_task *
-bcom_gen_bd_tx_init(int queue_len, phys_addr_t fifo,
- int initiator, int ipr);
-
-extern int
-bcom_gen_bd_tx_reset(struct bcom_task *tsk);
-
-extern void
-bcom_gen_bd_tx_release(struct bcom_task *tsk);
-
-
-/* PSC support utility wrappers */
-struct bcom_task * bcom_psc_gen_bd_rx_init(unsigned psc_num, int queue_len,
- phys_addr_t fifo, int maxbufsize);
-struct bcom_task * bcom_psc_gen_bd_tx_init(unsigned psc_num, int queue_len,
- phys_addr_t fifo);
-#endif /* __BESTCOMM_GEN_BD_H__ */
-
diff --git a/arch/powerpc/sysdev/bestcomm/sram.c b/arch/powerpc/sysdev/bestcomm/sram.c
deleted file mode 100644
index b6db23e085f..00000000000
--- a/arch/powerpc/sysdev/bestcomm/sram.c
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
- * Simple memory allocator for on-board SRAM
- *
- *
- * Maintainer : Sylvain Munaut <tnt@246tNt.com>
- *
- * Copyright (C) 2005 Sylvain Munaut <tnt@246tNt.com>
- *
- * 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/err.h>
-#include <linux/kernel.h>
-#include <linux/export.h>
-#include <linux/slab.h>
-#include <linux/spinlock.h>
-#include <linux/string.h>
-#include <linux/ioport.h>
-#include <linux/of.h>
-
-#include <asm/io.h>
-#include <asm/mmu.h>
-
-#include "sram.h"
-
-
-/* Struct keeping our 'state' */
-struct bcom_sram *bcom_sram = NULL;
-EXPORT_SYMBOL_GPL(bcom_sram); /* needed for inline functions */
-
-
-/* ======================================================================== */
-/* Public API */
-/* ======================================================================== */
-/* DO NOT USE in interrupts, if needed in irq handler, we should use the
- _irqsave version of the spin_locks */
-
-int bcom_sram_init(struct device_node *sram_node, char *owner)
-{
- int rv;
- const u32 *regaddr_p;
- u64 regaddr64, size64;
- unsigned int psize;
-
- /* Create our state struct */
- if (bcom_sram) {
- printk(KERN_ERR "%s: bcom_sram_init: "
- "Already initialized !\n", owner);
- return -EBUSY;
- }
-
- bcom_sram = kmalloc(sizeof(struct bcom_sram), GFP_KERNEL);
- if (!bcom_sram) {
- printk(KERN_ERR "%s: bcom_sram_init: "
- "Couldn't allocate internal state !\n", owner);
- return -ENOMEM;
- }
-
- /* Get address and size of the sram */
- regaddr_p = of_get_address(sram_node, 0, &size64, NULL);
- if (!regaddr_p) {
- printk(KERN_ERR "%s: bcom_sram_init: "
- "Invalid device node !\n", owner);
- rv = -EINVAL;
- goto error_free;
- }
-
- regaddr64 = of_translate_address(sram_node, regaddr_p);
-
- bcom_sram->base_phys = (phys_addr_t) regaddr64;
- bcom_sram->size = (unsigned int) size64;
-
- /* Request region */
- if (!request_mem_region(bcom_sram->base_phys, bcom_sram->size, owner)) {
- printk(KERN_ERR "%s: bcom_sram_init: "
- "Couldn't request region !\n", owner);
- rv = -EBUSY;
- goto error_free;
- }
-
- /* Map SRAM */
- /* sram is not really __iomem */
- bcom_sram->base_virt = (void*) ioremap(bcom_sram->base_phys, bcom_sram->size);
-
- if (!bcom_sram->base_virt) {
- printk(KERN_ERR "%s: bcom_sram_init: "
- "Map error SRAM zone 0x%08lx (0x%0x)!\n",
- owner, (long)bcom_sram->base_phys, bcom_sram->size );
- rv = -ENOMEM;
- goto error_release;
- }
-
- /* Create an rheap (defaults to 32 bits word alignment) */
- bcom_sram->rh = rh_create(4);
-
- /* Attach the free zones */
-#if 0
- /* Currently disabled ... for future use only */
- reg_addr_p = of_get_property(sram_node, "available", &psize);
-#else
- regaddr_p = NULL;
- psize = 0;
-#endif
-
- if (!regaddr_p || !psize) {
- /* Attach the whole zone */
- rh_attach_region(bcom_sram->rh, 0, bcom_sram->size);
- } else {
- /* Attach each zone independently */
- while (psize >= 2 * sizeof(u32)) {
- phys_addr_t zbase = of_translate_address(sram_node, regaddr_p);
- rh_attach_region(bcom_sram->rh, zbase - bcom_sram->base_phys, regaddr_p[1]);
- regaddr_p += 2;
- psize -= 2 * sizeof(u32);
- }
- }
-
- /* Init our spinlock */
- spin_lock_init(&bcom_sram->lock);
-
- return 0;
-
-error_release:
- release_mem_region(bcom_sram->base_phys, bcom_sram->size);
-error_free:
- kfree(bcom_sram);
- bcom_sram = NULL;
-
- return rv;
-}
-EXPORT_SYMBOL_GPL(bcom_sram_init);
-
-void bcom_sram_cleanup(void)
-{
- /* Free resources */
- if (bcom_sram) {
- rh_destroy(bcom_sram->rh);
- iounmap((void __iomem *)bcom_sram->base_virt);
- release_mem_region(bcom_sram->base_phys, bcom_sram->size);
- kfree(bcom_sram);
- bcom_sram = NULL;
- }
-}
-EXPORT_SYMBOL_GPL(bcom_sram_cleanup);
-
-void* bcom_sram_alloc(int size, int align, phys_addr_t *phys)
-{
- unsigned long offset;
-
- spin_lock(&bcom_sram->lock);
- offset = rh_alloc_align(bcom_sram->rh, size, align, NULL);
- spin_unlock(&bcom_sram->lock);
-
- if (IS_ERR_VALUE(offset))
- return NULL;
-
- *phys = bcom_sram->base_phys + offset;
- return bcom_sram->base_virt + offset;
-}
-EXPORT_SYMBOL_GPL(bcom_sram_alloc);
-
-void bcom_sram_free(void *ptr)
-{
- unsigned long offset;
-
- if (!ptr)
- return;
-
- offset = ptr - bcom_sram->base_virt;
-
- spin_lock(&bcom_sram->lock);
- rh_free(bcom_sram->rh, offset);
- spin_unlock(&bcom_sram->lock);
-}
-EXPORT_SYMBOL_GPL(bcom_sram_free);
-
diff --git a/arch/powerpc/sysdev/bestcomm/sram.h b/arch/powerpc/sysdev/bestcomm/sram.h
deleted file mode 100644
index b6d668963cc..00000000000
--- a/arch/powerpc/sysdev/bestcomm/sram.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Handling of a sram zone for bestcomm
- *
- *
- * Copyright (C) 2007 Sylvain Munaut <tnt@246tNt.com>
- *
- * 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.
- */
-
-#ifndef __BESTCOMM_SRAM_H__
-#define __BESTCOMM_SRAM_H__
-
-#include <asm/rheap.h>
-#include <asm/mmu.h>
-#include <linux/spinlock.h>
-
-
-/* Structure used internally */
- /* The internals are here for the inline functions
- * sake, certainly not for the user to mess with !
- */
-struct bcom_sram {
- phys_addr_t base_phys;
- void *base_virt;
- unsigned int size;
- rh_info_t *rh;
- spinlock_t lock;
-};
-
-extern struct bcom_sram *bcom_sram;
-
-
-/* Public API */
-extern int bcom_sram_init(struct device_node *sram_node, char *owner);
-extern void bcom_sram_cleanup(void);
-
-extern void* bcom_sram_alloc(int size, int align, phys_addr_t *phys);
-extern void bcom_sram_free(void *ptr);
-
-static inline phys_addr_t bcom_sram_va2pa(void *va) {
- return bcom_sram->base_phys +
- (unsigned long)(va - bcom_sram->base_virt);
-}
-
-static inline void *bcom_sram_pa2va(phys_addr_t pa) {
- return bcom_sram->base_virt +
- (unsigned long)(pa - bcom_sram->base_phys);
-}
-
-
-#endif /* __BESTCOMM_SRAM_H__ */
-
diff --git a/arch/powerpc/sysdev/cpm1.c b/arch/powerpc/sysdev/cpm1.c
index d4fa03f2b6a..5e6ff38ea69 100644
--- a/arch/powerpc/sysdev/cpm1.c
+++ b/arch/powerpc/sysdev/cpm1.c
@@ -120,6 +120,7 @@ static irqreturn_t cpm_error_interrupt(int irq, void *dev)
static struct irqaction cpm_error_irqaction = {
.handler = cpm_error_interrupt,
+ .flags = IRQF_NO_THREAD,
.name = "error",
};
diff --git a/arch/powerpc/sysdev/cpm2_pic.c b/arch/powerpc/sysdev/cpm2_pic.c
index 10386b676d8..a11bd1d433a 100644
--- a/arch/powerpc/sysdev/cpm2_pic.c
+++ b/arch/powerpc/sysdev/cpm2_pic.c
@@ -27,7 +27,6 @@
*/
#include <linux/stddef.h>
-#include <linux/init.h>
#include <linux/sched.h>
#include <linux/signal.h>
#include <linux/irq.h>
diff --git a/arch/powerpc/sysdev/cpm_common.c b/arch/powerpc/sysdev/cpm_common.c
index 4dd534194ae..4f786957129 100644
--- a/arch/powerpc/sysdev/cpm_common.c
+++ b/arch/powerpc/sysdev/cpm_common.c
@@ -22,6 +22,7 @@
#include <linux/spinlock.h>
#include <linux/export.h>
#include <linux/of.h>
+#include <linux/of_address.h>
#include <linux/slab.h>
#include <asm/udbg.h>
diff --git a/arch/powerpc/sysdev/dart_iommu.c b/arch/powerpc/sysdev/dart_iommu.c
index bd968a43a48..9e5353ff6d1 100644
--- a/arch/powerpc/sysdev/dart_iommu.c
+++ b/arch/powerpc/sysdev/dart_iommu.c
@@ -292,6 +292,7 @@ static void iommu_table_dart_setup(void)
iommu_table_dart.it_offset = 0;
/* it_size is in number of entries */
iommu_table_dart.it_size = dart_tablesize / sizeof(u32);
+ iommu_table_dart.it_page_shift = IOMMU_PAGE_SHIFT_4K;
/* Initialize the common IOMMU code */
iommu_table_dart.it_base = (unsigned long)dart_vbase;
@@ -475,6 +476,11 @@ void __init alloc_dart_table(void)
*/
dart_tablebase = (unsigned long)
__va(memblock_alloc_base(1UL<<24, 1UL<<24, 0x80000000L));
+ /*
+ * The DART space is later unmapped from the kernel linear mapping and
+ * accessing dart_tablebase during kmemleak scanning will fault.
+ */
+ kmemleak_no_scan((void *)dart_tablebase);
printk(KERN_INFO "DART table allocated at: %lx\n", dart_tablebase);
}
diff --git a/arch/powerpc/sysdev/dcr.c b/arch/powerpc/sysdev/dcr.c
index 1bd0eba4d35..e9056e43857 100644
--- a/arch/powerpc/sysdev/dcr.c
+++ b/arch/powerpc/sysdev/dcr.c
@@ -152,9 +152,9 @@ EXPORT_SYMBOL_GPL(dcr_resource_len);
#ifdef CONFIG_PPC_DCR_MMIO
-u64 of_translate_dcr_address(struct device_node *dev,
- unsigned int dcr_n,
- unsigned int *out_stride)
+static u64 of_translate_dcr_address(struct device_node *dev,
+ unsigned int dcr_n,
+ unsigned int *out_stride)
{
struct device_node *dp;
const u32 *p;
diff --git a/arch/powerpc/sysdev/ehv_pic.c b/arch/powerpc/sysdev/ehv_pic.c
index 6e0e1005227..2d20f10a420 100644
--- a/arch/powerpc/sysdev/ehv_pic.c
+++ b/arch/powerpc/sysdev/ehv_pic.c
@@ -19,6 +19,7 @@
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/of.h>
+#include <linux/of_address.h>
#include <asm/io.h>
#include <asm/irq.h>
@@ -27,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);
@@ -81,7 +80,7 @@ int ehv_pic_set_affinity(struct irq_data *d, const struct cpumask *dest,
ev_int_set_config(src, config, prio, cpuid);
spin_unlock_irqrestore(&ehv_pic_lock, flags);
- return 0;
+ return IRQ_SET_MASK_OK;
}
static unsigned int ehv_pic_type_to_vecpri(unsigned int type)
@@ -112,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);
@@ -143,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_85xx_l2ctlr.c b/arch/powerpc/sysdev/fsl_85xx_l2ctlr.c
index 8cf93f029e1..afc2dbf3701 100644
--- a/arch/powerpc/sysdev/fsl_85xx_l2ctlr.c
+++ b/arch/powerpc/sysdev/fsl_85xx_l2ctlr.c
@@ -203,6 +203,7 @@ static struct of_device_id mpc85xx_l2ctlr_of_match[] = {
{ .compatible = "fsl,p1024-l2-cache-controller",},
{ .compatible = "fsl,p1015-l2-cache-controller",},
{ .compatible = "fsl,p1010-l2-cache-controller",},
+ { .compatible = "fsl,bsc9131-l2-cache-controller",},
{},
};
diff --git a/arch/powerpc/sysdev/fsl_gtm.c b/arch/powerpc/sysdev/fsl_gtm.c
index 0eb871cc343..06ac3c61b3d 100644
--- a/arch/powerpc/sysdev/fsl_gtm.c
+++ b/arch/powerpc/sysdev/fsl_gtm.c
@@ -19,6 +19,8 @@
#include <linux/list.h>
#include <linux/io.h>
#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
#include <linux/spinlock.h>
#include <linux/bitops.h>
#include <linux/slab.h>
@@ -401,16 +403,15 @@ static int __init fsl_gtm_init(void)
gtm->clock = *clock;
for (i = 0; i < ARRAY_SIZE(gtm->timers); i++) {
- int ret;
- struct resource irq;
+ unsigned int irq;
- ret = of_irq_to_resource(np, i, &irq);
- if (ret == NO_IRQ) {
+ irq = irq_of_parse_and_map(np, i);
+ if (irq == NO_IRQ) {
pr_err("%s: not enough interrupts specified\n",
np->full_name);
goto err;
}
- gtm->timers[i].irq = irq.start;
+ gtm->timers[i].irq = irq;
gtm->timers[i].gtm = gtm;
}
diff --git a/arch/powerpc/sysdev/fsl_ifc.c b/arch/powerpc/sysdev/fsl_ifc.c
deleted file mode 100644
index 2a36fd6a958..00000000000
--- a/arch/powerpc/sysdev/fsl_ifc.c
+++ /dev/null
@@ -1,306 +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/init.h>
-#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++) {
- __be32 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_lbc.c b/arch/powerpc/sysdev/fsl_lbc.c
index 300be2d06a2..d631022ffb4 100644
--- a/arch/powerpc/sysdev/fsl_lbc.c
+++ b/arch/powerpc/sysdev/fsl_lbc.c
@@ -74,8 +74,8 @@ int fsl_lbc_find(phys_addr_t addr_base)
lbc = fsl_lbc_ctrl_dev->regs;
for (i = 0; i < ARRAY_SIZE(lbc->bank); i++) {
- __be32 br = in_be32(&lbc->bank[i].br);
- __be32 or = in_be32(&lbc->bank[i].or);
+ u32 br = in_be32(&lbc->bank[i].br);
+ u32 or = in_be32(&lbc->bank[i].or);
if (br & BR_V && (br & or & BR_BA) == fsl_lbc_addr(addr_base))
return i;
@@ -97,7 +97,7 @@ EXPORT_SYMBOL(fsl_lbc_find);
int fsl_upm_find(phys_addr_t addr_base, struct fsl_upm *upm)
{
int bank;
- __be32 br;
+ u32 br;
struct fsl_lbc_regs __iomem *lbc;
bank = fsl_lbc_find(addr_base);
@@ -214,10 +214,14 @@ static irqreturn_t fsl_lbc_ctrl_irq(int irqno, void *data)
struct fsl_lbc_ctrl *ctrl = data;
struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
u32 status;
+ unsigned long flags;
+ spin_lock_irqsave(&fsl_lbc_lock, flags);
status = in_be32(&lbc->ltesr);
- if (!status)
+ if (!status) {
+ spin_unlock_irqrestore(&fsl_lbc_lock, flags);
return IRQ_NONE;
+ }
out_be32(&lbc->ltesr, LTESR_CLEAR);
out_be32(&lbc->lteatr, 0);
@@ -260,6 +264,7 @@ static irqreturn_t fsl_lbc_ctrl_irq(int irqno, void *data)
if (status & ~LTESR_MASK)
dev_err(ctrl->dev, "Unknown error: "
"LTESR 0x%08X\n", status);
+ spin_unlock_irqrestore(&fsl_lbc_lock, flags);
return IRQ_HANDLED;
}
@@ -298,8 +303,8 @@ static int fsl_lbc_ctrl_probe(struct platform_device *dev)
goto err;
}
- fsl_lbc_ctrl_dev->irq = irq_of_parse_and_map(dev->dev.of_node, 0);
- if (fsl_lbc_ctrl_dev->irq == NO_IRQ) {
+ fsl_lbc_ctrl_dev->irq[0] = irq_of_parse_and_map(dev->dev.of_node, 0);
+ if (!fsl_lbc_ctrl_dev->irq[0]) {
dev_err(&dev->dev, "failed to get irq resource\n");
ret = -ENODEV;
goto err;
@@ -311,20 +316,34 @@ static int fsl_lbc_ctrl_probe(struct platform_device *dev)
if (ret < 0)
goto err;
- ret = request_irq(fsl_lbc_ctrl_dev->irq, fsl_lbc_ctrl_irq, 0,
+ ret = request_irq(fsl_lbc_ctrl_dev->irq[0], fsl_lbc_ctrl_irq, 0,
"fsl-lbc", fsl_lbc_ctrl_dev);
if (ret != 0) {
dev_err(&dev->dev, "failed to install irq (%d)\n",
- fsl_lbc_ctrl_dev->irq);
- ret = fsl_lbc_ctrl_dev->irq;
+ fsl_lbc_ctrl_dev->irq[0]);
+ ret = fsl_lbc_ctrl_dev->irq[0];
goto err;
}
+ fsl_lbc_ctrl_dev->irq[1] = irq_of_parse_and_map(dev->dev.of_node, 1);
+ if (fsl_lbc_ctrl_dev->irq[1]) {
+ ret = request_irq(fsl_lbc_ctrl_dev->irq[1], fsl_lbc_ctrl_irq,
+ IRQF_SHARED, "fsl-lbc-err", fsl_lbc_ctrl_dev);
+ if (ret) {
+ dev_err(&dev->dev, "failed to install irq (%d)\n",
+ fsl_lbc_ctrl_dev->irq[1]);
+ ret = fsl_lbc_ctrl_dev->irq[1];
+ goto err1;
+ }
+ }
+
/* Enable interrupts for any detected events */
out_be32(&fsl_lbc_ctrl_dev->regs->lteir, LTEIR_ENABLE);
return 0;
+err1:
+ free_irq(fsl_lbc_ctrl_dev->irq[0], fsl_lbc_ctrl_dev);
err:
iounmap(fsl_lbc_ctrl_dev->regs);
kfree(fsl_lbc_ctrl_dev);
diff --git a/arch/powerpc/sysdev/fsl_mpic_timer_wakeup.c b/arch/powerpc/sysdev/fsl_mpic_timer_wakeup.c
new file mode 100644
index 00000000000..1707bf04dec
--- /dev/null
+++ b/arch/powerpc/sysdev/fsl_mpic_timer_wakeup.c
@@ -0,0 +1,161 @@
+/*
+ * MPIC timer wakeup driver
+ *
+ * Copyright 2013 Freescale Semiconductor, Inc.
+ *
+ * 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+
+#include <asm/mpic_timer.h>
+#include <asm/mpic.h>
+
+struct fsl_mpic_timer_wakeup {
+ struct mpic_timer *timer;
+ struct work_struct free_work;
+};
+
+static struct fsl_mpic_timer_wakeup *fsl_wakeup;
+static DEFINE_MUTEX(sysfs_lock);
+
+static void fsl_free_resource(struct work_struct *ws)
+{
+ struct fsl_mpic_timer_wakeup *wakeup =
+ container_of(ws, struct fsl_mpic_timer_wakeup, free_work);
+
+ mutex_lock(&sysfs_lock);
+
+ if (wakeup->timer) {
+ disable_irq_wake(wakeup->timer->irq);
+ mpic_free_timer(wakeup->timer);
+ }
+
+ wakeup->timer = NULL;
+ mutex_unlock(&sysfs_lock);
+}
+
+static irqreturn_t fsl_mpic_timer_irq(int irq, void *dev_id)
+{
+ struct fsl_mpic_timer_wakeup *wakeup = dev_id;
+
+ schedule_work(&wakeup->free_work);
+
+ return wakeup->timer ? IRQ_HANDLED : IRQ_NONE;
+}
+
+static ssize_t fsl_timer_wakeup_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct timeval interval;
+ int val = 0;
+
+ mutex_lock(&sysfs_lock);
+ if (fsl_wakeup->timer) {
+ mpic_get_remain_time(fsl_wakeup->timer, &interval);
+ val = interval.tv_sec + 1;
+ }
+ mutex_unlock(&sysfs_lock);
+
+ return sprintf(buf, "%d\n", val);
+}
+
+static ssize_t fsl_timer_wakeup_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t count)
+{
+ struct timeval interval;
+ int ret;
+
+ interval.tv_usec = 0;
+ if (kstrtol(buf, 0, &interval.tv_sec))
+ return -EINVAL;
+
+ mutex_lock(&sysfs_lock);
+
+ if (fsl_wakeup->timer) {
+ disable_irq_wake(fsl_wakeup->timer->irq);
+ mpic_free_timer(fsl_wakeup->timer);
+ fsl_wakeup->timer = NULL;
+ }
+
+ if (!interval.tv_sec) {
+ mutex_unlock(&sysfs_lock);
+ return count;
+ }
+
+ fsl_wakeup->timer = mpic_request_timer(fsl_mpic_timer_irq,
+ fsl_wakeup, &interval);
+ if (!fsl_wakeup->timer) {
+ mutex_unlock(&sysfs_lock);
+ return -EINVAL;
+ }
+
+ ret = enable_irq_wake(fsl_wakeup->timer->irq);
+ if (ret) {
+ mpic_free_timer(fsl_wakeup->timer);
+ fsl_wakeup->timer = NULL;
+ mutex_unlock(&sysfs_lock);
+
+ return ret;
+ }
+
+ mpic_start_timer(fsl_wakeup->timer);
+
+ mutex_unlock(&sysfs_lock);
+
+ return count;
+}
+
+static struct device_attribute mpic_attributes = __ATTR(timer_wakeup, 0644,
+ fsl_timer_wakeup_show, fsl_timer_wakeup_store);
+
+static int __init fsl_wakeup_sys_init(void)
+{
+ int ret;
+
+ fsl_wakeup = kzalloc(sizeof(struct fsl_mpic_timer_wakeup), GFP_KERNEL);
+ if (!fsl_wakeup)
+ return -ENOMEM;
+
+ INIT_WORK(&fsl_wakeup->free_work, fsl_free_resource);
+
+ ret = device_create_file(mpic_subsys.dev_root, &mpic_attributes);
+ if (ret)
+ kfree(fsl_wakeup);
+
+ return ret;
+}
+
+static void __exit fsl_wakeup_sys_exit(void)
+{
+ device_remove_file(mpic_subsys.dev_root, &mpic_attributes);
+
+ mutex_lock(&sysfs_lock);
+
+ if (fsl_wakeup->timer) {
+ disable_irq_wake(fsl_wakeup->timer->irq);
+ mpic_free_timer(fsl_wakeup->timer);
+ }
+
+ kfree(fsl_wakeup);
+
+ mutex_unlock(&sysfs_lock);
+}
+
+module_init(fsl_wakeup_sys_init);
+module_exit(fsl_wakeup_sys_exit);
+
+MODULE_DESCRIPTION("Freescale MPIC global timer wakeup driver");
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Wang Dongsheng <dongsheng.wang@freescale.com>");
diff --git a/arch/powerpc/sysdev/fsl_msi.c b/arch/powerpc/sysdev/fsl_msi.c
index 6e53d97abd3..77efbaec7b9 100644
--- a/arch/powerpc/sysdev/fsl_msi.c
+++ b/arch/powerpc/sysdev/fsl_msi.c
@@ -28,7 +28,19 @@
#include "fsl_msi.h"
#include "fsl_pci.h"
-LIST_HEAD(msi_head);
+#define MSIIR_OFFSET_MASK 0xfffff
+#define MSIIR_IBS_SHIFT 0
+#define MSIIR_SRS_SHIFT 5
+#define MSIIR1_IBS_SHIFT 4
+#define MSIIR1_SRS_SHIFT 0
+#define MSI_SRS_MASK 0xf
+#define MSI_IBS_MASK 0x1f
+
+#define msi_hwirq(msi, msir_index, intr_index) \
+ ((msir_index) << (msi)->srs_shift | \
+ ((intr_index) << (msi)->ibs_shift))
+
+static LIST_HEAD(msi_head);
struct fsl_msi_feature {
u32 fsl_pic_ip;
@@ -80,18 +92,19 @@ static const struct irq_domain_ops fsl_msi_host_ops = {
static int fsl_msi_init_allocator(struct fsl_msi *msi_data)
{
- int rc;
+ int rc, hwirq;
- rc = msi_bitmap_alloc(&msi_data->bitmap, NR_MSI_IRQS,
+ rc = msi_bitmap_alloc(&msi_data->bitmap, NR_MSI_IRQS_MAX,
msi_data->irqhost->of_node);
if (rc)
return rc;
- rc = msi_bitmap_reserve_dt_hwirqs(&msi_data->bitmap);
- if (rc < 0) {
- msi_bitmap_free(&msi_data->bitmap);
- return rc;
- }
+ /*
+ * Reserve all the hwirqs
+ * The available hwirqs will be released in fsl_msi_setup_hwirq()
+ */
+ for (hwirq = 0; hwirq < NR_MSI_IRQS_MAX; hwirq++)
+ msi_bitmap_reserve_hwirq(&msi_data->bitmap, hwirq);
return 0;
}
@@ -130,7 +143,7 @@ static void fsl_compose_msi_msg(struct pci_dev *pdev, int hwirq,
struct pci_controller *hose = pci_bus_to_host(pdev->bus);
u64 address; /* Physical address of the MSIIR */
int len;
- const u64 *reg;
+ const __be64 *reg;
/* If the msi-address-64 property exists, then use it */
reg = of_get_property(hose->dn, "msi-address-64", &len);
@@ -144,8 +157,9 @@ static void fsl_compose_msi_msg(struct pci_dev *pdev, int hwirq,
msg->data = hwirq;
- pr_debug("%s: allocated srs: %d, ibs: %d\n",
- __func__, hwirq / IRQS_PER_MSI_REG, hwirq % IRQS_PER_MSI_REG);
+ pr_debug("%s: allocated srs: %d, ibs: %d\n", __func__,
+ (hwirq >> msi_data->srs_shift) & MSI_SRS_MASK,
+ (hwirq >> msi_data->ibs_shift) & MSI_IBS_MASK);
}
static int fsl_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
@@ -255,7 +269,7 @@ static void fsl_msi_cascade(unsigned int irq, struct irq_desc *desc)
msir_index = cascade_data->index;
- if (msir_index >= NR_MSI_REG)
+ if (msir_index >= NR_MSI_REG_MAX)
cascade_irq = NO_IRQ;
irqd_set_chained_irq_inprogress(idata);
@@ -285,8 +299,8 @@ static void fsl_msi_cascade(unsigned int irq, struct irq_desc *desc)
intr_index = ffs(msir_value) - 1;
cascade_irq = irq_linear_revmap(msi_data->irqhost,
- msir_index * IRQS_PER_MSI_REG +
- intr_index + have_shift);
+ msi_hwirq(msi_data, msir_index,
+ intr_index + have_shift));
if (cascade_irq != NO_IRQ)
generic_handle_irq(cascade_irq);
have_shift += intr_index + 1;
@@ -316,7 +330,7 @@ static int fsl_of_msi_remove(struct platform_device *ofdev)
if (msi->list.prev != NULL)
list_del(&msi->list);
- for (i = 0; i < NR_MSI_REG; i++) {
+ for (i = 0; i < NR_MSI_REG_MAX; i++) {
virq = msi->msi_virqs[i];
if (virq != NO_IRQ) {
cascade_data = irq_get_handler_data(virq);
@@ -333,11 +347,13 @@ static int fsl_of_msi_remove(struct platform_device *ofdev)
return 0;
}
+static struct lock_class_key fsl_msi_irq_class;
+
static int fsl_msi_setup_hwirq(struct fsl_msi *msi, struct platform_device *dev,
int offset, int irq_index)
{
struct fsl_msi_cascade_data *cascade_data = NULL;
- int virt_msir;
+ int virt_msir, i;
virt_msir = irq_of_parse_and_map(dev->dev.of_node, irq_index);
if (virt_msir == NO_IRQ) {
@@ -351,13 +367,18 @@ static int fsl_msi_setup_hwirq(struct fsl_msi *msi, struct platform_device *dev,
dev_err(&dev->dev, "No memory for MSI cascade data\n");
return -ENOMEM;
}
-
+ irq_set_lockdep_class(virt_msir, &fsl_msi_irq_class);
msi->msi_virqs[irq_index] = virt_msir;
cascade_data->index = offset;
cascade_data->msi_data = msi;
irq_set_handler_data(virt_msir, cascade_data);
irq_set_chained_handler(virt_msir, fsl_msi_cascade);
+ /* Release the hwirqs corresponding to this MSI register */
+ for (i = 0; i < IRQS_PER_MSI_REG; i++)
+ msi_bitmap_free_hwirqs(&msi->bitmap,
+ msi_hwirq(msi, offset, i), 1);
+
return 0;
}
@@ -366,14 +387,12 @@ static int fsl_of_msi_probe(struct platform_device *dev)
{
const struct of_device_id *match;
struct fsl_msi *msi;
- struct resource res;
+ struct resource res, msiir;
int err, i, j, irq_index, count;
- int rc;
const u32 *p;
const struct fsl_msi_feature *features;
int len;
u32 offset;
- static const u32 all_avail[] = { 0, NR_MSI_IRQS };
match = of_match_device(fsl_of_msi_ids, &dev->dev);
if (!match)
@@ -390,7 +409,7 @@ static int fsl_of_msi_probe(struct platform_device *dev)
platform_set_drvdata(dev, msi);
msi->irqhost = irq_domain_add_linear(dev->dev.of_node,
- NR_MSI_IRQS, &fsl_msi_host_ops, msi);
+ NR_MSI_IRQS_MAX, &fsl_msi_host_ops, msi);
if (msi->irqhost == NULL) {
dev_err(&dev->dev, "No memory for MSI irqhost\n");
@@ -419,6 +438,16 @@ static int fsl_of_msi_probe(struct platform_device *dev)
}
msi->msiir_offset =
features->msiir_offset + (res.start & 0xfffff);
+
+ /*
+ * First read the MSIIR/MSIIR1 offset from dts
+ * On failure use the hardcode MSIIR offset
+ */
+ if (of_address_to_resource(dev->dev.of_node, 1, &msiir))
+ msi->msiir_offset = features->msiir_offset +
+ (res.start & MSIIR_OFFSET_MASK);
+ else
+ msi->msiir_offset = msiir.start & MSIIR_OFFSET_MASK;
}
msi->feature = features->fsl_pic_ip;
@@ -429,42 +458,66 @@ static int fsl_of_msi_probe(struct platform_device *dev)
*/
msi->phandle = dev->dev.of_node->phandle;
- rc = fsl_msi_init_allocator(msi);
- if (rc) {
+ err = fsl_msi_init_allocator(msi);
+ if (err) {
dev_err(&dev->dev, "Error allocating MSI bitmap\n");
goto error_out;
}
p = of_get_property(dev->dev.of_node, "msi-available-ranges", &len);
- if (p && len % (2 * sizeof(u32)) != 0) {
- dev_err(&dev->dev, "%s: Malformed msi-available-ranges property\n",
- __func__);
- err = -EINVAL;
- goto error_out;
- }
- if (!p) {
- p = all_avail;
- len = sizeof(all_avail);
- }
+ if (of_device_is_compatible(dev->dev.of_node, "fsl,mpic-msi-v4.3")) {
+ msi->srs_shift = MSIIR1_SRS_SHIFT;
+ msi->ibs_shift = MSIIR1_IBS_SHIFT;
+ if (p)
+ dev_warn(&dev->dev, "%s: dose not support msi-available-ranges property\n",
+ __func__);
+
+ for (irq_index = 0; irq_index < NR_MSI_REG_MSIIR1;
+ irq_index++) {
+ err = fsl_msi_setup_hwirq(msi, dev,
+ irq_index, irq_index);
+ if (err)
+ goto error_out;
+ }
+ } else {
+ static const u32 all_avail[] =
+ { 0, NR_MSI_REG_MSIIR * IRQS_PER_MSI_REG };
+
+ msi->srs_shift = MSIIR_SRS_SHIFT;
+ msi->ibs_shift = MSIIR_IBS_SHIFT;
- for (irq_index = 0, i = 0; i < len / (2 * sizeof(u32)); i++) {
- if (p[i * 2] % IRQS_PER_MSI_REG ||
- p[i * 2 + 1] % IRQS_PER_MSI_REG) {
- printk(KERN_WARNING "%s: %s: msi available range of %u at %u is not IRQ-aligned\n",
- __func__, dev->dev.of_node->full_name,
- p[i * 2 + 1], p[i * 2]);
+ if (p && len % (2 * sizeof(u32)) != 0) {
+ dev_err(&dev->dev, "%s: Malformed msi-available-ranges property\n",
+ __func__);
err = -EINVAL;
goto error_out;
}
- offset = p[i * 2] / IRQS_PER_MSI_REG;
- count = p[i * 2 + 1] / IRQS_PER_MSI_REG;
+ if (!p) {
+ p = all_avail;
+ len = sizeof(all_avail);
+ }
- for (j = 0; j < count; j++, irq_index++) {
- err = fsl_msi_setup_hwirq(msi, dev, offset + j, irq_index);
- if (err)
+ for (irq_index = 0, i = 0; i < len / (2 * sizeof(u32)); i++) {
+ if (p[i * 2] % IRQS_PER_MSI_REG ||
+ p[i * 2 + 1] % IRQS_PER_MSI_REG) {
+ pr_warn("%s: %s: msi available range of %u at %u is not IRQ-aligned\n",
+ __func__, dev->dev.of_node->full_name,
+ p[i * 2 + 1], p[i * 2]);
+ err = -EINVAL;
goto error_out;
+ }
+
+ offset = p[i * 2] / IRQS_PER_MSI_REG;
+ count = p[i * 2 + 1] / IRQS_PER_MSI_REG;
+
+ for (j = 0; j < count; j++, irq_index++) {
+ err = fsl_msi_setup_hwirq(msi, dev, offset + j,
+ irq_index);
+ if (err)
+ goto error_out;
+ }
}
}
@@ -507,6 +560,10 @@ static const struct of_device_id fsl_of_msi_ids[] = {
.data = &mpic_msi_feature,
},
{
+ .compatible = "fsl,mpic-msi-v4.3",
+ .data = &mpic_msi_feature,
+ },
+ {
.compatible = "fsl,ipic-msi",
.data = &ipic_msi_feature,
},
diff --git a/arch/powerpc/sysdev/fsl_msi.h b/arch/powerpc/sysdev/fsl_msi.h
index 8225f8653f7..df9aa9fe093 100644
--- a/arch/powerpc/sysdev/fsl_msi.h
+++ b/arch/powerpc/sysdev/fsl_msi.h
@@ -16,9 +16,11 @@
#include <linux/of.h>
#include <asm/msi_bitmap.h>
-#define NR_MSI_REG 8
+#define NR_MSI_REG_MSIIR 8 /* MSIIR can index 8 MSI registers */
+#define NR_MSI_REG_MSIIR1 16 /* MSIIR1 can index 16 MSI registers */
+#define NR_MSI_REG_MAX NR_MSI_REG_MSIIR1
#define IRQS_PER_MSI_REG 32
-#define NR_MSI_IRQS (NR_MSI_REG * IRQS_PER_MSI_REG)
+#define NR_MSI_IRQS_MAX (NR_MSI_REG_MAX * IRQS_PER_MSI_REG)
#define FSL_PIC_IP_MASK 0x0000000F
#define FSL_PIC_IP_MPIC 0x00000001
@@ -31,9 +33,11 @@ struct fsl_msi {
unsigned long cascade_irq;
u32 msiir_offset; /* Offset of MSIIR, relative to start of CCSR */
+ u32 ibs_shift; /* Shift of interrupt bit select */
+ u32 srs_shift; /* Shift of the shared interrupt register select */
void __iomem *msi_regs;
u32 feature;
- int msi_virqs[NR_MSI_REG];
+ int msi_virqs[NR_MSI_REG_MAX];
struct msi_bitmap bitmap;
diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c
index 92a5915b182..4bd091a0558 100644
--- a/arch/powerpc/sysdev/fsl_pci.c
+++ b/arch/powerpc/sysdev/fsl_pci.c
@@ -22,26 +22,33 @@
#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>
#include <asm/prom.h>
#include <asm/pci-bridge.h>
+#include <asm/ppc-pci.h>
#include <asm/machdep.h>
+#include <asm/disassemble.h>
+#include <asm/ppc-opcode.h>
#include <sysdev/fsl_soc.h>
#include <sysdev/fsl_pci.h>
static int fsl_pcie_bus_fixup, is_mpc83xx_pci;
-static void quirk_fsl_pcie_header(struct pci_dev *dev)
+static void quirk_fsl_pcie_early(struct pci_dev *dev)
{
u8 hdr_type;
/* if we aren't a PCIe don't bother */
- if (!pci_find_capability(dev, PCI_CAP_ID_EXP))
+ if (!pci_is_pcie(dev))
return;
/* if we aren't in host mode don't bother */
@@ -54,18 +61,57 @@ static void quirk_fsl_pcie_header(struct pci_dev *dev)
return;
}
-static int __init fsl_pcie_check_link(struct pci_controller *hose)
+static int fsl_indirect_read_config(struct pci_bus *, unsigned int,
+ int, int, u32 *);
+
+static int fsl_pcie_check_link(struct pci_controller *hose)
{
- u32 val;
+ u32 val = 0;
+
+ if (hose->indirect_type & PPC_INDIRECT_TYPE_FSL_CFG_REG_LINK) {
+ if (hose->ops->read == fsl_indirect_read_config) {
+ struct pci_bus bus;
+ bus.number = hose->first_busno;
+ bus.sysdata = hose;
+ bus.ops = hose->ops;
+ indirect_read_config(&bus, 0, PCIE_LTSSM, 4, &val);
+ } else
+ early_read_config_dword(hose, 0, 0, PCIE_LTSSM, &val);
+ if (val < PCIE_LTSSM_L0)
+ return 1;
+ } else {
+ struct ccsr_pci __iomem *pci = hose->private_data;
+ /* for PCIe IP rev 3.0 or greater use CSR0 for link state */
+ val = (in_be32(&pci->pex_csr0) & PEX_CSR0_LTSSM_MASK)
+ >> PEX_CSR0_LTSSM_SHIFT;
+ if (val != PEX_CSR0_LTSSM_L0)
+ return 1;
+ }
- early_read_config_dword(hose, 0, 0, PCIE_LTSSM, &val);
- if (val < PCIE_LTSSM_L0)
- return 1;
return 0;
}
+static int fsl_indirect_read_config(struct pci_bus *bus, unsigned int devfn,
+ int offset, int len, u32 *val)
+{
+ struct pci_controller *hose = pci_bus_to_host(bus);
+
+ if (fsl_pcie_check_link(hose))
+ hose->indirect_type |= PPC_INDIRECT_TYPE_NO_PCIE_LINK;
+ else
+ hose->indirect_type &= ~PPC_INDIRECT_TYPE_NO_PCIE_LINK;
+
+ return indirect_read_config(bus, devfn, offset, len, val);
+}
+
#if defined(CONFIG_FSL_SOC_BOOKE) || defined(CONFIG_PPC_86xx)
+static struct pci_ops fsl_indirect_pcie_ops =
+{
+ .read = fsl_indirect_read_config,
+ .write = indirect_write_config,
+};
+
#define MAX_PHYS_ADDR_BITS 40
static u64 pci64_dma_offset = 1ull << MAX_PHYS_ADDR_BITS;
@@ -79,7 +125,7 @@ static int fsl_pci_dma_set_mask(struct device *dev, u64 dma_mask)
* address width of the SoC such that we can address any internal
* SoC address from across PCI if needed
*/
- if ((dev->bus == &pci_bus_type) &&
+ if ((dev_is_pci(dev)) &&
dma_mask >= DMA_BIT_MASK(MAX_PHYS_ADDR_BITS)) {
set_dma_ops(dev, &dma_direct_ops);
set_dma_offset(dev, pci64_dma_offset);
@@ -106,7 +152,7 @@ static int setup_one_atmu(struct ccsr_pci __iomem *pci,
flags |= 0x10000000; /* enable relaxed ordering */
for (i = 0; size > 0; i++) {
- unsigned int bits = min(__ilog2(size),
+ unsigned int bits = min(ilog2(size),
__ffs(pci_addr | phys_addr));
if (index + i >= 5)
@@ -126,13 +172,12 @@ static int setup_one_atmu(struct ccsr_pci __iomem *pci,
}
/* atmu setup for fsl pci/pcie controller */
-static void setup_pci_atmu(struct pci_controller *hose,
- struct resource *rsrc)
+static void setup_pci_atmu(struct pci_controller *hose)
{
- struct ccsr_pci __iomem *pci;
+ struct ccsr_pci __iomem *pci = hose->private_data;
int i, j, n, mem_log, win_idx = 3, start_idx = 1, end_idx = 4;
u64 mem, sz, paddr_hi = 0;
- u64 paddr_lo = ULLONG_MAX;
+ u64 offset = 0, paddr_lo = ULLONG_MAX;
u32 pcicsrbar = 0, pcicsrbar_sz;
u32 piwar = PIWAR_EN | PIWAR_PF | PIWAR_TGI_LOCAL |
PIWAR_READ_SNOOP | PIWAR_WRITE_SNOOP;
@@ -140,15 +185,6 @@ static void setup_pci_atmu(struct pci_controller *hose,
const u64 *reg;
int len;
- pr_debug("PCI memory map start 0x%016llx, size 0x%016llx\n",
- (u64)rsrc->start, (u64)resource_size(rsrc));
-
- pci = ioremap(rsrc->start, resource_size(rsrc));
- if (!pci) {
- dev_err(hose->parent, "Unable to map ATMU registers\n");
- return;
- }
-
if (early_find_capability(hose, 0, 0, PCI_CAP_ID_EXP)) {
if (in_be32(&pci->block_rev1) >= PCIE_IP_REV_2_2) {
win_idx = 2;
@@ -171,8 +207,9 @@ static void setup_pci_atmu(struct pci_controller *hose,
paddr_lo = min(paddr_lo, (u64)hose->mem_resources[i].start);
paddr_hi = max(paddr_hi, (u64)hose->mem_resources[i].end);
- n = setup_one_atmu(pci, j, &hose->mem_resources[i],
- hose->pci_mem_offset);
+ /* We assume all memory resources have the same offset */
+ offset = hose->mem_offset[i];
+ n = setup_one_atmu(pci, j, &hose->mem_resources[i], offset);
if (n < 0 || j >= 5) {
pr_err("Ran out of outbound PCI ATMUs for resource %d!\n", i);
@@ -196,23 +233,23 @@ static void setup_pci_atmu(struct pci_controller *hose,
out_be32(&pci->pow[j].powbar, (hose->io_base_phys >> 12));
/* Enable, IO R/W */
out_be32(&pci->pow[j].powar, 0x80088000
- | (__ilog2(hose->io_resource.end
+ | (ilog2(hose->io_resource.end
- hose->io_resource.start + 1) - 1));
}
}
/* convert to pci address space */
- paddr_hi -= hose->pci_mem_offset;
- paddr_lo -= hose->pci_mem_offset;
+ paddr_hi -= offset;
+ paddr_lo -= offset;
if (paddr_hi == paddr_lo) {
pr_err("%s: No outbound window space\n", name);
- goto out;
+ return;
}
if (paddr_lo == 0) {
pr_err("%s: No space for inbound window\n", name);
- goto out;
+ return;
}
/* setup PCSRBAR/PEXCSRBAR */
@@ -261,16 +298,16 @@ static void setup_pci_atmu(struct pci_controller *hose,
}
sz = min(mem, paddr_lo);
- mem_log = __ilog2_u64(sz);
+ mem_log = ilog2(sz);
/* PCIe can overmap inbound & outbound since RX & TX are separated */
if (early_find_capability(hose, 0, 0, PCI_CAP_ID_EXP)) {
/* Size window to exact size if power-of-two or one size up */
if ((1ull << mem_log) != mem) {
+ mem_log++;
if ((1ull << mem_log) > mem)
pr_info("%s: Setting PCI inbound window "
"greater than memory size\n", name);
- mem_log++;
}
piwar |= ((mem_log - 1) & PIWAR_SZ_MASK);
@@ -290,7 +327,7 @@ static void setup_pci_atmu(struct pci_controller *hose,
* SWIOTLB and access the full range of memory
*/
if (sz != mem) {
- mem_log = __ilog2_u64(mem);
+ mem_log = ilog2(mem);
/* Size window up if we dont fit in exact power-of-2 */
if ((1ull << mem_log) != mem)
@@ -327,7 +364,7 @@ static void setup_pci_atmu(struct pci_controller *hose,
sz -= 1ull << mem_log;
if (sz) {
- mem_log = __ilog2_u64(sz);
+ mem_log = ilog2(sz);
piwar |= (mem_log - 1);
out_be32(&pci->piw[win_idx].pitar, paddr >> 12);
@@ -343,7 +380,9 @@ static void setup_pci_atmu(struct pci_controller *hose,
}
if (hose->dma_window_size < mem) {
-#ifndef CONFIG_SWIOTLB
+#ifdef CONFIG_SWIOTLB
+ ppc_swiotlb_enable = 1;
+#else
pr_err("%s: ERROR: Memory size exceeds PCI ATMU ability to "
"map - enable CONFIG_SWIOTLB to avoid dma errors.\n",
name);
@@ -358,9 +397,6 @@ static void setup_pci_atmu(struct pci_controller *hose,
pr_info("%s: DMA window size is 0x%llx\n", name,
(u64)hose->dma_window_size);
}
-
-out:
- iounmap(pci);
}
static void __init setup_pci_cmd(struct pci_controller *hose)
@@ -421,13 +457,17 @@ void fsl_pcibios_fixup_bus(struct pci_bus *bus)
}
}
-int __init fsl_add_bridge(struct device_node *dev, int is_primary)
+int fsl_add_bridge(struct platform_device *pdev, int is_primary)
{
int len;
struct pci_controller *hose;
struct resource rsrc;
const int *bus_range;
u8 hdr_type, progif;
+ struct device_node *dev;
+ struct ccsr_pci __iomem *pci;
+
+ dev = pdev->dev.of_node;
if (!of_device_is_available(dev)) {
pr_warning("%s: disabled\n", dev->full_name);
@@ -453,13 +493,27 @@ int __init fsl_add_bridge(struct device_node *dev, int is_primary)
if (!hose)
return -ENOMEM;
+ /* set platform device as the parent */
+ hose->parent = &pdev->dev;
hose->first_busno = bus_range ? bus_range[0] : 0x0;
hose->last_busno = bus_range ? bus_range[1] : 0xff;
+ pr_debug("PCI memory map start 0x%016llx, size 0x%016llx\n",
+ (u64)rsrc.start, (u64)resource_size(&rsrc));
+
+ pci = hose->private_data = ioremap(rsrc.start, resource_size(&rsrc));
+ if (!hose->private_data)
+ goto no_bridge;
+
setup_indirect_pci(hose, rsrc.start, rsrc.start + 0x4,
- PPC_INDIRECT_TYPE_BIG_ENDIAN);
+ PPC_INDIRECT_TYPE_BIG_ENDIAN);
+
+ if (in_be32(&pci->block_rev1) < PCIE_IP_REV_3_0)
+ hose->indirect_type |= PPC_INDIRECT_TYPE_FSL_CFG_REG_LINK;
if (early_find_capability(hose, 0, 0, PCI_CAP_ID_EXP)) {
+ /* use fsl_indirect_read_config for PCIe */
+ hose->ops = &fsl_indirect_pcie_ops;
/* For PCIE read HEADER_TYPE to identify controler mode */
early_read_config_byte(hose, 0, 0, PCI_HEADER_TYPE, &hdr_type);
if ((hdr_type & 0x7f) != PCI_HEADER_TYPE_BRIDGE)
@@ -495,11 +549,12 @@ int __init fsl_add_bridge(struct device_node *dev, int is_primary)
pci_process_bridge_OF_ranges(hose, dev, is_primary);
/* Setup PEX window registers */
- setup_pci_atmu(hose, &rsrc);
+ setup_pci_atmu(hose);
return 0;
no_bridge:
+ iounmap(hose->private_data);
/* unmap cfg_data & cfg_addr separately if not on same page */
if (((unsigned long)hose->cfg_data & PAGE_MASK) !=
((unsigned long)hose->cfg_addr & PAGE_MASK))
@@ -510,7 +565,8 @@ no_bridge:
}
#endif /* CONFIG_FSL_SOC_BOOKE || CONFIG_PPC_86xx */
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_FREESCALE, PCI_ANY_ID, quirk_fsl_pcie_header);
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_FREESCALE, PCI_ANY_ID,
+ quirk_fsl_pcie_early);
#if defined(CONFIG_PPC_83xx) || defined(CONFIG_PPC_MPC512x)
struct mpc83xx_pcie_priv {
@@ -676,6 +732,7 @@ static int __init mpc83xx_pcie_setup(struct pci_controller *hose,
WARN_ON(hose->dn->data);
hose->dn->data = pcie;
hose->ops = &mpc83xx_pcie_ops;
+ hose->indirect_type |= PPC_INDIRECT_TYPE_FSL_CFG_REG_LINK;
out_le32(pcie->cfg_type0 + PEX_OUTWIN0_TAH, 0);
out_le32(pcie->cfg_type0 + PEX_OUTWIN0_TAL, 0);
@@ -814,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
@@ -821,19 +886,180 @@ u64 fsl_pci_immrbar_base(struct pci_controller *hose)
return 0;
}
+#ifdef CONFIG_E500
+static int mcheck_handle_load(struct pt_regs *regs, u32 inst)
+{
+ unsigned int rd, ra, rb, d;
+
+ rd = get_rt(inst);
+ ra = get_ra(inst);
+ rb = get_rb(inst);
+ d = get_d(inst);
+
+ switch (get_op(inst)) {
+ case 31:
+ switch (get_xop(inst)) {
+ case OP_31_XOP_LWZX:
+ case OP_31_XOP_LWBRX:
+ regs->gpr[rd] = 0xffffffff;
+ break;
+
+ case OP_31_XOP_LWZUX:
+ regs->gpr[rd] = 0xffffffff;
+ regs->gpr[ra] += regs->gpr[rb];
+ break;
+
+ case OP_31_XOP_LBZX:
+ regs->gpr[rd] = 0xff;
+ break;
+
+ case OP_31_XOP_LBZUX:
+ regs->gpr[rd] = 0xff;
+ regs->gpr[ra] += regs->gpr[rb];
+ break;
+
+ case OP_31_XOP_LHZX:
+ case OP_31_XOP_LHBRX:
+ regs->gpr[rd] = 0xffff;
+ break;
+
+ case OP_31_XOP_LHZUX:
+ regs->gpr[rd] = 0xffff;
+ regs->gpr[ra] += regs->gpr[rb];
+ break;
+
+ case OP_31_XOP_LHAX:
+ regs->gpr[rd] = ~0UL;
+ break;
+
+ case OP_31_XOP_LHAUX:
+ regs->gpr[rd] = ~0UL;
+ regs->gpr[ra] += regs->gpr[rb];
+ break;
+
+ default:
+ return 0;
+ }
+ break;
+
+ case OP_LWZ:
+ regs->gpr[rd] = 0xffffffff;
+ break;
+
+ case OP_LWZU:
+ regs->gpr[rd] = 0xffffffff;
+ regs->gpr[ra] += (s16)d;
+ break;
+
+ case OP_LBZ:
+ regs->gpr[rd] = 0xff;
+ break;
+
+ case OP_LBZU:
+ regs->gpr[rd] = 0xff;
+ regs->gpr[ra] += (s16)d;
+ break;
+
+ case OP_LHZ:
+ regs->gpr[rd] = 0xffff;
+ break;
+
+ case OP_LHZU:
+ regs->gpr[rd] = 0xffff;
+ regs->gpr[ra] += (s16)d;
+ break;
+
+ case OP_LHA:
+ regs->gpr[rd] = ~0UL;
+ break;
+
+ case OP_LHAU:
+ regs->gpr[rd] = ~0UL;
+ regs->gpr[ra] += (s16)d;
+ break;
+
+ default:
+ return 0;
+ }
+
+ return 1;
+}
+
+static int is_in_pci_mem_space(phys_addr_t addr)
+{
+ struct pci_controller *hose;
+ struct resource *res;
+ int i;
+
+ list_for_each_entry(hose, &hose_list, list_node) {
+ if (!(hose->indirect_type & PPC_INDIRECT_TYPE_EXT_REG))
+ continue;
+
+ for (i = 0; i < 3; i++) {
+ res = &hose->mem_resources[i];
+ if ((res->flags & IORESOURCE_MEM) &&
+ addr >= res->start && addr <= res->end)
+ return 1;
+ }
+ }
+ return 0;
+}
+
+int fsl_pci_mcheck_exception(struct pt_regs *regs)
+{
+ u32 inst;
+ int ret;
+ phys_addr_t addr = 0;
+
+ /* Let KVM/QEMU deal with the exception */
+ if (regs->msr & MSR_GS)
+ return 0;
+
+#ifdef CONFIG_PHYS_64BIT
+ addr = mfspr(SPRN_MCARU);
+ addr <<= 32;
+#endif
+ addr += mfspr(SPRN_MCAR);
+
+ if (is_in_pci_mem_space(addr)) {
+ if (user_mode(regs)) {
+ pagefault_disable();
+ ret = get_user(regs->nip, &inst);
+ pagefault_enable();
+ } else {
+ ret = probe_kernel_address(regs->nip, inst);
+ }
+
+ if (mcheck_handle_load(regs, inst)) {
+ regs->nip += 4;
+ return 1;
+ }
+ }
+
+ return 0;
+}
+#endif
+
#if defined(CONFIG_FSL_SOC_BOOKE) || defined(CONFIG_PPC_86xx)
static const struct of_device_id pci_ids[] = {
{ .compatible = "fsl,mpc8540-pci", },
{ .compatible = "fsl,mpc8548-pcie", },
{ .compatible = "fsl,mpc8610-pci", },
{ .compatible = "fsl,mpc8641-pcie", },
+ { .compatible = "fsl,qoriq-pcie", },
+ { .compatible = "fsl,qoriq-pcie-v2.1", },
+ { .compatible = "fsl,qoriq-pcie-v2.2", },
+ { .compatible = "fsl,qoriq-pcie-v2.3", },
+ { .compatible = "fsl,qoriq-pcie-v2.4", },
+ { .compatible = "fsl,qoriq-pcie-v3.0", },
+
+ /*
+ * The following entries are for compatibility with older device
+ * trees.
+ */
{ .compatible = "fsl,p1022-pcie", },
- { .compatible = "fsl,p1010-pcie", },
- { .compatible = "fsl,p1023-pcie", },
{ .compatible = "fsl,p4080-pcie", },
- { .compatible = "fsl,qoriq-pcie-v2.4", },
- { .compatible = "fsl,qoriq-pcie-v2.3", },
- { .compatible = "fsl,qoriq-pcie-v2.2", },
+
{},
};
@@ -871,73 +1097,170 @@ 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;
-#ifdef CONFIG_SWIOTLB
- struct pci_controller *hose;
-#endif
+ 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(node, fsl_pci_primary == node);
+ dr = in_be32(&pci->pex_pme_mes_dr);
+ if (!dr)
+ return IRQ_NONE;
-#ifdef CONFIG_SWIOTLB
- if (ret == 0) {
- hose = pci_find_hose_for_OF_device(pdev->dev.of_node);
+ out_be32(&pci->pex_pme_mes_dr, dr);
- /*
- * if we couldn't map all of DRAM via the dma windows
- * we need SWIOTLB to handle buffers located outside of
- * dma capable memory region
- */
- if (memblock_end_of_DRAM() - 1 > hose->dma_window_base_cur +
- hose->dma_window_size)
- ppc_swiotlb_enable = 1;
+ return IRQ_HANDLED;
+}
+
+static int fsl_pci_pme_probe(struct pci_controller *hose)
+{
+ struct ccsr_pci __iomem *pci;
+ struct pci_dev *dev;
+ int pme_irq;
+ int res;
+ u16 pms;
+
+ /* 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;
}
-#endif
- mpc85xx_pci_err_probe(pdev);
+ 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);
+
+ return -ENODEV;
+ }
+
+ pci = hose->private_data;
+
+ /* Enable PTOD, ENL23D & EXL23D */
+ clrbits32(&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;
}
-#ifdef CONFIG_PM
-static int fsl_pci_resume(struct device *dev)
+static void send_pme_turnoff_message(struct pci_controller *hose)
{
- struct pci_controller *hose;
- struct resource pci_rsrc;
-
- hose = pci_find_hose_for_OF_device(dev->of_node);
- if (!hose)
- return -ENODEV;
+ struct ccsr_pci __iomem *pci = hose->private_data;
+ u32 dr;
+ int i;
+
+ /* Send PME_Turn_Off Message Request */
+ setbits32(&pci->pex_pmcr, PEX_PMCR_PTOMR);
+
+ /* 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;
+ }
- if (of_address_to_resource(dev->of_node, 0, &pci_rsrc)) {
- dev_err(dev, "Get pci register base failed.");
- return -ENODEV;
+ udelay(1000);
}
+}
- setup_pci_atmu(hose, &pci_rsrc);
+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;
+
+ list_for_each_entry_safe(hose, tmp, &hose_list, list_node)
+ fsl_pci_syscore_do_suspend(hose);
return 0;
}
-static const struct dev_pm_ops pci_pm_ops = {
- .resume = fsl_pci_resume,
-};
+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;
+ }
-#define PCI_PM_OPS (&pci_pm_ops)
+ udelay(1000);
+ }
-#else
+ setup_pci_atmu(hose);
+}
-#define PCI_PM_OPS NULL
+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,
@@ -945,6 +1268,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 d078537adec..c1cec771d5e 100644
--- a/arch/powerpc/sysdev/fsl_pci.h
+++ b/arch/powerpc/sysdev/fsl_pci.h
@@ -14,9 +14,17 @@
#ifndef __POWERPC_FSL_PCI_H
#define __POWERPC_FSL_PCI_H
+struct platform_device;
+
+
+/* FSL PCI controller BRR1 register */
+#define PCI_FSL_BRR1 0xbf8
+#define PCI_FSL_BRR1_VER 0xffff
+
#define PCIE_LTSSM 0x0404 /* PCIE Link Training and Status */
#define PCIE_LTSSM_L0 0x16 /* L0 state */
#define PCIE_IP_REV_2_2 0x02080202 /* PCIE IP block version Rev2.2 */
+#define PCIE_IP_REV_3_0 0x02080300 /* PCIE IP block version Rev3.0 */
#define PIWAR_EN 0x80000000 /* Enable */
#define PIWAR_PF 0x20000000 /* prefetch */
#define PIWAR_TGI_LOCAL 0x00f00000 /* target - local memory */
@@ -24,6 +32,13 @@
#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 */
@@ -89,10 +104,21 @@ struct ccsr_pci {
__be32 pex_err_cap_r1; /* 0x.e2c - PCIE error capture register 0 */
__be32 pex_err_cap_r2; /* 0x.e30 - PCIE error capture register 0 */
__be32 pex_err_cap_r3; /* 0x.e34 - PCIE error capture register 0 */
+ u8 res_e38[200];
+ __be32 pdb_stat; /* 0x.f00 - PCIE Debug Status */
+ u8 res_f04[16];
+ __be32 pex_csr0; /* 0x.f14 - PEX Control/Status register 0*/
+#define PEX_CSR0_LTSSM_MASK 0xFC
+#define PEX_CSR0_LTSSM_SHIFT 2
+#define PEX_CSR0_LTSSM_L0 0x11
+ __be32 pex_csr1; /* 0x.f18 - PEX Control/Status register 1*/
+ u8 res_f1c[228];
+
};
-extern int fsl_add_bridge(struct device_node *dev, int is_primary);
+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);
@@ -113,5 +139,11 @@ static inline int mpc85xx_pci_err_probe(struct platform_device *op)
}
#endif
+#ifdef CONFIG_FSL_PCI
+extern int fsl_pci_mcheck_exception(struct pt_regs *);
+#else
+static inline int fsl_pci_mcheck_exception(struct pt_regs *regs) {return 0; }
+#endif
+
#endif /* __POWERPC_FSL_PCI_H */
#endif /* __KERNEL__ */
diff --git a/arch/powerpc/sysdev/fsl_pmc.c b/arch/powerpc/sysdev/fsl_pmc.c
index 592a0f8d527..8cf4aa0e3a2 100644
--- a/arch/powerpc/sysdev/fsl_pmc.c
+++ b/arch/powerpc/sysdev/fsl_pmc.c
@@ -18,6 +18,7 @@
#include <linux/suspend.h>
#include <linux/delay.h>
#include <linux/device.h>
+#include <linux/of_address.h>
#include <linux/of_platform.h>
struct pmc_regs {
diff --git a/arch/powerpc/sysdev/fsl_rio.c b/arch/powerpc/sysdev/fsl_rio.c
index e2fb3171f41..c04b718307c 100644
--- a/arch/powerpc/sysdev/fsl_rio.c
+++ b/arch/powerpc/sysdev/fsl_rio.c
@@ -28,6 +28,8 @@
#include <linux/dma-mapping.h>
#include <linux/interrupt.h>
#include <linux/device.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
#include <linux/of_platform.h>
#include <linux/delay.h>
#include <linux/slab.h>
@@ -389,8 +391,10 @@ int fsl_rio_setup(struct platform_device *dev)
ops->get_inb_message = fsl_get_inb_message;
rmu_node = of_parse_phandle(dev->dev.of_node, "fsl,srio-rmu-handle", 0);
- if (!rmu_node)
+ if (!rmu_node) {
+ dev_err(&dev->dev, "No valid fsl,srio-rmu-handle property\n");
goto err_rmu;
+ }
rc = of_address_to_resource(rmu_node, 0, &rmu_regs);
if (rc) {
dev_err(&dev->dev, "Can't get %s property 'reg'\n",
@@ -411,6 +415,7 @@ int fsl_rio_setup(struct platform_device *dev)
/*set up doobell node*/
np = of_find_compatible_node(NULL, NULL, "fsl,srio-dbell-unit");
if (!np) {
+ dev_err(&dev->dev, "No fsl,srio-dbell-unit node\n");
rc = -ENODEV;
goto err_dbell;
}
@@ -439,6 +444,7 @@ int fsl_rio_setup(struct platform_device *dev)
/*set up port write node*/
np = of_find_compatible_node(NULL, NULL, "fsl,srio-port-write-unit");
if (!np) {
+ dev_err(&dev->dev, "No fsl,srio-port-write-unit node\n");
rc = -ENODEV;
goto err_pw;
}
@@ -529,6 +535,7 @@ int fsl_rio_setup(struct platform_device *dev)
sprintf(port->name, "RIO mport %d", i);
priv->dev = &dev->dev;
+ port->dev.parent = &dev->dev;
port->ops = ops;
port->priv = priv;
port->phys_efptr = 0x100;
@@ -630,14 +637,18 @@ int fsl_rio_setup(struct platform_device *dev)
return 0;
err:
kfree(pw);
+ pw = NULL;
err_pw:
kfree(dbell);
+ dbell = NULL;
err_dbell:
iounmap(rmu_regs_win);
+ rmu_regs_win = NULL;
err_rmu:
kfree(ops);
err_ops:
iounmap(rio_regs_win);
+ rio_regs_win = NULL;
err_rio_regs:
return rc;
}
diff --git a/arch/powerpc/sysdev/fsl_rmu.c b/arch/powerpc/sysdev/fsl_rmu.c
index 14bd5221f28..b48197ae44d 100644
--- a/arch/powerpc/sysdev/fsl_rmu.c
+++ b/arch/powerpc/sysdev/fsl_rmu.c
@@ -27,6 +27,7 @@
#include <linux/types.h>
#include <linux/dma-mapping.h>
#include <linux/interrupt.h>
+#include <linux/of_irq.h>
#include <linux/of_platform.h>
#include <linux/slab.h>
@@ -880,9 +881,9 @@ fsl_open_inb_mbox(struct rio_mport *mport, void *dev_id, int mbox, int entries)
rc = request_irq(IRQ_RIO_RX(mport), fsl_rio_rx_handler, 0,
"msg_rx", (void *)mport);
if (rc < 0) {
- dma_free_coherent(priv->dev, RIO_MSG_BUFFER_SIZE,
- rmu->msg_tx_ring.virt_buffer[i],
- rmu->msg_tx_ring.phys_buffer[i]);
+ dma_free_coherent(priv->dev,
+ rmu->msg_rx_ring.size * RIO_MAX_MSG_SIZE,
+ rmu->msg_rx_ring.virt, rmu->msg_rx_ring.phys);
goto out;
}
diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c
index 97118dc3d28..ffd1169ebaa 100644
--- a/arch/powerpc/sysdev/fsl_soc.c
+++ b/arch/powerpc/sysdev/fsl_soc.c
@@ -25,7 +25,6 @@
#include <linux/of.h>
#include <linux/of_platform.h>
#include <linux/phy.h>
-#include <linux/phy_fixed.h>
#include <linux/spi/spi.h>
#include <linux/fsl_devices.h>
#include <linux/fs_enet_pd.h>
@@ -58,10 +57,10 @@ phys_addr_t get_immrbase(void)
if (soc) {
int size;
u32 naddr;
- const u32 *prop = of_get_property(soc, "#address-cells", &size);
+ const __be32 *prop = of_get_property(soc, "#address-cells", &size);
if (prop && size == 4)
- naddr = *prop;
+ naddr = be32_to_cpup(prop);
else
naddr = 2;
@@ -178,37 +177,6 @@ u32 get_baudrate(void)
EXPORT_SYMBOL(get_baudrate);
#endif /* CONFIG_CPM2 */
-#ifdef CONFIG_FIXED_PHY
-static int __init of_add_fixed_phys(void)
-{
- int ret;
- struct device_node *np;
- u32 *fixed_link;
- struct fixed_phy_status status = {};
-
- for_each_node_by_name(np, "ethernet") {
- fixed_link = (u32 *)of_get_property(np, "fixed-link", NULL);
- if (!fixed_link)
- continue;
-
- status.link = 1;
- status.duplex = fixed_link[1];
- status.speed = fixed_link[2];
- status.pause = fixed_link[3];
- status.asym_pause = fixed_link[4];
-
- ret = fixed_phy_add(PHY_POLL, fixed_link[0], &status);
- if (ret) {
- of_node_put(np);
- return ret;
- }
- }
-
- return 0;
-}
-arch_initcall(of_add_fixed_phys);
-#endif /* CONFIG_FIXED_PHY */
-
#if defined(CONFIG_FSL_SOC_BOOKE) || defined(CONFIG_PPC_86xx)
static __be32 __iomem *rstcr;
diff --git a/arch/powerpc/sysdev/fsl_soc.h b/arch/powerpc/sysdev/fsl_soc.h
index c6d00736f07..4c5a19ef4f0 100644
--- a/arch/powerpc/sysdev/fsl_soc.h
+++ b/arch/powerpc/sysdev/fsl_soc.h
@@ -21,8 +21,6 @@ struct device_node;
extern void fsl_rstcr_restart(char *cmd);
-#if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE)
-
/* The different ports that the DIU can be connected to */
enum fsl_diu_monitor_port {
FSL_DIU_PORT_DVI, /* DVI */
@@ -43,7 +41,6 @@ struct platform_diu_data_ops {
};
extern struct platform_diu_data_ops diu_ops;
-#endif
void fsl_hv_restart(char *cmd);
void fsl_hv_halt(void);
diff --git a/arch/powerpc/sysdev/ge/ge_pic.h b/arch/powerpc/sysdev/ge/ge_pic.h
index 6149916da3f..908dbd9826b 100644
--- a/arch/powerpc/sysdev/ge/ge_pic.h
+++ b/arch/powerpc/sysdev/ge/ge_pic.h
@@ -1,7 +1,6 @@
#ifndef __GEF_PIC_H__
#define __GEF_PIC_H__
-#include <linux/init.h>
void gef_pic_cascade(unsigned int, struct irq_desc *);
unsigned int gef_pic_get_irq(void);
diff --git a/arch/powerpc/sysdev/i8259.c b/arch/powerpc/sysdev/i8259.c
index 997df6a7ab5..45598da0b32 100644
--- a/arch/powerpc/sysdev/i8259.c
+++ b/arch/powerpc/sysdev/i8259.c
@@ -8,7 +8,6 @@
*/
#undef DEBUG
-#include <linux/init.h>
#include <linux/ioport.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
diff --git a/arch/powerpc/sysdev/indirect_pci.c b/arch/powerpc/sysdev/indirect_pci.c
index 82fdad885d2..1f6c570d66d 100644
--- a/arch/powerpc/sysdev/indirect_pci.c
+++ b/arch/powerpc/sysdev/indirect_pci.c
@@ -20,9 +20,8 @@
#include <asm/pci-bridge.h>
#include <asm/machdep.h>
-static int
-indirect_read_config(struct pci_bus *bus, unsigned int devfn, int offset,
- int len, u32 *val)
+int indirect_read_config(struct pci_bus *bus, unsigned int devfn,
+ int offset, int len, u32 *val)
{
struct pci_controller *hose = pci_bus_to_host(bus);
volatile void __iomem *cfg_data;
@@ -78,9 +77,8 @@ indirect_read_config(struct pci_bus *bus, unsigned int devfn, int offset,
return PCIBIOS_SUCCESSFUL;
}
-static int
-indirect_write_config(struct pci_bus *bus, unsigned int devfn, int offset,
- int len, u32 val)
+int indirect_write_config(struct pci_bus *bus, unsigned int devfn,
+ int offset, int len, u32 val)
{
struct pci_controller *hose = pci_bus_to_host(bus);
volatile void __iomem *cfg_data;
@@ -154,10 +152,8 @@ static struct pci_ops indirect_pci_ops =
.write = indirect_write_config,
};
-void __init
-setup_indirect_pci(struct pci_controller* hose,
- resource_size_t cfg_addr,
- resource_size_t cfg_data, u32 flags)
+void setup_indirect_pci(struct pci_controller *hose, resource_size_t cfg_addr,
+ resource_size_t cfg_data, u32 flags)
{
resource_size_t base = cfg_addr & PAGE_MASK;
void __iomem *mbase;
diff --git a/arch/powerpc/sysdev/mpc5xxx_clocks.c b/arch/powerpc/sysdev/mpc5xxx_clocks.c
index 96f815a55df..5492dc5f56f 100644
--- a/arch/powerpc/sysdev/mpc5xxx_clocks.c
+++ b/arch/powerpc/sysdev/mpc5xxx_clocks.c
@@ -9,9 +9,9 @@
#include <linux/kernel.h>
#include <linux/of_platform.h>
#include <linux/export.h>
+#include <asm/mpc5xxx.h>
-unsigned int
-mpc5xxx_get_bus_frequency(struct device_node *node)
+unsigned long mpc5xxx_get_bus_frequency(struct device_node *node)
{
struct device_node *np;
const unsigned int *p_bus_freq = NULL;
diff --git a/arch/powerpc/sysdev/mpc8xx_pic.c b/arch/powerpc/sysdev/mpc8xx_pic.c
index b724622c3a0..c4828c0be5b 100644
--- a/arch/powerpc/sysdev/mpc8xx_pic.c
+++ b/arch/powerpc/sysdev/mpc8xx_pic.c
@@ -1,6 +1,5 @@
#include <linux/kernel.h>
#include <linux/stddef.h>
-#include <linux/init.h>
#include <linux/sched.h>
#include <linux/signal.h>
#include <linux/irq.h>
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
index 3b2efd41abf..be33c9768ea 100644
--- a/arch/powerpc/sysdev/mpic.c
+++ b/arch/powerpc/sysdev/mpic.c
@@ -48,6 +48,12 @@
#define DBG(fmt...)
#endif
+struct bus_type mpic_subsys = {
+ .name = "mpic",
+ .dev_name = "mpic",
+};
+EXPORT_SYMBOL_GPL(mpic_subsys);
+
static struct mpic *mpics;
static struct mpic *mpic_primary;
static DEFINE_RAW_SPINLOCK(mpic_lock);
@@ -529,7 +535,7 @@ static void __init mpic_scan_ht_pic(struct mpic *mpic, u8 __iomem *devbase,
mpic->fixups[irq].data = readl(base + 4) | 0x80000000;
}
}
-
+
static void __init mpic_scan_ht_pics(struct mpic *mpic)
{
@@ -836,7 +842,7 @@ int mpic_set_affinity(struct irq_data *d, const struct cpumask *cpumask,
mpic_physmask(mask));
}
- return 0;
+ return IRQ_SET_MASK_OK;
}
static unsigned int mpic_type_to_vecpri(struct mpic *mpic, unsigned int type)
@@ -880,25 +886,25 @@ int mpic_set_irq_type(struct irq_data *d, unsigned int flow_type)
/* Default: read HW settings */
if (flow_type == IRQ_TYPE_DEFAULT) {
- switch(vold & (MPIC_INFO(VECPRI_POLARITY_MASK) |
- MPIC_INFO(VECPRI_SENSE_MASK))) {
- case MPIC_INFO(VECPRI_SENSE_EDGE) |
- MPIC_INFO(VECPRI_POLARITY_POSITIVE):
- flow_type = IRQ_TYPE_EDGE_RISING;
- break;
- case MPIC_INFO(VECPRI_SENSE_EDGE) |
- MPIC_INFO(VECPRI_POLARITY_NEGATIVE):
- flow_type = IRQ_TYPE_EDGE_FALLING;
- break;
- case MPIC_INFO(VECPRI_SENSE_LEVEL) |
- MPIC_INFO(VECPRI_POLARITY_POSITIVE):
- flow_type = IRQ_TYPE_LEVEL_HIGH;
- break;
- case MPIC_INFO(VECPRI_SENSE_LEVEL) |
- MPIC_INFO(VECPRI_POLARITY_NEGATIVE):
- flow_type = IRQ_TYPE_LEVEL_LOW;
- break;
- }
+ int vold_ps;
+
+ vold_ps = vold & (MPIC_INFO(VECPRI_POLARITY_MASK) |
+ MPIC_INFO(VECPRI_SENSE_MASK));
+
+ if (vold_ps == (MPIC_INFO(VECPRI_SENSE_EDGE) |
+ MPIC_INFO(VECPRI_POLARITY_POSITIVE)))
+ flow_type = IRQ_TYPE_EDGE_RISING;
+ else if (vold_ps == (MPIC_INFO(VECPRI_SENSE_EDGE) |
+ MPIC_INFO(VECPRI_POLARITY_NEGATIVE)))
+ flow_type = IRQ_TYPE_EDGE_FALLING;
+ else if (vold_ps == (MPIC_INFO(VECPRI_SENSE_LEVEL) |
+ MPIC_INFO(VECPRI_POLARITY_POSITIVE)))
+ flow_type = IRQ_TYPE_LEVEL_HIGH;
+ else if (vold_ps == (MPIC_INFO(VECPRI_SENSE_LEVEL) |
+ MPIC_INFO(VECPRI_POLARITY_NEGATIVE)))
+ flow_type = IRQ_TYPE_LEVEL_LOW;
+ else
+ WARN_ONCE(1, "mpic: unknown IRQ type %d\n", vold);
}
/* Apply to irq desc */
@@ -920,6 +926,22 @@ int mpic_set_irq_type(struct irq_data *d, unsigned int flow_type)
return IRQ_SET_MASK_OK_NOCOPY;
}
+static int mpic_irq_set_wake(struct irq_data *d, unsigned int on)
+{
+ struct irq_desc *desc = container_of(d, struct irq_desc, irq_data);
+ struct mpic *mpic = mpic_from_irq_data(d);
+
+ if (!(mpic->flags & MPIC_FSL))
+ return -ENXIO;
+
+ if (on)
+ desc->action->flags |= IRQF_NO_SUSPEND;
+ else
+ desc->action->flags &= ~IRQF_NO_SUSPEND;
+
+ return 0;
+}
+
void mpic_set_vector(unsigned int virq, unsigned int vector)
{
struct mpic *mpic = mpic_from_irq(virq);
@@ -957,6 +979,7 @@ static struct irq_chip mpic_irq_chip = {
.irq_unmask = mpic_unmask_irq,
.irq_eoi = mpic_end_irq,
.irq_set_type = mpic_set_irq_type,
+ .irq_set_wake = mpic_irq_set_wake,
};
#ifdef CONFIG_SMP
@@ -971,6 +994,7 @@ static struct irq_chip mpic_tm_chip = {
.irq_mask = mpic_mask_tm,
.irq_unmask = mpic_unmask_tm,
.irq_eoi = mpic_end_irq,
+ .irq_set_wake = mpic_irq_set_wake,
};
#ifdef CONFIG_MPIC_U3_HT_IRQS
@@ -1001,8 +1025,12 @@ static int mpic_host_map(struct irq_domain *h, unsigned int virq,
if (hw == mpic->spurious_vec)
return -EINVAL;
- if (mpic->protected && test_bit(hw, mpic->protected))
- return -EINVAL;
+ if (mpic->protected && test_bit(hw, mpic->protected)) {
+ pr_warning("mpic: Mapping of source 0x%x failed, "
+ "source protected by firmware !\n",\
+ (unsigned int)hw);
+ return -EPERM;
+ }
#ifdef CONFIG_SMP
else if (hw >= mpic->ipi_vecs[0]) {
@@ -1029,8 +1057,12 @@ static int mpic_host_map(struct irq_domain *h, unsigned int virq,
if (mpic_map_error_int(mpic, virq, hw))
return 0;
- if (hw >= mpic->num_sources)
+ if (hw >= mpic->num_sources) {
+ pr_warning("mpic: Mapping of source 0x%x failed, "
+ "source out of range !\n",\
+ (unsigned int)hw);
return -EINVAL;
+ }
mpic_msi_reserve_hwirq(mpic, hw);
@@ -1056,8 +1088,14 @@ static int mpic_host_map(struct irq_domain *h, unsigned int virq,
* is done here.
*/
if (!mpic_is_ipi(mpic, hw) && (mpic->flags & MPIC_NO_RESET)) {
+ int cpu;
+
+ preempt_disable();
+ cpu = mpic_processor_id(mpic);
+ preempt_enable();
+
mpic_set_vector(virq, hw);
- mpic_set_destination(virq, mpic_processor_id(mpic));
+ mpic_set_destination(virq, cpu);
mpic_irq_set_priority(virq, 8);
}
@@ -1165,10 +1203,33 @@ static struct irq_domain_ops mpic_host_ops = {
.xlate = mpic_host_xlate,
};
+static u32 fsl_mpic_get_version(struct mpic *mpic)
+{
+ u32 brr1;
+
+ if (!(mpic->flags & MPIC_FSL))
+ return 0;
+
+ brr1 = _mpic_read(mpic->reg_type, &mpic->thiscpuregs,
+ MPIC_FSL_BRR1);
+
+ return brr1 & MPIC_FSL_BRR1_VER;
+}
+
/*
* Exported functions
*/
+u32 fsl_mpic_primary_get_version(void)
+{
+ struct mpic *mpic = mpic_primary;
+
+ if (mpic)
+ return fsl_mpic_get_version(mpic);
+
+ return 0;
+}
+
struct mpic * __init mpic_alloc(struct device_node *node,
phys_addr_t phys_addr,
unsigned int flags,
@@ -1182,6 +1243,7 @@ struct mpic * __init mpic_alloc(struct device_node *node,
const char *vers;
const u32 *psrc;
u32 last_irq;
+ u32 fsl_version = 0;
/* Default MPIC search parameters */
static const struct of_device_id __initconst mpic_device_id[] = {
@@ -1314,7 +1376,6 @@ struct mpic * __init mpic_alloc(struct device_node *node,
mpic_map(mpic, mpic->paddr, &mpic->tmregs, MPIC_INFO(TIMER_BASE), 0x1000);
if (mpic->flags & MPIC_FSL) {
- u32 brr1, version;
int ret;
/*
@@ -1325,9 +1386,7 @@ struct mpic * __init mpic_alloc(struct device_node *node,
mpic_map(mpic, mpic->paddr, &mpic->thiscpuregs,
MPIC_CPU_THISBASE, 0x1000);
- brr1 = _mpic_read(mpic->reg_type, &mpic->thiscpuregs,
- MPIC_FSL_BRR1);
- version = brr1 & MPIC_FSL_BRR1_VER;
+ fsl_version = fsl_mpic_get_version(mpic);
/* Error interrupt mask register (EIMR) is required for
* handling individual device error interrupts. EIMR
@@ -1342,11 +1401,30 @@ struct mpic * __init mpic_alloc(struct device_node *node,
* is the number of vectors which have been consumed by
* ipis and timer interrupts.
*/
- if (version >= 0x401) {
+ if (fsl_version >= 0x401) {
ret = mpic_setup_error_int(mpic, intvec_top - 12);
if (ret)
return NULL;
}
+
+ }
+
+ /*
+ * EPR is only available starting with v4.0. To support
+ * platforms that don't know the MPIC version at compile-time,
+ * such as qemu-e500, turn off coreint if this MPIC doesn't
+ * support it. Note that we never enable it if it wasn't
+ * requested in the first place.
+ *
+ * This is done outside the MPIC_FSL check, so that we
+ * also disable coreint if the MPIC node doesn't have
+ * an "fsl,mpic" compatible at all. This will be the case
+ * with device trees generated by older versions of QEMU.
+ * fsl_version will be zero if MPIC_FSL is not set.
+ */
+ if (fsl_version < 0x400 && (flags & MPIC_ENABLE_COREINT)) {
+ WARN_ON(ppc_md.get_irq != mpic_get_coreint_irq);
+ ppc_md.get_irq = mpic_get_irq;
}
/* Reset */
@@ -1403,7 +1481,7 @@ struct mpic * __init mpic_alloc(struct device_node *node,
* as a default instead of the value read from the HW.
*/
last_irq = (greg_feature & MPIC_GREG_FEATURE_LAST_SRC_MASK)
- >> MPIC_GREG_FEATURE_LAST_SRC_SHIFT;
+ >> MPIC_GREG_FEATURE_LAST_SRC_SHIFT;
if (isu_size)
last_irq = isu_size * MPIC_MAX_ISU - 1;
of_property_read_u32(mpic->node, "last-interrupt-source", &last_irq);
@@ -1498,9 +1576,7 @@ void __init mpic_init(struct mpic *mpic)
mpic_cpu_write(MPIC_INFO(CPU_CURRENT_TASK_PRI), 0xf);
if (mpic->flags & MPIC_FSL) {
- u32 brr1 = _mpic_read(mpic->reg_type, &mpic->thiscpuregs,
- MPIC_FSL_BRR1);
- u32 version = brr1 & MPIC_FSL_BRR1_VER;
+ u32 version = fsl_mpic_get_version(mpic);
/*
* Timer group B is present at the latest in MPIC 3.1 (e.g.
@@ -1512,10 +1588,6 @@ void __init mpic_init(struct mpic *mpic)
num_timers = 8;
}
- /* FSL mpic error interrupt intialization */
- if (mpic->flags & MPIC_FSL_HAS_EIMR)
- mpic_err_int_init(mpic, MPIC_FSL_ERR_INT);
-
/* Initialize timers to our reserved vectors and mask them for now */
for (i = 0; i < num_timers; i++) {
unsigned int offset = mpic_tm_offset(mpic, i);
@@ -1555,7 +1627,7 @@ void __init mpic_init(struct mpic *mpic)
/* start with vector = source number, and masked */
u32 vecpri = MPIC_VECPRI_MASK | i |
(8 << MPIC_VECPRI_PRIORITY_SHIFT);
-
+
/* check if protected */
if (mpic->protected && test_bit(i, mpic->protected))
continue;
@@ -1564,7 +1636,7 @@ void __init mpic_init(struct mpic *mpic)
mpic_irq_write(i, MPIC_INFO(IRQ_DESTINATION), 1 << cpu);
}
}
-
+
/* Init spurious vector */
mpic_write(mpic->gregs, MPIC_INFO(GREG_SPURIOUS), mpic->spurious_vec);
@@ -1599,6 +1671,10 @@ void __init mpic_init(struct mpic *mpic)
irq_set_chained_handler(virq, &mpic_cascade);
}
}
+
+ /* FSL mpic error interrupt intialization */
+ if (mpic->flags & MPIC_FSL_HAS_EIMR)
+ mpic_err_int_init(mpic, MPIC_FSL_ERR_INT);
}
void __init mpic_set_clk_ratio(struct mpic *mpic, u32 clock_ratio)
@@ -1675,7 +1751,7 @@ void mpic_setup_this_cpu(void)
* it differently, then we should make sure we also change the default
* values of irq_desc[].affinity in irq.c.
*/
- if (distribute_irqs) {
+ if (distribute_irqs && !(mpic->flags & MPIC_SINGLE_DEST_CPU)) {
for (i = 0; i < mpic->num_sources ; i++)
mpic_irq_write(i, MPIC_INFO(IRQ_DESTINATION),
mpic_irq_read(i, MPIC_INFO(IRQ_DESTINATION)) | msk);
@@ -1971,6 +2047,8 @@ static struct syscore_ops mpic_syscore_ops = {
static int mpic_init_sys(void)
{
register_syscore_ops(&mpic_syscore_ops);
+ subsys_system_register(&mpic_subsys, NULL);
+
return 0;
}
diff --git a/arch/powerpc/sysdev/mpic_msgr.c b/arch/powerpc/sysdev/mpic_msgr.c
index c75325865a8..2c9b52aa266 100644
--- a/arch/powerpc/sysdev/mpic_msgr.c
+++ b/arch/powerpc/sysdev/mpic_msgr.c
@@ -237,15 +237,13 @@ static int mpic_msgr_probe(struct platform_device *dev)
raw_spin_lock_init(&msgr->lock);
if (receive_mask & (1 << i)) {
- struct resource irq;
-
- if (of_irq_to_resource(np, irq_index, &irq) == NO_IRQ) {
+ msgr->irq = irq_of_parse_and_map(np, irq_index);
+ if (msgr->irq == NO_IRQ) {
dev_err(&dev->dev,
"Missing interrupt specifier");
kfree(msgr);
return -EFAULT;
}
- msgr->irq = irq.start;
irq_index += 1;
} else {
msgr->irq = NO_IRQ;
diff --git a/arch/powerpc/sysdev/mpic_msi.c b/arch/powerpc/sysdev/mpic_msi.c
index bbf342c8831..7dc39f35a4c 100644
--- a/arch/powerpc/sysdev/mpic_msi.c
+++ b/arch/powerpc/sysdev/mpic_msi.c
@@ -35,7 +35,7 @@ static int mpic_msi_reserve_u3_hwirqs(struct mpic *mpic)
const struct irq_domain_ops *ops = mpic->irqhost->ops;
struct device_node *np;
int flags, index, i;
- struct of_irq oirq;
+ struct of_phandle_args oirq;
pr_debug("mpic: found U3, guessing msi allocator setup\n");
@@ -63,9 +63,9 @@ static int mpic_msi_reserve_u3_hwirqs(struct mpic *mpic)
pr_debug("mpic: mapping hwirqs for %s\n", np->full_name);
index = 0;
- while (of_irq_map_one(np, index++, &oirq) == 0) {
- ops->xlate(mpic->irqhost, NULL, oirq.specifier,
- oirq.size, &hwirq, &flags);
+ while (of_irq_parse_one(np, index++, &oirq) == 0) {
+ ops->xlate(mpic->irqhost, NULL, oirq.args,
+ oirq.args_count, &hwirq, &flags);
msi_bitmap_reserve_hwirq(&mpic->msi_bitmap, hwirq);
}
}
diff --git a/arch/powerpc/sysdev/mpic_timer.c b/arch/powerpc/sysdev/mpic_timer.c
new file mode 100644
index 00000000000..9d9b06217f8
--- /dev/null
+++ b/arch/powerpc/sysdev/mpic_timer.c
@@ -0,0 +1,601 @@
+/*
+ * MPIC timer driver
+ *
+ * Copyright 2013 Freescale Semiconductor, Inc.
+ * Author: Dongsheng Wang <Dongsheng.Wang@freescale.com>
+ * Li Yang <leoli@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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/of_irq.h>
+#include <linux/syscore_ops.h>
+#include <sysdev/fsl_soc.h>
+#include <asm/io.h>
+
+#include <asm/mpic_timer.h>
+
+#define FSL_GLOBAL_TIMER 0x1
+
+/* Clock Ratio
+ * Divide by 64 0x00000300
+ * Divide by 32 0x00000200
+ * Divide by 16 0x00000100
+ * Divide by 8 0x00000000 (Hardware default div)
+ */
+#define MPIC_TIMER_TCR_CLKDIV 0x00000300
+
+#define MPIC_TIMER_TCR_ROVR_OFFSET 24
+
+#define TIMER_STOP 0x80000000
+#define GTCCR_TOG 0x80000000
+#define TIMERS_PER_GROUP 4
+#define MAX_TICKS (~0U >> 1)
+#define MAX_TICKS_CASCADE (~0U)
+#define TIMER_OFFSET(num) (1 << (TIMERS_PER_GROUP - 1 - num))
+
+/* tv_usec should be less than ONE_SECOND, otherwise use tv_sec */
+#define ONE_SECOND 1000000
+
+struct timer_regs {
+ u32 gtccr;
+ u32 res0[3];
+ u32 gtbcr;
+ u32 res1[3];
+ u32 gtvpr;
+ u32 res2[3];
+ u32 gtdr;
+ u32 res3[3];
+};
+
+struct cascade_priv {
+ u32 tcr_value; /* TCR register: CASC & ROVR value */
+ unsigned int cascade_map; /* cascade map */
+ unsigned int timer_num; /* cascade control timer */
+};
+
+struct timer_group_priv {
+ struct timer_regs __iomem *regs;
+ struct mpic_timer timer[TIMERS_PER_GROUP];
+ struct list_head node;
+ unsigned int timerfreq;
+ unsigned int idle;
+ unsigned int flags;
+ spinlock_t lock;
+ void __iomem *group_tcr;
+};
+
+static struct cascade_priv cascade_timer[] = {
+ /* cascade timer 0 and 1 */
+ {0x1, 0xc, 0x1},
+ /* cascade timer 1 and 2 */
+ {0x2, 0x6, 0x2},
+ /* cascade timer 2 and 3 */
+ {0x4, 0x3, 0x3}
+};
+
+static LIST_HEAD(timer_group_list);
+
+static void convert_ticks_to_time(struct timer_group_priv *priv,
+ const u64 ticks, struct timeval *time)
+{
+ u64 tmp_sec;
+
+ time->tv_sec = (__kernel_time_t)div_u64(ticks, priv->timerfreq);
+ tmp_sec = (u64)time->tv_sec * (u64)priv->timerfreq;
+
+ time->tv_usec = 0;
+
+ if (tmp_sec <= ticks)
+ time->tv_usec = (__kernel_suseconds_t)
+ div_u64((ticks - tmp_sec) * 1000000, priv->timerfreq);
+
+ return;
+}
+
+/* the time set by the user is converted to "ticks" */
+static int convert_time_to_ticks(struct timer_group_priv *priv,
+ const struct timeval *time, u64 *ticks)
+{
+ u64 max_value; /* prevent u64 overflow */
+ u64 tmp = 0;
+
+ u64 tmp_sec;
+ u64 tmp_ms;
+ u64 tmp_us;
+
+ max_value = div_u64(ULLONG_MAX, priv->timerfreq);
+
+ if (time->tv_sec > max_value ||
+ (time->tv_sec == max_value && time->tv_usec > 0))
+ return -EINVAL;
+
+ tmp_sec = (u64)time->tv_sec * (u64)priv->timerfreq;
+ tmp += tmp_sec;
+
+ tmp_ms = time->tv_usec / 1000;
+ tmp_ms = div_u64((u64)tmp_ms * (u64)priv->timerfreq, 1000);
+ tmp += tmp_ms;
+
+ tmp_us = time->tv_usec % 1000;
+ tmp_us = div_u64((u64)tmp_us * (u64)priv->timerfreq, 1000000);
+ tmp += tmp_us;
+
+ *ticks = tmp;
+
+ return 0;
+}
+
+/* detect whether there is a cascade timer available */
+static struct mpic_timer *detect_idle_cascade_timer(
+ struct timer_group_priv *priv)
+{
+ struct cascade_priv *casc_priv;
+ unsigned int map;
+ unsigned int array_size = ARRAY_SIZE(cascade_timer);
+ unsigned int num;
+ unsigned int i;
+ unsigned long flags;
+
+ casc_priv = cascade_timer;
+ for (i = 0; i < array_size; i++) {
+ spin_lock_irqsave(&priv->lock, flags);
+ map = casc_priv->cascade_map & priv->idle;
+ if (map == casc_priv->cascade_map) {
+ num = casc_priv->timer_num;
+ priv->timer[num].cascade_handle = casc_priv;
+
+ /* set timer busy */
+ priv->idle &= ~casc_priv->cascade_map;
+ spin_unlock_irqrestore(&priv->lock, flags);
+ return &priv->timer[num];
+ }
+ spin_unlock_irqrestore(&priv->lock, flags);
+ casc_priv++;
+ }
+
+ return NULL;
+}
+
+static int set_cascade_timer(struct timer_group_priv *priv, u64 ticks,
+ unsigned int num)
+{
+ struct cascade_priv *casc_priv;
+ u32 tcr;
+ u32 tmp_ticks;
+ u32 rem_ticks;
+
+ /* set group tcr reg for cascade */
+ casc_priv = priv->timer[num].cascade_handle;
+ if (!casc_priv)
+ return -EINVAL;
+
+ tcr = casc_priv->tcr_value |
+ (casc_priv->tcr_value << MPIC_TIMER_TCR_ROVR_OFFSET);
+ setbits32(priv->group_tcr, tcr);
+
+ tmp_ticks = div_u64_rem(ticks, MAX_TICKS_CASCADE, &rem_ticks);
+
+ out_be32(&priv->regs[num].gtccr, 0);
+ out_be32(&priv->regs[num].gtbcr, tmp_ticks | TIMER_STOP);
+
+ out_be32(&priv->regs[num - 1].gtccr, 0);
+ out_be32(&priv->regs[num - 1].gtbcr, rem_ticks);
+
+ return 0;
+}
+
+static struct mpic_timer *get_cascade_timer(struct timer_group_priv *priv,
+ u64 ticks)
+{
+ struct mpic_timer *allocated_timer;
+
+ /* Two cascade timers: Support the maximum time */
+ const u64 max_ticks = (u64)MAX_TICKS * (u64)MAX_TICKS_CASCADE;
+ int ret;
+
+ if (ticks > max_ticks)
+ return NULL;
+
+ /* detect idle timer */
+ allocated_timer = detect_idle_cascade_timer(priv);
+ if (!allocated_timer)
+ return NULL;
+
+ /* set ticks to timer */
+ ret = set_cascade_timer(priv, ticks, allocated_timer->num);
+ if (ret < 0)
+ return NULL;
+
+ return allocated_timer;
+}
+
+static struct mpic_timer *get_timer(const struct timeval *time)
+{
+ struct timer_group_priv *priv;
+ struct mpic_timer *timer;
+
+ u64 ticks;
+ unsigned int num;
+ unsigned int i;
+ unsigned long flags;
+ int ret;
+
+ list_for_each_entry(priv, &timer_group_list, node) {
+ ret = convert_time_to_ticks(priv, time, &ticks);
+ if (ret < 0)
+ return NULL;
+
+ if (ticks > MAX_TICKS) {
+ if (!(priv->flags & FSL_GLOBAL_TIMER))
+ return NULL;
+
+ timer = get_cascade_timer(priv, ticks);
+ if (!timer)
+ continue;
+
+ return timer;
+ }
+
+ for (i = 0; i < TIMERS_PER_GROUP; i++) {
+ /* one timer: Reverse allocation */
+ num = TIMERS_PER_GROUP - 1 - i;
+ spin_lock_irqsave(&priv->lock, flags);
+ if (priv->idle & (1 << i)) {
+ /* set timer busy */
+ priv->idle &= ~(1 << i);
+ /* set ticks & stop timer */
+ out_be32(&priv->regs[num].gtbcr,
+ ticks | TIMER_STOP);
+ out_be32(&priv->regs[num].gtccr, 0);
+ priv->timer[num].cascade_handle = NULL;
+ spin_unlock_irqrestore(&priv->lock, flags);
+ return &priv->timer[num];
+ }
+ spin_unlock_irqrestore(&priv->lock, flags);
+ }
+ }
+
+ return NULL;
+}
+
+/**
+ * mpic_start_timer - start hardware timer
+ * @handle: the timer to be started.
+ *
+ * It will do ->fn(->dev) callback from the hardware interrupt at
+ * the ->timeval point in the future.
+ */
+void mpic_start_timer(struct mpic_timer *handle)
+{
+ struct timer_group_priv *priv = container_of(handle,
+ struct timer_group_priv, timer[handle->num]);
+
+ clrbits32(&priv->regs[handle->num].gtbcr, TIMER_STOP);
+}
+EXPORT_SYMBOL(mpic_start_timer);
+
+/**
+ * mpic_stop_timer - stop hardware timer
+ * @handle: the timer to be stoped
+ *
+ * The timer periodically generates an interrupt. Unless user stops the timer.
+ */
+void mpic_stop_timer(struct mpic_timer *handle)
+{
+ struct timer_group_priv *priv = container_of(handle,
+ struct timer_group_priv, timer[handle->num]);
+ struct cascade_priv *casc_priv;
+
+ setbits32(&priv->regs[handle->num].gtbcr, TIMER_STOP);
+
+ casc_priv = priv->timer[handle->num].cascade_handle;
+ if (casc_priv) {
+ out_be32(&priv->regs[handle->num].gtccr, 0);
+ out_be32(&priv->regs[handle->num - 1].gtccr, 0);
+ } else {
+ out_be32(&priv->regs[handle->num].gtccr, 0);
+ }
+}
+EXPORT_SYMBOL(mpic_stop_timer);
+
+/**
+ * mpic_get_remain_time - get timer time
+ * @handle: the timer to be selected.
+ * @time: time for timer
+ *
+ * Query timer remaining time.
+ */
+void mpic_get_remain_time(struct mpic_timer *handle, struct timeval *time)
+{
+ struct timer_group_priv *priv = container_of(handle,
+ struct timer_group_priv, timer[handle->num]);
+ struct cascade_priv *casc_priv;
+
+ u64 ticks;
+ u32 tmp_ticks;
+
+ casc_priv = priv->timer[handle->num].cascade_handle;
+ if (casc_priv) {
+ tmp_ticks = in_be32(&priv->regs[handle->num].gtccr);
+ tmp_ticks &= ~GTCCR_TOG;
+ ticks = ((u64)tmp_ticks & UINT_MAX) * (u64)MAX_TICKS_CASCADE;
+ tmp_ticks = in_be32(&priv->regs[handle->num - 1].gtccr);
+ ticks += tmp_ticks;
+ } else {
+ ticks = in_be32(&priv->regs[handle->num].gtccr);
+ ticks &= ~GTCCR_TOG;
+ }
+
+ convert_ticks_to_time(priv, ticks, time);
+}
+EXPORT_SYMBOL(mpic_get_remain_time);
+
+/**
+ * mpic_free_timer - free hardware timer
+ * @handle: the timer to be removed.
+ *
+ * Free the timer.
+ *
+ * Note: can not be used in interrupt context.
+ */
+void mpic_free_timer(struct mpic_timer *handle)
+{
+ struct timer_group_priv *priv = container_of(handle,
+ struct timer_group_priv, timer[handle->num]);
+
+ struct cascade_priv *casc_priv;
+ unsigned long flags;
+
+ mpic_stop_timer(handle);
+
+ casc_priv = priv->timer[handle->num].cascade_handle;
+
+ free_irq(priv->timer[handle->num].irq, priv->timer[handle->num].dev);
+
+ spin_lock_irqsave(&priv->lock, flags);
+ if (casc_priv) {
+ u32 tcr;
+ tcr = casc_priv->tcr_value | (casc_priv->tcr_value <<
+ MPIC_TIMER_TCR_ROVR_OFFSET);
+ clrbits32(priv->group_tcr, tcr);
+ priv->idle |= casc_priv->cascade_map;
+ priv->timer[handle->num].cascade_handle = NULL;
+ } else {
+ priv->idle |= TIMER_OFFSET(handle->num);
+ }
+ spin_unlock_irqrestore(&priv->lock, flags);
+}
+EXPORT_SYMBOL(mpic_free_timer);
+
+/**
+ * mpic_request_timer - get a hardware timer
+ * @fn: interrupt handler function
+ * @dev: callback function of the data
+ * @time: time for timer
+ *
+ * This executes the "request_irq", returning NULL
+ * else "handle" on success.
+ */
+struct mpic_timer *mpic_request_timer(irq_handler_t fn, void *dev,
+ const struct timeval *time)
+{
+ struct mpic_timer *allocated_timer;
+ int ret;
+
+ if (list_empty(&timer_group_list))
+ return NULL;
+
+ if (!(time->tv_sec + time->tv_usec) ||
+ time->tv_sec < 0 || time->tv_usec < 0)
+ return NULL;
+
+ if (time->tv_usec > ONE_SECOND)
+ return NULL;
+
+ allocated_timer = get_timer(time);
+ if (!allocated_timer)
+ return NULL;
+
+ ret = request_irq(allocated_timer->irq, fn,
+ IRQF_TRIGGER_LOW, "global-timer", dev);
+ if (ret) {
+ mpic_free_timer(allocated_timer);
+ return NULL;
+ }
+
+ allocated_timer->dev = dev;
+
+ return allocated_timer;
+}
+EXPORT_SYMBOL(mpic_request_timer);
+
+static int timer_group_get_freq(struct device_node *np,
+ struct timer_group_priv *priv)
+{
+ u32 div;
+
+ if (priv->flags & FSL_GLOBAL_TIMER) {
+ struct device_node *dn;
+
+ dn = of_find_compatible_node(NULL, NULL, "fsl,mpic");
+ if (dn) {
+ of_property_read_u32(dn, "clock-frequency",
+ &priv->timerfreq);
+ of_node_put(dn);
+ }
+ }
+
+ if (priv->timerfreq <= 0)
+ return -EINVAL;
+
+ if (priv->flags & FSL_GLOBAL_TIMER) {
+ div = (1 << (MPIC_TIMER_TCR_CLKDIV >> 8)) * 8;
+ priv->timerfreq /= div;
+ }
+
+ return 0;
+}
+
+static int timer_group_get_irq(struct device_node *np,
+ struct timer_group_priv *priv)
+{
+ const u32 all_timer[] = { 0, TIMERS_PER_GROUP };
+ const u32 *p;
+ u32 offset;
+ u32 count;
+
+ unsigned int i;
+ unsigned int j;
+ unsigned int irq_index = 0;
+ unsigned int irq;
+ int len;
+
+ p = of_get_property(np, "fsl,available-ranges", &len);
+ if (p && len % (2 * sizeof(u32)) != 0) {
+ pr_err("%s: malformed available-ranges property.\n",
+ np->full_name);
+ return -EINVAL;
+ }
+
+ if (!p) {
+ p = all_timer;
+ len = sizeof(all_timer);
+ }
+
+ len /= 2 * sizeof(u32);
+
+ for (i = 0; i < len; i++) {
+ offset = p[i * 2];
+ count = p[i * 2 + 1];
+ for (j = 0; j < count; j++) {
+ irq = irq_of_parse_and_map(np, irq_index);
+ if (!irq) {
+ pr_err("%s: irq parse and map failed.\n",
+ np->full_name);
+ return -EINVAL;
+ }
+
+ /* Set timer idle */
+ priv->idle |= TIMER_OFFSET((offset + j));
+ priv->timer[offset + j].irq = irq;
+ priv->timer[offset + j].num = offset + j;
+ irq_index++;
+ }
+ }
+
+ return 0;
+}
+
+static void timer_group_init(struct device_node *np)
+{
+ struct timer_group_priv *priv;
+ unsigned int i = 0;
+ int ret;
+
+ priv = kzalloc(sizeof(struct timer_group_priv), GFP_KERNEL);
+ if (!priv) {
+ pr_err("%s: cannot allocate memory for group.\n",
+ np->full_name);
+ return;
+ }
+
+ if (of_device_is_compatible(np, "fsl,mpic-global-timer"))
+ priv->flags |= FSL_GLOBAL_TIMER;
+
+ priv->regs = of_iomap(np, i++);
+ if (!priv->regs) {
+ pr_err("%s: cannot ioremap timer register address.\n",
+ np->full_name);
+ goto out;
+ }
+
+ if (priv->flags & FSL_GLOBAL_TIMER) {
+ priv->group_tcr = of_iomap(np, i++);
+ if (!priv->group_tcr) {
+ pr_err("%s: cannot ioremap tcr address.\n",
+ np->full_name);
+ goto out;
+ }
+ }
+
+ ret = timer_group_get_freq(np, priv);
+ if (ret < 0) {
+ pr_err("%s: cannot get timer frequency.\n", np->full_name);
+ goto out;
+ }
+
+ ret = timer_group_get_irq(np, priv);
+ if (ret < 0) {
+ pr_err("%s: cannot get timer irqs.\n", np->full_name);
+ goto out;
+ }
+
+ spin_lock_init(&priv->lock);
+
+ /* Init FSL timer hardware */
+ if (priv->flags & FSL_GLOBAL_TIMER)
+ setbits32(priv->group_tcr, MPIC_TIMER_TCR_CLKDIV);
+
+ list_add_tail(&priv->node, &timer_group_list);
+
+ return;
+
+out:
+ if (priv->regs)
+ iounmap(priv->regs);
+
+ if (priv->group_tcr)
+ iounmap(priv->group_tcr);
+
+ kfree(priv);
+}
+
+static void mpic_timer_resume(void)
+{
+ struct timer_group_priv *priv;
+
+ list_for_each_entry(priv, &timer_group_list, node) {
+ /* Init FSL timer hardware */
+ if (priv->flags & FSL_GLOBAL_TIMER)
+ setbits32(priv->group_tcr, MPIC_TIMER_TCR_CLKDIV);
+ }
+}
+
+static const struct of_device_id mpic_timer_ids[] = {
+ { .compatible = "fsl,mpic-global-timer", },
+ {},
+};
+
+static struct syscore_ops mpic_timer_syscore_ops = {
+ .resume = mpic_timer_resume,
+};
+
+static int __init mpic_timer_init(void)
+{
+ struct device_node *np = NULL;
+
+ for_each_matching_node(np, mpic_timer_ids)
+ timer_group_init(np);
+
+ register_syscore_ops(&mpic_timer_syscore_ops);
+
+ if (list_empty(&timer_group_list))
+ return -ENODEV;
+
+ return 0;
+}
+subsys_initcall(mpic_timer_init);
diff --git a/arch/powerpc/sysdev/msi_bitmap.c b/arch/powerpc/sysdev/msi_bitmap.c
index 0968b66b4cf..2ff630267e9 100644
--- a/arch/powerpc/sysdev/msi_bitmap.c
+++ b/arch/powerpc/sysdev/msi_bitmap.c
@@ -202,7 +202,7 @@ void __init test_of_node(void)
/* There should really be a struct device_node allocator */
memset(&of_node, 0, sizeof(of_node));
- kref_init(&of_node.kref);
+ of_node_init(&of_node);
of_node.full_name = node_name;
check(0 == msi_bitmap_alloc(&bmp, size, &of_node));
diff --git a/arch/powerpc/sysdev/mv64x60_dev.c b/arch/powerpc/sysdev/mv64x60_dev.c
index 0f6af41ebb4..c2dba7db71a 100644
--- a/arch/powerpc/sysdev/mv64x60_dev.c
+++ b/arch/powerpc/sysdev/mv64x60_dev.c
@@ -214,15 +214,27 @@ static struct platform_device * __init mv64x60_eth_register_shared_pdev(
struct device_node *np, int id)
{
struct platform_device *pdev;
- struct resource r[1];
+ struct resource r[2];
int err;
err = of_address_to_resource(np, 0, &r[0]);
if (err)
return ERR_PTR(err);
+ /* register an orion mdio bus driver */
+ r[1].start = r[0].start + 0x4;
+ r[1].end = r[0].start + 0x84 - 1;
+ r[1].flags = IORESOURCE_MEM;
+
+ if (id == 0) {
+ pdev = platform_device_register_simple("orion-mdio", -1, &r[1], 1);
+ if (IS_ERR(pdev))
+ return pdev;
+ }
+
pdev = platform_device_register_simple(MV643XX_ETH_SHARED_NAME, id,
- r, 1);
+ &r[0], 1);
+
return pdev;
}
@@ -436,7 +448,7 @@ static int __init mv64x60_device_setup(void)
int err;
id = 0;
- for_each_compatible_node(np, "serial", "marvell,mv64360-mpsc") {
+ for_each_compatible_node(np, NULL, "marvell,mv64360-mpsc") {
err = mv64x60_mpsc_device_setup(np, id++);
if (err)
printk(KERN_ERR "Failed to initialize MV64x60 "
diff --git a/arch/powerpc/sysdev/mv64x60_udbg.c b/arch/powerpc/sysdev/mv64x60_udbg.c
index 50a81387e9b..3b8734b870e 100644
--- a/arch/powerpc/sysdev/mv64x60_udbg.c
+++ b/arch/powerpc/sysdev/mv64x60_udbg.c
@@ -85,7 +85,7 @@ static void mv64x60_udbg_init(void)
if (!stdout)
return;
- for_each_compatible_node(np, "serial", "marvell,mv64360-mpsc") {
+ for_each_compatible_node(np, NULL, "marvell,mv64360-mpsc") {
if (np == stdout)
break;
}
diff --git a/arch/powerpc/sysdev/of_rtc.c b/arch/powerpc/sysdev/of_rtc.c
index c9e803f3e26..6f54b54b132 100644
--- a/arch/powerpc/sysdev/of_rtc.c
+++ b/arch/powerpc/sysdev/of_rtc.c
@@ -11,6 +11,7 @@
#include <linux/kernel.h>
#include <linux/of.h>
#include <linux/init.h>
+#include <linux/of_address.h>
#include <linux/of_platform.h>
#include <linux/slab.h>
diff --git a/arch/powerpc/sysdev/ppc4xx_hsta_msi.c b/arch/powerpc/sysdev/ppc4xx_hsta_msi.c
new file mode 100644
index 00000000000..11c888416f0
--- /dev/null
+++ b/arch/powerpc/sysdev/ppc4xx_hsta_msi.c
@@ -0,0 +1,215 @@
+/*
+ * MSI support for PPC4xx SoCs using High Speed Transfer Assist (HSTA) for
+ * generation of the interrupt.
+ *
+ * Copyright © 2013 Alistair Popple <alistair@popple.id.au> IBM Corporation
+ *
+ * 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/msi.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/pci.h>
+#include <linux/semaphore.h>
+#include <asm/msi_bitmap.h>
+
+struct ppc4xx_hsta_msi {
+ struct device *dev;
+
+ /* The ioremapped HSTA MSI IO space */
+ u32 __iomem *data;
+
+ /* Physical address of HSTA MSI IO space */
+ u64 address;
+ struct msi_bitmap bmp;
+
+ /* An array mapping offsets to hardware IRQs */
+ int *irq_map;
+
+ /* Number of hwirqs supported */
+ int irq_count;
+};
+static struct ppc4xx_hsta_msi ppc4xx_hsta_msi;
+
+static int hsta_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
+{
+ struct msi_msg msg;
+ struct msi_desc *entry;
+ int irq, hwirq;
+ u64 addr;
+
+ list_for_each_entry(entry, &dev->msi_list, list) {
+ irq = msi_bitmap_alloc_hwirqs(&ppc4xx_hsta_msi.bmp, 1);
+ if (irq < 0) {
+ pr_debug("%s: Failed to allocate msi interrupt\n",
+ __func__);
+ return irq;
+ }
+
+ hwirq = ppc4xx_hsta_msi.irq_map[irq];
+ if (hwirq == NO_IRQ) {
+ pr_err("%s: Failed mapping irq %d\n", __func__, irq);
+ return -EINVAL;
+ }
+
+ /*
+ * HSTA generates interrupts on writes to 128-bit aligned
+ * addresses.
+ */
+ addr = ppc4xx_hsta_msi.address + irq*0x10;
+ msg.address_hi = upper_32_bits(addr);
+ msg.address_lo = lower_32_bits(addr);
+
+ /* Data is not used by the HSTA. */
+ msg.data = 0;
+
+ pr_debug("%s: Setup irq %d (0x%0llx)\n", __func__, hwirq,
+ (((u64) msg.address_hi) << 32) | msg.address_lo);
+
+ if (irq_set_msi_desc(hwirq, entry)) {
+ pr_err(
+ "%s: Invalid hwirq %d specified in device tree\n",
+ __func__, hwirq);
+ msi_bitmap_free_hwirqs(&ppc4xx_hsta_msi.bmp, irq, 1);
+ return -EINVAL;
+ }
+ write_msi_msg(hwirq, &msg);
+ }
+
+ return 0;
+}
+
+static int hsta_find_hwirq_offset(int hwirq)
+{
+ int irq;
+
+ /* Find the offset given the hwirq */
+ for (irq = 0; irq < ppc4xx_hsta_msi.irq_count; irq++)
+ if (ppc4xx_hsta_msi.irq_map[irq] == hwirq)
+ return irq;
+
+ return -EINVAL;
+}
+
+static void hsta_teardown_msi_irqs(struct pci_dev *dev)
+{
+ struct msi_desc *entry;
+ int irq;
+
+ list_for_each_entry(entry, &dev->msi_list, list) {
+ if (entry->irq == NO_IRQ)
+ continue;
+
+ irq = hsta_find_hwirq_offset(entry->irq);
+
+ /* entry->irq should always be in irq_map */
+ BUG_ON(irq < 0);
+ irq_set_msi_desc(entry->irq, NULL);
+ msi_bitmap_free_hwirqs(&ppc4xx_hsta_msi.bmp, irq, 1);
+ pr_debug("%s: Teardown IRQ %u (index %u)\n", __func__,
+ entry->irq, irq);
+ }
+}
+
+static int hsta_msi_check_device(struct pci_dev *pdev, int nvec, int type)
+{
+ /* We don't support MSI-X */
+ if (type == PCI_CAP_ID_MSIX) {
+ pr_debug("%s: MSI-X not supported.\n", __func__);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int hsta_msi_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct resource *mem;
+ int irq, ret, irq_count;
+
+ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (IS_ERR(mem)) {
+ dev_err(dev, "Unable to get mmio space\n");
+ return -EINVAL;
+ }
+
+ irq_count = of_irq_count(dev->of_node);
+ if (!irq_count) {
+ dev_err(dev, "Unable to find IRQ range\n");
+ return -EINVAL;
+ }
+
+ ppc4xx_hsta_msi.dev = dev;
+ ppc4xx_hsta_msi.address = mem->start;
+ ppc4xx_hsta_msi.data = ioremap(mem->start, resource_size(mem));
+ ppc4xx_hsta_msi.irq_count = irq_count;
+ if (IS_ERR(ppc4xx_hsta_msi.data)) {
+ dev_err(dev, "Unable to map memory\n");
+ return -ENOMEM;
+ }
+
+ ret = msi_bitmap_alloc(&ppc4xx_hsta_msi.bmp, irq_count, dev->of_node);
+ if (ret)
+ goto out;
+
+ ppc4xx_hsta_msi.irq_map = kmalloc(sizeof(int) * irq_count, GFP_KERNEL);
+ if (IS_ERR(ppc4xx_hsta_msi.irq_map)) {
+ ret = -ENOMEM;
+ goto out1;
+ }
+
+ /* Setup a mapping from irq offsets to hardware irq numbers */
+ for (irq = 0; irq < irq_count; irq++) {
+ ppc4xx_hsta_msi.irq_map[irq] =
+ irq_of_parse_and_map(dev->of_node, irq);
+ if (ppc4xx_hsta_msi.irq_map[irq] == NO_IRQ) {
+ dev_err(dev, "Unable to map IRQ\n");
+ ret = -EINVAL;
+ goto out2;
+ }
+ }
+
+ ppc_md.setup_msi_irqs = hsta_setup_msi_irqs;
+ ppc_md.teardown_msi_irqs = hsta_teardown_msi_irqs;
+ ppc_md.msi_check_device = hsta_msi_check_device;
+ return 0;
+
+out2:
+ kfree(ppc4xx_hsta_msi.irq_map);
+
+out1:
+ msi_bitmap_free(&ppc4xx_hsta_msi.bmp);
+
+out:
+ iounmap(ppc4xx_hsta_msi.data);
+ return ret;
+}
+
+static const struct of_device_id hsta_msi_ids[] = {
+ {
+ .compatible = "ibm,hsta-msi",
+ },
+ {}
+};
+
+static struct platform_driver hsta_msi_driver = {
+ .probe = hsta_msi_probe,
+ .driver = {
+ .name = "hsta-msi",
+ .owner = THIS_MODULE,
+ .of_match_table = hsta_msi_ids,
+ },
+};
+
+static int hsta_msi_init(void)
+{
+ return platform_driver_register(&hsta_msi_driver);
+}
+subsys_initcall(hsta_msi_init);
diff --git a/arch/powerpc/sysdev/ppc4xx_ocm.c b/arch/powerpc/sysdev/ppc4xx_ocm.c
new file mode 100644
index 00000000000..85d9e37f5cc
--- /dev/null
+++ b/arch/powerpc/sysdev/ppc4xx_ocm.c
@@ -0,0 +1,416 @@
+/*
+ * PowerPC 4xx OCM memory allocation support
+ *
+ * (C) Copyright 2009, Applied Micro Circuits Corporation
+ * Victor Gallardo (vgallardo@amcc.com)
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/dma-mapping.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <asm/rheap.h>
+#include <asm/ppc4xx_ocm.h>
+#include <linux/slab.h>
+#include <linux/debugfs.h>
+
+#define OCM_DISABLED 0
+#define OCM_ENABLED 1
+
+struct ocm_block {
+ struct list_head list;
+ void __iomem *addr;
+ int size;
+ const char *owner;
+};
+
+/* non-cached or cached region */
+struct ocm_region {
+ phys_addr_t phys;
+ void __iomem *virt;
+
+ int memtotal;
+ int memfree;
+
+ rh_info_t *rh;
+ struct list_head list;
+};
+
+struct ocm_info {
+ int index;
+ int status;
+ int ready;
+
+ phys_addr_t phys;
+
+ int alignment;
+ int memtotal;
+ int cache_size;
+
+ struct ocm_region nc; /* non-cached region */
+ struct ocm_region c; /* cached region */
+};
+
+static struct ocm_info *ocm_nodes;
+static int ocm_count;
+
+static struct ocm_info *ocm_get_node(unsigned int index)
+{
+ if (index >= ocm_count) {
+ printk(KERN_ERR "PPC4XX OCM: invalid index");
+ return NULL;
+ }
+
+ return &ocm_nodes[index];
+}
+
+static int ocm_free_region(struct ocm_region *ocm_reg, const void *addr)
+{
+ struct ocm_block *blk, *tmp;
+ unsigned long offset;
+
+ if (!ocm_reg->virt)
+ return 0;
+
+ list_for_each_entry_safe(blk, tmp, &ocm_reg->list, list) {
+ if (blk->addr == addr) {
+ offset = addr - ocm_reg->virt;
+ ocm_reg->memfree += blk->size;
+ rh_free(ocm_reg->rh, offset);
+ list_del(&blk->list);
+ kfree(blk);
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static void __init ocm_init_node(int count, struct device_node *node)
+{
+ struct ocm_info *ocm;
+
+ const unsigned int *cell_index;
+ const unsigned int *cache_size;
+ int len;
+
+ struct resource rsrc;
+ int ioflags;
+
+ ocm = ocm_get_node(count);
+
+ cell_index = of_get_property(node, "cell-index", &len);
+ if (!cell_index) {
+ printk(KERN_ERR "PPC4XX OCM: missing cell-index property");
+ return;
+ }
+ ocm->index = *cell_index;
+
+ if (of_device_is_available(node))
+ ocm->status = OCM_ENABLED;
+
+ cache_size = of_get_property(node, "cached-region-size", &len);
+ if (cache_size)
+ ocm->cache_size = *cache_size;
+
+ if (of_address_to_resource(node, 0, &rsrc)) {
+ printk(KERN_ERR "PPC4XX OCM%d: could not get resource address\n",
+ ocm->index);
+ return;
+ }
+
+ ocm->phys = rsrc.start;
+ ocm->memtotal = (rsrc.end - rsrc.start + 1);
+
+ printk(KERN_INFO "PPC4XX OCM%d: %d Bytes (%s)\n",
+ ocm->index, ocm->memtotal,
+ (ocm->status == OCM_DISABLED) ? "disabled" : "enabled");
+
+ if (ocm->status == OCM_DISABLED)
+ return;
+
+ /* request region */
+
+ if (!request_mem_region(ocm->phys, ocm->memtotal, "ppc4xx_ocm")) {
+ printk(KERN_ERR "PPC4XX OCM%d: could not request region\n",
+ ocm->index);
+ return;
+ }
+
+ /* Configure non-cached and cached regions */
+
+ ocm->nc.phys = ocm->phys;
+ ocm->nc.memtotal = ocm->memtotal - ocm->cache_size;
+ ocm->nc.memfree = ocm->nc.memtotal;
+
+ ocm->c.phys = ocm->phys + ocm->nc.memtotal;
+ ocm->c.memtotal = ocm->cache_size;
+ ocm->c.memfree = ocm->c.memtotal;
+
+ if (ocm->nc.memtotal == 0)
+ ocm->nc.phys = 0;
+
+ if (ocm->c.memtotal == 0)
+ ocm->c.phys = 0;
+
+ printk(KERN_INFO "PPC4XX OCM%d: %d Bytes (non-cached)\n",
+ ocm->index, ocm->nc.memtotal);
+
+ printk(KERN_INFO "PPC4XX OCM%d: %d Bytes (cached)\n",
+ ocm->index, ocm->c.memtotal);
+
+ /* ioremap the non-cached region */
+ if (ocm->nc.memtotal) {
+ ioflags = _PAGE_NO_CACHE | _PAGE_GUARDED | _PAGE_EXEC;
+ ocm->nc.virt = __ioremap(ocm->nc.phys, ocm->nc.memtotal,
+ ioflags);
+
+ if (!ocm->nc.virt) {
+ printk(KERN_ERR
+ "PPC4XX OCM%d: failed to ioremap non-cached memory\n",
+ ocm->index);
+ ocm->nc.memfree = 0;
+ return;
+ }
+ }
+
+ /* ioremap the cached region */
+
+ if (ocm->c.memtotal) {
+ ioflags = _PAGE_EXEC;
+ ocm->c.virt = __ioremap(ocm->c.phys, ocm->c.memtotal,
+ ioflags);
+
+ if (!ocm->c.virt) {
+ printk(KERN_ERR
+ "PPC4XX OCM%d: failed to ioremap cached memory\n",
+ ocm->index);
+ ocm->c.memfree = 0;
+ return;
+ }
+ }
+
+ /* Create Remote Heaps */
+
+ ocm->alignment = 4; /* default 4 byte alignment */
+
+ if (ocm->nc.virt) {
+ ocm->nc.rh = rh_create(ocm->alignment);
+ rh_attach_region(ocm->nc.rh, 0, ocm->nc.memtotal);
+ }
+
+ if (ocm->c.virt) {
+ ocm->c.rh = rh_create(ocm->alignment);
+ rh_attach_region(ocm->c.rh, 0, ocm->c.memtotal);
+ }
+
+ INIT_LIST_HEAD(&ocm->nc.list);
+ INIT_LIST_HEAD(&ocm->c.list);
+
+ ocm->ready = 1;
+
+ return;
+}
+
+static int ocm_debugfs_show(struct seq_file *m, void *v)
+{
+ struct ocm_block *blk, *tmp;
+ unsigned int i;
+
+ for (i = 0; i < ocm_count; i++) {
+ struct ocm_info *ocm = ocm_get_node(i);
+
+ if (!ocm || !ocm->ready)
+ continue;
+
+ seq_printf(m, "PPC4XX OCM : %d\n", ocm->index);
+ seq_printf(m, "PhysAddr : 0x%llx\n", ocm->phys);
+ seq_printf(m, "MemTotal : %d Bytes\n", ocm->memtotal);
+ seq_printf(m, "MemTotal(NC) : %d Bytes\n", ocm->nc.memtotal);
+ seq_printf(m, "MemTotal(C) : %d Bytes\n", ocm->c.memtotal);
+
+ seq_printf(m, "\n");
+
+ seq_printf(m, "NC.PhysAddr : 0x%llx\n", ocm->nc.phys);
+ seq_printf(m, "NC.VirtAddr : 0x%p\n", ocm->nc.virt);
+ seq_printf(m, "NC.MemTotal : %d Bytes\n", ocm->nc.memtotal);
+ seq_printf(m, "NC.MemFree : %d Bytes\n", ocm->nc.memfree);
+
+ list_for_each_entry_safe(blk, tmp, &ocm->nc.list, list) {
+ seq_printf(m, "NC.MemUsed : %d Bytes (%s)\n",
+ blk->size, blk->owner);
+ }
+
+ seq_printf(m, "\n");
+
+ seq_printf(m, "C.PhysAddr : 0x%llx\n", ocm->c.phys);
+ seq_printf(m, "C.VirtAddr : 0x%p\n", ocm->c.virt);
+ seq_printf(m, "C.MemTotal : %d Bytes\n", ocm->c.memtotal);
+ seq_printf(m, "C.MemFree : %d Bytes\n", ocm->c.memfree);
+
+ list_for_each_entry_safe(blk, tmp, &ocm->c.list, list) {
+ seq_printf(m, "C.MemUsed : %d Bytes (%s)\n",
+ blk->size, blk->owner);
+ }
+
+ seq_printf(m, "\n");
+ }
+
+ return 0;
+}
+
+static int ocm_debugfs_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, ocm_debugfs_show, NULL);
+}
+
+static const struct file_operations ocm_debugfs_fops = {
+ .open = ocm_debugfs_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static int ocm_debugfs_init(void)
+{
+ struct dentry *junk;
+
+ junk = debugfs_create_dir("ppc4xx_ocm", 0);
+ if (!junk) {
+ printk(KERN_ALERT "debugfs ppc4xx ocm: failed to create dir\n");
+ return -1;
+ }
+
+ if (debugfs_create_file("info", 0644, junk, NULL, &ocm_debugfs_fops)) {
+ printk(KERN_ALERT "debugfs ppc4xx ocm: failed to create file\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+void *ppc4xx_ocm_alloc(phys_addr_t *phys, int size, int align,
+ int flags, const char *owner)
+{
+ void __iomem *addr = NULL;
+ unsigned long offset;
+ struct ocm_info *ocm;
+ struct ocm_region *ocm_reg;
+ struct ocm_block *ocm_blk;
+ int i;
+
+ for (i = 0; i < ocm_count; i++) {
+ ocm = ocm_get_node(i);
+
+ if (!ocm || !ocm->ready)
+ continue;
+
+ if (flags == PPC4XX_OCM_NON_CACHED)
+ ocm_reg = &ocm->nc;
+ else
+ ocm_reg = &ocm->c;
+
+ if (!ocm_reg->virt)
+ continue;
+
+ if (align < ocm->alignment)
+ align = ocm->alignment;
+
+ offset = rh_alloc_align(ocm_reg->rh, size, align, NULL);
+
+ if (IS_ERR_VALUE(offset))
+ continue;
+
+ ocm_blk = kzalloc(sizeof(struct ocm_block), GFP_KERNEL);
+ if (!ocm_blk) {
+ printk(KERN_ERR "PPC4XX OCM: could not allocate ocm block");
+ rh_free(ocm_reg->rh, offset);
+ break;
+ }
+
+ *phys = ocm_reg->phys + offset;
+ addr = ocm_reg->virt + offset;
+ size = ALIGN(size, align);
+
+ ocm_blk->addr = addr;
+ ocm_blk->size = size;
+ ocm_blk->owner = owner;
+ list_add_tail(&ocm_blk->list, &ocm_reg->list);
+
+ ocm_reg->memfree -= size;
+
+ break;
+ }
+
+ return addr;
+}
+
+void ppc4xx_ocm_free(const void *addr)
+{
+ int i;
+
+ if (!addr)
+ return;
+
+ for (i = 0; i < ocm_count; i++) {
+ struct ocm_info *ocm = ocm_get_node(i);
+
+ if (!ocm || !ocm->ready)
+ continue;
+
+ if (ocm_free_region(&ocm->nc, addr) ||
+ ocm_free_region(&ocm->c, addr))
+ return;
+ }
+}
+
+static int __init ppc4xx_ocm_init(void)
+{
+ struct device_node *np;
+ int count;
+
+ count = 0;
+ for_each_compatible_node(np, NULL, "ibm,ocm")
+ count++;
+
+ if (!count)
+ return 0;
+
+ ocm_nodes = kzalloc((count * sizeof(struct ocm_info)), GFP_KERNEL);
+ if (!ocm_nodes) {
+ printk(KERN_ERR "PPC4XX OCM: failed to allocate OCM nodes!\n");
+ return -ENOMEM;
+ }
+
+ ocm_count = count;
+ count = 0;
+
+ for_each_compatible_node(np, NULL, "ibm,ocm") {
+ ocm_init_node(count, np);
+ count++;
+ }
+
+ ocm_debugfs_init();
+
+ return 0;
+}
+
+arch_initcall(ppc4xx_ocm_init);
diff --git a/arch/powerpc/sysdev/ppc4xx_pci.c b/arch/powerpc/sysdev/ppc4xx_pci.c
index 56e8b3c3c89..df6e2fc4ff9 100644
--- a/arch/powerpc/sysdev/ppc4xx_pci.c
+++ b/arch/powerpc/sysdev/ppc4xx_pci.c
@@ -176,8 +176,12 @@ static int __init ppc4xx_parse_dma_ranges(struct pci_controller *hose,
return -ENXIO;
}
- /* Check that we are fully contained within 32 bits space */
- if (res->end > 0xffffffff) {
+ /* Check that we are fully contained within 32 bits space if we are not
+ * running on a 460sx or 476fpe which have 64 bit bus addresses.
+ */
+ if (res->end > 0xffffffff &&
+ !(of_device_is_compatible(hose->dn, "ibm,plb-pciex-460sx")
+ || of_device_is_compatible(hose->dn, "ibm,plb-pciex-476fpe"))) {
printk(KERN_ERR "%s: dma-ranges outside of 32 bits space\n",
hose->dn->full_name);
return -ENXIO;
@@ -257,6 +261,7 @@ static void __init ppc4xx_configure_pci_PMMs(struct pci_controller *hose,
/* Setup outbound memory windows */
for (i = j = 0; i < 3; i++) {
struct resource *res = &hose->mem_resources[i];
+ resource_size_t offset = hose->mem_offset[i];
/* we only care about memory windows */
if (!(res->flags & IORESOURCE_MEM))
@@ -270,7 +275,7 @@ static void __init ppc4xx_configure_pci_PMMs(struct pci_controller *hose,
/* Configure the resource */
if (ppc4xx_setup_one_pci_PMM(hose, reg,
res->start,
- res->start - hose->pci_mem_offset,
+ res->start - offset,
resource_size(res),
res->flags,
j) == 0) {
@@ -279,7 +284,7 @@ static void __init ppc4xx_configure_pci_PMMs(struct pci_controller *hose,
/* If the resource PCI address is 0 then we have our
* ISA memory hole
*/
- if (res->start == hose->pci_mem_offset)
+ if (res->start == offset)
found_isa_hole = 1;
}
}
@@ -457,6 +462,7 @@ static void __init ppc4xx_configure_pcix_POMs(struct pci_controller *hose,
/* Setup outbound memory windows */
for (i = j = 0; i < 3; i++) {
struct resource *res = &hose->mem_resources[i];
+ resource_size_t offset = hose->mem_offset[i];
/* we only care about memory windows */
if (!(res->flags & IORESOURCE_MEM))
@@ -470,7 +476,7 @@ static void __init ppc4xx_configure_pcix_POMs(struct pci_controller *hose,
/* Configure the resource */
if (ppc4xx_setup_one_pcix_POM(hose, reg,
res->start,
- res->start - hose->pci_mem_offset,
+ res->start - offset,
resource_size(res),
res->flags,
j) == 0) {
@@ -479,7 +485,7 @@ static void __init ppc4xx_configure_pcix_POMs(struct pci_controller *hose,
/* If the resource PCI address is 0 then we have our
* ISA memory hole
*/
- if (res->start == hose->pci_mem_offset)
+ if (res->start == offset)
found_isa_hole = 1;
}
}
@@ -1056,7 +1062,7 @@ static int __init apm821xx_pciex_core_init(struct device_node *np)
return 1;
}
-static int apm821xx_pciex_init_port_hw(struct ppc4xx_pciex_port *port)
+static int __init apm821xx_pciex_init_port_hw(struct ppc4xx_pciex_port *port)
{
u32 val;
@@ -1438,7 +1444,8 @@ static int __init ppc4xx_pciex_check_core_init(struct device_node *np)
ppc4xx_pciex_hwops = &ppc405ex_pcie_hwops;
#endif
#ifdef CONFIG_476FPE
- if (of_device_is_compatible(np, "ibm,plb-pciex-476fpe"))
+ if (of_device_is_compatible(np, "ibm,plb-pciex-476fpe")
+ || of_device_is_compatible(np, "ibm,plb-pciex-476gtr"))
ppc4xx_pciex_hwops = &ppc_476fpe_pcie_hwops;
#endif
if (ppc4xx_pciex_hwops == NULL) {
@@ -1749,7 +1756,10 @@ static int __init ppc4xx_setup_one_pciex_POM(struct ppc4xx_pciex_port *port,
dcr_write(port->dcrs, DCRO_PEGPL_OMR1MSKL,
sa | DCRO_PEGPL_460SX_OMR1MSKL_UOT
| DCRO_PEGPL_OMRxMSKL_VAL);
- else if (of_device_is_compatible(port->node, "ibm,plb-pciex-476fpe"))
+ else if (of_device_is_compatible(
+ port->node, "ibm,plb-pciex-476fpe") ||
+ of_device_is_compatible(
+ port->node, "ibm,plb-pciex-476gtr"))
dcr_write(port->dcrs, DCRO_PEGPL_OMR1MSKL,
sa | DCRO_PEGPL_476FPE_OMR1MSKL_UOT
| DCRO_PEGPL_OMRxMSKL_VAL);
@@ -1792,6 +1802,7 @@ static void __init ppc4xx_configure_pciex_POMs(struct ppc4xx_pciex_port *port,
/* Setup outbound memory windows */
for (i = j = 0; i < 3; i++) {
struct resource *res = &hose->mem_resources[i];
+ resource_size_t offset = hose->mem_offset[i];
/* we only care about memory windows */
if (!(res->flags & IORESOURCE_MEM))
@@ -1805,7 +1816,7 @@ static void __init ppc4xx_configure_pciex_POMs(struct ppc4xx_pciex_port *port,
/* Configure the resource */
if (ppc4xx_setup_one_pciex_POM(port, hose, mbase,
res->start,
- res->start - hose->pci_mem_offset,
+ res->start - offset,
resource_size(res),
res->flags,
j) == 0) {
@@ -1814,7 +1825,7 @@ static void __init ppc4xx_configure_pciex_POMs(struct ppc4xx_pciex_port *port,
/* If the resource PCI address is 0 then we have our
* ISA memory hole
*/
- if (res->start == hose->pci_mem_offset)
+ if (res->start == offset)
found_isa_hole = 1;
}
}
@@ -1878,7 +1889,10 @@ static void __init ppc4xx_configure_pciex_PIMs(struct ppc4xx_pciex_port *port,
sa |= PCI_BASE_ADDRESS_MEM_PREFETCH;
if (of_device_is_compatible(port->node, "ibm,plb-pciex-460sx") ||
- of_device_is_compatible(port->node, "ibm,plb-pciex-476fpe"))
+ of_device_is_compatible(
+ port->node, "ibm,plb-pciex-476fpe") ||
+ of_device_is_compatible(
+ port->node, "ibm,plb-pciex-476gtr"))
sa |= PCI_BASE_ADDRESS_MEM_TYPE_64;
out_le32(mbase + PECFG_BAR0HMPA, RES_TO_U32_HIGH(sa));
diff --git a/arch/powerpc/sysdev/ppc4xx_soc.c b/arch/powerpc/sysdev/ppc4xx_soc.c
index 0debcc31ad7..5c77c9ba33a 100644
--- a/arch/powerpc/sysdev/ppc4xx_soc.c
+++ b/arch/powerpc/sysdev/ppc4xx_soc.c
@@ -19,6 +19,7 @@
#include <linux/errno.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
+#include <linux/of_irq.h>
#include <linux/of_platform.h>
#include <asm/dcr.h>
diff --git a/arch/powerpc/sysdev/qe_lib/Kconfig b/arch/powerpc/sysdev/qe_lib/Kconfig
index 41ac3dfac98..3c251993bac 100644
--- a/arch/powerpc/sysdev/qe_lib/Kconfig
+++ b/arch/powerpc/sysdev/qe_lib/Kconfig
@@ -22,6 +22,6 @@ config UCC
config QE_USB
bool
- default y if USB_GADGET_FSL_QE
+ default y if USB_FSL_QE
help
QE USB Controller support
diff --git a/arch/powerpc/sysdev/qe_lib/qe_io.c b/arch/powerpc/sysdev/qe_lib/qe_io.c
index a88807b3dd5..d09994164da 100644
--- a/arch/powerpc/sysdev/qe_lib/qe_io.c
+++ b/arch/powerpc/sysdev/qe_lib/qe_io.c
@@ -16,7 +16,6 @@
#include <linux/stddef.h>
#include <linux/kernel.h>
-#include <linux/init.h>
#include <linux/errno.h>
#include <linux/module.h>
#include <linux/ioport.h>
diff --git a/arch/powerpc/sysdev/qe_lib/ucc.c b/arch/powerpc/sysdev/qe_lib/ucc.c
index 134b07d2943..621575b7e84 100644
--- a/arch/powerpc/sysdev/qe_lib/ucc.c
+++ b/arch/powerpc/sysdev/qe_lib/ucc.c
@@ -14,7 +14,6 @@
* option) any later version.
*/
#include <linux/kernel.h>
-#include <linux/init.h>
#include <linux/errno.h>
#include <linux/stddef.h>
#include <linux/spinlock.h>
diff --git a/arch/powerpc/sysdev/qe_lib/ucc_fast.c b/arch/powerpc/sysdev/qe_lib/ucc_fast.c
index cceb2e36673..65aaf15032a 100644
--- a/arch/powerpc/sysdev/qe_lib/ucc_fast.c
+++ b/arch/powerpc/sysdev/qe_lib/ucc_fast.c
@@ -13,7 +13,6 @@
* option) any later version.
*/
#include <linux/kernel.h>
-#include <linux/init.h>
#include <linux/errno.h>
#include <linux/slab.h>
#include <linux/stddef.h>
diff --git a/arch/powerpc/sysdev/qe_lib/ucc_slow.c b/arch/powerpc/sysdev/qe_lib/ucc_slow.c
index 1c062f48f1a..befaf1123f7 100644
--- a/arch/powerpc/sysdev/qe_lib/ucc_slow.c
+++ b/arch/powerpc/sysdev/qe_lib/ucc_slow.c
@@ -13,7 +13,6 @@
* option) any later version.
*/
#include <linux/kernel.h>
-#include <linux/init.h>
#include <linux/errno.h>
#include <linux/slab.h>
#include <linux/stddef.h>
diff --git a/arch/powerpc/sysdev/rtc_cmos_setup.c b/arch/powerpc/sysdev/rtc_cmos_setup.c
index 9afba924e94..af0f9beddca 100644
--- a/arch/powerpc/sysdev/rtc_cmos_setup.c
+++ b/arch/powerpc/sysdev/rtc_cmos_setup.c
@@ -62,10 +62,7 @@ static int __init add_rtc(void)
pd = platform_device_register_simple("rtc_cmos", -1,
&res[0], num_res);
- if (IS_ERR(pd))
- return PTR_ERR(pd);
-
- return 0;
+ return PTR_ERR_OR_ZERO(pd);
}
fs_initcall(add_rtc);
diff --git a/arch/powerpc/sysdev/scom.c b/arch/powerpc/sysdev/scom.c
index 9193e12df69..6f5a8d177c4 100644
--- a/arch/powerpc/sysdev/scom.c
+++ b/arch/powerpc/sysdev/scom.c
@@ -25,6 +25,7 @@
#include <asm/debug.h>
#include <asm/prom.h>
#include <asm/scom.h>
+#include <asm/uaccess.h>
const struct scom_controller *scom_controller;
EXPORT_SYMBOL_GPL(scom_controller);
@@ -53,7 +54,7 @@ scom_map_t scom_map_device(struct device_node *dev, int index)
{
struct device_node *parent;
unsigned int cells, size;
- const u32 *prop;
+ const __be32 *prop, *sprop;
u64 reg, cnt;
scom_map_t ret;
@@ -62,12 +63,24 @@ scom_map_t scom_map_device(struct device_node *dev, int index)
if (parent == NULL)
return 0;
- prop = of_get_property(parent, "#scom-cells", NULL);
- cells = prop ? *prop : 1;
-
+ /*
+ * We support "scom-reg" properties for adding scom registers
+ * to a random device-tree node with an explicit scom-parent
+ *
+ * We also support the simple "reg" property if the device is
+ * a direct child of a scom controller.
+ *
+ * In case both exist, "scom-reg" takes precedence.
+ */
prop = of_get_property(dev, "scom-reg", &size);
+ sprop = of_get_property(parent, "#scom-cells", NULL);
+ if (!prop && parent == dev->parent) {
+ prop = of_get_property(dev, "reg", &size);
+ sprop = of_get_property(parent, "#address-cells", NULL);
+ }
if (!prop)
- return 0;
+ return NULL;
+ cells = sprop ? be32_to_cpup(sprop) : 1;
size >>= 2;
if (index >= (size / (2*cells)))
@@ -86,62 +99,89 @@ EXPORT_SYMBOL_GPL(scom_map_device);
#ifdef CONFIG_SCOM_DEBUGFS
struct scom_debug_entry {
struct device_node *dn;
- unsigned long addr;
- scom_map_t map;
- spinlock_t lock;
- char name[8];
- struct debugfs_blob_wrapper blob;
+ struct debugfs_blob_wrapper path;
+ char name[16];
};
-static int scom_addr_set(void *data, u64 val)
+static ssize_t scom_debug_read(struct file *filp, char __user *ubuf,
+ size_t count, loff_t *ppos)
{
- struct scom_debug_entry *ent = data;
-
- ent->addr = 0;
- scom_unmap(ent->map);
-
- ent->map = scom_map(ent->dn, val, 1);
- if (scom_map_ok(ent->map))
- ent->addr = val;
- else
- return -EFAULT;
-
- return 0;
-}
-
-static int scom_addr_get(void *data, u64 *val)
-{
- struct scom_debug_entry *ent = data;
- *val = ent->addr;
- return 0;
+ struct scom_debug_entry *ent = filp->private_data;
+ u64 __user *ubuf64 = (u64 __user *)ubuf;
+ loff_t off = *ppos;
+ ssize_t done = 0;
+ u64 reg, reg_cnt, val;
+ scom_map_t map;
+ int rc;
+
+ if (off < 0 || (off & 7) || (count & 7))
+ return -EINVAL;
+ reg = off >> 3;
+ reg_cnt = count >> 3;
+
+ map = scom_map(ent->dn, reg, reg_cnt);
+ if (!scom_map_ok(map))
+ return -ENXIO;
+
+ for (reg = 0; reg < reg_cnt; reg++) {
+ rc = scom_read(map, reg, &val);
+ if (!rc)
+ rc = put_user(val, ubuf64);
+ if (rc) {
+ if (!done)
+ done = rc;
+ break;
+ }
+ ubuf64++;
+ *ppos += 8;
+ done += 8;
+ }
+ scom_unmap(map);
+ return done;
}
-DEFINE_SIMPLE_ATTRIBUTE(scom_addr_fops, scom_addr_get, scom_addr_set,
- "0x%llx\n");
-static int scom_val_set(void *data, u64 val)
+static ssize_t scom_debug_write(struct file* filp, const char __user *ubuf,
+ size_t count, loff_t *ppos)
{
- struct scom_debug_entry *ent = data;
-
- if (!scom_map_ok(ent->map))
- return -EFAULT;
-
- scom_write(ent->map, 0, val);
-
- return 0;
+ struct scom_debug_entry *ent = filp->private_data;
+ u64 __user *ubuf64 = (u64 __user *)ubuf;
+ loff_t off = *ppos;
+ ssize_t done = 0;
+ u64 reg, reg_cnt, val;
+ scom_map_t map;
+ int rc;
+
+ if (off < 0 || (off & 7) || (count & 7))
+ return -EINVAL;
+ reg = off >> 3;
+ reg_cnt = count >> 3;
+
+ map = scom_map(ent->dn, reg, reg_cnt);
+ if (!scom_map_ok(map))
+ return -ENXIO;
+
+ for (reg = 0; reg < reg_cnt; reg++) {
+ rc = get_user(val, ubuf64);
+ if (!rc)
+ rc = scom_write(map, reg, val);
+ if (rc) {
+ if (!done)
+ done = rc;
+ break;
+ }
+ ubuf64++;
+ done += 8;
+ }
+ scom_unmap(map);
+ return done;
}
-static int scom_val_get(void *data, u64 *val)
-{
- struct scom_debug_entry *ent = data;
-
- if (!scom_map_ok(ent->map))
- return -EFAULT;
-
- *val = scom_read(ent->map, 0);
- return 0;
-}
-DEFINE_SIMPLE_ATTRIBUTE(scom_val_fops, scom_val_get, scom_val_set,
- "0x%llx\n");
+static const struct file_operations scom_debug_fops = {
+ .read = scom_debug_read,
+ .write = scom_debug_write,
+ .open = simple_open,
+ .llseek = default_llseek,
+};
static int scom_debug_init_one(struct dentry *root, struct device_node *dn,
int i)
@@ -154,11 +194,9 @@ static int scom_debug_init_one(struct dentry *root, struct device_node *dn,
return -ENOMEM;
ent->dn = of_node_get(dn);
- ent->map = SCOM_MAP_INVALID;
- spin_lock_init(&ent->lock);
- snprintf(ent->name, 8, "scom%d", i);
- ent->blob.data = (void*) dn->full_name;
- ent->blob.size = strlen(dn->full_name);
+ snprintf(ent->name, 16, "%08x", i);
+ ent->path.data = (void*) dn->full_name;
+ ent->path.size = strlen(dn->full_name);
dir = debugfs_create_dir(ent->name, root);
if (!dir) {
@@ -167,9 +205,8 @@ static int scom_debug_init_one(struct dentry *root, struct device_node *dn,
return -1;
}
- debugfs_create_file("addr", 0600, dir, ent, &scom_addr_fops);
- debugfs_create_file("value", 0600, dir, ent, &scom_val_fops);
- debugfs_create_blob("path", 0400, dir, &ent->blob);
+ debugfs_create_blob("devspec", 0400, dir, &ent->path);
+ debugfs_create_file("access", 0600, dir, ent, &scom_debug_fops);
return 0;
}
@@ -185,8 +222,13 @@ static int scom_debug_init(void)
return -1;
i = rc = 0;
- for_each_node_with_property(dn, "scom-controller")
- rc |= scom_debug_init_one(root, dn, i++);
+ for_each_node_with_property(dn, "scom-controller") {
+ int id = of_get_ibm_chip_id(dn);
+ if (id == -1)
+ id = i;
+ rc |= scom_debug_init_one(root, dn, id);
+ i++;
+ }
return rc;
}
diff --git a/arch/powerpc/sysdev/udbg_memcons.c b/arch/powerpc/sysdev/udbg_memcons.c
new file mode 100644
index 00000000000..9998c0de12d
--- /dev/null
+++ b/arch/powerpc/sysdev/udbg_memcons.c
@@ -0,0 +1,104 @@
+/*
+ * A udbg backend which logs messages and reads input from in memory
+ * buffers.
+ *
+ * The console output can be read from memcons_output which is a
+ * circular buffer whose next write position is stored in memcons.output_pos.
+ *
+ * Input may be passed by writing into the memcons_input buffer when it is
+ * empty. The input buffer is empty when both input_pos == input_start and
+ * *input_start == '\0'.
+ *
+ * Copyright (C) 2003-2005 Anton Blanchard and Milton Miller, IBM Corp
+ * Copyright (C) 2013 Alistair Popple, IBM Corp
+ *
+ * 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.
+ */
+
+#include <linux/kernel.h>
+#include <asm/barrier.h>
+#include <asm/page.h>
+#include <asm/processor.h>
+#include <asm/udbg.h>
+
+struct memcons {
+ char *output_start;
+ char *output_pos;
+ char *output_end;
+ char *input_start;
+ char *input_pos;
+ char *input_end;
+};
+
+static char memcons_output[CONFIG_PPC_MEMCONS_OUTPUT_SIZE];
+static char memcons_input[CONFIG_PPC_MEMCONS_INPUT_SIZE];
+
+struct memcons memcons = {
+ .output_start = memcons_output,
+ .output_pos = memcons_output,
+ .output_end = &memcons_output[CONFIG_PPC_MEMCONS_OUTPUT_SIZE],
+ .input_start = memcons_input,
+ .input_pos = memcons_input,
+ .input_end = &memcons_input[CONFIG_PPC_MEMCONS_INPUT_SIZE],
+};
+
+void memcons_putc(char c)
+{
+ char *new_output_pos;
+
+ *memcons.output_pos = c;
+ wmb();
+ new_output_pos = memcons.output_pos + 1;
+ if (new_output_pos >= memcons.output_end)
+ new_output_pos = memcons.output_start;
+
+ memcons.output_pos = new_output_pos;
+}
+
+int memcons_getc_poll(void)
+{
+ char c;
+ char *new_input_pos;
+
+ if (*memcons.input_pos) {
+ c = *memcons.input_pos;
+
+ new_input_pos = memcons.input_pos + 1;
+ if (new_input_pos >= memcons.input_end)
+ new_input_pos = memcons.input_start;
+ else if (*new_input_pos == '\0')
+ new_input_pos = memcons.input_start;
+
+ *memcons.input_pos = '\0';
+ wmb();
+ memcons.input_pos = new_input_pos;
+ return c;
+ }
+
+ return -1;
+}
+
+int memcons_getc(void)
+{
+ int c;
+
+ while (1) {
+ c = memcons_getc_poll();
+ if (c == -1)
+ cpu_relax();
+ else
+ break;
+ }
+
+ return c;
+}
+
+void udbg_init_memcons(void)
+{
+ udbg_putc = memcons_putc;
+ udbg_getc = memcons_getc;
+ udbg_getc_poll = memcons_getc_poll;
+}
diff --git a/arch/powerpc/sysdev/xics/icp-hv.c b/arch/powerpc/sysdev/xics/icp-hv.c
index df0fc582146..c1917cf67c3 100644
--- a/arch/powerpc/sysdev/xics/icp-hv.c
+++ b/arch/powerpc/sysdev/xics/icp-hv.c
@@ -12,7 +12,6 @@
#include <linux/irq.h>
#include <linux/smp.h>
#include <linux/interrupt.h>
-#include <linux/init.h>
#include <linux/cpu.h>
#include <linux/of.h>
diff --git a/arch/powerpc/sysdev/xics/icp-native.c b/arch/powerpc/sysdev/xics/icp-native.c
index 48861d3fcd0..de8d9483bbe 100644
--- a/arch/powerpc/sysdev/xics/icp-native.c
+++ b/arch/powerpc/sysdev/xics/icp-native.c
@@ -26,6 +26,7 @@
#include <asm/errno.h>
#include <asm/xics.h>
#include <asm/kvm_ppc.h>
+#include <asm/dbell.h>
struct icp_ipl {
union {
@@ -51,6 +52,12 @@ static struct icp_ipl __iomem *icp_native_regs[NR_CPUS];
static inline unsigned int icp_native_get_xirr(void)
{
int cpu = smp_processor_id();
+ unsigned int xirr;
+
+ /* Handled an interrupt latched by KVM */
+ xirr = kvmppc_get_xics_latch();
+ if (xirr)
+ return xirr;
return in_be32(&icp_native_regs[cpu]->xirr.word);
}
@@ -81,7 +88,7 @@ static void icp_native_set_cpu_priority(unsigned char cppr)
iosync();
}
-static void icp_native_eoi(struct irq_data *d)
+void icp_native_eoi(struct irq_data *d)
{
unsigned int hw_irq = (unsigned int)irqd_to_hwirq(d);
@@ -138,7 +145,14 @@ static unsigned int icp_native_get_irq(void)
static void icp_native_cause_ipi(int cpu, unsigned long data)
{
- icp_native_set_qirr(cpu, IPI_PRIORITY);
+ kvmppc_set_host_ipi(cpu, 1);
+#ifdef CONFIG_PPC_DOORBELL
+ if (cpu_has_feature(CPU_FTR_DBELL) &&
+ (cpumask_test_cpu(cpu, cpu_sibling_mask(smp_processor_id()))))
+ doorbell_cause_ipi(cpu, data);
+ else
+#endif
+ icp_native_set_qirr(cpu, IPI_PRIORITY);
}
void xics_wake_cpu(int cpu)
@@ -151,6 +165,7 @@ static irqreturn_t icp_native_ipi_action(int irq, void *dev_id)
{
int cpu = smp_processor_id();
+ kvmppc_set_host_ipi(cpu, 0);
icp_native_set_qirr(cpu, 0xff);
return smp_ipi_demux();
@@ -208,7 +223,7 @@ static int __init icp_native_init_one_node(struct device_node *np,
unsigned int *indx)
{
unsigned int ilen;
- const u32 *ireg;
+ const __be32 *ireg;
int i;
int reg_tuple_size;
int num_servers = 0;
diff --git a/arch/powerpc/sysdev/xics/ics-opal.c b/arch/powerpc/sysdev/xics/ics-opal.c
index f7e8609df0d..3c6ee1b64e5 100644
--- a/arch/powerpc/sysdev/xics/ics-opal.c
+++ b/arch/powerpc/sysdev/xics/ics-opal.c
@@ -112,6 +112,7 @@ static int ics_opal_set_affinity(struct irq_data *d,
bool force)
{
unsigned int hw_irq = (unsigned int)irqd_to_hwirq(d);
+ __be16 oserver;
int16_t server;
int8_t priority;
int64_t rc;
@@ -120,13 +121,13 @@ static int ics_opal_set_affinity(struct irq_data *d,
if (hw_irq == XICS_IPI || hw_irq == XICS_IRQ_SPURIOUS)
return -1;
- rc = opal_get_xive(hw_irq, &server, &priority);
+ rc = opal_get_xive(hw_irq, &oserver, &priority);
if (rc != OPAL_SUCCESS) {
- pr_err("%s: opal_set_xive(irq=%d [hw 0x%x] server=%x)"
- " error %lld\n",
- __func__, d->irq, hw_irq, server, rc);
+ pr_err("%s: opal_get_xive(irq=%d [hw 0x%x]) error %lld\n",
+ __func__, d->irq, hw_irq, rc);
return -1;
}
+ server = be16_to_cpu(oserver);
wanted_server = xics_get_irq_server(d->irq, cpumask, 1);
if (wanted_server < 0) {
@@ -148,7 +149,7 @@ static int ics_opal_set_affinity(struct irq_data *d,
__func__, d->irq, hw_irq, server, rc);
return -1;
}
- return 0;
+ return IRQ_SET_MASK_OK;
}
static struct irq_chip ics_opal_irq_chip = {
@@ -181,7 +182,7 @@ static int ics_opal_map(struct ics *ics, unsigned int virq)
{
unsigned int hw_irq = (unsigned int)virq_to_hw(virq);
int64_t rc;
- int16_t server;
+ __be16 server;
int8_t priority;
if (WARN_ON(hw_irq == XICS_IPI || hw_irq == XICS_IRQ_SPURIOUS))
@@ -201,7 +202,7 @@ static int ics_opal_map(struct ics *ics, unsigned int virq)
static void ics_opal_mask_unknown(struct ics *ics, unsigned long vec)
{
int64_t rc;
- int16_t server;
+ __be16 server;
int8_t priority;
/* Check if HAL knows about this interrupt */
@@ -215,14 +216,14 @@ static void ics_opal_mask_unknown(struct ics *ics, unsigned long vec)
static long ics_opal_get_server(struct ics *ics, unsigned long vec)
{
int64_t rc;
- int16_t server;
+ __be16 server;
int8_t priority;
/* Check if HAL knows about this interrupt */
rc = opal_get_xive(vec, &server, &priority);
if (rc != OPAL_SUCCESS)
return -1;
- return ics_opal_unmangle_server(server);
+ return ics_opal_unmangle_server(be16_to_cpu(server));
}
int __init ics_opal_init(void)
diff --git a/arch/powerpc/sysdev/xics/ics-rtas.c b/arch/powerpc/sysdev/xics/ics-rtas.c
index c782f85cf7e..936575d99c5 100644
--- a/arch/powerpc/sysdev/xics/ics-rtas.c
+++ b/arch/powerpc/sysdev/xics/ics-rtas.c
@@ -213,7 +213,7 @@ static int ics_rtas_host_match(struct ics *ics, struct device_node *node)
return !of_device_is_compatible(node, "chrp,iic");
}
-int ics_rtas_init(void)
+__init int ics_rtas_init(void)
{
ibm_get_xive = rtas_token("ibm,get-xive");
ibm_set_xive = rtas_token("ibm,set-xive");
diff --git a/arch/powerpc/sysdev/xics/xics-common.c b/arch/powerpc/sysdev/xics/xics-common.c
index 9049d9f4448..fe0cca47716 100644
--- a/arch/powerpc/sysdev/xics/xics-common.c
+++ b/arch/powerpc/sysdev/xics/xics-common.c
@@ -49,7 +49,7 @@ void xics_update_irq_servers(void)
int i, j;
struct device_node *np;
u32 ilen;
- const u32 *ireg;
+ const __be32 *ireg;
u32 hcpuid;
/* Find the server numbers for the boot cpu. */
@@ -75,8 +75,8 @@ void xics_update_irq_servers(void)
* default distribution server
*/
for (j = 0; j < i; j += 2) {
- if (ireg[j] == hcpuid) {
- xics_default_distrib_server = ireg[j+1];
+ if (be32_to_cpu(ireg[j]) == hcpuid) {
+ xics_default_distrib_server = be32_to_cpu(ireg[j+1]);
break;
}
}
@@ -383,7 +383,7 @@ void __init xics_register_ics(struct ics *ics)
static void __init xics_get_server_size(void)
{
struct device_node *np;
- const u32 *isize;
+ const __be32 *isize;
/* We fetch the interrupt server size from the first ICS node
* we find if any
@@ -394,7 +394,7 @@ static void __init xics_get_server_size(void)
isize = of_get_property(np, "ibm,interrupt-server#-size", NULL);
if (!isize)
return;
- xics_interrupt_server_size = *isize;
+ xics_interrupt_server_size = be32_to_cpu(*isize);
of_node_put(np);
}
diff --git a/arch/powerpc/sysdev/xilinx_intc.c b/arch/powerpc/sysdev/xilinx_intc.c
index 8d73c3c0bee..83f943a8e0d 100644
--- a/arch/powerpc/sysdev/xilinx_intc.c
+++ b/arch/powerpc/sysdev/xilinx_intc.c
@@ -23,6 +23,8 @@
#include <linux/kernel.h>
#include <linux/irq.h>
#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
#include <asm/io.h>
#include <asm/processor.h>
#include <asm/i8259.h>