* [v3 7/9] ARM: dt: tegra114: Add new board, Dalmore
From: Hiroshi Doyu @ 2013-01-15 8:14 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1358237598-32413-1-git-send-email-hdoyu@nvidia.com>
Add a new evaluation board, Dalmore for Tegra 114 family.
Signed-off-by: Hiroshi Doyu <hdoyu@nvidia.com>
---
arch/arm/boot/dts/Makefile | 3 ++-
arch/arm/boot/dts/tegra114-dalmore.dts | 21 +++++++++++++++++++++
2 files changed, 23 insertions(+), 1 deletion(-)
create mode 100644 arch/arm/boot/dts/tegra114-dalmore.dts
diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index b511bc1..04e43d2 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -147,7 +147,8 @@ dtb-$(CONFIG_ARCH_TEGRA) += tegra20-harmony.dtb \
tegra20-whistler.dtb \
tegra30-cardhu-a02.dtb \
tegra30-cardhu-a04.dtb \
- tegra30-beaver.dtb
+ tegra30-beaver.dtb \
+ tegra114-dalmore.dtb
dtb-$(CONFIG_ARCH_VEXPRESS) += vexpress-v2p-ca5s.dtb \
vexpress-v2p-ca9.dtb \
vexpress-v2p-ca15-tc1.dtb \
diff --git a/arch/arm/boot/dts/tegra114-dalmore.dts b/arch/arm/boot/dts/tegra114-dalmore.dts
new file mode 100644
index 0000000..a30aca6
--- /dev/null
+++ b/arch/arm/boot/dts/tegra114-dalmore.dts
@@ -0,0 +1,21 @@
+/dts-v1/;
+
+/include/ "tegra114.dtsi"
+
+/ {
+ model = "NVIDIA Tegra114 Dalmore evaluation board";
+ compatible = "nvidia,dalmore", "nvidia,tegra114";
+
+ memory {
+ reg = <0x80000000 0x40000000>;
+ };
+
+ serial at 70006300 {
+ status = "okay";
+ clock-frequency = <408000000>;
+ };
+
+ pmc {
+ nvidia,invert-interrupt;
+ };
+};
--
1.7.9.5
^ permalink raw reply related
* [v3 6/9] ARM: dt: tegra114: Add new SoC base, Tegra 114 SoC
From: Hiroshi Doyu @ 2013-01-15 8:14 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1358237598-32413-1-git-send-email-hdoyu@nvidia.com>
Initial support for Tegra 114 SoC. This is expected to be included in
the board DTS files, Tegra 114 SoC based evaluation board family.
Signed-off-by: Hiroshi Doyu <hdoyu@nvidia.com>
---
arch/arm/boot/dts/tegra114.dtsi | 116 +++++++++++++++++++++++++++++++++++++++
1 file changed, 116 insertions(+)
create mode 100644 arch/arm/boot/dts/tegra114.dtsi
diff --git a/arch/arm/boot/dts/tegra114.dtsi b/arch/arm/boot/dts/tegra114.dtsi
new file mode 100644
index 0000000..175cbc3
--- /dev/null
+++ b/arch/arm/boot/dts/tegra114.dtsi
@@ -0,0 +1,116 @@
+/include/ "skeleton.dtsi"
+
+/ {
+ compatible = "nvidia,tegra114";
+ interrupt-parent = <&gic>;
+
+ gic: interrupt-controller {
+ compatible = "arm,cortex-a15-gic";
+ #interrupt-cells = <3>;
+ interrupt-controller;
+ reg = <0x50041000 0x1000>,
+ <0x50042000 0x1000>,
+ <0x50044000 0x2000>,
+ <0x50046000 0x2000>;
+ interrupts = <1 9 0xf04>;
+ };
+
+ timer at 60005000 {
+ compatible = "nvidia,tegra114-timer", "nvidia,tegra20-timer";
+ reg = <0x60005000 0x400>;
+ interrupts = <0 0 0x04
+ 0 1 0x04
+ 0 41 0x04
+ 0 42 0x04
+ 0 121 0x04
+ 0 122 0x04>;
+ };
+
+ serial at 70006000 {
+ compatible = "nvidia,tegra114-uart", "nvidia,tegra20-uart";
+ reg = <0x70006000 0x40>;
+ reg-shift = <2>;
+ interrupts = <0 36 0x04>;
+ status = "disabled";
+ };
+
+ serial at 70006040 {
+ compatible = "nvidia,tegra114-uart", "nvidia,tegra20-uart";
+ reg = <0x70006040 0x40>;
+ reg-shift = <2>;
+ interrupts = <0 37 0x04>;
+ status = "disabled";
+ };
+
+ serial at 70006200 {
+ compatible = "nvidia,tegra114-uart", "nvidia,tegra20-uart";
+ reg = <0x70006200 0x100>;
+ reg-shift = <2>;
+ interrupts = <0 46 0x04>;
+ status = "disabled";
+ };
+
+ serial at 70006300 {
+ compatible = "nvidia,tegra114-uart", "nvidia,tegra20-uart";
+ reg = <0x70006300 0x100>;
+ reg-shift = <2>;
+ interrupts = <0 90 0x04>;
+ status = "disabled";
+ };
+
+ serial at 70006400 {
+ compatible = "nvidia,tegra114-uart", "nvidia,tegra20-uart";
+ reg = <0x70006400 0x100>;
+ reg-shift = <2>;
+ interrupts = <0 91 0x04>;
+ status = "disabled";
+ };
+
+ rtc {
+ compatible = "nvidia,tegra114-rtc", "nvidia,tegra20-rtc";
+ reg = <0x7000e000 0x100>;
+ interrupts = <0 2 0x04>;
+ };
+
+ pmc {
+ compatible = "nvidia,tegra114-pmc", "nvidia,tegra20-pmc";
+ reg = <0x7000e400 0x400>;
+ };
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu at 0 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a15";
+ reg = <0>;
+ };
+
+ cpu at 1 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a15";
+ reg = <1>;
+ };
+
+ cpu at 2 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a15";
+ reg = <2>;
+ };
+
+ cpu at 3 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a15";
+ reg = <3>;
+ };
+ };
+
+ timer {
+ compatible = "arm,armv7-timer";
+ interrupts = <1 13 0xf08>,
+ <1 14 0xf08>,
+ <1 11 0xf08>,
+ <1 10 0xf08>;
+ };
+};
--
1.7.9.5
^ permalink raw reply related
* [v3 5/9] ARM: tegra: Skip scu_enable(scu_base) if not Cortex A9
From: Hiroshi Doyu @ 2013-01-15 8:14 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1358237598-32413-1-git-send-email-hdoyu@nvidia.com>
Skip scu_enable(scu_base) if CPU is not Cortex A9.
Signed-off-by: Hiroshi Doyu <hdoyu@nvidia.com>
---
arch/arm/mach-tegra/platsmp.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/arch/arm/mach-tegra/platsmp.c b/arch/arm/mach-tegra/platsmp.c
index 689ee4b..e329e93 100644
--- a/arch/arm/mach-tegra/platsmp.c
+++ b/arch/arm/mach-tegra/platsmp.c
@@ -38,7 +38,6 @@
extern void tegra_secondary_startup(void);
static cpumask_t tegra_cpu_init_mask;
-static void __iomem *scu_base = IO_ADDRESS(TEGRA_ARM_PERIF_BASE);
#define EVP_CPU_RESET_VECTOR \
(IO_ADDRESS(TEGRA_EXCEPTION_VECTORS_BASE) + 0x100)
@@ -184,10 +183,14 @@ static void __init tegra_smp_init_cpus(void)
static void __init tegra_smp_prepare_cpus(unsigned int max_cpus)
{
+ phys_addr_t base;
+
/* Always mark the boot CPU (CPU0) as initialized. */
cpumask_set_cpu(0, &tegra_cpu_init_mask);
- scu_enable(scu_base);
+ base = scu_get_base();
+ if (base)
+ scu_enable(IO_ADDRESS(base));
}
struct smp_operations tegra_smp_ops __initdata = {
--
1.7.9.5
^ permalink raw reply related
* [v3 4/9] ARM: Add API to detect SCU base address from CP15
From: Hiroshi Doyu @ 2013-01-15 8:14 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1358237598-32413-1-git-send-email-hdoyu@nvidia.com>
Add API to detect SCU base address from CP15.
Signed-off-by: Hiroshi Doyu <hdoyu@nvidia.com>
---
arch/arm/include/asm/smp_scu.h | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/arch/arm/include/asm/smp_scu.h b/arch/arm/include/asm/smp_scu.h
index 4eb6d00..f619eef 100644
--- a/arch/arm/include/asm/smp_scu.h
+++ b/arch/arm/include/asm/smp_scu.h
@@ -6,6 +6,23 @@
#define SCU_PM_POWEROFF 3
#ifndef __ASSEMBLER__
+
+#include <asm/cputype.h>
+
+static inline phys_addr_t scu_get_base(void)
+{
+ phys_addr_t pa;
+ unsigned long part_number = read_cpuid_part_number();
+
+ switch (part_number) {
+ case ARM_CPU_PART_CORTEX_A9:
+ /* Get SCU physical base */
+ asm("mrc p15, 4, %0, c15, c0, 0" : "=r" (pa));
+ return pa;
+ default:
+ return 0;
+ }
+}
unsigned int scu_get_core_count(void __iomem *);
void scu_enable(void __iomem *);
int scu_power_mode(void __iomem *, unsigned int);
--
1.7.9.5
^ permalink raw reply related
* [v3 3/9] ARM: tegra: Use DT /cpu node to detect number of CPU core
From: Hiroshi Doyu @ 2013-01-15 8:14 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1358237598-32413-1-git-send-email-hdoyu@nvidia.com>
SCU based detection only works with Cortex-A9 MP and it doesn't
support ones with multiple clusters. The only way to detect number of
CPU core correctly is with DT /cpu node.
Tegra SoCs decided to use DT detection as the only way and to not use
SCU based detection at all. Even if DT /cpu node based detection
fails, it continues with a single core
Signed-off-by: Hiroshi Doyu <hdoyu@nvidia.com>
---
Based on the discussion:
http://lists.infradead.org/pipermail/linux-arm-kernel/2013-January/140608.html
Signed-off-by: Hiroshi Doyu <hdoyu@nvidia.com>
---
arch/arm/mach-tegra/platsmp.c | 15 ---------------
1 file changed, 15 deletions(-)
diff --git a/arch/arm/mach-tegra/platsmp.c b/arch/arm/mach-tegra/platsmp.c
index 6867030..689ee4b 100644
--- a/arch/arm/mach-tegra/platsmp.c
+++ b/arch/arm/mach-tegra/platsmp.c
@@ -177,23 +177,8 @@ done:
return status;
}
-/*
- * Initialise the CPU possible map early - this describes the CPUs
- * which may be present or become present in the system.
- */
static void __init tegra_smp_init_cpus(void)
{
- unsigned int i, ncores = scu_get_core_count(scu_base);
-
- if (ncores > nr_cpu_ids) {
- pr_warn("SMP: %u cores greater than maximum (%u), clipping\n",
- ncores, nr_cpu_ids);
- ncores = nr_cpu_ids;
- }
-
- for (i = 0; i < ncores; i++)
- set_cpu_possible(i, true);
-
set_smp_cross_call(gic_raise_softirq);
}
--
1.7.9.5
^ permalink raw reply related
* [v3 2/9] HACK: ARM: tegra: Use CLK_IGNORE_UNUSED for Tegra 114 SoC
From: Hiroshi Doyu @ 2013-01-15 8:14 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1358237598-32413-1-git-send-email-hdoyu@nvidia.com>
Use CLK_IGNORE_UNUSED for the Tegra 114 SoC to ensure
clk_disable_unused() is not called. Otherwise the system will die,
because the usecount of the clocks is incorrect. This patch will be
reverted once the Tegra 114 clocks are implemented.
Signed-off-by: Hiroshi Doyu <hdoyu@nvidia.com>
---
NOTE: Will be updated once the latest ccf is merged.
---
arch/arm/mach-tegra/tegra30_clocks_data.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/arch/arm/mach-tegra/tegra30_clocks_data.c b/arch/arm/mach-tegra/tegra30_clocks_data.c
index 741d264..dba507c 100644
--- a/arch/arm/mach-tegra/tegra30_clocks_data.c
+++ b/arch/arm/mach-tegra/tegra30_clocks_data.c
@@ -1384,6 +1384,8 @@ static void tegra30_init_one_clock(struct clk *c)
if (!clk->lookup.dev_id && !clk->lookup.con_id)
clk->lookup.con_id = c->name;
clk->lookup.clk = c;
+ if (tegra_chip_id == TEGRA114) /* FIXME: Implement T114 clocks */
+ c->flags |= CLK_IGNORE_UNUSED;
clkdev_add(&clk->lookup);
tegra_clk_add(c);
}
--
1.7.9.5
^ permalink raw reply related
* [v3 1/9] ARM: tegra: fuse: Add chipid TEGRA114 0x35
From: Hiroshi Doyu @ 2013-01-15 8:13 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1358237598-32413-1-git-send-email-hdoyu@nvidia.com>
Add tegra_chip_id TEGRA114 0x35
Signed-off-by: Hiroshi Doyu <hdoyu@nvidia.com>
---
arch/arm/mach-tegra/fuse.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/arm/mach-tegra/fuse.h b/arch/arm/mach-tegra/fuse.h
index ff1383d..da78434 100644
--- a/arch/arm/mach-tegra/fuse.h
+++ b/arch/arm/mach-tegra/fuse.h
@@ -37,6 +37,7 @@ enum tegra_revision {
#define TEGRA20 0x20
#define TEGRA30 0x30
+#define TEGRA114 0x35
extern int tegra_sku_id;
extern int tegra_cpu_process_id;
--
1.7.9.5
^ permalink raw reply related
* [v3 0/9] ARM: Initial support for Tegra 114 SoC
From: Hiroshi Doyu @ 2013-01-15 8:13 UTC (permalink / raw)
To: linux-arm-kernel
Hi,
This patchset adds initial support for NVIDIA's new Tegra 114 SoC
(T114) based on the ARM Cortex-A15 MP. It has the minimal support to
allow the kernel to boot up into shell console. This can be used as a
basis for adding other device drivers for this SoC. Currently there
are 2 evaluation boards available, "Dalmore" and "Pluto".
For those who want to try:
$ make ARCH=arm tegra_defconfig
$ scripts/config -e ARCH_TEGRA_114_SOC -d DRM -d SUSPEND \
-d PM_RUNTIME -d CPU_FREQ -d CPU_IDLE -d HOTPLUG_CPU
$ make ARCH=arm menuconfig # if needed to configure more
$ make ARCH=arm all -j9
You may also want to enable CONFIG_ARM_APPENDED_DTB and
CONFIG_ARM_ATAG_DTB_COMPAT if the bootloader doesn't support DT yet.
Verified that this single image booted up with "Dalmore(T114)",
"Pluto(T114)" and "Cardhu(T30)". For "Cardhu(T30)" with this single
image, SPI driver doesn't seem to afford the above configuration , it
hangs at boot-up. With SPI disabled, it's ok.
v3:
Rebased against next-20130115.
Dropped TSC/arch timer patch.
Use /cpus entry in DT to detect cpu core #.
v2:
Rebased against the latest Stephen Warren's linux-next_common
Add /cpus entry in DT
Add comment to initialize TSC only in secure mode.
Hiroshi Doyu (9):
ARM: tegra: fuse: Add chipid TEGRA114 0x35
HACK: ARM: tegra: Use CLK_IGNORE_UNUSED for Tegra 114 SoC
ARM: tegra: Use DT /cpu node to detect number of CPU core
ARM: Add API to detect SCU base address from CP15
ARM: tegra: Skip scu_enable(scu_base) if not Cortex A9
ARM: dt: tegra114: Add new SoC base, Tegra 114 SoC
ARM: dt: tegra114: Add new board, Dalmore
ARM: dt: tegra114: Add new board, Pluto
ARM: tegra: Add initial support for Tegra 114 SoC.
arch/arm/boot/dts/Makefile | 4 +-
arch/arm/boot/dts/tegra114-dalmore.dts | 21 ++++++
arch/arm/boot/dts/tegra114-pluto.dts | 21 ++++++
arch/arm/boot/dts/tegra114.dtsi | 116 +++++++++++++++++++++++++++++
arch/arm/include/asm/smp_scu.h | 17 +++++
arch/arm/mach-tegra/Kconfig | 10 +++
arch/arm/mach-tegra/Makefile | 1 +
arch/arm/mach-tegra/board-dt-tegra114.c | 48 ++++++++++++
arch/arm/mach-tegra/common.c | 1 +
arch/arm/mach-tegra/fuse.h | 1 +
arch/arm/mach-tegra/platsmp.c | 22 ++----
arch/arm/mach-tegra/tegra30_clocks_data.c | 2 +
12 files changed, 246 insertions(+), 18 deletions(-)
create mode 100644 arch/arm/boot/dts/tegra114-dalmore.dts
create mode 100644 arch/arm/boot/dts/tegra114-pluto.dts
create mode 100644 arch/arm/boot/dts/tegra114.dtsi
create mode 100644 arch/arm/mach-tegra/board-dt-tegra114.c
--
1.7.9.5
^ permalink raw reply
* [PATCH] ARM: davinci: da850 evm: pass platform data for adv7343 encoder
From: Lad, Prabhakar @ 2013-01-15 8:04 UTC (permalink / raw)
To: linux-arm-kernel
Without this patch the adv7343 encoder was being set to default
configuration which caused display not to work on this board.
This patch passes the necessary platform data required for adv7343
encoder to work on da850 evm.
Signed-off-by: Lad, Prabhakar <prabhakar.lad@ti.com>
---
This patch is dependent on http://patchwork.linuxtv.org/patch/16272/
arch/arm/mach-davinci/board-da850-evm.c | 13 +++++++++++++
1 files changed, 13 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-davinci/board-da850-evm.c b/arch/arm/mach-davinci/board-da850-evm.c
index 0299915..d0e3ec3 100644
--- a/arch/arm/mach-davinci/board-da850-evm.c
+++ b/arch/arm/mach-davinci/board-da850-evm.c
@@ -1256,11 +1256,24 @@ static struct vpif_capture_config da850_vpif_capture_config = {
};
/* VPIF display configuration */
+
+static struct adv7343_platform_data adv7343_pdata = {
+ .mode_config = {
+ .dac_3 = 1,
+ .dac_2 = 1,
+ .dac_1 = 1,
+ },
+ .sd_config = {
+ .sd_dac_out1 = 1,
+ },
+};
+
static struct vpif_subdev_info da850_vpif_subdev[] = {
{
.name = "adv7343",
.board_info = {
I2C_BOARD_INFO("adv7343", 0x2a),
+ .platform_data = &adv7343_pdata,
},
},
};
--
1.7.4.1
^ permalink raw reply related
* OMAP baseline test results for v3.8-rc3
From: Felipe Balbi @ 2013-01-15 7:32 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20130114224222.GC18224@blackmetal.musicnaut.iki.fi>
Hi,
On Tue, Jan 15, 2013 at 12:42:22AM +0200, Aaro Koskinen wrote:
> On Mon, Jan 14, 2013 at 11:18:46PM +0200, Felipe Balbi wrote:
> > On Mon, Jan 14, 2013 at 10:46:54PM +0200, Aaro Koskinen wrote:
> > > [ 0.207946] twl 1-0048: PIH (irq 23) chaining IRQs 338..346
> > > [ 0.208129] twl 1-0048: power (irq 343) chaining IRQs 346..353
> > > [ 0.209350] twl4030_gpio twl4030_gpio: gpio (irq 338) chaining IRQs 354..371
> > > [ 1.218749] omap_i2c omap_i2c.1: timeout waiting for bus ready
> > > [ 1.218811] omap_i2c omap_i2c.1: SA 0049 CON 9602 CNT 0004
> >
> > here's the issue, there is unloaded data in the FIFO. Can you enable
> > full I2C debugging logs ?
>
> If I enable I2C DEBUGs, the problem is not reproducible. Everything
> looks normal:
>
> [ 0.270141] twl 1-0048: PIH (irq 23) chaining IRQs 338..346
> [ 0.270294] twl 1-0048: power (irq 343) chaining IRQs 346..353
> [ 0.270477] i2c i2c-1: master_xfer[0] W, addr=0x49, len=1
> [ 0.270538] i2c i2c-1: master_xfer[1] R, addr=0x49, len=1
> [ 0.270568] omap_i2c omap_i2c.1: addr: 0x0049, len: 1, flags: 0x0, stop: 0
> [ 0.270629] omap_i2c omap_i2c.1: IRQ (ISR = 0x0010)
> [ 0.270690] omap_i2c omap_i2c.1: IRQ (ISR = 0x0004)
> [ 0.270751] omap_i2c omap_i2c.1: addr: 0x0049, len: 1, flags: 0x1, stop: 1
> [ 0.270843] omap_i2c omap_i2c.1: IRQ (ISR = 0x0008)
> [ 0.270874] omap_i2c omap_i2c.1: IRQ (ISR = 0x0004)
> [ 0.270935] i2c i2c-1: master_xfer[0] W, addr=0x49, len=2
> [ 0.270965] omap_i2c omap_i2c.1: addr: 0x0049, len: 2, flags: 0x0, stop: 1
> [ 0.271026] omap_i2c omap_i2c.1: IRQ (ISR = 0x0010)
> [ 0.271118] omap_i2c omap_i2c.1: IRQ (ISR = 0x0004)
> [ 0.272155] twl4030_gpio twl4030_gpio: gpio (irq 338) chaining IRQs 354..371
still another race ? I'll look into it.
> > > > git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb.git i2c-deferred-STP
> > >
> > > I could not reproduce the issue with these. Tested around 20 boots.
> > > There's a noticeable delay (over 4 secs!) around where I2C is initialized
> > > and used for the first time, but no errors and the boot completes:
> > >
> > > [ 0.187530] SCSI subsystem initialized
> > > [ 0.188110] usbcore: registered new interface driver usbfs
> > > [ 0.188415] usbcore: registered new interface driver hub
> > > [ 0.188781] usbcore: registered new device driver usb
> > > [ 0.189453] musb-omap2430 musb-omap2430: invalid resource
> > > [ 4.296905] twl 1-0048: PIH (irq 23) chaining IRQs 338..346
> > > [ 4.297088] twl 1-0048: power (irq 343) chaining IRQs 346..353
> > > [ 4.329010] twl4030_gpio twl4030_gpio: gpio (irq 338) chaining IRQs 354..371
> > > [ 4.470123] VUSB1V5: 1500 mV normal standby
> > > [ 4.470916] VUSB1V8: 1800 mV normal standby
> >
> > cool, at least it works, but looks like there is something still weird
> > going on. Can you enable full logs so I see what's happening ?
>
> With your patches, all DEBUG logs are identical (there is same
> amount I2C of transfers), except there is only a single interrupt per
> transfer. Still, the transfers are taking considerably longer, and we
> see those delays in the boot:
>
> [ 4.281280] twl 1-0048: PIH (irq 23) chaining IRQs 338..346
> [ 4.281433] twl 1-0048: power (irq 343) chaining IRQs 346..353
> [ 4.281616] i2c i2c-1: master_xfer[0] W, addr=0x49, len=1
> [ 4.281677] i2c i2c-1: master_xfer[1] R, addr=0x49, len=1
> [ 4.281707] omap_i2c omap_i2c.1: addr: 0x0049, len: 1, flags: 0x0, stop: 0
> [ 4.281799] omap_i2c omap_i2c.1: IRQ (ISR = 0x0010)
> [ 4.281829] omap_i2c omap_i2c.1: addr: 0x0049, len: 1, flags: 0x1, stop: 1
> [ 4.281921] omap_i2c omap_i2c.1: IRQ (ISR = 0x0008)
> [ 4.296905] i2c i2c-1: master_xfer[0] W, addr=0x49, len=2
> [ 4.296936] omap_i2c omap_i2c.1: addr: 0x0049, len: 2, flags: 0x0, stop: 1
> [ 4.296997] omap_i2c omap_i2c.1: IRQ (ISR = 0x0010)
> [ 4.313476] twl4030_gpio twl4030_gpio: gpio (irq 338) chaining IRQs 354..371
>
> This log excerpt has only 3 transfers, but the time duration is already
> 10x longer compared to vanilla 3.8-rc3.
weird, there's nothing extremely expensive added by my patchset, I'll go
over them and try to figure out what's going on.
Thanks for notifying me about it.
--
balbi
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20130115/263fe819/attachment-0001.sig>
^ permalink raw reply
* [PATCH v2 3/3 RFT] ARM: tegra: dts: seaboard: enable keyboard
From: Laxman Dewangan @ 2013-01-15 7:24 UTC (permalink / raw)
To: linux-arm-kernel
Enable tegra based keyboard controller and populate the key matrix for
seaboard. The key matrix was originally on driver code which is removed
to have clean driver. The key mapping is now passed through dts file.
Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com>
---
Added the configuration of kbc parameter as suggested by Stephen and
corrected type for LEFTCTRL.
arch/arm/boot/dts/tegra20-seaboard.dts | 139 ++++++++++++++++++++++++++++++++
1 files changed, 139 insertions(+), 0 deletions(-)
diff --git a/arch/arm/boot/dts/tegra20-seaboard.dts b/arch/arm/boot/dts/tegra20-seaboard.dts
index f9e3ad4..2e87330 100644
--- a/arch/arm/boot/dts/tegra20-seaboard.dts
+++ b/arch/arm/boot/dts/tegra20-seaboard.dts
@@ -612,6 +612,145 @@
};
};
+ kbc {
+ status = "okay";
+ nvidia,debounce-delay-ms = <32>;
+ nvidia,repeat-delay-ms = <160>;
+ nvidia,ghost-filter;
+ nvidia,kbc-row-pins = <0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15>;
+ nvidia,kbc-col-pins = <16 17 18 19 20 21 22 23>;
+ linux,keymap = <0x00020011 /* KEY_W */
+ 0x0003001F /* KEY_S */
+ 0x0004001E /* KEY_A */
+ 0x0005002C /* KEY_Z */
+ 0x000701d0 /* KEY_FN */
+
+ 0x0107007D /* KEY_LEFTMETA */
+ 0x02060064 /* KEY_RIGHTALT */
+ 0x02070038 /* KEY_LEFTALT */
+
+ 0x03000006 /* KEY_5 */
+ 0x03010005 /* KEY_4 */
+ 0x03020013 /* KEY_R */
+ 0x03030012 /* KEY_E */
+ 0x03040021 /* KEY_F */
+ 0x03050020 /* KEY_D */
+ 0x0306002D /* KEY_X */
+
+ 0x04000008 /* KEY_7 */
+ 0x04010007 /* KEY_6 */
+ 0x04020014 /* KEY_T */
+ 0x04030023 /* KEY_H */
+ 0x04040022 /* KEY_G */
+ 0x0405002F /* KEY_V */
+ 0x0406002E /* KEY_C */
+ 0x04070039 /* KEY_SPACE */
+
+ 0x0500000A /* KEY_9 */
+ 0x05010009 /* KEY_8 */
+ 0x05020016 /* KEY_U */
+ 0x05030015 /* KEY_Y */
+ 0x05040024 /* KEY_J */
+ 0x05050031 /* KEY_N */
+ 0x05060030 /* KEY_B */
+ 0x0507002B /* KEY_BACKSLASH */
+
+ 0x0600000C /* KEY_MINUS */
+ 0x0601000B /* KEY_0 */
+ 0x06020018 /* KEY_O */
+ 0x06030017 /* KEY_I */
+ 0x06040026 /* KEY_L */
+ 0x06050025 /* KEY_K */
+ 0x06060033 /* KEY_COMMA */
+ 0x06070032 /* KEY_M */
+
+ 0x0701000D /* KEY_EQUAL */
+ 0x0702001B /* KEY_RIGHTBRACE */
+ 0x0703001C /* KEY_ENTER */
+ 0x0707008B /* KEY_MENU */
+
+ 0x08040036 /* KEY_RIGHTSHIFT */
+ 0x0805002A /* KEY_LEFTSHIFT */
+
+ 0x09050061 /* KEY_RIGHTCTRL */
+ 0x0907001D /* KEY_LEFTCTRL */
+
+ 0x0B00001A /* KEY_LEFTBRACE */
+ 0x0B010019 /* KEY_P */
+ 0x0B020028 /* KEY_APOSTROPHE */
+ 0x0B030027 /* KEY_SEMICOLON */
+ 0x0B040035 /* KEY_SLASH */
+ 0x0B050034 /* KEY_DOT */
+
+ 0x0C000044 /* KEY_F10 */
+ 0x0C010043 /* KEY_F9 */
+ 0x0C02000E /* KEY_BACKSPACE */
+ 0x0C030004 /* KEY_3 */
+ 0x0C040003 /* KEY_2 */
+ 0x0C050067 /* KEY_UP */
+ 0x0C0600D2 /* KEY_PRINT */
+ 0x0C070077 /* KEY_PAUSE */
+
+ 0x0D00006E /* KEY_INSERT */
+ 0x0D01006F /* KEY_DELETE */
+ 0x0D030068 /* KEY_PAGEUP */
+ 0x0D04006D /* KEY_PAGEDOWN */
+ 0x0D05006A /* KEY_RIGHT */
+ 0x0D06006C /* KEY_DOWN */
+ 0x0D070069 /* KEY_LEFT */
+
+ 0x0E000057 /* KEY_F11 */
+ 0x0E010058 /* KEY_F12 */
+ 0x0E020042 /* KEY_F8 */
+ 0x0E030010 /* KEY_Q */
+ 0x0E04003E /* KEY_F4 */
+ 0x0E05003D /* KEY_F3 */
+ 0x0E060002 /* KEY_1 */1
+ 0x0E070041 /* KEY_F7 */
+
+ 0x0F000001 /* KEY_ESC */
+ 0x0F010029 /* KEY_GRAVE */
+ 0x0F02003F /* KEY_F5 */
+ 0x0F03000F /* KEY_TAB */
+ 0x0F04003B /* KEY_F1 */
+ 0x0F05003C /* KEY_F2 */
+ 0x0F06003A /* KEY_CAPSLOCK */
+ 0x0F070040 /* KEY_F6 */
+
+ /* Software Handled Function Keys */
+ 0x14000047 /* KEY_KP7 */
+
+ 0x15000049 /* KEY_KP9 */
+ 0x15010048 /* KEY_KP8 */
+ 0x1502004B /* KEY_KP4 */
+ 0x1504004F /* KEY_KP1 */
+
+ 0x1601004E /* KEY_KPSLASH */
+ 0x1602004D /* KEY_KP6 */
+ 0x1603004C /* KEY_KP5 */
+ 0x16040051 /* KEY_KP3 */
+ 0x16050050 /* KEY_KP2 */
+ 0x16070052 /* KEY_KP0 */
+
+ 0x1B010037 /* KEY_KPASTERISK */
+ 0x1B03004A /* KEY_KPMINUS */
+ 0x1B04004E /* KEY_KPPLUS */
+ 0x1B050053 /* KEY_KPDOT */
+
+ 0x1C050073 /* KEY_VOLUMEUP */
+
+ 0x1D030066 /* KEY_HOME */
+ 0x1D04006B /* KEY_END */
+ 0x1D0500E0 /* KEY_BRIGHTNESSDOWN */
+ 0x1D060072 /* KEY_VOLUMEDOWN */
+ 0x1D0700E1 /* KEY_BRIGHTNESSUP */
+
+ 0x1E000045 /* KEY_NUMLOCK */
+ 0x1E010046 /* KEY_SCROLLLOCK */
+ 0x1E020071 /* KEY_MUTE */
+
+ 0x1F04008A>; /* KEY_HELP */
+ };
regulators {
compatible = "simple-bus";
#address-cells = <1>;
--
1.7.1.1
^ permalink raw reply related
* rtc: vt8500: Fix year field in vt8500_rtc_set_time
From: Tony Prisk @ 2013-01-15 7:22 UTC (permalink / raw)
To: linux-arm-kernel
Alessandro,
This patch was sent out at the same time as two other RTC fixes for
vt8500 but this one seems to have stopped somewhere along the way while
the other two have been accepted.
The patch is showing in the RTC patch system along with the other two:
http://patchwork.ozlabs.org/patch/208756/
Greg,
How did the first two patches find their way to you - did you pick them
up off one of the lists?
patch 1 - rtc: vt8500: Fix handling of data passed in struct rtc_time
patch 2 - [fix-3.8] rtc: vt8500: Correct handling of CR_24H bitfield
Hope this is enough information to help you figure out what I'm talking
about :)
Regards
Tony P
^ permalink raw reply
* [kvmarm] [PATCH v5 13/14] KVM: ARM: Handle I/O aborts
From: Gleb Natapov @ 2013-01-15 7:00 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20130114223638.GB3937@mudshark.cambridge.arm.com>
On Mon, Jan 14, 2013 at 10:36:38PM +0000, Will Deacon wrote:
> On Mon, Jan 14, 2013 at 07:12:49PM +0000, Christoffer Dall wrote:
> > On Mon, Jan 14, 2013 at 2:00 PM, Will Deacon <will.deacon@arm.com> wrote:
> > > On Mon, Jan 14, 2013 at 06:53:14PM +0000, Alexander Graf wrote:
> > >> On 01/14/2013 07:50 PM, Will Deacon wrote:
> > >> > FWIW, KVM only needs this code for handling complex MMIO instructions, which
> > >> > aren't even generated by recent guest kernels. I'm inclined to suggest removing
> > >> > this emulation code from KVM entirely given that it's likely to bitrot as
> > >> > it is executed less and less often.
> > >>
> > >> That'd mean that you heavily limit what type of guests you're executing,
> > >> which I don't think is a good idea.
> > >
> > > To be honest, I don't think we know whether that's true or not. How many
> > > guests out there do writeback accesses to MMIO devices? Even on older
> > > Linux guests, it was dependent on how GCC felt.
> >
> > I don't think bitrot'ing is a valid argument: the code doesn't depend
> > on any other implementation state that's likely to change and break
> > this code (the instruction encoding is not exactly going to change).
> > And we should simply finish the selftest code to test this stuff
> > (which should be finished if the code is unified or not, and is on my
> > todo list).
>
> Maybe `bitrot' is the wrong word. The scenario I envisage is the addition
> of new instructions to the architecture which aren't handled by the current
> code, then we end up with emulation code that works for some percentage of
> the instruction set only. If the code is rarely used, it will likely go
> untouched until it crashes somebody's VM.
>
This is precisely the situation with x86 too. X86 has to many instruction
that can potentially access MMIO memory, but luckily not all of them
are used for that. When guest appears that uses instruction x86 kvm does
not emulate yet we add emulation of required instruction. If this is the
only concern about the code it should stay IMO.
> > > I see where you're coming from, I just don't think we can quantify it either
> > > way outside of Linux.
> > >
> > FWIW, I know of at least a couple of companies wanting to use KVM for
> > running non-Linux guests as well.
>
> Oh, I don't doubt that. The point is, do we have any idea how they behave
> under KVM? Do they generate complex MMIO accesses? Do they expect firmware
> shims, possibly sitting above hyp? Do they require a signed boot sequence?
> Do they run on Cortex-A15 (the only target CPU we have at the moment)?
>
> > But, however a shame, I can more easily maintain this single patch
> > out-of-tree, so I'm willing to drop this logic for now if it gets
> > things moving.
>
> I would hope that, if this code is actually required, you would consider
> merging it with what we have rather than maintaining it out-of-tree.
>
> Will
> --
> To unsubscribe from this list: send the line "unsubscribe kvm" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
--
Gleb.
^ permalink raw reply
* [PATCH] timer: vt8500: Convert vt8500 to use CLKSRC_OF
From: Tony Prisk @ 2013-01-15 6:50 UTC (permalink / raw)
To: linux-arm-kernel
This patch converts arch-vt8500 to make use of CLKSRC_OF. Doing so
removes the need for include/linux/vt8500_timer.h as vt8500_timer_init
no longer needs to be visible outside vt8500_timer.c
Signed-off-by: Tony Prisk <linux@prisktech.co.nz>
---
Hi Olof,
Here is the fix as requested by Stephen Warren, based on vt8500/timer.
arch/arm/mach-vt8500/Kconfig | 1 +
arch/arm/mach-vt8500/vt8500.c | 4 ++--
drivers/clocksource/vt8500_timer.c | 3 ++-
include/linux/vt8500_timer.h | 22 ----------------------
4 files changed, 5 insertions(+), 25 deletions(-)
delete mode 100644 include/linux/vt8500_timer.h
diff --git a/arch/arm/mach-vt8500/Kconfig b/arch/arm/mach-vt8500/Kconfig
index 570a801..d1cbda6 100644
--- a/arch/arm/mach-vt8500/Kconfig
+++ b/arch/arm/mach-vt8500/Kconfig
@@ -4,6 +4,7 @@ config ARCH_VT8500
select ARCH_HAS_CPUFREQ
select ARCH_REQUIRE_GPIOLIB
select CLKDEV_LOOKUP
+ select CLKSRC_OF
select CPU_ARM926T
select GENERIC_CLOCKEVENTS
select GENERIC_GPIO
diff --git a/arch/arm/mach-vt8500/vt8500.c b/arch/arm/mach-vt8500/vt8500.c
index b9fd9d3..fe99b70 100644
--- a/arch/arm/mach-vt8500/vt8500.c
+++ b/arch/arm/mach-vt8500/vt8500.c
@@ -18,9 +18,9 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#include <linux/clocksource.h>
#include <linux/io.h>
#include <linux/pm.h>
-#include <linux/vt8500_timer.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
@@ -186,8 +186,8 @@ DT_MACHINE_START(WMT_DT, "VIA/Wondermedia SoC (Device Tree Support)")
.dt_compat = vt8500_dt_compat,
.map_io = vt8500_map_io,
.init_irq = vt8500_init_irq,
- .init_time = vt8500_timer_init,
.init_machine = vt8500_init,
+ .init_time = clocksource_of_init,
.restart = vt8500_restart,
.handle_irq = vt8500_handle_irq,
MACHINE_END
diff --git a/drivers/clocksource/vt8500_timer.c b/drivers/clocksource/vt8500_timer.c
index 3dd21a4..b75b8e3 100644
--- a/drivers/clocksource/vt8500_timer.c
+++ b/drivers/clocksource/vt8500_timer.c
@@ -134,7 +134,7 @@ static struct of_device_id vt8500_timer_ids[] = {
{ }
};
-void __init vt8500_timer_init(void)
+static void __init vt8500_timer_init(void)
{
struct device_node *np;
int timer_irq;
@@ -182,3 +182,4 @@ void __init vt8500_timer_init(void)
clockevents_register_device(&clockevent);
}
+CLOCKSOURCE_OF_DECLARE(vt8500, "via,vt8500-timer", vt8500_timer_init)
diff --git a/include/linux/vt8500_timer.h b/include/linux/vt8500_timer.h
deleted file mode 100644
index 33b0ee8..0000000
--- a/include/linux/vt8500_timer.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright 2012 Tony Prisk <linux@prisktech.co.nz>
- *
- * 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 __VT8500_TIMER_H
-#define __VT8500_TIMER_H
-
-#include <asm/mach/time.h>
-
-void vt8500_timer_init(void);
-
-#endif
--
1.7.9.5
^ permalink raw reply related
* [GIT PULL] ste_dma40 updates for 3.9
From: Olof Johansson @ 2013-01-15 6:48 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20130114101542.GA5363@balto.lan>
Hi,
On Mon, Jan 14, 2013 at 2:15 AM, Fabio Baltieri
<fabio.baltieri@linaro.org> wrote:
> Hello Arnd, Olof,
>
> This contains a series of updates and fixes for the ste_dma40 driver.
>
> The driver is specific for the ux500, and the patches were acked by both Linus
> Walleij, and Vinod Koul (dmaengine), who agreed to push this through arm-soc.
>
> Can you please pull those in for -next?
While I don't mind taking this through arm-soc, I don't see a strong
reason to do so?
This series of patches only modify the ste_dma40 driver, there are no
corresponding changes under arch/arm that need to be coordinated or
considered w.r.t. merge conflicts. I.e. they all seem nicely isolated
to only the driver.
So is there a specific reason for why these shouldn't just go in
through the dmaengine tree?
Thanks,
-Olof
^ permalink raw reply
* [PATCH 1/2] ARM: 7114/1: cache-l2x0: add missed dummy outer_resume entry
From: Barry Song @ 2013-01-15 6:45 UTC (permalink / raw)
To: linux-arm-kernel
From: Barry Song <Baohua.Song@csr.com>
commit 91c2ebb90b1890a adds resume entry for l2 in secure mode,
http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;h=91c2ebb
but it misses the dummy entry when CONFIG_CACHE_L2X0 is not set.
Signed-off-by: Barry Song <Baohua.Song@csr.com>
---
arch/arm/include/asm/outercache.h | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/arch/arm/include/asm/outercache.h b/arch/arm/include/asm/outercache.h
index 53426c6..12f71a1 100644
--- a/arch/arm/include/asm/outercache.h
+++ b/arch/arm/include/asm/outercache.h
@@ -92,6 +92,7 @@ static inline void outer_flush_range(phys_addr_t start, phys_addr_t end)
static inline void outer_flush_all(void) { }
static inline void outer_inv_all(void) { }
static inline void outer_disable(void) { }
+static inline void outer_resume(void) { }
#endif
--
1.7.5.4
Member of the CSR plc group of companies. CSR plc registered in England and Wales, registered number 4187346, registered office Churchill House, Cambridge Business Park, Cowley Road, Cambridge, CB4 0WZ, United Kingdom
More information can be found at www.csr.com. Follow CSR on Twitter at http://twitter.com/CSR_PLC and read our blog at www.csr.com/blog
^ permalink raw reply related
* [GIT PULL v2] Renesas ARM-based SoC defconfig for v3.9
From: Olof Johansson @ 2013-01-15 6:44 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1358210975-26970-1-git-send-email-horms+renesas@verge.net.au>
Hi,
On Mon, Jan 14, 2013 at 4:49 PM, Simon Horman
<horms+renesas@verge.net.au> wrote:
> Hi Olof, Hi Arnd,
>
> please consider the following defconfig enhancements for 3.9.
>
> ----------------------------------------------------------------
> The following changes since commit a49f0d1ea3ec94fc7cf33a7c36a16343b74bd565:
>
> Linux 3.8-rc1 (2012-12-21 17:19:00 -0800)
>
> are available in the git repository at:
>
> git://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas.git
Missing branch or tag name? defconfig branch looks like the right one,
but please confirm.
-Olof
^ permalink raw reply
* [PATCHv2 1/4] clockevents: Add generic timer broadcast receiver
From: Santosh Shilimkar @ 2013-01-15 6:40 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20130114153612.GF7990@e106331-lin.cambridge.arm.com>
On Monday 14 January 2013 09:06 PM, Mark Rutland wrote:
> On Mon, Jan 14, 2013 at 02:17:26PM +0000, Thomas Gleixner wrote:
>> On Mon, 14 Jan 2013, Mark Rutland wrote:
>>> On Mon, Jan 14, 2013 at 11:50:55AM +0000, Thomas Gleixner wrote:
>>>> On Mon, 14 Jan 2013, Mark Rutland wrote:
>>>>
>>>>> On Mon, Jan 14, 2013 at 11:06:31AM +0000, Thomas Gleixner wrote:
>>>>>> On Wed, 9 Jan 2013, Mark Rutland wrote:
>>>>>>> +#ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
>>>>>>> +extern int tick_receive_broadcast(void);
>>>>>>> +#else
>>>>>>> +static inline int tick_receive_broadcast(void)
>>>>>>> +{
>>>>>>> + return 0;
>>>>>>> +}
>>>>>>
>>>>>> What's the inline function for? If an arch does not have broadcasting
>>>>>> support it should not have a receive broadcast function call either.
>>>>>
>>>>> That was how this was originally structured [1], but Santosh suggested this
>>>>> would break the build for !GENERIC_CLOCKEVENTS_BROADCAST [1]. It means that the
>>>>> arch-specific receive path (i.e. IPI handler) doesn't have to be #ifdef'd,
>>>>> which makes it less ugly.
>>>>
>>>> Hmm. If you want to keep the IPI around unconditionally the inline
>>>> makes some sense, though the question is whether keeping an unused IPI
>>>> around makes sense in the first place. I'd rather see a warning that
>>>> an unexpected IPI happened than a silent inline function being called.
>>>
>>> How about I add a warning (e.g. "Impossible timer broadcast received.") and
>>> return -EOPNOTSUPP when !GENERIC_CLOCKEVENTS_BROADCAST?
>>
>> You still need to do something with the return value in the arch IPI
>> code, right?
>
> Good point. Having the stub when !CONFIG_GENERIC_CLOCKEVENTS_BROADCAST is
> clearly problematic.
>
> I'll go with your original suggestion, removing the tick_receive_broadcast stub
> for !CONFIG_GENERIC_CLOCKEVENTS_BROADCAST and I'll #idef the IPI_TIMER handler.
> That way it'll fall down to the standard warning for an unexpected/unknown IPI
> for arch/arm at least.
>
The alternative is fine by me.
Regards
santosh
^ permalink raw reply
* [PATCH v2 1/2] i2c-core: dt: Pick i2c bus number from i2c alias if present
From: Olof Johansson @ 2013-01-15 6:34 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1358189602-24180-2-git-send-email-dianders@chromium.org>
On Mon, Jan 14, 2013 at 10:53:21AM -0800, Doug Anderson wrote:
> This allows you to get the equivalent functionality of
> i2c_add_numbered_adapter() with all data in the device tree and no
> special case code in your driver. This is a common device tree
> technique.
>
> For quick reference, the FDT syntax for using an alias to provide an
> ID looks like:
> aliases {
> i2c0 = &i2c_0;
> i2c1 = &i2c_1;
> };
>
> Signed-off-by: Doug Anderson <dianders@chromium.org>
> Acked-by: Haojian Zhuang <haojian.zhuang@gmail.com>
The call path for i2c_add_numbered_adapter() with nr == -1 is a little
awkward now, but I don't see much how it can be improved much.
Acked-by: Olof Johansson <olof@lixom.net>
-Olof
^ permalink raw reply
* [PATCH 06/16] ARM: b.L: generic SMP secondary bringup and hotplug support
From: Santosh Shilimkar @ 2013-01-15 6:32 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAMpgmWCxQMoncnMqy_bzB+mBU7eGO_L4fR+Q5uMaxdFn4mL5PA@mail.gmail.com>
On Monday 14 January 2013 11:35 PM, Achin Gupta wrote:
> Hi Santosh,
>
> On Fri, Jan 11, 2013 at 6:02 PM, Santosh Shilimkar
> <santosh.shilimkar@ti.com> wrote:
>> On Thursday 10 January 2013 05:50 AM, Nicolas Pitre wrote:
>>>
>>> Now that the b.L power API is in place, we can use it for SMP secondary
>>> bringup and CPU hotplug in a generic fashion.
>>>
>>> Signed-off-by: Nicolas Pitre <nico@linaro.org>
>>> ---
>>> arch/arm/common/Makefile | 2 +-
>>> arch/arm/common/bL_platsmp.c | 79
>>> ++++++++++++++++++++++++++++++++++++++++++++
>>> 2 files changed, 80 insertions(+), 1 deletion(-)
>>> create mode 100644 arch/arm/common/bL_platsmp.c
>>>
>>> diff --git a/arch/arm/common/Makefile b/arch/arm/common/Makefile
>>> index 894c2ddf9b..59b36db7cc 100644
>>> --- a/arch/arm/common/Makefile
>>> +++ b/arch/arm/common/Makefile
>>> @@ -15,4 +15,4 @@ obj-$(CONFIG_PCI_HOST_ITE8152) += it8152.o
>>> obj-$(CONFIG_ARM_TIMER_SP804) += timer-sp.o
>>> obj-$(CONFIG_FIQ_GLUE) += fiq_glue.o fiq_glue_setup.o
>>> obj-$(CONFIG_FIQ_DEBUGGER) += fiq_debugger.o
>>> -obj-$(CONFIG_BIG_LITTLE) += bL_head.o bL_entry.o vlock.o
>>> +obj-$(CONFIG_BIG_LITTLE) += bL_head.o bL_entry.o bL_platsmp.o
>>> vlock.o
>>> diff --git a/arch/arm/common/bL_platsmp.c b/arch/arm/common/bL_platsmp.c
>>> new file mode 100644
>>> index 0000000000..0acb9f4685
>>> --- /dev/null
>>> +++ b/arch/arm/common/bL_platsmp.c
>>> @@ -0,0 +1,79 @@
>>> +/*
>>> + * linux/arch/arm/mach-vexpress/bL_platsmp.c
>>> + *
>>> + * Created by: Nicolas Pitre, November 2012
>>> + * Copyright: (C) 2012 Linaro Limited
>>> + *
>>> + * This program is free software; you can redistribute it and/or modify
>>> + * it under the terms of the GNU General Public License version 2 as
>>> + * published by the Free Software Foundation.
>>> + *
>>> + * Code to handle secondary CPU bringup and hotplug for the bL power API.
>>> + */
>>> +
>>> +#include <linux/init.h>
>>> +#include <linux/smp.h>
>>> +
>>> +#include <asm/bL_entry.h>
>>> +#include <asm/smp_plat.h>
>>> +#include <asm/hardware/gic.h>
>>> +
>>> +static void __init simple_smp_init_cpus(void)
>>> +{
>>> + set_smp_cross_call(gic_raise_softirq);
>>> +}
>>> +
>>> +static int __cpuinit bL_boot_secondary(unsigned int cpu, struct
>>> task_struct *idle)
>>> +{
>>> + unsigned int pcpu, pcluster, ret;
>>> + extern void secondary_startup(void);
>>> +
>>> + pcpu = cpu_logical_map(cpu) & 0xff;
>>> + pcluster = (cpu_logical_map(cpu) >> 8) & 0xff;
>>> + pr_debug("%s: logical CPU %d is physical CPU %d cluster %d\n",
>>> + __func__, cpu, pcpu, pcluster);
>>> +
>>> + bL_set_entry_vector(pcpu, pcluster, NULL);
>>> + ret = bL_cpu_power_up(pcpu, pcluster);
>>> + if (ret)
>>> + return ret;
>>> + bL_set_entry_vector(pcpu, pcluster, secondary_startup);
>>> + gic_raise_softirq(cpumask_of(cpu), 0);
>>> + sev();
>>
>> softirq() should be enough to break a CPU if it is in standby with
>> wfe state. Is that additional sev() needed here ?
>
> Not if the target cpu has its I & F bits disabled and that would be the
> case with a secondary waiting to be woken up
>
This is interesting since CPU is actually in standby state and this
was not my understanding so far. Your statement at least contradicts
the ARM ARM (B1.8.12 Wait For Interrupt)
-----------------------
The processor can remain in the WFI low-power state until it is reset,
or it detects one of the following WFI wake-up
events:
? a physical IRQ interrupt, regardless of the value of the CPSR.I bit
? a physical FIQ interrupt, regardless of the value of the CPSR.F bit
----------------------------------
Are you referring to some new behavior on latest ARMv7 CPUs ?
Regards,
Santosh
^ permalink raw reply
* [PATCH v4 2/5] ARM: dts: Add disable-wp for sd card slot on smdk5250
From: Olof Johansson @ 2013-01-15 6:27 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1357923834-31641-2-git-send-email-dianders@chromium.org>
On Fri, Jan 11, 2013 at 09:03:51AM -0800, Doug Anderson wrote:
> The next change will remove the code from the dw_mmc-exynos that added
> the DW_MCI_QUIRK_NO_WRITE_PROTECT. Keep existing functionality of
> having no write protect pin on smdk5250 by adding the disable-wp
> property.
>
> Signed-off-by: Doug Anderson <dianders@chromium.org>
> Acked-by: Seungwon Jeon <tgih.jun@samsung.com>
Acked-by: Olof Johansson <olof@lixom.net>
-Olof
^ permalink raw reply
* [PATCH v3] i2c: exynos5: add High Speed I2C controller driver
From: Naveen Krishna Ch @ 2013-01-15 6:23 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAHfPSqCFAVb71kMYAVoZJphiUtSoTUP2yD=Jw1+GBu-n10kVBA@mail.gmail.com>
On 28 December 2012 22:06, Naveen Krishna Ch <naveenkrishna.ch@gmail.com> wrote:
> On 28 December 2012 16:57, Naveen Krishna Chatradhi
> <ch.naveen@samsung.com> wrote:
>> Adds support for High Speed I2C driver found in Exynos5 and later
>> SoCs from Samsung. This driver currently supports Auto mode.
>>
>> Driver only supports Device Tree method of passing platform data.
>> Note: Added debugfs support for registers view, not tested.
>>
>> Signed-off-by: Taekgyun Ko <taeggyun.ko@samsung.com>
>> Signed-off-by: Naveen Krishna Chatradhi <ch.naveen@samsung.com>
>> ---
>> Changes since v2: fixed comments from Felipe Balbi.
>> And minor fixes for the return values in exynos5_i2c_doxfer()
>>
>> drivers/i2c/busses/Kconfig | 7 +
>> drivers/i2c/busses/Makefile | 1 +
>> drivers/i2c/busses/i2c-exynos5.c | 736 ++++++++++++++++++++++++++++++++++++++
>> 3 files changed, 744 insertions(+)
>> create mode 100644 drivers/i2c/busses/i2c-exynos5.c
>>
>> diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
>> index bdca511..4caea76 100644
>> --- a/drivers/i2c/busses/Kconfig
>> +++ b/drivers/i2c/busses/Kconfig
>> @@ -618,6 +618,13 @@ config I2C_S3C2410
>> Say Y here to include support for I2C controller in the
>> Samsung SoCs.
>>
>> +config I2C_EXYNOS5
>> + tristate "Exynos5 high-speed I2C driver"
>> + depends on ARCH_EXYNOS5
>> + help
>> + Say Y here to include support for High-speed I2C controller in the
>> + Exynos5 based Samsung SoCs.
>> +
>> config I2C_S6000
>> tristate "S6000 I2C support"
>> depends on XTENSA_VARIANT_S6000
>> diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
>> index 6181f3f..4b1548c 100644
>> --- a/drivers/i2c/busses/Makefile
>> +++ b/drivers/i2c/busses/Makefile
>> @@ -61,6 +61,7 @@ obj-$(CONFIG_I2C_PUV3) += i2c-puv3.o
>> obj-$(CONFIG_I2C_PXA) += i2c-pxa.o
>> obj-$(CONFIG_I2C_PXA_PCI) += i2c-pxa-pci.o
>> obj-$(CONFIG_I2C_S3C2410) += i2c-s3c2410.o
>> +obj-$(CONFIG_I2C_EXYNOS5) += i2c-exynos5.o
>> obj-$(CONFIG_I2C_S6000) += i2c-s6000.o
>> obj-$(CONFIG_I2C_SH7760) += i2c-sh7760.o
>> obj-$(CONFIG_I2C_SH_MOBILE) += i2c-sh_mobile.o
>> diff --git a/drivers/i2c/busses/i2c-exynos5.c b/drivers/i2c/busses/i2c-exynos5.c
>> new file mode 100644
>> index 0000000..a5eb959
>> --- /dev/null
>> +++ b/drivers/i2c/busses/i2c-exynos5.c
>> @@ -0,0 +1,736 @@
>> +/**
>> + * i2c-exynos5.c - Samsung Exynos5 I2C Controller Driver
>> + *
>> + * Copyright (C) 2012 Samsung Electronics Co., Ltd.
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License version 2 as
>> + * published by the Free Software Foundation.
>> +*/
>> +
>> +#include <linux/kernel.h>
>> +#include <linux/module.h>
>> +#include <linux/debugfs.h>
>> +
>> +#include <linux/i2c.h>
>> +#include <linux/init.h>
>> +#include <linux/time.h>
>> +#include <linux/interrupt.h>
>> +#include <linux/delay.h>
>> +#include <linux/errno.h>
>> +#include <linux/err.h>
>> +#include <linux/platform_device.h>
>> +#include <linux/pm_runtime.h>
>> +#include <linux/clk.h>
>> +#include <linux/slab.h>
>> +#include <linux/io.h>
>> +#include <linux/of_address.h>
>> +#include <linux/of_gpio.h>
>> +#include <linux/of_irq.h>
>> +#include <linux/of_i2c.h>
>> +
>> +/* Register Map */
>> +#define HSI2C_CTL 0x00
>> +#define HSI2C_FIFO_CTL 0x04
>> +#define HSI2C_TRAILIG_CTL 0x08
>> +#define HSI2C_CLK_CTL 0x0C
>> +#define HSI2C_CLK_SLOT 0x10
>> +#define HSI2C_INT_ENABLE 0x20
>> +#define HSI2C_INT_STATUS 0x24
>> +#define HSI2C_ERR_STATUS 0x2C
>> +#define HSI2C_FIFO_STATUS 0x30
>> +#define HSI2C_TX_DATA 0x34
>> +#define HSI2C_RX_DATA 0x38
>> +#define HSI2C_CONF 0x40
>> +#define HSI2C_AUTO_CONF 0x44
>> +#define HSI2C_TIMEOUT 0x48
>> +#define HSI2C_MANUAL_CMD 0x4C
>> +#define HSI2C_TRANS_STATUS 0x50
>> +#define HSI2C_TIMING_HS1 0x54
>> +#define HSI2C_TIMING_HS2 0x58
>> +#define HSI2C_TIMING_HS3 0x5C
>> +#define HSI2C_TIMING_FS1 0x60
>> +#define HSI2C_TIMING_FS2 0x64
>> +#define HSI2C_TIMING_FS3 0x68
>> +#define HSI2C_TIMING_SLA 0x6C
>> +#define HSI2C_ADDR 0x70
>> +
>> +/* I2C_CTL Register bits */
>> +#define HSI2C_FUNC_MODE_I2C (1u << 0)
>> +#define HSI2C_MASTER (1u << 3)
>> +#define HSI2C_RXCHON (1u << 6)
>> +#define HSI2C_TXCHON (1u << 7)
>> +#define HSI2C_SW_RST (1u << 31)
>> +
>> +/* I2C_FIFO_CTL Register bits */
>> +#define HSI2C_RXFIFO_EN (1u << 0)
>> +#define HSI2C_TXFIFO_EN (1u << 1)
>> +#define HSI2C_TXFIFO_TRIGGER_LEVEL (0x20 << 16)
>> +#define HSI2C_RXFIFO_TRIGGER_LEVEL (0x20 << 4)
>> +
>> +/* I2C_TRAILING_CTL Register bits */
>> +#define HSI2C_TRAILING_COUNT (0xf)
>> +
>> +/* I2C_INT_EN Register bits */
>> +#define HSI2C_INT_TX_ALMOSTEMPTY_EN (1u << 0)
>> +#define HSI2C_INT_RX_ALMOSTFULL_EN (1u << 1)
>> +#define HSI2C_INT_TRAILING_EN (1u << 6)
>> +#define HSI2C_INT_I2C_EN (1u << 9)
>> +
>> +/* I2C_FIFO_STAT Register bits */
>> +#define HSI2C_RX_FIFO_EMPTY (1u << 24)
>> +#define HSI2C_RX_FIFO_FULL (1u << 23)
>> +#define HSI2C_RX_FIFO_LEVEL_MASK (0x7 << 16)
>> +#define HSI2C_TX_FIFO_EMPTY (1u << 8)
>> +#define HSI2C_TX_FIFO_FULL (1u << 7)
>> +#define HSI2C_TX_FIFO_LEVEL_MASK (0x7 << 7)
>> +#define HSI2C_FIFO_EMPTY (0x1000100)
>> +
>> +/* I2C_CONF Register bits */
>> +#define HSI2C_AUTO_MODE (1u << 31)
>> +#define HSI2C_10BIT_ADDR_MODE (1u << 30)
>> +#define HSI2C_HS_MODE (1u << 29)
>> +
>> +/* I2C_AUTO_CONF Register bits */
>> +#define HSI2C_READ_WRITE (1u << 16)
>> +#define HSI2C_STOP_AFTER_TRANS (1u << 17)
>> +#define HSI2C_MASTER_RUN (1u << 31)
>> +
>> +/* I2C_TIMEOUT Register bits */
>> +#define HSI2C_TIMEOUT_EN (1u << 31)
>> +
>> +/* I2C_TRANS_STATUS register bits */
>> +#define HSI2C_MASTER_BUSY (1u << 17)
>> +#define HSI2C_SLAVE_BUSY (1u << 16)
>> +#define HSI2C_NO_DEV (1u << 3)
>> +#define HSI2C_NO_DEV_ACK (1u << 2)
>> +#define HSI2C_TRANS_ABORT (1u << 1)
>> +#define HSI2C_TRANS_DONE (1u << 0)
>> +
>> +/**
>> + * Although exynos5 supports max HS-IIC speed of 3.4Mhz,
>> + * but currently we are facing booting issues beyond 1Mhz
>> + * So limiting HS-IIC bus speed to 1Mhz
>> +*/
>> +#define HSI2C_HS_TX_CLOCK 1000000
>> +#define HSI2C_FS_TX_CLOCK 400000
>> +
>> +#define HSI2C_FAST_SPD 0
>> +#define HSI2C_HIGH_SPD 1
>> +
>> +#define EXYNOS5_I2C_TIMEOUT (msecs_to_jiffies(1000))
>> +
>> +/* timeout for pm runtime autosuspend */
>> +#define EXYNOS5_I2C_PM_TIMEOUT 1000 /* ms */
>> +
>> +struct exynos5_i2c {
>> + struct i2c_adapter adap;
>> + unsigned int suspended:1;
>> +
>> + struct i2c_msg *msg;
>> + unsigned int msg_idx;
>> + struct completion msg_complete;
>> + unsigned int msg_ptr;
>> +
>> + unsigned int irq;
>> +
>> + void __iomem *regs;
>> + struct clk *clk;
>> + struct device *dev;
>> + int gpios[2];
>> +
>> + int bus_num;
>> + int speed_mode;
>> + struct dentry *debugfs_root;
>> +};
>> +
>> +static const struct of_device_id exynos5_i2c_match[] = {
>> + { .compatible = "samsung,exynos5-hsi2c" },
>> + {},
>> +};
>> +MODULE_DEVICE_TABLE(of, exynos5_i2c_match);
>> +
>> +static void exynos5_i2c_stop(struct exynos5_i2c *i2c, int err)
>> +{
>> + dev_vdbg(i2c->dev, "STOP\n");
>> +
>> + i2c->msg_idx++;
>> + if (err)
>> + i2c->msg_idx = err;
>> +
>> + /* Disable interrrupts */
>> + writel(0, i2c->regs + HSI2C_INT_ENABLE);
>> + complete(&i2c->msg_complete);
>> +}
>> +
>> +static void exynos5_i2c_en_timeout(struct exynos5_i2c *i2c)
>> +{
>> + unsigned long i2c_timeout = readl(i2c->regs + HSI2C_TIMEOUT);
>> +
>> + /* Clear to enable Timeout */
>> + i2c_timeout &= ~HSI2C_TIMEOUT_EN;
>> + writel(i2c_timeout, i2c->regs + HSI2C_TIMEOUT);
>> +}
>> +
>> +static void exynos5_i2c_master_run(struct exynos5_i2c *i2c)
>> +{
>> + /* Start data transfer in Master mode */
>> + u32 i2c_auto_conf = readl(i2c->regs + HSI2C_AUTO_CONF);
>> + i2c_auto_conf |= HSI2C_MASTER_RUN;
>> + writel(i2c_auto_conf, i2c->regs + HSI2C_AUTO_CONF);
>> +}
>> +
>> +/**
>> + * exynos5_i2c_set_bus: get the i2c bus for a master transaction
>> +*/
>> +static int exynos5_i2c_set_master(struct exynos5_i2c *i2c)
>> +{
>> + unsigned long t_status;
>> + int timeout = 400;
>> +
>> + while (timeout-- > 0) {
>> + t_status = readl(i2c->regs + HSI2C_TRANS_STATUS);
>> +
>> + if (!(t_status & HSI2C_MASTER_BUSY))
>> + return 0;
>> +
>> + msleep(20);
>> + }
>> +
>> + return -ETIMEDOUT;
>> +}
>> +
>> +/**
>> + * exynos5_i2c_irq: top level IRQ servicing routine
>> +*/
>> +static irqreturn_t exynos5_i2c_irq(int irqno, void *dev_id)
>> +{
>> + struct exynos5_i2c *i2c = dev_id;
>> + unsigned long t_stat;
>> + unsigned char byte;
>> +
>> + t_stat = readl(i2c->regs + HSI2C_TRANS_STATUS);
>> +
>> + if (t_stat & HSI2C_TRANS_ABORT) {
>> + /* deal with arbitration loss */
>> + dev_err(i2c->dev, "deal with arbitration loss\n");
>> + goto out;
>> + }
>> + if (i2c->msg->flags & I2C_M_RD) {
>> + if (t_stat & HSI2C_TRANS_DONE) {
>> + dev_dbg(i2c->dev, "Device found.");
>> + while ((readl(i2c->regs + HSI2C_FIFO_STATUS) &
>> + HSI2C_RX_FIFO_EMPTY) == 0) {
>> + byte = readl(i2c->regs + HSI2C_RX_DATA);
>> + dev_dbg(i2c->dev, "read rx_data = %x", byte);
>> + i2c->msg->buf[i2c->msg_ptr++] = byte;
>> + }
>> +
>> + if (i2c->msg_ptr >= i2c->msg->len)
>> + exynos5_i2c_stop(i2c, 0);
>> +
>> + } else if (t_stat & HSI2C_NO_DEV) {
>> + dev_dbg(i2c->dev, "No device found.");
>> + exynos5_i2c_stop(i2c, -ENXIO);
>> + } else if (t_stat & HSI2C_NO_DEV_ACK &&
>> + !(i2c->msg->flags & I2C_M_IGNORE_NAK)) {
>> + dev_dbg(i2c->dev, "No device Ack.");
>> + exynos5_i2c_stop(i2c, -ENXIO);
>> + }
>> + } else {
>> + byte = i2c->msg->buf[i2c->msg_ptr++];
>> + dev_dbg(i2c->dev, "write tx_data = %x ", byte);
>> + writel(byte, i2c->regs + HSI2C_TX_DATA);
>> +
>> + if (i2c->msg_ptr >= i2c->msg->len)
>> + exynos5_i2c_stop(i2c, 0);
>> + }
>> +
>> + out:
>> + /* Set those bits to clear them */
>> + writel(readl(i2c->regs + HSI2C_INT_STATUS),
>> + i2c->regs + HSI2C_INT_STATUS);
>> +
>> + return IRQ_HANDLED;
>> +}
>> +
>> +static void exynos5_i2c_message_start(struct exynos5_i2c *i2c,
>> + struct i2c_msg *msgs)
>> +{
>> + unsigned long usi_ctl = HSI2C_FUNC_MODE_I2C | HSI2C_MASTER;
>> + unsigned long i2c_auto_conf;
>> + unsigned long i2c_addr = ((msgs->addr & 0x7f) << 10);
>> + unsigned long usi_int_en = 0;
>> +
>> + exynos5_i2c_en_timeout(i2c);
>> +
>> + if (msgs->flags & I2C_M_RD) {
>> + usi_ctl &= ~HSI2C_TXCHON;
>> + usi_ctl |= HSI2C_RXCHON;
>> +
>> + i2c_auto_conf |= HSI2C_READ_WRITE;
>> +
>> + usi_int_en |= (HSI2C_INT_RX_ALMOSTFULL_EN |
>> + HSI2C_INT_TRAILING_EN);
>> + } else {
>> + usi_ctl &= ~HSI2C_RXCHON;
>> + usi_ctl |= HSI2C_TXCHON;
>> +
>> + i2c_auto_conf &= ~HSI2C_READ_WRITE;
>> +
>> + usi_int_en |= HSI2C_INT_TX_ALMOSTEMPTY_EN;
>> + }
>> +
>> + writel(i2c_addr, i2c->regs + HSI2C_ADDR);
>> + writel(usi_ctl, i2c->regs + HSI2C_CTL);
>> +
>> + i2c_auto_conf |= i2c->msg->len;
>> + i2c_auto_conf |= HSI2C_STOP_AFTER_TRANS;
>> + writel(i2c_auto_conf, i2c->regs + HSI2C_AUTO_CONF);
>> +
>> + exynos5_i2c_master_run(i2c);
>> +
>> + /* Enable appropriate interrupts */
>> + writel(usi_int_en, i2c->regs + HSI2C_INT_ENABLE);
>> +}
>> +
>> +static int exynos5_i2c_doxfer(struct exynos5_i2c *i2c, struct i2c_msg *msgs)
>> +{
>> + unsigned long timeout;
>> + int ret;
>> +
>> + if (i2c->suspended) {
>> + dev_err(i2c->dev, "HS-I2C is not initialzed.\n");
>> + return -EIO;
>> + }
>> +
>> + if (exynos5_i2c_set_master(i2c)) {
>> + dev_err(i2c->dev, "cannot get bus, Master busy.\n");
>> + return -EAGAIN;
>> + }
>> +
>> + i2c->msg = msgs;
>> + i2c->msg_ptr = 0;
>> + i2c->msg_idx = 0;
>> +
>> + INIT_COMPLETION(i2c->msg_complete);
>> +
>> + exynos5_i2c_message_start(i2c, msgs);
>> +
>> + timeout = wait_for_completion_timeout(&i2c->msg_complete,
>> + EXYNOS5_I2C_TIMEOUT);
>> +
>> + ret = i2c->msg_idx;
>> +
>> + if (timeout == 0)
>> + dev_dbg(i2c->dev, "timeout\n");
>> + else if ((ret != msgs->len) && (ret < 0))
>> + dev_dbg(i2c->dev, "incomplete xfer (%d)\n", i2c->msg_idx);
>> +
>> + return ret;
>> +}
>> +
>> +static int exynos5_i2c_xfer(struct i2c_adapter *adap,
>> + struct i2c_msg *msgs, int num)
>> +{
>> + struct exynos5_i2c *i2c = (struct exynos5_i2c *)adap->algo_data;
>> + int retry, i;
>> + int ret;
>> +
>> + ret = pm_runtime_get_sync(i2c->dev);
>> + if (IS_ERR_VALUE(ret))
>> + goto out;
>> +
>> + clk_prepare_enable(i2c->clk);
>> +
>> + for (retry = 0; retry < adap->retries; retry++) {
>> + for (i = 0; i < num; i++) {
>> + ret = exynos5_i2c_doxfer(i2c, msgs);
>> + msgs++;
>> +
>> + if (ret == -EAGAIN)
>> + break;
>> + }
>> + if (i == num) {
>> + clk_disable_unprepare(i2c->clk);
>> +
>> + if (i2c->msg_idx == -ENXIO)
>> + ret = i2c->msg_idx;
>> + else
>> + ret = num;
>> + goto out;
>> + }
>> +
>> + dev_dbg(i2c->dev, "retrying transfer (%d)\n", retry);
>> +
>> + udelay(100);
>> + }
>> +
>> + ret = -EREMOTEIO;
>> + clk_disable_unprepare(i2c->clk);
>> + out:
>> + pm_runtime_mark_last_busy(i2c->dev);
>> + pm_runtime_put_autosuspend(i2c->dev);
>> + return ret;
>> +}
>> +
>> +static u32 exynos5_i2c_func(struct i2c_adapter *adap)
>> +{
>> + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
>> +}
>> +
>> +static const struct i2c_algorithm exynos5_i2c_algorithm = {
>> + .master_xfer = exynos5_i2c_xfer,
>> + .functionality = exynos5_i2c_func,
>> +};
>> +
>> +static int exynos5_i2c_set_timing(struct exynos5_i2c *i2c, int speed_mode)
>> +{
>> + unsigned long i2c_timing_s1;
>> + unsigned long i2c_timing_s2;
>> + unsigned long i2c_timing_s3;
>> + unsigned long i2c_timing_sla;
>> + unsigned int op_clk;
>> + unsigned int clkin = clk_get_rate(i2c->clk);
>> + unsigned int n_clkdiv;
>> + unsigned int t_start_su, t_start_hd;
>> + unsigned int t_stop_su;
>> + unsigned int t_data_su, t_data_hd;
>> + unsigned int t_scl_l, t_scl_h;
>> + unsigned int t_sr_release;
>> + unsigned int t_ftl_cycle;
>> + unsigned int i = 0, utemp0 = 0, utemp1 = 0, utemp2 = 0;
>> +
>> + if (speed_mode == HSI2C_HIGH_SPD)
>> + op_clk = HSI2C_HS_TX_CLOCK;
>> + else
>> + op_clk = HSI2C_FS_TX_CLOCK;
>> +
>> + /* FPCLK / FI2C =
>> + * (CLK_DIV + 1) * (TSCLK_L + TSCLK_H + 2) + 8 + 2 * FLT_CYCLE
>> + * uTemp0 = (CLK_DIV + 1) * (TSCLK_L + TSCLK_H + 2)
>> + * uTemp1 = (TSCLK_L + TSCLK_H + 2)
>> + * uTemp2 = TSCLK_L + TSCLK_H
>> + */
>> + t_ftl_cycle = (readl(i2c->regs + HSI2C_CONF) >> 16) & 0x7;
>> + utemp0 = (clkin / op_clk) - 8 - 2 * t_ftl_cycle;
>> +
>> + /* CLK_DIV max is 256 */
>> + for (i = 0; i < 256; i++) {
>> + utemp1 = utemp0 / (i + 1);
>> + /* SCLK_L/H max is 255
>> + * so sclk_l + sclk_h has max value of 510
>> + */
>> + if (utemp1 < 511) {
>> + utemp2 = utemp1 - 2;
>> + break;
>> + }
>> + }
>> +
>> + n_clkdiv = i;
>> + t_scl_l = utemp2 / 2;
>> + t_scl_h = utemp2 / 2;
>> + t_start_su = t_scl_l;
>> + t_start_hd = t_scl_l;
>> + t_stop_su = t_scl_l;
>> + t_data_su = t_scl_l / 2;
>> + t_data_hd = t_scl_l / 2;
>> + t_sr_release = utemp2;
>> +
>> + i2c_timing_s1 = t_start_su << 24 | t_start_hd << 16 | t_stop_su << 8;
>> + i2c_timing_s2 = t_data_su << 24 | t_scl_l << 8 | t_scl_h << 0;
>> + i2c_timing_s3 = n_clkdiv << 16 | t_sr_release << 0;
>> + i2c_timing_sla = t_data_hd << 0;
>> +
>> + dev_dbg(i2c->dev, "tSTART_SU: %X, tSTART_HD: %X, tSTOP_SU: %X\n",
>> + t_start_su, t_start_hd, t_stop_su);
>> + dev_dbg(i2c->dev, "tDATA_SU: %X, tSCL_L: %X, tSCL_H: %X\n",
>> + t_data_su, t_scl_l, t_scl_h);
>> + dev_dbg(i2c->dev, "nClkDiv: %X, tSR_RELEASE: %X\n",
>> + n_clkdiv, t_sr_release);
>> + dev_dbg(i2c->dev, "tDATA_HD: %X\n", t_data_hd);
>> +
>> + if (speed_mode == HSI2C_HIGH_SPD) {
>> + writel(i2c_timing_s1, i2c->regs + HSI2C_TIMING_HS1);
>> + writel(i2c_timing_s2, i2c->regs + HSI2C_TIMING_HS2);
>> + writel(i2c_timing_s3, i2c->regs + HSI2C_TIMING_HS3);
>> + } else {
>> + writel(i2c_timing_s1, i2c->regs + HSI2C_TIMING_FS1);
>> + writel(i2c_timing_s2, i2c->regs + HSI2C_TIMING_FS2);
>> + writel(i2c_timing_s3, i2c->regs + HSI2C_TIMING_FS3);
>> + }
>> + writel(i2c_timing_sla, i2c->regs + HSI2C_TIMING_SLA);
>> +
>> + return 0;
>> +}
>> +
>> +/**
>> + * Parse a list of GPIOs from a node property and request each one
>> + *
>> + * @param i2c i2c driver data
>> + * @return 0 on success, -EINVAL on error, in which case no GPIOs requested
>> +*/
>> +static int exynos5_i2c_parse_dt_gpio(struct exynos5_i2c *i2c)
>> +{
>> + int idx, gpio, ret;
>> +
>> + for (idx = 0; idx < 2; idx++) {
>> + gpio = of_get_gpio(i2c->dev->of_node, idx);
>> + if (!gpio_is_valid(gpio)) {
>> + dev_err(i2c->dev, "invalid gpio[%d]: %d\n", idx, gpio);
>> + return -EINVAL;
>> + }
>> + i2c->gpios[idx] = gpio;
>> +
>> + ret = devm_gpio_request(i2c->dev, gpio, "i2c-bus");
>> + if (ret) {
>> + dev_err(i2c->dev, "gpio [%d] request failed\n", gpio);
>> + return -EINVAL;
>> + }
>> + }
>> + return 0;
>> +}
>> +
>> +static void exynos5_i2c_init(struct exynos5_i2c *i2c)
>> +{
>> + unsigned long usi_trailing_ctl = HSI2C_TRAILING_COUNT;
>> + unsigned long i2c_conf = HSI2C_AUTO_MODE;
>> + unsigned long usi_fifo_ctl;
>> +
>> + writel(usi_trailing_ctl, i2c->regs + HSI2C_TRAILIG_CTL);
>> +
>> + /* Set default trigger level for TXFIFO and RXFIFO */
>> + usi_fifo_ctl = HSI2C_TXFIFO_TRIGGER_LEVEL | HSI2C_RXFIFO_TRIGGER_LEVEL;
>> +
>> + /* Enable RXFIFO and TXFIFO */
>> + usi_fifo_ctl = HSI2C_RXFIFO_EN | HSI2C_TXFIFO_EN;
>> + writel(usi_fifo_ctl, i2c->regs + HSI2C_FIFO_CTL);
>> +
>> + if (i2c->speed_mode == HSI2C_HIGH_SPD) {
>> + exynos5_i2c_set_timing(i2c, HSI2C_HIGH_SPD);
>> + /* Configure I2C controller in High speed mode */
>> + i2c_conf |= HSI2C_HS_MODE;
>> + writel(i2c_conf, i2c->regs + HSI2C_CONF);
>> + } else {
>> + /* Configure I2C controller in Fast speed mode */
>> + exynos5_i2c_set_timing(i2c, HSI2C_FAST_SPD);
>> + }
>> +}
>> +
>> +#define HSI2C_REG(regname) {.name = #regname, .offset = regname}
>> +static struct debugfs_reg32 exynos5_hsi2c_regs[] = {
>> + HSI2C_REG(HSI2C_CTL), HSI2C_REG(HSI2C_FIFO_CTL),
>> + HSI2C_REG(HSI2C_TRAILIG_CTL), HSI2C_REG(HSI2C_CLK_CTL),
>> + HSI2C_REG(HSI2C_CLK_SLOT), HSI2C_REG(HSI2C_INT_ENABLE),
>> + HSI2C_REG(HSI2C_INT_STATUS), HSI2C_REG(HSI2C_ERR_STATUS),
>> + HSI2C_REG(HSI2C_FIFO_STATUS), HSI2C_REG(HSI2C_TX_DATA),
>> + HSI2C_REG(HSI2C_RX_DATA), HSI2C_REG(HSI2C_CONF),
>> + HSI2C_REG(HSI2C_AUTO_CONF), HSI2C_REG(HSI2C_TIMEOUT),
>> + HSI2C_REG(HSI2C_MANUAL_CMD), HSI2C_REG(HSI2C_TRANS_STATUS),
>> + HSI2C_REG(HSI2C_TIMING_HS1), HSI2C_REG(HSI2C_TIMING_HS2),
>> + HSI2C_REG(HSI2C_TIMING_HS3), HSI2C_REG(HSI2C_TIMING_FS1),
>> + HSI2C_REG(HSI2C_TIMING_FS2), HSI2C_REG(HSI2C_TIMING_FS3),
>> + HSI2C_REG(HSI2C_TIMING_SLA), HSI2C_REG(HSI2C_ADDR),
>> +};
>> +
>> +static struct debugfs_regset32 exynos5_hsi2c_regset = {
>> + .regs = exynos5_hsi2c_regs,
>> + .nregs = ARRAY_SIZE(exynos5_hsi2c_regs),
>> +};
>> +
>> +static struct dentry *exynos5_hsi2c_reg_debugfs;
>> +
>> +static int exynos5_i2c_probe(struct platform_device *pdev)
>> +{
>> + struct device_node *np = pdev->dev.of_node;
>> + struct exynos5_i2c *i2c;
>> + int ret;
>> +
>> + if (!np) {
>> + dev_err(&pdev->dev, "no device node\n");
>> + return -ENOENT;
>> + }
>> +
>> + i2c = devm_kzalloc(&pdev->dev, sizeof(struct exynos5_i2c), GFP_KERNEL);
>> + if (!i2c) {
>> + dev_err(&pdev->dev, "no memory for state\n");
>> + return -ENOMEM;
>> + }
>> +
>> + i2c->bus_num = -1;
>> + /* Mode of operation High/Fast Speed mode */
>> + of_property_read_u32(np, "samsung,hs-mode", &i2c->speed_mode);
>> +
>> + strlcpy(i2c->adap.name, "exynos5-hsi2c", sizeof(i2c->adap.name));
>> + i2c->adap.owner = THIS_MODULE;
>> + i2c->adap.algo = &exynos5_i2c_algorithm;
>> + i2c->adap.retries = 2;
>> + i2c->adap.class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
>> +
>> + i2c->dev = &pdev->dev;
>> + i2c->clk = clk_get(&pdev->dev, "hsi2c");
>> + if (IS_ERR(i2c->clk)) {
>> + dev_err(&pdev->dev, "cannot get clock\n");
>> + ret = -ENOENT;
>> + goto err_noclk;
>> + }
>> +
>> + dev_dbg(&pdev->dev, "clock source %p\n", i2c->clk);
>> +
>> + clk_prepare_enable(i2c->clk);
>> +
>> + i2c->regs = of_iomap(np, 0);
>> + if (!i2c->regs) {
>> + dev_err(&pdev->dev, "cannot map HS-I2C IO\n");
>> + ret = -ENXIO;
>> + goto err_clk;
>> + }
>> +
>> + /* inititalise the gpio */
>> + if (exynos5_i2c_parse_dt_gpio(i2c))
>> + return -EINVAL;
>> +
>> + i2c->irq = irq_of_parse_and_map(np, 0);
>> + if (i2c->irq) {
>> + ret = devm_request_irq(&pdev->dev, i2c->irq, exynos5_i2c_irq,
>> + 0, dev_name(&pdev->dev), i2c);
>> + if (ret < 0) {
>> + dev_err(&pdev->dev, "cannot request HS-I2C IRQ %d\n",
>> + i2c->irq);
>> + goto err_iomap;
>> + }
>> + }
>> +
>> + /*
>> + * TODO: Use private lock to avoid race conditions as
>> + * mentioned in pm_runtime.txt
>> + */
>> + pm_runtime_enable(i2c->dev);
>> + pm_runtime_set_autosuspend_delay(i2c->dev, EXYNOS5_I2C_PM_TIMEOUT);
>> + pm_runtime_use_autosuspend(i2c->dev);
>> +
>> + ret = pm_runtime_get_sync(i2c->dev);
>> + if (IS_ERR_VALUE(ret))
>> + goto err_iomap;
>> +
>> + exynos5_i2c_init(i2c);
>> +
>> + i2c->adap.algo_data = i2c;
>> + i2c->adap.dev.parent = &pdev->dev;
>> + i2c->adap.nr = i2c->bus_num;
>> + i2c->adap.dev.of_node = pdev->dev.of_node;
>> +
>> + ret = i2c_add_numbered_adapter(&i2c->adap);
>> + if (ret < 0) {
>> + dev_err(&pdev->dev, "failed to add bus to i2c core\n");
>> + goto err_pm;
>> + }
>> +
>> + init_completion(&i2c->msg_complete);
>> + of_i2c_register_devices(&i2c->adap);
>> + platform_set_drvdata(pdev, i2c);
>> +
>> + dev_info(&pdev->dev, "%s: Exynos5 HS-I2C adapter\n",
>> + dev_name(&i2c->adap.dev));
>> +
>> + exynos5_hsi2c_reg_debugfs = debugfs_create_regset32("exynos5-hsi2c",
>> + S_IFREG | S_IRUGO,
>> + NULL, &exynos5_hsi2c_regset);
> I took the reference of this call from MFD driver, which is the only
> driver using this (i guess)
> usb/dwc3.c driver had a generic implementation. I wasn't sure of the
> implementation.
> if someone can help, i willing to do that.
>> + clk_disable_unprepare(i2c->clk);
>> + pm_runtime_mark_last_busy(i2c->dev);
>> + pm_runtime_put_autosuspend(i2c->dev);
>> + return 0;
>> +
>> + err_pm:
>> + pm_runtime_put(i2c->dev);
>> + pm_runtime_disable(&pdev->dev);
>> + err_iomap:
>> + iounmap(i2c->regs);
>> + err_clk:
>> + clk_disable_unprepare(i2c->clk);
>> + err_noclk:
>> + return ret;
>> +}
>> +
>> +static int exynos5_i2c_remove(struct platform_device *pdev)
>> +{
>> + struct exynos5_i2c *i2c = platform_get_drvdata(pdev);
>> + int ret;
>> +
>> + ret = pm_runtime_get_sync(&pdev->dev);
>> + if (IS_ERR_VALUE(ret))
>> + return ret;
>> +
>> + clk_disable_unprepare(i2c->clk);
>> + pm_runtime_put(&pdev->dev);
>> + pm_runtime_disable(&pdev->dev);
>> +
>> + i2c_del_adapter(&i2c->adap);
>> +
>> + iounmap(i2c->regs);
>> + platform_set_drvdata(pdev, NULL);
>> +
>> + return 0;
>> +}
>> +
>> +#ifdef CONFIG_PM
>> +static int exynos5_i2c_suspend_noirq(struct device *dev)
>> +{
>> + struct platform_device *pdev = to_platform_device(dev);
>> + struct exynos5_i2c *i2c = platform_get_drvdata(pdev);
>> +
>> + i2c->suspended = 1;
>> +
>> + return 0;
>> +}
>> +
>> +static int exynos5_i2c_resume_noirq(struct device *dev)
>> +{
>> + struct platform_device *pdev = to_platform_device(dev);
>> + struct exynos5_i2c *i2c = platform_get_drvdata(pdev);
>> +
>> + clk_prepare_enable(i2c->clk);
>> + exynos5_i2c_init(i2c);
>> + clk_disable_unprepare(i2c->clk);
>> + i2c->suspended = 0;
>> +
>> + return 0;
>> +}
>> +
>> +static const struct dev_pm_ops exynos5_i2c_dev_pm_ops = {
>> + .suspend_noirq = exynos5_i2c_suspend_noirq,
>> + .resume_noirq = exynos5_i2c_resume_noirq,
>> +};
>> +
>> +#define EXYNOS5_DEV_PM_OPS (&exynos5_i2c_dev_pm_ops)
>> +#else
>> +#define EXYNOS5_DEV_PM_OPS NULL
>> +#endif
>> +
>> +static struct platform_driver exynos5_i2c_driver = {
>> + .probe = exynos5_i2c_probe,
>> + .remove = exynos5_i2c_remove,
>> + .driver = {
>> + .owner = THIS_MODULE,
>> + .name = "exynos5-hsi2c",
>> + .pm = EXYNOS5_DEV_PM_OPS,
>> + .of_match_table = exynos5_i2c_match,
>> + },
>> +};
>> +
>> +static int __init i2c_adap_exynos5_init(void)
>> +{
>> + return platform_driver_register(&exynos5_i2c_driver);
>> +}
>> +subsys_initcall(i2c_adap_exynos5_init);
>> +
>> +static void __exit i2c_adap_exynos5_exit(void)
>> +{
>> + platform_driver_unregister(&exynos5_i2c_driver);
>> +}
>> +module_exit(i2c_adap_exynos5_exit);
>> +
>> +MODULE_DESCRIPTION("Exynos5 HS-I2C Bus driver");
>> +MODULE_AUTHOR("Naveen Krishna Chatradhi, <ch.naveen@samsung.com>");
>> +MODULE_AUTHOR("Taekgyun Ko, <taeggyun.ko@samsung.com>");
>> +MODULE_LICENSE("GPL");
>> --
>> 1.7.9.5
Any comments please. Thanks in advance
>>
>
>
>
> --
> Shine bright,
> (: Nav :)
--
Shine bright,
(: Nav :)
^ permalink raw reply
* [PATCH 15/16] ARM: vexpress/dcscb: handle platform coherency exit/setup and CCI
From: Santosh Shilimkar @ 2013-01-15 6:23 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20130114122547.GA21142@e102568-lin.cambridge.arm.com>
On Monday 14 January 2013 05:55 PM, Lorenzo Pieralisi wrote:
> On Sat, Jan 12, 2013 at 07:21:24AM +0000, Santosh Shilimkar wrote:
>> On Saturday 12 January 2013 12:58 AM, Nicolas Pitre wrote:
>>> On Fri, 11 Jan 2013, Santosh Shilimkar wrote:
>>>
>>>> On Thursday 10 January 2013 05:50 AM, Nicolas Pitre wrote:
>>>>> From: Dave Martin <dave.martin@linaro.org>
>>>>>
>>>>> + /*
>>>>> + * Flush the local CPU cache.
>>>>> + *
>>>>> + * A15/A7 can hit in the cache with SCTLR.C=0, so we don't need
>>>>> + * a preliminary flush here for those CPUs. At least, that's
>>>>> + * the theory -- without the extra flush, Linux explodes on
>>>>> + * RTSM (maybe not needed anymore, to be investigated).
>>>>> + */
>>>> This is expected if the entire code is not in one stack frame and the
>>>> additional flush is needed to avoid possible stack corruption. This
>>>> issue has been discussed in past on the list.
>>>
>>> I missed that. Do you have a reference or pointer handy?
>>>
>>> What is strange is that this is 100% reproducible on RTSM while this
>>> apparently is not an issue on real hardware so far.
>>>
>> I tried searching archives and realized the discussion was in private
>> email thread. There are some bits and pieces on list but not all the
>> information.
>>
>> The main issue RMK pointed out is- An additional L1 flush needed
>> to avoid the effective change of view of memory when the C bit is
>> turned off, and the cache is no longer searched for local CPU accesses.
>>
>> In your case dcscb_power_down() has updated the stack which can be hit
>> in cache line and hence cache is dirty now. Then cpu_proc_fin() clears
>> the C-bit and hence for sub sequent calls the L1 cache won't be
>> searched. You then call flush_cache_all() which again updates the
>> stack but avoids searching the L1 cache. So it overwrites previous
>> saved stack frame. This seems to be an issue in your case as well.
>
> On A15/A7 even with the C bit cleared the D-cache is searched, the
> situation above cannot happen and if it does we are facing a HW/model bug.
> If this code is run on A9 then we have a problem since there, when the C bit
> is cleared D-cache is not searched (and that's why the sequence above
> should be written in assembly with no data access whatsoever), but on
> A15/A7 we do not.
>
Good point. May be model has modeled A9 and not A15 but in either
case, lets be consistent for all ARMv7 machines at least to avoid
people debugging similar issues. Many machines share code for ARMv7
processors so the best things is to stick to the sequence which works
across all ARMv7 processors.
> I have been running this code on TC2 for hours on end with nary a problem.
>
Thanks for the additional information.
> The sequence:
>
> - clear C bit
> - clean D-cache
> - exit SMP
>
> must be written in assembly with no data access whatsoever to make it
> portable across v7 implementations. I think I will write some docs and
> add them to the kernel to avoid further discussion on this topic.
>
Best thing is to update the ARM Architecture Reference Manual because
thats is what most of the time gets referred by many OS vendors.
> FYI, the thread Santosh mentioned:
>
> http://lists.infradead.org/pipermail/linux-arm-kernel/2012-May/099791.html
>
Yes. This is one of the relevant thread. Thanks.
Regards,
Santosh
^ permalink raw reply
* [V3 PATCH 25/25] usb: ehci: ehci-mv: add device tree support
From: Chao Xie @ 2013-01-15 6:19 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1358230758-10176-1-git-send-email-chao.xie@marvell.com>
All blocks are removed. Add the device tree support for ehci.
Signed-off-by: Chao Xie <chao.xie@marvell.com>
Acked-by: Alan Stern <stern@rowland.harvard.edu>
---
drivers/usb/host/ehci-mv.c | 104 +++++++++++++++++++++++++++++++++-----------
1 files changed, 79 insertions(+), 25 deletions(-)
diff --git a/drivers/usb/host/ehci-mv.c b/drivers/usb/host/ehci-mv.c
index 171e145..0e99dac 100644
--- a/drivers/usb/host/ehci-mv.c
+++ b/drivers/usb/host/ehci-mv.c
@@ -13,6 +13,7 @@
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
+#include <linux/of.h>
#include <linux/err.h>
#include <linux/usb/otg.h>
#include <linux/usb/mv_usb2.h>
@@ -32,11 +33,9 @@ struct ehci_hcd_mv {
struct usb_phy *otg;
- struct mv_usb_platform_data *pdata;
-
/* clock source and total clock number */
unsigned int clknum;
- struct clk *clk[0];
+ struct clk **clk;
};
static void ehci_clock_enable(struct ehci_hcd_mv *ehci_mv)
@@ -138,22 +137,55 @@ static const struct hc_driver mv_ehci_hc_driver = {
.bus_resume = ehci_bus_resume,
};
+static int __devinit mv_ehci_parse_dt(struct platform_device *pdev,
+ struct ehci_hcd_mv *ehci_mv)
+{
+ struct device_node *np = pdev->dev.of_node;
+ unsigned int clks_num;
+ int i, ret;
+ const char *clk_name;
+
+ if (!np)
+ return 1;
+
+ clks_num = of_property_count_strings(np, "clocks");
+ if (clks_num < 0)
+ return clks_num;
+
+ ehci_mv->clk = devm_kzalloc(&pdev->dev,
+ sizeof(struct clk *) * clks_num, GFP_KERNEL);
+ if (ehci_mv->clk == NULL)
+ return -ENOMEM;
+
+ for (i = 0; i < clks_num; i++) {
+ ret = of_property_read_string_index(np, "clocks", i,
+ &clk_name);
+ if (ret)
+ return ret;
+ ehci_mv->clk[i] = clk_get(NULL, clk_name);
+ if (IS_ERR(ehci_mv->clk[i]))
+ return PTR_ERR(ehci_mv->clk[i]);
+ }
+
+ ehci_mv->clknum = clks_num;
+
+ ret = of_property_read_u32(np, "mode", &ehci_mv->mode);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
static int mv_ehci_probe(struct platform_device *pdev)
{
- struct mv_usb_platform_data *pdata = pdev->dev.platform_data;
struct usb_hcd *hcd;
struct ehci_hcd *ehci;
struct ehci_hcd_mv *ehci_mv;
struct resource *r;
- int clk_i, retval = -ENODEV;
+ int retval = -ENODEV;
u32 offset;
size_t size;
- if (!pdata) {
- dev_err(&pdev->dev, "missing platform_data\n");
- return -ENODEV;
- }
-
if (usb_disabled())
return -ENODEV;
@@ -161,7 +193,7 @@ static int mv_ehci_probe(struct platform_device *pdev)
if (!hcd)
return -ENOMEM;
- size = sizeof(*ehci_mv) + sizeof(struct clk *) * pdata->clknum;
+ size = sizeof(*ehci_mv);
ehci_mv = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
if (ehci_mv == NULL) {
dev_err(&pdev->dev, "cannot allocate ehci_hcd_mv\n");
@@ -170,19 +202,36 @@ static int mv_ehci_probe(struct platform_device *pdev)
}
platform_set_drvdata(pdev, ehci_mv);
- ehci_mv->pdata = pdata;
ehci_mv->hcd = hcd;
- ehci_mv->clknum = pdata->clknum;
- for (clk_i = 0; clk_i < ehci_mv->clknum; clk_i++) {
- ehci_mv->clk[clk_i] =
- devm_clk_get(&pdev->dev, pdata->clkname[clk_i]);
- if (IS_ERR(ehci_mv->clk[clk_i])) {
- dev_err(&pdev->dev, "error get clck \"%s\"\n",
- pdata->clkname[clk_i]);
- retval = PTR_ERR(ehci_mv->clk[clk_i]);
- goto err_clear_drvdata;
+ retval = mv_ehci_parse_dt(pdev, ehci_mv);
+ if (retval > 0) {
+ struct mv_usb_platform_data *pdata = pdev->dev.platform_data;
+ int clk_i = 0;
+
+ /* no CONFIG_OF */
+ if (pdata == NULL) {
+ dev_err(&pdev->dev, "missing platform_data\n");
+ return -ENODEV;
+ }
+ ehci_mv->mode = pdata->mode;
+ ehci_mv->clknum = pdata->clknum;
+
+ size = sizeof(struct clk *) * ehci_mv->clknum;
+ ehci_mv->clk = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
+ if (ehci_mv->clk == NULL)
+ return -ENOMEM;
+ for (clk_i = 0; clk_i < ehci_mv->clknum; clk_i++) {
+ ehci_mv->clk[clk_i] = devm_clk_get(&pdev->dev,
+ pdata->clkname[clk_i]);
+ if (IS_ERR(ehci_mv->clk[clk_i])) {
+ retval = PTR_ERR(ehci_mv->clk[clk_i]);
+ return retval;
+ }
}
+ } else if (retval < 0) {
+ dev_err(&pdev->dev, "error parse dt\n");
+ return retval;
}
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -230,7 +279,6 @@ static int mv_ehci_probe(struct platform_device *pdev)
ehci = hcd_to_ehci(hcd);
ehci->caps = (struct ehci_caps *) ehci_mv->cap_regs;
- ehci_mv->mode = pdata->mode;
if (ehci_mv->mode == MV_USB_MODE_OTG) {
#ifdef CONFIG_USB_OTG_UTILS
ehci_mv->otg = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2);
@@ -334,13 +382,19 @@ static void mv_ehci_shutdown(struct platform_device *pdev)
hcd->driver->shutdown(hcd);
}
+static struct of_device_id mv_ehci_dt_ids[] = {
+ { .compatible = "mrvl,mv-ehci" },
+};
+MODULE_DEVICE_TABLE(of, mv_ehci_dt_ids);
+
static struct platform_driver ehci_mv_driver = {
.probe = mv_ehci_probe,
.remove = mv_ehci_remove,
.shutdown = mv_ehci_shutdown,
.driver = {
- .name = "mv-ehci",
- .bus = &platform_bus_type,
- },
+ .name = "mv-ehci",
+ .bus = &platform_bus_type,
+ .of_match_table = mv_ehci_dt_ids,
+ },
.id_table = ehci_id_table,
};
--
1.7.4.1
^ permalink raw reply related
* [V3 PATCH 24/25] usb: otg: mv_otg: add device tree support
From: Chao Xie @ 2013-01-15 6:19 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1358230758-10176-1-git-send-email-chao.xie@marvell.com>
All blocks are removed. Add the device tree support for otg.
Signed-off-by: Chao Xie <chao.xie@marvell.com>
---
drivers/usb/otg/mv_otg.c | 127 +++++++++++++++++++++++++++++++++++++--------
drivers/usb/otg/mv_otg.h | 6 +-
2 files changed, 107 insertions(+), 26 deletions(-)
diff --git a/drivers/usb/otg/mv_otg.c b/drivers/usb/otg/mv_otg.c
index 379df92..89b5512 100644
--- a/drivers/usb/otg/mv_otg.c
+++ b/drivers/usb/otg/mv_otg.c
@@ -17,6 +17,7 @@
#include <linux/device.h>
#include <linux/proc_fs.h>
#include <linux/clk.h>
+#include <linux/of.h>
#include <linux/workqueue.h>
#include <linux/platform_device.h>
@@ -333,7 +334,7 @@ static void mv_otg_update_inputs(struct mv_otg *mvotg)
else
otg_ctrl->id = !!(otgsc & OTGSC_STS_USB_ID);
- if (mvotg->pdata->otg_force_a_bus_req && !otg_ctrl->id)
+ if (mvotg->otg_force_a_bus_req && !otg_ctrl->id)
otg_ctrl->a_bus_req = 1;
otg_ctrl->a_sess_vld = !!(otgsc & OTGSC_STS_A_SESSION_VALID);
@@ -690,21 +691,69 @@ int mv_otg_remove(struct platform_device *pdev)
return 0;
}
+static int mv_otg_parse_dt(struct platform_device *pdev,
+ struct mv_otg *mvotg)
+{
+ struct device_node *np = pdev->dev.of_node;
+ unsigned int clks_num;
+ unsigned int val;
+ int i, ret;
+ const char *clk_name;
+
+ if (!np)
+ return 1;
+
+ clks_num = of_property_count_strings(np, "clocks");
+ if (clks_num < 0)
+ return clks_num;
+
+ mvotg->clk = devm_kzalloc(&pdev->dev,
+ sizeof(struct clk *) * clks_num, GFP_KERNEL);
+ if (mvotg->clk == NULL)
+ return -ENOMEM;
+
+ for (i = 0; i < clks_num; i++) {
+ ret = of_property_read_string_index(np, "clocks", i,
+ &clk_name);
+ if (ret)
+ return ret;
+ mvotg->clk[i] = devm_clk_get(&pdev->dev, clk_name);
+ if (IS_ERR(mvotg->clk[i]))
+ return PTR_ERR(mvotg->clk[i]);
+ }
+
+ mvotg->clknum = clks_num;
+
+ ret = of_property_read_u32(np, "extern_attr", &mvotg->extern_attr);
+ if (ret)
+ return ret;
+
+ ret = of_property_read_u32(np, "mode", &mvotg->mode);
+ if (ret)
+ return ret;
+
+ ret = of_property_read_u32(np, "force_a_bus_req", &val);
+ if (ret)
+ return ret;
+ mvotg->otg_force_a_bus_req = !!val;
+
+ ret = of_property_read_u32(np, "disable_clock_gating", &val);
+ if (ret)
+ return ret;
+ mvotg->clock_gating = !val;
+
+ return 0;
+}
+
static int mv_otg_probe(struct platform_device *pdev)
{
- struct mv_usb_platform_data *pdata = pdev->dev.platform_data;
struct mv_otg *mvotg;
struct usb_otg *otg;
struct resource *r;
- int retval = 0, clk_i, i;
+ int retval = 0, i;
size_t size;
- if (pdata == NULL) {
- dev_err(&pdev->dev, "failed to get platform data\n");
- return -ENODEV;
- }
-
- size = sizeof(*mvotg) + sizeof(struct clk *) * pdata->clknum;
+ size = sizeof(*mvotg);
mvotg = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
if (!mvotg) {
dev_err(&pdev->dev, "failed to allocate memory!\n");
@@ -718,17 +767,45 @@ static int mv_otg_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, mvotg);
mvotg->pdev = pdev;
- mvotg->extern_attr = pdata->extern_attr;
- mvotg->pdata = pdata;
- mvotg->clknum = pdata->clknum;
- for (clk_i = 0; clk_i < mvotg->clknum; clk_i++) {
- mvotg->clk[clk_i] = devm_clk_get(&pdev->dev,
+ retval = mv_otg_parse_dt(pdev, mvotg);
+ if (retval > 0) {
+ struct mv_usb_platform_data *pdata = pdev->dev.platform_data;
+ /* no CONFIG_OF */
+ int clk_i = 0;
+
+ if (pdata == NULL) {
+ dev_err(&pdev->dev, "missing platform_data\n");
+ return -ENODEV;
+ }
+ mvotg->extern_attr = pdata->extern_attr;
+ mvotg->mode = pdata->mode;
+ mvotg->clknum = pdata->clknum;
+ mvotg->otg_force_a_bus_req = pdata->otg_force_a_bus_req;
+ if (pdata->disable_otg_clock_gating)
+ mvotg->clock_gating = 0;
+
+ size = sizeof(struct clk *) * mvotg->clknum;
+ mvotg->clk = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
+ if (mvotg->clk == NULL) {
+ dev_err(&pdev->dev,
+ "failed to allocate memory for clk\n");
+ return -ENOMEM;
+ }
+
+ for (clk_i = 0; clk_i < mvotg->clknum; clk_i++) {
+ mvotg->clk[clk_i] = devm_clk_get(&pdev->dev,
pdata->clkname[clk_i]);
- if (IS_ERR(mvotg->clk[clk_i])) {
- retval = PTR_ERR(mvotg->clk[clk_i]);
- return retval;
+ if (IS_ERR(mvotg->clk[clk_i])) {
+ dev_err(&pdev->dev, "failed to get clk %s\n",
+ pdata->clkname[clk_i]);
+ retval = PTR_ERR(mvotg->clk[clk_i]);
+ return retval;
+ }
}
+ } else if (retval < 0) {
+ dev_err(&pdev->dev, "error parse dt\n");
+ return retval;
}
mvotg->qwork = create_singlethread_workqueue("mv_otg_queue");
@@ -770,6 +847,7 @@ static int mv_otg_probe(struct platform_device *pdev)
}
mvotg->mvphy = mv_usb2_get_phy();
if (mvotg->mvphy == NULL) {
+ dev_err(&pdev->dev, "failed to get usb phy\n");
retval = -ENODEV;
goto err_destroy_workqueue;
}
@@ -791,9 +869,6 @@ static int mv_otg_probe(struct platform_device *pdev)
mv_usb2_register_notifier(mvotg->mvphy, &mvotg->notifier);
}
- if (pdata->disable_otg_clock_gating)
- mvotg->clock_gating = 0;
-
mv_otg_reset(mvotg);
mv_otg_init_irq(mvotg);
@@ -892,13 +967,19 @@ static int mv_otg_resume(struct platform_device *pdev)
}
#endif
+static struct of_device_id mv_otg_dt_ids[] = {
+ { .compatible = "mrvl,mv-otg" },
+};
+MODULE_DEVICE_TABLE(of, mv_otg_dt_ids);
+
static struct platform_driver mv_otg_driver = {
.probe = mv_otg_probe,
.remove = __exit_p(mv_otg_remove),
.driver = {
- .owner = THIS_MODULE,
- .name = driver_name,
- },
+ .owner = THIS_MODULE,
+ .name = driver_name,
+ .of_match_table = mv_otg_dt_ids,
+ },
#ifdef CONFIG_PM
.suspend = mv_otg_suspend,
.resume = mv_otg_resume,
diff --git a/drivers/usb/otg/mv_otg.h b/drivers/usb/otg/mv_otg.h
index f5bc7dd..3b9356d 100644
--- a/drivers/usb/otg/mv_otg.h
+++ b/drivers/usb/otg/mv_otg.h
@@ -157,12 +157,12 @@ struct mv_otg {
spinlock_t wq_lock;
- struct mv_usb_platform_data *pdata;
-
unsigned int active;
unsigned int clock_gating;
+ unsigned int mode;
+ unsigned int otg_force_a_bus_req;
unsigned int clknum;
- struct clk *clk[0];
+ struct clk **clk;
};
#endif
--
1.7.4.1
^ 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