Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [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


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox