* [GIT PULL] Versatile Express clk
From: Mike Turquette @ 2012-10-11 22:40 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1348501568.27071.5.camel@hornet>
Quoting Pawel Moll (2012-09-24 08:46:08)
> Hi Mike,
>
> Would you be so kind and pull the VE clocking stuff? They are rebased on
> top of Linus' Realview patch.
>
Hi Pawel,
I've taken these into my new clk-next towards 3.8. That branch is not
yet pushed out publicly but will be after -rc1 is released.
Regards,
Mike
> Thanks!
>
> Pawel
>
>
> The following changes since commit b9f8a0f8e255919bdcfb96a8d50d1523233a458a:
>
> clk: convert ARM RealView to common clk (2012-09-24 16:28:29 +0100)
>
> are available in the git repository at:
>
> git://git.linaro.org/people/pawelmoll/linux.git clk-v3.6-rc7
>
> for you to fetch changes up to b262f1ed394218f9327b72e7d1d17a5e62074be0:
>
> clk: Common clocks implementation for Versatile Express (2012-09-24 16:28:30 +0100)
>
> ----------------------------------------------------------------
> Pawel Moll (2):
> clk: Versatile Express clock generators ("osc") driver
> clk: Common clocks implementation for Versatile Express
>
> arch/arm/include/asm/hardware/sp810.h | 2 +
> drivers/clk/Kconfig | 8 +-
> drivers/clk/versatile/Makefile | 2 +
> drivers/clk/versatile/clk-vexpress-osc.c | 150 ++++++++++++++++++++++++++++++
> drivers/clk/versatile/clk-vexpress.c | 142 ++++++++++++++++++++++++++++
> 5 files changed, 301 insertions(+), 3 deletions(-)
> create mode 100644 drivers/clk/versatile/clk-vexpress-osc.c
> create mode 100644 drivers/clk/versatile/clk-vexpress.c
^ permalink raw reply
* [RFC PATCH] ARM: vt8500: Convert arch-vt8500 to multiplatform
From: linux at prisktech.co.nz @ 2012-10-11 22:33 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <201210112029.05572.arnd@arndb.de>
> On Thursday 11 October 2012, Tony Prisk wrote:
>> > config VT8500
>> > bool "Via/Wondermedia VT8500 / WM8505 / WM8650" if ARCH_MULTIPLATFORM
>> > default VT8500_SINGLE
>> >
>> > Arnd
>>
>> Alexey (or anyone else),
>>
>> Do you want it kept in the meantime?
>>
>> I think the easiest way to add/keep it would be to create:
>>
>> ARCH_VT8500_SINGLE (arm/Kconfig) and ARCH_VT8500_MULTI
>> (arch-vt8500/Kconfig) and have them both select ARCH_VT8500 as an option
>> to make drivers available.
>
> You only need one new symbol, not too. Keeping CONFIG_VT8500 as the
> user-selectable option as I outlined in the example means that
> existing .config files keep working, which is sometimes useful.
>
> Arnd
>
To clarify what you said (because I'm not sure I got it the first time)...
Keep ARCH_VT8500 as the single-platform Kconfig option.
Add a new ARCH_VT8500_MULTI (for example) as the multiplatform Kconfig option.
Have ARCH_VT8500_MULTI select ARCH_VT8500??
The last bit confuses me (and seems a little backwards, although I suspect it
would work since none of the options would cause conflicts). Without ARCH_VT8500
selected, we have no driver options without changing all the Kconfig's.
If this is correct, we are basically using _MULTI to add more options on top of
_VT8500.
Am I close or did I completely misunderstand? :)
Regards
Tony P
^ permalink raw reply
* [PATCH] ARM: nomadik: fixup some FSMC merge problems
From: Linus Walleij @ 2012-10-11 22:23 UTC (permalink / raw)
To: linux-arm-kernel
Due to a clash between refactoring and due to loss of a header
file that remained in my working tree the Nomadik stopped
compiling after switching to the FSMC driver. This patch fixes
it up.
Cc: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
arch/arm/mach-nomadik/board-nhk8815.c | 21 +++++++++++++++++----
1 file changed, 17 insertions(+), 4 deletions(-)
diff --git a/arch/arm/mach-nomadik/board-nhk8815.c b/arch/arm/mach-nomadik/board-nhk8815.c
index a105d1b..3f97ef4 100644
--- a/arch/arm/mach-nomadik/board-nhk8815.c
+++ b/arch/arm/mach-nomadik/board-nhk8815.c
@@ -37,14 +37,15 @@
#include <plat/mtu.h>
#include <plat/pincfg.h>
-#include <mach/fsmc.h>
-
#include "cpu-8815.h"
/* Initial value for SRC control register: all timers use MXTAL/8 source */
#define SRC_CR_INIT_MASK 0x00007fff
#define SRC_CR_INIT_VAL 0x2aaa8000
+#define ALE_OFF 0x1000000
+#define CLE_OFF 0x800000
+
/* These addresses span 16MB, so use three individual pages */
static struct resource nhk8815_nand_resources[] = {
{
@@ -53,6 +54,16 @@ static struct resource nhk8815_nand_resources[] = {
.end = 0x40000000 + SZ_16K - 1,
.flags = IORESOURCE_MEM,
}, {
+ .name = "nand_addr",
+ .start = 0x40000000 + ALE_OFF,
+ .end = 0x40000000 +ALE_OFF + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .name = "nand_cmd",
+ .start = 0x40000000 + CLE_OFF,
+ .end = 0x40000000 + CLE_OFF + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ }, {
.name = "fsmc_regs",
.start = NOMADIK_FSMC_BASE,
.end = NOMADIK_FSMC_BASE + SZ_4K - 1,
@@ -105,8 +116,6 @@ static struct fsmc_nand_platform_data nhk8815_nand_platform_data = {
.partitions = nhk8815_partitions,
.nr_partitions = ARRAY_SIZE(nhk8815_partitions),
.width = FSMC_NAND_BW8,
- .ale_off = 0x1000000,
- .cle_off = 0x800000,
};
static struct platform_device nhk8815_nand_device = {
@@ -171,6 +180,10 @@ static struct platform_device nhk8815_onenand_device = {
.num_resources = ARRAY_SIZE(nhk8815_onenand_resource),
};
+/* bus control reg. and bus timing reg. for CS0..CS3 */
+#define FSMC_BCR(x) (NOMADIK_FSMC_VA + (x << 3))
+#define FSMC_BTR(x) (NOMADIK_FSMC_VA + (x << 3) + 0x04)
+
static void __init nhk8815_onenand_init(void)
{
#ifdef CONFIG_MTD_ONENAND
--
1.7.11.4
^ permalink raw reply related
* [RFC][PATCH v4? 0/7] Adaptive Body-Bias for OMAP
From: Mike Turquette @ 2012-10-11 22:21 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20121011133304.GA19170@kahuna>
Quoting Nishanth Menon (2012-10-11 06:33:04)
> On 18:26-20121003, Mike Turquette wrote:
> > From: Mike Turquette <mturquette@linaro.org>
> [...]
> >
> > arch/arm/mach-omap2/Makefile | 8 +-
> > arch/arm/mach-omap2/abb.c | 322 +++++++++++++++++++++++++
> > arch/arm/mach-omap2/abb.h | 94 ++++++++
> [...]
> > arch/arm/plat-omap/include/plat/voltage.h | 1 +
> > 18 files changed, 699 insertions(+), 37 deletions(-)
> > create mode 100644 arch/arm/mach-omap2/abb.c
> > create mode 100644 arch/arm/mach-omap2/abb.h
> > create mode 100644 arch/arm/mach-omap2/abb36xx_data.c
> > create mode 100644 arch/arm/mach-omap2/abb44xx_data.c
>
> dumb question: with the request to move everything out of mach-omap2
> directory, do we still want to add more files into mach-omap2?
>
Not a dumb question at all. I approached this problem by modeling it
after existing voltage layer code (in particular the vp and vc drivers).
My hope is to get it merged as-is and then bundle the abb code up with
the vp/vc migration to drivers/* when that happens some day. People
using omap36xx and above need this code now, so it seems prudent to take
this approach today.
Regards,
Mike
> Regards,
> NM
^ permalink raw reply
* [PATCH 1/2] ARM: nomadik: switch over to using the FSMC driver
From: Linus Walleij @ 2012-10-11 22:20 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20121011180406.GX12801@game.jcrosoft.org>
On Thu, Oct 11, 2012 at 8:04 PM, Jean-Christophe PLAGNIOL-VILLARD
<plagnioj@jcrosoft.com> wrote:
> On 14:07 Thu 11 Oct , Artem Bityutskiy wrote:
>>
>> Pushed both to l2-mtd.git, thanks!
>
> wait on this one Linus said he will send an other version based on my patch
> for fmsc
I made a fix-up patch instead, that's simpler I guess... mailing out now.
Thanks,
Linus Walleij
^ permalink raw reply
* [PATCH 4/4] ARM: AT91: Add AT91RM9200 device tree
From: Joachim Eastwood @ 2012-10-11 22:05 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1349993126-9519-1-git-send-email-manabian@gmail.com>
Signed-off-by: Joachim Eastwood <manabian@gmail.com>
---
arch/arm/boot/dts/at91rm9200.dtsi | 218 ++++++++++++++++++++++++++++++++++++++
1 file changed, 218 insertions(+)
create mode 100644 arch/arm/boot/dts/at91rm9200.dtsi
diff --git a/arch/arm/boot/dts/at91rm9200.dtsi b/arch/arm/boot/dts/at91rm9200.dtsi
new file mode 100644
index 0000000..81a344c
--- /dev/null
+++ b/arch/arm/boot/dts/at91rm9200.dtsi
@@ -0,0 +1,218 @@
+/*
+ * at91rm9200.dtsi - Device Tree Include file for AT91RM9200 family SoC
+ *
+ * Copyright (C) 2011 Atmel,
+ * 2011 Nicolas Ferre <nicolas.ferre@atmel.com>,
+ * 2012 Joachim Eastwood <manabian@gmail.com>
+ *
+ * Based on at91sam9260.dtsi
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+/include/ "skeleton.dtsi"
+
+/ {
+ model = "Atmel AT91RM9200 family SoC";
+ compatible = "atmel,at91rm9200";
+ interrupt-parent = <&aic>;
+
+ aliases {
+ serial0 = &dbgu;
+ serial1 = &usart0;
+ serial2 = &usart1;
+ serial3 = &usart2;
+ serial4 = &usart3;
+ gpio0 = &pioA;
+ gpio1 = &pioB;
+ gpio2 = &pioC;
+ gpio3 = &pioD;
+ tcb0 = &tcb0;
+ tcb1 = &tcb1;
+ };
+ cpus {
+ cpu at 0 {
+ compatible = "arm,arm920t";
+ };
+ };
+
+ memory {
+ reg = <0x20000000 0x04000000>;
+ };
+
+ ahb {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ apb {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ aic: interrupt-controller at fffff000 {
+ #interrupt-cells = <3>;
+ compatible = "atmel,at91rm9200-aic";
+ interrupt-controller;
+ reg = <0xfffff000 0x200>;
+ atmel,external-irqs = <25 26 27 28 29 30 31>;
+ };
+
+ ramc0: ramc at ffffff00 {
+ compatible = "atmel,at91rm9200-sdramc";
+ reg = <0xffffff00 0x100>;
+ };
+
+ pmc: pmc at fffffc00 {
+ compatible = "atmel,at91rm9200-pmc";
+ reg = <0xfffffc00 0x100>;
+ };
+
+ st: timer at fffffd00 {
+ compatible = "atmel,at91rm9200-st";
+ reg = <0xfffffd00 0x100>;
+ interrupts = <1 4 7>;
+ };
+
+ tcb0: timer at fffa0000 {
+ compatible = "atmel,at91rm9200-tcb";
+ reg = <0xfffa0000 0x100>;
+ interrupts = <17 4 0 18 4 0 19 4 0>;
+ };
+
+ tcb1: timer at fffa4000 {
+ compatible = "atmel,at91rm9200-tcb";
+ reg = <0xfffa4000 0x100>;
+ interrupts = <20 4 0 21 4 0 22 4 0>;
+ };
+
+ pioA: gpio at fffff400 {
+ compatible = "atmel,at91rm9200-gpio";
+ reg = <0xfffff400 0x100>;
+ interrupts = <2 4 1>;
+ #gpio-cells = <2>;
+ gpio-controller;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ pioB: gpio at fffff600 {
+ compatible = "atmel,at91rm9200-gpio";
+ reg = <0xfffff600 0x100>;
+ interrupts = <3 4 1>;
+ #gpio-cells = <2>;
+ gpio-controller;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ pioC: gpio at fffff800 {
+ compatible = "atmel,at91rm9200-gpio";
+ reg = <0xfffff800 0x100>;
+ interrupts = <4 4 1>;
+ #gpio-cells = <2>;
+ gpio-controller;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ pioD: gpio at fffffa00 {
+ compatible = "atmel,at91rm9200-gpio";
+ reg = <0xfffffa00 0x100>;
+ interrupts = <5 4 1>;
+ #gpio-cells = <2>;
+ gpio-controller;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ status = "disabled";
+ };
+
+ dbgu: serial at fffff200 {
+ compatible = "atmel,at91rm9200-usart";
+ reg = <0xfffff200 0x200>;
+ interrupts = <1 4 7>;
+ status = "disabled";
+ };
+
+ usart0: serial at fffc0000 {
+ compatible = "atmel,at91rm9200-usart";
+ reg = <0xfffc0000 0x200>;
+ interrupts = <6 4 5>;
+ atmel,use-dma-rx;
+ atmel,use-dma-tx;
+ status = "disabled";
+ };
+
+ usart1: serial at fffc4000 {
+ compatible = "atmel,at91rm9200-usart";
+ reg = <0xfffc4000 0x200>;
+ interrupts = <7 4 5>;
+ atmel,use-dma-rx;
+ atmel,use-dma-tx;
+ status = "disabled";
+ };
+
+ usart2: serial at fffc8000 {
+ compatible = "atmel,at91rm9200-usart";
+ reg = <0xfffc8000 0x200>;
+ interrupts = <8 4 5>;
+ atmel,use-dma-rx;
+ atmel,use-dma-tx;
+ status = "disabled";
+ };
+
+ usart3: serial at fffcc000 {
+ compatible = "atmel,at91rm9200-usart";
+ reg = <0xfffcc000 0x200>;
+ interrupts = <23 4 5>;
+ atmel,use-dma-rx;
+ atmel,use-dma-tx;
+ status = "disabled";
+ };
+
+ usb1: gadget at fffb0000 {
+ compatible = "atmel,at91rm9200-udc";
+ reg = <0xfffb0000 0x4000>;
+ interrupts = <11 4 2>;
+ status = "disabled";
+ };
+ };
+
+ nand0: nand at 40000000 {
+ compatible = "atmel,at91rm9200-nand";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x40000000 0x10000000>;
+ atmel,nand-addr-offset = <21>;
+ atmel,nand-cmd-offset = <22>;
+ nand-ecc-mode = "soft";
+ gpios = <&pioC 2 0
+ 0
+ &pioB 1 0
+ >;
+ status = "disabled";
+ };
+
+ usb0: ohci at 00300000 {
+ compatible = "atmel,at91rm9200-ohci", "usb-ohci";
+ reg = <0x00300000 0x100000>;
+ interrupts = <23 4 2>;
+ status = "disabled";
+ };
+ };
+
+ i2c at 0 {
+ compatible = "i2c-gpio";
+ gpios = <&pioA 23 0 /* sda */
+ &pioA 24 0 /* scl */
+ >;
+ i2c-gpio,sda-open-drain;
+ i2c-gpio,scl-open-drain;
+ i2c-gpio,delay-us = <2>; /* ~100 kHz */
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+};
--
1.7.12.2
^ permalink raw reply related
* [PATCH 3/4] ARM: AT91: Add AT91RM9200 support to DT board
From: Joachim Eastwood @ 2012-10-11 22:05 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1349993126-9519-1-git-send-email-manabian@gmail.com>
Signed-off-by: Joachim Eastwood <manabian@gmail.com>
---
Hi,
This patch has some potential issues.
Before this patch board-dt would fail building when only AT91RM9200 was enabled because at91sam926x_timer symbol would be missing. This patch uses the at91rm9200_timer which
will fail if AT91RM9200 is not enabled.
Any thoughts on solving this? As mention above this bug exists in mainline now.
I had to create a new at91rm9200_dt_initialize since at91_dt_initialize will panic when it tries to add rstc and shdwc.
Is it okay to add at91rm9200_dt_initialize or should we fix at91_dt_rstc and at91_dt_shdwc to not panic when DT nodes are not found?
regards
Joachim Eastwood
arch/arm/mach-at91/board-dt.c | 15 +++++++++++++++
arch/arm/mach-at91/generic.h | 1 +
arch/arm/mach-at91/setup.c | 14 ++++++++++++++
3 files changed, 30 insertions(+)
diff --git a/arch/arm/mach-at91/board-dt.c b/arch/arm/mach-at91/board-dt.c
index e8f45c4..0e73317 100644
--- a/arch/arm/mach-at91/board-dt.c
+++ b/arch/arm/mach-at91/board-dt.c
@@ -45,11 +45,26 @@ static void __init at91_dt_device_init(void)
of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
}
+static const char *at91rm9200_dt_board_compat[] __initdata = {
+ "atmel,at91rm9200",
+ NULL
+};
+
static const char *at91_dt_board_compat[] __initdata = {
"atmel,at91sam9",
NULL
};
+DT_MACHINE_START(at91rm9200_dt, "Atmel AT91RM9200 (Device Tree)")
+ .timer = &at91rm9200_timer,
+ .map_io = at91_map_io,
+ .handle_irq = at91_aic_handle_irq,
+ .init_early = at91rm9200_dt_initialize,
+ .init_irq = at91_dt_init_irq,
+ .init_machine = at91_dt_device_init,
+ .dt_compat = at91rm9200_dt_board_compat,
+MACHINE_END
+
DT_MACHINE_START(at91sam_dt, "Atmel AT91SAM (Device Tree)")
/* Maintainer: Atmel */
.timer = &at91sam926x_timer,
diff --git a/arch/arm/mach-at91/generic.h b/arch/arm/mach-at91/generic.h
index f496506..9bb5ce5 100644
--- a/arch/arm/mach-at91/generic.h
+++ b/arch/arm/mach-at91/generic.h
@@ -20,6 +20,7 @@ extern void __init at91_init_sram(int bank, unsigned long base,
extern void __init at91rm9200_set_type(int type);
extern void __init at91_initialize(unsigned long main_clock);
extern void __init at91x40_initialize(unsigned long main_clock);
+extern void __init at91rm9200_dt_initialize(void);
extern void __init at91_dt_initialize(void);
/* Interrupts */
diff --git a/arch/arm/mach-at91/setup.c b/arch/arm/mach-at91/setup.c
index da9881b..2c1fdd4 100644
--- a/arch/arm/mach-at91/setup.c
+++ b/arch/arm/mach-at91/setup.c
@@ -338,6 +338,7 @@ static void at91_dt_rstc(void)
}
static struct of_device_id ramc_ids[] = {
+ { .compatible = "atmel,at91rm9200-sdramc" },
{ .compatible = "atmel,at91sam9260-sdramc" },
{ .compatible = "atmel,at91sam9g45-ddramc" },
{ /*sentinel*/ }
@@ -436,6 +437,19 @@ end:
of_node_put(np);
}
+void __init at91rm9200_dt_initialize(void)
+{
+ at91_dt_ramc();
+
+ /* Init clock subsystem */
+ at91_dt_clock_init();
+
+ /* Register the processor-specific clocks */
+ at91_boot_soc.register_clocks();
+
+ at91_boot_soc.init();
+}
+
void __init at91_dt_initialize(void)
{
at91_dt_rstc();
--
1.7.12.2
^ permalink raw reply related
* [PATCH 2/4] ARM: AT91: Add usart/tc DT clock lookup to AT91RM9200
From: Joachim Eastwood @ 2012-10-11 22:05 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1349993126-9519-1-git-send-email-manabian@gmail.com>
Signed-off-by: Joachim Eastwood <manabian@gmail.com>
---
arch/arm/mach-at91/at91rm9200.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/arch/arm/mach-at91/at91rm9200.c b/arch/arm/mach-at91/at91rm9200.c
index b4f0565..eef3f53 100644
--- a/arch/arm/mach-at91/at91rm9200.c
+++ b/arch/arm/mach-at91/at91rm9200.c
@@ -188,6 +188,19 @@ static struct clk_lookup periph_clocks_lookups[] = {
CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk),
CLKDEV_CON_DEV_ID("pclk", "ssc.2", &ssc2_clk),
CLKDEV_CON_DEV_ID(NULL, "i2c-at91rm9200", &twi_clk),
+ /* usart lookup table for DT entries */
+ CLKDEV_CON_DEV_ID("usart", "fffff200.serial", &mck),
+ CLKDEV_CON_DEV_ID("usart", "fffc0000.serial", &usart0_clk),
+ CLKDEV_CON_DEV_ID("usart", "fffc4000.serial", &usart1_clk),
+ CLKDEV_CON_DEV_ID("usart", "fffc8000.serial", &usart2_clk),
+ CLKDEV_CON_DEV_ID("usart", "fffcc000.serial", &usart3_clk),
+ /* tc lookup table for DT entries */
+ CLKDEV_CON_DEV_ID("t0_clk", "fffa0000.timer", &tc0_clk),
+ CLKDEV_CON_DEV_ID("t1_clk", "fffa0000.timer", &tc1_clk),
+ CLKDEV_CON_DEV_ID("t2_clk", "fffa0000.timer", &tc2_clk),
+ CLKDEV_CON_DEV_ID("t0_clk", "fffa4000.timer", &tc3_clk),
+ CLKDEV_CON_DEV_ID("t1_clk", "fffa4000.timer", &tc4_clk),
+ CLKDEV_CON_DEV_ID("t2_clk", "fffa4000.timer", &tc5_clk),
/* fake hclk clock */
CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &ohci_clk),
CLKDEV_CON_ID("pioA", &pioA_clk),
--
1.7.12.2
^ permalink raw reply related
* [PATCH 1/4] ARM: AT91: Add DT support to AT91RM9200 System Timer
From: Joachim Eastwood @ 2012-10-11 22:05 UTC (permalink / raw)
To: linux-arm-kernel
Based on AT91 PIT DT patch from Jean-Christophe PLAGNIOL-VILLARD.
Signed-off-by: Joachim Eastwood <manabian@gmail.com>
---
.../devicetree/bindings/arm/atmel-at91.txt | 6 +++
arch/arm/mach-at91/at91rm9200_time.c | 63 +++++++++++++++++++++-
2 files changed, 67 insertions(+), 2 deletions(-)
diff --git a/Documentation/devicetree/bindings/arm/atmel-at91.txt b/Documentation/devicetree/bindings/arm/atmel-at91.txt
index ecc81e3..8adc9a8 100644
--- a/Documentation/devicetree/bindings/arm/atmel-at91.txt
+++ b/Documentation/devicetree/bindings/arm/atmel-at91.txt
@@ -7,6 +7,12 @@ PIT Timer required properties:
- interrupts: Should contain interrupt for the PIT which is the IRQ line
shared across all System Controller members.
+System Timer (ST) required properties:
+- compatible: Should be "atmel,at91rm9200-st"
+- reg: Should contain registers location and length
+- interrupts: Should contain interrupt for the ST which is the IRQ line
+ shared across all System Controller members.
+
TC/TCLIB Timer required properties:
- compatible: Should be "atmel,<chip>-pit".
<chip> can be "at91rm9200" or "at91sam9x5"
diff --git a/arch/arm/mach-at91/at91rm9200_time.c b/arch/arm/mach-at91/at91rm9200_time.c
index aaa443b..cafe988 100644
--- a/arch/arm/mach-at91/at91rm9200_time.c
+++ b/arch/arm/mach-at91/at91rm9200_time.c
@@ -24,6 +24,9 @@
#include <linux/irq.h>
#include <linux/clockchips.h>
#include <linux/export.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
#include <asm/mach/time.h>
@@ -91,7 +94,8 @@ static irqreturn_t at91rm9200_timer_interrupt(int irq, void *dev_id)
static struct irqaction at91rm9200_timer_irq = {
.name = "at91_tick",
.flags = IRQF_SHARED | IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
- .handler = at91rm9200_timer_interrupt
+ .handler = at91rm9200_timer_interrupt,
+ .irq = NR_IRQS_LEGACY + AT91_ID_SYS,
};
static cycle_t read_clk32k(struct clocksource *cs)
@@ -179,8 +183,60 @@ static struct clock_event_device clkevt = {
void __iomem *at91_st_base;
EXPORT_SYMBOL_GPL(at91_st_base);
+#ifdef CONFIG_OF
+static struct of_device_id at91rm9200_st_timer_ids[] = {
+ { .compatible = "atmel,at91rm9200-st" },
+ { /* sentinel */ }
+};
+
+static int __init of_at91rm9200_st_init(void)
+{
+ struct device_node *np;
+ int ret;
+
+ np = of_find_matching_node(NULL, at91rm9200_st_timer_ids);
+ if (!np)
+ goto err;
+
+ at91_st_base = of_iomap(np, 0);
+ if (!at91_st_base)
+ goto node_err;
+
+ /* Get the interrupts property */
+ ret = irq_of_parse_and_map(np, 0);
+ if (!ret)
+ goto ioremap_err;
+ at91rm9200_timer_irq.irq = ret;
+
+ of_node_put(np);
+
+ return 0;
+
+ioremap_err:
+ iounmap(at91_st_base);
+node_err:
+ of_node_put(np);
+err:
+ return -EINVAL;
+}
+#else
+static int __init of_at91rm9200_st_init(void)
+{
+ return -EINVAL;
+}
+#endif
+
void __init at91rm9200_ioremap_st(u32 addr)
{
+#ifdef CONFIG_OF
+ struct device_node *np;
+
+ np = of_find_matching_node(NULL, at91rm9200_st_timer_ids);
+ if (np) {
+ of_node_put(np);
+ return;
+ }
+#endif
at91_st_base = ioremap(addr, 256);
if (!at91_st_base)
panic("Impossible to ioremap ST\n");
@@ -191,13 +247,16 @@ void __init at91rm9200_ioremap_st(u32 addr)
*/
void __init at91rm9200_timer_init(void)
{
+ /* For device tree enabled device: initialize here */
+ of_at91rm9200_st_init();
+
/* Disable all timer interrupts, and clear any pending ones */
at91_st_write(AT91_ST_IDR,
AT91_ST_PITS | AT91_ST_WDOVF | AT91_ST_RTTINC | AT91_ST_ALMS);
at91_st_read(AT91_ST_SR);
/* Make IRQs happen for the system timer */
- setup_irq(NR_IRQS_LEGACY + AT91_ID_SYS, &at91rm9200_timer_irq);
+ setup_irq(at91rm9200_timer_irq.irq, &at91rm9200_timer_irq);
/* The 32KiHz "Slow Clock" (tick every 30517.58 nanoseconds) is used
* directly for the clocksource and all clockevents, after adjusting
--
1.7.12.2
^ permalink raw reply related
* [PATCH 07/11] fsmc/nand: Provide contiguous buffers to dma
From: Linus Walleij @ 2012-10-11 21:51 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAOh2x=mr4jQ1WQTC50H6OsN_E+7gtVSy_UMwjrt6Rj-QbQRtOA@mail.gmail.com>
On Thu, Oct 11, 2012 at 7:07 PM, viresh kumar <viresh.kumar@linaro.org> wrote:
> On Thu, Oct 11, 2012 at 9:36 PM, Linus Walleij <linus.walleij@linaro.org> wrote:
>>
>> And the block layer of the subsystem should take care
>> of only handing the driver buffers that are contiguous
>
> But why should that be a constraint on block layer? It is working in virtual
> space and is concerned about that onlly.
Not the block layer, the block layer of the subsystem.
It has to pick out the chunks that get transferred down to the drivers.
For example drivers/mmc/card/block.c will convert transfers into
sglists and pass down to the MMC drivers. mmc_queue_map_sg()
calls blk_rq_map_sg() to do the job. It's even documented in
Documentation/block/biodoc.txt
I don't know how that works in MTD...
Yours,
Linus Walleij
^ permalink raw reply
* [RFC PATCH v2 00/16] DMA Engine support for AM33xx
From: Matt Porter @ 2012-10-11 21:49 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CACxGe6vL2ieaYN_YhZn9=e7=prwdfwZtgPr4Ei3VMNnViib6XA@mail.gmail.com>
On Thu, Oct 11, 2012 at 10:31:58PM +0100, Grant Likely wrote:
> Hey Matt,
>
> Do you know now similar are the EDMA engines on the am33xx and am389x? I've
> been working on am389x upstreaming and I'll try these patches out if it is
> the same engine.
Hi Grant,
It's the same one. am389x/ti816x and am387x/ti814x are part of the same
architectural family as am33xx. They've just never had a lot of upstream
support from TI. I heard rumors that you might be working with am389x
and I'm glad you're confirming that for me! ;)
The only differences between am33xx's implementation and the others is
going to be the number PaRAM slots, number of TCs, the channel mapping,
and then the crossbar mapping. As you can see from the TODO list, I
don't yet support the crossbar, but it'll be in the next version of this
series. The other items are already covered in the DT binding so it
should be straightforward to hook this up for am389x assuming your hwmod
and clock data is good for that part.
-Matt
^ permalink raw reply
* [RFC PATCH v2 00/16] DMA Engine support for AM33xx
From: Grant Likely @ 2012-10-11 21:31 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1349982281-10785-1-git-send-email-mporter@ti.com>
Hey Matt,
Do you know now similar are the EDMA engines on the am33xx and am389x? I've
been working on am389x upstreaming and I'll try these patches out if it is
the same engine.
g.
On Oct 11, 2012 8:03 PM, "Matt Porter" <mporter@ti.com> wrote:
> Changes since v1:
> - Rebased on top of mainline from 12250d8
> - Dropped the feature removal schedule patch
> - Implemented dma_request_slave_channel_compat() and
> converted the mmc and spi drivers to use it
> - Dropped unneeded #address-cells and #size-cells from
> EDMA DT support
> - Moved private EDMA header to linux/platform_data/ and
> removed some unneeded definitions
> - Fixed parsing of optional properties
>
> TODO:
> - Add AM33xx crossbar support to the private EDMA API
> (any EDMA events on the crossbar are not supported)
> - Add dmaengine support for per-channel caps so the
> hack to set the maximum segments can be replaced with
> a query to the dmaengine driver
>
> This series adds DMA Engine support for AM33xx, which uses
> an EDMA DMAC. The EDMA DMAC has been previously supported by only
> a private API implementation (much like the situation with OMAP
> DMA) found on the DaVinci family of SoCs.
>
> The series applies on top of mainline from
> 12250d843e8489ee00b5b7726da855e51694e792 and the following patches:
>
> - Vaibhav's patch to fix AM33xx boot on mainline
> https://patchwork.kernel.org/patch/1569231/
> - dmaengine DT support from Vinod's dmaengine_dt branch in
> git://git.infradead.org/users/vkoul/slave-dma.git since
> 027478851791df751176398be02a3b1c5f6aa824
>
> The approach taken is similar to how OMAP DMA is being converted to
> DMA Engine support. With the functional EDMA private API already
> existing in mach-davinci/dma.c, we first move that to an ARM common
> area so it can be shared. Adding DT and runtime PM support to the
> private EDMA API implementation allows it to run on AM33xx. AM33xx
> *only* boots using DT so we leverage Jon's generic DT DMA helpers to
> register EDMA DMAC with the of_dma framework and then add support
> for calling the dma_request_slave_channel() API to both the mmc
> and spi drivers.
>
> What works? Well, with this series we now have MMC and SPI support
> on AM33xx. The only caveat for MMC is that the mmc3 controller has
> its events on the crossbar and is not usable yet.
>
> This is tested on BeagleBone with a SPI framebuffer driver and SD
> card. It is regression tested on AM180x-EVM (which also makes use
> of the EDMA dmaengine driver and the EDMA private API) using SD,
> SPI flash, and the onboard audio supported by the ASoC Davinci
> driver.
>
> After this series, the plan is to convert the last in-tree user
> of the private EDMA API (davinci-pcm/mcasp) and then eliminate
> the private EDMA API by folding its functionality into
> drivers/dma/edma.c.
>
> Matt Porter (16):
> dmaengine: edma: fix slave config dependency on direction
> ARM: davinci: move private EDMA API to arm/common
> ARM: edma: remove unused transfer controller handlers
> ARM: edma: add DT and runtime PM support for AM335x
> dmaengine: edma: enable build for AM33XX
> dmaengine: edma: Add TI EDMA device tree binding
> ARM: dts: add AM33XX EDMA support
> ARM: omap: add hsmmc am33xx specific init
> dmaengine: add dma_request_slave_channel_compat()
> mmc: omap_hsmmc: convert to dma_request_slave_channel_compat()
> mmc: omap_hsmmc: limit max_segs with the EDMA DMAC
> mmc: omap_hsmmc: add generic DMA request support to the DT binding
> ARM: dts: add AM33XX MMC support
> spi: omap2-mcspi: convert to dma_request_slave_channel_compat()
> spi: omap2-mcspi: add generic DMA request support to the DT binding
> ARM: dts: add AM33XX SPI support
>
> Documentation/devicetree/bindings/dma/ti-edma.txt | 49 +
> .../devicetree/bindings/mmc/ti-omap-hsmmc.txt | 25 +-
> Documentation/devicetree/bindings/spi/omap-spi.txt | 27 +-
> arch/arm/Kconfig | 1 +
> arch/arm/boot/dts/am335x-bone.dts | 23 +
> arch/arm/boot/dts/am33xx.dtsi | 100 ++
> arch/arm/common/Kconfig | 3 +
> arch/arm/common/Makefile | 1 +
> arch/arm/common/edma.c | 1781
> ++++++++++++++++++++
> arch/arm/mach-davinci/Makefile | 2 +-
> arch/arm/mach-davinci/board-da830-evm.c | 4 +-
> arch/arm/mach-davinci/board-da850-evm.c | 8 +-
> arch/arm/mach-davinci/board-dm646x-evm.c | 4 +-
> arch/arm/mach-davinci/board-omapl138-hawk.c | 8 +-
> arch/arm/mach-davinci/board-tnetv107x-evm.c | 2 +-
> arch/arm/mach-davinci/davinci.h | 2 +-
> arch/arm/mach-davinci/devices-da8xx.c | 8 +-
> arch/arm/mach-davinci/devices-tnetv107x.c | 6 +-
> arch/arm/mach-davinci/devices.c | 7 +-
> arch/arm/mach-davinci/dm355.c | 6 +-
> arch/arm/mach-davinci/dm365.c | 6 +-
> arch/arm/mach-davinci/dm644x.c | 6 +-
> arch/arm/mach-davinci/dm646x.c | 6 +-
> arch/arm/mach-davinci/dma.c | 1588
> -----------------
> arch/arm/mach-davinci/include/mach/da8xx.h | 2 +-
> arch/arm/mach-davinci/include/mach/edma.h | 267 ---
> arch/arm/mach-omap2/hsmmc.c | 7 +-
> arch/arm/plat-omap/Kconfig | 1 +
> drivers/dma/Kconfig | 2 +-
> drivers/dma/edma.c | 57 +-
> drivers/mmc/host/davinci_mmc.c | 1 +
> drivers/mmc/host/omap_hsmmc.c | 20 +-
> drivers/spi/spi-omap2-mcspi.c | 65 +-
> include/linux/dmaengine.h | 10 +
> include/linux/mfd/davinci_voicecodec.h | 3 +-
> include/linux/platform_data/edma.h | 198 +++
> include/linux/platform_data/spi-davinci.h | 2 +-
> sound/soc/davinci/davinci-evm.c | 1 +
> sound/soc/davinci/davinci-pcm.c | 1 +
> sound/soc/davinci/davinci-pcm.h | 2 +-
> sound/soc/davinci/davinci-sffsdr.c | 6 +-
> 41 files changed, 2361 insertions(+), 1957 deletions(-)
> create mode 100644 Documentation/devicetree/bindings/dma/ti-edma.txt
> create mode 100644 arch/arm/common/edma.c
> delete mode 100644 arch/arm/mach-davinci/dma.c
> delete mode 100644 arch/arm/mach-davinci/include/mach/edma.h
> create mode 100644 include/linux/platform_data/edma.h
>
> --
> 1.7.9.5
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20121011/6f884852/attachment-0001.html>
^ permalink raw reply
* [PATCH v2 1/4] net: mvneta: driver for Marvell Armada 370/XP network unit
From: Francois Romieu @ 2012-10-11 21:26 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1349969282-12676-2-git-send-email-thomas.petazzoni@free-electrons.com>
Thomas Petazzoni <thomas.petazzoni@free-electrons.com> :
[...]
> diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c
> new file mode 100644
> index 0000000..4f7fe08
> --- /dev/null
> +++ b/drivers/net/ethernet/marvell/mvneta.c
[...]
> +struct mvneta_port {
> + /* Packet size in bytes */
> + int pkt_size;
> +
> + /* Base virtual address of the Ethernet controller registers */
> + void __iomem *base;
> +
> + /* Array of RX queues */
> + struct mvneta_rx_queue *rxqs;
> +
> + /* Array of TX queues */
> + struct mvneta_tx_queue *txqs;
> +
> + /* Timer */
> + struct timer_list tx_done_timer;
> +
> + /* Back pointer to the Linux network interface device */
> + struct net_device *dev;
You can avoid five comments.
> +
> + u32 cause_rx_tx[CONFIG_NR_CPUS];
> + struct napi_struct napi;
> +
> + /* Flags */
> + unsigned long flags;
> +#define MVNETA_F_TX_DONE_TIMER_BIT 0
> +
> + /* Napi weight */
> + int weight;
> +
> + /* Core clock [Hz] */
> + unsigned int clk_rate;
clk_rate_hz
[...]
> +/* Get System Network Statistics */
> +struct rtnl_link_stats64 *mvneta_get_stats64(struct net_device *dev,
> + struct rtnl_link_stats64 *stats)
> +{
> + struct mvneta_port *pp = netdev_priv(dev);
> + unsigned int start;
> +
> + memset(stats, 0, sizeof(struct rtnl_link_stats64));
> +
> + do {
> + start = u64_stats_fetch_begin_bh(&pp->rx_stats.syncp);
> + stats->rx_packets = pp->rx_stats.packets;
> + stats->rx_bytes = pp->rx_stats.bytes;
> + } while (u64_stats_fetch_retry_bh(&pp->rx_stats.syncp, start));
> +
> +
> + do {
> + start = u64_stats_fetch_begin_bh(&pp->tx_stats.syncp);
> + stats->tx_packets = pp->tx_stats.packets;
> + stats->tx_bytes = pp->tx_stats.bytes;
> + } while (u64_stats_fetch_retry_bh(&pp->tx_stats.syncp, start));
> +
> + stats->rx_errors = dev->stats.rx_errors;
> + stats->rx_dropped = dev->stats.rx_dropped;
> +
> + stats->tx_dropped = dev->stats.tx_dropped;
> +
> + return stats;
> +
> +}
Excess empty line.
[...]
> +static void mvneta_rxq_desc_num_update(struct mvneta_port *pp,
> + struct mvneta_rx_queue *rxq,
> + int rx_done, int rx_filled)
> +{
> + u32 val;
> +
> + if ((rx_done <= 0xff) && (rx_filled <= 0xff)) {
> + val = rx_done |
> + (rx_filled << MVNETA_RXQ_ADD_NON_OCCUPIED_SHIFT);
> + mvreg_write(pp, MVNETA_RXQ_STATUS_UPDATE_REG(rxq->id), val);
> + return;
> + }
> +
> + /* Only 255 descriptors can be added at once */
> + while ((rx_done > 0) || (rx_filled > 0)) {
> + if (rx_done <= 0xff) {
> + val = rx_done;
> + rx_done = 0;
> + } else {
> + val = 0xff;
> + rx_done -= 0xff;
> + }
> + if (rx_filled <= 0xff) {
> + val |= rx_filled
> + << MVNETA_RXQ_ADD_NON_OCCUPIED_SHIFT;
val |= rx_filled << MVNETA_RXQ_ADD_NON_OCCUPIED_SHIFT;
> + rx_filled = 0;
> + } else {
> + val |= 0xff << MVNETA_RXQ_ADD_NON_OCCUPIED_SHIFT;
> + rx_filled -= 0xff;
> + }
> + mvreg_write(pp, MVNETA_RXQ_STATUS_UPDATE_REG(rxq->id), val);
> + }
> +}
> +
> +/* Get pointer to next RX descriptor to be processed by SW */
> +static struct mvneta_rx_desc *
> +mvneta_rxq_next_desc_get(struct mvneta_rx_queue *rxq)
> +{
> + int rx_desc = rxq->next_desc_to_proc;
> +
> + rxq->next_desc_to_proc =
> + MVNETA_QUEUE_NEXT_DESC(rxq, rx_desc);
rxq->next_desc_to_proc = MVNETA_QUEUE_NEXT_DESC(rxq, rx_desc);
> +
> + return rxq->descs + rx_desc;
> +}
> +
> +/* Change maximum receive size of the port. */
> +static void mvneta_max_rx_size_set(struct mvneta_port *pp, int max_rx_size)
> +{
> + u32 val;
> +
> + val = mvreg_read(pp, MVNETA_GMAC_CTRL_0);
> + val &= ~MVNETA_GMAC_MAX_RX_SIZE_MASK;
> + val |= (((max_rx_size - MVNETA_MH_SIZE) / 2)
> + << MVNETA_GMAC_MAX_RX_SIZE_SHIFT);
Excess parenthesis.
Operator on start of line.
[...]
> +static struct mvneta_tx_desc *
> +mvneta_txq_next_desc_get(struct mvneta_tx_queue *txq)
> +{
> + int tx_desc = txq->next_desc_to_proc;
> + txq->next_desc_to_proc =
> + MVNETA_QUEUE_NEXT_DESC(txq, tx_desc);
int tx_desc = txq->next_desc_to_proc;
txq->next_desc_to_proc = MVNETA_QUEUE_NEXT_DESC(txq, tx_desc);
[...]
> +static void mvneta_port_up(struct mvneta_port *pp)
> +{
> + int queue;
> + u32 q_map;
> +
> + /* Enable all initialized TXs. */
> + mvneta_mib_counters_clear(pp);
> + q_map = 0;
> + for (queue = 0; queue < mvneta_txq_number; queue++) {
> + struct mvneta_tx_queue *txq = &pp->txqs[queue];
> + if (txq->descs != NULL)
> + q_map |= (1 << queue);
> + }
> + mvreg_write(pp, MVNETA_TXQ_CMD, q_map);
> +
> + /* Enable all initialized RXQs. */
> + q_map = 0;
> + for (queue = 0; queue < mvneta_rxq_number; queue++) {
> + struct mvneta_rx_queue *rxq = &pp->rxqs[queue];
> + if (rxq->descs != NULL)
> + q_map |= (1 << queue);
> + }
> +
> + mvreg_write(pp, MVNETA_RXQ_CMD, q_map);
> +}
> +
> +/* Stop the Ethernet port activity */
> +static void mvneta_port_down(struct mvneta_port *pp)
> +{
> + u32 val;
> + int count;
> +
> + /* Stop Rx port activity. Check port Rx activity. */
> + val = (mvreg_read(pp, MVNETA_RXQ_CMD))
> + & MVNETA_RXQ_ENABLE_MASK;
val = mvreg_read(pp, MVNETA_RXQ_CMD) & MVNETA_RXQ_ENABLE_MASK;
> + /* Issue stop command for active channels only */
> + if (val != 0)
> + mvreg_write(pp, MVNETA_RXQ_CMD,
> + val << MVNETA_RXQ_DISABLE_SHIFT);
Too bad "val" isn't one character shorter.
> +
> + /* Wait for all Rx activity to terminate. */
> + count = 0;
> + do {
> + if (count >= MVNETA_RX_DISABLE_TIMEOUT_MSEC) {
> + netdev_warn(pp->dev,
> + "TIMEOUT for RX stopped ! rx_queue_cmd: 0x08%x\n",
> + val);
> + break;
> + }
> + mdelay(1);
> + count++;
> +
> + val = mvreg_read(pp, MVNETA_RXQ_CMD);
> + } while (val & 0xff);
You can test "if (count++ >= MVNETA_RX_DISABLE_TIMEOUT_MSEC) {". Nobody
will notice.
> +
> + /* Stop Tx port activity. Check port Tx activity. Issue stop
> + command for active channels only */
> + val = (mvreg_read(pp, MVNETA_TXQ_CMD)) & MVNETA_TXQ_ENABLE_MASK;
> +
> + if (val != 0)
> + mvreg_write(pp, MVNETA_TXQ_CMD,
> + (val << MVNETA_TXQ_DISABLE_SHIFT));
> +
> + /* Wait for all Tx activity to terminate. */
> + count = 0;
> + do {
> + if (count >= MVNETA_TX_DISABLE_TIMEOUT_MSEC) {
> + netdev_warn(pp->dev,
> + "TIMEOUT for TX stopped tx_queue_cmd - 0x%08x\n",
> + val);
> + break;
> + }
> + mdelay(1);
> + count++;
> +
> + /* Check TX Command reg that all Txqs are stopped */
> + val = mvreg_read(pp, MVNETA_TXQ_CMD);
> +
> + } while (val & 0xff);
> +
> + /* Double check to verify that TX FIFO is empty */
> + count = 0;
> + do {
> + if (count >= MVNETA_TX_FIFO_EMPTY_TIMEOUT) {
> + netdev_warn(pp->dev,
> + "TX FIFO empty timeout status=0x08%x",
> + val);
"TX FIFO empty timeout status=0x08%x", val);
> + break;
> + }
> + mdelay(1);
> + count++;
> +
> + val = mvreg_read(pp, MVNETA_PORT_STATUS);
> + } while (!(val & MVNETA_TX_FIFO_EMPTY) &&
> + (val & MVNETA_TX_IN_PRGRS));
> +
> + udelay(200);
> +}
> +
> +/* Enable the port by setting the port enable bit of the MAC control register */
> +static void mvneta_port_enable(struct mvneta_port *pp)
> +{
> + u32 val;
> +
> + /* Enable port */
> + val = mvreg_read(pp, MVNETA_GMAC_CTRL_0);
> + val |= MVNETA_GMAC0_PORT_ENABLE;
> + mvreg_write(pp, MVNETA_GMAC_CTRL_0, val);
> +}
> +
> +/* Disable the port and wait for about 200 usec before retuning */
> +static void mvneta_port_disable(struct mvneta_port *pp)
> +{
> + u32 val;
> +
> + /* Reset the Enable bit in the Serial Control Register */
> + val = mvreg_read(pp, MVNETA_GMAC_CTRL_0);
> + val &= ~(MVNETA_GMAC0_PORT_ENABLE);
Excess parenthesis.
> + mvreg_write(pp, MVNETA_GMAC_CTRL_0, val);
> +
> + udelay(200);
> +}
> +
> +/* Multicast tables methods */
> +
> +/* Set all entries in Unicast MAC Table; queue==-1 means reject all */
> +static void mvneta_set_ucast_table(struct mvneta_port *pp, int queue)
> +{
> + int offset;
> + u32 val;
> +
> + if (queue == -1) {
> + val = 0;
> + } else {
> + val = (((0x01 | (queue << 1)) << 0) |
> + ((0x01 | (queue << 1)) << 8) |
> + ((0x01 | (queue << 1)) << 16) |
> + ((0x01 | (queue << 1)) << 24));
val = (0x01 | (queue << 1)) |
((0x01 | (queue << 1)) << 8) |
((0x01 | (queue << 1)) << 16) |
((0x01 | (queue << 1)) << 24);
val = 0x01 | (queue << 1);
val |= (val << 24) | (val << 16) | (val << 8);
> + }
> +
> + for (offset = 0; offset <= 0xc; offset += 4)
> + mvreg_write(pp, MVNETA_DA_FILT_UCAST_BASE + offset, val);
> +}
> +
> +/* Set all entries in Special Multicast MAC Table; queue==-1 means reject all */
> +static void mvneta_set_special_mcast_table(struct mvneta_port *pp, int queue)
> +{
> + int offs;
> + u32 val;
> +
> + if (queue == -1) {
> + val = 0;
> + } else {
> + val = (((0x01 | (queue << 1)) << 0) |
> + ((0x01 | (queue << 1)) << 8) |
> + ((0x01 | (queue << 1)) << 16) |
> + ((0x01 | (queue << 1)) << 24));
Bis.
> + }
> +
> + for (offs = 0; offs <= 0xfc; offs += 4)
> + mvreg_write(pp, (MVNETA_DA_FILT_SPEC_MCAST + offs), val);
> +
> +}
> +
> +/* Set all entries in Other Multicast MAC Table. queue==-1 means reject all */
> +static void mvneta_set_other_mcast_table(struct mvneta_port *pp, int queue)
> +{
> + int offset;
> + u32 val;
> +
> + if (queue == -1) {
> + memset(pp->mcast_count, 0, sizeof(pp->mcast_count));
> + val = 0;
> + } else {
> + memset(pp->mcast_count, 1, sizeof(pp->mcast_count));
> + val = (((0x01 | (queue << 1)) << 0) |
> + ((0x01 | (queue << 1)) << 8) |
> + ((0x01 | (queue << 1)) << 16) |
> + ((0x01 | (queue << 1)) << 24));
Ter.
[...]
> +static void mvneta_rx_pkts_coal_set(struct mvneta_port *pp,
> + struct mvneta_rx_queue *rxq, u32 value)
> +{
> + mvreg_write(pp, MVNETA_RXQ_THRESHOLD_REG(rxq->id),
> + (value | MVNETA_RXQ_NON_OCCUPIED(0)));
Excess parenthesis.
> + rxq->pkts_coal = value;
> +}
> +
> +/*
> + * Set the time delay in usec before
> + * RX interrupt will be generated by HW.
> + */
> +static void mvneta_rx_time_coal_set(struct mvneta_port *pp,
> + struct mvneta_rx_queue *rxq, u32 value)
> +{
> + u32 val = (pp->clk_rate / 1000000) * value;
> +
> + mvreg_write(pp, MVNETA_RXQ_TIME_COAL_REG(rxq->id), val);
> + rxq->time_coal = value;
> +}
> +
> +/* Set threshold for TX_DONE pkts coalescing */
> +static void mvneta_tx_done_pkts_coal_set(struct mvneta_port *pp,
> + struct mvneta_tx_queue *txq, u32 value)
> +{
> + u32 val;
> +
> + val = mvreg_read(pp, MVNETA_TXQ_SIZE_REG(txq->id));
> +
> + val &= ~MVNETA_TXQ_SENT_THRESH_ALL_MASK;
> + val |= MVNETA_TXQ_SENT_THRESH_MASK(value);
> +
> + mvreg_write(pp, MVNETA_TXQ_SIZE_REG(txq->id), val);
> +
> + txq->done_pkts_coal = value;
> +}
> +
> +/* Trigger tx done timer in MVNETA_TX_DONE_TIMER_PERIOD msecs */
> +static void mvneta_add_tx_done_timer(struct mvneta_port *pp)
> +{
> + if (test_and_set_bit(MVNETA_F_TX_DONE_TIMER_BIT, &pp->flags) == 0) {
> + pp->tx_done_timer.expires = jiffies +
> + msecs_to_jiffies(MVNETA_TX_DONE_TIMER_PERIOD);
> + add_timer(&pp->tx_done_timer);
> + }
> +}
> +
> +
> +/* Handle rx descriptor fill by setting buf_cookie and buf_phys_addr */
> +static void mvneta_rx_desc_fill(struct mvneta_rx_desc *rx_desc,
> + u32 phys_addr, u32 cookie)
> +{
> + rx_desc->buf_cookie = cookie;
> + rx_desc->buf_phys_addr = phys_addr;
> +}
> +
> +/* Decrement sent descriptors counter */
> +static void mvneta_txq_sent_desc_dec(struct mvneta_port *pp,
> + struct mvneta_tx_queue *txq,
> + int sent_desc)
> +{
> + u32 val;
> +
> + /* Only 255 TX descriptors can be updated at once */
> + while (sent_desc > 0xff) {
> + val = (0xff << MVNETA_TXQ_DEC_SENT_SHIFT);
Parenthesis.
> + mvreg_write(pp, MVNETA_TXQ_UPDATE_REG(txq->id), val);
> + sent_desc = sent_desc - 0xff;
> + }
> +
> + val = (sent_desc << MVNETA_TXQ_DEC_SENT_SHIFT);
Parenthesis.
[...]
> +static u32 mvneta_txq_desc_csum(int l3_offs, int l3_proto,
> + int ip_hdr_len, int l4_proto)
> +{
> + u32 command;
> +
> + /* Fields: L3_offset, IP_hdrlen, L3_type, G_IPv4_chk,
> + G_L4_chk, L4_type; required only for checksum
> + calculation */
> + command = (l3_offs << MVNETA_TX_L3_OFF_SHIFT);
> + command |= (ip_hdr_len << MVNETA_TX_IP_HLEN_SHIFT);
Parenthesis.
> +
> + if (l3_proto == swab16(ETH_P_IP))
> + command |= MVNETA_TXD_IP_CSUM;
> + else
> + command |= MVNETA_TX_L3_IP6;
> +
> + if (l4_proto == IPPROTO_TCP)
> + command |= MVNETA_TX_L4_CSUM_FULL;
> + else if (l4_proto == IPPROTO_UDP)
> + command |= (MVNETA_TX_L4_UDP | MVNETA_TX_L4_CSUM_FULL);
> + else
> + command |= MVNETA_TX_L4_CSUM_NOT;
> +
> + return command;
> +}
> +
> +/* Display more error info */
> +static void mvneta_rx_error(struct mvneta_port *pp,
> + struct mvneta_rx_desc *rx_desc)
> +{
> + u32 status = rx_desc->status;
> +
> + if ((status & MVNETA_RXD_FIRST_LAST_DESC)
> + != MVNETA_RXD_FIRST_LAST_DESC) {
if ((status & MVNETA_RXD_FIRST_LAST_DESC) !=
MVNETA_RXD_FIRST_LAST_DESC) {
The length of the MVNETA prefix is a self inflicted pain.
(...]
> +static struct mvneta_tx_queue *mvneta_tx_done_policy(struct mvneta_port *pp,
> + u32 cause)
> +{
> + int queue;
> + queue = fls(cause) - 1;
> + if (queue < 0 || queue >= mvneta_txq_number)
> + return NULL;
> + return &pp->txqs[queue];
return (q < 0 || q >= mvneta_txq_number) ? NULL : &pp->txqs[q]; ?
(I admit it will obviously not resurrect an unicorn)
> +}
> +
> +/* Free tx queue skbuffs */
> +static void mvneta_txq_bufs_free(struct mvneta_port *pp,
> + struct mvneta_tx_queue *txq, int num)
> +{
> + struct sk_buff *skb;
> + int i;
> + struct mvneta_tx_desc *tx_desc;
int i;
> + for (i = 0; i < num; i++) {
> + skb = txq->tx_skb[txq->txq_get_index];
> + tx_desc = txq->descs + txq->txq_get_index;
struct mvneta_tx_desc *tx_desc = txq->descs + txq->txq_get_index;
struct sk_buff *skb = txq->tx_skb[txq->txq_get_index];
> +
> + mvneta_txq_inc_get(txq);
> +
> + if (!skb)
> + continue;
> + if (tx_desc) {
> + dma_unmap_single(pp->dev->dev.parent,
> + tx_desc->buf_phys_addr,
> + tx_desc->data_size,
> + DMA_TO_DEVICE);
> + dev_kfree_skb_any(skb);
if (!(skb && txd))
continue;
dma_unmap_single(pp->dev->dev.parent, tx_desc->buf_phys_addr,
tx_desc->data_size, DMA_TO_DEVICE);
> + }
> + }
> +}
> +
> +/* Handle end of transmission */
> +static int mvneta_txq_done(struct mvneta_port *pp,
> + struct mvneta_tx_queue *txq)
> +{
> + int tx_done;
> +
> + tx_done = mvneta_txq_sent_desc_proc(pp, txq);
> + if (tx_done == 0)
> + return tx_done;
> + mvneta_txq_bufs_free(pp, txq, tx_done);
> +
> + txq->count -= tx_done;
> +
> + return tx_done;
> +}
> +
> +/* Refill processing */
> +static int mvneta_rx_refill(struct mvneta_port *pp,
> + struct mvneta_rx_desc *rx_desc)
> +
> +{
> + unsigned long phys_addr;
dma_addr_t phys_addr;
> + struct sk_buff *skb;
> +
> + skb = netdev_alloc_skb(pp->dev, pp->pkt_size);
> + if (!skb)
> + return 1;
> +
> + phys_addr = dma_map_single(pp->dev->dev.parent, skb->head,
> + MVNETA_RX_BUF_SIZE(pp->pkt_size),
> + DMA_FROM_DEVICE);
> + if (unlikely(dma_mapping_error(pp->dev->dev.parent,
> + phys_addr))) {
> + dev_kfree_skb_irq(skb);
dev_kfree_skb in softirq context.
[...]
> +static struct mvneta_rx_queue *mvneta_rx_policy(struct mvneta_port *pp,
> + u32 cause)
> +{
> + int queue = fls(cause >> 8) - 1;
> + if (queue < 0 || queue >= mvneta_rxq_number)
> + return NULL;
> + return &pp->rxqs[queue];
> +}
> +
> +/* Drop packets received by the RXQ and free buffers */
> +static void mvneta_rxq_drop_pkts(struct mvneta_port *pp,
> + struct mvneta_rx_queue *rxq)
> +{
> + struct mvneta_rx_desc *rx_desc;
> + struct sk_buff *skb;
Variable scope.
> + int rx_done, i;
> +
> + rx_done = mvneta_rxq_busy_desc_num_get(pp, rxq);
> + for (i = 0; i < rxq->size; i++) {
> + rx_desc = rxq->descs + i;
> + skb = (struct sk_buff *)rx_desc->buf_cookie;
> + dev_kfree_skb_any(skb);
> + dma_unmap_single(pp->dev->dev.parent, rx_desc->buf_phys_addr,
> + rx_desc->data_size, DMA_FROM_DEVICE);
> +
> +
> + }
> + if (rx_done)
> + mvneta_rxq_desc_num_update(pp, rxq, rx_done, rx_done);
> +}
> +
> +
> +/* Main rx processing */
> +static int mvneta_rx(struct mvneta_port *pp, int rx_todo,
> + struct mvneta_rx_queue *rxq)
> +{
> + struct net_device *dev = pp->dev;
> +
> + int rx_done, rx_filled, err;
> + struct mvneta_rx_desc *rx_desc;
Variable scope.
> + u32 rx_status;
> + int rx_bytes;
> + struct sk_buff *skb;
> +
> + /* Get number of received packets */
> + rx_done = mvneta_rxq_busy_desc_num_get(pp, rxq);
> +
> + if (rx_todo > rx_done)
> + rx_todo = rx_done;
> +
> + rx_done = 0;
> + rx_filled = 0;
> +
> + /* Fairness NAPI loop */
> + while (rx_done < rx_todo) {
> + rx_desc = mvneta_rxq_next_desc_get(rxq);
> + prefetch(rx_desc);
> + rx_done++;
> + rx_filled++;
> + rx_status = rx_desc->status;
> + skb = (struct sk_buff *)rx_desc->buf_cookie;
> +
> + if (((rx_status & MVNETA_RXD_FIRST_LAST_DESC)
> + != MVNETA_RXD_FIRST_LAST_DESC)
> + || (rx_status & MVNETA_RXD_ERR_SUMMARY)) {
...
> + dev->stats.rx_errors++;
> + mvneta_rx_error(pp, rx_desc);
> + mvneta_rx_desc_fill(rx_desc, rx_desc->buf_phys_addr,
> + (u32)skb);
> + continue;
> + }
> +
> + dma_unmap_single(pp->dev->dev.parent, rx_desc->buf_phys_addr,
> + rx_desc->data_size, DMA_FROM_DEVICE);
> +
> + rx_bytes = rx_desc->data_size -
> + (MVNETA_ETH_CRC_SIZE + MVNETA_MH_SIZE);
> + u64_stats_update_begin(&pp->rx_stats.syncp);
> + pp->rx_stats.packets++;
> + pp->rx_stats.bytes += rx_bytes;
> + u64_stats_update_end(&pp->rx_stats.syncp);
> +
> + /* Linux processing */
> + skb->data += MVNETA_MH_SIZE;
> + skb->tail += (rx_bytes + MVNETA_MH_SIZE);
skb_reserve + skb_put would be more idiomatic imho.
> + skb->len = rx_bytes;
> +
> + skb->protocol = eth_type_trans(skb, dev);
> +
> + mvneta_rx_csum(pp, rx_desc, skb);
> +
> + if (dev->features & NETIF_F_GRO)
> + napi_gro_receive(&pp->napi, skb);
> + else
> + netif_receive_skb(skb);
No test. Go for straight napi_gro_receive.
> +
> + /* Refill processing */
> + err = mvneta_rx_refill(pp, rx_desc);
> + if (err) {
> + netdev_err(pp->dev, "Linux processing - Can't refill\n");
> + rxq->missed++;
> + rx_filled--;
> + }
> + }
> +
> + /* Update rxq management counters */
> + mvneta_rxq_desc_num_update(pp, rxq, rx_done, rx_filled);
> +
> + return rx_done;
> +}
> +
> +/* Handle tx fragmentation processing */
> +static int mvneta_tx_frag_process(struct mvneta_port *pp, struct sk_buff *skb,
> + struct mvneta_tx_queue *txq)
> +{
> + int i, j;
> + struct mvneta_tx_desc *tx_desc;
> + skb_frag_t *frag;
struct device *d = pp->dev->dev.parent;
struct mvneta_tx_desc *tx_desc;
int i, j;
> +
> + for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
> + frag = &skb_shinfo(skb)->frags[i];
skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
void *addr = page_address(frag->page.p) + frag->page_offset;
> +
> + tx_desc = mvneta_txq_next_desc_get(txq);
> + tx_desc->data_size = frag->size;
> +
> + tx_desc->buf_phys_addr =
> + dma_map_single(pp->dev->dev.parent,
> + page_address(frag->page.p) +
> + frag->page_offset, tx_desc->data_size,
> + DMA_TO_DEVICE);
tx_desc->buf_phys_addr = dma_map_single(d, addr, frag->size,
DMA_TO_DEVICE);
[...]
> +static int mvneta_tx(struct sk_buff *skb, struct net_device *dev)
> +{
> + struct mvneta_port *pp = netdev_priv(dev);
> + int frags = 0;
> + int res = NETDEV_TX_OK;
> + u32 tx_cmd;
> + struct mvneta_tx_queue *txq = &pp->txqs[mvneta_txq_def];
> + struct mvneta_tx_desc *tx_desc;
Longer first.
> +
> + if (!netif_running(dev))
> + goto out;
> +
> + frags = skb_shinfo(skb)->nr_frags + 1;
> +
> + /* Are there enough TX descriptors to send packet ? */
Never. You must disable queueing before it's too late.
> + if ((txq->count + frags) >= txq->size) {
> + frags = 0;
> + res = NETDEV_TX_BUSY;
> + goto out;
> + }
> +
> + /* Get a descriptor for the first part of the packet */
> + tx_desc = mvneta_txq_next_desc_get(txq);
> +
> + tx_cmd = mvneta_skb_tx_csum(pp, skb);
> +
> + tx_desc->data_size = skb_headlen(skb);
> +
> + tx_desc->buf_phys_addr = dma_map_single(dev->dev.parent, skb->data,
> + tx_desc->data_size,
> + DMA_TO_DEVICE);
> + if (unlikely(dma_mapping_error(dev->dev.parent,
> + tx_desc->buf_phys_addr))) {
> + mvneta_txq_desc_put(txq);
> + frags = 0;
> + res = NETDEV_TX_BUSY;
Neither. You drop the packet, update the stats and return ok.
> + goto out;
> + }
> +
> + if (frags == 1) {
> + /* First and Last descriptor */
> + tx_cmd |= MVNETA_TXD_FLZ_DESC;
> + tx_desc->command = tx_cmd;
> + txq->tx_skb[txq->txq_put_index] = skb;
> + mvneta_txq_inc_put(txq);
> + } else {
> + /* First but not Last */
> + tx_cmd |= MVNETA_TXD_F_DESC;
> + txq->tx_skb[txq->txq_put_index] = NULL;
> + mvneta_txq_inc_put(txq);
> + tx_desc->command = tx_cmd;
> + /* Continue with other skb fragments */
> + if (mvneta_tx_frag_process(pp, skb, txq)) {
> + dma_unmap_single(dev->dev.parent,
> + tx_desc->buf_phys_addr,
> + tx_desc->data_size,
> + DMA_TO_DEVICE);
> + mvneta_txq_desc_put(txq);
> + frags = 0;
> + res = NETDEV_TX_BUSY;
Sic.
[...]
> +/* handle tx done - called from tx done timer callback */
> +static u32 mvneta_tx_done_gbe(struct mvneta_port *pp, u32 cause_tx_done,
> + int *tx_todo)
Why is it not done in napi context ?
--
Ueimor
^ permalink raw reply
* Booting vanilla kernel on the beaglebone
From: N, Mugunthan V @ 2012-10-11 21:20 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <5076B2FE.8040000@ti.com>
> -------- Original Message --------
> Subject: Re: Booting vanilla kernel on the beaglebone
> Date: Thu, 11 Oct 2012 07:09:48 +0200
> From: Richard Cochran <richardcochran@gmail.com>
> To: Hiremath, Vaibhav <hvaibhav@ti.com>
> CC: linux-arm-kernel at lists.infradead.org
> <linux-arm-kernel@lists.infradead.org>
>
> On Tue, Oct 09, 2012 at 06:34:18PM +0000, Hiremath, Vaibhav wrote:
> >
> > As I mentioned they are expected to get merged for rc1 and result of
> > integration during merge window.
>
> There is a DT binding document
>
> Documentation/devicetree/bindings/net/cpsw.txt
>
> but cpsw does not appear in either am335x-bone.dts, am335x-evm.dts, or
> am33xx.dtsi, or for that matter, in *any* dts file anywhere. I have
> looked in mainline master, linux-next, and in the master branch of
>
> git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap.git
>
> Is there an issue keeping the cpsw/DT combination from working?
> If not, is there a file dts for the bealgebone somewhere?
Richard
I have a working branch for CPSW which is based on 3.5.0-rc6 in the following git repo
Repo: https://github.com/hvaibhav/am335x-linux.git
Branch: am335x-linux-next-master-cpsw
Regards
Mugunthan V N
^ permalink raw reply
* bug with 3.4.6, 3.5.3, 3.6.1
From: Gilles Chanteperdrix @ 2012-10-11 20:58 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20121011195033.GA31946@mudshark.cambridge.arm.com>
On 10/11/2012 09:50 PM, Will Deacon wrote:
> On 10/11/2012 03:59 PM, Will Deacon wrote:
>> I'll have to do some digging and get back to you.
>
> Ok, so here's what I think is going on (although note that I'm at home now,
> so I've not been able to test anything):
>
> - Your PHYS_OFFSET is at 2GB, so your static idmap is as follows:
> idmap: 0x8029c638 - 0x8029c66c and I think your init_mm lives
> at 0x8037f2b4.
>
> - The idmap takes up two sections, so actually spans from:
> 0x80200000 - 0x80400000 and is mapped as *strongly ordered*.
>
> This means that the atomic_inc(&mm->mm_count); in secondary_start_kernel
> is UNPREDICTABLE, because it results in an exclusive access to
> strongly-ordered memory.
>
> There are several ways to solve this:
>
> 1. Avoid exclusives with the idmap (see patch below)
> 2. Set idmap_pgd to swapper when VA == PA
> 3. Map idmap with pages and round up text section
> 4. Switch to swapper before entering secondary_start_kernel
> 5. Make idmap normal (cacheable?) shared memory
>
> However, these have some problems:
>
> (2) means the idmap is cacheable. This is probably not an issue
> when VA == PA, but it's still an oddity compared to other setups
>
> (3) is really messy
>
> (4,5) probably have serious issues with SMP
>
> so I've had a crack at (1) below. Please see if it fixes your problem.
>
> Cheers,
>
> Will
>
> --->8
>
> diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
> index d100eac..aa55580 100644
> --- a/arch/arm/kernel/smp.c
> +++ b/arch/arm/kernel/smp.c
> @@ -290,18 +290,24 @@ static void percpu_timer_setup(void);
> asmlinkage void __cpuinit secondary_start_kernel(void)
> {
> struct mm_struct *mm = &init_mm;
> - unsigned int cpu = smp_processor_id();
> + unsigned int cpu;
> +
> + /*
> + * The identity mapping is uncached (strongly ordered), so
> + * switch away from it before attempting any exclusive accesses.
> + */
> + cpu_switch_mm(mm->pgd, mm);
> + enter_lazy_tlb(mm, current);
> + local_flush_tlb_all();
>
> /*
> * All kernel threads share the same mm context; grab a
> * reference and switch to it.
> */
> + cpu = smp_processor_id();
> atomic_inc(&mm->mm_count);
> current->active_mm = mm;
> cpumask_set_cpu(cpu, mm_cpumask(mm));
> - cpu_switch_mm(mm->pgd, mm);
> - enter_lazy_tlb(mm, current);
> - local_flush_tlb_all();
>
> printk("CPU%u: Booted secondary processor\n", cpu);
Works for me. But note that now the comment is wrong.
--
Gilles.
^ permalink raw reply
* [RFC PATCH] ARM: vt8500: Convert arch-vt8500 to multiplatform
From: Arnd Bergmann @ 2012-10-11 20:29 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1349979450.16017.3.camel@gitbox>
On Thursday 11 October 2012, Tony Prisk wrote:
> > config VT8500
> > bool "Via/Wondermedia VT8500 / WM8505 / WM8650" if ARCH_MULTIPLATFORM
> > default VT8500_SINGLE
> >
> > Arnd
>
> Alexey (or anyone else),
>
> Do you want it kept in the meantime?
>
> I think the easiest way to add/keep it would be to create:
>
> ARCH_VT8500_SINGLE (arm/Kconfig) and ARCH_VT8500_MULTI
> (arch-vt8500/Kconfig) and have them both select ARCH_VT8500 as an option
> to make drivers available.
You only need one new symbol, not too. Keeping CONFIG_VT8500 as the
user-selectable option as I outlined in the example means that
existing .config files keep working, which is sometimes useful.
Arnd
^ permalink raw reply
* [PATCH RFC 7/7] cpsw: use the time stamping capabilities of the cpts
From: Richard Cochran @ 2012-10-11 20:27 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1349985570.git.richardcochran@gmail.com>
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
---
drivers/net/ethernet/ti/cpsw.c | 33 +++++++++++++++++++++++++++++++++
1 files changed, 33 insertions(+), 0 deletions(-)
diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index 5a7ed50..32a52ec 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -35,6 +35,7 @@
#include <linux/platform_data/cpsw.h>
#include "cpsw_ale.h"
+#include "cpts.h"
#include "davinci_cpdma.h"
#define CPSW_DEBUG (NETIF_MSG_HW | NETIF_MSG_WOL | \
@@ -238,6 +239,7 @@ struct cpsw_priv {
/* snapshot of IRQ numbers */
u32 irqs_table[4];
u32 num_irqs;
+ struct cpts cpts;
};
#define napi_to_priv(napi) container_of(napi, struct cpsw_priv, napi)
@@ -274,6 +276,7 @@ void cpsw_tx_handler(void *token, int len, int status)
if (unlikely(netif_queue_stopped(ndev)))
netif_start_queue(ndev);
+ cpts_tx_timestamp(&priv->cpts, skb);
priv->stats.tx_packets++;
priv->stats.tx_bytes += len;
dev_kfree_skb_any(skb);
@@ -294,6 +297,7 @@ void cpsw_rx_handler(void *token, int len, int status)
}
if (likely(status >= 0)) {
skb_put(skb, len);
+ cpts_rx_timestamp(&priv->cpts, skb);
skb->protocol = eth_type_trans(skb, ndev);
netif_receive_skb(skb);
priv->stats.rx_bytes += len;
@@ -612,6 +616,11 @@ static netdev_tx_t cpsw_ndo_start_xmit(struct sk_buff *skb,
return NETDEV_TX_OK;
}
+ if (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP && priv->cpts.tx_enable)
+ skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
+
+ skb_tx_timestamp(skb);
+
ret = cpdma_chan_submit(priv->txch, skb, skb->data,
skb->len, GFP_KERNEL);
if (unlikely(ret != 0)) {
@@ -649,6 +658,21 @@ static void cpsw_ndo_change_rx_flags(struct net_device *ndev, int flags)
dev_err(&ndev->dev, "multicast traffic cannot be filtered!\n");
}
+static int cpsw_ndo_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
+{
+ struct cpsw_priv *priv = netdev_priv(dev);
+
+ if (!netif_running(dev))
+ return -EINVAL;
+
+ switch (cmd) {
+ case SIOCSHWTSTAMP:
+ return cpts_hwtstamp_ioctl(&priv->cpts, req);
+ }
+
+ return -ENOTSUPP;
+}
+
static void cpsw_ndo_tx_timeout(struct net_device *ndev)
{
struct cpsw_priv *priv = netdev_priv(ndev);
@@ -689,6 +713,7 @@ static const struct net_device_ops cpsw_netdev_ops = {
.ndo_stop = cpsw_ndo_stop,
.ndo_start_xmit = cpsw_ndo_start_xmit,
.ndo_change_rx_flags = cpsw_ndo_change_rx_flags,
+ .ndo_do_ioctl = cpsw_ndo_ioctl,
.ndo_validate_addr = eth_validate_addr,
.ndo_change_mtu = eth_change_mtu,
.ndo_tx_timeout = cpsw_ndo_tx_timeout,
@@ -978,6 +1003,8 @@ static int __devinit cpsw_probe(struct platform_device *pdev)
priv->regs = regs;
priv->host_port = data->host_port_num;
priv->host_port_regs = regs + data->host_port_reg_ofs;
+ priv->cpts.reg = regs + data->cpts_reg_ofs;
+ priv->cpts.tsp = regs + priv->data.slave_data[0].slave_reg_ofs;
priv->cpsw_ss_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
if (!priv->cpsw_ss_res) {
@@ -1099,6 +1126,11 @@ static int __devinit cpsw_probe(struct platform_device *pdev)
goto clean_irq_ret;
}
+ if (cpts_register(&pdev->dev, &priv->cpts))
+ dev_err(priv->dev, "error registering cpts device\n");
+
+ __raw_writel(ETH_P_1588, &priv->regs->ts_ltype);
+
cpsw_notice(priv, probe, "initialized device (regs %x, irq %d)\n",
priv->cpsw_res->start, ndev->irq);
@@ -1138,6 +1170,7 @@ static int __devexit cpsw_remove(struct platform_device *pdev)
pr_info("removing device");
platform_set_drvdata(pdev, NULL);
+ cpts_unregister(&priv->cpts);
free_irq(ndev->irq, priv);
cpsw_ale_destroy(priv->ale);
cpdma_chan_destroy(priv->txch);
--
1.7.2.5
^ permalink raw reply related
* [PATCH RFC 6/7] cpsw: add a DT field for the cpts offset
From: Richard Cochran @ 2012-10-11 20:27 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1349985570.git.richardcochran@gmail.com>
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
---
Documentation/devicetree/bindings/net/cpsw.txt | 3 +++
drivers/net/ethernet/ti/cpsw.c | 7 +++++++
include/linux/platform_data/cpsw.h | 1 +
3 files changed, 11 insertions(+), 0 deletions(-)
diff --git a/Documentation/devicetree/bindings/net/cpsw.txt b/Documentation/devicetree/bindings/net/cpsw.txt
index 3af47b7..dba014f 100644
--- a/Documentation/devicetree/bindings/net/cpsw.txt
+++ b/Documentation/devicetree/bindings/net/cpsw.txt
@@ -16,6 +16,7 @@ Required properties:
- ale_entries : Specifies No of entries ALE can hold
- host_port_reg_ofs : Specifies host port register offset
- hw_stats_reg_ofs : Specifies hardware statistics register offset
+- cpts_reg_ofs : Specifies the offset of the CPTS registers
- bd_ram_ofs : Specifies internal desciptor RAM offset
- bd_ram_size : Specifies internal descriptor RAM size
- rx_descs : Specifies number of Rx descriptors
@@ -52,6 +53,7 @@ Examples:
ale_entries = <1024>;
host_port_reg_ofs = <0x108>;
hw_stats_reg_ofs = <0x900>;
+ cpts_reg_ofs = <0xc00>;
bd_ram_ofs = <0x2000>;
bd_ram_size = <0x2000>;
no_bd_ram = <0>;
@@ -86,6 +88,7 @@ Examples:
ale_entries = <1024>;
host_port_reg_ofs = <0x108>;
hw_stats_reg_ofs = <0x900>;
+ cpts_reg_ofs = <0xc00>;
bd_ram_ofs = <0x2000>;
bd_ram_size = <0x2000>;
no_bd_ram = <0>;
diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index 600699e..5a7ed50 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -819,6 +819,13 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
}
data->hw_stats_reg_ofs = prop;
+ if (of_property_read_u32(node, "cpts_reg_ofs", &prop)) {
+ pr_err("Missing cpts_reg_ofs property in the DT.\n");
+ ret = -EINVAL;
+ goto error_ret;
+ }
+ data->cpts_reg_ofs = prop;
+
if (of_property_read_u32(node, "bd_ram_ofs", &prop)) {
pr_err("Missing bd_ram_ofs property in the DT.\n");
ret = -EINVAL;
diff --git a/include/linux/platform_data/cpsw.h b/include/linux/platform_data/cpsw.h
index c4e23d0..a052b1d 100644
--- a/include/linux/platform_data/cpsw.h
+++ b/include/linux/platform_data/cpsw.h
@@ -41,6 +41,7 @@ struct cpsw_platform_data {
u32 host_port_num; /* The port number for the host port */
u32 hw_stats_reg_ofs; /* cpsw hardware statistics counters */
+ u32 cpts_reg_ofs; /* cpts registers */
u32 bd_ram_ofs; /* embedded buffer descriptor RAM offset*/
u32 bd_ram_size; /*buffer descriptor ram size */
--
1.7.2.5
^ permalink raw reply related
* [PATCH RFC 5/7] cpts: introduce time stamping code and a PTP hardware clock.
From: Richard Cochran @ 2012-10-11 20:27 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1349985570.git.richardcochran@gmail.com>
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
---
drivers/net/ethernet/ti/Kconfig | 8 +
drivers/net/ethernet/ti/Makefile | 2 +-
drivers/net/ethernet/ti/cpts.c | 469 ++++++++++++++++++++++++++++++++++++++
drivers/net/ethernet/ti/cpts.h | 148 ++++++++++++
4 files changed, 626 insertions(+), 1 deletions(-)
create mode 100644 drivers/net/ethernet/ti/cpts.c
create mode 100644 drivers/net/ethernet/ti/cpts.h
diff --git a/drivers/net/ethernet/ti/Kconfig b/drivers/net/ethernet/ti/Kconfig
index b26cbda..cbc3905 100644
--- a/drivers/net/ethernet/ti/Kconfig
+++ b/drivers/net/ethernet/ti/Kconfig
@@ -60,6 +60,14 @@ config TI_CPSW
To compile this driver as a module, choose M here: the module
will be called cpsw.
+config TI_CPTS
+ boolean "TI Common Platform Time Sync (CPTS) Support"
+ depends on TI_CPSW && PTP_1588_CLOCK && !(TI_CPSW=y && PTP_1588_CLOCK=m)
+ ---help---
+ This driver supports the Common Platform Time Sync unit of
+ the CPSW Ethernet Switch. The unit can time stamp PTP UDP/IPv4
+ and Layer 2 packets, and the driver offers a PTP Hardware Clock.
+
config TLAN
tristate "TI ThunderLAN support"
depends on (PCI || EISA)
diff --git a/drivers/net/ethernet/ti/Makefile b/drivers/net/ethernet/ti/Makefile
index 91bd8bb..c65148e 100644
--- a/drivers/net/ethernet/ti/Makefile
+++ b/drivers/net/ethernet/ti/Makefile
@@ -8,4 +8,4 @@ obj-$(CONFIG_TI_DAVINCI_EMAC) += davinci_emac.o
obj-$(CONFIG_TI_DAVINCI_MDIO) += davinci_mdio.o
obj-$(CONFIG_TI_DAVINCI_CPDMA) += davinci_cpdma.o
obj-$(CONFIG_TI_CPSW) += ti_cpsw.o
-ti_cpsw-y := cpsw_ale.o cpsw.o
+ti_cpsw-y := cpsw_ale.o cpsw.o cpts.o
diff --git a/drivers/net/ethernet/ti/cpts.c b/drivers/net/ethernet/ti/cpts.c
new file mode 100644
index 0000000..b7547db
--- /dev/null
+++ b/drivers/net/ethernet/ti/cpts.c
@@ -0,0 +1,469 @@
+/*
+ * TI Common Platform Time Sync
+ *
+ * Copyright (C) 2012 Richard Cochran <richardcochran@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include <linux/err.h>
+#include <linux/if.h>
+#include <linux/hrtimer.h>
+#include <linux/module.h>
+#include <linux/net_tstamp.h>
+#include <linux/ptp_classify.h>
+#include <linux/time.h>
+#include <linux/uaccess.h>
+#include <linux/workqueue.h>
+
+#include <plat/clock.h>
+
+#include "cpts.h"
+
+#ifdef CONFIG_TI_CPTS
+
+static struct sock_filter ptp_filter[] = {
+ PTP_FILTER
+};
+
+#define cpts_read32(c, r) __raw_readl(&c->reg->r)
+#define cpts_write32(c, v, r) __raw_writel(v, &c->reg->r)
+#define port_read32(c, r) __raw_readl(&c->tsp->r)
+#define port_write32(c, v, r) __raw_writel(v, &c->tsp->r)
+
+static int event_expired(struct cpts_event *event)
+{
+ return time_after(jiffies, event->tmo);
+}
+
+static int event_type(struct cpts_event *event)
+{
+ return (event->high >> EVENT_TYPE_SHIFT) & EVENT_TYPE_MASK;
+}
+
+static int cpts_fifo_pop(struct cpts *cpts, u32 *high, u32 *low)
+{
+ u32 r = cpts_read32(cpts, intstat_raw);
+
+ if (r & TS_PEND_RAW) {
+ *high = cpts_read32(cpts, event_high);
+ *low = cpts_read32(cpts, event_low);
+ cpts_write32(cpts, EVENT_POP, event_pop);
+ return 0;
+ }
+ return -1;
+}
+
+/*
+ * Returns zero if matching event type was found.
+ */
+static int cpts_fifo_read(struct cpts *cpts, int match)
+{
+ int i, type = -1;
+ u32 hi, lo;
+ struct cpts_event *event;
+
+ for (i = 0; i < CPTS_FIFO_DEPTH; i++) {
+ if (cpts_fifo_pop(cpts, &hi, &lo))
+ break;
+ if (list_empty(&cpts->pool)) {
+ pr_err("cpts: event pool is empty\n");
+ return -1;
+ }
+ event = list_first_entry(&cpts->pool, struct cpts_event, list);
+ event->tmo = jiffies + 2;
+ event->high = hi;
+ event->low = lo;
+ type = event_type(event);
+ switch (type) {
+ case CPTS_EV_PUSH:
+ case CPTS_EV_RX:
+ case CPTS_EV_TX:
+ list_del_init(&event->list);
+ list_add_tail(&event->list, &cpts->events);
+ break;
+ case CPTS_EV_ROLL:
+ case CPTS_EV_HALF:
+ case CPTS_EV_HW:
+ break;
+ default:
+ pr_err("cpts: unkown event type\n");
+ break;
+ }
+ if (type == match)
+ break;
+ }
+ return type == match ? 0 : -1;
+}
+
+static cycle_t cpts_systim_read(const struct cyclecounter *cc)
+{
+ u64 val = 0;
+ struct cpts_event *event;
+ struct list_head *this, *next;
+ struct cpts *cpts = container_of(cc, struct cpts, cc);
+
+ cpts_write32(cpts, TS_PUSH, ts_push);
+ if (cpts_fifo_read(cpts, CPTS_EV_PUSH))
+ pr_err("cpts: unable to obtain a time stamp\n");
+
+ list_for_each_safe(this, next, &cpts->events) {
+ event = list_entry(this, struct cpts_event, list);
+ if (event_type(event) == CPTS_EV_PUSH) {
+ list_del_init(&event->list);
+ list_add(&event->list, &cpts->pool);
+ val = event->low;
+ break;
+ }
+ }
+
+ return val;
+}
+
+/* PTP clock operations */
+
+static int cpts_ptp_adjfreq(struct ptp_clock_info *ptp, s32 ppb)
+{
+ return 0;
+}
+
+static int cpts_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
+{
+ s64 now;
+ unsigned long flags;
+ struct cpts *cpts = container_of(ptp, struct cpts, info);
+
+ spin_lock_irqsave(&cpts->lock, flags);
+ now = timecounter_read(&cpts->tc);
+ now += delta;
+ timecounter_init(&cpts->tc, &cpts->cc, now);
+ spin_unlock_irqrestore(&cpts->lock, flags);
+
+ return 0;
+}
+
+static int cpts_ptp_gettime(struct ptp_clock_info *ptp, struct timespec *ts)
+{
+ u64 ns;
+ u32 remainder;
+ unsigned long flags;
+ struct cpts *cpts = container_of(ptp, struct cpts, info);
+
+ spin_lock_irqsave(&cpts->lock, flags);
+ ns = timecounter_read(&cpts->tc);
+ spin_unlock_irqrestore(&cpts->lock, flags);
+
+ ts->tv_sec = div_u64_rem(ns, 1000000000, &remainder);
+ ts->tv_nsec = remainder;
+
+ return 0;
+}
+
+static int cpts_ptp_settime(struct ptp_clock_info *ptp,
+ const struct timespec *ts)
+{
+ u64 ns;
+ unsigned long flags;
+ struct cpts *cpts = container_of(ptp, struct cpts, info);
+
+ ns = ts->tv_sec * 1000000000ULL;
+ ns += ts->tv_nsec;
+
+ spin_lock_irqsave(&cpts->lock, flags);
+ timecounter_init(&cpts->tc, &cpts->cc, ns);
+ spin_unlock_irqrestore(&cpts->lock, flags);
+
+ return 0;
+}
+
+static int cpts_ptp_enable(struct ptp_clock_info *ptp,
+ struct ptp_clock_request *rq, int on)
+{
+ return -EOPNOTSUPP;
+}
+
+static struct ptp_clock_info cpts_info = {
+ .owner = THIS_MODULE,
+ .name = "CTPS timer",
+ .max_adj = 1,
+ .n_ext_ts = 0,
+ .pps = 0,
+ .adjfreq = cpts_ptp_adjfreq,
+ .adjtime = cpts_ptp_adjtime,
+ .gettime = cpts_ptp_gettime,
+ .settime = cpts_ptp_settime,
+ .enable = cpts_ptp_enable,
+};
+
+static void cpts_overflow_check(struct work_struct *work)
+{
+ struct timespec ts;
+ struct cpts *cpts = container_of(work, struct cpts, overflow_work.work);
+
+ cpts_write32(cpts, CPTS_EN, control);
+ cpts_write32(cpts, TS_PEND_EN, int_enable);
+ cpts_ptp_gettime(&cpts->info, &ts);
+ pr_debug("cpts overflow check at %ld.%09lu\n", ts.tv_sec, ts.tv_nsec);
+ schedule_delayed_work(&cpts->overflow_work, CPTS_OVERFLOW_PERIOD);
+}
+
+#define CPTS_REF_CLOCK_NAME "cpsw_cpts_rft_clk"
+
+static void cpts_clk_init(struct cpts *cpts)
+{
+ cpts->refclk = clk_get(NULL, CPTS_REF_CLOCK_NAME);
+ if (IS_ERR(cpts->refclk)) {
+ pr_err("Failed to clk_get %s\n", CPTS_REF_CLOCK_NAME);
+ cpts->refclk = NULL;
+ return;
+ }
+ clk_enable(cpts->refclk);
+ cpts->freq = cpts->refclk->recalc(cpts->refclk);
+ pr_err("freq = %lu\n", cpts->freq);
+}
+
+static void cpts_clk_release(struct cpts *cpts)
+{
+ clk_disable(cpts->refclk);
+ clk_put(cpts->refclk);
+}
+
+static int cpts_match(struct sk_buff *skb, unsigned int ptp_class,
+ u16 ts_seqid, u8 ts_msgtype)
+{
+ u16 *seqid;
+ unsigned int offset;
+ u8 *msgtype, *data = skb->data;
+
+ switch (ptp_class) {
+ case PTP_CLASS_V1_IPV4:
+ case PTP_CLASS_V2_IPV4:
+ offset = ETH_HLEN + IPV4_HLEN(data) + UDP_HLEN;
+ break;
+ case PTP_CLASS_V1_IPV6:
+ case PTP_CLASS_V2_IPV6:
+ offset = OFF_PTP6;
+ break;
+ case PTP_CLASS_V2_L2:
+ offset = ETH_HLEN;
+ break;
+ case PTP_CLASS_V2_VLAN:
+ offset = ETH_HLEN + VLAN_HLEN;
+ break;
+ default:
+ return 0;
+ }
+
+ if (skb->len + ETH_HLEN < offset + OFF_PTP_SEQUENCE_ID + sizeof(*seqid))
+ return 0;
+
+ if (unlikely(ptp_class & PTP_CLASS_V1))
+ msgtype = data + offset + OFF_PTP_CONTROL;
+ else
+ msgtype = data + offset;
+
+ seqid = (u16 *)(data + offset + OFF_PTP_SEQUENCE_ID);
+
+ return (ts_msgtype == (*msgtype & 0xf) && ts_seqid == ntohs(*seqid));
+}
+
+static u64 cpts_find_ts(struct cpts *cpts, struct sk_buff *skb, int ev_type)
+{
+ u64 ns = 0;
+ struct cpts_event *event;
+ struct list_head *this, *next;
+ unsigned int class = sk_run_filter(skb, ptp_filter);
+ unsigned long flags;
+ u16 seqid;
+ u8 mtype;
+
+ if (class == PTP_CLASS_NONE)
+ return 0;
+
+ spin_lock_irqsave(&cpts->lock, flags);
+ cpts_fifo_read(cpts, CPTS_EV_PUSH);
+ list_for_each_safe(this, next, &cpts->events) {
+ event = list_entry(this, struct cpts_event, list);
+ if (event_expired(event)) {
+ list_del_init(&event->list);
+ list_add(&event->list, &cpts->pool);
+ continue;
+ }
+ mtype = (event->high >> MESSAGE_TYPE_SHIFT) & MESSAGE_TYPE_MASK;
+ seqid = (event->high >> SEQUENCE_ID_SHIFT) & SEQUENCE_ID_MASK;
+ if (ev_type == event_type(event) &&
+ cpts_match(skb, class, seqid, mtype)) {
+ ns = timecounter_cyc2time(&cpts->tc, event->low);
+ list_del_init(&event->list);
+ list_add(&event->list, &cpts->pool);
+ break;
+ }
+ }
+ spin_unlock_irqrestore(&cpts->lock, flags);
+
+ return ns;
+}
+
+void cpts_rx_timestamp(struct cpts *cpts, struct sk_buff *skb)
+{
+ u64 ns;
+ struct skb_shared_hwtstamps *ssh;
+
+ if (!cpts->rx_enable)
+ return;
+ ns = cpts_find_ts(cpts, skb, CPTS_EV_RX);
+ if (!ns)
+ return;
+ ssh = skb_hwtstamps(skb);
+ memset(ssh, 0, sizeof(*ssh));
+ ssh->hwtstamp = ns_to_ktime(ns);
+}
+
+void cpts_tx_timestamp(struct cpts *cpts, struct sk_buff *skb)
+{
+ u64 ns;
+ struct skb_shared_hwtstamps ssh;
+
+ if (!(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS))
+ return;
+ ns = cpts_find_ts(cpts, skb, CPTS_EV_TX);
+ if (!ns)
+ return;
+ memset(&ssh, 0, sizeof(ssh));
+ ssh.hwtstamp = ns_to_ktime(ns);
+ skb_tstamp_tx(skb, &ssh);
+}
+
+#endif /*CONFIG_TI_CPTS*/
+
+int cpts_hwtstamp_ioctl(struct cpts *cpts, struct ifreq *ifr)
+{
+#ifdef CONFIG_TI_CPTS
+ struct hwtstamp_config cfg;
+ u32 ctrl, mtype;
+
+ if (copy_from_user(&cfg, ifr->ifr_data, sizeof(cfg)))
+ return -EFAULT;
+
+ /* reserved for future extensions */
+ if (cfg.flags)
+ return -EINVAL;
+
+ ctrl = port_read32(cpts, control);
+ ctrl &= ~CTRL_ALL_TS_MASK;
+
+ switch (cfg.tx_type) {
+ case HWTSTAMP_TX_OFF:
+ cpts->tx_enable = 0;
+ break;
+ case HWTSTAMP_TX_ON:
+ cpts->tx_enable = 1;
+ ctrl |= CTRL_TX_TS_BITS;
+ break;
+ default:
+ return -ERANGE;
+ }
+
+ switch (cfg.rx_filter) {
+ case HWTSTAMP_FILTER_NONE:
+ cpts->rx_enable = 0;
+ break;
+ case HWTSTAMP_FILTER_ALL:
+ case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
+ case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
+ case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
+ return -ERANGE;
+ case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
+ case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
+ case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
+ case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
+ case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
+ case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
+ case HWTSTAMP_FILTER_PTP_V2_EVENT:
+ case HWTSTAMP_FILTER_PTP_V2_SYNC:
+ case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
+ cpts->rx_enable = 1;
+ cfg.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;
+ ctrl |= CTRL_RX_TS_BITS;
+ break;
+ default:
+ return -ERANGE;
+ }
+
+ mtype = (30 << TS_SEQ_ID_OFFSET_SHIFT) | EVENT_MSG_BITS;
+ port_write32(cpts, mtype, ts_seq_mtype);
+ port_write32(cpts, ctrl, control);
+
+ return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0;
+#else
+ return -EOPNOTSUPP;
+#endif
+}
+
+int cpts_register(struct device *dev, struct cpts *cpts)
+{
+#ifdef CONFIG_TI_CPTS
+ int err, i;
+ unsigned long flags;
+
+ if (ptp_filter_init(ptp_filter, ARRAY_SIZE(ptp_filter))) {
+ pr_err("cpts: bad ptp filter\n");
+ return -EINVAL;
+ }
+ cpts->info = cpts_info;
+ cpts->clock = ptp_clock_register(&cpts->info, dev);
+ if (IS_ERR(cpts->clock)) {
+ err = PTR_ERR(cpts->clock);
+ cpts->clock = NULL;
+ return err;
+ }
+ spin_lock_init(&cpts->lock);
+
+ cpts->cc.read = cpts_systim_read;
+ cpts->cc.mask = CLOCKSOURCE_MASK(32);
+ cpts->cc.mult = 4;
+ cpts->cc.shift = 0;
+
+ INIT_LIST_HEAD(&cpts->events);
+ INIT_LIST_HEAD(&cpts->pool);
+ for (i = 0; i < CPTS_MAX_EVENTS; i++)
+ list_add(&cpts->pool_data[i].list, &cpts->pool);
+
+ cpts_clk_init(cpts);
+ cpts_write32(cpts, CPTS_EN, control);
+ cpts_write32(cpts, TS_PEND_EN, int_enable);
+
+ spin_lock_irqsave(&cpts->lock, flags);
+ timecounter_init(&cpts->tc, &cpts->cc, ktime_to_ns(ktime_get_real()));
+ spin_unlock_irqrestore(&cpts->lock, flags);
+
+ INIT_DELAYED_WORK(&cpts->overflow_work, cpts_overflow_check);
+ schedule_delayed_work(&cpts->overflow_work, CPTS_OVERFLOW_PERIOD);
+
+ cpts->phc_index = ptp_clock_index(cpts->clock);
+#endif
+ return 0;
+}
+
+void cpts_unregister(struct cpts *cpts)
+{
+#ifdef CONFIG_TI_CPTS
+ if (cpts->clock) {
+ ptp_clock_unregister(cpts->clock);
+ cancel_delayed_work_sync(&cpts->overflow_work);
+ }
+ if (cpts->refclk)
+ cpts_clk_release(cpts);
+#endif
+}
diff --git a/drivers/net/ethernet/ti/cpts.h b/drivers/net/ethernet/ti/cpts.h
new file mode 100644
index 0000000..86e45ff
--- /dev/null
+++ b/drivers/net/ethernet/ti/cpts.h
@@ -0,0 +1,148 @@
+/*
+ * TI Common Platform Time Sync
+ *
+ * Copyright (C) 2012 Richard Cochran <richardcochran@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#ifndef _TI_CPTS_H_
+#define _TI_CPTS_H_
+
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/clocksource.h>
+#include <linux/device.h>
+#include <linux/list.h>
+#include <linux/ptp_clock_kernel.h>
+#include <linux/skbuff.h>
+
+#include "cpsw_reg.h"
+
+struct cpsw_cpts {
+ u32 idver; /* Identification and version */
+ u32 control; /* Time sync control */
+ u32 res1;
+ u32 ts_push; /* Time stamp event push */
+ u32 ts_load_val; /* Time stamp load value */
+ u32 ts_load_en; /* Time stamp load enable */
+ u32 res2[2];
+ u32 intstat_raw; /* Time sync interrupt status raw */
+ u32 intstat_masked; /* Time sync interrupt status masked */
+ u32 int_enable; /* Time sync interrupt enable */
+ u32 res3;
+ u32 event_pop; /* Event interrupt pop */
+ u32 event_low; /* 32 Bit Event Time Stamp */
+ u32 event_high; /* Event Type Fields */
+};
+
+/* Bit definitions for the IDVER register */
+#define TX_IDENT_SHIFT (16) /* TX Identification Value */
+#define TX_IDENT_MASK (0xffff)
+#define RTL_VER_SHIFT (11) /* RTL Version Value */
+#define RTL_VER_MASK (0x1f)
+#define MAJOR_VER_SHIFT (8) /* Major Version Value */
+#define MAJOR_VER_MASK (0x7)
+#define MINOR_VER_SHIFT (0) /* Minor Version Value */
+#define MINOR_VER_MASK (0xff)
+
+/* Bit definitions for the CONTROL register */
+#define HW4_TS_PUSH_EN (1<<11) /* Hardware push 4 enable */
+#define HW3_TS_PUSH_EN (1<<10) /* Hardware push 3 enable */
+#define HW2_TS_PUSH_EN (1<<9) /* Hardware push 2 enable */
+#define HW1_TS_PUSH_EN (1<<8) /* Hardware push 1 enable */
+#define INT_TEST (1<<1) /* Interrupt Test */
+#define CPTS_EN (1<<0) /* Time Sync Enable */
+
+/*
+ * Definitions for the single bit resisters:
+ * TS_PUSH TS_LOAD_EN INTSTAT_RAW INTSTAT_MASKED INT_ENABLE EVENT_POP
+ */
+#define TS_PUSH (1<<0) /* Time stamp event push */
+#define TS_LOAD_EN (1<<0) /* Time Stamp Load */
+#define TS_PEND_RAW (1<<0) /* int read (before enable) */
+#define TS_PEND (1<<0) /* masked interrupt read (after enable) */
+#define TS_PEND_EN (1<<0) /* masked interrupt enable */
+#define EVENT_POP (1<<0) /* writing discards one event */
+
+/* Bit definitions for the EVENT_HIGH register */
+#define PORT_NUMBER_SHIFT (24) /* Indicates Ethernet port or HW pin */
+#define PORT_NUMBER_MASK (0x1f)
+#define EVENT_TYPE_SHIFT (20) /* Time sync event type */
+#define EVENT_TYPE_MASK (0xf)
+#define MESSAGE_TYPE_SHIFT (16) /* PTP message type */
+#define MESSAGE_TYPE_MASK (0xf)
+#define SEQUENCE_ID_SHIFT (0) /* PTP message sequence ID */
+#define SEQUENCE_ID_MASK (0xffff)
+
+enum {
+ CPTS_EV_PUSH, /* Time Stamp Push Event */
+ CPTS_EV_ROLL, /* Time Stamp Rollover Event */
+ CPTS_EV_HALF, /* Time Stamp Half Rollover Event */
+ CPTS_EV_HW, /* Hardware Time Stamp Push Event */
+ CPTS_EV_RX, /* Ethernet Receive Event */
+ CPTS_EV_TX, /* Ethernet Transmit Event */
+};
+
+/* This covers any input clock up to about 500 MHz. */
+#define CPTS_OVERFLOW_PERIOD (HZ * 8)
+
+#define CPTS_FIFO_DEPTH 16
+#define CPTS_MAX_EVENTS 32
+
+struct cpts_event {
+ struct list_head list;
+ unsigned long tmo;
+ u32 high;
+ u32 low;
+};
+
+struct cpts {
+ struct cpsw_cpts __iomem *reg;
+ struct cpsw_port __iomem *tsp;
+ int tx_enable;
+#ifdef CONFIG_TI_CPTS
+ int rx_enable;
+ struct ptp_clock_info info;
+ struct ptp_clock *clock;
+ spinlock_t lock; /* protects time registers */
+ struct cyclecounter cc;
+ struct timecounter tc;
+ struct delayed_work overflow_work;
+ int phc_index;
+ struct clk *refclk;
+ unsigned long freq;
+ struct list_head events;
+ struct list_head pool;
+ struct cpts_event pool_data[CPTS_MAX_EVENTS];
+#endif
+};
+
+#ifdef CONFIG_TI_CPTS
+extern void cpts_rx_timestamp(struct cpts *cpts, struct sk_buff *skb);
+extern void cpts_tx_timestamp(struct cpts *cpts, struct sk_buff *skb);
+#else
+static inline void cpts_rx_timestamp(struct cpts *cpts, struct sk_buff *skb)
+{
+}
+static inline void cpts_tx_timestamp(struct cpts *cpts, struct sk_buff *skb)
+{
+}
+#endif
+
+extern int cpts_hwtstamp_ioctl(struct cpts *cpts, struct ifreq *ifr);
+extern int cpts_register(struct device *dev, struct cpts *cpts);
+extern void cpts_unregister(struct cpts *cpts);
+
+#endif
--
1.7.2.5
^ permalink raw reply related
* [PATCH RFC 4/7] cpsw: add a common header file for regsiter declarations
From: Richard Cochran @ 2012-10-11 20:27 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1349985570.git.richardcochran@gmail.com>
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
---
drivers/net/ethernet/ti/cpsw_reg.h | 81 ++++++++++++++++++++++++++++++++++++
1 files changed, 81 insertions(+), 0 deletions(-)
create mode 100644 drivers/net/ethernet/ti/cpsw_reg.h
diff --git a/drivers/net/ethernet/ti/cpsw_reg.h b/drivers/net/ethernet/ti/cpsw_reg.h
new file mode 100644
index 0000000..88fb15f
--- /dev/null
+++ b/drivers/net/ethernet/ti/cpsw_reg.h
@@ -0,0 +1,81 @@
+/*
+ * Common CPSW register declarations
+ *
+ * Copyright (C) 2012 Richard Cochran <richardcochran@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#ifndef _TI_CPSW_REG_H_
+#define _TI_CPSW_REG_H_
+
+struct cpsw_port {
+ u32 control; /* Control Register */
+ u32 res1;
+ u32 max_blks; /* Maximum FIFO Blocks */
+ u32 blk_cnt; /* FIFO Block Usage Count (Read Only) */
+ u32 tx_in_ctl; /* Transmit FIFO Control */
+ u32 port_vlan; /* VLAN Register */
+ u32 tx_pri_map; /* Tx Header Priority to Switch Pri Map */
+ u32 ts_seq_mtype; /* Time Sync Seq ID Offset and Msg Type */
+ u32 sa_lo; /* CPGMAC_SL Source Address Low */
+ u32 sa_hi; /* CPGMAC_SL Source Address High */
+ u32 send_percent; /* Transmit Queue Send Percentages */
+ u32 res2;
+ u32 rx_dscp_pri_map0; /* Rx DSCP Priority to Rx Packet Mapping */
+ u32 rx_dscp_pri_map1; /* Rx DSCP Priority to Rx Packet Mapping */
+ u32 rx_dscp_pri_map2; /* Rx DSCP Priority to Rx Packet Mapping */
+ u32 rx_dscp_pri_map3; /* Rx DSCP Priority to Rx Packet Mapping */
+ u32 rx_dscp_pri_map4; /* Rx DSCP Priority to Rx Packet Mapping */
+ u32 rx_dscp_pri_map5; /* Rx DSCP Priority to Rx Packet Mapping */
+ u32 rx_dscp_pri_map6; /* Rx DSCP Priority to Rx Packet Mapping */
+ u32 rx_dscp_pri_map7; /* Rx DSCP Priority to Rx Packet Mapping */
+};
+
+/* Bit definitions for the CONTROL register */
+#define PASS_PRI_TAGGED (1<<24) /* Pass Priority Tagged */
+#define VLAN_LTYPE2_EN (1<<21) /* VLAN LTYPE 2 enable */
+#define VLAN_LTYPE1_EN (1<<20) /* VLAN LTYPE 1 enable */
+#define DSCP_PRI_EN (1<<16) /* DSCP Priority Enable */
+#define TS_320 (1<<14) /* Time Sync Dest Port 320 enable */
+#define TS_319 (1<<13) /* Time Sync Dest Port 319 enable */
+#define TS_132 (1<<12) /* Time Sync Dest IP Addr 132 enable */
+#define TS_131 (1<<11) /* Time Sync Dest IP Addr 131 enable */
+#define TS_130 (1<<10) /* Time Sync Dest IP Addr 130 enable */
+#define TS_129 (1<<9) /* Time Sync Dest IP Addr 129 enable */
+#define TS_BIT8 (1<<8) /* ts_ttl_nonzero? */
+#define TS_ANNEX_D_EN (1<<4) /* Time Sync Annex D enable */
+#define TS_LTYPE2_EN (1<<3) /* Time Sync LTYPE 2 enable */
+#define TS_LTYPE1_EN (1<<2) /* Time Sync LTYPE 1 enable */
+#define TS_TX_EN (1<<1) /* Time Sync Transmit Enable */
+#define TS_RX_EN (1<<0) /* Time Sync Receive Enable */
+
+#define CTRL_TS_BITS \
+ (TS_320 | TS_319 | TS_132 | TS_131 | TS_130 | TS_129 | TS_BIT8 | \
+ TS_ANNEX_D_EN | TS_LTYPE2_EN | TS_LTYPE1_EN)
+
+#define CTRL_ALL_TS_MASK (CTRL_TS_BITS | TS_TX_EN | TS_RX_EN)
+#define CTRL_TX_TS_BITS (CTRL_TS_BITS | TS_TX_EN)
+#define CTRL_RX_TS_BITS (CTRL_TS_BITS | TS_RX_EN)
+
+/* Bit definitions for the TS_SEQ_MTYPE register */
+#define TS_SEQ_ID_OFFSET_SHIFT (16) /* Time Sync Sequence ID Offset */
+#define TS_SEQ_ID_OFFSET_MASK (0x3f)
+#define TS_MSG_TYPE_EN_SHIFT (0) /* Time Sync Message Type Enable */
+#define TS_MSG_TYPE_EN_MASK (0xffff)
+
+/* The PTP event messages - Sync, Delay_Req, Pdelay_Req, and Pdelay_Resp. */
+#define EVENT_MSG_BITS ((1<<0) | (1<<1) | (1<<2) | (1<<3))
+
+#endif
--
1.7.2.5
^ permalink raw reply related
* [PATCH RFC 3/7] cpsw: correct the CPSW_PORT register bank declaration
From: Richard Cochran @ 2012-10-11 20:27 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1349985570.git.richardcochran@gmail.com>
This commit corrects and expands the slave port register bank
according to TI's Technical Reference Manual.
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
---
Documentation/devicetree/bindings/net/cpsw.txt | 8 ++++----
drivers/net/ethernet/ti/cpsw.c | 14 +++++++++++++-
2 files changed, 17 insertions(+), 5 deletions(-)
diff --git a/Documentation/devicetree/bindings/net/cpsw.txt b/Documentation/devicetree/bindings/net/cpsw.txt
index dcaabe9..3af47b7 100644
--- a/Documentation/devicetree/bindings/net/cpsw.txt
+++ b/Documentation/devicetree/bindings/net/cpsw.txt
@@ -59,14 +59,14 @@ Examples:
mac_control = <0x20>;
slaves = <2>;
cpsw_emac0: slave at 0 {
- slave_reg_ofs = <0x208>;
+ slave_reg_ofs = <0x200>;
sliver_reg_ofs = <0xd80>;
phy_id = "davinci_mdio.16:00";
/* Filled in by U-Boot */
mac-address = [ 00 00 00 00 00 00 ];
};
cpsw_emac1: slave at 1 {
- slave_reg_ofs = <0x308>;
+ slave_reg_ofs = <0x300>;
sliver_reg_ofs = <0xdc0>;
phy_id = "davinci_mdio.16:01";
/* Filled in by U-Boot */
@@ -93,14 +93,14 @@ Examples:
mac_control = <0x20>;
slaves = <2>;
cpsw_emac0: slave at 0 {
- slave_reg_ofs = <0x208>;
+ slave_reg_ofs = <0x200>;
sliver_reg_ofs = <0xd80>;
phy_id = "davinci_mdio.16:00";
/* Filled in by U-Boot */
mac-address = [ 00 00 00 00 00 00 ];
};
cpsw_emac1: slave at 1 {
- slave_reg_ofs = <0x308>;
+ slave_reg_ofs = <0x300>;
sliver_reg_ofs = <0xdc0>;
phy_id = "davinci_mdio.16:01";
/* Filled in by U-Boot */
diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index 24304e8..600699e 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -157,9 +157,11 @@ struct cpsw_ss_regs {
};
struct cpsw_slave_regs {
+ u32 control;
+ u32 res1;
u32 max_blks;
u32 blk_cnt;
- u32 flow_thresh;
+ u32 tx_in_ctl;
u32 port_vlan;
u32 tx_pri_map;
u32 ts_ctl;
@@ -167,6 +169,16 @@ struct cpsw_slave_regs {
u32 ts_vlan;
u32 sa_lo;
u32 sa_hi;
+ u32 send_percent;
+ u32 res2;
+ u32 rx_dscp_pri_map0;
+ u32 rx_dscp_pri_map1;
+ u32 rx_dscp_pri_map2;
+ u32 rx_dscp_pri_map3;
+ u32 rx_dscp_pri_map4;
+ u32 rx_dscp_pri_map5;
+ u32 rx_dscp_pri_map6;
+ u32 rx_dscp_pri_map7;
};
struct cpsw_host_regs {
--
1.7.2.5
^ permalink raw reply related
* [PATCH RFC 2/7] cpsw: add missing fields to the CPSW_SS register bank.
From: Richard Cochran @ 2012-10-11 20:27 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1349985570.git.richardcochran@gmail.com>
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
---
drivers/net/ethernet/ti/cpsw.c | 8 ++++++++
1 files changed, 8 insertions(+), 0 deletions(-)
diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index a996188..24304e8 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -146,6 +146,14 @@ struct cpsw_ss_regs {
u32 soft_reset;
u32 stat_port_en;
u32 ptype;
+ u32 soft_idle;
+ u32 thru_rate;
+ u32 gap_thresh;
+ u32 tx_start_wds;
+ u32 flow_control;
+ u32 vlan_ltype;
+ u32 ts_ltype;
+ u32 dlr_ltype;
};
struct cpsw_slave_regs {
--
1.7.2.5
^ permalink raw reply related
* [PATCH RFC 1/7] cpsw: rename register banks to match the reference manual
From: Richard Cochran @ 2012-10-11 20:27 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1349985570.git.richardcochran@gmail.com>
The code mixes up the CPSW_SS and the CPSW_WR register naming. This patch
changes the names to conform to the published Technical Reference Manual
from TI, in order to make working on the code less confusing.
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
---
drivers/net/ethernet/ti/cpsw.c | 18 +++++++++---------
1 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index df55e24..a996188 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -129,7 +129,7 @@ static int rx_packet_max = CPSW_MAX_PACKET_SIZE;
module_param(rx_packet_max, int, 0);
MODULE_PARM_DESC(rx_packet_max, "maximum receive packet size (bytes)");
-struct cpsw_ss_regs {
+struct cpsw_wr_regs {
u32 id_ver;
u32 soft_reset;
u32 control;
@@ -140,7 +140,7 @@ struct cpsw_ss_regs {
u32 misc_en;
};
-struct cpsw_regs {
+struct cpsw_ss_regs {
u32 id_ver;
u32 control;
u32 soft_reset;
@@ -202,8 +202,8 @@ struct cpsw_priv {
struct napi_struct napi;
struct device *dev;
struct cpsw_platform_data data;
- struct cpsw_regs __iomem *regs;
- struct cpsw_ss_regs __iomem *ss_regs;
+ struct cpsw_ss_regs __iomem *regs;
+ struct cpsw_wr_regs __iomem *wr_regs;
struct cpsw_host_regs __iomem *host_port_regs;
u32 msg_enable;
struct net_device_stats stats;
@@ -230,8 +230,8 @@ struct cpsw_priv {
static void cpsw_intr_enable(struct cpsw_priv *priv)
{
- __raw_writel(0xFF, &priv->ss_regs->tx_en);
- __raw_writel(0xFF, &priv->ss_regs->rx_en);
+ __raw_writel(0xFF, &priv->wr_regs->tx_en);
+ __raw_writel(0xFF, &priv->wr_regs->rx_en);
cpdma_ctlr_int_ctrl(priv->dma, true);
return;
@@ -239,8 +239,8 @@ static void cpsw_intr_enable(struct cpsw_priv *priv)
static void cpsw_intr_disable(struct cpsw_priv *priv)
{
- __raw_writel(0, &priv->ss_regs->tx_en);
- __raw_writel(0, &priv->ss_regs->rx_en);
+ __raw_writel(0, &priv->wr_regs->tx_en);
+ __raw_writel(0, &priv->wr_regs->rx_en);
cpdma_ctlr_int_ctrl(priv->dma, false);
return;
@@ -972,7 +972,7 @@ static int __devinit cpsw_probe(struct platform_device *pdev)
dev_err(priv->dev, "unable to map i/o region\n");
goto clean_cpsw_ss_iores_ret;
}
- priv->ss_regs = regs;
+ priv->wr_regs = regs;
for_each_slave(priv, cpsw_slave_init, priv);
--
1.7.2.5
^ permalink raw reply related
* [PATCH RFC 0/7] support the cpts found on am335x devices
From: Richard Cochran @ 2012-10-11 20:27 UTC (permalink / raw)
To: linux-arm-kernel
This patch series, based on today's mainline master 12250d8, is a RFC
adding support for the Common Platform Time Sync (CPTS) found on the
popular BeagleBone. The code enables hardware time stamping and a PTP
Hardware Clock.
Due to DT problems with the most current CPSW driver, this work has
been compiled and booted, but not tested. However, I have tested work
similar to this, based on the AM335XPSP_04.06.00.08 branch in TI's
arago repo, and found it to work well.
There are two open issue with this driver, which will hopefully soon
be resolved.
1. ATM it is not possible to adjust the clock frequency. I heard a
rumor that the fractional multipliers on the am335x do not work
when changed, but I have not yet verified this myself. Even if it
turns out to be true, still the driver will be useful for 802.1AS
applications, since they will typically use a free running clock.
2. Time stamping only works on UDP packets. Although Layer 2 is
supposed to work according to the TRM, I have not yet figured out
how. The UDP only works when setting an undocumented bit, so maybe
someone from TI can fill me in on this.
Thanks,
Richard
Richard Cochran (7):
cpsw: rename register banks to match the reference manual
cpsw: add missing fields to the CPSW_SS register bank.
cpsw: correct the CPSW_PORT register bank declaration
cpsw: add a common header file for regsiter declarations
cpts: introduce time stamping code and a PTP hardware clock.
cpsw: add a DT field for the cpts offset
cpsw: use the time stamping capabilities of the cpts
Documentation/devicetree/bindings/net/cpsw.txt | 11 +-
drivers/net/ethernet/ti/Kconfig | 8 +
drivers/net/ethernet/ti/Makefile | 2 +-
drivers/net/ethernet/ti/cpsw.c | 80 ++++-
drivers/net/ethernet/ti/cpsw_reg.h | 81 ++++
drivers/net/ethernet/ti/cpts.c | 469 ++++++++++++++++++++++++
drivers/net/ethernet/ti/cpts.h | 148 ++++++++
include/linux/platform_data/cpsw.h | 1 +
8 files changed, 785 insertions(+), 15 deletions(-)
create mode 100644 drivers/net/ethernet/ti/cpsw_reg.h
create mode 100644 drivers/net/ethernet/ti/cpts.c
create mode 100644 drivers/net/ethernet/ti/cpts.h
--
1.7.2.5
^ permalink raw reply
* [PATCH] Boottime: A tool for automatic measurement of kernel/bootloader boot time
From: Nishanth Menon @ 2012-10-11 20:17 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1349966545-19340-1-git-send-email-lee.jones@linaro.org>
On 15:42-20121011, Lee Jones wrote:
> From: Jonas Aaberg <jonas.aberg@stericsson.com>
>
> The overhead is very low and the results will be found under
> sysfs/bootime, as well as detailed results in debugfs under
> boottime/. The bootgraph* files are compatible with
> scripts/bootgraph.pl. The reason for this patch is to provide
> data (sysfs/boottime) suitable for automatic testcases as
> well as help for developers to reduce the boot time (debugfs).
Tried master:
250d8 Merge branch 'i2c-embedded/for-next' of git://git.pengutronix.de/git/wsa/linux
and v3.6-rc7
with omap2plus_defconfig + CONFIG_BOOTTIME enabled:
init/boottime.c:47:9: error: ?cpu_usage_stat? defined as wrong kind of tag
init/boottime.c:47:24: error: array type has incomplete element type
init/boottime.c: In function ?boottime_mark_core?:
init/boottime.c:127:313: error: ?struct kernel_stat? has no member named ?cpustat?
init/boottime.c:128:311: error: ?struct kernel_stat? has no member named ?cpustat?
init/boottime.c:129:313: error: ?struct kernel_stat? has no member named ?cpustat?
init/boottime.c:130:310: error: ?struct kernel_stat? has no member named ?cpustat?
if it depended on some other patch or a specific maintainer branch,
it was'nt clear.
--
Regards,
Nishanth Menon
^ 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