* [PATCH 0/4] variable PHYS_OFFSET support
From: Russell King - ARM Linux @ 2011-01-04 10:41 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1294129208-15201-1-git-send-email-nico@fluxnic.net>
On Tue, Jan 04, 2011 at 03:20:04AM -0500, Nicolas Pitre wrote:
> So here it is, in a form which I think should be ready for merging.
>
> ARM mode is well tested.
> Thumb2 mode is only compile tested at the moment.
I don't believe this is ready for merging - there's still work to be
done with the early assembly code using PHYS_OFFSET. That currently
doesn't _appear_ to be a problem because it still uses the old platform
specific setting of PHYS_OFFSET - and that needs careful thought as:
#if (PHYS_OFFSET & 0x001fffff)
#error "PHYS_OFFSET must be at an even 2MiB boundary!"
#endif
has been eroded from 16MB downwards to 2MB over time because of
platform setups - eg, MSM for example.
As we're having to store the p:v offset (it's cheaper to store it than
your way of making PHYS_OFFSET depend on the translation and PAGE_OFFSET)
then we might as well also store what we think is the physical offset
and use that for PHYS_OFFSET too once the assembly code issue has been
sorted.
So, what I suggest is a different patch ordering:
1. Fix the assembly code not to rely upon a fixed PHYS_OFFSET (is this
even possible with the 2MB requirement?)
2. Fix the initializers in platform code (ignoring MSM).
3. Rename PHYS_OFFSET to be PLAT_PHYS_OFFSET in platform memory.h files,
defining PHYS_OFFSET in asm/memory.h to be PLAT_PHYS_OFFSET. (We
could make PHYS_OFFSET at this point be a variable, which'd stop any
new initializers using PHYS_OFFSET - which I think would be beneficial
anyway.)
4. Introduce P2V patching _with_ the module support. With this patch
create __pv_phys_offset, and if P2V patching is enabled, redefine
PHYS_OFFSET to be this variable. Note that __pv_phys_offset would
need to be exported to modules.
So, I don't think it's ready for this coming merge window.
^ permalink raw reply
* [PATCH 2/4] arm: Kconfig: remove duplicated GENERIC_HARDIRQS entry
From: Felipe Balbi @ 2011-01-04 10:38 UTC (permalink / raw)
To: linux-arm-kernel
GENERIC_HARDIRQS is defined under kernel/irq/Kconfig,
so it's safe to drop the duplicated entry and simply
select HAVE_GENERIC_HARDIRQS. While at that, also
remove GENERIC_HARDIRQS_NO__DO_IRQ because it's also
defined under kernel/irq/Kconfig when
HAVE_GENERIC_HARDIRQS is selected.
Signed-off-by: Felipe Balbi <balbi@ti.com>
---
arch/arm/Kconfig | 8 +-------
1 files changed, 1 insertions(+), 7 deletions(-)
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index d56d21c0..e6f0f8b 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -15,6 +15,7 @@ config ARM
select HAVE_FTRACE_MCOUNT_RECORD if (!XIP_KERNEL)
select HAVE_DYNAMIC_FTRACE if (!XIP_KERNEL)
select HAVE_GENERIC_DMA_COHERENT
+ select HAVE_GENERIC_HARDIRQS
select HAVE_KERNEL_GZIP
select HAVE_KERNEL_LZO
select HAVE_KERNEL_LZMA
@@ -88,10 +89,6 @@ config MCA
<file:Documentation/mca.txt> (and especially the web page given
there) before attempting to build an MCA bus kernel.
-config GENERIC_HARDIRQS
- bool
- default y
-
config STACKTRACE_SUPPORT
bool
default y
@@ -171,9 +168,6 @@ config FIQ
config ARCH_MTD_XIP
bool
-config GENERIC_HARDIRQS_NO__DO_IRQ
- def_bool y
-
config ARM_L1_CACHE_SHIFT_6
bool
help
--
1.7.3.4.598.g85356
--TYecfFk8j8mZq+dy--
^ permalink raw reply related
* [PATCH 2/2] arm: omap: select HAVE_SPARSE_IRQ
From: Felipe Balbi @ 2011-01-04 10:34 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20110104095410.GA17298@n2100.arm.linux.org.uk>
Hi,
On Tue, Jan 04, 2011 at 09:54:10AM +0000, Russell King - ARM Linux wrote:
>On Tue, Jan 04, 2011 at 11:39:26AM +0200, Felipe Balbi wrote:
>> select HAVE_SPARSE_IRQ and irq_descs can be added
>> to a radix tree instead of an array.
>
>Please move HAVE_GENERIC_HARDIRQS to the config ARM entry, and remove
>these:
>
>config GENERIC_HARDIRQS
> bool
> default y
>
>config GENERIC_HARDIRQS_NO__DO_IRQ
> def_bool y
>
>as they're in kernel/irq/Kconfig, and are visible if HAVE_GENERIC_HARDIRQS
>is enabled.
do you mean:
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index d56d21c0..70ff78a 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -14,6 +14,7 @@ config ARM
select HAVE_FUNCTION_TRACER if (!XIP_KERNEL)
select HAVE_FTRACE_MCOUNT_RECORD if (!XIP_KERNEL)
select HAVE_DYNAMIC_FTRACE if (!XIP_KERNEL)
+ select HAVE_GENERIC_HARDIRQS
select HAVE_GENERIC_DMA_COHERENT
select HAVE_KERNEL_GZIP
select HAVE_KERNEL_LZO
@@ -88,10 +89,6 @@ config MCA
<file:Documentation/mca.txt> (and especially the web page given
there) before attempting to build an MCA bus kernel.
-config GENERIC_HARDIRQS
- bool
- default y
-
config STACKTRACE_SUPPORT
bool
default y
@@ -171,9 +168,6 @@ config FIQ
config ARCH_MTD_XIP
bool
-config GENERIC_HARDIRQS_NO__DO_IRQ
- def_bool y
-
config ARM_L1_CACHE_SHIFT_6
bool
help
@@ -510,7 +504,7 @@ config ARCH_MMP
select GENERIC_CLOCKEVENTS
select TICK_ONESHOT
select PLAT_PXA
- select SPARSE_IRQ
+ select HAVE_SPARSE_IRQ
help
Support for Marvell's PXA168/PXA910(MMP) and MMP2 processor line.
@@ -589,7 +583,7 @@ config ARCH_PXA
select GENERIC_CLOCKEVENTS
select TICK_ONESHOT
select PLAT_PXA
- select SPARSE_IRQ
+ select HAVE_SPARSE_IRQ
help
Support for Intel/Marvell's PXA2xx/PXA3xx processor line.
@@ -1398,15 +1392,6 @@ config HW_PERF_EVENTS
Enable hardware performance counter support for perf events. If
disabled, perf events will use software events only.
-config SPARSE_IRQ
- def_bool n
- help
- This enables support for sparse irqs. This is useful in general
- as most CPUs have a fairly sparse array of IRQ vectors, which
- the irq_desc then maps directly on to. Systems with a high
- number of off-chip IRQs will want to treat this as
- experimental until they have been independently verified.
-
source "mm/Kconfig"
config FORCE_MAX_ZONEORDER
--
balbi
^ permalink raw reply related
* [PATCH 3/4] ARM: module support for CONFIG_ARM_PATCH_PHYS_VIRT
From: Russell King - ARM Linux @ 2011-01-04 10:06 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1294129208-15201-4-git-send-email-nico@fluxnic.net>
On Tue, Jan 04, 2011 at 03:20:07AM -0500, Nicolas Pitre wrote:
> Thanks to Russell King for his contribution to this patch.
>
> Signed-off-by: Nicolas Pitre <nicolas.pitre@linaro.org>
This should all be part of the patch introducing the patching - without
it you will end up with a kernel which has the dynamic P:V translation
support but the modules will be buggered.
^ permalink raw reply
* [PATCH v2 05/10] net/fec: add dual fec support for mx28
From: Baruch Siach @ 2011-01-04 9:59 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1294133056-21195-6-git-send-email-shawn.guo@freescale.com>
Hi Shawn,
On Tue, Jan 04, 2011 at 05:24:11PM +0800, Shawn Guo wrote:
> This patch is to add mx28 dual fec support. Here are some key notes
> for mx28 fec controller.
>
> - mx28 fec design made an assumption that it runs on a
> big-endian system, which is incorrect. As the result, the
> driver has to swap every frame going to and coming from
> the controller.
> - external phys can only be configured by fec0, which means
> fec1 can not work independently and both phys need to be
> configured by mii_bus attached on fec0.
> - mx28 fec reset will get mac address registers reset too.
> - MII/RMII mode and 10M/100M speed are configured differently
> from i.mx/mxs fec controller.
> - ETHER_EN bit must be set to get interrupt work.
>
> Signed-off-by: Shawn Guo <shawn.guo@freescale.com>
> ---
> Changes for v2:
> - Use module parameter fec.macaddr over new kernel command line
> fec_mac to pass mac address
Since you introduce this new kernel command line parameter in patch #3 of this
series, why not just make it right in the first place? This should make both
patches smaller and easier for review.
> - Update comment in fec_get_mac() to stop using confusing word
> "default"
> - Fix copyright breakage in fec.h
Ditto.
> drivers/net/Kconfig | 7 ++-
> drivers/net/fec.c | 139 ++++++++++++++++++++++++++++++++++++++++----------
> drivers/net/fec.h | 5 +-
> include/linux/fec.h | 3 +-
> 4 files changed, 120 insertions(+), 34 deletions(-)
[snip]
> diff --git a/drivers/net/fec.c b/drivers/net/fec.c
> index f147508..b2b3e37 100644
> --- a/drivers/net/fec.c
> +++ b/drivers/net/fec.c
> @@ -17,6 +17,8 @@
> *
> * Bug fixes and cleanup by Philippe De Muyter (phdm at macqel.be)
> * Copyright (c) 2004-2006 Macq Electronique SA.
> + *
> + * Copyright (C) 2010 Freescale Semiconductor, Inc.
> */
>
> #include <linux/module.h>
> @@ -45,21 +47,34 @@
>
> #include <asm/cacheflush.h>
>
> -#ifndef CONFIG_ARCH_MXC
> +#if !defined(CONFIG_ARCH_MXC) && !defined(CONFIG_SOC_IMX28)
> #include <asm/coldfire.h>
> #include <asm/mcfsim.h>
> #endif
>
> #include "fec.h"
>
> -#ifdef CONFIG_ARCH_MXC
> -#include <mach/hardware.h>
Since you now remove mach/hardware.h for ARCH_MXC, does this build for all
i.MX variants?
> +#ifdef CONFIG_SOC_IMX28
> +/*
> + * mx28 does not have MIIGSK registers
> + */
> +#undef FEC_MIIGSK_ENR
> +#include <mach/mxs.h>
> +#else
> +#define cpu_is_mx28() (0)
> +#endif
This breaks kernels for multiple archs (e.g. i.MX28 and i.MX25). Please use
run-time detection of CPU type, and do the MII/RMII etc. configuration
accordingly.
> +
> +#if defined(CONFIG_ARCH_MXC) || defined(CONFIG_SOC_IMX28)
> #define FEC_ALIGNMENT 0xf
> #else
> #define FEC_ALIGNMENT 0x3
> #endif
[snip]
baruch
--
~. .~ Tk Open Systems
=}------------------------------------------------ooO--U--Ooo------------{=
- baruch at tkos.co.il - tel: +972.2.679.5364, http://www.tkos.co.il -
^ permalink raw reply
* [PATCH 2/2] arm: omap: select HAVE_SPARSE_IRQ
From: Russell King - ARM Linux @ 2011-01-04 9:55 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20110104095410.GA17298@n2100.arm.linux.org.uk>
On Tue, Jan 04, 2011 at 09:54:10AM +0000, Russell King - ARM Linux wrote:
> On Tue, Jan 04, 2011 at 11:39:26AM +0200, Felipe Balbi wrote:
> > select HAVE_SPARSE_IRQ and irq_descs can be added
> > to a radix tree instead of an array.
>
> Please move HAVE_GENERIC_HARDIRQS to the config ARM entry, and remove
> these:
>
> config GENERIC_HARDIRQS
> bool
> default y
>
> config GENERIC_HARDIRQS_NO__DO_IRQ
> def_bool y
>
> as they're in kernel/irq/Kconfig, and are visible if HAVE_GENERIC_HARDIRQS
> is enabled.
Note also that should be a separate patch from adding HAVE_SPARSE_IRQ to
OMAP, as it's an independent but necessary change.
^ permalink raw reply
* [PATCH 2/2] arm: omap: select HAVE_SPARSE_IRQ
From: Russell King - ARM Linux @ 2011-01-04 9:54 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1294133966-20279-3-git-send-email-balbi@ti.com>
On Tue, Jan 04, 2011 at 11:39:26AM +0200, Felipe Balbi wrote:
> select HAVE_SPARSE_IRQ and irq_descs can be added
> to a radix tree instead of an array.
Please move HAVE_GENERIC_HARDIRQS to the config ARM entry, and remove
these:
config GENERIC_HARDIRQS
bool
default y
config GENERIC_HARDIRQS_NO__DO_IRQ
def_bool y
as they're in kernel/irq/Kconfig, and are visible if HAVE_GENERIC_HARDIRQS
is enabled.
^ permalink raw reply
* [PATCH 2/2] arm: omap: select HAVE_SPARSE_IRQ
From: Felipe Balbi @ 2011-01-04 9:39 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1294133966-20279-1-git-send-email-balbi@ti.com>
select HAVE_SPARSE_IRQ and irq_descs can be added
to a radix tree instead of an array.
Signed-off-by: Felipe Balbi <balbi@ti.com>
---
arch/arm/Kconfig | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index d56d21c0..c4ffe2e 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -826,6 +826,8 @@ config ARCH_DAVINCI
config ARCH_OMAP
bool "TI OMAP"
select HAVE_CLK
+ select HAVE_GENERIC_HARDIRQS
+ select HAVE_SPARSE_IRQ
select ARCH_REQUIRE_GPIOLIB
select ARCH_HAS_CPUFREQ
select GENERIC_CLOCKEVENTS
--
1.7.3.4.598.g85356
^ permalink raw reply related
* [PATCH 1/2] arm: omap: gpio: don't access irq_desc array directly
From: Felipe Balbi @ 2011-01-04 9:39 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1294133966-20279-1-git-send-email-balbi@ti.com>
Instead of accessing the irq_desc array directly
we can use irq_to_desc(irq). That will allow us to,
if wanted, select SPARSE_IRQ and irq_descs will be
added to a radix tree, instead of a array.
Signed-off-by: Felipe Balbi <balbi@ti.com>
---
arch/arm/plat-omap/gpio.c | 10 +++++++---
1 files changed, 7 insertions(+), 3 deletions(-)
diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c
index c05c653..c351758 100644
--- a/arch/arm/plat-omap/gpio.c
+++ b/arch/arm/plat-omap/gpio.c
@@ -905,8 +905,10 @@ static int gpio_irq_type(unsigned irq, unsigned type)
spin_lock_irqsave(&bank->lock, flags);
retval = _set_gpio_triggering(bank, get_gpio_index(gpio), type);
if (retval == 0) {
- irq_desc[irq].status &= ~IRQ_TYPE_SENSE_MASK;
- irq_desc[irq].status |= type;
+ struct irq_desc *d = irq_to_desc(irq);
+
+ d->status &= ~IRQ_TYPE_SENSE_MASK;
+ d->status |= type;
}
spin_unlock_irqrestore(&bank->lock, flags);
@@ -1925,7 +1927,9 @@ static int __init _omap_gpio_init(void)
for (j = bank->virtual_irq_start;
j < bank->virtual_irq_start + gpio_count; j++) {
- lockdep_set_class(&irq_desc[j].lock, &gpio_lock_class);
+ struct irq_desc *d = irq_to_desc(j);
+
+ lockdep_set_class(&d->lock, &gpio_lock_class);
set_irq_chip_data(j, bank);
if (bank_is_mpuio(bank))
set_irq_chip(j, &mpuio_irq_chip);
--
1.7.3.4.598.g85356
^ permalink raw reply related
* [PATCH 0/2] IRQ-related changes
From: Felipe Balbi @ 2011-01-04 9:39 UTC (permalink / raw)
To: linux-arm-kernel
Hi,
The following two patches are enabling SPARSE_IRQ
numbering scheme on OMAP. I lightly tested on a pandaboard
and seems to be working fine so far:
# cat /proc/interrupts
CPU0 CPU1
39: 1 0 GIC TWL6030-PIH
44: 1758 0 GIC DMA
69: 7615 0 GIC gp timer
88: 195 0 GIC i2c_omap
89: 0 0 GIC i2c_omap
93: 0 0 GIC i2c_omap
94: 0 0 GIC i2c_omap
102: 0 0 GIC serial idle
104: 0 0 GIC serial idle
105: 0 0 GIC serial idle
106: 743 0 GIC serial idle, OMAP UART2
115: 2356 0 GIC mmc0
160: 0 0 GPIO mmc0
376: 0 0 twl6030 twl4030_pwrbutton
379: 0 0 twl6030 rtc0
IPI: 1111 9537
LOC: 0 0
Err: 0
The first patch just removes the direct access to irq_desc
array and converts it to irq_to_desc(). Second patch simply
selects HAVE_GENERIC_HARDIRQS and HAVE_SPARSE_IRQ. I boot
tested with and without enabling:
-> General setup
-> IRQ subsystem
-> SPARSE_IRQ
and both kernels boot fine.
Felipe Balbi (2):
arm: omap: gpio: don't access irq_desc array directly
arm: omap: select HAVE_SPARSE_IRQ
arch/arm/Kconfig | 2 ++
arch/arm/plat-omap/gpio.c | 10 +++++++---
2 files changed, 9 insertions(+), 3 deletions(-)
--
1.7.3.4.598.g85356
^ permalink raw reply
* [PATCH v4] davinci: Support various speedgrades for MityDSP-L138 and MityARM-1808 SoMs
From: Nori, Sekhar @ 2011-01-04 9:35 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1294060905-14254-1-git-send-email-michael.williamson@criticallink.com>
On Mon, Jan 03, 2011 at 18:51:45, Michael Williamson wrote:
> For the MityDSP-L138/MityARM-1808 SoMs, the speed grade can be determined
> from the part number string read from the factory configuration block on
> the on-board I2C PROM. Configure the maximum CPU speed based on this
> information.
>
> This patch was tested using a MityDSP-L138 and MityARM-1808 at various
> speedgrades. Also, for code coverage, a bogus configuration was tested
> as well as a configuration having an unknown part number.
Thanks for the extensive testing. This looks good to me, except,
a whitespace nit below. But otherwise:
Reviewed-by: Sekhar Nori <nsekhar@ti.com>
> +#ifdef CONFIG_CPU_FREQ
> +static void mityomapl138_cpufreq_init(const char *partnum)
> +{
> + int i, ret;
> +
> + for (i = 0; partnum && i < ARRAY_SIZE(mityomapl138_pn_info); i++) {
> + /*
> + * the part number has additional characters beyond what is
> + * stored in the table. This information is not needed for
> + * determining the speed grade, and would require several
> + * more table entries. Only check the first N characters
> + * for a match.
> + */
> + if (!strncmp(partnum, mityomapl138_pn_info[i].part_no,
> + strlen(mityomapl138_pn_info[i].part_no))) {
> + da850_max_speed = mityomapl138_pn_info[i].max_freq;
> + break;
The indentation here makes it look like strlen is part of if()
body. May be you can indent it substantially to the right. I will
leave it to your judgment.
Thanks,
Sekhar
^ permalink raw reply
* [PATCH v2 10/10] ARM: mxs: add initial pm support
From: Shawn Guo @ 2011-01-04 9:24 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1294133056-21195-1-git-send-email-shawn.guo@freescale.com>
This is a very initial pm support and basically does nothing.
With this pm support entry, drivers can start testing their own
pm functions.
Signed-off-by: Shawn Guo <shawn.guo@freescale.com>
---
Changes for v2:
- Let build of pm.c depend on CONFIG_PM
- Remove the blank line above device_initcall in pm.c
arch/arm/mach-mxs/Makefile | 2 ++
arch/arm/mach-mxs/pm.c | 43 +++++++++++++++++++++++++++++++++++++++++++
2 files changed, 45 insertions(+), 0 deletions(-)
create mode 100644 arch/arm/mach-mxs/pm.c
diff --git a/arch/arm/mach-mxs/Makefile b/arch/arm/mach-mxs/Makefile
index f23ebbd..45a2925 100644
--- a/arch/arm/mach-mxs/Makefile
+++ b/arch/arm/mach-mxs/Makefile
@@ -1,6 +1,8 @@
# Common support
obj-y := clock.o devices.o gpio.o icoll.o iomux.o ocotp.o system.o timer.o
+obj-$(CONFIG_PM) += pm.o
+
obj-$(CONFIG_SOC_IMX23) += clock-mx23.o mm-mx23.o
obj-$(CONFIG_SOC_IMX28) += clock-mx28.o mm-mx28.o
diff --git a/arch/arm/mach-mxs/pm.c b/arch/arm/mach-mxs/pm.c
new file mode 100644
index 0000000..fb042da
--- /dev/null
+++ b/arch/arm/mach-mxs/pm.c
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2010 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/suspend.h>
+#include <linux/io.h>
+#include <mach/system.h>
+
+static int mxs_suspend_enter(suspend_state_t state)
+{
+ switch (state) {
+ case PM_SUSPEND_MEM:
+ arch_idle();
+ break;
+
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static struct platform_suspend_ops mxs_suspend_ops = {
+ .enter = mxs_suspend_enter,
+ .valid = suspend_valid_only_mem,
+};
+
+static int __init mxs_pm_init(void)
+{
+ suspend_set_ops(&mxs_suspend_ops);
+ return 0;
+}
+device_initcall(mxs_pm_init);
--
1.7.1
^ permalink raw reply related
* [PATCH v2 09/10] ARM: mx28: read fec mac address from ocotp
From: Shawn Guo @ 2011-01-04 9:24 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1294133056-21195-1-git-send-email-shawn.guo@freescale.com>
Read fec mac address from ocotp and save it into fec_platform_data
mac field for fec driver to use.
Signed-off-by: Shawn Guo <shawn.guo@freescale.com>
---
Changes for v2:
- It's not necessary to remove "const" for fec_platform_data from
platform-fec.c and devices-common.h, so add it back.
- Hard-coding Freescale OUI (00:04:9f) instead of just the first
two two octets.
- Correct the return of mx28evk_fec_get_mac() and check it
with caller
arch/arm/mach-mxs/mach-mx28evk.c | 32 ++++++++++++++++++++++++++++++++
1 files changed, 32 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-mxs/mach-mx28evk.c b/arch/arm/mach-mxs/mach-mx28evk.c
index def6519..54fa512 100644
--- a/arch/arm/mach-mxs/mach-mx28evk.c
+++ b/arch/arm/mach-mxs/mach-mx28evk.c
@@ -129,12 +129,44 @@ static struct fec_platform_data mx28_fec_pdata[] = {
},
};
+static int __init mx28evk_fec_get_mac(void)
+{
+ int i, ret;
+ u32 val;
+
+ /*
+ * OCOTP only stores the last 4 octets for each mac address,
+ * so hard-code Freescale OUI (00:04:9f) here.
+ */
+ for (i = 0; i < 2; i++) {
+ ret = mxs_read_ocotp(0x20 + i * 0x10, 1, &val);
+ if (ret)
+ goto error;
+
+ mx28_fec_pdata[i].mac[0] = 0x00;
+ mx28_fec_pdata[i].mac[1] = 0x04;
+ mx28_fec_pdata[i].mac[2] = 0x9f;
+ mx28_fec_pdata[i].mac[3] = (val >> 16) & 0xff;
+ mx28_fec_pdata[i].mac[4] = (val >> 8) & 0xff;
+ mx28_fec_pdata[i].mac[5] = (val >> 0) & 0xff;
+ }
+
+ return 0;
+
+error:
+ pr_err("%s: timeout when reading fec mac from OCOTP\n", __func__);
+ return ret;
+}
+
static void __init mx28evk_init(void)
{
mxs_iomux_setup_multiple_pads(mx28evk_pads, ARRAY_SIZE(mx28evk_pads));
mx28_add_duart();
+ if (mx28evk_fec_get_mac())
+ pr_warn("%s: failed on fec mac setup\n", __func__);
+
mx28evk_fec_reset();
mx28_add_fec(0, &mx28_fec_pdata[0]);
#ifdef CONFIG_FEC2
--
1.7.1
^ permalink raw reply related
* [PATCH v2 08/10] ARM: mxs: add ocotp read function
From: Shawn Guo @ 2011-01-04 9:24 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1294133056-21195-1-git-send-email-shawn.guo@freescale.com>
Signed-off-by: Shawn Guo <shawn.guo@freescale.com>
---
Changes for v2:
- Add mutex locking for mxs_read_ocotp()
- Use type size_t for count and i
- Add comment for clk_enable/disable skipping
- Add ERROR bit clearing and polling step
arch/arm/mach-mxs/Makefile | 2 +-
arch/arm/mach-mxs/include/mach/common.h | 1 +
arch/arm/mach-mxs/ocotp.c | 79 +++++++++++++++++++++++++++++++
3 files changed, 81 insertions(+), 1 deletions(-)
create mode 100644 arch/arm/mach-mxs/ocotp.c
diff --git a/arch/arm/mach-mxs/Makefile b/arch/arm/mach-mxs/Makefile
index 39d3f9c..f23ebbd 100644
--- a/arch/arm/mach-mxs/Makefile
+++ b/arch/arm/mach-mxs/Makefile
@@ -1,5 +1,5 @@
# Common support
-obj-y := clock.o devices.o gpio.o icoll.o iomux.o system.o timer.o
+obj-y := clock.o devices.o gpio.o icoll.o iomux.o ocotp.o system.o timer.o
obj-$(CONFIG_SOC_IMX23) += clock-mx23.o mm-mx23.o
obj-$(CONFIG_SOC_IMX28) += clock-mx28.o mm-mx28.o
diff --git a/arch/arm/mach-mxs/include/mach/common.h b/arch/arm/mach-mxs/include/mach/common.h
index 59133eb..cf02552 100644
--- a/arch/arm/mach-mxs/include/mach/common.h
+++ b/arch/arm/mach-mxs/include/mach/common.h
@@ -13,6 +13,7 @@
struct clk;
+extern int mxs_read_ocotp(int offset, int count, u32 *values);
extern int mxs_reset_block(void __iomem *);
extern void mxs_timer_init(struct clk *, int);
diff --git a/arch/arm/mach-mxs/ocotp.c b/arch/arm/mach-mxs/ocotp.c
new file mode 100644
index 0000000..902ef59
--- /dev/null
+++ b/arch/arm/mach-mxs/ocotp.c
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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.
+ */
+
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/mutex.h>
+
+#include <mach/mxs.h>
+
+#define BM_OCOTP_CTRL_BUSY (1 << 8)
+#define BM_OCOTP_CTRL_ERROR (1 << 9)
+#define BM_OCOTP_CTRL_RD_BANK_OPEN (1 << 12)
+
+static DEFINE_MUTEX(ocotp_mutex);
+
+int mxs_read_ocotp(unsigned offset, size_t count, u32 *values)
+{
+ void __iomem *ocotp_base = MXS_IO_ADDRESS(MXS_OCOTP_BASE_ADDR);
+ int timeout = 0x400;
+ size_t i;
+
+ mutex_lock(&ocotp_mutex);
+
+ /*
+ * clk_enable(hbus_clk) for ocotp can be skipped
+ * as it must be on when system is running.
+ */
+
+ /* try to clear ERROR bit */
+ __mxs_clrl(BM_OCOTP_CTRL_ERROR, ocotp_base);
+
+ /* check both BUSY and ERROR cleared */
+ while ((__raw_readl(ocotp_base) &
+ (BM_OCOTP_CTRL_BUSY | BM_OCOTP_CTRL_ERROR)) && --timeout)
+ /* nothing */;
+
+ if (unlikely(!timeout))
+ goto error_unlock;
+
+ /* open OCOTP banks for read */
+ __mxs_setl(BM_OCOTP_CTRL_RD_BANK_OPEN, ocotp_base);
+
+ /* approximately wait 32 hclk cycles */
+ udelay(1);
+
+ /* poll BUSY bit becoming cleared */
+ timeout = 0x400;
+ while ((__raw_readl(ocotp_base) & BM_OCOTP_CTRL_BUSY) && --timeout)
+ /* nothing */;
+
+ if (unlikely(!timeout))
+ goto error_unlock;
+
+ for (i = 0; i < count; i++, offset += 4)
+ *values++ = __raw_readl(ocotp_base + offset);
+
+ /* close banks for power saving */
+ __mxs_clrl(BM_OCOTP_CTRL_RD_BANK_OPEN, ocotp_base);
+
+ mutex_unlock(&ocotp_mutex);
+
+ return 0;
+
+error_unlock:
+ mutex_unlock(&ocotp_mutex);
+ pr_err("%s: timeout in reading OCOTP\n", __func__);
+ return -ETIMEDOUT;
+}
--
1.7.1
^ permalink raw reply related
* [PATCH v2 07/10] ARM: mx28: add the second fec device registration
From: Shawn Guo @ 2011-01-04 9:24 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1294133056-21195-1-git-send-email-shawn.guo@freescale.com>
Signed-off-by: Shawn Guo <shawn.guo@freescale.com>
---
arch/arm/mach-mxs/mach-mx28evk.c | 28 +++++++++++++++++++++++++---
1 files changed, 25 insertions(+), 3 deletions(-)
diff --git a/arch/arm/mach-mxs/mach-mx28evk.c b/arch/arm/mach-mxs/mach-mx28evk.c
index d162e95..def6519 100644
--- a/arch/arm/mach-mxs/mach-mx28evk.c
+++ b/arch/arm/mach-mxs/mach-mx28evk.c
@@ -57,6 +57,19 @@ static const iomux_cfg_t mx28evk_pads[] __initconst = {
(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
MX28_PAD_ENET_CLK__CLKCTRL_ENET |
(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+ /* fec1 */
+ MX28_PAD_ENET0_CRS__ENET1_RX_EN |
+ (MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+ MX28_PAD_ENET0_RXD2__ENET1_RXD0 |
+ (MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+ MX28_PAD_ENET0_RXD3__ENET1_RXD1 |
+ (MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+ MX28_PAD_ENET0_COL__ENET1_TX_EN |
+ (MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+ MX28_PAD_ENET0_TXD2__ENET1_TXD0 |
+ (MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+ MX28_PAD_ENET0_TXD3__ENET1_TXD1 |
+ (MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
/* phy power line */
MX28_PAD_SSP1_DATA3__GPIO_2_15 |
(MXS_PAD_4MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
@@ -106,8 +119,14 @@ static void __init mx28evk_fec_reset(void)
gpio_set_value(MX28EVK_FEC_PHY_RESET, 1);
}
-static const struct fec_platform_data mx28_fec_pdata __initconst = {
- .phy = PHY_INTERFACE_MODE_RMII,
+static struct fec_platform_data mx28_fec_pdata[] = {
+ {
+ /* fec0 */
+ .phy = PHY_INTERFACE_MODE_RMII,
+ }, {
+ /* fec1 */
+ .phy = PHY_INTERFACE_MODE_RMII,
+ },
};
static void __init mx28evk_init(void)
@@ -117,7 +136,10 @@ static void __init mx28evk_init(void)
mx28_add_duart();
mx28evk_fec_reset();
- mx28_add_fec(0, &mx28_fec_pdata);
+ mx28_add_fec(0, &mx28_fec_pdata[0]);
+#ifdef CONFIG_FEC2
+ mx28_add_fec(1, &mx28_fec_pdata[1]);
+#endif
}
static void __init mx28evk_timer_init(void)
--
1.7.1
^ permalink raw reply related
* [PATCH v2 06/10] ARM: mx28: update clocks for dual fec support
From: Shawn Guo @ 2011-01-04 9:24 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1294133056-21195-1-git-send-email-shawn.guo@freescale.com>
Register clocks fec.0 and fec.1 for dual fec support.
Signed-off-by: Shawn Guo <shawn.guo@freescale.com>
---
Changes for v2:
- Rebase the patch against patch below which gets fundamental
clocks explicitly called in clk_enable.
[PATCH v4] ARM: mxs: Change duart device to use amba-pl011
- Register clocks fec.0 and fec.1 respectively than use wildcard
NULL for both instances.
arch/arm/mach-mxs/clock-mx28.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-mxs/clock-mx28.c b/arch/arm/mach-mxs/clock-mx28.c
index f20b254..f79587b 100644
--- a/arch/arm/mach-mxs/clock-mx28.c
+++ b/arch/arm/mach-mxs/clock-mx28.c
@@ -607,6 +607,7 @@ static struct clk_lookup lookups[] = {
/* for amba-pl011 driver */
_REGISTER_CLOCK("duart", NULL, uart_clk)
_REGISTER_CLOCK("fec.0", NULL, fec_clk)
+ _REGISTER_CLOCK("fec.1", NULL, fec_clk)
_REGISTER_CLOCK("rtc", NULL, rtc_clk)
_REGISTER_CLOCK("pll2", NULL, pll2_clk)
_REGISTER_CLOCK(NULL, "hclk", hbus_clk)
--
1.7.1
^ permalink raw reply related
* [PATCH v2 05/10] net/fec: add dual fec support for mx28
From: Shawn Guo @ 2011-01-04 9:24 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1294133056-21195-1-git-send-email-shawn.guo@freescale.com>
This patch is to add mx28 dual fec support. Here are some key notes
for mx28 fec controller.
- mx28 fec design made an assumption that it runs on a
big-endian system, which is incorrect. As the result, the
driver has to swap every frame going to and coming from
the controller.
- external phys can only be configured by fec0, which means
fec1 can not work independently and both phys need to be
configured by mii_bus attached on fec0.
- mx28 fec reset will get mac address registers reset too.
- MII/RMII mode and 10M/100M speed are configured differently
from i.mx/mxs fec controller.
- ETHER_EN bit must be set to get interrupt work.
Signed-off-by: Shawn Guo <shawn.guo@freescale.com>
---
Changes for v2:
- Use module parameter fec.macaddr over new kernel command line
fec_mac to pass mac address
- Update comment in fec_get_mac() to stop using confusing word
"default"
- Fix copyright breakage in fec.h
drivers/net/Kconfig | 7 ++-
drivers/net/fec.c | 139 ++++++++++++++++++++++++++++++++++++++++----------
drivers/net/fec.h | 5 +-
include/linux/fec.h | 3 +-
4 files changed, 120 insertions(+), 34 deletions(-)
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 4f1755b..f34629b 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -1944,18 +1944,19 @@ config 68360_ENET
config FEC
bool "FEC ethernet controller (of ColdFire and some i.MX CPUs)"
depends on M523x || M527x || M5272 || M528x || M520x || M532x || \
- MACH_MX27 || ARCH_MX35 || ARCH_MX25 || ARCH_MX5
+ MACH_MX27 || ARCH_MX35 || ARCH_MX25 || ARCH_MX5 || SOC_IMX28
select PHYLIB
help
Say Y here if you want to use the built-in 10/100 Fast ethernet
controller on some Motorola ColdFire and Freescale i.MX processors.
config FEC2
- bool "Second FEC ethernet controller (on some ColdFire CPUs)"
+ bool "Second FEC ethernet controller"
depends on FEC
help
Say Y here if you want to use the second built-in 10/100 Fast
- ethernet controller on some Motorola ColdFire processors.
+ ethernet controller on some Motorola ColdFire and Freescale
+ i.MX processors.
config FEC_MPC52xx
tristate "MPC52xx FEC driver"
diff --git a/drivers/net/fec.c b/drivers/net/fec.c
index f147508..b2b3e37 100644
--- a/drivers/net/fec.c
+++ b/drivers/net/fec.c
@@ -17,6 +17,8 @@
*
* Bug fixes and cleanup by Philippe De Muyter (phdm at macqel.be)
* Copyright (c) 2004-2006 Macq Electronique SA.
+ *
+ * Copyright (C) 2010 Freescale Semiconductor, Inc.
*/
#include <linux/module.h>
@@ -45,21 +47,34 @@
#include <asm/cacheflush.h>
-#ifndef CONFIG_ARCH_MXC
+#if !defined(CONFIG_ARCH_MXC) && !defined(CONFIG_SOC_IMX28)
#include <asm/coldfire.h>
#include <asm/mcfsim.h>
#endif
#include "fec.h"
-#ifdef CONFIG_ARCH_MXC
-#include <mach/hardware.h>
+#ifdef CONFIG_SOC_IMX28
+/*
+ * mx28 does not have MIIGSK registers
+ */
+#undef FEC_MIIGSK_ENR
+#include <mach/mxs.h>
+#else
+#define cpu_is_mx28() (0)
+#endif
+
+#if defined(CONFIG_ARCH_MXC) || defined(CONFIG_SOC_IMX28)
#define FEC_ALIGNMENT 0xf
#else
#define FEC_ALIGNMENT 0x3
#endif
-static unsigned char fec_mac_default[ETH_ALEN];
+static unsigned char macaddr[ETH_ALEN];
+module_param_array(macaddr, byte, NULL, 0);
+MODULE_PARM_DESC(macaddr, "FEC Ethernet MAC address");
+
+static struct mii_bus *fec_mii_bus;
#if defined(CONFIG_M5272)
/*
@@ -127,7 +142,8 @@ static unsigned char fec_mac_default[ETH_ALEN];
* account when setting it.
*/
#if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) || \
- defined(CONFIG_M520x) || defined(CONFIG_M532x) || defined(CONFIG_ARCH_MXC)
+ defined(CONFIG_M520x) || defined(CONFIG_M532x) || \
+ defined(CONFIG_ARCH_MXC) || defined(CONFIG_SOC_IMX28)
#define OPT_FRAME_SIZE (PKT_MAXBUF_SIZE << 16)
#else
#define OPT_FRAME_SIZE 0
@@ -206,6 +222,17 @@ static void fec_stop(struct net_device *dev);
/* Transmitter timeout */
#define TX_TIMEOUT (2 * HZ)
+static void *swap_buffer(void *bufaddr, int len)
+{
+ int i;
+ unsigned int *buf = bufaddr;
+
+ for (i = 0; i < (len + 3) / 4; i++, buf++)
+ *buf = __swab32(*buf);
+
+ return bufaddr;
+}
+
static netdev_tx_t
fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
@@ -254,6 +281,14 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
bufaddr = fep->tx_bounce[index];
}
+ /*
+ * mx28 fec design made an incorrect assumption that it's running
+ * on a big endian system. As the result, the driver has to swap
+ * every frame going to and coming from the controller.
+ */
+ if (cpu_is_mx28())
+ swap_buffer(bufaddr, skb->len);
+
/* Save skb pointer */
fep->tx_skbuff[fep->skb_cur] = skb;
@@ -485,6 +520,9 @@ fec_enet_rx(struct net_device *dev)
dma_unmap_single(NULL, bdp->cbd_bufaddr, bdp->cbd_datlen,
DMA_FROM_DEVICE);
+ if (cpu_is_mx28())
+ swap_buffer(data, pkt_len);
+
/* This does 16 byte alignment, exactly what we need.
* The packet length includes FCS, but we don't want to
* include that when passing upstream as it messes up
@@ -540,9 +578,10 @@ static void __inline__ fec_get_mac(struct net_device *dev)
/*
* try to get mac address in following order:
*
- * 1) kernel command line fec_mac=xx:xx:xx...
+ * 1) module parameter via kernel command line in form
+ * fec.macaddr=0x00,0x04,0x9f,0x01,0x30,0xe0
*/
- iap = fec_mac_default;
+ iap = macaddr;
/*
* 2) from flash or fuse (via platform data)
@@ -570,9 +609,9 @@ static void __inline__ fec_get_mac(struct net_device *dev)
memcpy(dev->dev_addr, iap, ETH_ALEN);
- /* Adjust MAC if using default MAC address */
- if (iap == fec_mac_default)
- dev->dev_addr[ETH_ALEN-1] = fec_mac_default[ETH_ALEN-1] + fep->pdev->id;
+ /* Adjust MAC if using macaddr */
+ if (iap == macaddr)
+ dev->dev_addr[ETH_ALEN-1] = macaddr[ETH_ALEN-1] + fep->pdev->id;
}
/* ------------------------------------------------------------------------- */
@@ -686,6 +725,7 @@ static int fec_enet_mii_probe(struct net_device *dev)
char mdio_bus_id[MII_BUS_ID_SIZE];
char phy_name[MII_BUS_ID_SIZE + 3];
int phy_id;
+ int dev_id = fep->pdev->id;
fep->phy_dev = NULL;
@@ -697,6 +737,8 @@ static int fec_enet_mii_probe(struct net_device *dev)
continue;
if (fep->mii_bus->phy_map[phy_id]->phy_id == 0)
continue;
+ if (cpu_is_mx28() && dev_id--)
+ continue;
strncpy(mdio_bus_id, fep->mii_bus->id, MII_BUS_ID_SIZE);
break;
}
@@ -738,6 +780,28 @@ static int fec_enet_mii_init(struct platform_device *pdev)
struct fec_enet_private *fep = netdev_priv(dev);
int err = -ENXIO, i;
+ /*
+ * The dual fec interfaces are not equivalent on mx28. Here are the
+ * differences:
+ *
+ * - fec0 supports MII & RMII modes while fec1 only supports RMII
+ * - fec0 acts as the 1588 time master while fec1 is slave
+ * - external phys can only be configured by fec0
+ *
+ * That is to say fec1 can not work independently. It only works
+ * when fec0 is working. The reason behind this design is that the
+ * second interface is added primarily for Switch mode.
+ *
+ * Because of the last point above, both phys are attached on fec0
+ * mdio interface in board design, and need to be configured by
+ * fec0 mii_bus.
+ */
+ if (cpu_is_mx28() && pdev->id) {
+ /* fec1 uses fec0 mii_bus */
+ fep->mii_bus = fec_mii_bus;
+ return 0;
+ }
+
fep->mii_timeout = 0;
/*
@@ -774,6 +838,10 @@ static int fec_enet_mii_init(struct platform_device *pdev)
if (mdiobus_register(fep->mii_bus))
goto err_out_free_mdio_irq;
+ /* save fec0 mii_bus */
+ if (cpu_is_mx28())
+ fec_mii_bus = fep->mii_bus;
+
return 0;
err_out_free_mdio_irq:
@@ -1069,24 +1137,6 @@ static const struct net_device_ops fec_netdev_ops = {
.ndo_do_ioctl = fec_enet_ioctl,
};
-static int __init fec_mac_addr_setup(char *mac_addr)
-{
- int i;
- unsigned int tmp;
-
- for (i = 0; i < ETH_ALEN; i++) {
- if (sscanf(mac_addr + 3*i, "%2x", &tmp) != 1) {
- printk(KERN_WARNING "Malformed fec mac address\n");
- return 0;
- }
- fec_mac_default[i] = tmp;
- }
-
- return 1;
-}
-
-__setup("fec_mac=", fec_mac_addr_setup);
-
/*
* XXX: We need to clean up on failure exits here.
*
@@ -1164,11 +1214,22 @@ fec_restart(struct net_device *dev, int duplex)
{
struct fec_enet_private *fep = netdev_priv(dev);
int i;
+ u32 val, temp_mac[2];
/* Whack a reset. We should wait for this. */
writel(1, fep->hwp + FEC_ECNTRL);
udelay(10);
+ /*
+ * The fec reset on mx28 will reset mac address too,
+ * so need to reconfigure it.
+ */
+ if (cpu_is_mx28()) {
+ memcpy(&temp_mac, dev->dev_addr, ETH_ALEN);
+ writel(cpu_to_be32(temp_mac[0]), fep->hwp + FEC_ADDR_LOW);
+ writel(cpu_to_be32(temp_mac[1]), fep->hwp + FEC_ADDR_HIGH);
+ }
+
/* Clear any outstanding interrupt. */
writel(0xffc00000, fep->hwp + FEC_IEVENT);
@@ -1215,6 +1276,28 @@ fec_restart(struct net_device *dev, int duplex)
/* Set MII speed */
writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED);
+ /*
+ * The phy interface and speed need to get configured
+ * differently on mx28.
+ */
+ if (cpu_is_mx28()) {
+ val = readl(fep->hwp + FEC_R_CNTRL);
+
+ /* MII or RMII */
+ if (fep->phy_interface == PHY_INTERFACE_MODE_RMII)
+ val |= (1 << 8);
+ else
+ val &= ~(1 << 8);
+
+ /* 10M or 100M */
+ if (fep->phy_dev && fep->phy_dev->speed == SPEED_100)
+ val &= ~(1 << 9);
+ else
+ val |= (1 << 9);
+
+ writel(val, fep->hwp + FEC_R_CNTRL);
+ }
+
#ifdef FEC_MIIGSK_ENR
if (fep->phy_interface == PHY_INTERFACE_MODE_RMII) {
/* disable the gasket and wait */
diff --git a/drivers/net/fec.h b/drivers/net/fec.h
index 2c48b25..ace318d 100644
--- a/drivers/net/fec.h
+++ b/drivers/net/fec.h
@@ -14,7 +14,8 @@
/****************************************************************************/
#if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) || \
- defined(CONFIG_M520x) || defined(CONFIG_M532x) || defined(CONFIG_ARCH_MXC)
+ defined(CONFIG_M520x) || defined(CONFIG_M532x) || \
+ defined(CONFIG_ARCH_MXC) || defined(CONFIG_SOC_IMX28)
/*
* Just figures, Motorola would have to change the offsets for
* registers in the same peripheral device on different models
@@ -78,7 +79,7 @@
/*
* Define the buffer descriptor structure.
*/
-#ifdef CONFIG_ARCH_MXC
+#if defined(CONFIG_ARCH_MXC) || defined(CONFIG_SOC_IMX28)
struct bufdesc {
unsigned short cbd_datlen; /* Data length */
unsigned short cbd_sc; /* Control and status info */
diff --git a/include/linux/fec.h b/include/linux/fec.h
index bf0c69f..bcff455 100644
--- a/include/linux/fec.h
+++ b/include/linux/fec.h
@@ -1,9 +1,10 @@
/* include/linux/fec.h
*
* Copyright (c) 2009 Orex Computed Radiography
- * Copyright (C) 2010 Freescale Semiconductor, Inc.
* Baruch Siach <baruch@tkos.co.il>
*
+ * Copyright (C) 2010 Freescale Semiconductor, Inc.
+ *
* Header file for the FEC platform data
*
* This program is free software; you can redistribute it and/or modify
--
1.7.1
^ permalink raw reply related
* [PATCH v2 04/10] net/fec: improve pm for better suspend/resume
From: Shawn Guo @ 2011-01-04 9:24 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1294133056-21195-1-git-send-email-shawn.guo@freescale.com>
The following commit made a fix to use fec_enet_open/fec_enet_close
over fec_enet_init/fec_stop for suspend/resume, because fec_enet_init
does not allow to have a working network interface at resume.
e3fe8558c7fc182972c3d947d88744482111f304
net/fec: fix pm to survive to suspend/resume
This fix works for i.mx/mxc fec controller, but fails on mx28 fec
which gets a different interrupt logic design. On i.mx fec, interrupt
can be triggered even bit ETHER_EN of ECR register is not set. But
on mx28 fec, ETHER_EN must be set to get interrupt work. Meanwhile,
MII interrupt is mandatory to resume the driver, because MDIO
read/write changed to interrupt mode by commit below.
97b72e4320a9aaa4a7f1592ee7d2da7e2c9bd349
fec: use interrupt for MDIO completion indication
fec_restart/fec_stop comes out as the solution working for both
cases.
Signed-off-by: Shawn Guo <shawn.guo@freescale.com>
---
drivers/net/fec.c | 12 ++++++++----
1 files changed, 8 insertions(+), 4 deletions(-)
diff --git a/drivers/net/fec.c b/drivers/net/fec.c
index cd59814..f147508 100644
--- a/drivers/net/fec.c
+++ b/drivers/net/fec.c
@@ -1387,8 +1387,10 @@ fec_suspend(struct device *dev)
if (ndev) {
fep = netdev_priv(ndev);
- if (netif_running(ndev))
- fec_enet_close(ndev);
+ if (netif_running(ndev)) {
+ fec_stop(ndev);
+ netif_device_detach(ndev);
+ }
clk_disable(fep->clk);
}
return 0;
@@ -1403,8 +1405,10 @@ fec_resume(struct device *dev)
if (ndev) {
fep = netdev_priv(ndev);
clk_enable(fep->clk);
- if (netif_running(ndev))
- fec_enet_open(ndev);
+ if (netif_running(ndev)) {
+ fec_restart(ndev, fep->full_duplex);
+ netif_device_attach(ndev);
+ }
}
return 0;
}
--
1.7.1
^ permalink raw reply related
* [PATCH v2 03/10] net/fec: add mac field into platform data and consolidate fec_get_mac
From: Shawn Guo @ 2011-01-04 9:24 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1294133056-21195-1-git-send-email-shawn.guo@freescale.com>
Add mac field into fec_platform_data and consolidate function
fec_get_mac to get mac address in following order.
1) kernel command line fec_mac=xx:xx:xx...
2) from flash in case of CONFIG_M5272 or fec_platform_data mac
field for others, which typically have mac stored in fuse
3) fec mac address registers set by bootloader
Signed-off-by: Shawn Guo <shawn.guo@freescale.com>
---
drivers/net/fec.c | 90 ++++++++++++++++++++++++++++----------------------
include/linux/fec.h | 2 +
2 files changed, 52 insertions(+), 40 deletions(-)
diff --git a/drivers/net/fec.c b/drivers/net/fec.c
index 47f6b3b..cd59814 100644
--- a/drivers/net/fec.c
+++ b/drivers/net/fec.c
@@ -59,15 +59,9 @@
#define FEC_ALIGNMENT 0x3
#endif
-/*
- * Define the fixed address of the FEC hardware.
- */
-#if defined(CONFIG_M5272)
-
-static unsigned char fec_mac_default[] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-};
+static unsigned char fec_mac_default[ETH_ALEN];
+#if defined(CONFIG_M5272)
/*
* Some hardware gets it MAC address out of local flash memory.
* if this is non-zero then assume it is the address to get MAC from.
@@ -537,27 +531,40 @@ rx_processing_done:
}
/* ------------------------------------------------------------------------- */
-#ifdef CONFIG_M5272
static void __inline__ fec_get_mac(struct net_device *dev)
{
struct fec_enet_private *fep = netdev_priv(dev);
+ struct fec_platform_data *pdata = fep->pdev->dev.platform_data;
unsigned char *iap, tmpaddr[ETH_ALEN];
- if (FEC_FLASHMAC) {
- /*
- * Get MAC address from FLASH.
- * If it is all 1's or 0's, use the default.
- */
- iap = (unsigned char *)FEC_FLASHMAC;
- if ((iap[0] == 0) && (iap[1] == 0) && (iap[2] == 0) &&
- (iap[3] == 0) && (iap[4] == 0) && (iap[5] == 0))
- iap = fec_mac_default;
- if ((iap[0] == 0xff) && (iap[1] == 0xff) && (iap[2] == 0xff) &&
- (iap[3] == 0xff) && (iap[4] == 0xff) && (iap[5] == 0xff))
- iap = fec_mac_default;
- } else {
- *((unsigned long *) &tmpaddr[0]) = readl(fep->hwp + FEC_ADDR_LOW);
- *((unsigned short *) &tmpaddr[4]) = (readl(fep->hwp + FEC_ADDR_HIGH) >> 16);
+ /*
+ * try to get mac address in following order:
+ *
+ * 1) kernel command line fec_mac=xx:xx:xx...
+ */
+ iap = fec_mac_default;
+
+ /*
+ * 2) from flash or fuse (via platform data)
+ */
+ if (!is_valid_ether_addr(iap)) {
+#ifdef CONFIG_M5272
+ if (FEC_FLASHMAC)
+ iap = (unsigned char *)FEC_FLASHMAC;
+#else
+ if (pdata)
+ memcpy(iap, pdata->mac, ETH_ALEN);
+#endif
+ }
+
+ /*
+ * 3) FEC mac registers set by bootloader
+ */
+ if (!is_valid_ether_addr(iap)) {
+ *((unsigned long *) &tmpaddr[0]) =
+ be32_to_cpu(readl(fep->hwp + FEC_ADDR_LOW));
+ *((unsigned short *) &tmpaddr[4]) =
+ be16_to_cpu(readl(fep->hwp + FEC_ADDR_HIGH) >> 16);
iap = &tmpaddr[0];
}
@@ -567,7 +574,6 @@ static void __inline__ fec_get_mac(struct net_device *dev)
if (iap == fec_mac_default)
dev->dev_addr[ETH_ALEN-1] = fec_mac_default[ETH_ALEN-1] + fep->pdev->id;
}
-#endif
/* ------------------------------------------------------------------------- */
@@ -1063,6 +1069,24 @@ static const struct net_device_ops fec_netdev_ops = {
.ndo_do_ioctl = fec_enet_ioctl,
};
+static int __init fec_mac_addr_setup(char *mac_addr)
+{
+ int i;
+ unsigned int tmp;
+
+ for (i = 0; i < ETH_ALEN; i++) {
+ if (sscanf(mac_addr + 3*i, "%2x", &tmp) != 1) {
+ printk(KERN_WARNING "Malformed fec mac address\n");
+ return 0;
+ }
+ fec_mac_default[i] = tmp;
+ }
+
+ return 1;
+}
+
+__setup("fec_mac=", fec_mac_addr_setup);
+
/*
* XXX: We need to clean up on failure exits here.
*
@@ -1087,22 +1111,8 @@ static int fec_enet_init(struct net_device *dev)
fep->hwp = (void __iomem *)dev->base_addr;
fep->netdev = dev;
- /* Set the Ethernet address */
-#ifdef CONFIG_M5272
+ /* Get the Ethernet address */
fec_get_mac(dev);
-#else
- {
- unsigned long l;
- l = readl(fep->hwp + FEC_ADDR_LOW);
- dev->dev_addr[0] = (unsigned char)((l & 0xFF000000) >> 24);
- dev->dev_addr[1] = (unsigned char)((l & 0x00FF0000) >> 16);
- dev->dev_addr[2] = (unsigned char)((l & 0x0000FF00) >> 8);
- dev->dev_addr[3] = (unsigned char)((l & 0x000000FF) >> 0);
- l = readl(fep->hwp + FEC_ADDR_HIGH);
- dev->dev_addr[4] = (unsigned char)((l & 0xFF000000) >> 24);
- dev->dev_addr[5] = (unsigned char)((l & 0x00FF0000) >> 16);
- }
-#endif
/* Set receive and transmit descriptor base. */
fep->rx_bd_base = cbd_base;
diff --git a/include/linux/fec.h b/include/linux/fec.h
index 5d3523d..bf0c69f 100644
--- a/include/linux/fec.h
+++ b/include/linux/fec.h
@@ -1,6 +1,7 @@
/* include/linux/fec.h
*
* Copyright (c) 2009 Orex Computed Radiography
+ * Copyright (C) 2010 Freescale Semiconductor, Inc.
* Baruch Siach <baruch@tkos.co.il>
*
* Header file for the FEC platform data
@@ -16,6 +17,7 @@
struct fec_platform_data {
phy_interface_t phy;
+ unsigned char mac[ETH_ALEN];
};
#endif
--
1.7.1
^ permalink raw reply related
* [PATCH v2 02/10] net/fec: remove the use of "index" which is legacy
From: Shawn Guo @ 2011-01-04 9:24 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1294133056-21195-1-git-send-email-shawn.guo@freescale.com>
The "index" becomes legacy since fep->pdev->id starts working
to identify the instance.
Moreover, the call of fec_enet_init(ndev, 0) always passes 0
to fep->index. This makes the following code in fec_get_mac buggy.
/* Adjust MAC if using default MAC address */
if (iap == fec_mac_default)
dev->dev_addr[ETH_ALEN-1] = fec_mac_default[ETH_ALEN-1] + fep->index;
It may be the time to remove "index" and use fep->pdev->id instead.
Signed-off-by: Shawn Guo <shawn.guo@freescale.com>
---
drivers/net/fec.c | 9 +++------
1 files changed, 3 insertions(+), 6 deletions(-)
diff --git a/drivers/net/fec.c b/drivers/net/fec.c
index 52e9ca8..47f6b3b 100644
--- a/drivers/net/fec.c
+++ b/drivers/net/fec.c
@@ -186,7 +186,6 @@ struct fec_enet_private {
int mii_timeout;
uint phy_speed;
phy_interface_t phy_interface;
- int index;
int link;
int full_duplex;
struct completion mdio_done;
@@ -566,7 +565,7 @@ static void __inline__ fec_get_mac(struct net_device *dev)
/* Adjust MAC if using default MAC address */
if (iap == fec_mac_default)
- dev->dev_addr[ETH_ALEN-1] = fec_mac_default[ETH_ALEN-1] + fep->index;
+ dev->dev_addr[ETH_ALEN-1] = fec_mac_default[ETH_ALEN-1] + fep->pdev->id;
}
#endif
@@ -1067,9 +1066,8 @@ static const struct net_device_ops fec_netdev_ops = {
/*
* XXX: We need to clean up on failure exits here.
*
- * index is only used in legacy code
*/
-static int fec_enet_init(struct net_device *dev, int index)
+static int fec_enet_init(struct net_device *dev)
{
struct fec_enet_private *fep = netdev_priv(dev);
struct bufdesc *cbd_base;
@@ -1086,7 +1084,6 @@ static int fec_enet_init(struct net_device *dev, int index)
spin_lock_init(&fep->hw_lock);
- fep->index = index;
fep->hwp = (void __iomem *)dev->base_addr;
fep->netdev = dev;
@@ -1316,7 +1313,7 @@ fec_probe(struct platform_device *pdev)
}
clk_enable(fep->clk);
- ret = fec_enet_init(ndev, 0);
+ ret = fec_enet_init(ndev);
if (ret)
goto failed_init;
--
1.7.1
^ permalink raw reply related
* [PATCH v2 01/10] net/fec: fix MMFR_OP type in fec_enet_mdio_write
From: Shawn Guo @ 2011-01-04 9:24 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1294133056-21195-1-git-send-email-shawn.guo@freescale.com>
FEC_MMFR_OP_WRITE should be used than FEC_MMFR_OP_READ in
a mdio write operation.
It's probably a typo introduced by commit:
e6b043d512fa8d9a3801bf5d72bfa3b8fc3b3cc8
netdev/fec.c: add phylib supporting to enable carrier detection (v2)
Signed-off-by: Shawn Guo <shawn.guo@freescale.com>
---
drivers/net/fec.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/fec.c b/drivers/net/fec.c
index cce32d4..52e9ca8 100644
--- a/drivers/net/fec.c
+++ b/drivers/net/fec.c
@@ -651,8 +651,8 @@ static int fec_enet_mdio_write(struct mii_bus *bus, int mii_id, int regnum,
fep->mii_timeout = 0;
init_completion(&fep->mdio_done);
- /* start a read op */
- writel(FEC_MMFR_ST | FEC_MMFR_OP_READ |
+ /* start a write op */
+ writel(FEC_MMFR_ST | FEC_MMFR_OP_WRITE |
FEC_MMFR_PA(mii_id) | FEC_MMFR_RA(regnum) |
FEC_MMFR_TA | FEC_MMFR_DATA(value),
fep->hwp + FEC_MII_DATA);
--
1.7.1
^ permalink raw reply related
* [PATCH v2 00/10] net/fec: add dual fec support for i.MX28
From: Shawn Guo @ 2011-01-04 9:24 UTC (permalink / raw)
To: linux-arm-kernel
This patch series is to add dual fec support for mx28, which is
a mxs-based soc. Some code changes related to the following commits
are also made in this patch set for some reasons.
e6b043d512fa8d9a3801bf5d72bfa3b8fc3b3cc8
netdev/fec.c: add phylib supporting to enable carrier detection (v2)
e3fe8558c7fc182972c3d947d88744482111f304
net/fec: fix pm to survive to suspend/resume
It's been tested on mx28 evk and mx51 babbage. For mx28, it has
to work against the tree
git://git.pengutronix.de/git/imx/linux-2.6.git imx-for-2.6.38
plus patch
[PATCH v4] ARM: mxs: Change duart device to use amba-pl011
The 5 patches below preceding with * have changes since v1, and
the detailed change log can be found in individual patch.
[PATCH v2 01/10] net/fec: fix MMFR_OP type in fec_enet_mdio_write
[PATCH v2 02/10] net/fec: remove the use of "index" which is legacy
[PATCH v2 03/10] net/fec: add mac field into platform data and consolidate fec_get_mac
[PATCH v2 04/10] net/fec: improve pm for better suspend/resume
*[PATCH v2 05/10] net/fec: add dual fec support for mx28
*[PATCH v2 06/10] ARM: mx28: update clocks for dual fec support
[PATCH v2 07/10] ARM: mx28: add the second fec device registration
*[PATCH v2 08/10] ARM: mxs: add ocotp read function
*[PATCH v2 09/10] ARM: mx28: read fec mac address from ocotp
*[PATCH v2 10/10] ARM: mxs: add initial pm support
Thanks for review.
Regards,
Shawn
^ permalink raw reply
* [RFC] Fixing CPU Hotplug for RealView Platforms
From: Vincent Guittot @ 2011-01-04 8:55 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20110103180305.GA4572@n2100.arm.linux.org.uk>
On 3 January 2011 19:03, Russell King - ARM Linux
<linux@arm.linux.org.uk> wrote:
> On Mon, Jan 03, 2011 at 06:39:56PM +0100, Vincent Guittot wrote:
>> On 3 January 2011 11:46, Russell King - ARM Linux
>> <linux@arm.linux.org.uk> wrote:
>> > On Mon, Dec 20, 2010 at 09:16:15AM +0100, Vincent Guittot wrote:
>> >> I'm also interested in hotplug latency measurement and have done some
>> >> on my CA9 platform u8500. I have the same kind of result for plugging
>> >> a secondary cpu:
>> >> ? total duration = 295ms
>> >> ? 166 us for the low level cpu wake up
>> >> ? 228ms between the return from platform_cpu_die and the cpu becomes online
>> >>
>> >> I have added some trace events for doing these measurements and I'd
>> >> like to add some generic traces point in the cpu hotplug code like we
>> >> already have in power management code (cpuidle, suspend, cpufreq ...)
>> >> These traces could be used with power events for studying the impact
>> >> of cpu hotplug in the complete power management scheme.
>> >
>> > Note that if you pass lpj=<number> to the kernel, you'll bypass the
>> > calibration and have a faster response to CPU onlining.
>> >
>>
>> yes, the total duration decreases down to 40ms
>
> I'm not sure that I believe it takes 40ms, as it's only taking about
> 104us to get to the calibration for me. ?The calibration when disabled
> is virtually a do-nothing, so shouldn't be taking 40ms.
>
> The trace code may be hitting locks which are interfering with the
> timing - this below is entirely lockless with a proper (and working)
> sched_clock() implementation.
>
> See mach-vexpress/platsmp.c for the things to add. ?Also note that it
> requires the SMP changes (and for good measure, the clksrc stuff too.)
> Might be easier to apply on top of linux-next.
>
> diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
> index 11d6a94..0b3a15a 100644
> --- a/arch/arm/kernel/smp.c
> +++ b/arch/arm/kernel/smp.c
> @@ -40,6 +40,7 @@
> ?#include <asm/ptrace.h>
> ?#include <asm/localtimer.h>
>
> +#include <asm/smp-debug.h>
> ?/*
> ?* as from 2.5, kernels no longer have an init_tasks structure
> ?* so we need some other way of telling a new secondary core
> @@ -47,6 +48,8 @@
> ?*/
> ?struct secondary_data secondary_data;
>
> +struct smp_debug smp_debug;
> +
> ?enum ipi_msg_type {
> ? ? ? ?IPI_TIMER = 2,
> ? ? ? ?IPI_RESCHEDULE,
> @@ -55,6 +58,24 @@ enum ipi_msg_type {
> ? ? ? ?IPI_CPU_STOP,
> ?};
>
> +static const char *debug_names[] = {
> + ? ? ? [D_START] ? ? ? ? ? ? ? = "Start",
> + ? ? ? [D_BOOT_SECONDARY_CALL] = "Booting",
> + ? ? ? [D_CROSS_CALL] ? ? ? ? ?= "Cross call",
> + ? ? ? [D_PEN_RELEASED] ? ? ? ?= "Pen released",
> + ? ? ? [D_UNLOCK] ? ? ? ? ? ? ?= "Unlock",
> + ? ? ? [D_BOOT_SECONDARY_RET] ?= "Boot returned",
> + ? ? ? [D_BOOT_DONE] ? ? ? ? ? = "Boot complete",
> + ? ? ? [D_SEC_RESTART] ? ? ? ? = "Sec: restart",
> + ? ? ? [D_SEC_UP] ? ? ? ? ? ? ?= "Sec: up",
> + ? ? ? [D_SEC_PLAT_ENTER] ? ? ?= "Sec: enter",
> + ? ? ? [D_SEC_PLAT_PEN_WRITE] ?= "Sec: pen write",
> + ? ? ? [D_SEC_PLAT_PEN_DONE] ? = "Sec: pen done",
> + ? ? ? [D_SEC_PLAT_EXIT] ? ? ? = "Sec: exit",
> + ? ? ? [D_SEC_CALIBRATE] ? ? ? = "Sec: calibrate",
> + ? ? ? [D_SEC_ONLINE] ? ? ? ? ?= "Sec: online",
> +};
> +
> ?int __cpuinit __cpu_up(unsigned int cpu)
> ?{
> ? ? ? ?struct cpuinfo_arm *ci = &per_cpu(cpu_data, cpu);
> @@ -111,7 +132,10 @@ int __cpuinit __cpu_up(unsigned int cpu)
> ? ? ? ?/*
> ? ? ? ? * Now bring the CPU into our world.
> ? ? ? ? */
> + ? ? ? smp_debug_mark(D_START);
> + ? ? ? smp_debug_mark(D_BOOT_SECONDARY_CALL);
> ? ? ? ?ret = boot_secondary(cpu, idle);
> + ? ? ? smp_debug_mark(D_BOOT_SECONDARY_RET);
> ? ? ? ?if (ret == 0) {
> ? ? ? ? ? ? ? ?unsigned long timeout;
>
> @@ -135,6 +159,7 @@ int __cpuinit __cpu_up(unsigned int cpu)
> ? ? ? ?} else {
> ? ? ? ? ? ? ? ?pr_err("CPU%u: failed to boot: %d\n", cpu, ret);
> ? ? ? ?}
> + ? ? ? smp_debug_mark(D_BOOT_DONE);
>
> ? ? ? ?secondary_data.stack = NULL;
> ? ? ? ?secondary_data.pgdir = 0;
> @@ -148,6 +173,14 @@ int __cpuinit __cpu_up(unsigned int cpu)
> ? ? ? ?}
>
> ? ? ? ?pgd_free(&init_mm, pgd);
> +{
> + ? ? ? int i;
> + ? ? ? for (i = 0; i < D_NUM; i++) {
> + ? ? ? ? ? ? ? if (debug_names[i] && smp_debug.entry[i])
> + ? ? ? ? ? ? ? ? ? ? ? pr_info("SMP: %s: %llu\n", debug_names[i],
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? smp_debug.entry[i] - smp_debug.entry[0]);
> + ? ? ? }
> +}
>
> ? ? ? ?return ret;
> ?}
> @@ -245,6 +278,8 @@ void __ref cpu_die(void)
> ? ? ? ? */
> ? ? ? ?platform_cpu_die(cpu);
>
> + ? ? ? smp_debug_mark(D_SEC_RESTART);
> +
> ? ? ? ?/*
> ? ? ? ? * Do not return to the idle loop - jump back to the secondary
> ? ? ? ? * cpu initialisation. ?There's some initialisation which needs
> @@ -278,6 +313,7 @@ asmlinkage void __cpuinit secondary_start_kernel(void)
> ? ? ? ?struct mm_struct *mm = &init_mm;
> ? ? ? ?unsigned int cpu = smp_processor_id();
>
> + ? ? ? smp_debug_mark(D_SEC_UP);
> ? ? ? ?printk("CPU%u: Booted secondary processor\n", cpu);
>
> ? ? ? ?/*
> @@ -312,6 +348,8 @@ asmlinkage void __cpuinit secondary_start_kernel(void)
> ? ? ? ? */
> ? ? ? ?percpu_timer_setup();
>
> + ? ? ? smp_debug_mark(D_SEC_CALIBRATE);
> +
> ? ? ? ?calibrate_delay();
>
> ? ? ? ?smp_store_cpu_info(cpu);
> @@ -320,6 +358,7 @@ asmlinkage void __cpuinit secondary_start_kernel(void)
> ? ? ? ? * OK, now it's safe to let the boot CPU continue
> ? ? ? ? */
> ? ? ? ?set_cpu_online(cpu, true);
> + ? ? ? smp_debug_mark(D_SEC_ONLINE);
>
> ? ? ? ?/*
> ? ? ? ? * OK, it's off to the idle thread for us
> diff --git a/arch/arm/mach-vexpress/platsmp.c b/arch/arm/mach-vexpress/platsmp.c
> index b1687b6..0a77a6b 100644
> --- a/arch/arm/mach-vexpress/platsmp.c
> +++ b/arch/arm/mach-vexpress/platsmp.c
> @@ -27,7 +27,7 @@
> ?#include "core.h"
>
> ?extern void vexpress_secondary_startup(void);
> -
> +#include <asm/smp-debug.h>
> ?/*
> ?* control for which core is the next to come out of the secondary
> ?* boot "holding pen"
> @@ -56,6 +56,7 @@ static DEFINE_SPINLOCK(boot_lock);
>
> ?void __cpuinit platform_secondary_init(unsigned int cpu)
> ?{
> + ? ? ? smp_debug_mark(D_SEC_PLAT_ENTER);
> ? ? ? ?/*
> ? ? ? ? * if any interrupts are already enabled for the primary
> ? ? ? ? * core (e.g. timer irq), then they will not have been enabled
> @@ -67,13 +68,16 @@ void __cpuinit platform_secondary_init(unsigned int cpu)
> ? ? ? ? * let the primary processor know we're out of the
> ? ? ? ? * pen, then head off into the C entry point
> ? ? ? ? */
> + ? ? ? smp_debug_mark(D_SEC_PLAT_PEN_WRITE);
> ? ? ? ?write_pen_release(-1);
> + ? ? ? smp_debug_mark(D_SEC_PLAT_PEN_DONE);
>
> ? ? ? ?/*
> ? ? ? ? * Synchronise with the boot thread.
> ? ? ? ? */
> ? ? ? ?spin_lock(&boot_lock);
> ? ? ? ?spin_unlock(&boot_lock);
> + ? ? ? smp_debug_mark(D_SEC_PLAT_EXIT);
> ?}
>
> ?int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
> @@ -99,6 +103,7 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
> ? ? ? ? * the boot monitor to read the system wide flags register,
> ? ? ? ? * and branch to the address found there.
> ? ? ? ? */
> + ? ? ? smp_debug_mark(D_CROSS_CALL);
> ? ? ? ?smp_cross_call(cpumask_of(cpu), 1);
>
> ? ? ? ?timeout = jiffies + (1 * HZ);
> @@ -109,12 +114,14 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
>
> ? ? ? ? ? ? ? ?udelay(10);
> ? ? ? ?}
> + ? ? ? smp_debug_mark(D_PEN_RELEASED);
>
> ? ? ? ?/*
> ? ? ? ? * now the secondary core is starting up let it run its
> ? ? ? ? * calibrations, then wait for it to finish
> ? ? ? ? */
> ? ? ? ?spin_unlock(&boot_lock);
> + ? ? ? smp_debug_mark(D_UNLOCK);
>
> ? ? ? ?return pen_release != -1 ? -ENOSYS : 0;
> ?}
> --- /dev/null ? 2010-08-07 18:16:05.574112050 +0100
> +++ arch/arm/include/asm/smp-debug.h ? ?2010-12-18 22:03:23.622580304 +0000
> @@ -0,0 +1,39 @@
> +#include <linux/sched.h>
> +
> +enum {
> + ? ? ? D_START,
> + ? ? ? D_INIT_IDLE,
> + ? ? ? D_PGD_ALLOC,
> + ? ? ? D_IDMAP_ADD,
> + ? ? ? D_BOOT_SECONDARY_CALL,
> + ? ? ? D_CROSS_CALL,
> + ? ? ? D_PEN_RELEASED,
> + ? ? ? D_UNLOCK,
> + ? ? ? D_BOOT_SECONDARY_RET,
> + ? ? ? D_BOOT_DONE,
> + ? ? ? D_IDMAP_DEL,
> + ? ? ? D_PGD_FREE,
> +
> + ? ? ? D_SEC = 16,
> + ? ? ? D_SEC_RESTART = D_SEC,
> + ? ? ? D_SEC_UP,
> + ? ? ? D_SEC_PLAT_ENTER,
> + ? ? ? D_SEC_PLAT_PEN_WRITE,
> + ? ? ? D_SEC_PLAT_PEN_DONE,
> + ? ? ? D_SEC_PLAT_EXIT,
> + ? ? ? D_SEC_CALIBRATE,
> + ? ? ? D_SEC_ONLINE,
> +
> + ? ? ? D_NUM,
> +};
> +
> +struct smp_debug {
> + ? ? ? unsigned long long ? ? ?entry[D_NUM];
> +};
> +
> +extern struct smp_debug smp_debug;
> +
> +static inline void smp_debug_mark(int ent)
> +{
> + ? ? ? smp_debug.entry[ent] = sched_clock();
> +}
>
In fact, 40ms is the total duration of cpu_up function. The time
between the return of platform_cpu_die and the online of the cpu is
now 93us
^ permalink raw reply
* [PATCH v7 4/7] omap3: nand: prefetch in irq mode support
From: Ghorai, Sukumar @ 2011-01-04 8:50 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <B85A65D85D7EB246BE421B3FB0FBB593024816D63C@dbde02.ent.ti.com>
[..snip...]
> > + if (info->buf_len & (info->buf_len < bytes))
>
> Meant to use logical AND here?
[Ghorai] thanks, you are right.
[..snip..]
> > + init_completion(&info->comp);
>
> You can use INIT_COMPLETION to reset the completion variable.
> Same change can be done in write below.
[..snip..]
> s/methode/method
>
[Ghorai] yes. I will do this
[..snip..]
> > + /* waiting for write to complete */
> > + wait_for_completion(&info->comp);
> > + /* wait for data to flushed-out before reset the prefetch */
> > + do {
> > + ret = gpmc_read_status(GPMC_PREFETCH_COUNT);
> > + } while (ret);
>
> Please have a timeout for this while loop in case hardware does
> not become ready. Also, consider using cpu_relax() inside the
> tight loop.
>
[Ghorai] Thanks. I will send again.
^ permalink raw reply
* [PATCH 1/4] ARM: runtime patching of __virt_to_phys() and __phys_to_virt()
From: Russell King - ARM Linux @ 2011-01-04 8:45 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1294129208-15201-2-git-send-email-nico@fluxnic.net>
This is basically my patch with a few blank lines removed, a couple
of \n's also removed, a #error if __virt_to_phys is defined by a platform,
a minor tweak to the assembly and it being only usable on PXA.
I much prefer my patch over this as anyone can use it. That's one of
the reasons why I arranged the code testing for __virt_to_phys as I
did, so the config option could be offered without having a big long
dependency list attached to it.
On Tue, Jan 04, 2011 at 03:20:05AM -0500, Nicolas Pitre wrote:
> On ARM it is common to find different offsets for the location of
> physical memory. In order to support multiple machine types with
> a single kernel binary, we need to make PHYS_OFFSET a variable.
> But turning PHYS_OFFSET into a global variable would impact performance
> of many hot paths.
>
> In the context of __virt_to_phys() and __phys_to_virt(), we currently have:
>
> #define __virt_to_phys(x) ((x) - PAGE_OFFSET + PHYS_OFFSET)
>
> This normally translates into the following assembly instruction:
>
> add rx, rx, #(PHYS_OFFSET - PAGE_OFFSET)
>
> If we can assume that the difference between PHYS_OFFSET and PAGE_OFFSET
> will always fit into 8 bits shifted to the MSBs, then we can easily patch
> this difference into the corresponding assembly instructions at run time.
> This is like saying that phys and virt offsets will always be at least
> 16 MB aligned which is a pretty safe assumption.
>
> So the idea is to create a table of pointers to all those add instructions,
> and have the early boot code to walk and patch them up before the kernel
> gets to use them. Result is equivalent to a variable PHYS_OFFSET with
> next to zero performance impact compared to the constant PHYS_OFFSET.
>
> Right now, the difference between PHYS_OFFSET and PAGE_OFFSET is determined
> by the actual physical address the kernel is executing from upon start,
> assuming that the kernel is located within the first 16 MB of RAM.
>
> Thanks to Eric Miao and Russell King for their contributions to this patch.
>
> Signed-off-by: Nicolas Pitre <nicolas.pitre@linaro.org>
> ---
> arch/arm/Kconfig | 5 ++++
> arch/arm/include/asm/memory.h | 51 +++++++++++++++++++++++++++++++++--------
> arch/arm/kernel/head.S | 35 ++++++++++++++++++++++++++++
> arch/arm/kernel/vmlinux.lds.S | 4 +++
> 4 files changed, 85 insertions(+), 10 deletions(-)
>
> diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
> index d56d21c0..136ed9b 100644
> --- a/arch/arm/Kconfig
> +++ b/arch/arm/Kconfig
> @@ -187,6 +187,11 @@ config VECTORS_BASE
> help
> The base address of exception vectors.
>
> +config ARM_PATCH_PHYS_VIRT
> + bool
> + depends on EXPERIMENTAL
> + depends on !XIP && !THUMB2_KERNEL
> +
> source "init/Kconfig"
>
> source "kernel/Kconfig.freezer"
> diff --git a/arch/arm/include/asm/memory.h b/arch/arm/include/asm/memory.h
> index 23c2e8e..2783ce2 100644
> --- a/arch/arm/include/asm/memory.h
> +++ b/arch/arm/include/asm/memory.h
> @@ -133,16 +133,6 @@
> #endif
>
> /*
> - * Physical vs virtual RAM address space conversion. These are
> - * private definitions which should NOT be used outside memory.h
> - * files. Use virt_to_phys/phys_to_virt/__pa/__va instead.
> - */
> -#ifndef __virt_to_phys
> -#define __virt_to_phys(x) ((x) - PAGE_OFFSET + PHYS_OFFSET)
> -#define __phys_to_virt(x) ((x) - PHYS_OFFSET + PAGE_OFFSET)
> -#endif
> -
> -/*
> * Convert a physical address to a Page Frame Number and back
> */
> #define __phys_to_pfn(paddr) ((paddr) >> PAGE_SHIFT)
> @@ -157,6 +147,47 @@
> #ifndef __ASSEMBLY__
>
> /*
> + * Physical vs virtual RAM address space conversion. These are
> + * private definitions which should NOT be used outside memory.h
> + * files. Use virt_to_phys/phys_to_virt/__pa/__va instead.
> + */
> +#ifdef CONFIG_ARM_PATCH_PHYS_VIRT
> +
> +#ifdef __virt_to_phys
> +#error "this machine configuration uses complex __virt_to_phys/__phys_to_virt and cannot use CONFIG_ARM_PATCH_PHYS_VIRT"
> +#endif
> +
> +#define __pv_stub(from,to,instr) \
> + __asm__( \
> + "1: " instr "\t%0, %1, %2\n" \
> + " .pushsection .pv_table,\"a\"\n" \
> + " .long 1b\n" \
> + " .popsection" \
> + : "=r" (to) \
> + : "r" (from), "I" (1))
> +
> +static inline unsigned long __virt_to_phys(unsigned long x)
> +{
> + unsigned long t;
> +
> + __pv_stub(x, t, "add");
> + return t;
> +}
> +
> +static inline unsigned long __phys_to_virt(unsigned long x)
> +{
> + unsigned long t;
> +
> + __pv_stub(x, t, "sub");
> + return t;
> +}
> +
> +#else
> +#define __virt_to_phys(x) ((x) - PAGE_OFFSET + PHYS_OFFSET)
> +#define __phys_to_virt(x) ((x) - PHYS_OFFSET + PAGE_OFFSET)
> +#endif
> +
> +/*
> * The DMA mask corresponding to the maximum bus address allocatable
> * using GFP_DMA. The default here places no restriction on DMA
> * allocations. This must be the smallest DMA mask in the system,
> diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S
> index 6bd82d2..eaaf0ad 100644
> --- a/arch/arm/kernel/head.S
> +++ b/arch/arm/kernel/head.S
> @@ -95,6 +95,9 @@ ENTRY(stext)
> #ifdef CONFIG_SMP_ON_UP
> bl __fixup_smp
> #endif
> +#ifdef CONFIG_ARM_PATCH_PHYS_VIRT
> + bl __fixup_pv_table
> +#endif
> bl __create_page_tables
>
> /*
> @@ -433,4 +436,36 @@ smp_on_up:
>
> #endif
>
> +#ifdef CONFIG_ARM_PATCH_PHYS_VIRT
> +
> +/* __fixup_pv_table - patch the stub instructions with the delta between
> + * PHYS_OFFSET and PAGE_OFFSET, which is assumed to be 16MiB aligned and
> + * can be expressed by an immediate shifter operand. The stub instruction
> + * has a form of '(add|sub) rd, rn, #imm'.
> + */
> +__fixup_pv_table:
> + adr r0, 1f
> + ldmia r0, {r3-r5}
> + sub r3, r0, r3 @ PHYS_OFFSET - PAGE_OFFSET
> + mov r6, r3, lsr #24 @ constant for add/sub instructions
> + teq r3, r6, lsl #24 @ must be 16MiB aligned
> + bne __error
> + orr r6, r6, #0x400 @ mask in rotate right 8 bits
> + add r4, r4, r3
> + add r5, r5, r3
> +2: cmp r4, r5
> + ldrlo r7, [r4], #4
> + ldrlo ip, [r7, r3]
> + mov ip, ip, lsr #12
> + orr ip, r6, ip, lsl #12
> + strlo ip, [r7, r3]
> + blo 2b
> + mov pc, lr
> +ENDPROC(__fixup_phys_virt)
> +
> +1: .word .
> + .word __pv_table_begin
> + .word __pv_table_end
> +#endif
> +
> #include "head-common.S"
> diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S
> index cead889..fb32c9d 100644
> --- a/arch/arm/kernel/vmlinux.lds.S
> +++ b/arch/arm/kernel/vmlinux.lds.S
> @@ -57,6 +57,10 @@ SECTIONS
> __smpalt_end = .;
> #endif
>
> + __pv_table_begin = .;
> + *(.pv_table)
> + __pv_table_end = .;
> +
> INIT_SETUP(16)
>
> INIT_CALLS
> --
> 1.7.3.2.193.g78bbb
>
^ 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