* [PATCH 2/2] powerpc/watchdog: allow the e500 watchdog driver to be compiled as a module
From: Timur Tabi @ 2010-09-17 22:53 UTC (permalink / raw)
To: benh, linuxppc-dev, kumar.gala, linux-watchdog
In-Reply-To: <1284764008-19469-1-git-send-email-timur@freescale.com>
Register the __init and __exit functions in the PowerPC e500 watchdog driver
as module entry/exit functions, and modify the Kconfig entry.
Add a .release method for the PowerPC e500 watchdog driver, so that the
watchdog is disabled when the driver is closed.
Loosely based on original code from Jiang Yutang <b14898@freescale.com>.
Signed-off-by: Timur Tabi <timur@freescale.com>
---
This patch requires:
powerpc: export ppc_tb_freq so that modules can reference it
drivers/watchdog/Kconfig | 5 ++++-
drivers/watchdog/booke_wdt.c | 39 +++++++++++++++++++++++++++++++++++++--
2 files changed, 41 insertions(+), 3 deletions(-)
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 24efd8e..d9cf5a9 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -957,9 +957,12 @@ config PIKA_WDT
the Warp platform.
config BOOKE_WDT
- bool "PowerPC Book-E Watchdog Timer"
+ tristate "PowerPC Book-E Watchdog Timer"
depends on BOOKE || 4xx
---help---
+ Watchdog driver for PowerPC e500 chips, such as the Freescale
+ MPC85xx SOCs.
+
Please see Documentation/watchdog/watchdog-api.txt for
more information.
diff --git a/drivers/watchdog/booke_wdt.c b/drivers/watchdog/booke_wdt.c
index 3d49671..a989998 100644
--- a/drivers/watchdog/booke_wdt.c
+++ b/drivers/watchdog/booke_wdt.c
@@ -4,7 +4,7 @@
* Author: Matthew McClintock
* Maintainer: Kumar Gala <galak@kernel.crashing.org>
*
- * Copyright 2005, 2008 Freescale Semiconductor Inc.
+ * Copyright 2005, 2008, 2010 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
@@ -114,6 +114,27 @@ static void __booke_wdt_enable(void *data)
mtspr(SPRN_TCR, val);
}
+/**
+ * booke_wdt_disable - disable the watchdog on the given CPU
+ *
+ * This function is called on each CPU. It disables the watchdog on that CPU.
+ *
+ * TCR[WRC] cannot be changed once it has been set to non-zero, but we can
+ * effectively disable the watchdog by setting its period to the maximum value.
+ */
+static void __booke_wdt_disable(void *data)
+{
+ u32 val;
+
+ val = mfspr(SPRN_TCR);
+ val &= ~(TCR_WIE | WDTP_MASK);
+ mtspr(SPRN_TCR, val);
+
+ /* clear status to make sure nothing is pending */
+ __booke_wdt_ping(NULL);
+
+}
+
static ssize_t booke_wdt_write(struct file *file, const char __user *buf,
size_t count, loff_t *ppos)
{
@@ -193,12 +214,21 @@ static int booke_wdt_open(struct inode *inode, struct file *file)
return nonseekable_open(inode, file);
}
+static int booke_wdt_release(struct inode *inode, struct file *file)
+{
+ on_each_cpu(__booke_wdt_disable, NULL, 0);
+ booke_wdt_enabled = 0;
+
+ return 0;
+}
+
static const struct file_operations booke_wdt_fops = {
.owner = THIS_MODULE,
.llseek = no_llseek,
.write = booke_wdt_write,
.unlocked_ioctl = booke_wdt_ioctl,
.open = booke_wdt_open,
+ .release = booke_wdt_release,
};
static struct miscdevice booke_wdt_miscdev = {
@@ -237,4 +267,9 @@ static int __init booke_wdt_init(void)
return ret;
}
-device_initcall(booke_wdt_init);
+
+module_init(booke_wdt_init);
+module_exit(booke_wdt_exit);
+
+MODULE_DESCRIPTION("PowerPC Book-E watchdog driver");
+MODULE_LICENSE("GPL");
--
1.7.2.3
^ permalink raw reply related
* [PATCH 1/2] powerpc: export ppc_tb_freq so that modules can reference it
From: Timur Tabi @ 2010-09-17 22:53 UTC (permalink / raw)
To: benh, linuxppc-dev, kumar.gala, linux-watchdog
Export the global variable 'ppc_tb_freq', so that modules (like the Book-E
watchdog driver) can use it.
Signed-off-by: Timur Tabi <timur@freescale.com>
---
This export is necessary for the Book-E watchdog driver to be compiled as a
module. Since ppc_proc_freq is already exported, I figured it's okay for
ppc_tb_freq to be exported as well.
arch/powerpc/kernel/time.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
index 8533b3b..49aa130 100644
--- a/arch/powerpc/kernel/time.c
+++ b/arch/powerpc/kernel/time.c
@@ -163,6 +163,7 @@ static long timezone_offset;
unsigned long ppc_proc_freq;
EXPORT_SYMBOL(ppc_proc_freq);
unsigned long ppc_tb_freq;
+EXPORT_SYMBOL(ppc_tb_freq);
static DEFINE_PER_CPU(u64, last_jiffy);
--
1.7.2.3
^ permalink raw reply related
* Re: [PATCH RFCv2 0/5] CARMA Board Support
From: Ira W. Snyder @ 2010-09-17 18:41 UTC (permalink / raw)
To: linuxppc-dev, linux-kernel
In-Reply-To: <1283964082-30133-1-git-send-email-iws@ovro.caltech.edu>
On Wed, Sep 08, 2010 at 09:41:17AM -0700, Ira W. Snyder wrote:
> Hello everyone,
>
> This is the second posting of these drivers, taking into account comments
> from the RFCv1 post. Thanks to all that contributed.
>
Any comments on this series? I haven't heard anything for more than a
week. Is there somebody else I should be CC'ing?
Thanks,
Ira
^ permalink raw reply
* Re: Generating elf kernel ?
From: Scott Wood @ 2010-09-17 17:44 UTC (permalink / raw)
To: tiejun.chen; +Cc: linuxppc-dev, Guillaume Dargaud
In-Reply-To: <4C92CB51.5010008@windriver.com>
On Fri, 17 Sep 2010 09:58:41 +0800
"tiejun.chen" <tiejun.chen@windriver.com> wrote:
> Scott Wood wrote:
> > The guest OS *is* the same as native Linux, as far as TLB handling is
> > concerned.
>
> Looks you means the TLB exception handler should be same between the native and
> the guest OS. Right?
Yes.
> Here I assume we're talking about e500mc since as far as I know for Freescale
> only e500mc is designed to support virtual machine based on ISA 2.0.6.
Yes, though there's nothing preventing virtualization on cores without
category E.HV (KVM supports this) -- it's just slower.
> I also know all TLB exceptions can direct to the guest OS when we enable
> EPCR[DTLBGS|ITLBGS|DSIGS|ISIGS]. But some TLB instructions (i.e. tlbwe )are the
> privileged instructions. So the guest OS always trap into the hypervisor and
> then the hypervisor should complete the real action with appropriate physical
> address.
Yes, of course. But that's not the point. I was just using it as a
convenient example because that's what I've recently done ELF loading
with... There's no reason U-Boot couldn't do the same if its ELF
loader were updated to support device trees. Currently U-Boot loads
bootwrapperless uImages to physical address zero.
And FWIW, we have run setups where our hv loads Linux to true
physical zero (with the hv living elsewhere), not just guest physical.
-Scott
^ permalink raw reply
* Re: Initial kernel command string (Was: Generating elf kernel ?)
From: tiejun.chen @ 2010-09-17 9:46 UTC (permalink / raw)
To: Guillaume Dargaud; +Cc: linuxppc-dev
In-Reply-To: <201009171127.51017.dargaud@lpsc.in2p3.fr>
Guillaume Dargaud wrote:
> Thanks for helping about the elf issue, I got it running. The problem was that
> I wasn't using the proper file produced by make !
>
>
> Now I have a strange and probably simple problem that the Initial kernel
> command string is incorrect. I want, and I have set in the .config:
> CONFIG_CMDLINE="console=ttyUL0,115200 rw root=/dev/nfs ip=bootp"
I think you should modify the bootargs on your dts.
------
chosen {
bootargs = "console=ttyS0 root=/dev/ram";
linux,stdout-path = "/plb@0/serial@83e00000";
} ;
>
> But when my kernel boots it uses:
> console=ttyUL0 root=/dev/ram
>
> I can check:
> strings arch/powerpc/boot/simpleImage.virtex405-ml405.elf | grep console
> Vconsole=ttyUL0 root=/dev/ram
>
>
> Also my previous kernel would wait for 2 seconds at the beginning to allow me
> to change the initial command string via the serial port, but now it just runs
> right through. How can I enable this option ?
It's possible on PowerPC kernel :)
You can take a look at the file, arch/powerpc/boot/main.c.
------
static void prep_cmdline(void *chosen)
{
if (cmdline[0] == '\0')
getprop(chosen, "bootargs", cmdline, COMMAND_LINE_SIZE-1);
printf("\n\rLinux/PowerPC load: %s", cmdline);
/* If possible, edit the command line */
if (console_ops.edit_cmdline)
console_ops.edit_cmdline(cmdline, COMMAND_LINE_SIZE);
printf("\n\r");
.......
So you have to define one function, console_ops.edit_cmdline -->
serial_edit_cmdline. Or you can try bind this to your boot console ops directly.
Please refer to the file, arch/powerpc/boot/serial.c.
Cheers!
Tiejun
>
> On the plus side it boots in .5 seconds !
>
> Here's my .config:
> CONFIG_40x=y
> CONFIG_4xx=y
> CONFIG_PPC_MMU_NOHASH=y
> CONFIG_PPC_MMU_NOHASH_32=y
> CONFIG_NOT_COHERENT_CACHE=y
> CONFIG_PPC32=y
> CONFIG_WORD_SIZE=32
> CONFIG_MMU=y
> CONFIG_GENERIC_CMOS_UPDATE=y
> CONFIG_GENERIC_TIME=y
> CONFIG_GENERIC_TIME_VSYSCALL=y
> CONFIG_GENERIC_CLOCKEVENTS=y
> CONFIG_GENERIC_HARDIRQS=y
> CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
> CONFIG_IRQ_PER_CPU=y
> CONFIG_NR_IRQS=512
> CONFIG_STACKTRACE_SUPPORT=y
> CONFIG_HAVE_LATENCYTOP_SUPPORT=y
> CONFIG_TRACE_IRQFLAGS_SUPPORT=y
> CONFIG_LOCKDEP_SUPPORT=y
> CONFIG_RWSEM_XCHGADD_ALGORITHM=y
> CONFIG_ARCH_HAS_ILOG2_U32=y
> CONFIG_GENERIC_HWEIGHT=y
> CONFIG_GENERIC_FIND_NEXT_BIT=y
> CONFIG_GENERIC_GPIO=y
> CONFIG_PPC=y
> CONFIG_EARLY_PRINTK=y
> CONFIG_GENERIC_NVRAM=y
> CONFIG_SCHED_OMIT_FRAME_POINTER=y
> CONFIG_ARCH_MAY_HAVE_PC_FDC=y
> CONFIG_PPC_OF=y
> CONFIG_OF=y
> CONFIG_PPC_UDBG_16550=y
> CONFIG_AUDIT_ARCH=y
> CONFIG_GENERIC_BUG=y
> CONFIG_DTC=y
> CONFIG_DEFAULT_UIMAGE=y
> CONFIG_ARCH_HIBERNATION_POSSIBLE=y
> CONFIG_PPC_DCR_NATIVE=y
> CONFIG_PPC_DCR_MMIO=y
> CONFIG_PPC_DCR=y
> CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
> CONFIG_PPC_ADV_DEBUG_REGS=y
> CONFIG_PPC_ADV_DEBUG_IACS=2
> CONFIG_PPC_ADV_DEBUG_DACS=2
> CONFIG_PPC_ADV_DEBUG_DVCS=0
> CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
> CONFIG_CONSTRUCTORS=y
> CONFIG_EXPERIMENTAL=y
> CONFIG_BROKEN_ON_SMP=y
> CONFIG_INIT_ENV_ARG_LIMIT=32
> CONFIG_LOCALVERSION=""
> CONFIG_TREE_RCU=y
> CONFIG_RCU_FANOUT=32
> CONFIG_IKCONFIG=y
> CONFIG_IKCONFIG_PROC=y
> CONFIG_LOG_BUF_SHIFT=14
> CONFIG_NAMESPACES=y
> CONFIG_CC_OPTIMIZE_FOR_SIZE=y
> CONFIG_SYSCTL=y
> CONFIG_ANON_INODES=y
> CONFIG_SYSCTL_SYSCALL=y
> CONFIG_KALLSYMS=y
> CONFIG_HOTPLUG=y
> CONFIG_PRINTK=y
> CONFIG_BUG=y
> CONFIG_ELF_CORE=y
> CONFIG_BASE_FULL=y
> CONFIG_FUTEX=y
> CONFIG_EPOLL=y
> CONFIG_SIGNALFD=y
> CONFIG_TIMERFD=y
> CONFIG_EVENTFD=y
> CONFIG_SHMEM=y
> CONFIG_AIO=y
> CONFIG_HAVE_PERF_EVENTS=y
> CONFIG_PERF_EVENTS=y
> CONFIG_VM_EVENT_COUNTERS=y
> CONFIG_COMPAT_BRK=y
> CONFIG_SLAB=y
> CONFIG_HAVE_OPROFILE=y
> CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
> CONFIG_HAVE_IOREMAP_PROT=y
> CONFIG_HAVE_KPROBES=y
> CONFIG_HAVE_KRETPROBES=y
> CONFIG_HAVE_ARCH_TRACEHOOK=y
> CONFIG_HAVE_DMA_ATTRS=y
> CONFIG_HAVE_DMA_API_DEBUG=y
> CONFIG_SLABINFO=y
> CONFIG_RT_MUTEXES=y
> CONFIG_BASE_SMALL=0
> CONFIG_MODULES=y
> CONFIG_MODULE_UNLOAD=y
> CONFIG_MODULE_FORCE_UNLOAD=y
> CONFIG_BLOCK=y
> CONFIG_IOSCHED_NOOP=y
> CONFIG_IOSCHED_DEADLINE=y
> CONFIG_IOSCHED_CFQ=y
> CONFIG_DEFAULT_CFQ=y
> CONFIG_DEFAULT_IOSCHED="cfq"
> CONFIG_INLINE_SPIN_UNLOCK=y
> CONFIG_INLINE_SPIN_UNLOCK_IRQ=y
> CONFIG_INLINE_READ_UNLOCK=y
> CONFIG_INLINE_READ_UNLOCK_IRQ=y
> CONFIG_INLINE_WRITE_UNLOCK=y
> CONFIG_INLINE_WRITE_UNLOCK_IRQ=y
> CONFIG_PPC4xx_GPIO=y
> CONFIG_XILINX_VIRTEX=y
> CONFIG_XILINX_VIRTEX_GENERIC_BOARD=y
> CONFIG_PPC40x_SIMPLE=y
> CONFIG_XILINX_VIRTEX_II_PRO=y
> CONFIG_XILINX_VIRTEX_4_FX=y
> CONFIG_IBM405_ERR77=y
> CONFIG_IBM405_ERR51=y
> CONFIG_SIMPLE_GPIO=y
> CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
> CONFIG_HZ_250=y
> CONFIG_HZ=250
> CONFIG_PREEMPT_VOLUNTARY=y
> CONFIG_BINFMT_ELF=y
> CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
> CONFIG_ARCH_HAS_WALK_MEMORY=y
> CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
> CONFIG_SPARSE_IRQ=y
> CONFIG_MAX_ACTIVE_REGIONS=32
> CONFIG_ARCH_FLATMEM_ENABLE=y
> CONFIG_ARCH_POPULATES_NODE_MAP=y
> CONFIG_SELECT_MEMORY_MODEL=y
> CONFIG_FLATMEM_MANUAL=y
> CONFIG_FLATMEM=y
> CONFIG_FLAT_NODE_MEM_MAP=y
> CONFIG_PAGEFLAGS_EXTENDED=y
> CONFIG_SPLIT_PTLOCK_CPUS=4
> CONFIG_ZONE_DMA_FLAG=1
> CONFIG_BOUNCE=y
> CONFIG_VIRT_TO_BUS=y
> CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
> CONFIG_PPC_4K_PAGES=y
> CONFIG_FORCE_MAX_ZONEORDER=11
> CONFIG_PROC_DEVICETREE=y
> CONFIG_CMDLINE_BOOL=y
> CONFIG_CMDLINE="console=ttyUL0,115200 rw root=/dev/nfs ip=bootp"
> CONFIG_EXTRA_TARGETS=""
> CONFIG_ISA_DMA_API=y
> CONFIG_ZONE_DMA=y
> CONFIG_NEED_DMA_MAP_STATE=y
> CONFIG_4xx_SOC=y
> CONFIG_PPC_PCI_CHOICE=y
> CONFIG_ADVANCED_OPTIONS=y
> CONFIG_LOWMEM_SIZE=0x30000000
> CONFIG_PAGE_OFFSET=0xc0000000
> CONFIG_KERNEL_START=0xc0000000
> CONFIG_PHYSICAL_START=0x00000000
> CONFIG_TASK_SIZE=0xc0000000
> CONFIG_CONSISTENT_SIZE=0x00200000
> CONFIG_NET=y
> CONFIG_PACKET=y
> CONFIG_UNIX=y
> CONFIG_INET=y
> CONFIG_IP_FIB_HASH=y
> CONFIG_IP_PNP=y
> CONFIG_IP_PNP_DHCP=y
> CONFIG_IP_PNP_BOOTP=y
> CONFIG_INET_DIAG=y
> CONFIG_INET_TCP_DIAG=y
> CONFIG_TCP_CONG_CUBIC=y
> CONFIG_DEFAULT_TCP_CONG="cubic"
> CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
> CONFIG_STANDALONE=y
> CONFIG_PREVENT_FIRMWARE_BUILD=y
> CONFIG_FW_LOADER=y
> CONFIG_FIRMWARE_IN_KERNEL=y
> CONFIG_EXTRA_FIRMWARE=""
> CONFIG_OF_FLATTREE=y
> CONFIG_OF_DYNAMIC=y
> CONFIG_OF_DEVICE=y
> CONFIG_OF_GPIO=y
> CONFIG_XILINX_DRIVERS=y
> CONFIG_NEED_XILINX_LLDMA=y
> CONFIG_HAVE_IDE=y
> CONFIG_SCSI_MOD=y
> CONFIG_NETDEVICES=y
> CONFIG_NETDEV_1000=y
> CONFIG_XILINX_LLTEMAC=y
> CONFIG_XILINX_LLTEMAC_MARVELL_88E1111_GMII=y
> CONFIG_INPUT=y
> CONFIG_INPUT_MOUSEDEV=y
> CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
> CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
> CONFIG_SERIO=y
> CONFIG_SERIO_SERPORT=y
> CONFIG_VT=y
> CONFIG_CONSOLE_TRANSLATIONS=y
> CONFIG_VT_CONSOLE=y
> CONFIG_HW_CONSOLE=y
> CONFIG_DEVKMEM=y
> CONFIG_SERIAL_UARTLITE=y
> CONFIG_SERIAL_UARTLITE_CONSOLE=y
> CONFIG_SERIAL_CORE=y
> CONFIG_SERIAL_CORE_CONSOLE=y
> CONFIG_UNIX98_PTYS=y
> CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
> CONFIG_ARCH_REQUIRE_GPIOLIB=y
> CONFIG_GPIOLIB=y
> CONFIG_GPIO_SYSFS=y
> CONFIG_GPIO_XILINX=y
> CONFIG_SSB_POSSIBLE=y
> CONFIG_DUMMY_CONSOLE=y
> CONFIG_XILINX_EDK=y
> CONFIG_UIO=y
> CONFIG_UIO_PDRV=y
> CONFIG_UIO_PDRV_GENIRQ=y
> CONFIG_FILE_LOCKING=y
> CONFIG_PROC_FS=y
> CONFIG_PROC_SYSCTL=y
> CONFIG_PROC_PAGE_MONITOR=y
> CONFIG_SYSFS=y
> CONFIG_CONFIGFS_FS=y
> CONFIG_NETWORK_FILESYSTEMS=y
> CONFIG_NFS_FS=y
> CONFIG_NFS_V3=y
> CONFIG_ROOT_NFS=y
> CONFIG_LOCKD=y
> CONFIG_LOCKD_V4=y
> CONFIG_NFS_COMMON=y
> CONFIG_SUNRPC=y
> CONFIG_MSDOS_PARTITION=y
> CONFIG_BITREVERSE=y
> CONFIG_GENERIC_FIND_LAST_BIT=y
> CONFIG_CRC_CCITT=y
> CONFIG_CRC32=y
> CONFIG_HAS_IOMEM=y
> CONFIG_HAS_IOPORT=y
> CONFIG_HAS_DMA=y
> CONFIG_HAVE_LMB=y
> CONFIG_NLATTR=y
> CONFIG_GENERIC_ATOMIC64=y
> CONFIG_PRINTK_TIME=y
> CONFIG_ENABLE_WARN_DEPRECATED=y
> CONFIG_ENABLE_MUST_CHECK=y
> CONFIG_FRAME_WARN=1024
> CONFIG_DEBUG_BUGVERBOSE=y
> CONFIG_DEBUG_MEMORY_INIT=y
> CONFIG_RCU_CPU_STALL_DETECTOR=y
> CONFIG_SYSCTL_SYSCALL_CHECK=y
> CONFIG_HAVE_FUNCTION_TRACER=y
> CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
> CONFIG_HAVE_DYNAMIC_FTRACE=y
> CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
> CONFIG_TRACING_SUPPORT=y
> CONFIG_HAVE_ARCH_KGDB=y
> CONFIG_PPC_WERROR=y
> CONFIG_PRINT_STACK_DEPTH=64
> CONFIG_DEFAULT_SECURITY_DAC=y
> CONFIG_DEFAULT_SECURITY=""
> CONFIG_CRYPTO=y
> CONFIG_CRYPTO_ALGAPI=y
> CONFIG_CRYPTO_ALGAPI2=y
> CONFIG_CRYPTO_RNG=y
> CONFIG_CRYPTO_RNG2=y
> CONFIG_CRYPTO_AES=y
> CONFIG_CRYPTO_ANSI_CPRNG=y
>
^ permalink raw reply
* Initial kernel command string (Was: Generating elf kernel ?)
From: Guillaume Dargaud @ 2010-09-17 9:27 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <4C91CC78.2020802@windriver.com>
Thanks for helping about the elf issue, I got it running. The problem was that
I wasn't using the proper file produced by make !
Now I have a strange and probably simple problem that the Initial kernel
command string is incorrect. I want, and I have set in the .config:
CONFIG_CMDLINE="console=ttyUL0,115200 rw root=/dev/nfs ip=bootp"
But when my kernel boots it uses:
console=ttyUL0 root=/dev/ram
I can check:
strings arch/powerpc/boot/simpleImage.virtex405-ml405.elf | grep console
Vconsole=ttyUL0 root=/dev/ram
Also my previous kernel would wait for 2 seconds at the beginning to allow me
to change the initial command string via the serial port, but now it just runs
right through. How can I enable this option ?
On the plus side it boots in .5 seconds !
Here's my .config:
CONFIG_40x=y
CONFIG_4xx=y
CONFIG_PPC_MMU_NOHASH=y
CONFIG_PPC_MMU_NOHASH_32=y
CONFIG_NOT_COHERENT_CACHE=y
CONFIG_PPC32=y
CONFIG_WORD_SIZE=32
CONFIG_MMU=y
CONFIG_GENERIC_CMOS_UPDATE=y
CONFIG_GENERIC_TIME=y
CONFIG_GENERIC_TIME_VSYSCALL=y
CONFIG_GENERIC_CLOCKEVENTS=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
CONFIG_IRQ_PER_CPU=y
CONFIG_NR_IRQS=512
CONFIG_STACKTRACE_SUPPORT=y
CONFIG_HAVE_LATENCYTOP_SUPPORT=y
CONFIG_TRACE_IRQFLAGS_SUPPORT=y
CONFIG_LOCKDEP_SUPPORT=y
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
CONFIG_ARCH_HAS_ILOG2_U32=y
CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_GENERIC_GPIO=y
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
CONFIG_GENERIC_NVRAM=y
CONFIG_SCHED_OMIT_FRAME_POINTER=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_PPC_OF=y
CONFIG_OF=y
CONFIG_PPC_UDBG_16550=y
CONFIG_AUDIT_ARCH=y
CONFIG_GENERIC_BUG=y
CONFIG_DTC=y
CONFIG_DEFAULT_UIMAGE=y
CONFIG_ARCH_HIBERNATION_POSSIBLE=y
CONFIG_PPC_DCR_NATIVE=y
CONFIG_PPC_DCR_MMIO=y
CONFIG_PPC_DCR=y
CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
CONFIG_PPC_ADV_DEBUG_REGS=y
CONFIG_PPC_ADV_DEBUG_IACS=2
CONFIG_PPC_ADV_DEBUG_DACS=2
CONFIG_PPC_ADV_DEBUG_DVCS=0
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
CONFIG_CONSTRUCTORS=y
CONFIG_EXPERIMENTAL=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
CONFIG_LOCALVERSION=""
CONFIG_TREE_RCU=y
CONFIG_RCU_FANOUT=32
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_LOG_BUF_SHIFT=14
CONFIG_NAMESPACES=y
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
CONFIG_SYSCTL=y
CONFIG_ANON_INODES=y
CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
CONFIG_ELF_CORE=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SIGNALFD=y
CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
CONFIG_AIO=y
CONFIG_HAVE_PERF_EVENTS=y
CONFIG_PERF_EVENTS=y
CONFIG_VM_EVENT_COUNTERS=y
CONFIG_COMPAT_BRK=y
CONFIG_SLAB=y
CONFIG_HAVE_OPROFILE=y
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
CONFIG_HAVE_IOREMAP_PROT=y
CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
CONFIG_HAVE_ARCH_TRACEHOOK=y
CONFIG_HAVE_DMA_ATTRS=y
CONFIG_HAVE_DMA_API_DEBUG=y
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
CONFIG_MODULE_FORCE_UNLOAD=y
CONFIG_BLOCK=y
CONFIG_IOSCHED_NOOP=y
CONFIG_IOSCHED_DEADLINE=y
CONFIG_IOSCHED_CFQ=y
CONFIG_DEFAULT_CFQ=y
CONFIG_DEFAULT_IOSCHED="cfq"
CONFIG_INLINE_SPIN_UNLOCK=y
CONFIG_INLINE_SPIN_UNLOCK_IRQ=y
CONFIG_INLINE_READ_UNLOCK=y
CONFIG_INLINE_READ_UNLOCK_IRQ=y
CONFIG_INLINE_WRITE_UNLOCK=y
CONFIG_INLINE_WRITE_UNLOCK_IRQ=y
CONFIG_PPC4xx_GPIO=y
CONFIG_XILINX_VIRTEX=y
CONFIG_XILINX_VIRTEX_GENERIC_BOARD=y
CONFIG_PPC40x_SIMPLE=y
CONFIG_XILINX_VIRTEX_II_PRO=y
CONFIG_XILINX_VIRTEX_4_FX=y
CONFIG_IBM405_ERR77=y
CONFIG_IBM405_ERR51=y
CONFIG_SIMPLE_GPIO=y
CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
CONFIG_HZ_250=y
CONFIG_HZ=250
CONFIG_PREEMPT_VOLUNTARY=y
CONFIG_BINFMT_ELF=y
CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
CONFIG_ARCH_HAS_WALK_MEMORY=y
CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
CONFIG_SPARSE_IRQ=y
CONFIG_MAX_ACTIVE_REGIONS=32
CONFIG_ARCH_FLATMEM_ENABLE=y
CONFIG_ARCH_POPULATES_NODE_MAP=y
CONFIG_SELECT_MEMORY_MODEL=y
CONFIG_FLATMEM_MANUAL=y
CONFIG_FLATMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
CONFIG_PPC_4K_PAGES=y
CONFIG_FORCE_MAX_ZONEORDER=11
CONFIG_PROC_DEVICETREE=y
CONFIG_CMDLINE_BOOL=y
CONFIG_CMDLINE="console=ttyUL0,115200 rw root=/dev/nfs ip=bootp"
CONFIG_EXTRA_TARGETS=""
CONFIG_ISA_DMA_API=y
CONFIG_ZONE_DMA=y
CONFIG_NEED_DMA_MAP_STATE=y
CONFIG_4xx_SOC=y
CONFIG_PPC_PCI_CHOICE=y
CONFIG_ADVANCED_OPTIONS=y
CONFIG_LOWMEM_SIZE=0x30000000
CONFIG_PAGE_OFFSET=0xc0000000
CONFIG_KERNEL_START=0xc0000000
CONFIG_PHYSICAL_START=0x00000000
CONFIG_TASK_SIZE=0xc0000000
CONFIG_CONSISTENT_SIZE=0x00200000
CONFIG_NET=y
CONFIG_PACKET=y
CONFIG_UNIX=y
CONFIG_INET=y
CONFIG_IP_FIB_HASH=y
CONFIG_IP_PNP=y
CONFIG_IP_PNP_DHCP=y
CONFIG_IP_PNP_BOOTP=y
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
CONFIG_TCP_CONG_CUBIC=y
CONFIG_DEFAULT_TCP_CONG="cubic"
CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
CONFIG_STANDALONE=y
CONFIG_PREVENT_FIRMWARE_BUILD=y
CONFIG_FW_LOADER=y
CONFIG_FIRMWARE_IN_KERNEL=y
CONFIG_EXTRA_FIRMWARE=""
CONFIG_OF_FLATTREE=y
CONFIG_OF_DYNAMIC=y
CONFIG_OF_DEVICE=y
CONFIG_OF_GPIO=y
CONFIG_XILINX_DRIVERS=y
CONFIG_NEED_XILINX_LLDMA=y
CONFIG_HAVE_IDE=y
CONFIG_SCSI_MOD=y
CONFIG_NETDEVICES=y
CONFIG_NETDEV_1000=y
CONFIG_XILINX_LLTEMAC=y
CONFIG_XILINX_LLTEMAC_MARVELL_88E1111_GMII=y
CONFIG_INPUT=y
CONFIG_INPUT_MOUSEDEV=y
CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
CONFIG_SERIO=y
CONFIG_SERIO_SERPORT=y
CONFIG_VT=y
CONFIG_CONSOLE_TRANSLATIONS=y
CONFIG_VT_CONSOLE=y
CONFIG_HW_CONSOLE=y
CONFIG_DEVKMEM=y
CONFIG_SERIAL_UARTLITE=y
CONFIG_SERIAL_UARTLITE_CONSOLE=y
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_UNIX98_PTYS=y
CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
CONFIG_ARCH_REQUIRE_GPIOLIB=y
CONFIG_GPIOLIB=y
CONFIG_GPIO_SYSFS=y
CONFIG_GPIO_XILINX=y
CONFIG_SSB_POSSIBLE=y
CONFIG_DUMMY_CONSOLE=y
CONFIG_XILINX_EDK=y
CONFIG_UIO=y
CONFIG_UIO_PDRV=y
CONFIG_UIO_PDRV_GENIRQ=y
CONFIG_FILE_LOCKING=y
CONFIG_PROC_FS=y
CONFIG_PROC_SYSCTL=y
CONFIG_PROC_PAGE_MONITOR=y
CONFIG_SYSFS=y
CONFIG_CONFIGFS_FS=y
CONFIG_NETWORK_FILESYSTEMS=y
CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
CONFIG_ROOT_NFS=y
CONFIG_LOCKD=y
CONFIG_LOCKD_V4=y
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
CONFIG_MSDOS_PARTITION=y
CONFIG_BITREVERSE=y
CONFIG_GENERIC_FIND_LAST_BIT=y
CONFIG_CRC_CCITT=y
CONFIG_CRC32=y
CONFIG_HAS_IOMEM=y
CONFIG_HAS_IOPORT=y
CONFIG_HAS_DMA=y
CONFIG_HAVE_LMB=y
CONFIG_NLATTR=y
CONFIG_GENERIC_ATOMIC64=y
CONFIG_PRINTK_TIME=y
CONFIG_ENABLE_WARN_DEPRECATED=y
CONFIG_ENABLE_MUST_CHECK=y
CONFIG_FRAME_WARN=1024
CONFIG_DEBUG_BUGVERBOSE=y
CONFIG_DEBUG_MEMORY_INIT=y
CONFIG_RCU_CPU_STALL_DETECTOR=y
CONFIG_SYSCTL_SYSCALL_CHECK=y
CONFIG_HAVE_FUNCTION_TRACER=y
CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
CONFIG_HAVE_DYNAMIC_FTRACE=y
CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
CONFIG_TRACING_SUPPORT=y
CONFIG_HAVE_ARCH_KGDB=y
CONFIG_PPC_WERROR=y
CONFIG_PRINT_STACK_DEPTH=64
CONFIG_DEFAULT_SECURITY_DAC=y
CONFIG_DEFAULT_SECURITY=""
CONFIG_CRYPTO=y
CONFIG_CRYPTO_ALGAPI=y
CONFIG_CRYPTO_ALGAPI2=y
CONFIG_CRYPTO_RNG=y
CONFIG_CRYPTO_RNG2=y
CONFIG_CRYPTO_AES=y
CONFIG_CRYPTO_ANSI_CPRNG=y
--
Guillaume Dargaud
http://www.gdargaud.net/
^ permalink raw reply
* Re: linux support for freescale e5500 core?
From: Kumar Gala @ 2010-09-17 7:39 UTC (permalink / raw)
To: Chris Friesen; +Cc: linuxppc-dev, paulus, Scott Wood, timur
In-Reply-To: <4C930C55.5030008@genband.com>
On Sep 17, 2010, at 1:36 AM, Chris Friesen wrote:
> On 09/16/2010 11:33 PM, Benjamin Herrenschmidt wrote:
>> On Fri, 2010-09-17 at 00:17 -0500, Kumar Gala wrote:
>>> Not sure how the 970 bit worked, but this seems a bit problematic =
for
>>> switching between kernel and application for how we do this on
>>> e500mc/e5500. We'd have to touch the control bit on every exception
>>> path which seems ugly to me.
>>=20
>> Unless the kernel uses dcbzl (feature fixup replacement ?)
>>=20
>> In that case it's on context switch only.
>=20
> This is basically what we did. Kernel and system libraries (glibc and
> friends) always use dcbzl, process flag indicates compatibility, touch
> the control bit on task context switch if the prev and next processes
> have different compatibility modes.
>=20
> On the 970 you have to invalidate the entire icache whenever you =
change
> the control bit. This is a pain involving a loop that calls icbi on =
512
> cachelines.
I'm pretty sure on e500mc / e5500 you only need proper sync/isync/msync =
after the change in the control register.
- k=
^ permalink raw reply
* [PATCH 3/3 v4] P4080/mtd: Fix the freescale lbc issue with 36bit mode
From: Roy Zang @ 2010-09-17 7:01 UTC (permalink / raw)
To: linux-mtd; +Cc: B07421, dedekind1, B25806, linuxppc-dev, akpm, dwmw2, B11780
In-Reply-To: <1284706869-12555-2-git-send-email-tie-fei.zang@freescale.com>
From: Lan Chunhe-B25806 <b25806@freescale.com>
When system uses 36bit physical address, res.start is 36bit
physical address. But the function of in_be32 returns 32bit
physical address. Then both of them compared each other is
wrong. So by converting the address of res.start into
the right format fixes this issue.
Signed-off-by: Lan Chunhe-B25806 <b25806@freescale.com>
Signed-off-by: Roy Zang <tie-fei.zang@freescale.com>
Reviewed-by: Anton Vorontsov <cbouatmailru@gmail.com>
---
arch/powerpc/include/asm/fsl_lbc.h | 1 +
arch/powerpc/sysdev/fsl_lbc.c | 23 ++++++++++++++++++++++-
drivers/mtd/nand/fsl_elbc_nand.c | 2 +-
3 files changed, 24 insertions(+), 2 deletions(-)
diff --git a/arch/powerpc/include/asm/fsl_lbc.h b/arch/powerpc/include/asm/fsl_lbc.h
index db94698..ad663e8 100644
--- a/arch/powerpc/include/asm/fsl_lbc.h
+++ b/arch/powerpc/include/asm/fsl_lbc.h
@@ -246,6 +246,7 @@ struct fsl_upm {
int width;
};
+extern u32 fsl_lbc_addr(phys_addr_t addr_base);
extern int fsl_lbc_find(phys_addr_t addr_base);
extern int fsl_upm_find(phys_addr_t addr_base, struct fsl_upm *upm);
diff --git a/arch/powerpc/sysdev/fsl_lbc.c b/arch/powerpc/sysdev/fsl_lbc.c
index 4920cd3..32c2120 100644
--- a/arch/powerpc/sysdev/fsl_lbc.c
+++ b/arch/powerpc/sysdev/fsl_lbc.c
@@ -34,6 +34,27 @@ struct fsl_lbc_ctrl *fsl_lbc_ctrl_dev;
EXPORT_SYMBOL(fsl_lbc_ctrl_dev);
/**
+ * fsl_lbc_addr - convert the base address
+ * @addr_base: base address of the memory bank
+ *
+ * This function converts a base address of lbc into the right format for the
+ * BR register. If the SOC has eLBC then it returns 32bit physical address
+ * else it convers a 34bit local bus physical address to correct format of
+ * 32bit address for BR register (Example: MPC8641).
+ */
+u32 fsl_lbc_addr(phys_addr_t addr_base)
+{
+ struct device_node *np = fsl_lbc_ctrl_dev->dev->of_node;
+ u32 addr = addr_base & 0xffff8000;
+
+ if (of_device_is_compatible(np, "fsl,elbc"))
+ return addr;
+
+ return addr | ((addr_base & 0x300000000ull) >> 19);
+}
+EXPORT_SYMBOL(fsl_lbc_addr);
+
+/**
* fsl_lbc_find - find Localbus bank
* @addr_base: base address of the memory bank
*
@@ -55,7 +76,7 @@ int fsl_lbc_find(phys_addr_t addr_base)
__be32 br = in_be32(&lbc->bank[i].br);
__be32 or = in_be32(&lbc->bank[i].or);
- if (br & BR_V && (br & or & BR_BA) == addr_base)
+ if (br & BR_V && (br & or & BR_BA) == fsl_lbc_addr(addr_base))
return i;
}
diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c
index 76ffd24..227618b 100644
--- a/drivers/mtd/nand/fsl_elbc_nand.c
+++ b/drivers/mtd/nand/fsl_elbc_nand.c
@@ -865,7 +865,7 @@ static int __devinit fsl_elbc_nand_probe(struct platform_device *dev)
(in_be32(&lbc->bank[bank].br) & BR_MSEL) == BR_MS_FCM &&
(in_be32(&lbc->bank[bank].br) &
in_be32(&lbc->bank[bank].or) & BR_BA)
- == res.start)
+ == fsl_lbc_addr(res.start))
break;
if (bank >= MAX_BANKS) {
--
1.5.6.5
^ permalink raw reply related
* [PATCH 1/3 v4] P4080/eLBC: Make Freescale elbc interrupt common to elbc devices
From: Roy Zang @ 2010-09-17 7:01 UTC (permalink / raw)
To: linux-mtd; +Cc: B07421, dedekind1, B25806, linuxppc-dev, akpm, dwmw2, B11780
From: Lan Chunhe-B25806 <b25806@freescale.com>
Move Freescale elbc interrupt from nand dirver to elbc driver.
Then all elbc devices can use the interrupt instead of ONLY nand.
Signed-off-by: Lan Chunhe-B25806 <b25806@freescale.com>
Signed-off-by: Roy Zang <tie-fei.zang@freescale.com>
---
Comparing v3:
1. minor fix from type unsigned int to u32
2. fix platform_driver issue.
3. add mutex for nand probe
arch/powerpc/Kconfig | 7 +-
arch/powerpc/include/asm/fsl_lbc.h | 31 +++++-
arch/powerpc/sysdev/fsl_lbc.c | 246 ++++++++++++++++++++++++++++++------
3 files changed, 242 insertions(+), 42 deletions(-)
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 631e5a0..44df1ba 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -687,9 +687,12 @@ config 4xx_SOC
bool
config FSL_LBC
- bool
+ bool "Freescale Local Bus support"
+ depends on FSL_SOC
help
- Freescale Localbus support
+ Enables reporting of errors from the Freescale local bus
+ controller. Also contains some common code used by
+ drivers for specific local bus peripherals.
config FSL_GTM
bool
diff --git a/arch/powerpc/include/asm/fsl_lbc.h b/arch/powerpc/include/asm/fsl_lbc.h
index 1b5a210..db94698 100644
--- a/arch/powerpc/include/asm/fsl_lbc.h
+++ b/arch/powerpc/include/asm/fsl_lbc.h
@@ -1,9 +1,10 @@
/* Freescale Local Bus Controller
*
- * Copyright (c) 2006-2007 Freescale Semiconductor
+ * Copyright (c) 2006-2007, 2010 Freescale Semiconductor
*
* Authors: Nick Spence <nick.spence@freescale.com>,
* Scott Wood <scottwood@freescale.com>
+ * Jack Lan <jack.lan@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
@@ -125,13 +126,23 @@ struct fsl_lbc_regs {
#define LTESR_ATMW 0x00800000
#define LTESR_ATMR 0x00400000
#define LTESR_CS 0x00080000
+#define LTESR_UPM 0x00000002
#define LTESR_CC 0x00000001
#define LTESR_NAND_MASK (LTESR_FCT | LTESR_PAR | LTESR_CC)
+#define LTESR_MASK (LTESR_BM | LTESR_FCT | LTESR_PAR | LTESR_WP \
+ | LTESR_ATMW | LTESR_ATMR | LTESR_CS | LTESR_UPM \
+ | LTESR_CC)
+#define LTESR_CLEAR 0xFFFFFFFF
+#define LTECCR_CLEAR 0xFFFFFFFF
+#define LTESR_STATUS LTESR_MASK
+#define LTEIR_ENABLE LTESR_MASK
+#define LTEDR_ENABLE 0x00000000
__be32 ltedr; /**< Transfer Error Disable Register */
__be32 lteir; /**< Transfer Error Interrupt Register */
__be32 lteatr; /**< Transfer Error Attributes Register */
__be32 ltear; /**< Transfer Error Address Register */
- u8 res6[0xC];
+ __be32 lteccr; /**< Transfer Error ECC Register */
+ u8 res6[0x8];
__be32 lbcr; /**< Configuration Register */
#define LBCR_LDIS 0x80000000
#define LBCR_LDIS_SHIFT 31
@@ -265,7 +276,23 @@ static inline void fsl_upm_end_pattern(struct fsl_upm *upm)
cpu_relax();
}
+/* overview of the fsl lbc controller */
+
+struct fsl_lbc_ctrl {
+ /* device info */
+ struct device *dev;
+ struct fsl_lbc_regs __iomem *regs;
+ int irq;
+ wait_queue_head_t irq_wait;
+ spinlock_t lock;
+ void *nand;
+
+ /* status read from LTESR by irq handler */
+ unsigned int irq_status;
+};
+
extern int fsl_upm_run_pattern(struct fsl_upm *upm, void __iomem *io_base,
u32 mar);
+extern struct fsl_lbc_ctrl *fsl_lbc_ctrl_dev;
#endif /* __ASM_FSL_LBC_H */
diff --git a/arch/powerpc/sysdev/fsl_lbc.c b/arch/powerpc/sysdev/fsl_lbc.c
index dceb8d1..4920cd3 100644
--- a/arch/powerpc/sysdev/fsl_lbc.c
+++ b/arch/powerpc/sysdev/fsl_lbc.c
@@ -2,8 +2,11 @@
* Freescale LBC and UPM routines.
*
* Copyright (c) 2007-2008 MontaVista Software, Inc.
+ * Copyright (c) 2010 Freescale Semiconductor
*
* Author: Anton Vorontsov <avorontsov@ru.mvista.com>
+ * Author: Jack Lan <Jack.Lan@freescale.com>
+ * Author: Roy Zang <tie-fei.zang@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
@@ -21,37 +24,14 @@
#include <linux/of.h>
#include <asm/prom.h>
#include <asm/fsl_lbc.h>
+#include <linux/slab.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
static spinlock_t fsl_lbc_lock = __SPIN_LOCK_UNLOCKED(fsl_lbc_lock);
-static struct fsl_lbc_regs __iomem *fsl_lbc_regs;
-
-static char __initdata *compat_lbc[] = {
- "fsl,pq2-localbus",
- "fsl,pq2pro-localbus",
- "fsl,pq3-localbus",
- "fsl,elbc",
-};
-
-static int __init fsl_lbc_init(void)
-{
- struct device_node *lbus;
- int i;
-
- for (i = 0; i < ARRAY_SIZE(compat_lbc); i++) {
- lbus = of_find_compatible_node(NULL, NULL, compat_lbc[i]);
- if (lbus)
- goto found;
- }
- return -ENODEV;
-
-found:
- fsl_lbc_regs = of_iomap(lbus, 0);
- of_node_put(lbus);
- if (!fsl_lbc_regs)
- return -ENOMEM;
- return 0;
-}
-arch_initcall(fsl_lbc_init);
+struct fsl_lbc_ctrl *fsl_lbc_ctrl_dev;
+EXPORT_SYMBOL(fsl_lbc_ctrl_dev);
/**
* fsl_lbc_find - find Localbus bank
@@ -65,13 +45,15 @@ arch_initcall(fsl_lbc_init);
int fsl_lbc_find(phys_addr_t addr_base)
{
int i;
+ struct fsl_lbc_regs __iomem *lbc;
- if (!fsl_lbc_regs)
+ if (!fsl_lbc_ctrl_dev || !fsl_lbc_ctrl_dev->regs)
return -ENODEV;
- for (i = 0; i < ARRAY_SIZE(fsl_lbc_regs->bank); i++) {
- __be32 br = in_be32(&fsl_lbc_regs->bank[i].br);
- __be32 or = in_be32(&fsl_lbc_regs->bank[i].or);
+ 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);
if (br & BR_V && (br & or & BR_BA) == addr_base)
return i;
@@ -94,22 +76,27 @@ int fsl_upm_find(phys_addr_t addr_base, struct fsl_upm *upm)
{
int bank;
__be32 br;
+ struct fsl_lbc_regs __iomem *lbc;
bank = fsl_lbc_find(addr_base);
if (bank < 0)
return bank;
- br = in_be32(&fsl_lbc_regs->bank[bank].br);
+ if (!fsl_lbc_ctrl_dev || !fsl_lbc_ctrl_dev->regs)
+ return -ENODEV;
+
+ lbc = fsl_lbc_ctrl_dev->regs;
+ br = in_be32(&lbc->bank[bank].br);
switch (br & BR_MSEL) {
case BR_MS_UPMA:
- upm->mxmr = &fsl_lbc_regs->mamr;
+ upm->mxmr = &lbc->mamr;
break;
case BR_MS_UPMB:
- upm->mxmr = &fsl_lbc_regs->mbmr;
+ upm->mxmr = &lbc->mbmr;
break;
case BR_MS_UPMC:
- upm->mxmr = &fsl_lbc_regs->mcmr;
+ upm->mxmr = &lbc->mcmr;
break;
default:
return -EINVAL;
@@ -143,14 +130,18 @@ EXPORT_SYMBOL(fsl_upm_find);
* thus UPM pattern actually executed. Note that mar usage depends on the
* pre-programmed AMX bits in the UPM RAM.
*/
+
int fsl_upm_run_pattern(struct fsl_upm *upm, void __iomem *io_base, u32 mar)
{
int ret = 0;
unsigned long flags;
+ if (!fsl_lbc_ctrl_dev || !fsl_lbc_ctrl_dev->regs)
+ return -ENODEV;
+
spin_lock_irqsave(&fsl_lbc_lock, flags);
- out_be32(&fsl_lbc_regs->mar, mar);
+ out_be32(&fsl_lbc_ctrl_dev->regs->mar, mar);
switch (upm->width) {
case 8:
@@ -172,3 +163,182 @@ int fsl_upm_run_pattern(struct fsl_upm *upm, void __iomem *io_base, u32 mar)
return ret;
}
EXPORT_SYMBOL(fsl_upm_run_pattern);
+
+static int __devinit fsl_lbc_ctrl_init(struct fsl_lbc_ctrl *ctrl)
+{
+ struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
+
+ /* clear event registers */
+ setbits32(&lbc->ltesr, LTESR_CLEAR);
+ out_be32(&lbc->lteatr, 0);
+ out_be32(&lbc->ltear, 0);
+ out_be32(&lbc->lteccr, LTECCR_CLEAR);
+ out_be32(&lbc->ltedr, LTEDR_ENABLE);
+
+ /* Enable interrupts for any detected events */
+ out_be32(&lbc->lteir, LTEIR_ENABLE);
+
+ return 0;
+}
+
+static int __devexit fsl_lbc_ctrl_remove(struct platform_device *dev)
+{
+ struct fsl_lbc_ctrl *ctrl = dev_get_drvdata(&dev->dev);
+
+ if (ctrl->irq)
+ free_irq(ctrl->irq, ctrl);
+
+ if (ctrl->regs)
+ iounmap(ctrl->regs);
+
+ dev_set_drvdata(&dev->dev, NULL);
+
+ kfree(ctrl);
+
+ return 0;
+}
+
+/*
+ * NOTE: This interrupt is used to report localbus events of various kinds,
+ * such as transaction errors on the chipselects.
+ */
+
+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;
+
+ status = in_be32(&lbc->ltesr);
+ if (!status)
+ return IRQ_NONE;
+
+ out_be32(&lbc->ltesr, LTESR_CLEAR);
+ out_be32(&lbc->lteatr, 0);
+ out_be32(&lbc->ltear, 0);
+ ctrl->irq_status = status;
+
+ if (status & LTESR_BM)
+ dev_err(ctrl->dev, "Local bus monitor time-out: "
+ "LTESR 0x%08X\n", status);
+ if (status & LTESR_WP)
+ dev_err(ctrl->dev, "Write protect error: "
+ "LTESR 0x%08X\n", status);
+ if (status & LTESR_ATMW)
+ dev_err(ctrl->dev, "Atomic write error: "
+ "LTESR 0x%08X\n", status);
+ if (status & LTESR_ATMR)
+ dev_err(ctrl->dev, "Atomic read error: "
+ "LTESR 0x%08X\n", status);
+ if (status & LTESR_CS)
+ dev_err(ctrl->dev, "Chip select error: "
+ "LTESR 0x%08X\n", status);
+ if (status & LTESR_UPM)
+ ;
+ if (status & LTESR_FCT) {
+ dev_err(ctrl->dev, "FCM command time-out: "
+ "LTESR 0x%08X\n", status);
+ smp_wmb();
+ wake_up(&ctrl->irq_wait);
+ }
+ if (status & LTESR_PAR) {
+ dev_err(ctrl->dev, "Parity or Uncorrectable ECC error: "
+ "LTESR 0x%08X\n", status);
+ smp_wmb();
+ wake_up(&ctrl->irq_wait);
+ }
+ if (status & LTESR_CC) {
+ smp_wmb();
+ wake_up(&ctrl->irq_wait);
+ }
+ if (status & ~LTESR_MASK)
+ dev_err(ctrl->dev, "Unknown error: "
+ "LTESR 0x%08X\n", status);
+ return IRQ_HANDLED;
+}
+
+/*
+ * fsl_lbc_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 __devinit fsl_lbc_ctrl_probe(struct platform_device *dev)
+{
+ int ret;
+
+ if (!dev->dev.of_node) {
+ dev_err(&dev->dev, "Device OF-Node is NULL");
+ return -EFAULT;
+ }
+ fsl_lbc_ctrl_dev = kzalloc(sizeof(*fsl_lbc_ctrl_dev), GFP_KERNEL);
+ if (!fsl_lbc_ctrl_dev)
+ return -ENOMEM;
+
+ dev_set_drvdata(&dev->dev, fsl_lbc_ctrl_dev);
+
+ spin_lock_init(&fsl_lbc_ctrl_dev->lock);
+ init_waitqueue_head(&fsl_lbc_ctrl_dev->irq_wait);
+
+ fsl_lbc_ctrl_dev->regs = of_iomap(dev->dev.of_node, 0);
+ if (!fsl_lbc_ctrl_dev->regs) {
+ dev_err(&dev->dev, "failed to get memory region\n");
+ ret = -ENODEV;
+ 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) {
+ dev_err(&dev->dev, "failed to get irq resource\n");
+ ret = -ENODEV;
+ goto err;
+ }
+
+ fsl_lbc_ctrl_dev->dev = &dev->dev;
+
+ ret = fsl_lbc_ctrl_init(fsl_lbc_ctrl_dev);
+ if (ret < 0)
+ goto err;
+
+ ret = request_irq(fsl_lbc_ctrl_dev->irq, 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;
+ goto err;
+ }
+
+ return 0;
+
+err:
+ iounmap(fsl_lbc_ctrl_dev->regs);
+ kfree(fsl_lbc_ctrl_dev);
+ return ret;
+}
+
+static const struct of_device_id fsl_lbc_match[] = {
+ { .compatible = "fsl,elbc", },
+ { .compatible = "fsl,pq3-localbus", },
+ { .compatible = "fsl,pq2-localbus", },
+ { .compatible = "fsl,pq2pro-localbus", },
+ {},
+};
+
+static struct platform_driver fsl_lbc_ctrl_driver = {
+ .driver = {
+ .name = "fsl-lbc",
+ .of_match_table = fsl_lbc_match,
+ },
+ .probe = fsl_lbc_ctrl_probe,
+};
+
+static int __init fsl_lbc_init(void)
+{
+ return platform_driver_register(&fsl_lbc_ctrl_driver);
+}
+module_init(fsl_lbc_init);
--
1.5.6.5
^ permalink raw reply related
* [PATCH 2/3 v4] P4080/mtd: Only make elbc nand driver detect nand flash partitions
From: Roy Zang @ 2010-09-17 7:01 UTC (permalink / raw)
To: linux-mtd; +Cc: B07421, dedekind1, B25806, linuxppc-dev, akpm, dwmw2, B11780
In-Reply-To: <1284706869-12555-1-git-send-email-tie-fei.zang@freescale.com>
From: Jack Lan <jack.lan@freescale.com>
The former driver had the two functions:
1. detecting nand flash partitions;
2. registering elbc interrupt.
Now, second function is removed to fsl_lbc.c.
Signed-off-by: Lan Chunhe-B25806 <b25806@freescale.com>
Signed-off-by: Roy Zang <tie-fei.zang@freescale.com>
---
drivers/mtd/nand/Kconfig | 1 +
drivers/mtd/nand/fsl_elbc_nand.c | 477 +++++++++++++++-----------------------
2 files changed, 193 insertions(+), 285 deletions(-)
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index 8b4b67c..4132c46 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -458,6 +458,7 @@ config MTD_NAND_ORION
config MTD_NAND_FSL_ELBC
tristate "NAND support for Freescale eLBC controllers"
depends on PPC_OF
+ select FSL_LBC
help
Various Freescale chips, including the 8313, include a NAND Flash
Controller Module with built-in hardware ECC capabilities.
diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c
index 80de0bf..76ffd24 100644
--- a/drivers/mtd/nand/fsl_elbc_nand.c
+++ b/drivers/mtd/nand/fsl_elbc_nand.c
@@ -1,9 +1,11 @@
/* Freescale Enhanced Local Bus Controller NAND driver
*
- * Copyright (c) 2006-2007 Freescale Semiconductor
+ * Copyright (c) 2006-2007, 2010 Freescale Semiconductor
*
* Authors: Nick Spence <nick.spence@freescale.com>,
* Scott Wood <scottwood@freescale.com>
+ * Jack Lan <jack.lan@freescale.com>
+ * Roy Zang <tie-fei.zang@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
@@ -27,6 +29,7 @@
#include <linux/string.h>
#include <linux/ioport.h>
#include <linux/of_platform.h>
+#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
@@ -42,14 +45,12 @@
#define ERR_BYTE 0xFF /* Value returned for read bytes when read failed */
#define FCM_TIMEOUT_MSECS 500 /* Maximum number of mSecs to wait for FCM */
-struct fsl_elbc_ctrl;
-
/* mtd information per set */
struct fsl_elbc_mtd {
struct mtd_info mtd;
struct nand_chip chip;
- struct fsl_elbc_ctrl *ctrl;
+ struct fsl_lbc_ctrl *ctrl;
struct device *dev;
int bank; /* Chip select bank number */
@@ -58,18 +59,12 @@ struct fsl_elbc_mtd {
unsigned int fmr; /* FCM Flash Mode Register value */
};
-/* overview of the fsl elbc controller */
+/* Freescale eLBC FCM controller infomation */
-struct fsl_elbc_ctrl {
+struct fsl_elbc_fcm_ctrl {
struct nand_hw_control controller;
struct fsl_elbc_mtd *chips[MAX_BANKS];
- /* device info */
- struct device *dev;
- struct fsl_lbc_regs __iomem *regs;
- int irq;
- wait_queue_head_t irq_wait;
- unsigned int irq_status; /* status read from LTESR by irq handler */
u8 __iomem *addr; /* Address of assigned FCM buffer */
unsigned int page; /* Last page written to / read from */
unsigned int read_bytes; /* Number of bytes read during command */
@@ -164,11 +159,12 @@ static void set_addr(struct mtd_info *mtd, int column, int page_addr, int oob)
{
struct nand_chip *chip = mtd->priv;
struct fsl_elbc_mtd *priv = chip->priv;
- struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+ struct fsl_lbc_ctrl *ctrl = priv->ctrl;
struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
+ struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand;
int buf_num;
- ctrl->page = page_addr;
+ elbc_fcm_ctrl->page = page_addr;
out_be32(&lbc->fbar,
page_addr >> (chip->phys_erase_shift - chip->page_shift));
@@ -185,16 +181,18 @@ static void set_addr(struct mtd_info *mtd, int column, int page_addr, int oob)
buf_num = page_addr & 7;
}
- ctrl->addr = priv->vbase + buf_num * 1024;
- ctrl->index = column;
+ elbc_fcm_ctrl->addr = priv->vbase + buf_num * 1024;
+ elbc_fcm_ctrl->index = column;
/* for OOB data point to the second half of the buffer */
if (oob)
- ctrl->index += priv->page_size ? 2048 : 512;
+ elbc_fcm_ctrl->index += priv->page_size ? 2048 : 512;
- dev_vdbg(ctrl->dev, "set_addr: bank=%d, ctrl->addr=0x%p (0x%p), "
+ dev_vdbg(priv->dev, "set_addr: bank=%d, "
+ "elbc_fcm_ctrl->addr=0x%p (0x%p), "
"index %x, pes %d ps %d\n",
- buf_num, ctrl->addr, priv->vbase, ctrl->index,
+ buf_num, elbc_fcm_ctrl->addr, priv->vbase,
+ elbc_fcm_ctrl->index,
chip->phys_erase_shift, chip->page_shift);
}
@@ -205,18 +203,19 @@ static int fsl_elbc_run_command(struct mtd_info *mtd)
{
struct nand_chip *chip = mtd->priv;
struct fsl_elbc_mtd *priv = chip->priv;
- struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+ struct fsl_lbc_ctrl *ctrl = priv->ctrl;
+ struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand;
struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
/* Setup the FMR[OP] to execute without write protection */
out_be32(&lbc->fmr, priv->fmr | 3);
- if (ctrl->use_mdr)
- out_be32(&lbc->mdr, ctrl->mdr);
+ if (elbc_fcm_ctrl->use_mdr)
+ out_be32(&lbc->mdr, elbc_fcm_ctrl->mdr);
- dev_vdbg(ctrl->dev,
+ dev_vdbg(priv->dev,
"fsl_elbc_run_command: fmr=%08x fir=%08x fcr=%08x\n",
in_be32(&lbc->fmr), in_be32(&lbc->fir), in_be32(&lbc->fcr));
- dev_vdbg(ctrl->dev,
+ dev_vdbg(priv->dev,
"fsl_elbc_run_command: fbar=%08x fpar=%08x "
"fbcr=%08x bank=%d\n",
in_be32(&lbc->fbar), in_be32(&lbc->fpar),
@@ -229,19 +228,18 @@ static int fsl_elbc_run_command(struct mtd_info *mtd)
/* wait for FCM complete flag or timeout */
wait_event_timeout(ctrl->irq_wait, ctrl->irq_status,
FCM_TIMEOUT_MSECS * HZ/1000);
- ctrl->status = ctrl->irq_status;
-
+ elbc_fcm_ctrl->status = ctrl->irq_status;
/* store mdr value in case it was needed */
- if (ctrl->use_mdr)
- ctrl->mdr = in_be32(&lbc->mdr);
+ if (elbc_fcm_ctrl->use_mdr)
+ elbc_fcm_ctrl->mdr = in_be32(&lbc->mdr);
- ctrl->use_mdr = 0;
+ elbc_fcm_ctrl->use_mdr = 0;
- if (ctrl->status != LTESR_CC) {
- dev_info(ctrl->dev,
+ if (elbc_fcm_ctrl->status != LTESR_CC) {
+ dev_info(priv->dev,
"command failed: fir %x fcr %x status %x mdr %x\n",
in_be32(&lbc->fir), in_be32(&lbc->fcr),
- ctrl->status, ctrl->mdr);
+ elbc_fcm_ctrl->status, elbc_fcm_ctrl->mdr);
return -EIO;
}
@@ -251,7 +249,7 @@ static int fsl_elbc_run_command(struct mtd_info *mtd)
static void fsl_elbc_do_read(struct nand_chip *chip, int oob)
{
struct fsl_elbc_mtd *priv = chip->priv;
- struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+ struct fsl_lbc_ctrl *ctrl = priv->ctrl;
struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
if (priv->page_size) {
@@ -284,15 +282,16 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
{
struct nand_chip *chip = mtd->priv;
struct fsl_elbc_mtd *priv = chip->priv;
- struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+ struct fsl_lbc_ctrl *ctrl = priv->ctrl;
+ struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand;
struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
- ctrl->use_mdr = 0;
+ elbc_fcm_ctrl->use_mdr = 0;
/* clear the read buffer */
- ctrl->read_bytes = 0;
+ elbc_fcm_ctrl->read_bytes = 0;
if (command != NAND_CMD_PAGEPROG)
- ctrl->index = 0;
+ elbc_fcm_ctrl->index = 0;
switch (command) {
/* READ0 and READ1 read the entire buffer to use hardware ECC. */
@@ -301,7 +300,7 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
/* fall-through */
case NAND_CMD_READ0:
- dev_dbg(ctrl->dev,
+ dev_dbg(priv->dev,
"fsl_elbc_cmdfunc: NAND_CMD_READ0, page_addr:"
" 0x%x, column: 0x%x.\n", page_addr, column);
@@ -309,8 +308,8 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
out_be32(&lbc->fbcr, 0); /* read entire page to enable ECC */
set_addr(mtd, 0, page_addr, 0);
- ctrl->read_bytes = mtd->writesize + mtd->oobsize;
- ctrl->index += column;
+ elbc_fcm_ctrl->read_bytes = mtd->writesize + mtd->oobsize;
+ elbc_fcm_ctrl->index += column;
fsl_elbc_do_read(chip, 0);
fsl_elbc_run_command(mtd);
@@ -318,14 +317,14 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
/* READOOB reads only the OOB because no ECC is performed. */
case NAND_CMD_READOOB:
- dev_vdbg(ctrl->dev,
+ dev_vdbg(priv->dev,
"fsl_elbc_cmdfunc: NAND_CMD_READOOB, page_addr:"
" 0x%x, column: 0x%x.\n", page_addr, column);
out_be32(&lbc->fbcr, mtd->oobsize - column);
set_addr(mtd, column, page_addr, 1);
- ctrl->read_bytes = mtd->writesize + mtd->oobsize;
+ elbc_fcm_ctrl->read_bytes = mtd->writesize + mtd->oobsize;
fsl_elbc_do_read(chip, 1);
fsl_elbc_run_command(mtd);
@@ -333,7 +332,7 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
/* READID must read all 5 possible bytes while CEB is active */
case NAND_CMD_READID:
- dev_vdbg(ctrl->dev, "fsl_elbc_cmdfunc: NAND_CMD_READID.\n");
+ dev_vdbg(priv->dev, "fsl_elbc_cmdfunc: NAND_CMD_READID.\n");
out_be32(&lbc->fir, (FIR_OP_CM0 << FIR_OP0_SHIFT) |
(FIR_OP_UA << FIR_OP1_SHIFT) |
@@ -341,9 +340,9 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
out_be32(&lbc->fcr, NAND_CMD_READID << FCR_CMD0_SHIFT);
/* 5 bytes for manuf, device and exts */
out_be32(&lbc->fbcr, 5);
- ctrl->read_bytes = 5;
- ctrl->use_mdr = 1;
- ctrl->mdr = 0;
+ elbc_fcm_ctrl->read_bytes = 5;
+ elbc_fcm_ctrl->use_mdr = 1;
+ elbc_fcm_ctrl->mdr = 0;
set_addr(mtd, 0, 0, 0);
fsl_elbc_run_command(mtd);
@@ -351,7 +350,7 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
/* ERASE1 stores the block and page address */
case NAND_CMD_ERASE1:
- dev_vdbg(ctrl->dev,
+ dev_vdbg(priv->dev,
"fsl_elbc_cmdfunc: NAND_CMD_ERASE1, "
"page_addr: 0x%x.\n", page_addr);
set_addr(mtd, 0, page_addr, 0);
@@ -359,7 +358,7 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
/* ERASE2 uses the block and page address from ERASE1 */
case NAND_CMD_ERASE2:
- dev_vdbg(ctrl->dev, "fsl_elbc_cmdfunc: NAND_CMD_ERASE2.\n");
+ dev_vdbg(priv->dev, "fsl_elbc_cmdfunc: NAND_CMD_ERASE2.\n");
out_be32(&lbc->fir,
(FIR_OP_CM0 << FIR_OP0_SHIFT) |
@@ -374,8 +373,8 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
(NAND_CMD_ERASE2 << FCR_CMD2_SHIFT));
out_be32(&lbc->fbcr, 0);
- ctrl->read_bytes = 0;
- ctrl->use_mdr = 1;
+ elbc_fcm_ctrl->read_bytes = 0;
+ elbc_fcm_ctrl->use_mdr = 1;
fsl_elbc_run_command(mtd);
return;
@@ -383,14 +382,12 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
/* SEQIN sets up the addr buffer and all registers except the length */
case NAND_CMD_SEQIN: {
__be32 fcr;
- dev_vdbg(ctrl->dev,
- "fsl_elbc_cmdfunc: NAND_CMD_SEQIN/PAGE_PROG, "
+ dev_vdbg(priv->dev,
+ "fsl_elbc_cmdfunc: NAND_CMD_SEQIN/PAGE_PROG, "
"page_addr: 0x%x, column: 0x%x.\n",
page_addr, column);
- ctrl->column = column;
- ctrl->oob = 0;
- ctrl->use_mdr = 1;
+ elbc_fcm_ctrl->use_mdr = 1;
fcr = (NAND_CMD_STATUS << FCR_CMD1_SHIFT) |
(NAND_CMD_SEQIN << FCR_CMD2_SHIFT) |
@@ -420,7 +417,7 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
/* OOB area --> READOOB */
column -= mtd->writesize;
fcr |= NAND_CMD_READOOB << FCR_CMD0_SHIFT;
- ctrl->oob = 1;
+ elbc_fcm_ctrl->oob = 1;
} else {
WARN_ON(column != 0);
/* First 256 bytes --> READ0 */
@@ -429,24 +426,24 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
}
out_be32(&lbc->fcr, fcr);
- set_addr(mtd, column, page_addr, ctrl->oob);
+ set_addr(mtd, column, page_addr, elbc_fcm_ctrl->oob);
return;
}
/* PAGEPROG reuses all of the setup from SEQIN and adds the length */
case NAND_CMD_PAGEPROG: {
int full_page;
- dev_vdbg(ctrl->dev,
+ dev_vdbg(priv->dev,
"fsl_elbc_cmdfunc: NAND_CMD_PAGEPROG "
- "writing %d bytes.\n", ctrl->index);
+ "writing %d bytes.\n", elbc_fcm_ctrl->index);
/* if the write did not start at 0 or is not a full page
* then set the exact length, otherwise use a full page
* write so the HW generates the ECC.
*/
- if (ctrl->oob || ctrl->column != 0 ||
- ctrl->index != mtd->writesize + mtd->oobsize) {
- out_be32(&lbc->fbcr, ctrl->index);
+ if (elbc_fcm_ctrl->oob || elbc_fcm_ctrl->column != 0 ||
+ elbc_fcm_ctrl->index != mtd->writesize + mtd->oobsize) {
+ out_be32(&lbc->fbcr, elbc_fcm_ctrl->index);
full_page = 0;
} else {
out_be32(&lbc->fbcr, 0);
@@ -458,21 +455,21 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
/* Read back the page in order to fill in the ECC for the
* caller. Is this really needed?
*/
- if (full_page && ctrl->oob_poi) {
+ if (full_page && elbc_fcm_ctrl->oob_poi) {
out_be32(&lbc->fbcr, 3);
set_addr(mtd, 6, page_addr, 1);
- ctrl->read_bytes = mtd->writesize + 9;
+ elbc_fcm_ctrl->read_bytes = mtd->writesize + 9;
fsl_elbc_do_read(chip, 1);
fsl_elbc_run_command(mtd);
- memcpy_fromio(ctrl->oob_poi + 6,
- &ctrl->addr[ctrl->index], 3);
- ctrl->index += 3;
+ memcpy_fromio(elbc_fcm_ctrl->oob_poi + 6,
+ &elbc_fcm_ctrl->addr[elbc_fcm_ctrl->index], 3);
+ elbc_fcm_ctrl->index += 3;
}
- ctrl->oob_poi = NULL;
+ elbc_fcm_ctrl->oob_poi = NULL;
return;
}
@@ -485,26 +482,26 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
out_be32(&lbc->fcr, NAND_CMD_STATUS << FCR_CMD0_SHIFT);
out_be32(&lbc->fbcr, 1);
set_addr(mtd, 0, 0, 0);
- ctrl->read_bytes = 1;
+ elbc_fcm_ctrl->read_bytes = 1;
fsl_elbc_run_command(mtd);
/* The chip always seems to report that it is
* write-protected, even when it is not.
*/
- setbits8(ctrl->addr, NAND_STATUS_WP);
+ setbits8(elbc_fcm_ctrl->addr, NAND_STATUS_WP);
return;
/* RESET without waiting for the ready line */
case NAND_CMD_RESET:
- dev_dbg(ctrl->dev, "fsl_elbc_cmdfunc: NAND_CMD_RESET.\n");
+ dev_dbg(priv->dev, "fsl_elbc_cmdfunc: NAND_CMD_RESET.\n");
out_be32(&lbc->fir, FIR_OP_CM0 << FIR_OP0_SHIFT);
out_be32(&lbc->fcr, NAND_CMD_RESET << FCR_CMD0_SHIFT);
fsl_elbc_run_command(mtd);
return;
default:
- dev_err(ctrl->dev,
+ dev_err(priv->dev,
"fsl_elbc_cmdfunc: error, unsupported command 0x%x.\n",
command);
}
@@ -524,24 +521,24 @@ static void fsl_elbc_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
{
struct nand_chip *chip = mtd->priv;
struct fsl_elbc_mtd *priv = chip->priv;
- struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+ struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand;
unsigned int bufsize = mtd->writesize + mtd->oobsize;
if (len <= 0) {
- dev_err(ctrl->dev, "write_buf of %d bytes", len);
- ctrl->status = 0;
+ dev_err(priv->dev, "write_buf of %d bytes", len);
+ elbc_fcm_ctrl->status = 0;
return;
}
- if ((unsigned int)len > bufsize - ctrl->index) {
- dev_err(ctrl->dev,
+ if ((unsigned int)len > bufsize - elbc_fcm_ctrl->index) {
+ dev_err(priv->dev,
"write_buf beyond end of buffer "
"(%d requested, %u available)\n",
- len, bufsize - ctrl->index);
- len = bufsize - ctrl->index;
+ len, bufsize - elbc_fcm_ctrl->index);
+ len = bufsize - elbc_fcm_ctrl->index;
}
- memcpy_toio(&ctrl->addr[ctrl->index], buf, len);
+ memcpy_toio(&elbc_fcm_ctrl->addr[elbc_fcm_ctrl->index], buf, len);
/*
* This is workaround for the weird elbc hangs during nand write,
* Scott Wood says: "...perhaps difference in how long it takes a
@@ -549,9 +546,9 @@ static void fsl_elbc_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
* is causing problems, and sync isn't helping for some reason."
* Reading back the last byte helps though.
*/
- in_8(&ctrl->addr[ctrl->index] + len - 1);
+ in_8(&elbc_fcm_ctrl->addr[elbc_fcm_ctrl->index] + len - 1);
- ctrl->index += len;
+ elbc_fcm_ctrl->index += len;
}
/*
@@ -562,13 +559,13 @@ static u8 fsl_elbc_read_byte(struct mtd_info *mtd)
{
struct nand_chip *chip = mtd->priv;
struct fsl_elbc_mtd *priv = chip->priv;
- struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+ struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand;
/* If there are still bytes in the FCM, then use the next byte. */
- if (ctrl->index < ctrl->read_bytes)
- return in_8(&ctrl->addr[ctrl->index++]);
+ if (elbc_fcm_ctrl->index < elbc_fcm_ctrl->read_bytes)
+ return in_8(&elbc_fcm_ctrl->addr[elbc_fcm_ctrl->index++]);
- dev_err(ctrl->dev, "read_byte beyond end of buffer\n");
+ dev_err(priv->dev, "read_byte beyond end of buffer\n");
return ERR_BYTE;
}
@@ -579,18 +576,19 @@ static void fsl_elbc_read_buf(struct mtd_info *mtd, u8 *buf, int len)
{
struct nand_chip *chip = mtd->priv;
struct fsl_elbc_mtd *priv = chip->priv;
- struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+ struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand;
int avail;
if (len < 0)
return;
- avail = min((unsigned int)len, ctrl->read_bytes - ctrl->index);
- memcpy_fromio(buf, &ctrl->addr[ctrl->index], avail);
- ctrl->index += avail;
+ avail = min((unsigned int)len,
+ elbc_fcm_ctrl->read_bytes - elbc_fcm_ctrl->index);
+ memcpy_fromio(buf, &elbc_fcm_ctrl->addr[elbc_fcm_ctrl->index], avail);
+ elbc_fcm_ctrl->index += avail;
if (len > avail)
- dev_err(ctrl->dev,
+ dev_err(priv->dev,
"read_buf beyond end of buffer "
"(%d requested, %d available)\n",
len, avail);
@@ -603,30 +601,32 @@ static int fsl_elbc_verify_buf(struct mtd_info *mtd, const u_char *buf, int len)
{
struct nand_chip *chip = mtd->priv;
struct fsl_elbc_mtd *priv = chip->priv;
- struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+ struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand;
int i;
if (len < 0) {
- dev_err(ctrl->dev, "write_buf of %d bytes", len);
+ dev_err(priv->dev, "write_buf of %d bytes", len);
return -EINVAL;
}
- if ((unsigned int)len > ctrl->read_bytes - ctrl->index) {
- dev_err(ctrl->dev,
- "verify_buf beyond end of buffer "
- "(%d requested, %u available)\n",
- len, ctrl->read_bytes - ctrl->index);
+ if ((unsigned int)len >
+ elbc_fcm_ctrl->read_bytes - elbc_fcm_ctrl->index) {
+ dev_err(priv->dev,
+ "verify_buf beyond end of buffer "
+ "(%d requested, %u available)\n",
+ len, elbc_fcm_ctrl->read_bytes - elbc_fcm_ctrl->index);
- ctrl->index = ctrl->read_bytes;
+ elbc_fcm_ctrl->index = elbc_fcm_ctrl->read_bytes;
return -EINVAL;
}
for (i = 0; i < len; i++)
- if (in_8(&ctrl->addr[ctrl->index + i]) != buf[i])
+ if (in_8(&elbc_fcm_ctrl->addr[elbc_fcm_ctrl->index + i])
+ != buf[i])
break;
- ctrl->index += len;
- return i == len && ctrl->status == LTESR_CC ? 0 : -EIO;
+ elbc_fcm_ctrl->index += len;
+ return i == len && elbc_fcm_ctrl->status == LTESR_CC ? 0 : -EIO;
}
/* This function is called after Program and Erase Operations to
@@ -635,22 +635,22 @@ static int fsl_elbc_verify_buf(struct mtd_info *mtd, const u_char *buf, int len)
static int fsl_elbc_wait(struct mtd_info *mtd, struct nand_chip *chip)
{
struct fsl_elbc_mtd *priv = chip->priv;
- struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+ struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand;
- if (ctrl->status != LTESR_CC)
+ if (elbc_fcm_ctrl->status != LTESR_CC)
return NAND_STATUS_FAIL;
/* The chip always seems to report that it is
* write-protected, even when it is not.
*/
- return (ctrl->mdr & 0xff) | NAND_STATUS_WP;
+ return (elbc_fcm_ctrl->mdr & 0xff) | NAND_STATUS_WP;
}
static int fsl_elbc_chip_init_tail(struct mtd_info *mtd)
{
struct nand_chip *chip = mtd->priv;
struct fsl_elbc_mtd *priv = chip->priv;
- struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+ struct fsl_lbc_ctrl *ctrl = priv->ctrl;
struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
unsigned int al;
@@ -665,41 +665,41 @@ static int fsl_elbc_chip_init_tail(struct mtd_info *mtd)
priv->fmr |= (12 << FMR_CWTO_SHIFT) | /* Timeout > 12 ms */
(al << FMR_AL_SHIFT);
- dev_dbg(ctrl->dev, "fsl_elbc_init: nand->numchips = %d\n",
+ dev_dbg(priv->dev, "fsl_elbc_init: nand->numchips = %d\n",
chip->numchips);
- dev_dbg(ctrl->dev, "fsl_elbc_init: nand->chipsize = %lld\n",
+ dev_dbg(priv->dev, "fsl_elbc_init: nand->chipsize = %lld\n",
chip->chipsize);
- dev_dbg(ctrl->dev, "fsl_elbc_init: nand->pagemask = %8x\n",
+ dev_dbg(priv->dev, "fsl_elbc_init: nand->pagemask = %8x\n",
chip->pagemask);
- dev_dbg(ctrl->dev, "fsl_elbc_init: nand->chip_delay = %d\n",
+ dev_dbg(priv->dev, "fsl_elbc_init: nand->chip_delay = %d\n",
chip->chip_delay);
- dev_dbg(ctrl->dev, "fsl_elbc_init: nand->badblockpos = %d\n",
+ dev_dbg(priv->dev, "fsl_elbc_init: nand->badblockpos = %d\n",
chip->badblockpos);
- dev_dbg(ctrl->dev, "fsl_elbc_init: nand->chip_shift = %d\n",
+ dev_dbg(priv->dev, "fsl_elbc_init: nand->chip_shift = %d\n",
chip->chip_shift);
- dev_dbg(ctrl->dev, "fsl_elbc_init: nand->page_shift = %d\n",
+ dev_dbg(priv->dev, "fsl_elbc_init: nand->page_shift = %d\n",
chip->page_shift);
- dev_dbg(ctrl->dev, "fsl_elbc_init: nand->phys_erase_shift = %d\n",
+ dev_dbg(priv->dev, "fsl_elbc_init: nand->phys_erase_shift = %d\n",
chip->phys_erase_shift);
- dev_dbg(ctrl->dev, "fsl_elbc_init: nand->ecclayout = %p\n",
+ dev_dbg(priv->dev, "fsl_elbc_init: nand->ecclayout = %p\n",
chip->ecclayout);
- dev_dbg(ctrl->dev, "fsl_elbc_init: nand->ecc.mode = %d\n",
+ dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.mode = %d\n",
chip->ecc.mode);
- dev_dbg(ctrl->dev, "fsl_elbc_init: nand->ecc.steps = %d\n",
+ dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.steps = %d\n",
chip->ecc.steps);
- dev_dbg(ctrl->dev, "fsl_elbc_init: nand->ecc.bytes = %d\n",
+ dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.bytes = %d\n",
chip->ecc.bytes);
- dev_dbg(ctrl->dev, "fsl_elbc_init: nand->ecc.total = %d\n",
+ dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.total = %d\n",
chip->ecc.total);
- dev_dbg(ctrl->dev, "fsl_elbc_init: nand->ecc.layout = %p\n",
+ dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.layout = %p\n",
chip->ecc.layout);
- dev_dbg(ctrl->dev, "fsl_elbc_init: mtd->flags = %08x\n", mtd->flags);
- dev_dbg(ctrl->dev, "fsl_elbc_init: mtd->size = %lld\n", mtd->size);
- dev_dbg(ctrl->dev, "fsl_elbc_init: mtd->erasesize = %d\n",
+ dev_dbg(priv->dev, "fsl_elbc_init: mtd->flags = %08x\n", mtd->flags);
+ dev_dbg(priv->dev, "fsl_elbc_init: mtd->size = %lld\n", mtd->size);
+ dev_dbg(priv->dev, "fsl_elbc_init: mtd->erasesize = %d\n",
mtd->erasesize);
- dev_dbg(ctrl->dev, "fsl_elbc_init: mtd->writesize = %d\n",
+ dev_dbg(priv->dev, "fsl_elbc_init: mtd->writesize = %d\n",
mtd->writesize);
- dev_dbg(ctrl->dev, "fsl_elbc_init: mtd->oobsize = %d\n",
+ dev_dbg(priv->dev, "fsl_elbc_init: mtd->oobsize = %d\n",
mtd->oobsize);
/* adjust Option Register and ECC to match Flash page size */
@@ -719,7 +719,7 @@ static int fsl_elbc_chip_init_tail(struct mtd_info *mtd)
chip->badblock_pattern = &largepage_memorybased;
}
} else {
- dev_err(ctrl->dev,
+ dev_err(priv->dev,
"fsl_elbc_init: page size %d is not supported\n",
mtd->writesize);
return -1;
@@ -750,18 +750,19 @@ static void fsl_elbc_write_page(struct mtd_info *mtd,
const uint8_t *buf)
{
struct fsl_elbc_mtd *priv = chip->priv;
- struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+ struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand;
fsl_elbc_write_buf(mtd, buf, mtd->writesize);
fsl_elbc_write_buf(mtd, chip->oob_poi, mtd->oobsize);
- ctrl->oob_poi = chip->oob_poi;
+ elbc_fcm_ctrl->oob_poi = chip->oob_poi;
}
static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv)
{
- struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+ struct fsl_lbc_ctrl *ctrl = priv->ctrl;
struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
+ struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand;
struct nand_chip *chip = &priv->chip;
dev_dbg(priv->dev, "eLBC Set Information for bank %d\n", priv->bank);
@@ -790,7 +791,7 @@ static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv)
chip->options = NAND_NO_READRDY | NAND_NO_AUTOINCR |
NAND_USE_FLASH_BBT;
- chip->controller = &ctrl->controller;
+ chip->controller = &elbc_fcm_ctrl->controller;
chip->priv = priv;
chip->ecc.read_page = fsl_elbc_read_page;
@@ -815,8 +816,7 @@ static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv)
static int fsl_elbc_chip_remove(struct fsl_elbc_mtd *priv)
{
- struct fsl_elbc_ctrl *ctrl = priv->ctrl;
-
+ struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand;
nand_release(&priv->mtd);
kfree(priv->mtd.name);
@@ -824,18 +824,21 @@ static int fsl_elbc_chip_remove(struct fsl_elbc_mtd *priv)
if (priv->vbase)
iounmap(priv->vbase);
- ctrl->chips[priv->bank] = NULL;
+ elbc_fcm_ctrl->chips[priv->bank] = NULL;
kfree(priv);
-
+ kfree(elbc_fcm_ctrl);
return 0;
}
-static int __devinit fsl_elbc_chip_probe(struct fsl_elbc_ctrl *ctrl,
- struct device_node *node)
+static struct mutex fsl_elbc_nand_mutex;
+
+static int __devinit fsl_elbc_nand_probe(struct platform_device *dev)
{
- struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
+ struct fsl_lbc_regs __iomem *lbc;
struct fsl_elbc_mtd *priv;
struct resource res;
+ struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = NULL;
+
#ifdef CONFIG_MTD_PARTITIONS
static const char *part_probe_types[]
= { "cmdlinepart", "RedBoot", NULL };
@@ -843,11 +846,16 @@ static int __devinit fsl_elbc_chip_probe(struct fsl_elbc_ctrl *ctrl,
#endif
int ret;
int bank;
+ struct device_node *node = dev->dev.of_node;
+
+ if (!fsl_lbc_ctrl_dev || !fsl_lbc_ctrl_dev->regs)
+ return -ENODEV;
+ lbc = fsl_lbc_ctrl_dev->regs;
/* get, allocate and map the memory resource */
ret = of_address_to_resource(node, 0, &res);
if (ret) {
- dev_err(ctrl->dev, "failed to get resource\n");
+ dev_err(fsl_lbc_ctrl_dev->dev, "failed to get resource\n");
return ret;
}
@@ -861,7 +869,8 @@ static int __devinit fsl_elbc_chip_probe(struct fsl_elbc_ctrl *ctrl,
break;
if (bank >= MAX_BANKS) {
- dev_err(ctrl->dev, "address did not match any chip selects\n");
+ dev_err(fsl_lbc_ctrl_dev->dev, "address did not match any "
+ "chip selects\n");
return -ENODEV;
}
@@ -869,14 +878,35 @@ static int __devinit fsl_elbc_chip_probe(struct fsl_elbc_ctrl *ctrl,
if (!priv)
return -ENOMEM;
- ctrl->chips[bank] = priv;
+ mutex_init(&fsl_elbc_nand_mutex);
+
+ mutex_lock(&fsl_elbc_nand_mutex);
+ if (!fsl_lbc_ctrl_dev->nand) {
+ elbc_fcm_ctrl = kzalloc(sizeof(*elbc_fcm_ctrl), GFP_KERNEL);
+ if (!elbc_fcm_ctrl) {
+ dev_err(fsl_lbc_ctrl_dev->dev, "failed to allocate "
+ "memory\n");
+ mutex_unlock(&fsl_elbc_nand_mutex);
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ spin_lock_init(&elbc_fcm_ctrl->controller.lock);
+ init_waitqueue_head(&elbc_fcm_ctrl->controller.wq);
+ fsl_lbc_ctrl_dev->nand = elbc_fcm_ctrl;
+ } else {
+ elbc_fcm_ctrl = fsl_lbc_ctrl_dev->nand;
+ }
+ mutex_unlock(&fsl_elbc_nand_mutex);
+
+ elbc_fcm_ctrl->chips[bank] = priv;
priv->bank = bank;
- priv->ctrl = ctrl;
- priv->dev = ctrl->dev;
+ priv->ctrl = fsl_lbc_ctrl_dev;
+ priv->dev = fsl_lbc_ctrl_dev->dev;
priv->vbase = ioremap(res.start, resource_size(&res));
if (!priv->vbase) {
- dev_err(ctrl->dev, "failed to map chip region\n");
+ dev_err(fsl_lbc_ctrl_dev->dev, "failed to map chip region\n");
ret = -ENOMEM;
goto err;
}
@@ -933,171 +963,48 @@ err:
return ret;
}
-static int __devinit fsl_elbc_ctrl_init(struct fsl_elbc_ctrl *ctrl)
+static int fsl_elbc_nand_remove(struct platform_device *dev)
{
- struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
-
- /*
- * NAND transactions can tie up the bus for a long time, so set the
- * bus timeout to max by clearing LBCR[BMT] (highest base counter
- * value) and setting LBCR[BMTPS] to the highest prescaler value.
- */
- clrsetbits_be32(&lbc->lbcr, LBCR_BMT, 15);
-
- /* clear event registers */
- setbits32(&lbc->ltesr, LTESR_NAND_MASK);
- out_be32(&lbc->lteatr, 0);
-
- /* Enable interrupts for any detected events */
- out_be32(&lbc->lteir, LTESR_NAND_MASK);
-
- ctrl->read_bytes = 0;
- ctrl->index = 0;
- ctrl->addr = NULL;
-
- return 0;
-}
-
-static int fsl_elbc_ctrl_remove(struct platform_device *ofdev)
-{
- struct fsl_elbc_ctrl *ctrl = dev_get_drvdata(&ofdev->dev);
int i;
-
+ struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = fsl_lbc_ctrl_dev->nand;
for (i = 0; i < MAX_BANKS; i++)
- if (ctrl->chips[i])
- fsl_elbc_chip_remove(ctrl->chips[i]);
-
- if (ctrl->irq)
- free_irq(ctrl->irq, ctrl);
+ if (elbc_fcm_ctrl->chips[i])
+ fsl_elbc_chip_remove(elbc_fcm_ctrl->chips[i]);
- if (ctrl->regs)
- iounmap(ctrl->regs);
+ fsl_lbc_ctrl_dev->nand = NULL;
+ kfree(elbc_fcm_ctrl);
- dev_set_drvdata(&ofdev->dev, NULL);
- kfree(ctrl);
return 0;
-}
-
-/* NOTE: This interrupt is also used to report other localbus events,
- * such as transaction errors on other chipselects. If we want to
- * capture those, we'll need to move the IRQ code into a shared
- * LBC driver.
- */
-static irqreturn_t fsl_elbc_ctrl_irq(int irqno, void *data)
-{
- struct fsl_elbc_ctrl *ctrl = data;
- struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
- __be32 status = in_be32(&lbc->ltesr) & LTESR_NAND_MASK;
-
- if (status) {
- out_be32(&lbc->ltesr, status);
- out_be32(&lbc->lteatr, 0);
-
- ctrl->irq_status = status;
- smp_wmb();
- wake_up(&ctrl->irq_wait);
-
- return IRQ_HANDLED;
- }
-
- return IRQ_NONE;
}
-/* fsl_elbc_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 __devinit fsl_elbc_ctrl_probe(struct platform_device *ofdev,
- const struct of_device_id *match)
-{
- struct device_node *child;
- struct fsl_elbc_ctrl *ctrl;
- int ret;
-
- ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL);
- if (!ctrl)
- return -ENOMEM;
-
- dev_set_drvdata(&ofdev->dev, ctrl);
-
- spin_lock_init(&ctrl->controller.lock);
- init_waitqueue_head(&ctrl->controller.wq);
- init_waitqueue_head(&ctrl->irq_wait);
-
- ctrl->regs = of_iomap(ofdev->dev.of_node, 0);
- if (!ctrl->regs) {
- dev_err(&ofdev->dev, "failed to get memory region\n");
- ret = -ENODEV;
- goto err;
- }
-
- ctrl->irq = of_irq_to_resource(ofdev->dev.of_node, 0, NULL);
- if (ctrl->irq == NO_IRQ) {
- dev_err(&ofdev->dev, "failed to get irq resource\n");
- ret = -ENODEV;
- goto err;
- }
-
- ctrl->dev = &ofdev->dev;
-
- ret = fsl_elbc_ctrl_init(ctrl);
- if (ret < 0)
- goto err;
-
- ret = request_irq(ctrl->irq, fsl_elbc_ctrl_irq, 0, "fsl-elbc", ctrl);
- if (ret != 0) {
- dev_err(&ofdev->dev, "failed to install irq (%d)\n",
- ctrl->irq);
- ret = ctrl->irq;
- goto err;
- }
-
- for_each_child_of_node(ofdev->dev.of_node, child)
- if (of_device_is_compatible(child, "fsl,elbc-fcm-nand"))
- fsl_elbc_chip_probe(ctrl, child);
-
- return 0;
-
-err:
- fsl_elbc_ctrl_remove(ofdev);
- return ret;
-}
-
-static const struct of_device_id fsl_elbc_match[] = {
- {
- .compatible = "fsl,elbc",
- },
+static const struct of_device_id fsl_elbc_nand_match[] = {
+ { .compatible = "fsl,elbc-fcm-nand", },
{}
};
-static struct of_platform_driver fsl_elbc_ctrl_driver = {
+static struct platform_driver fsl_elbc_nand_driver = {
.driver = {
- .name = "fsl-elbc",
+ .name = "fsl,elbc-fcm-nand",
.owner = THIS_MODULE,
- .of_match_table = fsl_elbc_match,
+ .of_match_table = fsl_elbc_nand_match,
},
- .probe = fsl_elbc_ctrl_probe,
- .remove = fsl_elbc_ctrl_remove,
+ .probe = fsl_elbc_nand_probe,
+ .remove = fsl_elbc_nand_remove,
};
-static int __init fsl_elbc_init(void)
+static int __init fsl_elbc_nand_init(void)
{
- return of_register_platform_driver(&fsl_elbc_ctrl_driver);
+ return platform_driver_register(&fsl_elbc_nand_driver);
}
-static void __exit fsl_elbc_exit(void)
+static void __exit fsl_elbc_nand_exit(void)
{
- of_unregister_platform_driver(&fsl_elbc_ctrl_driver);
+ platform_driver_unregister(&fsl_elbc_nand_driver);
}
-module_init(fsl_elbc_init);
-module_exit(fsl_elbc_exit);
+module_init(fsl_elbc_nand_init);
+module_exit(fsl_elbc_nand_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Freescale");
--
1.5.6.5
^ permalink raw reply related
* [PATCH] powerpc: define a compat_sys_recv cond_syscall
From: Ian Munsie @ 2010-09-17 7:05 UTC (permalink / raw)
To: Benjamin Herrenschmidt
Cc: Stephen Rothwell, linux-kernel, Eric Paris, linux-next,
Paul Mackerras, Ian Munsie, Russell King, Andrew Morton,
linuxppc-dev, David S. Miller, Eric W. Biederman
In-Reply-To: <20100903132410.ede593ed.sfr@canb.auug.org.au>
From: Stephen Rothwell <sfr@canb.auug.org.au>
Since compat_sys_recv is an optionl syscall if the kernel is compiled
without networking we need a cond_syscall defined for it since it is now
wired up directly on PowerPC.
Other architectures that wire up the socket calls directly as syscalls
do not run into this issue either because they don't have to deal with
the 32bit compat versions of the syscalls or just don't wire up that
particular compat syscall directly.
Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
Signed-off-by: Ian Munsie <imunsie@au1.ibm.com>
---
kernel/sys_ni.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c
index bad369e..c782fe9 100644
--- a/kernel/sys_ni.c
+++ b/kernel/sys_ni.c
@@ -50,6 +50,7 @@ cond_syscall(compat_sys_sendmsg);
cond_syscall(sys_recvmsg);
cond_syscall(sys_recvmmsg);
cond_syscall(compat_sys_recvmsg);
+cond_syscall(compat_sys_recv);
cond_syscall(compat_sys_recvfrom);
cond_syscall(compat_sys_recvmmsg);
cond_syscall(sys_socketcall);
--
1.7.1
^ permalink raw reply related
* Re: linux support for freescale e5500 core?
From: Chris Friesen @ 2010-09-17 6:36 UTC (permalink / raw)
To: Benjamin Herrenschmidt; +Cc: linuxppc-dev, paulus, Scott Wood, timur
In-Reply-To: <1284701585.30449.102.camel@pasglop>
On 09/16/2010 11:33 PM, Benjamin Herrenschmidt wrote:
> On Fri, 2010-09-17 at 00:17 -0500, Kumar Gala wrote:
>> Not sure how the 970 bit worked, but this seems a bit problematic for
>> switching between kernel and application for how we do this on
>> e500mc/e5500. We'd have to touch the control bit on every exception
>> path which seems ugly to me.
>
> Unless the kernel uses dcbzl (feature fixup replacement ?)
>
> In that case it's on context switch only.
This is basically what we did. Kernel and system libraries (glibc and
friends) always use dcbzl, process flag indicates compatibility, touch
the control bit on task context switch if the prev and next processes
have different compatibility modes.
On the 970 you have to invalidate the entire icache whenever you change
the control bit. This is a pain involving a loop that calls icbi on 512
cachelines.
Chris
--
Chris Friesen
Software Developer
GENBAND
chris.friesen@genband.com
www.genband.com
^ permalink raw reply
* Re: linux support for freescale e5500 core?
From: Benjamin Herrenschmidt @ 2010-09-17 5:33 UTC (permalink / raw)
To: Kumar Gala; +Cc: linuxppc-dev, Chris Friesen, paulus, Scott Wood, timur
In-Reply-To: <7EDBB1DD-BB9D-417D-8F4E-B9D5D9E030EF@kernel.crashing.org>
On Fri, 2010-09-17 at 00:17 -0500, Kumar Gala wrote:
> Not sure how the 970 bit worked, but this seems a bit problematic for
> switching between kernel and application for how we do this on
> e500mc/e5500. We'd have to touch the control bit on every exception
> path which seems ugly to me.
Unless the kernel uses dcbzl (feature fixup replacement ?)
In that case it's on context switch only.
Cheers,
Ben.
^ permalink raw reply
* Re: linux support for freescale e5500 core?
From: Kumar Gala @ 2010-09-17 5:17 UTC (permalink / raw)
To: Benjamin Herrenschmidt
Cc: linuxppc-dev, Chris Friesen, paulus, Scott Wood, timur
In-Reply-To: <1284681832.30449.101.camel@pasglop>
On Sep 16, 2010, at 7:03 PM, Benjamin Herrenschmidt wrote:
> On Thu, 2010-09-16 at 16:26 -0600, Chris Friesen wrote:
>>> Sounds like a candidate for upstreaming the patch :-)
>>=20
>> As I recall we proposed upstreaming it a while back but there wasn't =
a
>> lot of interest since it's most useful in supporting poorly-written
>> legacy apps. :)=20
>=20
> Heh. Well as long as only 970 had that bit ... but with e5500 coming =
up
> with that too, I suppose it makes -some- sense. Let's at least look at
> the approach you took and we can decide based on how invasive/ugly it
> is :-)
Not sure how the 970 bit worked, but this seems a bit problematic for =
switching between kernel and application for how we do this on =
e500mc/e5500. We'd have to touch the control bit on every exception =
path which seems ugly to me.
- k=
^ permalink raw reply
* Re: linux-next: build failure after merge of the final tree (powerpc related)
From: Stephen Rothwell @ 2010-09-17 4:27 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Paul Mackerras, linuxppc-dev
Cc: linux-next, linux-kernel, Ian Munsie
In-Reply-To: <20100903132410.ede593ed.sfr@canb.auug.org.au>
[-- Attachment #1: Type: text/plain, Size: 1374 bytes --]
Hi Ben,
On Fri, 3 Sep 2010 13:24:10 +1000 Stephen Rothwell <sfr@canb.auug.org.au> wrote:
>
> After merging the final tree, today's linux-next build
> (powerpc64 allnoconfig) failed like this:
>
> arch/powerpc/kernel/built-in.o: In function `.sys_call_table':
> (.text+0x8d48): undefined reference to `.compat_sys_recv'
>
> Caused by commit 86250b9d12caa1a3dee12a7cf638b7dd70eaadb6 ("powerpc: Wire
> up direct socket system calls").
>
> I have applied this patch for today:
>
> From: Stephen Rothwell <sfr@canb.auug.org.au>
> Date: Fri, 3 Sep 2010 13:19:04 +1000
> Subject: [PATCH] powerpc: define a compat_sys_recv cond_syscall
>
> Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
> ---
> kernel/sys_ni.c | 1 +
> 1 files changed, 1 insertions(+), 0 deletions(-)
>
> diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c
> index bad369e..c782fe9 100644
> --- a/kernel/sys_ni.c
> +++ b/kernel/sys_ni.c
> @@ -50,6 +50,7 @@ cond_syscall(compat_sys_sendmsg);
> cond_syscall(sys_recvmsg);
> cond_syscall(sys_recvmmsg);
> cond_syscall(compat_sys_recvmsg);
> +cond_syscall(compat_sys_recv);
> cond_syscall(compat_sys_recvfrom);
> cond_syscall(compat_sys_recvmmsg);
> cond_syscall(sys_socketcall);
> --
> 1.7.1
Ping?
--
Cheers,
Stephen Rothwell sfr@canb.auug.org.au
http://www.canb.auug.org.au/~sfr/
[-- Attachment #2: Type: application/pgp-signature, Size: 490 bytes --]
^ permalink raw reply
* Re: Generating elf kernel ?
From: tiejun.chen @ 2010-09-17 1:58 UTC (permalink / raw)
To: Scott Wood; +Cc: linuxppc-dev, Guillaume Dargaud
In-Reply-To: <20100916120944.11c45c31@schlenkerla.am.freescale.net>
Scott Wood wrote:
> On Thu, 16 Sep 2010 10:37:32 +0800
> "tiejun.chen" <tiejun.chen@windriver.com> wrote:
>
>> 1> can you load the Linux vmlinux directly to the physical address '0' on
>> current bootloader?
>
> That depends on what bootloader we're talking about -- I don't know
> what the original poster's custom loader can do. Obviously the
> bootloader itself would have to be executing from some other address
> (e.g. U-Boot runs from the top of RAM).
>
>> 2> additionally you have to find a way to pass dtb to the native vmlinux.
>
> Yes, of course. But that's a different issue. :-)
>
>> I believe the hypervisor can boot vmlinux directly. But your so-called vmlinux
>> should be guest OS. And the hypervisor will handle/assit TLB exception for the
>> guest OS on MMU. Right? So you can use the hypervisor to load vmlinux to any
>> physical address as you expect.
>
> I was just using our hypervisor as an example, since it has an ELF
> loader that can pass a device tree.
>
>> But the guest OS should not be same as the native Linux.
>
> The guest OS *is* the same as native Linux, as far as TLB handling is
> concerned.
Looks you means the TLB exception handler should be same between the native and
the guest OS. Right?
Here I assume we're talking about e500mc since as far as I know for Freescale
only e500mc is designed to support virtual machine based on ISA 2.0.6.
I also know all TLB exceptions can direct to the guest OS when we enable
EPCR[DTLBGS|ITLBGS|DSIGS|ISIGS]. But some TLB instructions (i.e. tlbwe )are the
privileged instructions. So the guest OS always trap into the hypervisor and
then the hypervisor should complete the real action with appropriate physical
address. And also the hypervisor can supervisor if the guest OS want to access
the invalid physical space.
So I don't think the guest OS is same as native Linux :)
Cheers
Tiejun
>
> -Scott
>
>
^ permalink raw reply
* Re: linux support for freescale e5500 core?
From: Benjamin Herrenschmidt @ 2010-09-17 0:03 UTC (permalink / raw)
To: Chris Friesen; +Cc: Chris Friesen, Scott Wood, paulus, timur, linuxppc-dev
In-Reply-To: <4C92998C.7000903@nortel.com>
On Thu, 2010-09-16 at 16:26 -0600, Chris Friesen wrote:
> > Sounds like a candidate for upstreaming the patch :-)
>
> As I recall we proposed upstreaming it a while back but there wasn't a
> lot of interest since it's most useful in supporting poorly-written
> legacy apps. :)
Heh. Well as long as only 970 had that bit ... but with e5500 coming up
with that too, I suppose it makes -some- sense. Let's at least look at
the approach you took and we can decide based on how invasive/ugly it
is :-)
Cheers,
Ben.
^ permalink raw reply
* [PATCH 3/4] powerpc/85xx: Minor fixups for kexec on 85xx
From: Matthew McClintock @ 2010-09-16 22:58 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Matthew McClintock, kumar.gala
In-Reply-To: <1284677906-23787-1-git-send-email-msm@freescale.com>
Make kexec_down_cpus atmoic since it will be incremented by all
cores as they are coming down
Remove duplicate calls to mpc85xx_smp_kexec_down, now it's called
by the crash and normal kexec pathway only once
Increase the timeout to wait for other cores to shutdown
Signed-off-by: Matthew McClintock <msm@freescale.com>
---
arch/powerpc/platforms/85xx/smp.c | 24 +++++++++++-------------
1 files changed, 11 insertions(+), 13 deletions(-)
diff --git a/arch/powerpc/platforms/85xx/smp.c b/arch/powerpc/platforms/85xx/smp.c
index cb8ad3b..29416a9 100644
--- a/arch/powerpc/platforms/85xx/smp.c
+++ b/arch/powerpc/platforms/85xx/smp.c
@@ -114,17 +114,15 @@ struct smp_ops_t smp_85xx_ops = {
};
#ifdef CONFIG_KEXEC
-static int kexec_down_cpus = 0;
+atomic_t kexec_down_cpus = ATOMIC_INIT(0);
void mpc85xx_smp_kexec_cpu_down(int crash_shutdown, int secondary)
{
- /* When crashing, this gets called on all CPU's we only
- * take down the non-boot cpus */
- if (smp_processor_id() != boot_cpuid)
- {
- local_irq_disable();
- kexec_down_cpus++;
+ local_irq_disable();
+ if (secondary) {
+ atomic_inc(&kexec_down_cpus);
+ /* loop forever */
while (1);
}
}
@@ -137,14 +135,14 @@ static void mpc85xx_smp_kexec_down(void *arg)
static void mpc85xx_smp_machine_kexec(struct kimage *image)
{
- int timeout = 2000;
- int i;
+ int timeout = INT_MAX;
+ int i, num_cpus = num_present_cpus();
- set_cpus_allowed(current, cpumask_of_cpu(boot_cpuid));
- smp_call_function(mpc85xx_smp_kexec_down, NULL, 0);
+ if (image->type == KEXEC_TYPE_DEFAULT)
+ smp_call_function(mpc85xx_smp_kexec_down, NULL, 0);
- while ( (kexec_down_cpus != (num_online_cpus() - 1)) &&
+ while ( (atomic_read(&kexec_down_cpus) != (num_cpus - 1)) &&
( timeout > 0 ) )
{
timeout--;
@@ -153,7 +151,7 @@ static void mpc85xx_smp_machine_kexec(struct kimage *image)
if ( !timeout )
printk(KERN_ERR "Unable to bring down secondary cpu(s)");
- for (i = 0; i < num_present_cpus(); i++)
+ for (i = 0; i < num_cpus; i++)
{
if ( i == smp_processor_id() ) continue;
mpic_reset_core(i);
--
1.6.6.1
^ permalink raw reply related
* [PATCH 4/4] powerpc/85xx: flush dcache before resetting cores
From: Matthew McClintock @ 2010-09-16 22:58 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Matthew McClintock, kumar.gala
In-Reply-To: <1284677906-23787-1-git-send-email-msm@freescale.com>
When we do an mpic_reset_core we need to make sure the dcache
is flushed
Signed-off-by: Matthew McClintock <msm@freescale.com>
---
arch/powerpc/platforms/85xx/smp.c | 50 +++++++++++++++++++++++++++++++++++++
1 files changed, 50 insertions(+), 0 deletions(-)
diff --git a/arch/powerpc/platforms/85xx/smp.c b/arch/powerpc/platforms/85xx/smp.c
index 29416a9..c89a370 100644
--- a/arch/powerpc/platforms/85xx/smp.c
+++ b/arch/powerpc/platforms/85xx/smp.c
@@ -16,6 +16,7 @@
#include <linux/delay.h>
#include <linux/of.h>
#include <linux/kexec.h>
+#include <linux/highmem.h>
#include <asm/machdep.h>
#include <asm/pgtable.h>
@@ -133,11 +134,60 @@ static void mpc85xx_smp_kexec_down(void *arg)
ppc_md.kexec_cpu_down(0,1);
}
+static void map_and_flush(unsigned long paddr)
+{
+ struct page *page = pfn_to_page(paddr >> PAGE_SHIFT);
+ unsigned long kaddr = (unsigned long)kmap(page);
+
+ flush_dcache_range(kaddr, kaddr + PAGE_SIZE);
+ kunmap(page);
+}
+
+/**
+ * Before we reset the other cores, we need to flush relevant cache
+ * out to memory so we don't get anything corrupted, some of these flushes
+ * are performed out of an overabundance of caution as interrupts are not
+ * disabled yet and we can switch cores
+ */
+static void mpc85xx_smp_flush_dcache_kexec(struct kimage *image)
+{
+ kimage_entry_t *ptr, entry;
+ unsigned long paddr;
+ int i;
+
+ if (image->type == KEXEC_TYPE_DEFAULT) {
+ /* normal kexec images are stored in temporary pages */
+ for (ptr = &image->head; (entry = *ptr) && !(entry & IND_DONE);
+ ptr = (entry & IND_INDIRECTION) ?
+ phys_to_virt(entry & PAGE_MASK) : ptr + 1) {
+ if (!(entry & IND_DESTINATION)) {
+ map_and_flush(entry);
+ }
+ }
+ /* flush out last IND_DONE page */
+ map_and_flush(entry);
+ } else {
+ /* crash type kexec images are copied to the crash region */
+ for (i = 0; i < image->nr_segments; i++) {
+ struct kexec_segment *seg = &image->segment[i];
+ for (paddr = seg->mem; paddr < seg->mem + seg->memsz;
+ paddr += PAGE_SIZE) {
+ map_and_flush(paddr);
+ }
+ }
+ }
+
+ /* also flush the kimage struct to be passed in as well */
+ flush_dcache_range((unsigned long)image,
+ (unsigned long)image + sizeof(*image));
+}
+
static void mpc85xx_smp_machine_kexec(struct kimage *image)
{
int timeout = INT_MAX;
int i, num_cpus = num_present_cpus();
+ mpc85xx_smp_flush_dcache_kexec(image);
if (image->type == KEXEC_TYPE_DEFAULT)
smp_call_function(mpc85xx_smp_kexec_down, NULL, 0);
--
1.6.6.1
^ permalink raw reply related
* Re: [PATCH 01/15] ppc: fix return type of BUID_{HI,LO} macros
From: Scott Wood @ 2010-09-16 23:04 UTC (permalink / raw)
To: linasvepstas
Cc: Nishanth Aravamudan, linuxppc-dev, Breno Leitao, Paul Mackerras,
Milton Miller
In-Reply-To: <AANLkTikHxiUQR2+Gao0sNn2mzVN-M=Z=+3Z3=7H7GJdK@mail.gmail.com>
On Thu, 16 Sep 2010 17:54:46 -0500
Linas Vepstas <linasvepstas@gmail.com> wrote:
> Acked-by: Linas Vepstas <linasvepstas@gmail.com>
>
> I'm guessing this worked up til now because the rtas_call function prototype
> was telling compiler to cast these to 32-bit before passing them as args.
> (and since these would still get passed as one arg per 64-bit reg, it
> still wouldn't go wrong.)
>
> What I'm wondering about is why there was no compiler warning about an
> implicit cast of a 64-bit int to a 32-bit int? Surely, this is something that
> should be warned about!
-Wconversion enables this.
There'd be a lot of false positives to squash with that enabled --
and it might not be worth the resulting explosion in casts.
-Scott
^ permalink raw reply
* Re: [PATCH 01/15] ppc: fix return type of BUID_{HI,LO} macros
From: Linas Vepstas @ 2010-09-16 22:54 UTC (permalink / raw)
To: Nishanth Aravamudan
Cc: linuxppc-dev, Paul Mackerras, Breno Leitao, Milton Miller
In-Reply-To: <20100915181319.GB3683@us.ibm.com>
Acked-by: Linas Vepstas <linasvepstas@gmail.com>
I'm guessing this worked up til now because the rtas_call function prototyp=
e
was telling compiler to cast these to 32-bit before passing them as args.
(and since these would still get passed as one arg per 64-bit reg, it
still wouldn't go wrong.)
What I'm wondering about is why there was no compiler warning about an
implicit cast of a 64-bit int to a 32-bit int? Surely, this is something t=
hat
should be warned about!
-- Linas
On 15 September 2010 13:13, Nishanth Aravamudan <nacc@us.ibm.com> wrote:
> BUID_HI and BUID_LO are used to pass data to call_rtas, which expects
> ints or u32s. But the macro doesn't cast the return, so the result is
> still u64. Use the upper_32_bits and lower_32_bits macros that have been
> added to kernel.h.
>
> Found by getting printf format errors trying to debug print the args, no
> actual code change for 64 bit kernels where the macros are actually
> used.
>
> Signed-off-by: Milton Miller <miltonm@bga.com>
> Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
> ---
> =C2=A0arch/powerpc/include/asm/ppc-pci.h | =C2=A0 =C2=A04 ++--
> =C2=A01 files changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/arch/powerpc/include/asm/ppc-pci.h b/arch/powerpc/include/as=
m/ppc-pci.h
> index 42fdff0..43268f1 100644
> --- a/arch/powerpc/include/asm/ppc-pci.h
> +++ b/arch/powerpc/include/asm/ppc-pci.h
> @@ -28,8 +28,8 @@ extern void find_and_init_phbs(void);
> =C2=A0extern struct pci_dev *isa_bridge_pcidev; =C2=A0 =C2=A0 =C2=A0/* ma=
y be NULL if no ISA bus */
>
> =C2=A0/** Bus Unit ID macros; get low and hi 32-bits of the 64-bit BUID *=
/
> -#define BUID_HI(buid) ((buid) >> 32)
> -#define BUID_LO(buid) ((buid) & 0xffffffff)
> +#define BUID_HI(buid) upper_32_bits(buid)
> +#define BUID_LO(buid) lower_32_bits(buid)
>
> =C2=A0/* PCI device_node operations */
> =C2=A0struct device_node;
> --
> 1.7.0.4
>
>
^ permalink raw reply
* [PATCH 1/4] powerpc/kexec: make masking/disabling interrupts generic
From: Matthew McClintock @ 2010-09-16 22:58 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Matthew McClintock, kumar.gala
Right now just the kexec crash pathway turns turns off the
interrupts. Pull that out and make a generic version for
use elsewhere
Signed-off-by: Matthew McClintock <msm@freescale.com>
---
arch/powerpc/include/asm/kexec.h | 1 +
arch/powerpc/kernel/crash.c | 13 +------------
arch/powerpc/kernel/machine_kexec.c | 24 ++++++++++++++++++++++++
arch/powerpc/kernel/machine_kexec_32.c | 4 ++++
4 files changed, 30 insertions(+), 12 deletions(-)
diff --git a/arch/powerpc/include/asm/kexec.h b/arch/powerpc/include/asm/kexec.h
index 076327f..f54408d 100644
--- a/arch/powerpc/include/asm/kexec.h
+++ b/arch/powerpc/include/asm/kexec.h
@@ -91,6 +91,7 @@ extern void machine_kexec_simple(struct kimage *image);
extern void crash_kexec_secondary(struct pt_regs *regs);
extern int overlaps_crashkernel(unsigned long start, unsigned long size);
extern void reserve_crashkernel(void);
+extern void machine_kexec_mask_interrupts(void);
#else /* !CONFIG_KEXEC */
static inline int kexec_sr_activated(int cpu) { return 0; }
diff --git a/arch/powerpc/kernel/crash.c b/arch/powerpc/kernel/crash.c
index 4457382..832c8c4 100644
--- a/arch/powerpc/kernel/crash.c
+++ b/arch/powerpc/kernel/crash.c
@@ -414,18 +414,7 @@ void default_machine_crash_shutdown(struct pt_regs *regs)
crash_kexec_wait_realmode(crashing_cpu);
#endif
- for_each_irq(i) {
- struct irq_desc *desc = irq_to_desc(i);
-
- if (!desc || !desc->chip || !desc->chip->eoi)
- continue;
-
- if (desc->status & IRQ_INPROGRESS)
- desc->chip->eoi(i);
-
- if (!(desc->status & IRQ_DISABLED))
- desc->chip->shutdown(i);
- }
+ machine_kexec_mask_interrupts();
/*
* Call registered shutdown routines savely. Swap out
diff --git a/arch/powerpc/kernel/machine_kexec.c b/arch/powerpc/kernel/machine_kexec.c
index dd6c141..df7e20c 100644
--- a/arch/powerpc/kernel/machine_kexec.c
+++ b/arch/powerpc/kernel/machine_kexec.c
@@ -14,10 +14,34 @@
#include <linux/threads.h>
#include <linux/memblock.h>
#include <linux/of.h>
+#include <linux/irq.h>
+
#include <asm/machdep.h>
#include <asm/prom.h>
#include <asm/sections.h>
+void machine_kexec_mask_interrupts(void) {
+ unsigned int i;
+
+ for_each_irq(i) {
+ struct irq_desc *desc = irq_to_desc(i);
+
+ if (!desc || !desc->chip)
+ continue;
+
+ if (desc->chip->eoi &&
+ desc->status & IRQ_INPROGRESS)
+ desc->chip->eoi(i);
+
+ if (desc->chip->mask)
+ desc->chip->mask(i);
+
+ if (desc->chip->disable &&
+ !(desc->status & IRQ_DISABLED))
+ desc->chip->disable(i);
+ }
+}
+
void machine_crash_shutdown(struct pt_regs *regs)
{
if (ppc_md.machine_crash_shutdown)
diff --git a/arch/powerpc/kernel/machine_kexec_32.c b/arch/powerpc/kernel/machine_kexec_32.c
index ae63a96..e63f2e7 100644
--- a/arch/powerpc/kernel/machine_kexec_32.c
+++ b/arch/powerpc/kernel/machine_kexec_32.c
@@ -39,6 +39,10 @@ void default_machine_kexec(struct kimage *image)
/* Interrupts aren't acceptable while we reboot */
local_irq_disable();
+ /* mask each interrupt so we are in a more sane state for the
+ * kexec kernel */
+ machine_kexec_mask_interrupts();
+
page_list = image->head;
/* we need both effective and real address here */
--
1.6.6.1
^ permalink raw reply related
* [PATCH 2/4] powerpc/85xx: Remove call to mpic_teardown_this_cpu in kexec
From: Matthew McClintock @ 2010-09-16 22:58 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Matthew McClintock, kumar.gala
In-Reply-To: <1284677906-23787-1-git-send-email-msm@freescale.com>
We no longer need to call this explicitly as a generic version is
called by default
Signed-off-by: Matthew McClintock <msm@freescale.com>
---
arch/powerpc/platforms/85xx/smp.c | 2 --
1 files changed, 0 insertions(+), 2 deletions(-)
diff --git a/arch/powerpc/platforms/85xx/smp.c b/arch/powerpc/platforms/85xx/smp.c
index a6b1065..cb8ad3b 100644
--- a/arch/powerpc/platforms/85xx/smp.c
+++ b/arch/powerpc/platforms/85xx/smp.c
@@ -118,8 +118,6 @@ static int kexec_down_cpus = 0;
void mpc85xx_smp_kexec_cpu_down(int crash_shutdown, int secondary)
{
- mpic_teardown_this_cpu(1);
-
/* When crashing, this gets called on all CPU's we only
* take down the non-boot cpus */
if (smp_processor_id() != boot_cpuid)
--
1.6.6.1
^ permalink raw reply related
* Re: linux support for freescale e5500 core?
From: Chris Friesen @ 2010-09-16 22:26 UTC (permalink / raw)
To: Benjamin Herrenschmidt
Cc: Chris Friesen, Scott Wood, paulus, timur, linuxppc-dev
In-Reply-To: <1284674628.30449.98.camel@pasglop>
On 09/16/2010 04:03 PM, Benjamin Herrenschmidt wrote:
> On Thu, 2010-09-16 at 15:44 -0600, Chris Friesen wrote:
>> Right. We currently use a 970-series cpu and have implemented a
>> per-process flag to indicate whether 32-byte mode is needed or not.
>> We'd have to do something similar with the new cpu.
>
> Sounds like a candidate for upstreaming the patch :-)
As I recall we proposed upstreaming it a while back but there wasn't a
lot of interest since it's most useful in supporting poorly-written
legacy apps. :)
Chris
--
The author works for GENBAND Corporation (GENBAND) who is solely
responsible for this email and its contents. All enquiries regarding
this email should be addressed to GENBAND. Nortel has provided the use
of the nortel.com domain to GENBAND in connection with this email solely
for the purpose of connectivity and Nortel Networks Inc. has no
liability for the email or its contents. GENBAND's web site is
http://www.genband.com
^ permalink raw reply
* [PATCH 4/7] wire up sys_time_change_notify() on powerpc
From: Alexander Shishkin @ 2010-09-16 22:10 UTC (permalink / raw)
To: linux-kernel
Cc: Jesper Nilsson, Greg KH, Chris Friesen, John Stultz,
Andreas Schwab, Kay Sievers, linuxppc-dev, Alexander Shishkin,
Paul Mackerras, H. Peter Anvin, Kirill A. Shutemov, Andrew Morton,
Linus Torvalds, Christoph Hellwig
In-Reply-To: <1284675049-23479-1-git-send-email-virtuoso@slind.org>
Signed-off-by: Alexander Shishkin <virtuoso@slind.org>
CC: Benjamin Herrenschmidt <benh@kernel.crashing.org>
CC: Paul Mackerras <paulus@samba.org>
CC: Andrew Morton <akpm@linux-foundation.org>
CC: Andreas Schwab <schwab@linux-m68k.org>
CC: Alexander Shishkin <virtuoso@slind.org>
CC: Christoph Hellwig <hch@lst.de>
CC: Jesper Nilsson <jesper.nilsson@axis.com>
CC: linuxppc-dev@lists.ozlabs.org
CC: linux-kernel@vger.kernel.org
---
arch/powerpc/include/asm/systbl.h | 1 +
arch/powerpc/include/asm/unistd.h | 3 ++-
2 files changed, 3 insertions(+), 1 deletions(-)
diff --git a/arch/powerpc/include/asm/systbl.h b/arch/powerpc/include/asm/systbl.h
index 3d21266..124b610 100644
--- a/arch/powerpc/include/asm/systbl.h
+++ b/arch/powerpc/include/asm/systbl.h
@@ -329,3 +329,4 @@ COMPAT_SYS(rt_tgsigqueueinfo)
SYSCALL(fanotify_init)
COMPAT_SYS(fanotify_mark)
SYSCALL_SPU(prlimit64)
+SYSCALL(time_change_notify)
diff --git a/arch/powerpc/include/asm/unistd.h b/arch/powerpc/include/asm/unistd.h
index 597e6f9..6ab64da 100644
--- a/arch/powerpc/include/asm/unistd.h
+++ b/arch/powerpc/include/asm/unistd.h
@@ -348,10 +348,11 @@
#define __NR_fanotify_init 323
#define __NR_fanotify_mark 324
#define __NR_prlimit64 325
+#define __NR_time_change_notify 326
#ifdef __KERNEL__
-#define __NR_syscalls 326
+#define __NR_syscalls 327
#define __NR__exit __NR_exit
#define NR_syscalls __NR_syscalls
--
1.7.2.1.45.gb66c2
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox