* Re: System Clock runaway on Xilinx platform
From: Grant Likely @ 2008-02-06 20:29 UTC (permalink / raw)
To: khollan; +Cc: linuxppc-embedded
In-Reply-To: <15312437.post@talk.nabble.com>
On 2/6/08, khollan <khollan@daktronics.com> wrote:
>
> Hi all,
>
> Thanks for the help so far!
> I'm now running linux 2.6.21 on my custom virtex 4 board modeled after the
> ml410. The cpu clock is 300MHz and the PLB bus is 175MHz.
>
> My question is which clock is the linux system clock that keeps track of the
> date derived from? I set my date with rdate -s time.mit.edu at boot and
> then compare with the date command and rdate -p time.mit.edu and they are
> off by 20 or so seconds even just after a few minutes, this trend continues
> and it will be off by a day after a few hours. I think I just don't have
> something defined correctly but I can't figure out which.
The clock is maintained off of the PowerPC time base register (TBL,
TBU). On Virtex ppc platforms, the time base frequency is supposed to
be the same as the CPU clock. Can you figure out *exactly* how
quickly the clock is drifting?
How are you booting your Virtex platform? u-boot or a zImage.elf? If
it's a zImage, the CPU clock frequency is set in
arch/ppc/boot/simple/embed_config.c (search for CONFIG_XILINX and look
for the line that sets bd->bi_intfreq). Make XPAR_CORE_CLOCK_FREQ_HZ
in xparameters matches you CPU clock speed.
Side note: you may notice that bd->bi_tbfreq is also used but not set;
that's because bd->bi_intfreq and bd->tbfreq point to the same memory
location. (It's kind of messed up that way, don't worry too much
about it)
If you're using u-boot, then u-boot will set the cpu frequency in the
board info structure.
Cheers,
g.
--
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.
^ permalink raw reply
* [PATCH 0/4] [POWERPC] Updates to allow cpu dlpar remove to work again
From: Nathan Fontenot @ 2008-02-06 20:37 UTC (permalink / raw)
To: linuxppc-dev
The following patches make some small corrections to allow cpu dlpar remove to
work again. Cpu dlpar remove is currently failing because the cpu we are
removing may still have irq's pinned to it or have it's CPPR reset during
the cpu teardown process.
-Nathan Fontenot
^ permalink raw reply
* [PATCH 1/4][POWERPC] Update irq descriptor affinity
From: Nathan Fontenot @ 2008-02-06 20:37 UTC (permalink / raw)
To: linuxppc-dev
[-- Attachment #1: Type: text/plain, Size: 430 bytes --]
The affinity mask in the virq descriptor needs to be set before we reset the
affinity for the virq. Without doing this the call to get the new irq server
fails and we end up leaving the virq pinned to the cpu we are removing.
This does not fail the cpu remove from the kernel, but it does prevent cpu dlpar
remove operations from returning the cpu to the hypervisor.
Signed-off-by: Nathan Fontenot <nfont@austin.ibm.com>
---
[-- Attachment #2: irq_mapping.patch --]
[-- Type: text/x-patch, Size: 578 bytes --]
Index: linux-2.6/arch/powerpc/platforms/pseries/xics.c
===================================================================
--- linux-2.6.orig/arch/powerpc/platforms/pseries/xics.c 2008-02-04 14:27:43.000000000 -0600
+++ linux-2.6/arch/powerpc/platforms/pseries/xics.c 2008-02-05 10:40:06.000000000 -0600
@@ -880,8 +880,8 @@
virq, cpu);
/* Reset affinity to all cpus */
+ irq_desc[virq].affinity = CPU_MASK_ALL;
desc->chip->set_affinity(virq, CPU_MASK_ALL);
- irq_desc[irq].affinity = CPU_MASK_ALL;
unlock:
spin_unlock_irqrestore(&desc->lock, flags);
}
^ permalink raw reply
* [PATCH 2/4] [POWERPC] Split xics_teardown_cpu()
From: Nathan Fontenot @ 2008-02-06 20:37 UTC (permalink / raw)
To: linuxppc-dev
[-- Attachment #1: Type: text/plain, Size: 625 bytes --]
This patch splits off the kexec path bits of the xics_teardown_cpu()
routine into its own xics_kexec_teardown_cpu() routine. With the
previous combined routine the CPPR for a cpu that is being removed may have its
CPPR reset in the plpar_eoi() call (which explicitly sets the CPPR to a non-zero
value). Splitting of the kexec bits of the code prevents this from happening in
the cpu remove path.
Once again, this does not cause the cpu remove from the kernel to fail, but it
does cause cpu dlpar operations to not be able to return the cpu to the hypervisor.
Signed-off-by: Nathan Fontenot <nfont@austin.ibm.com>
---
[-- Attachment #2: kexec_teardown_cpu.patch --]
[-- Type: text/x-patch, Size: 2742 bytes --]
Index: linux-2.6/arch/powerpc/platforms/pseries/hotplug-cpu.c
===================================================================
--- linux-2.6.orig/arch/powerpc/platforms/pseries/hotplug-cpu.c 2008-02-04 14:27:43.000000000 -0600
+++ linux-2.6/arch/powerpc/platforms/pseries/hotplug-cpu.c 2008-02-04 16:29:27.000000000 -0600
@@ -58,7 +58,7 @@
{
local_irq_disable();
idle_task_exit();
- xics_teardown_cpu(0);
+ xics_teardown_cpu();
unregister_slb_shadow(hard_smp_processor_id(), __pa(get_slb_shadow()));
rtas_stop_self();
/* Should never get here... */
Index: linux-2.6/arch/powerpc/platforms/pseries/kexec.c
===================================================================
--- linux-2.6.orig/arch/powerpc/platforms/pseries/kexec.c 2008-02-04 14:27:43.000000000 -0600
+++ linux-2.6/arch/powerpc/platforms/pseries/kexec.c 2008-02-04 16:29:46.000000000 -0600
@@ -54,7 +54,7 @@
static void pseries_kexec_cpu_down_xics(int crash_shutdown, int secondary)
{
pseries_kexec_cpu_down(crash_shutdown, secondary);
- xics_teardown_cpu(secondary);
+ xics_kexec_teardown_cpu(secondary);
}
void __init setup_kexec_cpu_down_xics(void)
Index: linux-2.6/arch/powerpc/platforms/pseries/xics.c
===================================================================
--- linux-2.6.orig/arch/powerpc/platforms/pseries/xics.c 2008-02-04 16:25:36.000000000 -0600
+++ linux-2.6/arch/powerpc/platforms/pseries/xics.c 2008-02-04 16:28:50.000000000 -0600
@@ -776,11 +776,9 @@
}
#endif /* CONFIG_SMP */
-void xics_teardown_cpu(int secondary)
+void xics_teardown_cpu()
{
int cpu = smp_processor_id();
- unsigned int ipi;
- struct irq_desc *desc;
xics_set_cpu_priority(0);
@@ -791,9 +789,17 @@
lpar_qirr_info(cpu, 0xff);
else
direct_qirr_info(cpu, 0xff);
+}
+
+void xics_kexec_teardown_cpu(int secondary)
+{
+ unsigned int ipi;
+ struct irq_desc *desc;
+
+ xics_teardown_cpu();
/*
- * we need to EOI the IPI if we got here from kexec down IPI
+ * we need to EOI the IPI
*
* probably need to check all the other interrupts too
* should we be flagging idle loop instead?
Index: linux-2.6/arch/powerpc/platforms/pseries/xics.h
===================================================================
--- linux-2.6.orig/arch/powerpc/platforms/pseries/xics.h 2008-02-04 14:27:43.000000000 -0600
+++ linux-2.6/arch/powerpc/platforms/pseries/xics.h 2008-02-04 16:29:08.000000000 -0600
@@ -16,7 +16,8 @@
extern void xics_init_IRQ(void);
extern void xics_setup_cpu(void);
-extern void xics_teardown_cpu(int secondary);
+extern void xics_teardown_cpu(void);
+extern void xics_kexec_teardown_cpu(int secondary);
extern void xics_cause_IPI(int cpu);
extern void xics_request_IPIs(void);
extern void xics_migrate_irqs_away(void);
^ permalink raw reply
* [PATCH 3/4][POWERPC] Remove redundant of_get_cpu_node routine
From: Nathan Fontenot @ 2008-02-06 20:37 UTC (permalink / raw)
To: linuxppc-dev
[-- Attachment #1: Type: text/plain, Size: 163 bytes --]
It appears that xics.c has its own of_get_cpu_node(). Remove this and use the
common one from prom.c.
Signed-off-by: Nathan Fontenot <nfont@austin.ibm.com>
---
[-- Attachment #2: of_get_cpu_node.patch --]
[-- Type: text/x-patch, Size: 1172 bytes --]
Index: linux-2.6/arch/powerpc/platforms/pseries/xics.c
===================================================================
--- linux-2.6.orig/arch/powerpc/platforms/pseries/xics.c 2008-02-06 11:31:44.000000000 -0600
+++ linux-2.6/arch/powerpc/platforms/pseries/xics.c 2008-02-06 11:34:34.000000000 -0600
@@ -658,31 +658,6 @@
set_irq_chained_handler(cascade, pseries_8259_cascade);
}
-static struct device_node *cpuid_to_of_node(int cpu)
-{
- struct device_node *np;
- u32 hcpuid = get_hard_smp_processor_id(cpu);
-
- for_each_node_by_type(np, "cpu") {
- int i, len;
- const u32 *intserv;
-
- intserv = of_get_property(np, "ibm,ppc-interrupt-server#s",
- &len);
-
- if (!intserv)
- intserv = of_get_property(np, "reg", &len);
-
- i = len / sizeof(u32);
-
- while (i--)
- if (intserv[i] == hcpuid)
- return np;
- }
-
- return NULL;
-}
-
void __init xics_init_IRQ(void)
{
int i, j;
@@ -711,7 +686,7 @@
xics_init_host();
/* Find the server numbers for the boot cpu. */
- np = cpuid_to_of_node(boot_cpuid);
+ np = of_get_cpu_node(boot_cpuid, NULL);
BUG_ON(!np);
ireg = of_get_property(np, "ibm,ppc-interrupt-gserver#s", &ilen);
if (!ireg)
^ permalink raw reply
* [PATCH 4/4][POWERPC] Update default irq servers when boot cpu is removed
From: Nathan Fontenot @ 2008-02-06 20:37 UTC (permalink / raw)
To: linuxppc-dev
[-- Attachment #1: Type: text/plain, Size: 544 bytes --]
The xics code does update the default server information when the boot cpu is
removed. This patches recognizes when the boot cpu is being removed and updates
the appropriate information based on the new 'boot cpu'.
Failure to update this information can causes us to leave irqs pinned to cpus
that are being removed, especially when removing the boot cpu. The cpu is
removed from the kernel, but cpu dlpar remove operations fail since we cannot
return the cpu to the hypervisor.
Signed-off-by: Nathan Fonteno <nfont@austin.ibm.com>
---
[-- Attachment #2: gserver_update.patch --]
[-- Type: text/x-patch, Size: 2922 bytes --]
Index: linux-2.6/arch/powerpc/platforms/pseries/xics.c
===================================================================
--- linux-2.6.orig/arch/powerpc/platforms/pseries/xics.c 2008-02-06 11:34:34.000000000 -0600
+++ linux-2.6/arch/powerpc/platforms/pseries/xics.c 2008-02-06 13:28:25.000000000 -0600
@@ -160,6 +160,46 @@
/* High level handlers and init code */
+static void xics_update_irq_servers(void)
+{
+ int i, j;
+ struct device_node *np;
+ u32 ilen;
+ const u32 *ireg, *isize;
+ u32 hcpuid;
+
+ /* Find the server numbers for the boot cpu. */
+ np = of_get_cpu_node(boot_cpuid, NULL);
+ BUG_ON(!np);
+
+ ireg = of_get_property(np, "ibm,ppc-interrupt-gserver#s", &ilen);
+ if (!ireg) {
+ of_node_put(np);
+ return;
+ }
+
+ i = ilen / sizeof(int);
+ hcpuid = get_hard_smp_processor_id(boot_cpuid);
+
+ /* Global interrupt distribution server is specified in the last
+ * entry of "ibm,ppc-interrupt-gserver#s" property. Get the last
+ * entry fom this property for current boot cpu id and use it as
+ * default distribution server
+ */
+ for (j = 0; j < i; j += 2) {
+ if (ireg[j] == hcpuid) {
+ default_server = hcpuid;
+ default_distrib_server = ireg[j+1];
+
+ isize = of_get_property(np,
+ "ibm,interrupt-server#-size", NULL);
+ if (isize)
+ interrupt_server_size = *isize;
+ }
+ }
+
+ of_node_put(np);
+}
#ifdef CONFIG_SMP
static int get_irq_server(unsigned int virq, unsigned int strict_check)
@@ -169,6 +209,9 @@
cpumask_t cpumask = irq_desc[virq].affinity;
cpumask_t tmp = CPU_MASK_NONE;
+ if (! cpu_isset(default_server, cpu_online_map))
+ xics_update_irq_servers();
+
if (!distribute_irqs)
return default_server;
@@ -660,12 +703,9 @@
void __init xics_init_IRQ(void)
{
- int i, j;
struct device_node *np;
- u32 ilen, indx = 0;
- const u32 *ireg, *isize;
+ u32 indx = 0;
int found = 0;
- u32 hcpuid;
ppc64_boot_msg(0x20, "XICS Init");
@@ -684,34 +724,7 @@
return;
xics_init_host();
-
- /* Find the server numbers for the boot cpu. */
- np = of_get_cpu_node(boot_cpuid, NULL);
- BUG_ON(!np);
- ireg = of_get_property(np, "ibm,ppc-interrupt-gserver#s", &ilen);
- if (!ireg)
- goto skip_gserver_check;
- i = ilen / sizeof(int);
- hcpuid = get_hard_smp_processor_id(boot_cpuid);
-
- /* Global interrupt distribution server is specified in the last
- * entry of "ibm,ppc-interrupt-gserver#s" property. Get the last
- * entry fom this property for current boot cpu id and use it as
- * default distribution server
- */
- for (j = 0; j < i; j += 2) {
- if (ireg[j] == hcpuid) {
- default_server = hcpuid;
- default_distrib_server = ireg[j+1];
-
- isize = of_get_property(np,
- "ibm,interrupt-server#-size", NULL);
- if (isize)
- interrupt_server_size = *isize;
- }
- }
-skip_gserver_check:
- of_node_put(np);
+ xics_update_irq_servers();
if (firmware_has_feature(FW_FEATURE_LPAR))
ppc_md.get_irq = xics_get_irq_lpar;
^ permalink raw reply
* Fwd: Please pull linux-2.6-mpc52xx.git
From: Grant Likely @ 2008-02-06 21:34 UTC (permalink / raw)
To: Paul Mackerras, Rigby John-R61273, linuxppc-dev
In-Reply-To: <fa686aa40802061333kd6567bay92c530bb08a2aac8@mail.gmail.com>
(resend; including the mailing list this time)
Paul,
Please pull my mpc52xx tree. It contains the MPC512x work which John
Rigby has been doing. I should have got these out to you sooner, but
I forgot about them. :-(
Cheers,
g.
The following changes since commit 99e139126ab2e84be67969650f92eb37c12ab5cd:
Michael Ellerman (1):
[POWERPC] Cell IOMMU fixed mapping support
are available in the git repository at:
git://git.secretlab.ca/git/linux-2.6-mpc52xx.git for-2.6.25
John Rigby (4):
[POWERPC] mpc512x: Basic platform support
[POWERPC] mpc512x: Device tree for MPC5121 ADS
[POWERPC] mpc512x: Factor out 5200 dependencies from 52xx psc driver
[POWERPC] mpc512x: Add MPC512x PSC support to MPC52xx psc driver
arch/powerpc/Kconfig | 2 +-
arch/powerpc/boot/dts/mpc5121ads.dts | 122 ++++++++
arch/powerpc/platforms/512x/Kconfig | 20 ++
arch/powerpc/platforms/512x/Makefile | 4 +
arch/powerpc/platforms/512x/mpc5121_ads.c | 104 +++++++
arch/powerpc/platforms/Kconfig | 1 +
arch/powerpc/platforms/Kconfig.cputype | 6 +-
arch/powerpc/platforms/Makefile | 1 +
drivers/serial/Kconfig | 12 +-
drivers/serial/mpc52xx_uart.c | 431 ++++++++++++++++++++++++-----
include/asm-powerpc/mpc512x.h | 22 ++
include/asm-powerpc/mpc52xx_psc.h | 48 ++++
12 files changed, 694 insertions(+), 79 deletions(-)
create mode 100644 arch/powerpc/boot/dts/mpc5121ads.dts
create mode 100644 arch/powerpc/platforms/512x/Kconfig
create mode 100644 arch/powerpc/platforms/512x/Makefile
create mode 100644 arch/powerpc/platforms/512x/mpc5121_ads.c
create mode 100644 include/asm-powerpc/mpc512x.h
--
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.
--
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.
^ permalink raw reply
* [PATCH] Freescale enhanced Local Bus Controller FCM NAND support.
From: Scott Wood @ 2008-02-06 21:36 UTC (permalink / raw)
To: dwmw2; +Cc: linuxppc-dev, linux-mtd
Signed-off-by: Nick Spence <nick.spence@freescale.com>
Signed-off-by: Scott Wood <scottwood@freescale.com>
---
drivers/mtd/nand/Kconfig | 9 +
drivers/mtd/nand/Makefile | 1 +
drivers/mtd/nand/fsl_elbc_nand.c | 1244 ++++++++++++++++++++++++++++++++++++++
3 files changed, 1254 insertions(+), 0 deletions(-)
create mode 100644 drivers/mtd/nand/fsl_elbc_nand.c
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index 0a840d5..4a3c675 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -321,4 +321,13 @@ config MTD_NAND_ORION
No board specific support is done by this driver, each board
must advertise a platform_device for the driver to attach.
+config MTD_NAND_FSL_ELBC
+ tristate "NAND support for Freescale eLBC controllers"
+ depends on MTD_NAND && PPC_OF
+ help
+ Various Freescale chips, including the 8313, include a NAND Flash
+ Controller Module with built-in hardware ECC capabilities.
+ Enabling this option will enable you to use this to control
+ external NAND devices.
+
endif # MTD_NAND
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index e35f5ea..80d575e 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -31,5 +31,6 @@ obj-$(CONFIG_MTD_NAND_PLATFORM) += plat_nand.o
obj-$(CONFIG_MTD_ALAUDA) += alauda.o
obj-$(CONFIG_MTD_NAND_PASEMI) += pasemi_nand.o
obj-$(CONFIG_MTD_NAND_ORION) += orion_nand.o
+obj-$(CONFIG_MTD_NAND_FSL_ELBC) += fsl_elbc_nand.o
nand-objs := nand_base.o nand_bbt.o
diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c
new file mode 100644
index 0000000..b025dfe
--- /dev/null
+++ b/drivers/mtd/nand/fsl_elbc_nand.c
@@ -0,0 +1,1244 @@
+/* Freescale Enhanced Local Bus Controller NAND driver
+ *
+ * Copyright (c) 2006-2007 Freescale Semiconductor
+ *
+ * Authors: Nick Spence <nick.spence@freescale.com>,
+ * Scott Wood <scottwood@freescale.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/ioport.h>
+#include <linux/of_platform.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/nand_ecc.h>
+#include <linux/mtd/partitions.h>
+
+#include <asm/io.h>
+
+
+#define MAX_BANKS 8
+#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 elbc_bank {
+ __be32 br; /**< Base Register */
+#define BR_BA 0xFFFF8000
+#define BR_BA_SHIFT 15
+#define BR_PS 0x00001800
+#define BR_PS_SHIFT 11
+#define BR_PS_8 0x00000800 /* Port Size 8 bit */
+#define BR_PS_16 0x00001000 /* Port Size 16 bit */
+#define BR_PS_32 0x00001800 /* Port Size 32 bit */
+#define BR_DECC 0x00000600
+#define BR_DECC_SHIFT 9
+#define BR_DECC_OFF 0x00000000 /* HW ECC checking and generation off */
+#define BR_DECC_CHK 0x00000200 /* HW ECC checking on, generation off */
+#define BR_DECC_CHK_GEN 0x00000400 /* HW ECC checking and generation on */
+#define BR_WP 0x00000100
+#define BR_WP_SHIFT 8
+#define BR_MSEL 0x000000E0
+#define BR_MSEL_SHIFT 5
+#define BR_MS_GPCM 0x00000000 /* GPCM */
+#define BR_MS_FCM 0x00000020 /* FCM */
+#define BR_MS_SDRAM 0x00000060 /* SDRAM */
+#define BR_MS_UPMA 0x00000080 /* UPMA */
+#define BR_MS_UPMB 0x000000A0 /* UPMB */
+#define BR_MS_UPMC 0x000000C0 /* UPMC */
+#define BR_V 0x00000001
+#define BR_V_SHIFT 0
+#define BR_RES ~(BR_BA|BR_PS|BR_DECC|BR_WP|BR_MSEL|BR_V)
+
+ __be32 or; /**< Base Register */
+#define OR0 0x5004
+#define OR1 0x500C
+#define OR2 0x5014
+#define OR3 0x501C
+#define OR4 0x5024
+#define OR5 0x502C
+#define OR6 0x5034
+#define OR7 0x503C
+
+#define OR_FCM_AM 0xFFFF8000
+#define OR_FCM_AM_SHIFT 15
+#define OR_FCM_BCTLD 0x00001000
+#define OR_FCM_BCTLD_SHIFT 12
+#define OR_FCM_PGS 0x00000400
+#define OR_FCM_PGS_SHIFT 10
+#define OR_FCM_CSCT 0x00000200
+#define OR_FCM_CSCT_SHIFT 9
+#define OR_FCM_CST 0x00000100
+#define OR_FCM_CST_SHIFT 8
+#define OR_FCM_CHT 0x00000080
+#define OR_FCM_CHT_SHIFT 7
+#define OR_FCM_SCY 0x00000070
+#define OR_FCM_SCY_SHIFT 4
+#define OR_FCM_SCY_1 0x00000010
+#define OR_FCM_SCY_2 0x00000020
+#define OR_FCM_SCY_3 0x00000030
+#define OR_FCM_SCY_4 0x00000040
+#define OR_FCM_SCY_5 0x00000050
+#define OR_FCM_SCY_6 0x00000060
+#define OR_FCM_SCY_7 0x00000070
+#define OR_FCM_RST 0x00000008
+#define OR_FCM_RST_SHIFT 3
+#define OR_FCM_TRLX 0x00000004
+#define OR_FCM_TRLX_SHIFT 2
+#define OR_FCM_EHTR 0x00000002
+#define OR_FCM_EHTR_SHIFT 1
+};
+
+struct elbc_regs {
+ struct elbc_bank bank[8];
+ u8 res0[0x28];
+ __be32 mar; /**< UPM Address Register */
+ u8 res1[0x4];
+ __be32 mamr; /**< UPMA Mode Register */
+ __be32 mbmr; /**< UPMB Mode Register */
+ __be32 mcmr; /**< UPMC Mode Register */
+ u8 res2[0x8];
+ __be32 mrtpr; /**< Memory Refresh Timer Prescaler Register */
+ __be32 mdr; /**< UPM Data Register */
+ u8 res3[0x4];
+ __be32 lsor; /**< Special Operation Initiation Register */
+ __be32 lsdmr; /**< SDRAM Mode Register */
+ u8 res4[0x8];
+ __be32 lurt; /**< UPM Refresh Timer */
+ __be32 lsrt; /**< SDRAM Refresh Timer */
+ u8 res5[0x8];
+ __be32 ltesr; /**< Transfer Error Status Register */
+#define LTESR_BM 0x80000000
+#define LTESR_FCT 0x40000000
+#define LTESR_PAR 0x20000000
+#define LTESR_WP 0x04000000
+#define LTESR_ATMW 0x00800000
+#define LTESR_ATMR 0x00400000
+#define LTESR_CS 0x00080000
+#define LTESR_CC 0x00000001
+#define LTESR_NAND_MASK (LTESR_FCT | LTESR_PAR | LTESR_CC)
+ __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 lbcr; /**< Configuration Register */
+#define LBCR_LDIS 0x80000000
+#define LBCR_LDIS_SHIFT 31
+#define LBCR_BCTLC 0x00C00000
+#define LBCR_BCTLC_SHIFT 22
+#define LBCR_AHD 0x00200000
+#define LBCR_LPBSE 0x00020000
+#define LBCR_LPBSE_SHIFT 17
+#define LBCR_EPAR 0x00010000
+#define LBCR_EPAR_SHIFT 16
+#define LBCR_BMT 0x0000FF00
+#define LBCR_BMT_SHIFT 8
+#define LBCR_INIT 0x00040000
+ __be32 lcrr; /**< Clock Ratio Register */
+#define LCRR_DBYP 0x80000000
+#define LCRR_DBYP_SHIFT 31
+#define LCRR_BUFCMDC 0x30000000
+#define LCRR_BUFCMDC_SHIFT 28
+#define LCRR_ECL 0x03000000
+#define LCRR_ECL_SHIFT 24
+#define LCRR_EADC 0x00030000
+#define LCRR_EADC_SHIFT 16
+#define LCRR_CLKDIV 0x0000000F
+#define LCRR_CLKDIV_SHIFT 0
+ u8 res7[0x8];
+ __be32 fmr; /**< Flash Mode Register */
+#define FMR_CWTO 0x0000F000
+#define FMR_CWTO_SHIFT 12
+#define FMR_BOOT 0x00000800
+#define FMR_ECCM 0x00000100
+#define FMR_AL 0x00000030
+#define FMR_AL_SHIFT 4
+#define FMR_OP 0x00000003
+#define FMR_OP_SHIFT 0
+ __be32 fir; /**< Flash Instruction Register */
+#define FIR_OP0 0xF0000000
+#define FIR_OP0_SHIFT 28
+#define FIR_OP1 0x0F000000
+#define FIR_OP1_SHIFT 24
+#define FIR_OP2 0x00F00000
+#define FIR_OP2_SHIFT 20
+#define FIR_OP3 0x000F0000
+#define FIR_OP3_SHIFT 16
+#define FIR_OP4 0x0000F000
+#define FIR_OP4_SHIFT 12
+#define FIR_OP5 0x00000F00
+#define FIR_OP5_SHIFT 8
+#define FIR_OP6 0x000000F0
+#define FIR_OP6_SHIFT 4
+#define FIR_OP7 0x0000000F
+#define FIR_OP7_SHIFT 0
+#define FIR_OP_NOP 0x0 /* No operation and end of sequence */
+#define FIR_OP_CA 0x1 /* Issue current column address */
+#define FIR_OP_PA 0x2 /* Issue current block+page address */
+#define FIR_OP_UA 0x3 /* Issue user defined address */
+#define FIR_OP_CM0 0x4 /* Issue command from FCR[CMD0] */
+#define FIR_OP_CM1 0x5 /* Issue command from FCR[CMD1] */
+#define FIR_OP_CM2 0x6 /* Issue command from FCR[CMD2] */
+#define FIR_OP_CM3 0x7 /* Issue command from FCR[CMD3] */
+#define FIR_OP_WB 0x8 /* Write FBCR bytes from FCM buffer */
+#define FIR_OP_WS 0x9 /* Write 1 or 2 bytes from MDR[AS] */
+#define FIR_OP_RB 0xA /* Read FBCR bytes to FCM buffer */
+#define FIR_OP_RS 0xB /* Read 1 or 2 bytes to MDR[AS] */
+#define FIR_OP_CW0 0xC /* Wait then issue FCR[CMD0] */
+#define FIR_OP_CW1 0xD /* Wait then issue FCR[CMD1] */
+#define FIR_OP_RBW 0xE /* Wait then read FBCR bytes */
+#define FIR_OP_RSW 0xE /* Wait then read 1 or 2 bytes */
+ __be32 fcr; /**< Flash Command Register */
+#define FCR_CMD0 0xFF000000
+#define FCR_CMD0_SHIFT 24
+#define FCR_CMD1 0x00FF0000
+#define FCR_CMD1_SHIFT 16
+#define FCR_CMD2 0x0000FF00
+#define FCR_CMD2_SHIFT 8
+#define FCR_CMD3 0x000000FF
+#define FCR_CMD3_SHIFT 0
+ __be32 fbar; /**< Flash Block Address Register */
+#define FBAR_BLK 0x00FFFFFF
+ __be32 fpar; /**< Flash Page Address Register */
+#define FPAR_SP_PI 0x00007C00
+#define FPAR_SP_PI_SHIFT 10
+#define FPAR_SP_MS 0x00000200
+#define FPAR_SP_CI 0x000001FF
+#define FPAR_SP_CI_SHIFT 0
+#define FPAR_LP_PI 0x0003F000
+#define FPAR_LP_PI_SHIFT 12
+#define FPAR_LP_MS 0x00000800
+#define FPAR_LP_CI 0x000007FF
+#define FPAR_LP_CI_SHIFT 0
+ __be32 fbcr; /**< Flash Byte Count Register */
+#define FBCR_BC 0x00000FFF
+ u8 res11[0x8];
+ u8 res8[0xF00];
+};
+
+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 device *dev;
+ int bank; /* Chip select bank number */
+ u8 __iomem *vbase; /* Chip select base virtual address */
+ int page_size; /* NAND page size (0=512, 1=2048) */
+ unsigned int fmr; /* FCM Flash Mode Register value */
+};
+
+/* overview of the fsl elbc controller */
+
+struct fsl_elbc_ctrl {
+ struct nand_hw_control controller;
+ struct fsl_elbc_mtd *chips[MAX_BANKS];
+
+ /* device info */
+ struct device *dev;
+ struct elbc_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 */
+ unsigned int column; /* Saved column from SEQIN */
+ unsigned int index; /* Pointer to next byte to 'read' */
+ unsigned int status; /* status read from LTESR after last op */
+ unsigned int mdr; /* UPM/FCM Data Register value */
+ unsigned int use_mdr; /* Non zero if the MDR is to be set */
+ unsigned int oob; /* Non zero if operating on OOB data */
+ char *oob_poi; /* Place to write ECC after read back */
+};
+
+/* These map to the positions used by the FCM hardware ECC generator */
+
+/* Small Page FLASH with FMR[ECCM] = 0 */
+static struct nand_ecclayout fsl_elbc_oob_sp_eccm0 = {
+ .eccbytes = 3,
+ .eccpos = {6, 7, 8},
+ .oobfree = { {0, 5}, {9, 7} },
+ .oobavail = 12,
+};
+
+/* Small Page FLASH with FMR[ECCM] = 1 */
+static struct nand_ecclayout fsl_elbc_oob_sp_eccm1 = {
+ .eccbytes = 3,
+ .eccpos = {8, 9, 10},
+ .oobfree = { {0, 5}, {6, 2}, {11, 5} },
+ .oobavail = 12,
+};
+
+/* Large Page FLASH with FMR[ECCM] = 0 */
+static struct nand_ecclayout fsl_elbc_oob_lp_eccm0 = {
+ .eccbytes = 12,
+ .eccpos = {6, 7, 8, 22, 23, 24, 38, 39, 40, 54, 55, 56},
+ .oobfree = { {1, 5}, {9, 13}, {25, 13}, {41, 13}, {57, 7} },
+ .oobavail = 48,
+};
+
+/* Large Page FLASH with FMR[ECCM] = 1 */
+static struct nand_ecclayout fsl_elbc_oob_lp_eccm1 = {
+ .eccbytes = 12,
+ .eccpos = {8, 9, 10, 24, 25, 26, 40, 41, 42, 56, 57, 58},
+ .oobfree = { {1, 7}, {11, 13}, {27, 13}, {43, 13}, {59, 5} },
+ .oobavail = 48,
+};
+
+/*=================================*/
+
+/*
+ * Set up the FCM hardware block and page address fields, and the fcm
+ * structure addr field to point to the correct FCM buffer in memory
+ */
+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 elbc_regs __iomem *lbc = ctrl->regs;
+ int buf_num;
+
+ ctrl->page = page_addr;
+
+ out_be32(&lbc->fbar,
+ page_addr >> (chip->phys_erase_shift - chip->page_shift));
+
+ if (priv->page_size) {
+ out_be32(&lbc->fpar,
+ ((page_addr << FPAR_LP_PI_SHIFT) & FPAR_LP_PI) |
+ (oob ? FPAR_LP_MS : 0) | column);
+ buf_num = (page_addr & 1) << 2;
+ } else {
+ out_be32(&lbc->fpar,
+ ((page_addr << FPAR_SP_PI_SHIFT) & FPAR_SP_PI) |
+ (oob ? FPAR_SP_MS : 0) | column);
+ buf_num = page_addr & 7;
+ }
+
+ ctrl->addr = priv->vbase + buf_num * 1024;
+ ctrl->index = column;
+
+ /* for OOB data point to the second half of the buffer */
+ if (oob)
+ ctrl->index += priv->page_size ? 2048 : 512;
+
+ dev_vdbg(ctrl->dev, "set_addr: bank=%d, ctrl->addr=0x%p (0x%p), "
+ "index %x, pes %d ps %d\n",
+ buf_num, ctrl->addr, priv->vbase, ctrl->index,
+ chip->phys_erase_shift, chip->page_shift);
+}
+
+/*
+ * execute FCM command and wait for it to complete
+ */
+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 elbc_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);
+
+ dev_vdbg(ctrl->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,
+ "fsl_elbc_run_command: fbar=%08x fpar=%08x "
+ "fbcr=%08x bank=%d\n",
+ in_be32(&lbc->fbar), in_be32(&lbc->fpar),
+ in_be32(&lbc->fbcr), priv->bank);
+
+ /* execute special operation */
+ out_be32(&lbc->lsor, priv->bank);
+
+ /* wait for FCM complete flag or timeout */
+ ctrl->irq_status = 0;
+ wait_event_timeout(ctrl->irq_wait, ctrl->irq_status,
+ FCM_TIMEOUT_MSECS * HZ/1000);
+ ctrl->status = ctrl->irq_status;
+
+ /* store mdr value in case it was needed */
+ if (ctrl->use_mdr)
+ ctrl->mdr = in_be32(&lbc->mdr);
+
+ ctrl->use_mdr = 0;
+
+ dev_vdbg(ctrl->dev,
+ "fsl_elbc_run_command: stat=%08x mdr=%08x fmr=%08x\n",
+ ctrl->status, ctrl->mdr, in_be32(&lbc->fmr));
+
+ /* returns 0 on success otherwise non-zero) */
+ return ctrl->status == LTESR_CC ? 0 : -EIO;
+}
+
+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 elbc_regs __iomem *lbc = ctrl->regs;
+
+ if (priv->page_size) {
+ out_be32(&lbc->fir,
+ (FIR_OP_CW0 << FIR_OP0_SHIFT) |
+ (FIR_OP_CA << FIR_OP1_SHIFT) |
+ (FIR_OP_PA << FIR_OP2_SHIFT) |
+ (FIR_OP_CW1 << FIR_OP3_SHIFT) |
+ (FIR_OP_RBW << FIR_OP4_SHIFT));
+
+ out_be32(&lbc->fcr, (NAND_CMD_READ0 << FCR_CMD0_SHIFT) |
+ (NAND_CMD_READSTART << FCR_CMD1_SHIFT));
+ } else {
+ out_be32(&lbc->fir,
+ (FIR_OP_CW0 << FIR_OP0_SHIFT) |
+ (FIR_OP_CA << FIR_OP1_SHIFT) |
+ (FIR_OP_PA << FIR_OP2_SHIFT) |
+ (FIR_OP_RBW << FIR_OP3_SHIFT));
+
+ if (oob)
+ out_be32(&lbc->fcr, NAND_CMD_READOOB << FCR_CMD0_SHIFT);
+ else
+ out_be32(&lbc->fcr, NAND_CMD_READ0 << FCR_CMD0_SHIFT);
+ }
+}
+
+/* cmdfunc send commands to the FCM */
+static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
+ int column, int page_addr)
+{
+ struct nand_chip *chip = mtd->priv;
+ struct fsl_elbc_mtd *priv = chip->priv;
+ struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+ struct elbc_regs __iomem *lbc = ctrl->regs;
+
+ ctrl->use_mdr = 0;
+
+ /* clear the read buffer */
+ ctrl->read_bytes = 0;
+ if (command != NAND_CMD_PAGEPROG)
+ ctrl->index = 0;
+
+ switch (command) {
+ /* READ0 and READ1 read the entire buffer to use hardware ECC. */
+ case NAND_CMD_READ1:
+ column += 256;
+
+ /* fall-through */
+ case NAND_CMD_READ0:
+ dev_dbg(ctrl->dev,
+ "fsl_elbc_cmdfunc: NAND_CMD_READ0, page_addr:"
+ " 0x%x, column: 0x%x.\n", page_addr, column);
+
+
+ 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;
+
+ fsl_elbc_do_read(chip, 0);
+ fsl_elbc_run_command(mtd);
+ return;
+
+ /* READOOB reads only the OOB because no ECC is performed. */
+ case NAND_CMD_READOOB:
+ dev_vdbg(ctrl->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;
+
+ fsl_elbc_do_read(chip, 1);
+ fsl_elbc_run_command(mtd);
+ return;
+
+ /* 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");
+
+ out_be32(&lbc->fir, (FIR_OP_CW0 << FIR_OP0_SHIFT) |
+ (FIR_OP_UA << FIR_OP1_SHIFT) |
+ (FIR_OP_RBW << FIR_OP2_SHIFT));
+ 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;
+
+ set_addr(mtd, 0, 0, 0);
+ fsl_elbc_run_command(mtd);
+ return;
+
+ /* ERASE1 stores the block and page address */
+ case NAND_CMD_ERASE1:
+ dev_vdbg(ctrl->dev,
+ "fsl_elbc_cmdfunc: NAND_CMD_ERASE1, "
+ "page_addr: 0x%x.\n", page_addr);
+ set_addr(mtd, 0, page_addr, 0);
+ return;
+
+ /* ERASE2 uses the block and page address from ERASE1 */
+ case NAND_CMD_ERASE2:
+ dev_vdbg(ctrl->dev, "fsl_elbc_cmdfunc: NAND_CMD_ERASE2.\n");
+
+ out_be32(&lbc->fir,
+ (FIR_OP_CW0 << FIR_OP0_SHIFT) |
+ (FIR_OP_PA << FIR_OP1_SHIFT) |
+ (FIR_OP_CM1 << FIR_OP2_SHIFT));
+
+ out_be32(&lbc->fcr,
+ (NAND_CMD_ERASE1 << FCR_CMD0_SHIFT) |
+ (NAND_CMD_ERASE2 << FCR_CMD1_SHIFT));
+
+ out_be32(&lbc->fbcr, 0);
+ ctrl->read_bytes = 0;
+
+ fsl_elbc_run_command(mtd);
+ return;
+
+ /* 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, "
+ "page_addr: 0x%x, column: 0x%x.\n",
+ page_addr, column);
+
+ ctrl->column = column;
+ ctrl->oob = 0;
+
+ fcr = (NAND_CMD_PAGEPROG << FCR_CMD1_SHIFT) |
+ (NAND_CMD_SEQIN << FCR_CMD2_SHIFT);
+
+ if (priv->page_size) {
+ out_be32(&lbc->fir,
+ (FIR_OP_CW0 << FIR_OP0_SHIFT) |
+ (FIR_OP_CA << FIR_OP1_SHIFT) |
+ (FIR_OP_PA << FIR_OP2_SHIFT) |
+ (FIR_OP_WB << FIR_OP3_SHIFT) |
+ (FIR_OP_CW1 << FIR_OP4_SHIFT));
+
+ fcr |= NAND_CMD_READ0 << FCR_CMD0_SHIFT;
+ } else {
+ out_be32(&lbc->fir,
+ (FIR_OP_CW0 << FIR_OP0_SHIFT) |
+ (FIR_OP_CM2 << FIR_OP1_SHIFT) |
+ (FIR_OP_CA << FIR_OP2_SHIFT) |
+ (FIR_OP_PA << FIR_OP3_SHIFT) |
+ (FIR_OP_WB << FIR_OP4_SHIFT) |
+ (FIR_OP_CW1 << FIR_OP5_SHIFT));
+
+ if (column >= mtd->writesize) {
+ /* OOB area --> READOOB */
+ column -= mtd->writesize;
+ fcr |= NAND_CMD_READOOB << FCR_CMD0_SHIFT;
+ ctrl->oob = 1;
+ } else if (column < 256) {
+ /* First 256 bytes --> READ0 */
+ fcr |= NAND_CMD_READ0 << FCR_CMD0_SHIFT;
+ } else {
+ /* Second 256 bytes --> READ1 */
+ fcr |= NAND_CMD_READ1 << FCR_CMD0_SHIFT;
+ }
+ }
+
+ out_be32(&lbc->fcr, fcr);
+ set_addr(mtd, column, page_addr, 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,
+ "fsl_elbc_cmdfunc: NAND_CMD_PAGEPROG "
+ "writing %d bytes.\n", 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);
+ full_page = 0;
+ } else {
+ out_be32(&lbc->fbcr, 0);
+ full_page = 1;
+ }
+
+ fsl_elbc_run_command(mtd);
+
+ /* Read back the page in order to fill in the ECC for the
+ * caller. Is this really needed?
+ */
+ if (full_page && ctrl->oob_poi) {
+ out_be32(&lbc->fbcr, 3);
+ set_addr(mtd, 6, page_addr, 1);
+
+ 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;
+ }
+
+ ctrl->oob_poi = NULL;
+ return;
+ }
+
+ /* CMD_STATUS must read the status byte while CEB is active */
+ /* Note - it does not wait for the ready line */
+ case NAND_CMD_STATUS:
+ out_be32(&lbc->fir,
+ (FIR_OP_CM0 << FIR_OP0_SHIFT) |
+ (FIR_OP_RBW << FIR_OP1_SHIFT));
+ 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;
+
+ 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);
+ return;
+
+ /* RESET without waiting for the ready line */
+ case NAND_CMD_RESET:
+ dev_dbg(ctrl->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,
+ "fsl_elbc_cmdfunc: error, unsupported command 0x%x.\n",
+ command);
+ }
+}
+
+static void fsl_elbc_select_chip(struct mtd_info *mtd, int chip)
+{
+ /* The hardware does not seem to support multiple
+ * chips per bank.
+ */
+}
+
+/*
+ * Write buf to the FCM Controller Data Buffer
+ */
+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;
+ unsigned int bufsize = mtd->writesize + mtd->oobsize;
+
+ if (len < 0) {
+ dev_err(ctrl->dev, "write_buf of %d bytes", len);
+ ctrl->status = 0;
+ return;
+ }
+
+ if ((unsigned int)len > bufsize - ctrl->index) {
+ dev_err(ctrl->dev,
+ "write_buf beyond end of buffer "
+ "(%d requested, %u available)\n",
+ len, bufsize - ctrl->index);
+ len = bufsize - ctrl->index;
+ }
+
+ memcpy_toio(&ctrl->addr[ctrl->index], buf, len);
+ ctrl->index += len;
+}
+
+/*
+ * read a byte from either the FCM hardware buffer if it has any data left
+ * otherwise issue a command to read a single byte.
+ */
+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;
+
+ /* 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++]);
+
+ dev_err(ctrl->dev, "read_byte beyond end of buffer\n");
+ return ERR_BYTE;
+}
+
+/*
+ * Read from the FCM Controller Data Buffer
+ */
+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;
+ 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;
+
+ if (len > avail)
+ dev_err(ctrl->dev,
+ "read_buf beyond end of buffer "
+ "(%d requested, %d available)\n",
+ len, avail);
+}
+
+/*
+ * Verify buffer against the FCM Controller Data Buffer
+ */
+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;
+ int i;
+
+ if (len < 0) {
+ dev_err(ctrl->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);
+
+ ctrl->index = ctrl->read_bytes;
+ return -EINVAL;
+ }
+
+ for (i = 0; i < len; i++)
+ if (in_8(&ctrl->addr[ctrl->index + i]) != buf[i])
+ break;
+
+ ctrl->index += len;
+ return i == len && ctrl->status == LTESR_CC ? 0 : -EIO;
+}
+
+/* This function is called after Program and Erase Operations to
+ * check for success or failure.
+ */
+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 elbc_regs __iomem *lbc = ctrl->regs;
+
+ if (ctrl->status != LTESR_CC)
+ return NAND_STATUS_FAIL;
+
+ /* Use READ_STATUS command, but wait for the device to be ready */
+ ctrl->use_mdr = 0;
+ out_be32(&lbc->fir,
+ (FIR_OP_CW0 << FIR_OP0_SHIFT) |
+ (FIR_OP_RBW << FIR_OP1_SHIFT));
+ 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;
+
+ fsl_elbc_run_command(mtd);
+
+ if (ctrl->status != LTESR_CC)
+ return NAND_STATUS_FAIL;
+
+ /* The chip always seems to report that it is
+ * write-protected, even when it is not.
+ */
+ setbits8(ctrl->addr, NAND_STATUS_WP);
+ return fsl_elbc_read_byte(mtd);
+}
+
+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 elbc_regs __iomem *lbc = ctrl->regs;
+ unsigned int al;
+
+ /* calculate FMR Address Length field */
+ al = 0;
+ if (chip->pagemask & 0xffff0000)
+ al++;
+ if (chip->pagemask & 0xff000000)
+ al++;
+
+ /* add to ECCM mode set in fsl_elbc_init */
+ priv->fmr |= (12 << FMR_CWTO_SHIFT) | /* Timeout > 12 ms */
+ (al << FMR_AL_SHIFT);
+
+ dev_dbg(ctrl->dev, "fsl_elbc_init: nand->numchips = %d\n",
+ chip->numchips);
+ dev_dbg(ctrl->dev, "fsl_elbc_init: nand->chipsize = %ld\n",
+ chip->chipsize);
+ dev_dbg(ctrl->dev, "fsl_elbc_init: nand->pagemask = %8x\n",
+ chip->pagemask);
+ dev_dbg(ctrl->dev, "fsl_elbc_init: nand->chip_delay = %d\n",
+ chip->chip_delay);
+ dev_dbg(ctrl->dev, "fsl_elbc_init: nand->badblockpos = %d\n",
+ chip->badblockpos);
+ dev_dbg(ctrl->dev, "fsl_elbc_init: nand->chip_shift = %d\n",
+ chip->chip_shift);
+ dev_dbg(ctrl->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",
+ chip->phys_erase_shift);
+ dev_dbg(ctrl->dev, "fsl_elbc_init: nand->ecclayout = %p\n",
+ chip->ecclayout);
+ dev_dbg(ctrl->dev, "fsl_elbc_init: nand->ecc.mode = %d\n",
+ chip->ecc.mode);
+ dev_dbg(ctrl->dev, "fsl_elbc_init: nand->ecc.steps = %d\n",
+ chip->ecc.steps);
+ dev_dbg(ctrl->dev, "fsl_elbc_init: nand->ecc.bytes = %d\n",
+ chip->ecc.bytes);
+ dev_dbg(ctrl->dev, "fsl_elbc_init: nand->ecc.total = %d\n",
+ chip->ecc.total);
+ dev_dbg(ctrl->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 = %d\n", mtd->size);
+ dev_dbg(ctrl->dev, "fsl_elbc_init: mtd->erasesize = %d\n",
+ mtd->erasesize);
+ dev_dbg(ctrl->dev, "fsl_elbc_init: mtd->writesize = %d\n",
+ mtd->writesize);
+ dev_dbg(ctrl->dev, "fsl_elbc_init: mtd->oobsize = %d\n",
+ mtd->oobsize);
+
+ /* adjust Option Register and ECC to match Flash page size */
+ if (mtd->writesize == 512) {
+ priv->page_size = 0;
+ clrbits32(&lbc->bank[priv->bank].or, ~OR_FCM_PGS);
+ } else if (mtd->writesize == 2048) {
+ priv->page_size = 1;
+ setbits32(&lbc->bank[priv->bank].or, OR_FCM_PGS);
+ /* adjust ecc setup if needed */
+ if ((in_be32(&lbc->bank[priv->bank].br) & BR_DECC) ==
+ BR_DECC_CHK_GEN) {
+ chip->ecc.size = 512;
+ chip->ecc.layout = (priv->fmr & FMR_ECCM) ?
+ &fsl_elbc_oob_lp_eccm1 :
+ &fsl_elbc_oob_lp_eccm0;
+ mtd->ecclayout = chip->ecc.layout;
+ mtd->oobavail = chip->ecc.layout->oobavail;
+ }
+ } else {
+ dev_err(ctrl->dev,
+ "fsl_elbc_init: page size %d is not supported\n",
+ mtd->writesize);
+ return -1;
+ }
+
+ /* The default u-boot configuration on MPC8313ERDB causes errors;
+ * more delay is needed. This should be safe for other boards
+ * as well.
+ */
+ setbits32(&lbc->bank[priv->bank].or, 0x70);
+ return 0;
+}
+
+static int fsl_elbc_read_page(struct mtd_info *mtd,
+ struct nand_chip *chip,
+ uint8_t *buf)
+{
+ fsl_elbc_read_buf(mtd, buf, mtd->writesize);
+ fsl_elbc_read_buf(mtd, chip->oob_poi, mtd->oobsize);
+
+ if (fsl_elbc_wait(mtd, chip) & NAND_STATUS_FAIL)
+ mtd->ecc_stats.failed++;
+
+ return 0;
+}
+
+/* ECC will be calculated automatically, and errors will be detected in
+ * waitfunc.
+ */
+static void fsl_elbc_write_page(struct mtd_info *mtd,
+ struct nand_chip *chip,
+ const uint8_t *buf)
+{
+ struct fsl_elbc_mtd *priv = chip->priv;
+ struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+
+ fsl_elbc_write_buf(mtd, buf, mtd->writesize);
+ fsl_elbc_write_buf(mtd, chip->oob_poi, mtd->oobsize);
+
+ 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 elbc_regs __iomem *lbc = ctrl->regs;
+ struct nand_chip *chip = &priv->chip;
+
+ dev_dbg(priv->dev, "eLBC Set Information for bank %d\n", priv->bank);
+
+ /* Fill in fsl_elbc_mtd structure */
+ priv->mtd.priv = chip;
+ priv->mtd.owner = THIS_MODULE;
+ priv->fmr = 0; /* rest filled in later */
+
+ /* fill in nand_chip structure */
+ /* set up function call table */
+ chip->read_byte = fsl_elbc_read_byte;
+ chip->write_buf = fsl_elbc_write_buf;
+ chip->read_buf = fsl_elbc_read_buf;
+ chip->verify_buf = fsl_elbc_verify_buf;
+ chip->select_chip = fsl_elbc_select_chip;
+ chip->cmdfunc = fsl_elbc_cmdfunc;
+ chip->waitfunc = fsl_elbc_wait;
+
+ /* set up nand options */
+ chip->options = NAND_NO_READRDY | NAND_NO_AUTOINCR;
+
+ chip->controller = &ctrl->controller;
+ chip->priv = priv;
+
+ chip->ecc.read_page = fsl_elbc_read_page;
+ chip->ecc.write_page = fsl_elbc_write_page;
+
+ /* If CS Base Register selects full hardware ECC then use it */
+ if ((in_be32(&lbc->bank[priv->bank].br) & BR_DECC) ==
+ BR_DECC_CHK_GEN) {
+ chip->ecc.mode = NAND_ECC_HW;
+ /* put in small page settings and adjust later if needed */
+ chip->ecc.layout = (priv->fmr & FMR_ECCM) ?
+ &fsl_elbc_oob_sp_eccm1 : &fsl_elbc_oob_sp_eccm0;
+ chip->ecc.size = 512;
+ chip->ecc.bytes = 3;
+ } else {
+ /* otherwise fall back to default software ECC */
+ chip->ecc.mode = NAND_ECC_SOFT;
+ }
+
+ return 0;
+}
+
+static int fsl_elbc_chip_remove(struct fsl_elbc_mtd *priv)
+{
+ struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+
+ nand_release(&priv->mtd);
+
+ if (priv->vbase)
+ iounmap(priv->vbase);
+
+ ctrl->chips[priv->bank] = NULL;
+ kfree(priv);
+
+ return 0;
+}
+
+static int fsl_elbc_chip_probe(struct fsl_elbc_ctrl *ctrl,
+ struct device_node *node)
+{
+ struct elbc_regs __iomem *lbc = ctrl->regs;
+ struct fsl_elbc_mtd *priv;
+ struct resource res;
+#ifdef CONFIG_MTD_PARTITIONS
+ static const char *part_probe_types[]
+ = { "cmdlinepart", "RedBoot", NULL };
+ struct mtd_partition *parts;
+#endif
+ int ret;
+ int bank;
+
+ /* 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");
+ return ret;
+ }
+
+ /* find which chip select it is connected to */
+ for (bank = 0; bank < MAX_BANKS; bank++)
+ if ((in_be32(&lbc->bank[bank].br) & BR_V) &&
+ (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)
+ break;
+
+ if (bank >= MAX_BANKS) {
+ dev_err(ctrl->dev, "address did not match any chip selects\n");
+ return -ENODEV;
+ }
+
+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ ctrl->chips[bank] = priv;
+ priv->bank = bank;
+ priv->ctrl = ctrl;
+ priv->dev = ctrl->dev;
+
+ priv->vbase = ioremap(res.start, res.end - res.start + 1);
+ if (!priv->vbase) {
+ dev_err(ctrl->dev, "failed to map chip region\n");
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ ret = fsl_elbc_chip_init(priv);
+ if (ret)
+ goto err;
+
+ ret = nand_scan_ident(&priv->mtd, 1);
+ if (ret)
+ goto err;
+
+ ret = fsl_elbc_chip_init_tail(&priv->mtd);
+ if (ret)
+ goto err;
+
+ ret = nand_scan_tail(&priv->mtd);
+ if (ret)
+ goto err;
+
+#ifdef CONFIG_MTD_PARTITIONS
+ /* First look for RedBoot table or partitions on the command
+ * line, these take precedence over device tree information */
+ ret = parse_mtd_partitions(&priv->mtd, part_probe_types, &parts, 0);
+ if (ret < 0)
+ goto err;
+
+#ifdef CONFIG_MTD_OF_PARTS
+ if (ret == 0) {
+ ret = of_mtd_parse_partitions(priv->dev, &priv->mtd,
+ node, &parts);
+ if (ret < 0)
+ goto err;
+ }
+#endif
+
+ if (ret > 0)
+ add_mtd_partitions(&priv->mtd, parts, ret);
+ else
+#endif
+ add_mtd_device(&priv->mtd);
+
+ printk(KERN_INFO "eLBC NAND device at 0x%zx, bank %d\n",
+ res.start, priv->bank);
+ return 0;
+
+err:
+ fsl_elbc_chip_remove(priv);
+ return ret;
+}
+
+static int __devinit fsl_elbc_ctrl_init(struct fsl_elbc_ctrl *ctrl)
+{
+ struct elbc_regs __iomem *lbc = ctrl->regs;
+
+ /* 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 __devexit fsl_elbc_ctrl_remove(struct of_device *ofdev)
+{
+ struct fsl_elbc_ctrl *ctrl = dev_get_drvdata(&ofdev->dev);
+ int i;
+
+ 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 (ctrl->regs)
+ iounmap(ctrl->regs);
+
+ 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 elbc_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 of_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->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->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->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 struct of_platform_driver fsl_elbc_ctrl_driver = {
+ .driver = {
+ .name = "fsl-elbc",
+ },
+ .match_table = fsl_elbc_match,
+ .probe = fsl_elbc_ctrl_probe,
+ .remove = __devexit_p(fsl_elbc_ctrl_remove),
+};
+
+static int __init fsl_elbc_init(void)
+{
+ return of_register_platform_driver(&fsl_elbc_ctrl_driver);
+}
+
+static void __exit fsl_elbc_exit(void)
+{
+ of_unregister_platform_driver(&fsl_elbc_ctrl_driver);
+}
+
+module_init(fsl_elbc_init);
+module_exit(fsl_elbc_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Freescale");
+MODULE_DESCRIPTION("Freescale Enhanced Local Bus Controller MTD NAND driver");
--
1.5.3.8
^ permalink raw reply related
* Re: System Clock runaway on Xilinx platform
From: Grant Likely @ 2008-02-06 22:52 UTC (permalink / raw)
To: Kevin Holland; +Cc: linuxppc-embedded
In-Reply-To: <1202337576.20550.6.camel@kevin-laptop>
On 2/6/08, Kevin Holland <khollan@daktronics.com> wrote:
> I load with the zImage.elf, so my xparameters are set like this:
>
> #define XPAR_CPU_PPC405_CORE_CLOCK_FREQ_HZ 300000000
> #define XPAR_CORE_CLOCK_FREQ_HZ XPAR_CPU_PPC405_CORE_CLOCK_FREQ_HZ
>
> I took readings every 5 min over a 15 min period and it seems to be
> increasing by approximately 50 sec every 5 mins.
Hmm; 5 min == 300 seconds
300 - 50 == 250 seconds
300/250 = 1.2
So, timebase_period_ns is set 1.2 times faster than the actual period.
Can you confirm that the EDK frequency is actually correct? Are you
*sure* that the CPU is running at 300MHz.
Cheers,
g.
--
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.
^ permalink raw reply
* Re: System Clock runaway on Xilinx platform
From: Kevin Holland @ 2008-02-06 22:39 UTC (permalink / raw)
To: Grant Likely; +Cc: linuxppc-embedded
In-Reply-To: <fa686aa40802061229w3c6ae051kec18d1d25ad1da4@mail.gmail.com>
I load with the zImage.elf, so my xparameters are set like this:
#define XPAR_CPU_PPC405_CORE_CLOCK_FREQ_HZ 300000000
#define XPAR_CORE_CLOCK_FREQ_HZ XPAR_CPU_PPC405_CORE_CLOCK_FREQ_HZ
I took readings every 5 min over a 15 min period and it seems to be
increasing by approximately 50 sec every 5 mins.
Thanks
Kevin
On Wed, 2008-02-06 at 13:29 -0700, Grant Likely wrote:
> On 2/6/08, khollan <khollan@daktronics.com> wrote:
> >
> > Hi all,
> >
> > Thanks for the help so far!
> > I'm now running linux 2.6.21 on my custom virtex 4 board modeled after the
> > ml410. The cpu clock is 300MHz and the PLB bus is 175MHz.
> >
> > My question is which clock is the linux system clock that keeps track of the
> > date derived from? I set my date with rdate -s time.mit.edu at boot and
> > then compare with the date command and rdate -p time.mit.edu and they are
> > off by 20 or so seconds even just after a few minutes, this trend continues
> > and it will be off by a day after a few hours. I think I just don't have
> > something defined correctly but I can't figure out which.
>
> The clock is maintained off of the PowerPC time base register (TBL,
> TBU). On Virtex ppc platforms, the time base frequency is supposed to
> be the same as the CPU clock. Can you figure out *exactly* how
> quickly the clock is drifting?
>
> How are you booting your Virtex platform? u-boot or a zImage.elf? If
> it's a zImage, the CPU clock frequency is set in
> arch/ppc/boot/simple/embed_config.c (search for CONFIG_XILINX and look
> for the line that sets bd->bi_intfreq). Make XPAR_CORE_CLOCK_FREQ_HZ
> in xparameters matches you CPU clock speed.
>
> Side note: you may notice that bd->bi_tbfreq is also used but not set;
> that's because bd->bi_intfreq and bd->tbfreq point to the same memory
> location. (It's kind of messed up that way, don't worry too much
> about it)
>
> If you're using u-boot, then u-boot will set the cpu frequency in the
> board info structure.
>
> Cheers,
> g.
>
^ permalink raw reply
* Re: drivers/char/hvc_* and /Documentation/powerpc/hvcs.txt
From: Timur Tabi @ 2008-02-06 23:16 UTC (permalink / raw)
To: Olof Johansson; +Cc: linuxppc-dev
In-Reply-To: <20080126010409.GA25717@lixom.net>
Olof Johansson wrote:
> Yep, pretty much. It's real easy to write a new backend to hvc, I've got
> a couple for various bringup environments here as well.
Could you tell me which kernel options I need to set/unset in order to get my
driver to be called? My driver loads and initializes, but its put_char function
is never called. Trying to debug to the console subsystem is making me dizzy.
--
Timur Tabi
Linux kernel developer at Freescale
^ permalink raw reply
* Re: [RFC][PATCH] remove section mappinng
From: Paul Mackerras @ 2008-02-07 0:09 UTC (permalink / raw)
To: Badari Pulavarty; +Cc: linux-mm, linuxppc-dev, anton
In-Reply-To: <1201558765.29357.1.camel@dyn9047017100.beaverton.ibm.com>
Badari Pulavarty writes:
> Thank you for your input and suggestions. Does this look reasonable
> to you ?
>
> Thanks,
> Badari
>
> For memory remove, we need to clean up htab mappings for the
> section of the memory we are removing.
>
> This patch implements support for removing htab bolted mappings
> for ppc64 lpar. Other sub-archs, may need to implement similar
> functionality for the hotplug memory remove to work.
Looks OK to me.
Paul.
^ permalink raw reply
* RE: System Clock runaway on Xilinx platform
From: Stephen Neuendorffer @ 2008-02-07 0:10 UTC (permalink / raw)
To: khollan, linuxppc-embedded
In-Reply-To: <15312437.post@talk.nabble.com>
The processor is an integer factor faster than the bus, unless you're
doing something really unusual. Are you sure that's not 300 and 150?
175/150 =3D 1.16, which might be the difference you're seeing?
Steve
> -----Original Message-----
> From: linuxppc-embedded-bounces+stephen=3Dneuendorffer.name@ozlabs.org
[mailto:linuxppc-embedded-
> bounces+stephen=3Dneuendorffer.name@ozlabs.org] On Behalf Of khollan
> Sent: Wednesday, February 06, 2008 11:42 AM
> To: linuxppc-embedded@ozlabs.org
> Subject: System Clock runaway on Xilinx platform
>=20
>=20
> Hi all,
>=20
> Thanks for the help so far!
> I'm now running linux 2.6.21 on my custom virtex 4 board modeled after
the
> ml410. The cpu clock is 300MHz and the PLB bus is 175MHz.
>=20
> My question is which clock is the linux system clock that keeps track
of the
> date derived from? I set my date with rdate -s time.mit.edu at boot
and
> then compare with the date command and rdate -p time.mit.edu and they
are
> off by 20 or so seconds even just after a few minutes, this trend
continues
> and it will be off by a day after a few hours. I think I just don't
have
> something defined correctly but I can't figure out which.
>=20
> Thanks
>=20
> Kevin
> --
> View this message in context:
http://www.nabble.com/System-Clock-runaway-on-Xilinx-platform-
> tp15312437p15312437.html
> Sent from the linuxppc-embedded mailing list archive at Nabble.com.
>=20
> _______________________________________________
> Linuxppc-embedded mailing list
> Linuxppc-embedded@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-embedded
^ permalink raw reply
* 440EPX is not booting from 1Gb/128MB NAND flash
From: Nikhil Gautam @ 2008-02-07 0:36 UTC (permalink / raw)
To: linuxppc-embedded
Hi,
I am trying to boot my board which is based on Sequoia 440EPX. The
only difference between my board and the reference board is that I
have a 1 Gb NAND flash ( NAND01GW3B2A) instead of 256Mb flash present
on reference board.
In U-boot I have changed the board configuration file to reflect correct specs.
* Now the NAND chip has to be defined (no autodetection used!)
*/
#define CFG_NAND_PAGE_SIZE (2048) /* NAND chip page size */
#define CFG_NAND_BLOCK_SIZE (128 << 10) /* NAND chip block size */
#define CFG_NAND_PAGE_COUNT (64) /* NAND chip page count */
#define CFG_NAND_BAD_BLOCK_POS (5) /* Location of bad block marker */
#define CFG_NAND_4_ADDR_CYCLE /* Fourth addr used (>32MB) */
I have also changed the eeprom configuration word to
0x87788252
0x0947D010
0xA0A82358
0x0D050000
Is there any other place where some NAND configuration is defined?
Thanks
Nikhil
^ permalink raw reply
* Reorg of 32-bit dma code
From: Becky Bruce @ 2008-02-07 0:32 UTC (permalink / raw)
To: linuxppc-dev
Guys,
I've been looking at converting 32-bit powerpc's DMA code over to the
64-bit method, where there is a dma_ops structure inside archdata
that tells us which operations a device should use for DMA. I'll be
needing this shortly because I need to implement swiotlb to deal with
PCI and large amounts of RAM on 32-bit systems that support 36-bit
physical addressing. (Yes, I know. Fun for me. Woohoo.)
Anyway, I have an initial booting first pass, and wanted to get some
feedback. What I've done at this point is to make dma_64 common to both
architectures (will rename it when I send a real patch...). The
dma_direct_* functions have been changed to work on both 32/64, and the
old dma_* functionality in dma-mapping.h has been removed. For now, to
avoid whacking on every 32-bit platform, the get_dma_ops() function has
been changed to return &dma_direct_ops if the device pointer exists but
the dma_ops field is NULL. I'm not sure if this needs to be ifdef'd for
64-bit?
I've copied a bit of code over from pci_64.c into pci_common.c - some of
it isn't in use yet but will be once I start doing actual setup in the
platform code. pcibios_setup_new_device() becomes common as well. I've
also temporarily hacked the 32-bit code to set archdata.dma_data to
PCI_DRAM_OFFSET, so we can eliminate the use of virt_to_bus() and instead
use the 64-bit method, which gets rid of some ugly ifdefs in the dma code.
That's really about it - the preliminary patch is below - clearly it will
need some cleanup, but I wanted to post early and often. Any feedback or
suggestions on cleaning this up are greatly appreciated.
Thanks!
-Becky
-----------
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index ebf8d16..34a6a82 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -55,10 +55,10 @@ extra-$(CONFIG_8xx) := head_8xx.o
extra-y += vmlinux.lds
obj-y += time.o prom.o traps.o setup-common.o \
- udbg.o misc.o io.o \
+ udbg.o misc.o io.o dma_64.o\
misc_$(CONFIG_WORD_SIZE).o
obj-$(CONFIG_PPC32) += entry_32.o setup_32.o
-obj-$(CONFIG_PPC64) += dma_64.o iommu.o
+obj-$(CONFIG_PPC64) += iommu.o
obj-$(CONFIG_PPC_MULTIPLATFORM) += prom_init.o
obj-$(CONFIG_MODULES) += ppc_ksyms.o
obj-$(CONFIG_BOOTX_TEXT) += btext.o
diff --git a/arch/powerpc/kernel/dma.c b/arch/powerpc/kernel/dma_64.c
index 8423907..0199a3b 100644
--- a/arch/powerpc/kernel/dma_64.c
+++ b/arch/powerpc/kernel/dma_64.c
@@ -8,9 +8,11 @@
#include <linux/device.h>
#include <linux/dma-mapping.h>
#include <asm/bug.h>
-#include <asm/iommu.h>
#include <asm/abs_addr.h>
+#ifdef CONFIG_PPC64
+#include <asm/iommu.h>
+
/*
* Generic iommu implementation
*/
@@ -108,6 +110,8 @@ struct dma_mapping_ops dma_iommu_ops = {
.dma_supported = dma_iommu_dma_supported,
};
EXPORT_SYMBOL(dma_iommu_ops);
+#endif /* CONFIG_PPC64 */
+
/*
* Generic direct DMA implementation
@@ -126,14 +130,28 @@ static unsigned long get_dma_direct_offset(struct device *dev)
static void *dma_direct_alloc_coherent(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t flag)
{
- struct page *page;
void *ret;
+
+#ifdef CONFIG_PPC64
+ struct page *page;
int node = dev->archdata.numa_node;
page = alloc_pages_node(node, flag, get_order(size));
if (page == NULL)
return NULL;
ret = page_address(page);
+#else
+ /* ignore region specifiers */
+ flag &= ~(__GFP_DMA | __GFP_HIGHMEM);
+
+ if (dev == NULL || dev->coherent_dma_mask < 0xffffffff)
+ flag |= GFP_DMA;
+
+ ret = (void *)__get_free_pages(flag, get_order(size));
+ if (ret == NULL)
+ return NULL;
+#endif
+
memset(ret, 0, size);
*dma_handle = virt_to_abs(ret) + get_dma_direct_offset(dev);
@@ -146,10 +164,29 @@ static void dma_direct_free_coherent(struct device *dev, size_t size,
free_pages((unsigned long)vaddr, get_order(size));
}
+/*
+ * Version of dma_direct_[alloc/free]_coherent for non-coherent devices or
+ * processors.
+ */
+#ifdef CONFIG_NOT_COHERENT_CACHE
+static void *dma_direct_alloc_noncoherent(struct device *dev, size_t size,
+ dma_addr_t *dma_handle, gfp_t flag)
+{
+ return __dma_alloc_coherent(size, dma_handle, flag);
+}
+
+static void dma_direct_free_noncoherent(struct device *dev, size_t size,
+ void *vaddr, dma_addr_t dma_handle)
+{
+ __dma_free_coherent(size, vaddr);
+}
+#endif
+
static dma_addr_t dma_direct_map_single(struct device *dev, void *ptr,
size_t size,
enum dma_data_direction direction)
{
+ __dma_sync(ptr, size, direction);
return virt_to_abs(ptr) + get_dma_direct_offset(dev);
}
@@ -180,16 +217,25 @@ static void dma_direct_unmap_sg(struct device *dev, struct scatterlist *sg,
static int dma_direct_dma_supported(struct device *dev, u64 mask)
{
+#ifdef CONFIG_PPC64
/* Could be improved to check for memory though it better be
* done via some global so platforms can set the limit in case
* they have limited DMA windows
*/
return mask >= DMA_32BIT_MASK;
+#else
+ return 1;
+#endif
}
struct dma_mapping_ops dma_direct_ops = {
+#ifdef CONFIG_NOT_COHERENT_CACHE
+ .alloc_coherent = dma_direct_alloc_noncoherent,
+ .free_coherent = dma_direct_free_noncoherent,
+#else
.alloc_coherent = dma_direct_alloc_coherent,
.free_coherent = dma_direct_free_coherent,
+#endif
.map_single = dma_direct_map_single,
.unmap_single = dma_direct_unmap_single,
.map_sg = dma_direct_map_sg,
diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c
index 980fe32..35d5b87 100644
--- a/arch/powerpc/kernel/pci-common.c
+++ b/arch/powerpc/kernel/pci-common.c
@@ -56,6 +56,34 @@ resource_size_t isa_mem_base;
/* Default PCI flags is 0 */
unsigned int ppc_pci_flags;
+static struct dma_mapping_ops *pci_dma_ops;
+
+void set_pci_dma_ops(struct dma_mapping_ops *dma_ops)
+{
+ pci_dma_ops = dma_ops;
+}
+
+struct dma_mapping_ops *get_pci_dma_ops(void)
+{
+ return pci_dma_ops;
+}
+EXPORT_SYMBOL(get_pci_dma_ops);
+
+int pci_set_dma_mask(struct pci_dev *dev, u64 mask)
+{
+ return dma_set_mask(&dev->dev, mask);
+}
+
+int pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask)
+{
+ int rc;
+
+ rc = dma_set_mask(&dev->dev, mask);
+ dev->dev.coherent_dma_mask = dev->dma_mask;
+
+ return rc;
+}
+
struct pci_controller *pcibios_alloc_controller(struct device_node *dev)
{
struct pci_controller *phb;
@@ -180,6 +208,36 @@ char __devinit *pcibios_setup(char *str)
return str;
}
+void __devinit pcibios_setup_new_device(struct pci_dev *dev)
+{
+ struct dev_archdata *sd = &dev->dev.archdata;
+
+ sd->of_node = pci_device_to_OF_node(dev);
+
+ DBG("PCI: device %s OF node: %s\n", pci_name(dev),
+ sd->of_node ? sd->of_node->full_name : "<none>");
+
+ sd->dma_ops = pci_dma_ops;
+#ifdef CONFIG_PPC32
+ /* Hack for now until the platforms do setup correctly.
+ * This value is *only* good in the generic dma_direct code,
+ * setting of this needs to be done by plat code based on which
+ * set of dma_ops it has. Since we only currently use
+ * dma_direct_ops on ppc32, this works for now.
+ */
+ sd->dma_data = (void *)PCI_DRAM_OFFSET;
+#endif
+
+#ifdef CONFIG_NUMA
+ sd->numa_node = pcibus_to_node(dev->bus);
+#else
+ sd->numa_node = -1;
+#endif
+ if (ppc_md.pci_dma_dev_setup)
+ ppc_md.pci_dma_dev_setup(dev);
+}
+EXPORT_SYMBOL(pcibios_setup_new_device);
+
/*
* Reads the interrupt pin to determine if interrupt is use by card.
* If the interrupt is used, then gets the interrupt line from the
diff --git a/arch/powerpc/kernel/pci_32.c b/arch/powerpc/kernel/pci_32.c
index 88db4ff..174b77e 100644
--- a/arch/powerpc/kernel/pci_32.c
+++ b/arch/powerpc/kernel/pci_32.c
@@ -424,6 +424,7 @@ void __devinit pcibios_do_bus_setup(struct pci_bus *bus)
unsigned long io_offset;
struct resource *res;
int i;
+ struct pci_dev *dev;
/* Hookup PHB resources */
io_offset = (unsigned long)hose->io_base_virt - isa_io_base;
@@ -457,6 +458,12 @@ void __devinit pcibios_do_bus_setup(struct pci_bus *bus)
bus->resource[i+1] = res;
}
}
+
+ if (ppc_md.pci_dma_bus_setup)
+ ppc_md.pci_dma_bus_setup(bus);
+
+ list_for_each_entry(dev, &bus->devices, bus_list)
+ pcibios_setup_new_device(dev);
}
/* the next one is stolen from the alpha port... */
diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c
index 5275074..2a5487c 100644
--- a/arch/powerpc/kernel/pci_64.c
+++ b/arch/powerpc/kernel/pci_64.c
@@ -52,35 +52,6 @@ EXPORT_SYMBOL(pci_io_base);
LIST_HEAD(hose_list);
-static struct dma_mapping_ops *pci_dma_ops;
-
-void set_pci_dma_ops(struct dma_mapping_ops *dma_ops)
-{
- pci_dma_ops = dma_ops;
-}
-
-struct dma_mapping_ops *get_pci_dma_ops(void)
-{
- return pci_dma_ops;
-}
-EXPORT_SYMBOL(get_pci_dma_ops);
-
-
-int pci_set_dma_mask(struct pci_dev *dev, u64 mask)
-{
- return dma_set_mask(&dev->dev, mask);
-}
-
-int pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask)
-{
- int rc;
-
- rc = dma_set_mask(&dev->dev, mask);
- dev->dev.coherent_dma_mask = dev->dma_mask;
-
- return rc;
-}
-
static void fixup_broken_pcnet32(struct pci_dev* dev)
{
if ((dev->class>>8 == PCI_CLASS_NETWORK_ETHERNET)) {
@@ -548,26 +519,6 @@ int __devinit pcibios_map_io_space(struct pci_bus *bus)
}
EXPORT_SYMBOL_GPL(pcibios_map_io_space);
-void __devinit pcibios_setup_new_device(struct pci_dev *dev)
-{
- struct dev_archdata *sd = &dev->dev.archdata;
-
- sd->of_node = pci_device_to_OF_node(dev);
-
- DBG("PCI: device %s OF node: %s\n", pci_name(dev),
- sd->of_node ? sd->of_node->full_name : "<none>");
-
- sd->dma_ops = pci_dma_ops;
-#ifdef CONFIG_NUMA
- sd->numa_node = pcibus_to_node(dev->bus);
-#else
- sd->numa_node = -1;
-#endif
- if (ppc_md.pci_dma_dev_setup)
- ppc_md.pci_dma_dev_setup(dev);
-}
-EXPORT_SYMBOL(pcibios_setup_new_device);
-
void __devinit pcibios_do_bus_setup(struct pci_bus *bus)
{
struct pci_dev *dev;
diff --git a/include/asm-powerpc/dma-mapping.h b/include/asm-powerpc/dma-mapping.h
index bbefb69..b177bac 100644
--- a/include/asm-powerpc/dma-mapping.h
+++ b/include/asm-powerpc/dma-mapping.h
@@ -43,9 +43,10 @@ extern void __dma_sync_page(struct page *page, unsigned long offset,
#endif /* ! CONFIG_NOT_COHERENT_CACHE */
-#ifdef CONFIG_PPC64
+extern struct dma_mapping_ops dma_direct_ops;
+
/*
- * DMA operations are abstracted for G5 vs. i/pSeries, PCI vs. VIO
+ * DMA operations are abstracted for G5 vs. i/pSeries, PCI vs. VIO, etc.
*/
struct dma_mapping_ops {
void * (*alloc_coherent)(struct device *dev, size_t size,
@@ -71,8 +72,18 @@ static inline struct dma_mapping_ops *get_dma_ops(struct device *dev)
* only ISA DMA device we support is the floppy and we have a hack
* in the floppy driver directly to get a device for us.
*/
- if (unlikely(dev == NULL || dev->archdata.dma_ops == NULL))
+ if (unlikely(dev == NULL))
return NULL;
+
+ /* Some legacy devices don't support archdata dma ops.
+ * Assume those devices can use dma_direct_ops.
+ * This also serves as a default for 32-bit platforms
+ * on which all devices use the direct ops and so we haven't
+ * set up the archdata dma_ops.
+ */
+ if (dev->archdata.dma_ops == NULL)
+ return &dma_direct_ops;
+
return dev->archdata.dma_ops;
}
@@ -192,121 +203,6 @@ static inline void dma_unmap_sg(struct device *dev, struct scatterlist *sg,
* Available generic sets of operations
*/
extern struct dma_mapping_ops dma_iommu_ops;
-extern struct dma_mapping_ops dma_direct_ops;
-
-#else /* CONFIG_PPC64 */
-
-#define dma_supported(dev, mask) (1)
-
-static inline int dma_set_mask(struct device *dev, u64 dma_mask)
-{
- if (!dev->dma_mask || !dma_supported(dev, mask))
- return -EIO;
-
- *dev->dma_mask = dma_mask;
-
- return 0;
-}
-
-static inline void *dma_alloc_coherent(struct device *dev, size_t size,
- dma_addr_t * dma_handle,
- gfp_t gfp)
-{
-#ifdef CONFIG_NOT_COHERENT_CACHE
- return __dma_alloc_coherent(size, dma_handle, gfp);
-#else
- void *ret;
- /* ignore region specifiers */
- gfp &= ~(__GFP_DMA | __GFP_HIGHMEM);
-
- if (dev == NULL || dev->coherent_dma_mask < 0xffffffff)
- gfp |= GFP_DMA;
-
- ret = (void *)__get_free_pages(gfp, get_order(size));
-
- if (ret != NULL) {
- memset(ret, 0, size);
- *dma_handle = virt_to_bus(ret);
- }
-
- return ret;
-#endif
-}
-
-static inline void
-dma_free_coherent(struct device *dev, size_t size, void *vaddr,
- dma_addr_t dma_handle)
-{
-#ifdef CONFIG_NOT_COHERENT_CACHE
- __dma_free_coherent(size, vaddr);
-#else
- free_pages((unsigned long)vaddr, get_order(size));
-#endif
-}
-
-static inline dma_addr_t
-dma_map_single(struct device *dev, void *ptr, size_t size,
- enum dma_data_direction direction)
-{
- BUG_ON(direction == DMA_NONE);
-
- __dma_sync(ptr, size, direction);
-
- return virt_to_bus(ptr);
-}
-
-static inline void dma_unmap_single(struct device *dev, dma_addr_t dma_addr,
- size_t size,
- enum dma_data_direction direction)
-{
- /* We do nothing. */
-}
-
-static inline dma_addr_t
-dma_map_page(struct device *dev, struct page *page,
- unsigned long offset, size_t size,
- enum dma_data_direction direction)
-{
- BUG_ON(direction == DMA_NONE);
-
- __dma_sync_page(page, offset, size, direction);
-
- return page_to_bus(page) + offset;
-}
-
-static inline void dma_unmap_page(struct device *dev, dma_addr_t dma_address,
- size_t size,
- enum dma_data_direction direction)
-{
- /* We do nothing. */
-}
-
-static inline int
-dma_map_sg(struct device *dev, struct scatterlist *sgl, int nents,
- enum dma_data_direction direction)
-{
- struct scatterlist *sg;
- int i;
-
- BUG_ON(direction == DMA_NONE);
-
- for_each_sg(sgl, sg, nents, i) {
- BUG_ON(!sg_page(sg));
- __dma_sync_page(sg_page(sg), sg->offset, sg->length, direction);
- sg->dma_address = page_to_bus(sg_page(sg)) + sg->offset;
- }
-
- return nents;
-}
-
-static inline void dma_unmap_sg(struct device *dev, struct scatterlist *sg,
- int nhwentries,
- enum dma_data_direction direction)
-{
- /* We don't do anything here. */
-}
-
-#endif /* CONFIG_PPC64 */
static inline void dma_sync_single_for_cpu(struct device *dev,
dma_addr_t dma_handle, size_t size,
diff --git a/include/asm-powerpc/machdep.h b/include/asm-powerpc/machdep.h
index 0872ec2..7652495 100644
--- a/include/asm-powerpc/machdep.h
+++ b/include/asm-powerpc/machdep.h
@@ -85,8 +85,6 @@ struct machdep_calls {
unsigned long (*tce_get)(struct iommu_table *tbl,
long index);
void (*tce_flush)(struct iommu_table *tbl);
- void (*pci_dma_dev_setup)(struct pci_dev *dev);
- void (*pci_dma_bus_setup)(struct pci_bus *bus);
void __iomem * (*ioremap)(phys_addr_t addr, unsigned long size,
unsigned long flags);
@@ -98,6 +96,9 @@ struct machdep_calls {
#endif
#endif /* CONFIG_PPC64 */
+ void (*pci_dma_dev_setup)(struct pci_dev *dev);
+ void (*pci_dma_bus_setup)(struct pci_bus *bus);
+
int (*probe)(void);
void (*setup_arch)(void); /* Optional, may be NULL */
void (*init_early)(void);
diff --git a/include/asm-powerpc/pci.h b/include/asm-powerpc/pci.h
index a05a942..0e52c78 100644
--- a/include/asm-powerpc/pci.h
+++ b/include/asm-powerpc/pci.h
@@ -60,6 +60,14 @@ static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel)
return channel ? 15 : 14;
}
+#ifdef CONFIG_PCI
+extern void set_pci_dma_ops(struct dma_mapping_ops *dma_ops);
+extern struct dma_mapping_ops *get_pci_dma_ops(void);
+#else /* CONFIG_PCI */
+#define set_pci_dma_ops(d)
+#define get_pci_dma_ops() NULL
+#endif
+
#ifdef CONFIG_PPC64
/*
@@ -70,9 +78,6 @@ static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel)
#define PCI_DISABLE_MWI
#ifdef CONFIG_PCI
-extern void set_pci_dma_ops(struct dma_mapping_ops *dma_ops);
-extern struct dma_mapping_ops *get_pci_dma_ops(void);
-
static inline void pci_dma_burst_advice(struct pci_dev *pdev,
enum pci_dma_burst_strategy *strat,
unsigned long *strategy_parameter)
@@ -89,9 +94,6 @@ static inline void pci_dma_burst_advice(struct pci_dev *pdev,
*strat = PCI_DMA_BURST_MULTIPLE;
*strategy_parameter = cacheline_size;
}
-#else /* CONFIG_PCI */
-#define set_pci_dma_ops(d)
-#define get_pci_dma_ops() NULL
#endif
#else /* 32-bit */
^ permalink raw reply related
* Re: [PATCH 2/8] pseries: phyp dump: reserve-release proof-of-concept
From: Paul Mackerras @ 2008-02-07 0:42 UTC (permalink / raw)
To: Manish Ahuja; +Cc: ppc-dev, linasvepstas, Larry Kessler, Michael Strosaker
In-Reply-To: <47964422.7080505@austin.ibm.com>
Manish Ahuja writes:
> Initial patch for reserving memory in early boot, and freeing it later.
> If the previous boot had ended with a crash, the reserved memory would contain
> a copy of the crashed kernel data.
[snip]
> +static void __init reserve_crashed_mem(void)
> +{
> + unsigned long base, size;
> +
> + if (phyp_dump_info->phyp_dump_is_active) {
> + /* Reserve *everything* above RMR. We'll free this real soon.*/
> + base = PHYP_DUMP_RMR_END;
> + size = lmb_end_of_DRAM() - base;
> +
> + /* XXX crashed_ram_end is wrong, since it may be beyond
> + * the memory_limit, it will need to be adjusted. */
> + lmb_reserve(base, size);
> +
> + phyp_dump_info->init_reserve_start = base;
> + phyp_dump_info->init_reserve_size = size;
> + }
> + else {
> + size = phyp_dump_info->cpu_state_size +
> + phyp_dump_info->hpte_region_size +
> + PHYP_DUMP_RMR_END;
> + base = lmb_end_of_DRAM() - size;
> + printk(KERN_ERR "Manish reserve regular kernel space is %ld %ld\n", base, size);
> + lmb_reserve(base, size);
This is still reserving memory even on systems that aren't running on
pHyp at all. Please rework this so that no memory is reserved if the
system doesn't support phyp-assisted dump.
Paul.
^ permalink raw reply
* Re: Reorg of 32-bit dma code
From: Benjamin Herrenschmidt @ 2008-02-07 1:26 UTC (permalink / raw)
To: Becky Bruce; +Cc: linuxppc-dev
In-Reply-To: <Pine.LNX.4.64.0802061802310.1616@monty.am.freescale.net>
On Wed, 2008-02-06 at 18:32 -0600, Becky Bruce wrote:
>
> I've been looking at converting 32-bit powerpc's DMA code over to the
> 64-bit method, where there is a dma_ops structure inside archdata
> that tells us which operations a device should use for DMA. I'll be
> needing this shortly because I need to implement swiotlb to deal with
> PCI and large amounts of RAM on 32-bit systems that support 36-bit
> physical addressing. (Yes, I know. Fun for me. Woohoo.)
>
> Anyway, I have an initial booting first pass, and wanted to get some
> feedback. What I've done at this point is to make dma_64 common to both
> architectures (will rename it when I send a real patch...). The
> dma_direct_* functions have been changed to work on both 32/64, and the
> old dma_* functionality in dma-mapping.h has been removed. For now, to
> avoid whacking on every 32-bit platform, the get_dma_ops() function has
> been changed to return &dma_direct_ops if the device pointer exists but
> the dma_ops field is NULL. I'm not sure if this needs to be ifdef'd for
> 64-bit?
I'd prefer so yes.
> I've copied a bit of code over from pci_64.c into pci_common.c - some of
> it isn't in use yet but will be once I start doing actual setup in the
> platform code. pcibios_setup_new_device() becomes common as well.
Cool !
> I've
> also temporarily hacked the 32-bit code to set archdata.dma_data to
> PCI_DRAM_OFFSET, so we can eliminate the use of virt_to_bus() and instead
> use the 64-bit method, which gets rid of some ugly ifdefs in the dma code.
Ok.
> That's really about it - the preliminary patch is below - clearly it will
> need some cleanup, but I wanted to post early and often. Any feedback or
> suggestions on cleaning this up are greatly appreciated.
I'll have a look asap, thanks for doing this !
Ben.
^ permalink raw reply
* Re: Reorg of 32-bit dma code
From: Kumar Gala @ 2008-02-07 2:39 UTC (permalink / raw)
To: benh; +Cc: linuxppc-dev
In-Reply-To: <1202347594.7079.107.camel@pasglop>
On Feb 6, 2008, at 7:26 PM, Benjamin Herrenschmidt wrote:
>
> On Wed, 2008-02-06 at 18:32 -0600, Becky Bruce wrote:
>>
>> I've been looking at converting 32-bit powerpc's DMA code over to the
>> 64-bit method, where there is a dma_ops structure inside archdata
>> that tells us which operations a device should use for DMA. I'll be
>> needing this shortly because I need to implement swiotlb to deal with
>> PCI and large amounts of RAM on 32-bit systems that support 36-bit
>> physical addressing. (Yes, I know. Fun for me. Woohoo.)
>>
>> Anyway, I have an initial booting first pass, and wanted to get some
>> feedback. What I've done at this point is to make dma_64 common to
>> both
>> architectures (will rename it when I send a real patch...). The
>> dma_direct_* functions have been changed to work on both 32/64, and
>> the
>> old dma_* functionality in dma-mapping.h has been removed. For
>> now, to
>> avoid whacking on every 32-bit platform, the get_dma_ops() function
>> has
>> been changed to return &dma_direct_ops if the device pointer exists
>> but
>> the dma_ops field is NULL. I'm not sure if this needs to be
>> ifdef'd for
>> 64-bit?
>
> I'd prefer so yes.
Can you explain why? Got no issue with doing this, but its good to
know hy.
>> I've copied a bit of code over from pci_64.c into pci_common.c -
>> some of
>> it isn't in use yet but will be once I start doing actual setup in
>> the
>> platform code. pcibios_setup_new_device() becomes common as well.
>
> Cool !
>
>> I've
>> also temporarily hacked the 32-bit code to set archdata.dma_data to
>> PCI_DRAM_OFFSET, so we can eliminate the use of virt_to_bus() and
>> instead
>> use the 64-bit method, which gets rid of some ugly ifdefs in the
>> dma code.
>
> Ok.
>
>> That's really about it - the preliminary patch is below - clearly
>> it will
>> need some cleanup, but I wanted to post early and often. Any
>> feedback or
>> suggestions on cleaning this up are greatly appreciated.
>
> I'll have a look asap, thanks for doing this !
Also, any ideas on how to handle setting dev->archdata for non-PCI
devices would be welcome.
- k
^ permalink raw reply
* Re: Reorg of 32-bit dma code
From: Becky Bruce @ 2008-02-07 2:45 UTC (permalink / raw)
To: benh; +Cc: linuxppc-dev
In-Reply-To: <1202347594.7079.107.camel@pasglop>
On Feb 6, 2008, at 7:26 PM, Benjamin Herrenschmidt wrote:
>
> On Wed, 2008-02-06 at 18:32 -0600, Becky Bruce wrote:
>>
>> I've been looking at converting 32-bit powerpc's DMA code over to the
>> 64-bit method, where there is a dma_ops structure inside archdata
>> that tells us which operations a device should use for DMA. I'll be
>> needing this shortly because I need to implement swiotlb to deal with
>> PCI and large amounts of RAM on 32-bit systems that support 36-bit
>> physical addressing. (Yes, I know. Fun for me. Woohoo.)
>>
>> Anyway, I have an initial booting first pass, and wanted to get some
>> feedback. What I've done at this point is to make dma_64 common
>> to both
>> architectures (will rename it when I send a real patch...). The
>> dma_direct_* functions have been changed to work on both 32/64,
>> and the
>> old dma_* functionality in dma-mapping.h has been removed. For
>> now, to
>> avoid whacking on every 32-bit platform, the get_dma_ops()
>> function has
>> been changed to return &dma_direct_ops if the device pointer
>> exists but
>> the dma_ops field is NULL. I'm not sure if this needs to be
>> ifdef'd for
>> 64-bit?
>
> I'd prefer so yes.
Ok. I'll put that in, but I'd like to understand why it's necessary....
>
>> I've copied a bit of code over from pci_64.c into pci_common.c -
>> some of
>> it isn't in use yet but will be once I start doing actual setup in
>> the
>> platform code. pcibios_setup_new_device() becomes common as well.
>
> Cool !
>
>> I've
>> also temporarily hacked the 32-bit code to set archdata.dma_data to
>> PCI_DRAM_OFFSET, so we can eliminate the use of virt_to_bus() and
>> instead
>> use the 64-bit method, which gets rid of some ugly ifdefs in the
>> dma code.
>
> Ok.
>
>> That's really about it - the preliminary patch is below - clearly
>> it will
>> need some cleanup, but I wanted to post early and often. Any
>> feedback or
>> suggestions on cleaning this up are greatly appreciated.
>
> I'll have a look asap, thanks for doing this !
>
Heh, don't thank me until you've looked at it :)
Another thing that has to be done here is that I will need to audit
all the driver code for places where the dev pointer passed to
dma_alloc_coherent() and friends is NULL. I've already fixed the
gianfar driver locally, but I expect there are a pile of them. If
you have any other suggestions for dealing with this, speak up.
Cheers,
B
^ permalink raw reply
* Re: Reorg of 32-bit dma code
From: Benjamin Herrenschmidt @ 2008-02-07 2:45 UTC (permalink / raw)
To: Kumar Gala; +Cc: linuxppc-dev
In-Reply-To: <77A19FBD-7861-4D32-84BA-BDEEC39A4982@kernel.crashing.org>
On Wed, 2008-02-06 at 20:39 -0600, Kumar Gala wrote:
> > I'd prefer so yes.
>
> Can you explain why? Got no issue with doing this, but its good to
> know hy.
Just in case ... let's not modify 64 bits behaviour especially to
something that will ultimately go away. I prefer failing if DMA ops are
not set rather than using a set of ops that will cause DMA to the wrong
place.
> Also, any ideas on how to handle setting dev->archdata for non-PCI
> devices would be welcome.
This has to be done by whoever creates the struct device. Can be a bit
annoying with platform devices, I agree. One way to do it is to use the
bus notifiers mechanism, which allows you for example to have a default
for any platform device.
Ben.
^ permalink raw reply
* Re: [PATCH] net: NEWEMAC: Remove "rgmii-interface" from rgmii matching table
From: Benjamin Herrenschmidt @ 2008-02-07 2:47 UTC (permalink / raw)
To: Olof Johansson; +Cc: linuxppc-dev, Stefan Roese, jeff, netdev
In-Reply-To: <20080206163554.GA18575@lixom.net>
On Wed, 2008-02-06 at 10:35 -0600, Olof Johansson wrote:
> On Wed, Feb 06, 2008 at 10:23:40AM -0600, Josh Boyer wrote:
> > On Wed, 6 Feb 2008 10:01:57 -0600
> > Olof Johansson <olof@lixom.net> wrote:
> >
> > > On Wed, Feb 06, 2008 at 01:21:59PM +0100, Stefan Roese wrote:
> > > > With the removal the the "rgmii-interface" device_type property from the
> > > > dts files, the newemac driver needs an update to only rely on compatible
> > > > property.
> > >
> > > What about systems using an older dts, such as one kexec:ing from an
> > > older kernel?
> >
> > Like what? Kexec doesn't work on 4xx yet.
>
> Sure, but similar restrictions would apply for customers who have a
> flashed device tree that want to boot a newer kernel. Deprecating old
> device tree support is something that should be done very carefully.
In that case, we -know- there was no such thing as the proper support
for 4xx in powerpc isn't really there before 2.6.25 anyway. The only
other is Cell/Axon which we verified still works.
Ben.
^ permalink raw reply
* Re: Fwd: Please pull linux-2.6-mpc52xx.git
From: Olof Johansson @ 2008-02-07 2:52 UTC (permalink / raw)
To: Grant Likely; +Cc: linuxppc-dev, Paul Mackerras, Rigby John-R61273
In-Reply-To: <fa686aa40802061334u5700bbf3ua3bbf6d967c9b2cc@mail.gmail.com>
Hi,
On Wed, Feb 06, 2008 at 02:34:24PM -0700, Grant Likely wrote:
> John Rigby (4):
> [POWERPC] mpc512x: Basic platform support
> [POWERPC] mpc512x: Device tree for MPC5121 ADS
> [POWERPC] mpc512x: Factor out 5200 dependencies from 52xx psc driver
> [POWERPC] mpc512x: Add MPC512x PSC support to MPC52xx psc driver
mpc52xx_defconfig no longer builds for me, and the two latter of the
above patches are the ones that touch that file:
(from powerpc.git HEAD=de0723dcca6e593a12a259798a54eb0e82628fb8, seems
to include this pull):
drivers/serial/mpc52xx_uart.c:137: error: 'mpc52xx_psc_ops' undeclared here (not in a function)
drivers/serial/mpc52xx_uart.c:149: error: conflicting types for 'mpc52xx_uart_of _match'
drivers/serial/mpc52xx_uart.c:135: error: previous definition of 'mpc52xx_uart_of_match' was here
drivers/serial/mpc52xx_uart.c:153: warning: braces around scalar initializer
drivers/serial/mpc52xx_uart.c:153: warning: (near initialization for 'mpc52xx_uart_of_match[0].data')
drivers/serial/mpc52xx_uart.c:153: error: empty scalar initializer
drivers/serial/mpc52xx_uart.c:153: error: (near initialization for 'mpc52xx_uart_of_match[0].data')
drivers/serial/mpc52xx_uart.c:154: error: expected '}' before ';' token
drivers/serial/mpc52xx_uart.c:157:2: error: #endif without #if
-Olof
^ permalink raw reply
* Re: [PATCH] Fix legacy serial search for opb bus ports
From: Arnd Bergmann @ 2008-02-07 2:51 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <9efb8c0e313840ccb1bdf918406cdc812ec5de94.1202212897.git.michael@ellerman.id.au>
On Tuesday 05 February 2008, Michael Ellerman wrote:
> The fix is to add two entries to the of_device_id table, one that looks
> for type = "opb" and the other compatible = "ibm,opb".
>
> Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
Acked-by: Arnd Bergmann <arnd@arndb.de>
^ permalink raw reply
* Please pull 'for-2.6.25' branch of 4xx tree
From: Josh Boyer @ 2008-02-07 3:19 UTC (permalink / raw)
To: paulus; +Cc: linuxppc-dev
Hi Paul,
Please pull from:
master.kernel.org:/pub/scm/linux/kernel/git/jwboyer/powerpc-4xx.git for-2.6.25
to pick up some fixes that should go in for 2.6.25 and Grant's Virtex
tree.
thx,
josh
Grant Likely (2):
[POWERPC] Fix incorrectly tagged __devinitdata structures
[POWERPC] Eliminate broken OF console initialization.
Josh Boyer (2):
[POWERPC] 4xx: Fix Walnut build
Merge branch 'virtex-for-2.6.25' of git://git.secretlab.ca/git/linux-2.6-v
Sean MacLennan (1):
[POWERPC] 4xx: Fix offset value on Warp board
Stephen Neuendorffer (3):
[POWERPC] Xilinx: Update compatible to use values generated by BSP generat
[POWERPC] Xilinx: hwicap driver
[POWERPC] Xilinx: hwicap: update booting-without-of.txt
Valentine Barshak (4):
[POWERPC] 4xx: Add USB ehci-ppc-of dts bindings.
[POWERPC] 4xx: Add 440EPx Sequoia ehci dts entry
[POWERPC] Add missing native dcr dcr_ind_lock spinlock
[POWERPC] 4xx: PCIe indirect DCR spinlock fix.
Documentation/powerpc/booting-without-of.txt | 42 ++
arch/powerpc/boot/dts/sequoia.dts | 8 +
arch/powerpc/platforms/40x/Kconfig | 1 +
arch/powerpc/platforms/40x/virtex.c | 2 +-
arch/powerpc/platforms/40x/walnut.c | 1 +
arch/powerpc/platforms/44x/warp.c | 2 +-
arch/powerpc/sysdev/dcr.c | 5 +-
drivers/block/xsysace.c | 6 +-
drivers/char/Kconfig | 10 +
drivers/char/Makefile | 1 +
drivers/char/xilinx_hwicap/Makefile | 7 +
drivers/char/xilinx_hwicap/buffer_icap.c | 380 +++++++++++
drivers/char/xilinx_hwicap/buffer_icap.h | 57 ++
drivers/char/xilinx_hwicap/fifo_icap.c | 381 +++++++++++
drivers/char/xilinx_hwicap/fifo_icap.h | 62 ++
drivers/char/xilinx_hwicap/xilinx_hwicap.c | 904 ++++++++++++++++++++++++++
drivers/char/xilinx_hwicap/xilinx_hwicap.h | 193 ++++++
drivers/serial/uartlite.c | 53 +--
drivers/video/xilinxfb.c | 4 +-
include/asm-powerpc/dcr-native.h | 47 +-
20 files changed, 2102 insertions(+), 64 deletions(-)
^ permalink raw reply
* Please pull powerpc.git for-2.6.25 branch
From: Paul Mackerras @ 2008-02-07 3:22 UTC (permalink / raw)
To: torvalds; +Cc: linuxppc-dev
Linus,
Please do
git pull \
git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc.git for-2.6.25
to get another powerpc update for 2.6.25. Various bug fixes have come
in, plus there are a few patches that I missed from the previous set.
Thanks,
Paul.
arch/powerpc/Kconfig | 21 -
arch/powerpc/Makefile | 9
arch/powerpc/boot/Makefile | 126 ++++---
arch/powerpc/boot/cuboot-mpc7448hpc2.c | 0
arch/powerpc/boot/dts/adder875-redboot.dts | 1
arch/powerpc/boot/dts/adder875-uboot.dts | 1
arch/powerpc/boot/dts/mpc5121ads.dts | 122 +++++++
arch/powerpc/boot/dts/mpc8313erdb.dts | 4
arch/powerpc/boot/dts/mpc8315erdb.dts | 2
arch/powerpc/boot/dts/mpc834x_mds.dts | 2
arch/powerpc/boot/dts/mpc8572ds.dts | 12 +
arch/powerpc/boot/dts/mpc885ads.dts | 1
arch/powerpc/boot/dts/storcenter.dts | 12 -
arch/powerpc/boot/wrapper | 23 +
arch/powerpc/configs/mpc83xx_defconfig | 10 -
arch/powerpc/kernel/asm-offsets.c | 3
arch/powerpc/kernel/cputable.c | 10 -
arch/powerpc/kernel/legacy_serial.c | 3
arch/powerpc/kernel/pmc.c | 2
arch/powerpc/kernel/traps.c | 2
arch/powerpc/kernel/vio.c | 2
arch/powerpc/mm/mem.c | 7
arch/powerpc/mm/numa.c | 66 +++-
arch/powerpc/oprofile/Makefile | 2
arch/powerpc/oprofile/common.c | 6
arch/powerpc/oprofile/op_model_fsl_emb.c | 28 +
arch/powerpc/platforms/512x/Kconfig | 20 +
arch/powerpc/platforms/512x/Makefile | 4
arch/powerpc/platforms/512x/mpc5121_ads.c | 104 ++++++
arch/powerpc/platforms/82xx/mpc8272_ads.c | 3
arch/powerpc/platforms/82xx/pq2fads.c | 3
arch/powerpc/platforms/83xx/mpc832x_rdb.c | 2
arch/powerpc/platforms/83xx/mpc83xx.h | 2
arch/powerpc/platforms/83xx/usb.c | 17 +
arch/powerpc/platforms/8xx/adder875.c | 6
arch/powerpc/platforms/8xx/ep88xc.c | 1
arch/powerpc/platforms/Kconfig | 2
arch/powerpc/platforms/Kconfig.cputype | 10 -
arch/powerpc/platforms/Makefile | 1
arch/powerpc/platforms/cell/Kconfig | 7
arch/powerpc/platforms/cell/axon_msi.c | 99 ++---
arch/powerpc/platforms/cell/setup.c | 2
arch/powerpc/platforms/cell/spufs/Makefile | 2
arch/powerpc/platforms/cell/spufs/file.c | 6
arch/powerpc/platforms/cell/spufs/inode.c | 29 +-
arch/powerpc/platforms/cell/spufs/run.c | 7
arch/powerpc/platforms/cell/spufs/sched.c | 28 +
arch/powerpc/platforms/cell/spufs/spufs.h | 5
arch/powerpc/platforms/cell/spufs/sputrace.c | 250 +++++++++++++
arch/powerpc/platforms/embedded6xx/storcenter.c | 25 -
arch/powerpc/platforms/pseries/hotplug-cpu.c | 2
arch/powerpc/platforms/pseries/kexec.c | 2
arch/powerpc/platforms/pseries/reconfig.c | 1
arch/powerpc/platforms/pseries/xics.c | 118 +++---
arch/powerpc/platforms/pseries/xics.h | 3
arch/powerpc/sysdev/fsl_soc.c | 2
arch/powerpc/sysdev/mpc8xx_pic.c | 10 -
arch/powerpc/sysdev/qe_lib/qe.c | 10 -
drivers/cdrom/viocd.c | 2
drivers/net/Kconfig | 4
drivers/net/cpmac.c | 55 +--
drivers/of/base.c | 25 +
drivers/of/platform.c | 10 +
drivers/serial/Kconfig | 12 -
drivers/serial/mpc52xx_uart.c | 431 +++++++++++++++++++----
include/asm-powerpc/cputable.h | 2
include/asm-powerpc/mpc512x.h | 22 +
include/asm-powerpc/mpc52xx_psc.h | 48 +++
include/asm-powerpc/oprofile_impl.h | 2
include/asm-powerpc/reg.h | 4
include/asm-powerpc/reg_booke.h | 62 ---
include/asm-powerpc/reg_fsl_emb.h | 72 ++++
include/asm-powerpc/system.h | 2
include/asm-powerpc/vio.h | 2
include/linux/of.h | 1
75 files changed, 1534 insertions(+), 482 deletions(-)
rename arch/powerpc/boot/{cuboot-hpc2.c => cuboot-mpc7448hpc2.c} (100%)
create mode 100644 arch/powerpc/boot/dts/mpc5121ads.dts
rename arch/powerpc/oprofile/{op_model_fsl_booke.c => op_model_fsl_emb.c} (90%)
create mode 100644 arch/powerpc/platforms/512x/Kconfig
create mode 100644 arch/powerpc/platforms/512x/Makefile
create mode 100644 arch/powerpc/platforms/512x/mpc5121_ads.c
create mode 100644 arch/powerpc/platforms/cell/spufs/sputrace.c
create mode 100644 include/asm-powerpc/mpc512x.h
create mode 100644 include/asm-powerpc/reg_fsl_emb.h
Andre Detsch (1):
[POWERPC] spufs: Fix memory leak on SPU affinity
Andy Fleming (2):
[POWERPC] Made FSL Book-E PMC support more generic
[POWERPC} Add oprofile support for e300
Anton Vorontsov (2):
cpmac: convert to new Fixed PHY infrastructure
[POWERPC] qe_lib: fix few fluffy negligences
Balbir Singh (1):
[POWERPC] Fake NUMA emulation for PowerPC
Bryan O'Donoghue (1):
[POWERPC] 8xx: Add clock-frequency to adder875 and mpc885ads dts
Christoph Hellwig (1):
[POWERPC] spufs: Add marker-based tracing facility
Grant Likely (1):
[POWERPC] bootwrapper: Build multiple cuImages
Jeremy Kerr (1):
[POWERPC] spufs: Fix SPE single-step mode
John Rigby (4):
[POWERPC] mpc512x: Basic platform support
[POWERPC] mpc512x: Device tree for MPC5121 ADS
[POWERPC] mpc512x: Factor out 5200 dependencies from 52xx psc driver
[POWERPC] mpc512x: Add MPC512x PSC support to MPC52xx psc driver
Jon Loeliger (1):
[POWERPC] Fix storcenter DTS typos, feedback, IRQs.
Julia Lawall (3):
[POWERPC] arch/powerpc/platforms/pseries: Add missing of_node_put
[POWERPC] arch/powerpc/sysdev: Add missing of_node_put
[POWERPC] arch/powerpc/platforms/82xx: Add missing of_node_put
Kim Phillips (6):
[POWERPC] 83xx: configure USB clock for MPC8315E
[POWERPC] 83xx: Correct 2nd PCI controller interrupt value in mpc834x_mds dts
[POWERPC] 83xx: Add rtc node to mpc8313erdb dts
[POWERPC] 83xx: mpc832x_rdb: fix compiler warning
[POWERPC] FSL: fix mpc83xx_spi device registration
[POWERPC] 83xx: Update mpc83xx_defconfig
Kumar Gala (1):
[POWERPC] 85xx: Add second cpu to 8572 dts
Michael Ellerman (6):
[POWERPC] Add of_get_next_parent()
[POWERPC] Search for and publish cell OF platform devices earlier
[POWERPC] Create and hook up of_platform_device_shutdown
[POWERPC] Convert axon_msi to an of_platform driver
[POWERPC] Avoid DMA exception when using axon_msi with IOMMU
[POWERPC] Fix legacy serial search for opb bus ports
Nathan Fontenot (4):
[POWERPC] Update irq descriptor affinity
[POWERPC] Split xics_teardown_cpu()
[POWERPC] Remove redundant of_get_cpu_node routine
[POWERPC] Update default irq servers when boot cpu is removed
Olof Johansson (1):
[POWERPC] Fix compilation for CONFIG_DEBUGGER=n and CONFIG_KEXEC=y
Scott Wood (2):
[POWERPC] 8xx: adder875, ep88xc: fix to match recent 8xx cleanups.
[POWERPC] update_mmu_cache: Don't cache-flush non-readable pages
Stephen Rothwell (3):
[POWERPC] Avoid possible extra of_node_put in axon_msi.c
[POWERPC] iSeries: Fix section mismatch in viodsasd
[POWERPC] iSeries: Fix section mismatch in viocd
Tony Breeds (1):
[POWERPC] Use a sensible default for clock_getres() in the VDSO
^ permalink raw reply
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