* [PATCH v2 0/5] ARM: tegra: enable wlan for t20 and t30
From: Stephen Warren @ 2012-10-15 21:18 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1348217700-12309-1-git-send-email-wni@nvidia.com>
On 09/21/2012 02:54 AM, Wei Ni wrote:
> Enable wlan for following tegra board:
> Tegra30: Cardhu.
> Tegra20: Seaboard, Ventana.
>
> Note that this series depends on specific brcmfmac patches:
> http://thread.gmane.org/gmane.linux.kernel.wireless.general/97337.
Now that those patches are in 3.7-rc1, I've applied this series to
Tegra's for-3.8/wifi branch (first 4) and for-3.8/defconfig branch (last
1). I'm not 100% sure yet exactly which patches will appear for 3.8; I
might just make a single for-3.8/dt branch instead of having a separate
wifi branch; we'll see...
Thanks.
^ permalink raw reply
* ARM: hw_breakpoint: silent EPERM when setting ARM_DSCR_MDBGEN on ARM_DEBUG_ARCH_V7_ECP14
From: Valentin Pistol @ 2012-10-15 20:48 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20121009210802.GA31615@mudshark.cambridge.arm.com>
> Can you try this with my hw-breakpoint branch please? I've reworked a fair
> amount of code there, so it might at least be more verbose if it fails.
I am trying the Linaro 12.08 images from
http://releases.linaro.org/12.08/android/leb-panda/
After testing it boots fine on my board, I replaced the uImage with
one built from your code at
git://git.kernel.org/pub/scm/linux/kernel/git/will/linux.git and
hw-breakpoint branch.
Unfortunately it gets stuck on "Uncompressing Linux... done, booting
the kernel." on the serial port.
What kernel config are you using? I'm using omap2plus_defconfig
resulting in a Linux-3.7.0-rc1-00015-gd633d80b kernel:
$ make mrproper
$ make ARCH=arm CROSS_COMPILE=arm-eabi- omap2plus_defconfig uImage
I also tried using the Linaro 12.08 kernel config from the above page:
$ make mrproper
$ cp linaro_kernel_config .config
$ make ARCH=arm CROSS_COMPILE=arm-eabi- uImage
[ accept a lot of default values due to kernel version changes ]
Then I mount the SD card and replace the uImage file yet neither uImages boot.
Here is the full serial log: http://pastebin.com/raw.php?i=YQ4vk634
> In that discussion, the TI folks are confusing `Monitor-mode Debug' with
> `Secure Monitor Mode'. They are two completely different things and (for the
> purposes of this discussion), unrelated. You should press them further on
> this!
Thanks for the clarification, I contacted them again and will see how
it turns out.
>> Have you used a Pandaboard and can comment on how to enable the
>> breakpoints/watchpoints?
>
> I haven't tried it, but I do have a Panda now so I could give it a go when I
> get a chance. I suspect there's something related to power-management at
> play... for JTAG, you need to hack MLO as described here:
>
> http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.faqs/ka15314.html
>
> maybe something similar is required for self-hosted (monitor mode) debug?
If you could give it a try on your Panda that would be great!
On Fri, Oct 12, 2012 at 7:26 AM, Dietmar Eggemann
<dietmar.eggemann@arm.com> wrote:
> I'm running Linaro 12.08 on Pandaboard (Rev A1) and on this board
> DBGAUTHSTATUS.NSNE and DBGAUTHSTATUS.NSE are set.
>
> With additional logs in enable_monitor_mode()
> [arch/arm/kernel/hw_breakpoint.c]:
>
> root at linaro-nano:~# dmesg | grep hw-break
> [ 0.321380] hw-breakpoint: arch_hw_breakpoint_init cpu0 debug_arch=3
> [ 0.321441] hw-breakpoint: enable_monitor_mode cpu1 DBGDSCR=03070002
> [ 0.321441] hw-breakpoint: enable_monitor_mode cpu1
> DBGAUTHSTATUS=000000af
> [ 0.321502] hw-breakpoint: enable_monitor_mode cpu0 DBGDSCR=03070002
> [ 0.321533] hw-breakpoint: enable_monitor_mode cpu0
> DBGAUTHSTATUS=000000af
> [ 0.321533] hw-breakpoint: found 5 (+1 reserved) breakpoint and 1
> watchpoint registers.
> [ 0.321563] hw-breakpoint: maximum watchpoint size is 4 bytes.
Dietmar,
That looks great! Did you flash the prebuilt images from Linaro 12.08
and replaced the kernel with those extra debug messages on top of
kernel at git://android.git.linaro.org/kernel/panda? Or are you using
Will's branch?
I am using a newer Pandaboard ES (Rev B1) and hope this is not the problem.
Could you please provide a few instructions to reproduce your setup?
Thanks!
Valentin
^ permalink raw reply
* [PATCH] gpio: clps711x: localise <mach/gpio.h> header
From: Alexander Shiyan @ 2012-10-15 20:47 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CACRpkdYxQsS4RfCxk3E4GPa+7GK2FeOVfTCps1ZtPC=gSw2a0g@mail.gmail.com>
On Mon, 15 Oct 2012 22:36:32 +0200
Linus Walleij <linus.walleij@linaro.org> wrote:
> On Mon, Oct 15, 2012 at 10:04 PM, Alexander Shiyan <shc_work@mail.ru> wrote:
> > On Mon, 15 Oct 2012 21:40:20 +0200
> > Linus Walleij <linus.walleij@linaro.org> wrote:
> >
> >> The commit adding the CLPS711x driver also added <mach/gpio.h>
> >> to the CLPS711x, and we want to get rid of all <mach/*>
> >> headers for the future. It turns out that the one macro defined
> >> in the file was only used in the GPIO driver itself, so just
> >> delete it and copy the macro into the driver.
> > ...
> >> -/* Simple helper for convert port & pin to GPIO number */
> >> -#define CLPS711X_GPIO(port, bit) ((port) * 8 + (bit))
> >
> > This macro is not used by driver and was be designed especially for future
> > easy modify existing drivers that use GPIO to gpio-driver.
>
> Then I will delete it for now (see separate patch).
>
> If we shall have a file with macros used like that it needs
> to atleast be something like
> <linux/platform_data/gpio-clps711x.h>
>
> We don't want to add new files to <mach/*>.
OK, but since it will be used only in board code, I reintroduce it
in arch/arm/mach-clps711x/common.h. On my opinion is no reason to
overload include/linux/*.
--
Alexander Shiyan <shc_work@mail.ru>
^ permalink raw reply
* [PATCH] gpio: clps711x: localise <mach/gpio.h> header
From: Linus Walleij @ 2012-10-15 20:36 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20121016000405.94f779c6066ded6289e35baa@mail.ru>
On Mon, Oct 15, 2012 at 10:04 PM, Alexander Shiyan <shc_work@mail.ru> wrote:
> On Mon, 15 Oct 2012 21:40:20 +0200
> Linus Walleij <linus.walleij@linaro.org> wrote:
>
>> The commit adding the CLPS711x driver also added <mach/gpio.h>
>> to the CLPS711x, and we want to get rid of all <mach/*>
>> headers for the future. It turns out that the one macro defined
>> in the file was only used in the GPIO driver itself, so just
>> delete it and copy the macro into the driver.
> ...
>> -/* Simple helper for convert port & pin to GPIO number */
>> -#define CLPS711X_GPIO(port, bit) ((port) * 8 + (bit))
>
> This macro is not used by driver and was be designed especially for future
> easy modify existing drivers that use GPIO to gpio-driver.
Then I will delete it for now (see separate patch).
If we shall have a file with macros used like that it needs
to atleast be something like
<linux/platform_data/gpio-clps711x.h>
We don't want to add new files to <mach/*>.
Yours,
Linus Walleij
^ permalink raw reply
* [PATCH] gpio: clps711x: delete local <mach/gpio.h> header
From: Linus Walleij @ 2012-10-15 20:34 UTC (permalink / raw)
To: linux-arm-kernel
This header file is unused and we shall not add new headers
to the <mach/*> namespace. The macro may be reintroduced when
there is a user for it.
Cc: Alexander Shiyan <shc_work@mail.ru>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Russell King <rmk+kernel@arm.linux.org.uk>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
arch/arm/mach-clps711x/include/mach/gpio.h | 13 -------------
1 file changed, 13 deletions(-)
delete mode 100644 arch/arm/mach-clps711x/include/mach/gpio.h
diff --git a/arch/arm/mach-clps711x/include/mach/gpio.h b/arch/arm/mach-clps711x/include/mach/gpio.h
deleted file mode 100644
index 8ac6889..0000000
--- a/arch/arm/mach-clps711x/include/mach/gpio.h
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * This file contains the CLPS711X GPIO definitions.
- *
- * Copyright (C) 2012 Alexander Shiyan <shc_work@mail.ru>
- *
- * 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.
- */
-
-/* Simple helper for convert port & pin to GPIO number */
-#define CLPS711X_GPIO(port, bit) ((port) * 8 + (bit))
--
1.7.11.7
^ permalink raw reply related
* [PATCH RFC 2/6 v3] gpio: Add sysfs support to block GPIO API
From: Linus Walleij @ 2012-10-15 20:30 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20121015181928.GB27923@kroah.com>
I really request Grant to comment on this...too.
On Mon, Oct 15, 2012 at 8:19 PM, Greg Kroah-Hartman
<gregkh@linuxfoundation.org> wrote:
> On Mon, Oct 15, 2012 at 08:07:02PM +0200, Jean-Christophe PLAGNIOL-VILLARD wrote:
>> On 21:11 Fri 12 Oct , Roland Stigge wrote:
>> > This patch adds sysfs support to the block GPIO API.
>> >
>> > Signed-off-by: Roland Stigge <stigge@antcom.de>
>> >
>> > ---
>> > Documentation/ABI/testing/sysfs-gpio | 6
>> > drivers/gpio/gpiolib.c | 226 ++++++++++++++++++++++++++++++++++-
>> > include/asm-generic/gpio.h | 11 +
>> > include/linux/gpio.h | 13 ++
>> > 4 files changed, 254 insertions(+), 2 deletions(-)
>> I really don't like this sysfs we need to add a specific device with ioctl
>
> Why?
I don't like it either, basically because the GPIO sysfs is not
entirely sound.
Another patch that is circulating concerns edge triggers and similar,
and it appear that some parts of the GPIO sysfs is for example
redefining and exporting IRQchip properties like trigger edge
in sysfs, while the settings of the irqchip actually used by the driver
is not reflected in the other direction. So you can *set* these things
by writing in the GPIO sysfs, but never trust what you *read* from
there. And you can set what edges an IRQ will trigger on a certain
GPIO, and the way to handle the IRQs from usespace is to poll
on a value. This is not really documented but well ...
Part of me just want to delete that, but I can't because it's now
an ABI.
The "devices" that the sysfs files are tied to are not real devices,
instead the code look like this: whenever a gpio is exported to
sysfs, the code calls (drivers/gpio/gpiolib.c):
dev = device_create(&gpio_class, desc->chip->dev, MKDEV(0, 0),
desc, ioname ? ioname : "gpio%u", gpio);
Mock device just to get a sysfs opening. And once device for
every GPIO with no hierarchical correspondence to anything
in the system.
The thing is that struct gpio_chip is not a device at all, it's something
else.
This inconsistency in the GPIO sysfs implementation make me
fear adding new stuff to it. The other problems need fixing first.
The reason an ioctl() IMO is better suited to do the job is that
it can properly represent a multiple-value operation on several
GPIOs at the same time in a struct, and it can conversely inform
userspace about which GPIOs may be a block of signals that
can be fired simultaneously instead of going to string parsing
and binary values in sysfs which look like worse hacks to me.
The last thing I'm a bit softer on though. Mainly I fear of this
sysfs ABI growing into a beast.
It was all merged prior to Grant becoming maintainer and
me becoming co-maintainer of it, so this is legacy business.
Sadly the main creator of this ABI is David Brownell who is
not able to respond nor maintain it from where he is now. But
we need to think hard about what we shall do with this particular
piece of legacy. Some of the stuff was added by Daniel
Gl?ckner so requesting advice from him.
Daniel: are you interested in helping us fixing the GPIOlib
sysfs ABI and kernel internals? I'm a bit afraid of it.
Yours,
Linus Walleij
^ permalink raw reply
* [PATCH] gpio: clps711x: localise <mach/gpio.h> header
From: Alexander Shiyan @ 2012-10-15 20:04 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1350330020-23240-1-git-send-email-linus.walleij@linaro.org>
On Mon, 15 Oct 2012 21:40:20 +0200
Linus Walleij <linus.walleij@linaro.org> wrote:
> The commit adding the CLPS711x driver also added <mach/gpio.h>
> to the CLPS711x, and we want to get rid of all <mach/*>
> headers for the future. It turns out that the one macro defined
> in the file was only used in the GPIO driver itself, so just
> delete it and copy the macro into the driver.
...
> -/* Simple helper for convert port & pin to GPIO number */
> -#define CLPS711X_GPIO(port, bit) ((port) * 8 + (bit))
...
This macro is not used by driver and was be designed especially for future
easy modify existing drivers that use GPIO to gpio-driver.
--
Alexander Shiyan <shc_work@mail.ru>
^ permalink raw reply
* [PATCH 2/4] ARM: kirkwood: DT board setup for Network Space v2 and parents
From: Rob Herring @ 2012-10-15 19:58 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1350315295-14567-3-git-send-email-simon.guinot@sequanux.org>
On 10/15/2012 10:34 AM, Simon Guinot wrote:
> This patch adds DT board setup for LaCie Network Space v2 and parents,
> based on the Marvell Kirkwood 6281 SoC. This includes Network Space v2
> (Max) and Internet Space v2.
>
> Signed-off-by: Simon Guinot <simon.guinot@sequanux.org>
> ---
> arch/arm/boot/dts/Makefile | 3 +
> arch/arm/boot/dts/kirkwood-is2.dts | 30 ++++++++++
> arch/arm/boot/dts/kirkwood-ns2-common.dtsi | 63 +++++++++++++++++++++
> arch/arm/boot/dts/kirkwood-ns2.dts | 30 ++++++++++
> arch/arm/boot/dts/kirkwood-ns2max.dts | 49 ++++++++++++++++
> arch/arm/mach-kirkwood/Kconfig | 21 +++++++
> arch/arm/mach-kirkwood/Makefile | 3 +
> arch/arm/mach-kirkwood/board-dt.c | 8 +++
> arch/arm/mach-kirkwood/board-ns2.c | 83 ++++++++++++++++++++++++++++
> arch/arm/mach-kirkwood/common.h | 8 +++
> drivers/leds/Kconfig | 4 +-
> 11 files changed, 301 insertions(+), 1 deletion(-)
> create mode 100644 arch/arm/boot/dts/kirkwood-is2.dts
> create mode 100644 arch/arm/boot/dts/kirkwood-ns2-common.dtsi
> create mode 100644 arch/arm/boot/dts/kirkwood-ns2.dts
> create mode 100644 arch/arm/boot/dts/kirkwood-ns2max.dts
> create mode 100644 arch/arm/mach-kirkwood/board-ns2.c
>
> diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
> index c1ce813..e6201b6 100644
> --- a/arch/arm/boot/dts/Makefile
> +++ b/arch/arm/boot/dts/Makefile
> @@ -34,9 +34,12 @@ dtb-$(CONFIG_ARCH_KIRKWOOD) += kirkwood-dns320.dtb \
> kirkwood-ib62x0.dtb \
> kirkwood-iconnect.dtb \
> kirkwood-iomega_ix2_200.dtb \
> + kirkwood-is2.dtb \
> kirkwood-km_kirkwood.dtb \
> kirkwood-lschlv2.dtb \
> kirkwood-lsxhl.dtb \
> + kirkwood-ns2.dtb \
> + kirkwood-ns2max.dtb \
> kirkwood-ts219-6281.dtb \
> kirkwood-ts219-6282.dtb
> dtb-$(CONFIG_ARCH_MSM) += msm8660-surf.dtb \
> diff --git a/arch/arm/boot/dts/kirkwood-is2.dts b/arch/arm/boot/dts/kirkwood-is2.dts
> new file mode 100644
> index 0000000..7bc4677
> --- /dev/null
> +++ b/arch/arm/boot/dts/kirkwood-is2.dts
> @@ -0,0 +1,30 @@
> +/dts-v1/;
> +
> +/include/ "kirkwood-ns2-common.dtsi"
> +
> +/ {
> + model = "LaCie Internet Space v2";
> + compatible = "lacie,inetspace_v2", "marvell,kirkwood-88f6281", "marvell,kirkwood";
Compatible strings must be documented.
Rob
> +
> + memory {
> + device_type = "memory";
> + reg = <0x00000000 0x8000000>;
> + };
> +
> + ocp at f1000000 {
> + sata at 80000 {
> + status = "okay";
> + nr-ports = <1>;
> + };
> + };
> +
> + ns2-leds {
> + compatible = "ns2-leds";
> +
> + blue-sata {
> + label = "ns2:blue:sata";
> + slow-gpio = <&gpio0 29 0>;
> + cmd-gpio = <&gpio0 30 0>;
> + };
> + };
> +};
> diff --git a/arch/arm/boot/dts/kirkwood-ns2-common.dtsi b/arch/arm/boot/dts/kirkwood-ns2-common.dtsi
> new file mode 100644
> index 0000000..9bc6785
> --- /dev/null
> +++ b/arch/arm/boot/dts/kirkwood-ns2-common.dtsi
> @@ -0,0 +1,63 @@
> +/include/ "kirkwood.dtsi"
> +
> +/ {
> + chosen {
> + bootargs = "console=ttyS0,115200n8";
> + };
> +
> + ocp at f1000000 {
> + serial at 12000 {
> + clock-frequency = <166666667>;
> + status = "okay";
> + };
> +
> + spi at 10600 {
> + status = "okay";
> +
> + flash at 0 {
> + #address-cells = <1>;
> + #size-cells = <1>;
> + compatible = "mx25l4005a";
> + reg = <0>;
> + spi-max-frequency = <20000000>;
> + mode = <0>;
> +
> + partition at 0 {
> + reg = <0x0 0x80000>;
> + label = "u-boot";
> + };
> + };
> + };
> +
> + i2c at 11000 {
> + status = "okay";
> +
> + eeprom at 50 {
> + compatible = "at,24c04";
> + pagesize = <16>;
> + reg = <0x50>;
> + };
> + };
> + };
> +
> + gpio_keys {
> + compatible = "gpio-keys";
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + button at 1 {
> + label = "Power push button";
> + linux,code = <116>;
> + gpios = <&gpio1 0 0>;
> + };
> + };
> +
> + gpio-leds {
> + compatible = "gpio-leds";
> +
> + red-fail {
> + label = "ns2:red:fail";
> + gpios = <&gpio0 12 0>;
> + };
> + };
> +};
> diff --git a/arch/arm/boot/dts/kirkwood-ns2.dts b/arch/arm/boot/dts/kirkwood-ns2.dts
> new file mode 100644
> index 0000000..d018213
> --- /dev/null
> +++ b/arch/arm/boot/dts/kirkwood-ns2.dts
> @@ -0,0 +1,30 @@
> +/dts-v1/;
> +
> +/include/ "kirkwood-ns2-common.dtsi"
> +
> +/ {
> + model = "LaCie Network Space v2";
> + compatible = "lacie,netspace_v2", "marvell,kirkwood-88f6281", "marvell,kirkwood";
> +
> + memory {
> + device_type = "memory";
> + reg = <0x00000000 0x10000000>;
> + };
> +
> + ocp at f1000000 {
> + sata at 80000 {
> + status = "okay";
> + nr-ports = <1>;
> + };
> + };
> +
> + ns2-leds {
> + compatible = "ns2-leds";
> +
> + blue-sata {
> + label = "ns2:blue:sata";
> + slow-gpio = <&gpio0 29 0>;
> + cmd-gpio = <&gpio0 30 0>;
> + };
> + };
> +};
> diff --git a/arch/arm/boot/dts/kirkwood-ns2max.dts b/arch/arm/boot/dts/kirkwood-ns2max.dts
> new file mode 100644
> index 0000000..82156e2
> --- /dev/null
> +++ b/arch/arm/boot/dts/kirkwood-ns2max.dts
> @@ -0,0 +1,49 @@
> +/dts-v1/;
> +
> +/include/ "kirkwood-ns2-common.dtsi"
> +
> +/ {
> + model = "LaCie Network Space Max v2";
> + compatible = "lacie,netspace_max_v2", "marvell,kirkwood-88f6281", "marvell,kirkwood";
> +
> + memory {
> + device_type = "memory";
> + reg = <0x00000000 0x10000000>;
> + };
> +
> + ocp at f1000000 {
> + sata at 80000 {
> + status = "okay";
> + nr-ports = <2>;
> + };
> + };
> +
> + gpio_fan {
> + compatible = "gpio-fan";
> + gpios = <&gpio0 22 1
> + &gpio0 7 1
> + &gpio1 1 1
> + &gpio0 23 1>;
> + gpio-fan,speed-map =
> + < 0 0
> + 1500 15
> + 1700 14
> + 1800 13
> + 2100 12
> + 3100 11
> + 3300 10
> + 4300 9
> + 5500 8>;
> + alarm-gpios = <&gpio0 25 1>;
> + };
> +
> + ns2-leds {
> + compatible = "ns2-leds";
> +
> + blue-sata {
> + label = "ns2:blue:sata";
> + slow-gpio = <&gpio0 29 0>;
> + cmd-gpio = <&gpio0 30 0>;
> + };
> + };
> +};
> diff --git a/arch/arm/mach-kirkwood/Kconfig b/arch/arm/mach-kirkwood/Kconfig
> index 50bca50..847e0c2 100644
> --- a/arch/arm/mach-kirkwood/Kconfig
> +++ b/arch/arm/mach-kirkwood/Kconfig
> @@ -130,6 +130,27 @@ config MACH_KM_KIRKWOOD_DT
> Say 'Y' here if you want your kernel to support the
> Keymile Kirkwood Reference Desgin, using Flattened Device Tree.
>
> +config MACH_INETSPACE_V2_DT
> + bool "LaCie Internet Space v2 NAS (Flattened Device Tree)"
> + select ARCH_KIRKWOOD_DT
> + help
> + Say 'Y' here if you want your kernel to support the LaCie
> + Internet Space v2 NAS, using Flattened Device Tree.
> +
> +config MACH_NETSPACE_V2_DT
> + bool "LaCie Network Space v2 NAS (Flattened Device Tree)"
> + select ARCH_KIRKWOOD_DT
> + help
> + Say 'Y' here if you want your kernel to support the LaCie
> + Network Space v2 NAS, using Flattened Device Tree.
> +
> +config MACH_NETSPACE_MAX_V2_DT
> + bool "LaCie Network Space Max v2 NAS (Flattened Device Tree)"
> + select ARCH_KIRKWOOD_DT
> + help
> + Say 'Y' here if you want your kernel to support the LaCie
> + Network Space Max v2 NAS, using Flattened Device Tree.
> +
> config MACH_TS219
> bool "QNAP TS-110, TS-119, TS-119P+, TS-210, TS-219, TS-219P and TS-219P+ Turbo NAS"
> help
> diff --git a/arch/arm/mach-kirkwood/Makefile b/arch/arm/mach-kirkwood/Makefile
> index 294779f..1f63d80 100644
> --- a/arch/arm/mach-kirkwood/Makefile
> +++ b/arch/arm/mach-kirkwood/Makefile
> @@ -31,3 +31,6 @@ obj-$(CONFIG_MACH_GOFLEXNET_DT) += board-goflexnet.o
> obj-$(CONFIG_MACH_LSXL_DT) += board-lsxl.o
> obj-$(CONFIG_MACH_IOMEGA_IX2_200_DT) += board-iomega_ix2_200.o
> obj-$(CONFIG_MACH_KM_KIRKWOOD_DT) += board-km_kirkwood.o
> +obj-$(CONFIG_MACH_INETSPACE_V2_DT) += board-ns2.o
> +obj-$(CONFIG_MACH_NETSPACE_V2_DT) += board-ns2.o
> +obj-$(CONFIG_MACH_NETSPACE_MAX_V2_DT) += board-ns2.o
> diff --git a/arch/arm/mach-kirkwood/board-dt.c b/arch/arm/mach-kirkwood/board-dt.c
> index 70c5a28..b3e0519 100644
> --- a/arch/arm/mach-kirkwood/board-dt.c
> +++ b/arch/arm/mach-kirkwood/board-dt.c
> @@ -96,6 +96,11 @@ static void __init kirkwood_dt_init(void)
> if (of_machine_is_compatible("keymile,km_kirkwood"))
> km_kirkwood_init();
>
> + if (of_machine_is_compatible("lacie,inetspace_v2") ||
> + of_machine_is_compatible("lacie,netspace_v2") ||
> + of_machine_is_compatible("lacie,netspace_max_v2"))
> + ns2_init();
> +
> of_platform_populate(NULL, kirkwood_dt_match_table,
> kirkwood_auxdata_lookup, NULL);
> }
> @@ -112,6 +117,9 @@ static const char *kirkwood_dt_board_compat[] = {
> "buffalo,lsxl",
> "iom,ix2-200",
> "keymile,km_kirkwood",
> + "lacie,inetspace_v2",
> + "lacie,netspace_max_v2",
> + "lacie,netspace_v2",
> NULL
> };
>
> diff --git a/arch/arm/mach-kirkwood/board-ns2.c b/arch/arm/mach-kirkwood/board-ns2.c
> new file mode 100644
> index 0000000..b36c55c
> --- /dev/null
> +++ b/arch/arm/mach-kirkwood/board-ns2.c
> @@ -0,0 +1,83 @@
> +/*
> + * Copyright 2012 (C), Simon Guinot <simon.guinot@sequanux.org>
> + *
> + * arch/arm/mach-kirkwood/board-ns2.c
> + *
> + * LaCie Network Space v2 board (and parents) initialization for drivers
> + * not converted to flattened device tree yet.
> + *
> + * This file is licensed under the terms of the GNU General Public
> + * License version 2. This program is licensed "as is" without any
> + * warranty of any kind, whether express or implied.
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/init.h>
> +#include <linux/platform_device.h>
> +#include <linux/mv643xx_eth.h>
> +#include <linux/gpio.h>
> +#include "common.h"
> +#include "mpp.h"
> +
> +static struct mv643xx_eth_platform_data ns2_ge00_data = {
> + .phy_addr = MV643XX_ETH_PHY_ADDR(8),
> +};
> +
> +static unsigned int ns2_mpp_config[] __initdata = {
> + MPP0_SPI_SCn,
> + MPP1_SPI_MOSI,
> + MPP2_SPI_SCK,
> + MPP3_SPI_MISO,
> + MPP4_NF_IO6,
> + MPP5_NF_IO7,
> + MPP6_SYSRST_OUTn,
> + MPP7_GPO, /* Fan speed (bit 1) */
> + MPP8_TW0_SDA,
> + MPP9_TW0_SCK,
> + MPP10_UART0_TXD,
> + MPP11_UART0_RXD,
> + MPP12_GPO, /* Red led */
> + MPP14_GPIO, /* USB fuse */
> + MPP16_GPIO, /* SATA 0 power */
> + MPP17_GPIO, /* SATA 1 power */
> + MPP18_NF_IO0,
> + MPP19_NF_IO1,
> + MPP20_SATA1_ACTn,
> + MPP21_SATA0_ACTn,
> + MPP22_GPIO, /* Fan speed (bit 0) */
> + MPP23_GPIO, /* Fan power */
> + MPP24_GPIO, /* USB mode select */
> + MPP25_GPIO, /* Fan rotation fail */
> + MPP26_GPIO, /* USB device vbus */
> + MPP28_GPIO, /* USB enable host vbus */
> + MPP29_GPIO, /* Blue led (slow register) */
> + MPP30_GPIO, /* Blue led (command register) */
> + MPP31_GPIO, /* Board power off */
> + MPP32_GPIO, /* Power button (0 = Released, 1 = Pushed) */
> + MPP33_GPO, /* Fan speed (bit 2) */
> + 0
> +};
> +
> +#define NS2_GPIO_POWER_OFF 31
> +
> +static void ns2_power_off(void)
> +{
> + gpio_set_value(NS2_GPIO_POWER_OFF, 1);
> +}
> +
> +void __init ns2_init(void)
> +{
> + /*
> + * Basic setup. Needs to be called early.
> + */
> + kirkwood_mpp_conf(ns2_mpp_config);
> +
> + kirkwood_ehci_init();
> + kirkwood_ge00_init(&ns2_ge00_data);
> +
> + if (gpio_request(NS2_GPIO_POWER_OFF, "power-off") == 0 &&
> + gpio_direction_output(NS2_GPIO_POWER_OFF, 0) == 0)
> + pm_power_off = ns2_power_off;
> + else
> + pr_err("ns2: failed to configure power-off GPIO\n");
> +}
> diff --git a/arch/arm/mach-kirkwood/common.h b/arch/arm/mach-kirkwood/common.h
> index bcffd7c..2f75f3f 100644
> --- a/arch/arm/mach-kirkwood/common.h
> +++ b/arch/arm/mach-kirkwood/common.h
> @@ -112,6 +112,14 @@ void km_kirkwood_init(void);
> static inline void km_kirkwood_init(void) {};
> #endif
>
> +#if defined(CONFIG_MACH_INETSPACE_V2_DT) || \
> + defined(CONFIG_MACH_NETSPACE_V2_DT) || \
> + defined(CONFIG_MACH_NETSPACE_MAX_V2_DT)
> +void ns2_init(void);
> +#else
> +static inline void ns2_init(void) {};
> +#endif
> +
> /* early init functions not converted to fdt yet */
> char *kirkwood_id(void);
> void kirkwood_l2_init(void);
> diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
> index f508def..e455c08 100644
> --- a/drivers/leds/Kconfig
> +++ b/drivers/leds/Kconfig
> @@ -379,7 +379,9 @@ config LEDS_NS2
> tristate "LED support for Network Space v2 GPIO LEDs"
> depends on LEDS_CLASS
> depends on MACH_NETSPACE_V2 || MACH_INETSPACE_V2 || \
> - MACH_NETSPACE_MAX_V2 || MACH_D2NET_V2
> + MACH_NETSPACE_MAX_V2 || MACH_D2NET_V2 || \
> + MACH_NETSPACE_V2_DT || MACH_INETSPACE_V2_DT || \
> + MACH_NETSPACE_MAX_V2_DT
> default y
> help
> This option enable support for the dual-GPIO LED found on the
>
^ permalink raw reply
* [PATCH 1/4] leds: leds-ns2: add device tree binding
From: Jason Cooper @ 2012-10-15 19:58 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20121015191222.GB28384@kw.sim.vm.gnt>
On Mon, Oct 15, 2012 at 09:12:22PM +0200, Simon Guinot wrote:
> On Mon, Oct 15, 2012 at 01:41:44PM -0400, Jason Cooper wrote:
> > On Mon, Oct 15, 2012 at 05:34:52PM +0200, Simon Guinot wrote:
> > > Signed-off-by: Simon Guinot <simon.guinot@sequanux.org>
> > > ---
> > > .../devicetree/bindings/gpio/leds-ns2.txt | 26 ++++++
> > > drivers/leds/leds-ns2.c | 84 +++++++++++++++++++-
> > > 2 files changed, 107 insertions(+), 3 deletions(-)
> > > create mode 100644 Documentation/devicetree/bindings/gpio/leds-ns2.txt
> > >
> > > diff --git a/Documentation/devicetree/bindings/gpio/leds-ns2.txt b/Documentation/devicetree/bindings/gpio/leds-ns2.txt
> > > new file mode 100644
> > > index 0000000..1a84969
> > > --- /dev/null
> > > +++ b/Documentation/devicetree/bindings/gpio/leds-ns2.txt
> > > @@ -0,0 +1,26 @@
> > > +Binding for dual-GPIO LED found on Network Space v2 (and parents).
> > > +
> > > +Required properties:
> > > +- compatible: "ns2-leds".
> > > +
> > > +Each LED is represented as a sub-node of the ns2-leds device.
> > > +
> > > +Required sub-node properties:
> > > +- cmd-gpio: Command LED GPIO. See OF device-tree GPIO specification.
> > > +- slow-gpio: Slow LED GPIO. See OF device-tree GPIO specification.
> > > +
> > > +Optional sub-node properties:
> > > +- label: Name for this LED. If omitted, the label is taken from the node name.
> > > +- linux,default-trigger: Trigger assigned to the LED.
> > > +
> > > +Example:
> > > +
> > > +ns2-leds {
> > > + compatible = "ns2-leds";
> > > +
> > > + blue-sata {
> > > + label = "ns2:blue:sata";
> > > + slow-gpio = <&gpio0 29 0>;
> > > + cmd-gpio = <&gpio0 30 0>;
> > > + };
> > > +};
> > > diff --git a/drivers/leds/leds-ns2.c b/drivers/leds/leds-ns2.c
> > > index d176ec8..55d199b 100644
> > > --- a/drivers/leds/leds-ns2.c
> > > +++ b/drivers/leds/leds-ns2.c
> > > @@ -30,6 +30,7 @@
> > > #include <linux/leds.h>
> > > #include <linux/module.h>
> > > #include <linux/platform_data/leds-kirkwood-ns2.h>
> > > +#include <linux/of_gpio.h>
> > >
> > > /*
> > > * The Network Space v2 dual-GPIO LED is wired to a CPLD and can blink in
> > > @@ -263,6 +264,68 @@ static void delete_ns2_led(struct ns2_led_data *led_dat)
> > > gpio_free(led_dat->slow);
> > > }
> > >
> > > +#ifdef CONFIG_OF_GPIO
> > > +/*
> > > + * Translate OpenFirmware node properties into platform_data.
> > > + */
> > > +static int __devinit
> > > +ns2_leds_get_of_pdata(struct device *dev, struct ns2_led_platform_data *pdata)
> > > +{
> > > + struct device_node *np = dev->of_node;
> > > + struct device_node *child;
> > > + struct ns2_led *leds;
> > > + int num_leds = 0;
> > > + int i = 0;
> > > +
> > > + num_leds = of_get_child_count(np);
> > > + if (!num_leds)
> > > + return -ENODEV;
> > > +
> > > + leds = devm_kzalloc(dev, num_leds * sizeof(struct ns2_led),
> > > + GFP_KERNEL);
> > > + if (!leds)
> > > + return -ENOMEM;
> > > +
> > > + for_each_child_of_node(np, child) {
> > > + const char *string;
> > > + int ret;
> > > +
> > > + ret = of_get_named_gpio(child, "cmd-gpio", 0);
> > > + if (ret < 0)
> > > + return ret;
> >
> > free leds?
>
> Maybe I missed something but I though it was the purpose of using devres
> function as devm_kzalloc.
You are correct. alloc/return involks a visceral reaction, akin to a
bull seeing red, my mistake. :-)
>
> >
> > > + leds[i].cmd = ret;
> > > + ret = of_get_named_gpio(child, "slow-gpio", 0);
> > > + if (ret < 0)
> > > + return ret;
> >
> > same here.
> >
> > > + leds[i].slow = ret;
> > > + ret = of_property_read_string(child, "label", &string);
> > > + leds[i].name = (ret == 0) ? string : child->name;
> > > + ret = of_property_read_string(child, "linux,default-trigger",
> > > + &string);
> > > + if (ret == 0)
> > > + leds[i].default_trigger = string;
> > > +
> > > + i++;
> > > + }
> > > +
> > > + pdata->leds = leds;
> > > + pdata->num_leds = num_leds;
> > > +
> > > + return 0;
> > > +}
> > > +
> > > +static const struct of_device_id of_ns2_leds_match[] = {
> > > + { .compatible = "ns2-leds", },
> >
> > Is this LaCie-specific? eg "lacie,ns2-leds"?
>
> Yes I think it is LaCie specific.
Ok, please change.
>
> >
> > > + {},
> > > +};
> > > +#else
> > > +static int __devinit
> > > +ns2_leds_get_of_pdata(struct device *dev, struct ns2_led_platform_data *pdata)
> > > +{
> > > + return -ENODEV;
> > > +}
> > > +#endif /* CONFIG_OF_GPIO */
> >
> > The above doesn't look right to me. The only time
> > ns2_leds_get_of_pdata() gets called is when OF_GPIO is enabled. You
> > should be able to remove the #else block.
>
> Yes you are right.
>
> >
> > > +
> > > static int __devinit ns2_led_probe(struct platform_device *pdev)
> > > {
> > > struct ns2_led_platform_data *pdata = pdev->dev.platform_data;
> > > @@ -270,11 +333,25 @@ static int __devinit ns2_led_probe(struct platform_device *pdev)
> > > int i;
> > > int ret;
> > >
> > > +#ifdef CONFIG_OF_GPIO
> > > + if (!pdata) {
> > > + pdata = devm_kzalloc(&pdev->dev,
> > > + sizeof(struct ns2_led_platform_data),
> > > + GFP_KERNEL);
> > > + if (!pdata)
> > > + return -ENOMEM;
> > > +
> > > + ret = ns2_leds_get_of_pdata(&pdev->dev, pdata);
> > > + if (ret)
> > > + return ret;
> > > + }
> > > +#else
> > > if (!pdata)
> > > return -EINVAL;
> > > +#endif /* CONFIG_OF_GPIO */
> > >
> > > leds_data = devm_kzalloc(&pdev->dev, sizeof(struct ns2_led_data) *
> > > - pdata->num_leds, GFP_KERNEL);
> > > + pdata->num_leds, GFP_KERNEL);
> > > if (!leds_data)
> > > return -ENOMEM;
> > >
> > > @@ -312,8 +389,9 @@ static struct platform_driver ns2_led_driver = {
> > > .probe = ns2_led_probe,
> > > .remove = __devexit_p(ns2_led_remove),
> > > .driver = {
> > > - .name = "leds-ns2",
> > > - .owner = THIS_MODULE,
> > > + .name = "leds-ns2",
> > > + .owner = THIS_MODULE,
> >
> > nit. whitespace before '=', above two lines.
>
> Sorry I don't get it. For the two lines before, I used two tabs before
> '='. As a result, this lines are aligned with the next one. I got no
> warnings and no errors from checkpatch.pl.
It's not a checkpatch problem. It's that before your patch, the equals
signs were lined up. Afterwards, they aren't. In either case, if you
would like to fix the whitespace (line up all struct elements and the
equals signs), that should be a separate patch.
>
> >
> > > + .of_match_table = of_match_ptr(of_ns2_leds_match),
> >
> > Have you tried this with OF_GPIO=n? of_match_ptr() handles CONFIG_OF
> > being enabled/disabled. Which means the case of CONFIG_OF=y,
> > CONFIG_OF_GPIO=n appears to be unhandled.
>
> Good caught. I guess I have just copied a bug from the driver gpio-fan.
On the next round, please add a separate patch fixing gpio-fan.c.
There shouldn't be any harm in moving the struct of_device_id {} outside
of the #ifdef and just above the struct platform_driver {} declaration.
That would maintain the convention. _probe() will just return -EINVAL
if OF_GPIO isn't enabled (without pdata, of course).
thx,
Jason.
^ permalink raw reply
* [PATCH RFC 1/6 v3] gpio: Add a block GPIO API to gpiolib
From: Linus Walleij @ 2012-10-15 19:56 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1350069085-13283-2-git-send-email-stigge@antcom.de>
On Fri, Oct 12, 2012 at 9:11 PM, Roland Stigge <stigge@antcom.de> wrote:
> +#define NR_GPIO_BLOCKS 16
> +
> +static struct gpio_block *gpio_block[NR_GPIO_BLOCKS];
16 looks quite arbitrary, as noted elsewhere please use a list.
Yours,
Linus Walleij
^ permalink raw reply
* [PATCH 07/11] fsmc/nand: Provide contiguous buffers to dma
From: Linus Walleij @ 2012-10-15 19:51 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAN8TOE-7d=YUSYsHFw9X5vnz8cpSJYv5uZfvBpDyhg+-F_LDiQ@mail.gmail.com>
On Mon, Oct 15, 2012 at 6:27 PM, Brian Norris
<computersforpeace@gmail.com> wrote:
> I would prefer not building a solution that hopes kmalloc() can get a
> large contiguous buffer (remember, eraseblock sizes come as large as
> 2MB these days). A real solution like CMA or scatter-gather seems like
> a better idea.
+1 on that, and as I think I illustrated the MMC subsystem is using
the block layer helpers to form scatter-gather lists for it's requests.
I don't see why the MTD subsystem need to be very different?
Yours,
Linus Walleij
^ permalink raw reply
* [PATCH V2 7/7] cpsw: use the time stamping capabilities of the cpts
From: Richard Cochran @ 2012-10-15 19:48 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1350329726.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 aeaa3bb..06a134f 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 | \
@@ -236,6 +237,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)
@@ -272,6 +274,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);
@@ -292,6 +295,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;
@@ -610,6 +614,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)) {
@@ -647,6 +656,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);
@@ -687,6 +711,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,
@@ -988,6 +1013,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) {
@@ -1109,6 +1136,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);
@@ -1148,6 +1180,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 V2 6/7] cpsw: add a DT field for the cpts offset
From: Richard Cochran @ 2012-10-15 19:48 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1350329726.git.richardcochran@gmail.com>
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
---
Documentation/devicetree/bindings/net/cpsw.txt | 3 +++
arch/arm/boot/dts/am33xx.dtsi | 1 +
drivers/net/ethernet/ti/cpsw.c | 7 +++++++
include/linux/platform_data/cpsw.h | 1 +
4 files changed, 12 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/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
index cd9b3b4..c981753 100644
--- a/arch/arm/boot/dts/am33xx.dtsi
+++ b/arch/arm/boot/dts/am33xx.dtsi
@@ -222,6 +222,7 @@
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 e29bb8f..aeaa3bb 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -817,6 +817,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 V2 5/7] cpts: introduce time stamping code and a PTP hardware clock.
From: Richard Cochran @ 2012-10-15 19:48 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1350329726.git.richardcochran@gmail.com>
This patch adds a driver for the CPTS that offers time
stamping and a PTP hardware clock. Even though the
hardware does not support frequency adjustment, still the
unit can be useful for 802.1AS for example.
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 | 468 ++++++++++++++++++++++++++++++++++++++
drivers/net/ethernet/ti/cpts.h | 148 ++++++++++++
4 files changed, 625 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..bdb20c4
--- /dev/null
+++ b/drivers/net/ethernet/ti/cpts.c
@@ -0,0 +1,468 @@
+/*
+ * 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 -EOPNOTSUPP;
+}
+
+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 = 0,
+ .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);
+}
+
+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 V2 4/7] cpsw: add a common header file for regsiter declarations
From: Richard Cochran @ 2012-10-15 19:48 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1350329726.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 V2 3/7] cpsw: correct the CPSW_PORT register bank declaration
From: Richard Cochran @ 2012-10-15 19:48 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1350329726.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 ++++----
arch/arm/boot/dts/am33xx.dtsi | 4 ++--
drivers/net/ethernet/ti/cpsw.c | 18 ++++++++++++++----
3 files changed, 20 insertions(+), 10 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/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
index f6bea04..cd9b3b4 100644
--- a/arch/arm/boot/dts/am33xx.dtsi
+++ b/arch/arm/boot/dts/am33xx.dtsi
@@ -238,13 +238,13 @@
interrupts = <40 41 42 43>;
ranges;
cpsw_emac0: slave at 0 {
- slave_reg_ofs = <0x208>;
+ slave_reg_ofs = <0x200>;
sliver_reg_ofs = <0xd80>;
/* 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>;
/* Filled in by U-Boot */
mac-address = [ 00 00 00 00 00 00 ];
diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index 1bdbb36..e29bb8f 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -157,16 +157,26 @@ 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;
- u32 ts_seq_ltype;
- u32 ts_vlan;
+ u32 ts_seq_mtype;
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 V2 2/7] cpsw: add missing fields to the CPSW_SS register bank.
From: Richard Cochran @ 2012-10-15 19:48 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1350329726.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 3568b46..1bdbb36 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 V2 1/7] cpsw: rename register banks to match the reference manual
From: Richard Cochran @ 2012-10-15 19:48 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1350329726.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 fb1a692..3568b46 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;
@@ -984,7 +984,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 V2 0/7] support the cpts found on am335x devices
From: Richard Cochran @ 2012-10-15 19:48 UTC (permalink / raw)
To: linux-arm-kernel
This patch series, based on linux-3.7-rc1 plus the fixes I posted
today, adds support for the Common Platform Time Sync (CPTS) found on
the popular BeagleBone. The code enables hardware time stamping and a
PTP Hardware Clock.
Changes in V2
- Now uses device tree
- Actually works with vanilla kernel
This work has been tested using the linuxptp PTP stack, and it seems
to be working quite well. One limitation of the hardware is that not
possible to adjust the clock frequency. Even without with this
capability, the driver will be still be useful for 802.1AS
applications, since they typically use a free running clock.
There is one open issue with this driver which will hopefully soon be
resolved. 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 +-
arch/arm/boot/dts/am33xx.dtsi | 5 +-
drivers/net/ethernet/ti/Kconfig | 8 +
drivers/net/ethernet/ti/Makefile | 2 +-
drivers/net/ethernet/ti/cpsw.c | 84 ++++-
drivers/net/ethernet/ti/cpsw_reg.h | 81 ++++
drivers/net/ethernet/ti/cpts.c | 468 ++++++++++++++++++++++++
drivers/net/ethernet/ti/cpts.h | 148 ++++++++
include/linux/platform_data/cpsw.h | 1 +
9 files changed, 788 insertions(+), 20 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 2/4] mtd: devices: elm: Add support for ELM error correction
From: Peter Korsgaard @ 2012-10-15 19:40 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1349274589-11389-3-git-send-email-avinashphilip@ti.com>
>>>>> Philip, Avinash <avinashphilip@ti.com> writes:
> Platforms containing the ELM module can be used to correct errors
> reported by BCH 4, 8 & 16 bit ECC scheme. For now only 4 & 8 bit
> support is added.
This sounds odd to me. What about something like:
The ELM hardware module can be used to speedup BCH 4/8/16 ECC scheme
error correction.
For now only 4 & 8 bit support is added.
> +++ b/drivers/mtd/devices/Makefile
> @@ -17,8 +17,10 @@ obj-$(CONFIG_MTD_LART) += lart.o
> obj-$(CONFIG_MTD_BLOCK2MTD) += block2mtd.o
> obj-$(CONFIG_MTD_DATAFLASH) += mtd_dataflash.o
> obj-$(CONFIG_MTD_M25P80) += m25p80.o
> +obj-$(CONFIG_MTD_NAND_OMAP2) += elm.o
You seem to only use it in 4/4 if CONFIG_MTD_NAND_OMAP_BCH is set, so it
probably makes more sense to use that symbol to not needlessly include
it if it won't be used.
> +++ b/drivers/mtd/devices/elm.c
> @@ -0,0 +1,440 @@
> +/*
> + * Error Location Module
> + *
> + * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.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.
> + *
> + */
> +
> +#include <linux/platform_device.h>
> +#include <linux/module.h>
> +#include <linux/interrupt.h>
> +#include <linux/io.h>
> +#include <linux/of.h>
> +#include <linux/pm_runtime.h>
> +#include <linux/platform_data/elm.h>
> +
> +#define ELM_IRQSTATUS 0x018
> +#define ELM_IRQENABLE 0x01c
> +#define ELM_LOCATION_CONFIG 0x020
> +#define ELM_PAGE_CTRL 0x080
> +#define ELM_SYNDROME_FRAGMENT_0 0x400
> +#define ELM_SYNDROME_FRAGMENT_6 0x418
> +#define ELM_LOCATION_STATUS 0x800
> +#define ELM_ERROR_LOCATION_0 0x880
> +
> +/* ELM Interrupt Status Register */
> +#define INTR_STATUS_PAGE_VALID BIT(8)
> +
> +/* ELM Interrupt Enable Register */
> +#define INTR_EN_PAGE_MASK BIT(8)
> +
> +/* ELM Location Configuration Register */
> +#define ECC_BCH_LEVEL_MASK 0x3
> +
> +/* ELM syndrome */
> +#define ELM_SYNDROME_VALID BIT(16)
> +
> +/* ELM_LOCATION_STATUS Register */
> +#define ECC_CORRECTABLE_MASK BIT(8)
> +#define ECC_NB_ERRORS_MASK 0x1f
> +
> +/* ELM_ERROR_LOCATION_0-15 Registers */
> +#define ECC_ERROR_LOCATION_MASK 0x1fff
> +
> +#define ELM_ECC_SIZE 0x7ff
> +
> +#define SYNDROME_FRAGMENT_REG_SIZE 0x40
> +#define ERROR_LOCATION_SIZE 0x100
> +#define MAX_BCH_ELM_ERROR 16
> +#define ELM_FRAGMENT_REG 7
> +
> +typedef u32 syn_t[ELM_FRAGMENT_REG];
> +typedef u32 elm_error_t[MAX_BCH_ELM_ERROR];
> +
> +struct elm_info {
> + struct device *dev;
> + void __iomem *elm_base;
> + struct completion elm_completion;
> + struct list_head list;
> + enum bch_ecc bch_type;
> +};
> +
> +static LIST_HEAD(elm_devices);
> +
> +static void elm_write_reg(void *offset, u32 val)
> +{
> + writel(val, offset);
> +}
> +
> +static u32 elm_read_reg(void *offset)
> +{
> + return readl(offset);
> +}
As written these read/write wrappers don't add anything. How about
passing struct elm_info and offset as an integer so you can drop
elm_base from all call sites, E.G.:
static void elm_write_reg(struct elm_info *info, int offset, u32 val)
{
writel(val, info->elm_base + offset);
}
> +
> +/**
> + * elm_config - Configure ELM module
> + * @info: elm info
> + */
> +static void elm_config(struct elm_info *info)
> +{
> + u32 reg_val;
> +
> + reg_val = (info->bch_type & ECC_BCH_LEVEL_MASK) | (ELM_ECC_SIZE << 16);
> + elm_write_reg(info->elm_base + ELM_LOCATION_CONFIG, reg_val);
> +}
> +
> +/**
> + * elm_configure_page_mode - Enable/Disable page mode
> + * @info: elm info
> + * @index: index number of syndrome fragment vector
> + * @enable: enable/disable flag for page mode
> + *
> + * Enable page mode for syndrome fragment index
> + */
> +static void elm_configure_page_mode(struct elm_info *info, int index,
> + bool enable)
> +{
> + u32 reg_val;
> +
> + reg_val = elm_read_reg(info->elm_base + ELM_PAGE_CTRL);
> + if (enable)
> + reg_val |= BIT(index); /* enable page mode */
> + else
> + reg_val &= ~BIT(index); /* disable page mode */
> +
> + elm_write_reg(info->elm_base + ELM_PAGE_CTRL, reg_val);
> +}
> +
> +static void rearrange_bch4(u8 *syndrome)
> +{
> + /*
> + * BCH4 has 52 bit used for ecc, but OOB stored with
> + * nibble 0 appended, removes appended 0 nibble
> + */
> + u64 *dst = (u64 *)syndrome;
> + *dst >>= 4;
> +}
> +
> +/**
> + * elm_reverse_eccdata - Reverse ecc data
> + * @info: elm info
> + * @ecc_data: buffer for calculated ecc
> + * @syndrome: buffer for syndrome polynomial
> + *
> + * ecc_data has to be reversed for syndrome vector
> + */
> +static void elm_reverse_eccdata(struct elm_info *info, u8 *ecc_data,
> + u8 *syndrome)
> +{
> + int i;
> + int bch_size = info->bch_type ? BCH8_ECC_OOB_BYTES : BCH4_SIZE;
> +
> + for (i = 0; i < bch_size; i++)
> + syndrome[bch_size - 1 - i] = ecc_data[i];
> +
> + /*
> + * syndrome polynomial to be rearranged for BCH 4 ecc scheme as 52
> + * bits being used and 4 bits being appended in syndrome vector
> + */
> + if (info->bch_type == BCH4_ECC)
> + rearrange_bch4(syndrome);
> +}
> +
> +/**
> + * elm_load_syndrome - Load ELM syndrome reg
> + * @info: elm info
> + * @index: syndrome fragment index
> + * @syndrome: Syndrome polynomial
> + *
> + * Load syndrome fragment registers with syndrome polynomial
> + */
> +static void elm_load_syndrome(struct elm_info *info, int index, u8 *syndrome)
> +{
> + int i;
> + int max = info->bch_type ? BCH8_SYNDROME_SIZE : BCH4_SYNDROME_SIZE;
> + void *syn_frag_base = info->elm_base + ELM_SYNDROME_FRAGMENT_0;
> + syn_t *syn_fragment;
> + u32 reg_val;
> +
> + elm_configure_page_mode(info, index, true);
> + syn_fragment = syn_frag_base + SYNDROME_FRAGMENT_REG_SIZE * index;
> +
> + for (i = 0; i < max; i++) {
> + reg_val = syndrome[0] | syndrome[1] << 8 | syndrome[2] << 16 |
> + syndrome[3] << 24;
> + elm_write_reg(*syn_fragment + i, reg_val);
> + /* Update syndrome polynomial pointer */
> + syndrome += 4;
> + }
> +}
> +
> +/**
> + * elm_start_processing - start elm syndrome processing
> + * @info: elm info
> + * @err_vec: elm error vectors
> + *
> + * Set syndrome valid bit for syndrome fragment registers for which
> + * elm syndrome fragment registers are loaded. This enables elm module
> + * to start processing syndrome vectors.
> + */
> +static void elm_start_processing(struct elm_info *info,
> + struct elm_errorvec *err_vec)
> +{
> + int i;
> + void *offset;
> + u32 reg_val;
> +
> + /*
> + * Set syndrome vector valid so that ELM module will process it for
> + * vectors error is reported
> + */
> + for (i = 0; i < ERROR_VECTOR_MAX; i++) {
> + if (err_vec[i].error_reported) {
> + offset = info->elm_base + ELM_SYNDROME_FRAGMENT_6 + i *
> + SYNDROME_FRAGMENT_REG_SIZE;
> + reg_val = elm_read_reg(offset);
> + reg_val |= ELM_SYNDROME_VALID;
> + elm_write_reg(offset, reg_val);
> + }
> + }
> +}
> +
> +/**
> + * elm_error_correction - locate correctable error position
> + * @info: elm info
> + * @err_vec: elm error vectors
> + *
> + * On completion of processing by elm module, error location status
> + * register updated with correctable/uncorrectable error information.
> + * In case of correctable errors, number of errors located from
> + * elm location status register & read the these many positions from
> + * elm error location register.
> + */
> +static void elm_error_correction(struct elm_info *info,
> + struct elm_errorvec *err_vec)
> +{
> + int i, j, errors = 0;
> + void *err_loc_base = info->elm_base + ELM_ERROR_LOCATION_0;
> + elm_error_t *err_loc;
> + void *offset;
> + u32 reg_val;
> +
> + for (i = 0; i < ERROR_VECTOR_MAX; i++) {
> + /* check error reported */
> + if (err_vec[i].error_reported) {
> + offset = info->elm_base + ELM_LOCATION_STATUS +
> + i * ERROR_LOCATION_SIZE;
> + reg_val = elm_read_reg(offset);
> + /* check correctable error or not */
> + if (reg_val & ECC_CORRECTABLE_MASK) {
> + err_loc = err_loc_base +
> + i * ERROR_LOCATION_SIZE;
> + /* read count of correctable errors */
> + err_vec[i].error_count = reg_val &
> + ECC_NB_ERRORS_MASK;
> +
> + /* update the error locations in error vector */
> + for (j = 0; j < err_vec[i].error_count; j++) {
> +
> + reg_val = elm_read_reg(*err_loc + j);
> + err_vec[i].error_loc[j] = reg_val &
> + ECC_ERROR_LOCATION_MASK;
> + }
> +
> + errors += err_vec[i].error_count;
> + } else {
> + err_vec[i].error_uncorrectable++;
> + }
> +
> + /* clearing interrupts for processed error vectors */
> + elm_write_reg(info->elm_base + ELM_IRQSTATUS, BIT(i));
> +
> + /* disable page mode */
> + elm_configure_page_mode(info, i, false);
> + }
> + }
> +
> + return;
> +}
> +
> +/**
> + * elm_decode_bch_error_page - Locate error position
> + * @info: elm info
> + * @ecc_calc: calculated ECC bytes from GPMC
> + * @err_vec: elm error vectors
> + *
> + * Called with one or greater reported and is vectors with error reported
> + * is updated in err_vec[].error_reported
> + */
> +void elm_decode_bch_error_page(struct device *dev, u8 *ecc_calc,
> + struct elm_errorvec *err_vec)
> +{
> + int i;
> + u8 syndrome[BCH_MAX_ECC_BYTES_PER_SECTOR] = {0}, *syn_p;
Why do you need to keep the entire syndrome around? You seem to only use
it between elm_reverse_eccdata() and elm_load_syndrome(), so it could as
well be BCH8_ECC_OOB_BYTES long (or rather a multiple of sizeof(u32).
It would also be good to do the shuffeling directly in elm_load_syndrome
so you don't need the extra copy.
> + struct elm_info *info = dev_get_drvdata(dev);
> + u32 reg_val;
> +
> + /* enable page mode interrupt */
> + reg_val = elm_read_reg(info->elm_base + ELM_IRQSTATUS);
> + elm_write_reg(info->elm_base + ELM_IRQSTATUS,
> + reg_val & INTR_STATUS_PAGE_VALID);
> + elm_write_reg(info->elm_base + ELM_IRQENABLE, INTR_EN_PAGE_MASK);
> +
> + syn_p = syndrome;
> + for (i = 0; i < ERROR_VECTOR_MAX; i++) {
> + if (err_vec[i].error_reported) {
> + elm_reverse_eccdata(info, ecc_calc, syn_p);
> + elm_load_syndrome(info, i, syn_p);
> + }
> +
> + ecc_calc += info->bch_type ? BCH8_SIZE : BCH4_SIZE;
> + syn_p += OOB_SECTOR_SIZE;
> + }
> +
> + elm_start_processing(info, err_vec);
> +
> + /*
> + * In case of error reported, wait for ELM module to finish
> + * locating error correction
> + */
> + wait_for_completion(&info->elm_completion);
> +
> + /* disable page mode interrupt */
> + reg_val = elm_read_reg(info->elm_base + ELM_IRQENABLE);
> + elm_write_reg(info->elm_base + ELM_IRQENABLE,
> + reg_val & ~INTR_EN_PAGE_MASK);
> + elm_error_correction(info, err_vec);
> +}
> +EXPORT_SYMBOL(elm_decode_bch_error_page);
> +
> +static irqreturn_t elm_isr(int this_irq, void *dev_id)
> +{
> + u32 reg_val;
> + struct elm_info *info = dev_id;
> +
> + reg_val = elm_read_reg(info->elm_base + ELM_IRQSTATUS);
> +
> + /* all error vectors processed */
> + if (reg_val & INTR_STATUS_PAGE_VALID) {
> + elm_write_reg(info->elm_base + ELM_IRQSTATUS,
> + reg_val & INTR_STATUS_PAGE_VALID);
> + complete(&info->elm_completion);
> + return IRQ_HANDLED;
> + }
> +
> + return IRQ_NONE;
> +}
> +
> +struct device *elm_request(enum bch_ecc bch_type)
> +{
> + struct elm_info *info;
> +
> + list_for_each_entry(info, &elm_devices, list) {
> + if (info && info->dev) {
> + info->bch_type = bch_type;
> + elm_config(info);
> + return info->dev;
> + }
> + }
> +
> + return NULL;
> +}
> +EXPORT_SYMBOL(elm_request);
> +
> +static int __devinit elm_probe(struct platform_device *pdev)
> +{
> + int ret = 0;
> + struct resource *res, *irq;
> + struct elm_info *info;
> +
> + info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
> + if (!info) {
> + dev_err(&pdev->dev, "failed to allocate memory\n");
> + return -ENOMEM;
> + }
> +
> + info->dev = &pdev->dev;
> +
> + irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
> + if (!irq) {
> + dev_err(&pdev->dev, "no irq resource defined\n");
> + return -ENODEV;
> + }
> +
> + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> + if (!res) {
> + dev_err(&pdev->dev, "no memory resource defined\n");
> + return -ENODEV;
> + }
> +
> +
> + info->elm_base = devm_request_and_ioremap(&pdev->dev, res);
> + if (!info->elm_base)
> + return -EADDRNOTAVAIL;
> +
> +
> + ret = devm_request_irq(&pdev->dev, irq->start, elm_isr, 0,
> + pdev->name, info);
> + if (ret) {
> + dev_err(&pdev->dev, "failure requesting irq %i\n", irq->start);
> + return ret;
> + }
> +
> + pm_runtime_enable(&pdev->dev);
> + if (pm_runtime_get_sync(&pdev->dev)) {
> + ret = -EINVAL;
> + pm_runtime_disable(&pdev->dev);
> + dev_err(&pdev->dev, "can't enable clock\n");
> + return ret;
> + }
> +
> + init_completion(&info->elm_completion);
> + INIT_LIST_HEAD(&info->list);
> + list_add(&info->list, &elm_devices);
> + platform_set_drvdata(pdev, info);
> + return ret;
> +}
> +
> +static int __devexit elm_remove(struct platform_device *pdev)
> +{
> + pm_runtime_put_sync(&pdev->dev);
> + pm_runtime_disable(&pdev->dev);
> + platform_set_drvdata(pdev, NULL);
> + return 0;
> +}
> +
> +
> +#ifdef CONFIG_OF
> +static const struct of_device_id elm_of_match[] = {
> + { .compatible = "ti,elm" },
> + {},
> +};
> +MODULE_DEVICE_TABLE(of, elm_of_match);
> +#endif
> +
> +static struct platform_driver elm_driver = {
> + .driver = {
> + .name = "elm",
> + .of_match_table = of_match_ptr(elm_of_match),
> + .owner = THIS_MODULE,
> + },
> + .probe = elm_probe,
> + .remove = __devexit_p(elm_remove),
> +};
> +
> +module_platform_driver(elm_driver);
> +
> +MODULE_DESCRIPTION("ELM driver for BCH error correction");
> +MODULE_AUTHOR("Texas Instruments");
> +MODULE_ALIAS("platform: elm");
> +MODULE_LICENSE("GPL v2");
> diff --git a/include/linux/platform_data/elm.h b/include/linux/platform_data/elm.h
> new file mode 100644
> index 0000000..eb53163
> --- /dev/null
> +++ b/include/linux/platform_data/elm.h
> @@ -0,0 +1,60 @@
> +/*
> + * BCH Error Location Module
> + *
> + * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.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.
> + *
> + */
> +
> +#ifndef __ELM_H
> +#define __ELM_H
> +
> +enum bch_ecc {
> + BCH4_ECC = 0,
> + BCH8_ECC,
> + BCH16_ECC,
It probably makes more sense to not provide the enum value for BCH16 as
you don't support it.
> +};
> +
> +/* ELM support 8 error syndrome process */
> +#define ERROR_VECTOR_MAX 8
> +#define OOB_SECTOR_SIZE 16
> +
> +#define BCH_MAX_ECC_BYTES_PER_SECTOR (OOB_SECTOR_SIZE * ERROR_VECTOR_MAX)
> +
> +#define BCH8_ECC_OOB_BYTES 13
> +/* RBL requires 14 byte even though BCH8 uses only 13 byte */
> +#define BCH8_SIZE (BCH8_ECC_OOB_BYTES + 1)
> +#define BCH4_SIZE 7
> +
> +#define BCH8_SYNDROME_SIZE 4 /* 13 bytes of ecc */
> +#define BCH4_SYNDROME_SIZE 2 /* 7 bytes of ecc */
> +
> +/**
> + * struct elm_errorvec - error vector for elm
> + * @error_reported: set true for vectors error is reported
> + *
> + * @error_count: number of correctable errors in the sector
> + * @error_uncorrectable: number of uncorrectable errors
> + * @error_loc: buffer for error location
> + *
> + */
> +struct elm_errorvec {
> + bool error_reported;
> + int error_count;
> + int error_uncorrectable;
> + int error_loc[ERROR_VECTOR_MAX];
> +};
> +
> +void elm_decode_bch_error_page(struct device *dev, u8 *ecc_calc,
> + struct elm_errorvec *err_vec);
> +struct device *elm_request(enum bch_ecc bch_type);
> +#endif /* __ELM_H */
> --
> 1.7.0.4
> ______________________________________________________
> Linux MTD discussion mailing list
> http://lists.infradead.org/mailman/listinfo/linux-mtd/
--
Bye, Peter Korsgaard
^ permalink raw reply
* [PATCH] gpio: clps711x: localise <mach/gpio.h> header
From: Linus Walleij @ 2012-10-15 19:40 UTC (permalink / raw)
To: linux-arm-kernel
The commit adding the CLPS711x driver also added <mach/gpio.h>
to the CLPS711x, and we want to get rid of all <mach/*>
headers for the future. It turns out that the one macro defined
in the file was only used in the GPIO driver itself, so just
delete it and copy the macro into the driver.
Cc: Alexander Shiyan <shc_work@mail.ru>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Russell King <rmk+kernel@arm.linux.org.uk>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
arch/arm/mach-clps711x/include/mach/gpio.h | 13 -------------
drivers/gpio/gpio-clps711x.c | 1 +
2 files changed, 1 insertion(+), 13 deletions(-)
delete mode 100644 arch/arm/mach-clps711x/include/mach/gpio.h
diff --git a/arch/arm/mach-clps711x/include/mach/gpio.h b/arch/arm/mach-clps711x/include/mach/gpio.h
deleted file mode 100644
index 8ac6889..0000000
--- a/arch/arm/mach-clps711x/include/mach/gpio.h
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * This file contains the CLPS711X GPIO definitions.
- *
- * Copyright (C) 2012 Alexander Shiyan <shc_work@mail.ru>
- *
- * 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.
- */
-
-/* Simple helper for convert port & pin to GPIO number */
-#define CLPS711X_GPIO(port, bit) ((port) * 8 + (bit))
diff --git a/drivers/gpio/gpio-clps711x.c b/drivers/gpio/gpio-clps711x.c
index ea21822..604b8ba 100644
--- a/drivers/gpio/gpio-clps711x.c
+++ b/drivers/gpio/gpio-clps711x.c
@@ -20,6 +20,7 @@
#define CLPS711X_GPIO_PORTS 5
#define CLPS711X_GPIO_NAME "gpio-clps711x"
+#define CLPS711X_GPIO(port, bit) ((port) * 8 + (bit))
struct clps711x_gpio {
struct gpio_chip chip[CLPS711X_GPIO_PORTS];
--
1.7.11.7
^ permalink raw reply related
* [PATCH 2/4] ARM: kirkwood: DT board setup for Network Space v2 and parents
From: Simon Guinot @ 2012-10-15 19:36 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1350315295-14567-3-git-send-email-simon.guinot@sequanux.org>
On Mon, Oct 15, 2012 at 05:34:53PM +0200, Simon Guinot wrote:
> This patch adds DT board setup for LaCie Network Space v2 and parents,
> based on the Marvell Kirkwood 6281 SoC. This includes Network Space v2
> (Max) and Internet Space v2.
>
> Signed-off-by: Simon Guinot <simon.guinot@sequanux.org>
> ---
It is not mentioned in the title but this patch is a v2. Here are the
differences with v1:
- Rebased against Linux 3.7-rc1.
- Add missing Kconfig options MACH_INETSPACE_V2_DT and
MACH_NETSPACE_MAX_V2_DT.
- Use ns2-leds DT binding.
- Move gpio-leds definition out from kirkwood-ns2-common.dtsi. The ns2
lite board (patch 3/4) uses a different configuration for GPIO LEDs.
> arch/arm/boot/dts/Makefile | 3 +
> arch/arm/boot/dts/kirkwood-is2.dts | 30 ++++++++++
> arch/arm/boot/dts/kirkwood-ns2-common.dtsi | 63 +++++++++++++++++++++
> arch/arm/boot/dts/kirkwood-ns2.dts | 30 ++++++++++
> arch/arm/boot/dts/kirkwood-ns2max.dts | 49 ++++++++++++++++
> arch/arm/mach-kirkwood/Kconfig | 21 +++++++
> arch/arm/mach-kirkwood/Makefile | 3 +
> arch/arm/mach-kirkwood/board-dt.c | 8 +++
> arch/arm/mach-kirkwood/board-ns2.c | 83 ++++++++++++++++++++++++++++
> arch/arm/mach-kirkwood/common.h | 8 +++
> drivers/leds/Kconfig | 4 +-
> 11 files changed, 301 insertions(+), 1 deletion(-)
> create mode 100644 arch/arm/boot/dts/kirkwood-is2.dts
> create mode 100644 arch/arm/boot/dts/kirkwood-ns2-common.dtsi
> create mode 100644 arch/arm/boot/dts/kirkwood-ns2.dts
> create mode 100644 arch/arm/boot/dts/kirkwood-ns2max.dts
> create mode 100644 arch/arm/mach-kirkwood/board-ns2.c
>
> diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
> index c1ce813..e6201b6 100644
> --- a/arch/arm/boot/dts/Makefile
> +++ b/arch/arm/boot/dts/Makefile
> @@ -34,9 +34,12 @@ dtb-$(CONFIG_ARCH_KIRKWOOD) += kirkwood-dns320.dtb \
> kirkwood-ib62x0.dtb \
> kirkwood-iconnect.dtb \
> kirkwood-iomega_ix2_200.dtb \
> + kirkwood-is2.dtb \
> kirkwood-km_kirkwood.dtb \
> kirkwood-lschlv2.dtb \
> kirkwood-lsxhl.dtb \
> + kirkwood-ns2.dtb \
> + kirkwood-ns2max.dtb \
> kirkwood-ts219-6281.dtb \
> kirkwood-ts219-6282.dtb
> dtb-$(CONFIG_ARCH_MSM) += msm8660-surf.dtb \
> diff --git a/arch/arm/boot/dts/kirkwood-is2.dts b/arch/arm/boot/dts/kirkwood-is2.dts
> new file mode 100644
> index 0000000..7bc4677
> --- /dev/null
> +++ b/arch/arm/boot/dts/kirkwood-is2.dts
> @@ -0,0 +1,30 @@
> +/dts-v1/;
> +
> +/include/ "kirkwood-ns2-common.dtsi"
> +
> +/ {
> + model = "LaCie Internet Space v2";
> + compatible = "lacie,inetspace_v2", "marvell,kirkwood-88f6281", "marvell,kirkwood";
> +
> + memory {
> + device_type = "memory";
> + reg = <0x00000000 0x8000000>;
> + };
> +
> + ocp at f1000000 {
> + sata at 80000 {
> + status = "okay";
> + nr-ports = <1>;
> + };
> + };
> +
> + ns2-leds {
> + compatible = "ns2-leds";
> +
> + blue-sata {
> + label = "ns2:blue:sata";
> + slow-gpio = <&gpio0 29 0>;
> + cmd-gpio = <&gpio0 30 0>;
> + };
> + };
> +};
> diff --git a/arch/arm/boot/dts/kirkwood-ns2-common.dtsi b/arch/arm/boot/dts/kirkwood-ns2-common.dtsi
> new file mode 100644
> index 0000000..9bc6785
> --- /dev/null
> +++ b/arch/arm/boot/dts/kirkwood-ns2-common.dtsi
> @@ -0,0 +1,63 @@
> +/include/ "kirkwood.dtsi"
> +
> +/ {
> + chosen {
> + bootargs = "console=ttyS0,115200n8";
> + };
> +
> + ocp at f1000000 {
> + serial at 12000 {
> + clock-frequency = <166666667>;
> + status = "okay";
> + };
> +
> + spi at 10600 {
> + status = "okay";
> +
> + flash at 0 {
> + #address-cells = <1>;
> + #size-cells = <1>;
> + compatible = "mx25l4005a";
> + reg = <0>;
> + spi-max-frequency = <20000000>;
> + mode = <0>;
> +
> + partition at 0 {
> + reg = <0x0 0x80000>;
> + label = "u-boot";
> + };
> + };
> + };
> +
> + i2c at 11000 {
> + status = "okay";
> +
> + eeprom at 50 {
> + compatible = "at,24c04";
> + pagesize = <16>;
> + reg = <0x50>;
> + };
> + };
> + };
> +
> + gpio_keys {
> + compatible = "gpio-keys";
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + button at 1 {
> + label = "Power push button";
> + linux,code = <116>;
> + gpios = <&gpio1 0 0>;
> + };
> + };
> +
> + gpio-leds {
> + compatible = "gpio-leds";
> +
> + red-fail {
> + label = "ns2:red:fail";
> + gpios = <&gpio0 12 0>;
> + };
> + };
> +};
> diff --git a/arch/arm/boot/dts/kirkwood-ns2.dts b/arch/arm/boot/dts/kirkwood-ns2.dts
> new file mode 100644
> index 0000000..d018213
> --- /dev/null
> +++ b/arch/arm/boot/dts/kirkwood-ns2.dts
> @@ -0,0 +1,30 @@
> +/dts-v1/;
> +
> +/include/ "kirkwood-ns2-common.dtsi"
> +
> +/ {
> + model = "LaCie Network Space v2";
> + compatible = "lacie,netspace_v2", "marvell,kirkwood-88f6281", "marvell,kirkwood";
> +
> + memory {
> + device_type = "memory";
> + reg = <0x00000000 0x10000000>;
> + };
> +
> + ocp at f1000000 {
> + sata at 80000 {
> + status = "okay";
> + nr-ports = <1>;
> + };
> + };
> +
> + ns2-leds {
> + compatible = "ns2-leds";
> +
> + blue-sata {
> + label = "ns2:blue:sata";
> + slow-gpio = <&gpio0 29 0>;
> + cmd-gpio = <&gpio0 30 0>;
> + };
> + };
> +};
> diff --git a/arch/arm/boot/dts/kirkwood-ns2max.dts b/arch/arm/boot/dts/kirkwood-ns2max.dts
> new file mode 100644
> index 0000000..82156e2
> --- /dev/null
> +++ b/arch/arm/boot/dts/kirkwood-ns2max.dts
> @@ -0,0 +1,49 @@
> +/dts-v1/;
> +
> +/include/ "kirkwood-ns2-common.dtsi"
> +
> +/ {
> + model = "LaCie Network Space Max v2";
> + compatible = "lacie,netspace_max_v2", "marvell,kirkwood-88f6281", "marvell,kirkwood";
> +
> + memory {
> + device_type = "memory";
> + reg = <0x00000000 0x10000000>;
> + };
> +
> + ocp at f1000000 {
> + sata at 80000 {
> + status = "okay";
> + nr-ports = <2>;
> + };
> + };
> +
> + gpio_fan {
> + compatible = "gpio-fan";
> + gpios = <&gpio0 22 1
> + &gpio0 7 1
> + &gpio1 1 1
> + &gpio0 23 1>;
> + gpio-fan,speed-map =
> + < 0 0
> + 1500 15
> + 1700 14
> + 1800 13
> + 2100 12
> + 3100 11
> + 3300 10
> + 4300 9
> + 5500 8>;
> + alarm-gpios = <&gpio0 25 1>;
> + };
> +
> + ns2-leds {
> + compatible = "ns2-leds";
> +
> + blue-sata {
> + label = "ns2:blue:sata";
> + slow-gpio = <&gpio0 29 0>;
> + cmd-gpio = <&gpio0 30 0>;
> + };
> + };
> +};
> diff --git a/arch/arm/mach-kirkwood/Kconfig b/arch/arm/mach-kirkwood/Kconfig
> index 50bca50..847e0c2 100644
> --- a/arch/arm/mach-kirkwood/Kconfig
> +++ b/arch/arm/mach-kirkwood/Kconfig
> @@ -130,6 +130,27 @@ config MACH_KM_KIRKWOOD_DT
> Say 'Y' here if you want your kernel to support the
> Keymile Kirkwood Reference Desgin, using Flattened Device Tree.
>
> +config MACH_INETSPACE_V2_DT
> + bool "LaCie Internet Space v2 NAS (Flattened Device Tree)"
> + select ARCH_KIRKWOOD_DT
> + help
> + Say 'Y' here if you want your kernel to support the LaCie
> + Internet Space v2 NAS, using Flattened Device Tree.
> +
> +config MACH_NETSPACE_V2_DT
> + bool "LaCie Network Space v2 NAS (Flattened Device Tree)"
> + select ARCH_KIRKWOOD_DT
> + help
> + Say 'Y' here if you want your kernel to support the LaCie
> + Network Space v2 NAS, using Flattened Device Tree.
> +
> +config MACH_NETSPACE_MAX_V2_DT
> + bool "LaCie Network Space Max v2 NAS (Flattened Device Tree)"
> + select ARCH_KIRKWOOD_DT
> + help
> + Say 'Y' here if you want your kernel to support the LaCie
> + Network Space Max v2 NAS, using Flattened Device Tree.
> +
> config MACH_TS219
> bool "QNAP TS-110, TS-119, TS-119P+, TS-210, TS-219, TS-219P and TS-219P+ Turbo NAS"
> help
> diff --git a/arch/arm/mach-kirkwood/Makefile b/arch/arm/mach-kirkwood/Makefile
> index 294779f..1f63d80 100644
> --- a/arch/arm/mach-kirkwood/Makefile
> +++ b/arch/arm/mach-kirkwood/Makefile
> @@ -31,3 +31,6 @@ obj-$(CONFIG_MACH_GOFLEXNET_DT) += board-goflexnet.o
> obj-$(CONFIG_MACH_LSXL_DT) += board-lsxl.o
> obj-$(CONFIG_MACH_IOMEGA_IX2_200_DT) += board-iomega_ix2_200.o
> obj-$(CONFIG_MACH_KM_KIRKWOOD_DT) += board-km_kirkwood.o
> +obj-$(CONFIG_MACH_INETSPACE_V2_DT) += board-ns2.o
> +obj-$(CONFIG_MACH_NETSPACE_V2_DT) += board-ns2.o
> +obj-$(CONFIG_MACH_NETSPACE_MAX_V2_DT) += board-ns2.o
> diff --git a/arch/arm/mach-kirkwood/board-dt.c b/arch/arm/mach-kirkwood/board-dt.c
> index 70c5a28..b3e0519 100644
> --- a/arch/arm/mach-kirkwood/board-dt.c
> +++ b/arch/arm/mach-kirkwood/board-dt.c
> @@ -96,6 +96,11 @@ static void __init kirkwood_dt_init(void)
> if (of_machine_is_compatible("keymile,km_kirkwood"))
> km_kirkwood_init();
>
> + if (of_machine_is_compatible("lacie,inetspace_v2") ||
> + of_machine_is_compatible("lacie,netspace_v2") ||
> + of_machine_is_compatible("lacie,netspace_max_v2"))
> + ns2_init();
> +
> of_platform_populate(NULL, kirkwood_dt_match_table,
> kirkwood_auxdata_lookup, NULL);
> }
> @@ -112,6 +117,9 @@ static const char *kirkwood_dt_board_compat[] = {
> "buffalo,lsxl",
> "iom,ix2-200",
> "keymile,km_kirkwood",
> + "lacie,inetspace_v2",
> + "lacie,netspace_max_v2",
> + "lacie,netspace_v2",
> NULL
> };
>
> diff --git a/arch/arm/mach-kirkwood/board-ns2.c b/arch/arm/mach-kirkwood/board-ns2.c
> new file mode 100644
> index 0000000..b36c55c
> --- /dev/null
> +++ b/arch/arm/mach-kirkwood/board-ns2.c
> @@ -0,0 +1,83 @@
> +/*
> + * Copyright 2012 (C), Simon Guinot <simon.guinot@sequanux.org>
> + *
> + * arch/arm/mach-kirkwood/board-ns2.c
> + *
> + * LaCie Network Space v2 board (and parents) initialization for drivers
> + * not converted to flattened device tree yet.
> + *
> + * This file is licensed under the terms of the GNU General Public
> + * License version 2. This program is licensed "as is" without any
> + * warranty of any kind, whether express or implied.
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/init.h>
> +#include <linux/platform_device.h>
> +#include <linux/mv643xx_eth.h>
> +#include <linux/gpio.h>
> +#include "common.h"
> +#include "mpp.h"
> +
> +static struct mv643xx_eth_platform_data ns2_ge00_data = {
> + .phy_addr = MV643XX_ETH_PHY_ADDR(8),
> +};
> +
> +static unsigned int ns2_mpp_config[] __initdata = {
> + MPP0_SPI_SCn,
> + MPP1_SPI_MOSI,
> + MPP2_SPI_SCK,
> + MPP3_SPI_MISO,
> + MPP4_NF_IO6,
> + MPP5_NF_IO7,
> + MPP6_SYSRST_OUTn,
> + MPP7_GPO, /* Fan speed (bit 1) */
> + MPP8_TW0_SDA,
> + MPP9_TW0_SCK,
> + MPP10_UART0_TXD,
> + MPP11_UART0_RXD,
> + MPP12_GPO, /* Red led */
> + MPP14_GPIO, /* USB fuse */
> + MPP16_GPIO, /* SATA 0 power */
> + MPP17_GPIO, /* SATA 1 power */
> + MPP18_NF_IO0,
> + MPP19_NF_IO1,
> + MPP20_SATA1_ACTn,
> + MPP21_SATA0_ACTn,
> + MPP22_GPIO, /* Fan speed (bit 0) */
> + MPP23_GPIO, /* Fan power */
> + MPP24_GPIO, /* USB mode select */
> + MPP25_GPIO, /* Fan rotation fail */
> + MPP26_GPIO, /* USB device vbus */
> + MPP28_GPIO, /* USB enable host vbus */
> + MPP29_GPIO, /* Blue led (slow register) */
> + MPP30_GPIO, /* Blue led (command register) */
> + MPP31_GPIO, /* Board power off */
> + MPP32_GPIO, /* Power button (0 = Released, 1 = Pushed) */
> + MPP33_GPO, /* Fan speed (bit 2) */
> + 0
> +};
> +
> +#define NS2_GPIO_POWER_OFF 31
> +
> +static void ns2_power_off(void)
> +{
> + gpio_set_value(NS2_GPIO_POWER_OFF, 1);
> +}
> +
> +void __init ns2_init(void)
> +{
> + /*
> + * Basic setup. Needs to be called early.
> + */
> + kirkwood_mpp_conf(ns2_mpp_config);
> +
> + kirkwood_ehci_init();
> + kirkwood_ge00_init(&ns2_ge00_data);
> +
> + if (gpio_request(NS2_GPIO_POWER_OFF, "power-off") == 0 &&
> + gpio_direction_output(NS2_GPIO_POWER_OFF, 0) == 0)
> + pm_power_off = ns2_power_off;
> + else
> + pr_err("ns2: failed to configure power-off GPIO\n");
> +}
> diff --git a/arch/arm/mach-kirkwood/common.h b/arch/arm/mach-kirkwood/common.h
> index bcffd7c..2f75f3f 100644
> --- a/arch/arm/mach-kirkwood/common.h
> +++ b/arch/arm/mach-kirkwood/common.h
> @@ -112,6 +112,14 @@ void km_kirkwood_init(void);
> static inline void km_kirkwood_init(void) {};
> #endif
>
> +#if defined(CONFIG_MACH_INETSPACE_V2_DT) || \
> + defined(CONFIG_MACH_NETSPACE_V2_DT) || \
> + defined(CONFIG_MACH_NETSPACE_MAX_V2_DT)
> +void ns2_init(void);
> +#else
> +static inline void ns2_init(void) {};
> +#endif
> +
> /* early init functions not converted to fdt yet */
> char *kirkwood_id(void);
> void kirkwood_l2_init(void);
> diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
> index f508def..e455c08 100644
> --- a/drivers/leds/Kconfig
> +++ b/drivers/leds/Kconfig
> @@ -379,7 +379,9 @@ config LEDS_NS2
> tristate "LED support for Network Space v2 GPIO LEDs"
> depends on LEDS_CLASS
> depends on MACH_NETSPACE_V2 || MACH_INETSPACE_V2 || \
> - MACH_NETSPACE_MAX_V2 || MACH_D2NET_V2
> + MACH_NETSPACE_MAX_V2 || MACH_D2NET_V2 || \
> + MACH_NETSPACE_V2_DT || MACH_INETSPACE_V2_DT || \
> + MACH_NETSPACE_MAX_V2_DT
> default y
> help
> This option enable support for the dual-GPIO LED found on the
> --
> 1.7.10
>
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 198 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20121015/4bc4b331/attachment-0001.sig>
^ permalink raw reply
* [PATCH v4] GPIO: Add support for GPIO on CLPS711X-target platform
From: Linus Walleij @ 2012-10-15 19:26 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1349798756-24777-1-git-send-email-shc_work@mail.ru>
On Tue, Oct 9, 2012 at 6:05 PM, Alexander Shiyan <shc_work@mail.ru> wrote:
> The CLPS711X CPUs provide some GPIOs for use in the system. This
> driver provides support for these via gpiolib. Due to platform
> limitations, driver does not support interrupts, only inputs and
> outputs.
>
> Signed-off-by: Alexander Shiyan <shc_work@mail.ru>
Applied with Russell's ACK.
Thanks!
Linus Walleij
^ permalink raw reply
* [PATCH 5/5] arm/dts: am33xx: Add cpsw and mdio module nodes for AM33XX
From: Richard Cochran @ 2012-10-15 19:16 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1350327320.git.richardcochran@gmail.com>
From: Mugunthan V N <mugunthanvnm@ti.com>
Add CPSW and MDIO related device tree data for AM33XX.
Also enable them into board/evm dts files by providing
respective phy-id.
Signed-off-by: Mugunthan V N <mugunthanvnm@ti.com>
Signed-off-by: Vaibhav Hiremath <hvaibhav@ti.com>
---
arch/arm/boot/dts/am335x-bone.dts | 8 ++++++
arch/arm/boot/dts/am335x-evm.dts | 8 ++++++
arch/arm/boot/dts/am33xx.dtsi | 50 +++++++++++++++++++++++++++++++++++++
3 files changed, 66 insertions(+), 0 deletions(-)
diff --git a/arch/arm/boot/dts/am335x-bone.dts b/arch/arm/boot/dts/am335x-bone.dts
index c634f87..e233cfa 100644
--- a/arch/arm/boot/dts/am335x-bone.dts
+++ b/arch/arm/boot/dts/am335x-bone.dts
@@ -78,3 +78,11 @@
};
};
};
+
+&cpsw_emac0 {
+ phy_id = "4a101000.mdio:00";
+};
+
+&cpsw_emac1 {
+ phy_id = "4a101000.mdio:01";
+};
diff --git a/arch/arm/boot/dts/am335x-evm.dts b/arch/arm/boot/dts/am335x-evm.dts
index 185d632..415c3b3 100644
--- a/arch/arm/boot/dts/am335x-evm.dts
+++ b/arch/arm/boot/dts/am335x-evm.dts
@@ -118,3 +118,11 @@
};
};
};
+
+&cpsw_emac0 {
+ phy_id = "4a101000.mdio:00";
+};
+
+&cpsw_emac1 {
+ phy_id = "4a101000.mdio:01";
+};
diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
index bb31bff..f6bea04 100644
--- a/arch/arm/boot/dts/am33xx.dtsi
+++ b/arch/arm/boot/dts/am33xx.dtsi
@@ -210,5 +210,55 @@
interrupt-parent = <&intc>;
interrupts = <91>;
};
+
+ mac: ethernet at 4A100000 {
+ compatible = "ti,cpsw";
+ ti,hwmods = "cpgmac0";
+ cpdma_channels = <8>;
+ host_port_no = <0>;
+ cpdma_reg_ofs = <0x800>;
+ cpdma_sram_ofs = <0xa00>;
+ ale_reg_ofs = <0xd00>;
+ ale_entries = <1024>;
+ host_port_reg_ofs = <0x108>;
+ hw_stats_reg_ofs = <0x900>;
+ bd_ram_ofs = <0x2000>;
+ bd_ram_size = <0x2000>;
+ no_bd_ram = <0>;
+ rx_descs = <64>;
+ mac_control = <0x20>;
+ slaves = <2>;
+ reg = <0x4a100000 0x800
+ 0x4a101200 0x100
+ 0x4a101000 0x100>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ interrupt-parent = <&intc>;
+ /* c0_rx_thresh_pend c0_rx_pend c0_tx_pend c0_misc_pend*/
+ interrupts = <40 41 42 43>;
+ ranges;
+ cpsw_emac0: slave at 0 {
+ slave_reg_ofs = <0x208>;
+ sliver_reg_ofs = <0xd80>;
+ /* Filled in by U-Boot */
+ mac-address = [ 00 00 00 00 00 00 ];
+ };
+ cpsw_emac1: slave at 1 {
+ slave_reg_ofs = <0x308>;
+ sliver_reg_ofs = <0xdc0>;
+ /* Filled in by U-Boot */
+ mac-address = [ 00 00 00 00 00 00 ];
+ };
+
+ davinci_mdio: mdio at 4a101000 {
+ compatible = "ti,davinci_mdio";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ ti,hwmods = "davinci_mdio";
+ bus_freq = <1000000>;
+ reg = <0x4a101000 0x100>;
+ };
+
+ };
};
};
--
1.7.2.5
^ permalink raw reply related
* [PATCH 4/5] net: cpsw: Add parent<->child relation support between cpsw and mdio
From: Richard Cochran @ 2012-10-15 19:16 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1350327320.git.richardcochran@gmail.com>
From: Vaibhav Hiremath <hvaibhav@ti.com>
CPGMAC SubSystem consist of various sub-modules, like, mdio, cpdma,
cpsw, etc... These sub-modules are also used in some of Davinci family
of devices. Now based on requirement, use-case and available technology
nodes the integration of these sub-modules varies across devices.
So coming back to Linux net driver, currently separate and independent
platform devices & drivers for CPSW and MDIO is implemented. In case of
Davinci they both has separate control, from resources perspective,
like clock.
In case of AM33XX, the resources are shared and only one register
bit-field is provided to control module/clock enable/disable, makes it
difficult to handle common resource.
So the solution here implemented in this patch is,
Create parent<->child relationship between both the drivers, making
CPSW as a parent and MDIO as its child and enumerate all the child nodes
under cpsw module.
Both the drivers will function exactly the way it was operating before,
including runtime-pm functionality. No change is required in MDIO driver
(for that matter to any child driver).
As this is only supported during DT boot, the parent<->child relationship
is created and populated in DT execution flow. The only required change
is inside DTS file, making MDIO as a child to CPSW node.
Signed-off-by: Vaibhav Hiremath <hvaibhav@ti.com>
Cc: Mugunthan V N <mugunthanvnm@ti.com>
---
drivers/net/ethernet/ti/cpsw.c | 16 ++++++++++++++--
1 files changed, 14 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index df55e24..fb1a692 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -827,7 +827,7 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
}
data->mac_control = prop;
- for_each_child_of_node(node, slave_node) {
+ for_each_node_by_name(slave_node, "slave") {
struct cpsw_slave_data *slave_data = data->slave_data + i;
const char *phy_id = NULL;
const void *mac_addr = NULL;
@@ -862,6 +862,14 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
i++;
}
+ /*
+ * Populate all the child nodes here...
+ */
+ ret = of_platform_populate(node, NULL, NULL, &pdev->dev);
+ /* We do not want to force this, as in some cases may not have child */
+ if (ret)
+ pr_warn("Doesn't have any child node\n");
+
return 0;
error_ret:
@@ -895,6 +903,11 @@ static int __devinit cpsw_probe(struct platform_device *pdev)
priv->msg_enable = netif_msg_init(debug_level, CPSW_DEBUG);
priv->rx_packet_max = max(rx_packet_max, 128);
+ /*
+ * This may be required here for child devices.
+ */
+ pm_runtime_enable(&pdev->dev);
+
if (cpsw_probe_dt(&priv->data, pdev)) {
pr_err("cpsw: platform data missing\n");
ret = -ENODEV;
@@ -921,7 +934,6 @@ static int __devinit cpsw_probe(struct platform_device *pdev)
for (i = 0; i < data->slaves; i++)
priv->slaves[i].slave_num = i;
- pm_runtime_enable(&pdev->dev);
priv->clk = clk_get(&pdev->dev, "fck");
if (IS_ERR(priv->clk)) {
dev_err(&pdev->dev, "fck is not found\n");
--
1.7.2.5
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox