* [PATCH 1/5] ARM: dts: emev2: Remove skeleton.dtsi inclusion
From: Geert Uytterhoeven @ 2016-10-21 9:16 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1477041370-22778-1-git-send-email-geert+renesas@glider.be>
As of commit 9c0da3cc61f1233c ("ARM: dts: explicitly mark skeleton.dtsi
as deprecated"), including skeleton.dtsi is deprecated.
This fixes the following warning with W=1:
Warning (unit_address_vs_reg): Node /memory has a reg or ranges property, but no unit name
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
---
arch/arm/boot/dts/emev2.dtsi | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/arch/arm/boot/dts/emev2.dtsi b/arch/arm/boot/dts/emev2.dtsi
index cd119400f440bb5a..0124faf175c8612b 100644
--- a/arch/arm/boot/dts/emev2.dtsi
+++ b/arch/arm/boot/dts/emev2.dtsi
@@ -8,13 +8,14 @@
* kind, whether express or implied.
*/
-#include "skeleton.dtsi"
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/interrupt-controller/irq.h>
/ {
compatible = "renesas,emev2";
interrupt-parent = <&gic>;
+ #address-cells = <1>;
+ #size-cells = <1>;
aliases {
gpio0 = &gpio0;
--
1.9.1
^ permalink raw reply related
* [PATCH 0/5] ARM: dts: renesas: Remove skeleton.dtsi inclusion
From: Geert Uytterhoeven @ 2016-10-21 9:16 UTC (permalink / raw)
To: linux-arm-kernel
Hi Simon, Magnus,
As of commit 9c0da3cc61f1233c ("ARM: dts: explicitly mark skeleton.dtsi
as deprecated"), including skeleton.dtsi is deprecated.
Hence this series removes its use for all Renesas 32-bit ARM SoCs.
This fixes the following warning seen with W=1:
Warning (unit_address_vs_reg): Node /memory has a reg or ranges property, but no unit name
Thanks for applying!
Geert Uytterhoeven (5):
ARM: dts: emev2: Remove skeleton.dtsi inclusion
ARM: dts: r8a7778: Remove skeleton.dtsi inclusion
ARM: dts: r8a7779: Remove skeleton.dtsi inclusion
ARM: dts: r8a7740: Remove skeleton.dtsi inclusion
ARM: dts: sh73a0: Remove skeleton.dtsi inclusion
arch/arm/boot/dts/emev2.dtsi | 3 ++-
arch/arm/boot/dts/r8a7740.dtsi | 4 ++--
arch/arm/boot/dts/r8a7778.dtsi | 4 ++--
arch/arm/boot/dts/r8a7779.dtsi | 4 ++--
arch/arm/boot/dts/sh73a0.dtsi | 4 ++--
5 files changed, 10 insertions(+), 9 deletions(-)
--
1.9.1
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert at linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
^ permalink raw reply
* [PATCH] ARM: sti: stih407-clocks: Identify critical clocks
From: Peter Griffin @ 2016-10-21 9:08 UTC (permalink / raw)
To: linux-arm-kernel
Lots of platforms contain clocks which if turned off would prove fatal.
The only way to recover is to restart the board(s). This driver takes
references to clocks which are required to be always-on. The Common
Clk Framework will then take references to them. This way they will
not be turned off during the clk_disabled_unused() procedure.
In this patch we are identifying clocks, which if gated would render
the STiH407 development board unserviceable.
Signed-off-by: Peter Griffin <peter.griffin@linaro.org>
---
arch/arm/boot/dts/stih407-clock.dtsi | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/arch/arm/boot/dts/stih407-clock.dtsi b/arch/arm/boot/dts/stih407-clock.dtsi
index 13029c0..34c119a 100644
--- a/arch/arm/boot/dts/stih407-clock.dtsi
+++ b/arch/arm/boot/dts/stih407-clock.dtsi
@@ -101,6 +101,7 @@
clocks = <&clk_sysin>;
clock-output-names = "clk-s-a0-pll-ofd-0";
+ clock-critical = <0>; /* clk-s-a0-pll-ofd-0 */
};
clk_s_a0_flexgen: clk-s-a0-flexgen {
@@ -112,6 +113,7 @@
<&clk_sysin>;
clock-output-names = "clk-ic-lmi0";
+ clock-critical = <CLK_IC_LMI0>;
};
};
@@ -126,6 +128,7 @@
"clk-s-c0-fs0-ch1",
"clk-s-c0-fs0-ch2",
"clk-s-c0-fs0-ch3";
+ clock-critical = <0>; /* clk-s-c0-fs0-ch0 */
};
clk_s_c0: clockgen-c at 09103000 {
@@ -139,6 +142,7 @@
clocks = <&clk_sysin>;
clock-output-names = "clk-s-c0-pll0-odf-0";
+ clock-critical = <0>; /* clk-s-c0-pll0-odf-0 */
};
clk_s_c0_pll1: clk-s-c0-pll1 {
@@ -194,6 +198,12 @@
"clk-main-disp",
"clk-aux-disp",
"clk-compo-dvp";
+ clock-critical = <CLK_PROC_STFE>,
+ <CLK_ICN_CPU>,
+ <CLK_TX_ICN_DMU>,
+ <CLK_EXT2F_A9>,
+ <CLK_ICN_LMI>,
+ <CLK_ICN_SBC>;
};
};
--
1.9.1
^ permalink raw reply related
* [PATCH 4/9] pinctrl: meson: allow gpio to request irq
From: Jerome Brunet @ 2016-10-21 9:06 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CACRpkdaCZPS45t3eTcjJExOu=YT_YkjNkdpg09jQqvLQOJH=Qw@mail.gmail.com>
On Thu, 2016-10-20 at 21:21 +0200, Linus Walleij wrote:
> On Wed, Oct 19, 2016 at 12:08 PM, Jerome Brunet <jbrunet@baylibre.com
> > wrote:
>
> >
> > Add the ability for gpio to request irq from the gpio interrupt
> > controller
> > if present. We have to specificaly that the parent interrupt
> > controller is
> > the gpio interrupt controller because gpio on meson SoCs can't
> > generate
> > interrupt directly on the GIC.
> >
> > Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
> (...)
> >
> > +???????select IRQ_DOMAIN
> > ????????select OF_GPIO
> > +???????select OF_IRQ
> (...)
> >
> > +static int meson_gpio_to_hwirq(struct meson_bank *bank, unsigned
> > int offset)
> > +{
> > +???????unsigned int hwirq;
> > +
> > +???????if (bank->irq_first < 0)
> > +???????????????/* this bank cannot generate irqs */
> > +???????????????return -1;
> > +
> > +???????hwirq = offset - bank->first + bank->irq_first;
> > +
> > +???????if (hwirq > bank->irq_last)
> > +???????????????/* this pin cannot generate irqs */
> > +???????????????return -1;
> > +
> > +???????return hwirq;
> > +}
>
> This is reimplementing irqdomain.
>
> >
> > +static int meson_gpio_to_irq(struct gpio_chip *chip, unsigned int
> > offset)
> > +{
> (...)
> >
> > +???????hwirq = meson_gpio_to_hwirq(bank, offset);
> > +???????if (hwirq < 0) {
> > +???????????????dev_dbg(pc->dev, "no interrupt for pin %u\n",
> > offset);
> > +???????????????return 0;
> > +???????}
>
> Isn't this usecase (also as described in the cover letter) a textbook
> example of when you should be using hierarchical irqdomain?
>
> Please check with Marc et al on hierarchical irqdomains.
Linus,
Do you mean I should create a new hierarchical?irqdomains in each of
the two pinctrl instances we have in these SoC, these domains being
stacked on the one I just added for controller in irqchip ?
I did not understand this is what you meant when I asked you the
question at ELCE.
>
> Yours,
> Linus Walleij
^ permalink raw reply
* [PATCH v3 00/17] pinctrl: exynos/samsung: Add header with values used for configuration
From: Linus Walleij @ 2016-10-21 9:02 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1472987060-28293-1-git-send-email-krzk@kernel.org>
On Sun, Sep 4, 2016 at 1:04 PM, Krzysztof Kozlowski <krzk@kernel.org> wrote:
> pinctrl: dt-bindings: samsung: Add header with values used for
> configuration
> pinctrl: dt-bindings: samsung: Update documentation with new macros
These two:
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Please merge all of it through the Exynos tree and ARM SoC once
you're done with the rewrite.
Yours,
Linus Walleij
^ permalink raw reply
* [PATCH v2 2/2] ARM: oxnas: Add OX820 config and makefile entry
From: Neil Armstrong @ 2016-10-21 8:58 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161021085848.1754-1-narmstrong@baylibre.com>
Refactor the oxnas Kconfig entries among the OX810SE and OX820 configs,
and add the files to support the OX820 SMP feature.
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
arch/arm/Makefile | 1 +
arch/arm/mach-oxnas/Kconfig | 30 +++++++++++++++++++++---------
2 files changed, 22 insertions(+), 9 deletions(-)
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 6be9ee1..68312a9 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -191,6 +191,7 @@ machine-$(CONFIG_ARCH_MXS) += mxs
machine-$(CONFIG_ARCH_NETX) += netx
machine-$(CONFIG_ARCH_NOMADIK) += nomadik
machine-$(CONFIG_ARCH_NSPIRE) += nspire
+machine-$(CONFIG_ARCH_OXNAS) += oxnas
machine-$(CONFIG_ARCH_OMAP1) += omap1
machine-$(CONFIG_ARCH_OMAP2PLUS) += omap2
machine-$(CONFIG_ARCH_ORION5X) += orion5x
diff --git a/arch/arm/mach-oxnas/Kconfig b/arch/arm/mach-oxnas/Kconfig
index 29100be..8fa4557 100644
--- a/arch/arm/mach-oxnas/Kconfig
+++ b/arch/arm/mach-oxnas/Kconfig
@@ -1,9 +1,16 @@
menuconfig ARCH_OXNAS
bool "Oxford Semiconductor OXNAS Family SoCs"
select ARCH_HAS_RESET_CONTROLLER
+ select COMMON_CLK_OXNAS
select GPIOLIB
+ select MFD_SYSCON
+ select OXNAS_RPS_TIMER
+ select PINCTRL_OXNAS
+ select RESET_CONTROLLER
+ select RESET_OXNAS
+ select VERSATILE_FPGA_IRQ
select PINCTRL
- depends on ARCH_MULTI_V5
+ depends on ARCH_MULTI_V5 || ARCH_MULTI_V6
help
Support for OxNas SoC family developed by Oxford Semiconductor.
@@ -11,16 +18,21 @@ if ARCH_OXNAS
config MACH_OX810SE
bool "Support OX810SE Based Products"
- select ARCH_HAS_RESET_CONTROLLER
- select COMMON_CLK_OXNAS
+ depends on ARCH_MULTI_V5
select CPU_ARM926T
- select MFD_SYSCON
- select OXNAS_RPS_TIMER
- select PINCTRL_OXNAS
- select RESET_CONTROLLER
- select RESET_OXNAS
- select VERSATILE_FPGA_IRQ
help
Include Support for the Oxford Semiconductor OX810SE SoC Based Products.
+config MACH_OX820
+ bool "Support OX820 Based Products"
+ depends on ARCH_MULTI_V6
+ select ARM_GIC
+ select DMA_CACHE_RWFO if SMP
+ select CPU_V6K
+ select HAVE_SMP
+ select HAVE_ARM_SCU if SMP
+ select HAVE_ARM_TWD if SMP
+ help
+ Include Support for the Oxford Semiconductor OX820 SoC Based Products.
+
endif
--
2.7.0
^ permalink raw reply related
* [PATCH v2 1/2] ARM: oxnas: Add OX820 SMP support
From: Neil Armstrong @ 2016-10-21 8:58 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161021085848.1754-1-narmstrong@baylibre.com>
The Oxford Semiconductor OX820 is a ARM11MPcore based SoC sharing some
features with the OX810 earlier SoC.
This patch adds the core to wake up the second core.
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
arch/arm/mach-oxnas/Makefile | 2 +
arch/arm/mach-oxnas/headsmp.S | 28 +++++++++++
arch/arm/mach-oxnas/hotplug.c | 111 ++++++++++++++++++++++++++++++++++++++++++
arch/arm/mach-oxnas/platsmp.c | 104 +++++++++++++++++++++++++++++++++++++++
4 files changed, 245 insertions(+)
create mode 100644 arch/arm/mach-oxnas/Makefile
create mode 100644 arch/arm/mach-oxnas/headsmp.S
create mode 100644 arch/arm/mach-oxnas/hotplug.c
create mode 100644 arch/arm/mach-oxnas/platsmp.c
diff --git a/arch/arm/mach-oxnas/Makefile b/arch/arm/mach-oxnas/Makefile
new file mode 100644
index 0000000..b625906
--- /dev/null
+++ b/arch/arm/mach-oxnas/Makefile
@@ -0,0 +1,2 @@
+obj-$(CONFIG_SMP) += platsmp.o headsmp.o
+obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
diff --git a/arch/arm/mach-oxnas/headsmp.S b/arch/arm/mach-oxnas/headsmp.S
new file mode 100644
index 0000000..2a94dcb
--- /dev/null
+++ b/arch/arm/mach-oxnas/headsmp.S
@@ -0,0 +1,28 @@
+/*
+ * linux/arch/arm/mach-oxnas/headsmp.S
+ *
+ * Copyright (C) 2013 Ma Haijun <mahaijuns@gmail.com>
+ * Copyright (c) 2003 ARM Limited
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/linkage.h>
+#include <linux/init.h>
+
+ __INIT
+
+/*
+ * OX820 specific entry point for secondary CPUs.
+ */
+ENTRY(ox820_secondary_startup)
+ mov r4, #0
+ /* invalidate both caches and branch target cache */
+ mcr p15, 0, r4, c7, c7, 0
+ /*
+ * we've been released from the holding pen: secondary_stack
+ * should now contain the SVC stack for this core
+ */
+ b secondary_startup
diff --git a/arch/arm/mach-oxnas/hotplug.c b/arch/arm/mach-oxnas/hotplug.c
new file mode 100644
index 0000000..18fa814
--- /dev/null
+++ b/arch/arm/mach-oxnas/hotplug.c
@@ -0,0 +1,111 @@
+/*
+ * linux/arch/arm/mach-oxnas/hotplug.c
+ *
+ * Copyright (C) 2002 ARM Ltd.
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/smp.h>
+
+#include <asm/cp15.h>
+#include <asm/smp_plat.h>
+
+static inline void cpu_enter_lowpower(void)
+{
+ unsigned int v;
+
+ asm volatile(
+ " mcr p15, 0, %1, c7, c5, 0\n"
+ " mcr p15, 0, %1, c7, c10, 4\n"
+ /*
+ * Turn off coherency
+ */
+ " mrc p15, 0, %0, c1, c0, 1\n"
+ " bic %0, %0, #0x20\n"
+ " mcr p15, 0, %0, c1, c0, 1\n"
+ " mrc p15, 0, %0, c1, c0, 0\n"
+ " bic %0, %0, %2\n"
+ " mcr p15, 0, %0, c1, c0, 0\n"
+ : "=&r" (v)
+ : "r" (0), "Ir" (CR_C)
+ : "cc");
+}
+
+static inline void cpu_leave_lowpower(void)
+{
+ unsigned int v;
+
+ asm volatile( "mrc p15, 0, %0, c1, c0, 0\n"
+ " orr %0, %0, %1\n"
+ " mcr p15, 0, %0, c1, c0, 0\n"
+ " mrc p15, 0, %0, c1, c0, 1\n"
+ " orr %0, %0, #0x20\n"
+ " mcr p15, 0, %0, c1, c0, 1\n"
+ : "=&r" (v)
+ : "Ir" (CR_C)
+ : "cc");
+}
+
+static inline void platform_do_lowpower(unsigned int cpu, int *spurious)
+{
+ /*
+ * there is no power-control hardware on this platform, so all
+ * we can do is put the core into WFI; this is safe as the calling
+ * code will have already disabled interrupts
+ */
+ for (;;) {
+ /*
+ * here's the WFI
+ */
+ asm(".word 0xe320f003\n"
+ :
+ :
+ : "memory", "cc");
+
+ if (pen_release == cpu_logical_map(cpu)) {
+ /*
+ * OK, proper wakeup, we're done
+ */
+ break;
+ }
+
+ /*
+ * Getting here, means that we have come out of WFI without
+ * having been woken up - this shouldn't happen
+ *
+ * Just note it happening - when we're woken, we can report
+ * its occurrence.
+ */
+ (*spurious)++;
+ }
+}
+
+/*
+ * platform-specific code to shutdown a CPU
+ *
+ * Called with IRQs disabled
+ */
+void ox820_cpu_die(unsigned int cpu)
+{
+ int spurious = 0;
+
+ /*
+ * we're ready for shutdown now, so do it
+ */
+ cpu_enter_lowpower();
+ platform_do_lowpower(cpu, &spurious);
+
+ /*
+ * bring this CPU back into the world of cache
+ * coherency, and then restore interrupts
+ */
+ cpu_leave_lowpower();
+
+ if (spurious)
+ pr_warn("CPU%u: %u spurious wakeup calls\n", cpu, spurious);
+}
diff --git a/arch/arm/mach-oxnas/platsmp.c b/arch/arm/mach-oxnas/platsmp.c
new file mode 100644
index 0000000..fd263b3
--- /dev/null
+++ b/arch/arm/mach-oxnas/platsmp.c
@@ -0,0 +1,104 @@
+/*
+ * arch/arm/mach-oxnas/platsmp.c
+ *
+ * Copyright (C) 2016 Neil Armstrong <narmstrong@baylibre.com>
+ * Copyright (C) 2013 Ma Haijun <mahaijuns@gmail.com>
+ * Copyright (C) 2002 ARM Ltd.
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+#include <asm/cacheflush.h>
+#include <asm/cp15.h>
+#include <asm/smp_plat.h>
+#include <asm/smp_scu.h>
+
+extern void ox820_secondary_startup(void);
+extern void ox820_cpu_die(unsigned int cpu);
+
+static void __iomem *cpu_ctrl;
+static void __iomem *gic_cpu_ctrl;
+
+#define HOLDINGPEN_CPU_OFFSET 0xc8
+#define HOLDINGPEN_LOCATION_OFFSET 0xc4
+
+#define GIC_NCPU_OFFSET(cpu) (0x100 + (cpu)*0x100)
+#define GIC_CPU_CTRL 0x00
+#define GIC_CPU_CTRL_ENABLE 1
+
+int __init ox820_boot_secondary(unsigned int cpu, struct task_struct *idle)
+{
+ /*
+ * Write the address of secondary startup into the
+ * system-wide flags register. The BootMonitor waits
+ * until it receives a soft interrupt, and then the
+ * secondary CPU branches to this address.
+ */
+ writel(virt_to_phys(ox820_secondary_startup),
+ cpu_ctrl + HOLDINGPEN_LOCATION_OFFSET);
+
+ writel(cpu, cpu_ctrl + HOLDINGPEN_CPU_OFFSET);
+
+ /*
+ * Enable GIC cpu interface in CPU Interface Control Register
+ */
+ writel(GIC_CPU_CTRL_ENABLE,
+ gic_cpu_ctrl + GIC_NCPU_OFFSET(cpu) + GIC_CPU_CTRL);
+
+ /*
+ * Send the secondary CPU a soft interrupt, thereby causing
+ * the boot monitor to read the system wide flags register,
+ * and branch to the address found there.
+ */
+ arch_send_wakeup_ipi_mask(cpumask_of(cpu));
+
+ return 0;
+}
+
+static void __init ox820_smp_prepare_cpus(unsigned int max_cpus)
+{
+ struct device_node *np;
+ void __iomem *scu_base;
+
+ np = of_find_compatible_node(NULL, NULL, "arm,arm11mp-scu");
+ scu_base = of_iomap(np, 0);
+ of_node_put(np);
+ if (!scu_base)
+ return;
+
+ /* Remap CPU Interrupt Interface Registers */
+ np = of_find_compatible_node(NULL, NULL, "arm,arm11mp-gic");
+ gic_cpu_ctrl = of_iomap(np, 1);
+ of_node_put(np);
+ if (!gic_cpu_ctrl)
+ goto unmap_scu;
+
+ np = of_find_compatible_node(NULL, NULL, "oxsemi,ox820-sys-ctrl");
+ cpu_ctrl = of_iomap(np, 0);
+ of_node_put(np);
+ if (!cpu_ctrl)
+ goto unmap_scu;
+
+ scu_enable(scu_base);
+ flush_cache_all();
+
+unmap_scu:
+ iounmap(scu_base);
+}
+
+static const struct smp_operations ox820_smp_ops __initconst = {
+ .smp_prepare_cpus = ox820_smp_prepare_cpus,
+ .smp_boot_secondary = ox820_boot_secondary,
+#ifdef CONFIG_HOTPLUG_CPU
+ .cpu_die = ox820_cpu_die,
+#endif
+};
+
+CPU_METHOD_OF_DECLARE(ox820_smp, "oxsemi,ox820-smp", &ox820_smp_ops);
--
2.7.0
^ permalink raw reply related
* [PATCH] arm64: mm: fix __page_to_voff definition
From: Neeraj Upadhyay @ 2016-10-21 8:58 UTC (permalink / raw)
To: linux-arm-kernel
Fix parameter name for __page_to_voff, to match its definition.
At present, we don't see any issue, as page_to_virt's caller
declares 'page'.
Fixes: 9f2875912dac ("arm64: mm: restrict virt_to_page() to the linear mapping")
Signed-off-by: Neeraj Upadhyay <neeraju@codeaurora.org>
---
arch/arm64/include/asm/memory.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm64/include/asm/memory.h b/arch/arm64/include/asm/memory.h
index ba62df8..b71086d 100644
--- a/arch/arm64/include/asm/memory.h
+++ b/arch/arm64/include/asm/memory.h
@@ -217,7 +217,7 @@ static inline void *phys_to_virt(phys_addr_t x)
#define _virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
#else
#define __virt_to_pgoff(kaddr) (((u64)(kaddr) & ~PAGE_OFFSET) / PAGE_SIZE * sizeof(struct page))
-#define __page_to_voff(kaddr) (((u64)(page) & ~VMEMMAP_START) * PAGE_SIZE / sizeof(struct page))
+#define __page_to_voff(page) (((u64)(page) & ~VMEMMAP_START) * PAGE_SIZE / sizeof(struct page))
#define page_to_virt(page) ((void *)((__page_to_voff(page)) | PAGE_OFFSET))
#define virt_to_page(vaddr) ((struct page *)((__virt_to_pgoff(vaddr)) | VMEMMAP_START))
--
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a
member of the Code Aurora Forum, hosted by The Linux Foundation
^ permalink raw reply related
* [PATCH v2 0/2] ARM: oxnas: Add SMP support for OX820
From: Neil Armstrong @ 2016-10-21 8:58 UTC (permalink / raw)
To: linux-arm-kernel
In order to support the SMP feature of the Oxford Semiconductor OX820 SoC,
add the necessary code to handle the wake-up, hotplug and cpu entry.
The OX820 has an ARM11MPCORE cluster with 2 cores and has proper hardware
support for secondary core booting.
Changes since v1 at http://lkml.kernel.org/r/20161017084303.20078-1-narmstrong at baylibre.com
- Remove useless holding pen loops and spinlock in boot_secondary
Neil Armstrong (2):
ARM: oxnas: Add OX820 SMP support
ARM: oxnas: Add OX820 config and makefile entry
arch/arm/Makefile | 1 +
arch/arm/mach-oxnas/Kconfig | 30 ++++++++----
arch/arm/mach-oxnas/Makefile | 2 +
arch/arm/mach-oxnas/headsmp.S | 28 +++++++++++
arch/arm/mach-oxnas/hotplug.c | 111 ++++++++++++++++++++++++++++++++++++++++++
arch/arm/mach-oxnas/platsmp.c | 104 +++++++++++++++++++++++++++++++++++++++
6 files changed, 267 insertions(+), 9 deletions(-)
create mode 100644 arch/arm/mach-oxnas/Makefile
create mode 100644 arch/arm/mach-oxnas/headsmp.S
create mode 100644 arch/arm/mach-oxnas/hotplug.c
create mode 100644 arch/arm/mach-oxnas/platsmp.c
--
2.7.0
^ permalink raw reply
* [PATCH] [media] c8sectpfe: Remove clk_disable_unprepare hacks
From: Peter Griffin @ 2016-10-21 8:55 UTC (permalink / raw)
To: linux-arm-kernel
Now that CLK_PROC_STFE is defined as a critical clock in
DT, we can remove the commented clk_disable_unprepare from
the c8sectpfe driver. This means we now have balanced
clk*enable/disable calls in the driver, but on STiH407
family the clock in reality will never actually be disabled.
This is due to a HW bug where once the IP has been configured
and the SLIM core is running, disabling the clock causes a
unrecoverable bus lockup.
Signed-off-by: Peter Griffin <peter.griffin@linaro.org>
---
drivers/media/platform/sti/c8sectpfe/c8sectpfe-core.c | 6 +-----
1 file changed, 1 insertion(+), 5 deletions(-)
diff --git a/drivers/media/platform/sti/c8sectpfe/c8sectpfe-core.c b/drivers/media/platform/sti/c8sectpfe/c8sectpfe-core.c
index 30c148b..79d793b 100644
--- a/drivers/media/platform/sti/c8sectpfe/c8sectpfe-core.c
+++ b/drivers/media/platform/sti/c8sectpfe/c8sectpfe-core.c
@@ -888,8 +888,7 @@ static int c8sectpfe_probe(struct platform_device *pdev)
return 0;
err_clk_disable:
- /* TODO uncomment when upstream has taken a reference on this clk */
- /*clk_disable_unprepare(fei->c8sectpfeclk);*/
+ clk_disable_unprepare(fei->c8sectpfeclk);
return ret;
}
@@ -924,11 +923,8 @@ static int c8sectpfe_remove(struct platform_device *pdev)
if (readl(fei->io + SYS_OTHER_CLKEN))
writel(0, fei->io + SYS_OTHER_CLKEN);
- /* TODO uncomment when upstream has taken a reference on this clk */
- /*
if (fei->c8sectpfeclk)
clk_disable_unprepare(fei->c8sectpfeclk);
- */
return 0;
}
--
1.9.1
^ permalink raw reply related
* [PATCH v2 6/6] powerpc: dts: acadia: DT fix s/#interrupts-parent/#interrupt-parent/
From: Geert Uytterhoeven @ 2016-10-21 8:51 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1477039877-20227-1-git-send-email-geert+renesas@glider.be>
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Acked-by: Rob Herring <robh@kernel.org>
---
v2:
- Add Acked-by.
---
arch/powerpc/boot/dts/acadia.dts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/powerpc/boot/dts/acadia.dts b/arch/powerpc/boot/dts/acadia.dts
index 57291f61ffe7021a..86266159521edac2 100644
--- a/arch/powerpc/boot/dts/acadia.dts
+++ b/arch/powerpc/boot/dts/acadia.dts
@@ -183,7 +183,7 @@
usb at ef603000 {
compatible = "ohci-be";
reg = <0xef603000 0x80>;
- interrupts-parent = <&UIC0>;
+ interrupt-parent = <&UIC0>;
interrupts = <0xd 0x4 0xe 0x4>;
};
--
1.9.1
^ permalink raw reply related
* [PATCH v2 5/6] dt: booting-without-of: DT fix s/#interrupt-cell/#interrupt-cells/
From: Geert Uytterhoeven @ 2016-10-21 8:51 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1477039877-20227-1-git-send-email-geert+renesas@glider.be>
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Acked-by: Rob Herring <robh@kernel.org>
---
v2:
- Add Acked-by.
---
Documentation/devicetree/booting-without-of.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Documentation/devicetree/booting-without-of.txt b/Documentation/devicetree/booting-without-of.txt
index 3f1437fbca6b49f3..5bcea91c0cc65af2 100644
--- a/Documentation/devicetree/booting-without-of.txt
+++ b/Documentation/devicetree/booting-without-of.txt
@@ -1302,7 +1302,7 @@ number and level/sense information. All interrupt children in an
OpenPIC interrupt domain use 2 cells per interrupt in their interrupts
property.
-The PCI bus binding specifies a #interrupt-cell value of 1 to encode
+The PCI bus binding specifies a #interrupt-cells value of 1 to encode
which interrupt pin (INTA,INTB,INTC,INTD) is used.
2) interrupt-parent property
--
1.9.1
^ permalink raw reply related
* [PATCH v2 4/6] ASoC: davinci-mcbsp: DT fix s/interrupts-names/interrupt-names/
From: Geert Uytterhoeven @ 2016-10-21 8:51 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1477039877-20227-1-git-send-email-geert+renesas@glider.be>
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Acked-by: Rob Herring <robh@kernel.org>
---
v2:
- Add Acked-by,
- Split off from a completely unrelated patch.
---
Documentation/devicetree/bindings/sound/davinci-mcbsp.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Documentation/devicetree/bindings/sound/davinci-mcbsp.txt b/Documentation/devicetree/bindings/sound/davinci-mcbsp.txt
index 55b53e1fd72c9d6e..e0b6165c9cfcec19 100644
--- a/Documentation/devicetree/bindings/sound/davinci-mcbsp.txt
+++ b/Documentation/devicetree/bindings/sound/davinci-mcbsp.txt
@@ -43,7 +43,7 @@ mcbsp0: mcbsp at 1d10000 {
<0x00310000 0x1000>;
reg-names = "mpu", "dat";
interrupts = <97 98>;
- interrupts-names = "rx", "tx";
+ interrupt-names = "rx", "tx";
dmas = <&edma0 3 1
&edma0 2 1>;
dma-names = "tx", "rx";
--
1.9.1
^ permalink raw reply related
* [PATCH v2 3/6] arm64: dts: lg1313: DT fix s/#interrupts-cells/#interrupt-cells/
From: Geert Uytterhoeven @ 2016-10-21 8:51 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1477039877-20227-1-git-send-email-geert+renesas@glider.be>
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
---
v2:
- New.
---
arch/arm64/boot/dts/lg/lg1313.dtsi | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm64/boot/dts/lg/lg1313.dtsi b/arch/arm64/boot/dts/lg/lg1313.dtsi
index e703e1149c757082..abb2162228e82d39 100644
--- a/arch/arm64/boot/dts/lg/lg1313.dtsi
+++ b/arch/arm64/boot/dts/lg/lg1313.dtsi
@@ -123,7 +123,7 @@
amba {
#address-cells = <2>;
#size-cells = <1>;
- #interrupts-cells = <3>;
+ #interrupt-cells = <3>;
compatible = "simple-bus";
interrupt-parent = <&gic>;
--
1.9.1
^ permalink raw reply related
* [PATCH v2 2/6] arm64: dts: lg1312: DT fix s/#interrupts-cells/#interrupt-cells/
From: Geert Uytterhoeven @ 2016-10-21 8:51 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1477039877-20227-1-git-send-email-geert+renesas@glider.be>
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Acked-by: Rob Herring <robh@kernel.org>
---
v2:
- Add Acked-by,
- Rebased.
---
arch/arm64/boot/dts/lg/lg1312.dtsi | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm64/boot/dts/lg/lg1312.dtsi b/arch/arm64/boot/dts/lg/lg1312.dtsi
index fbafa24cd5335b90..647606a83c517448 100644
--- a/arch/arm64/boot/dts/lg/lg1312.dtsi
+++ b/arch/arm64/boot/dts/lg/lg1312.dtsi
@@ -123,7 +123,7 @@
amba {
#address-cells = <2>;
#size-cells = <1>;
- #interrupts-cells = <3>;
+ #interrupt-cells = <3>;
compatible = "simple-bus";
interrupt-parent = <&gic>;
--
1.9.1
^ permalink raw reply related
* [PATCH v2 1/6] ARM: dts: STiH407: DT fix s/interrupts-names/interrupt-names/
From: Geert Uytterhoeven @ 2016-10-21 8:51 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1477039877-20227-1-git-send-email-geert+renesas@glider.be>
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Acked-by: Rob Herring <robh@kernel.org>
---
v2:
- Add Acked-by.
---
arch/arm/boot/dts/stih407-pinctrl.dtsi | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm/boot/dts/stih407-pinctrl.dtsi b/arch/arm/boot/dts/stih407-pinctrl.dtsi
index c325cc059ae4bc80..daab16b5ae645cee 100644
--- a/arch/arm/boot/dts/stih407-pinctrl.dtsi
+++ b/arch/arm/boot/dts/stih407-pinctrl.dtsi
@@ -1157,7 +1157,7 @@
reg = <0x0923f080 0x4>;
reg-names = "irqmux";
interrupts = <GIC_SPI 192 IRQ_TYPE_NONE>;
- interrupts-names = "irqmux";
+ interrupt-names = "irqmux";
ranges = <0 0x09230000 0x3000>;
pio40: gpio at 09230000 {
--
1.9.1
^ permalink raw reply related
* [PATCH v2 0/6] DT: Fix spelling of standard properties
From: Geert Uytterhoeven @ 2016-10-21 8:51 UTC (permalink / raw)
To: linux-arm-kernel
Hi all,
This patch series fixes misspellings of various standard DT properties
in DT binding documentation, DTS files, and error messages.
While most of these are harmless, some of them may cause hard-to-debug
failures.
Changes compared to v2:
- Dropped patches that have been applied already,
- Add Rob Herring's Acked-by,
- Split off "[PATCH v2 4/6] ASoC: davinci-mcbsp: DT fix
s/interrupts-names/interrupt-names/" from the unrelated "[PATCH 06/14]
dmaengine: bcm2835: DT spelling s/interrupts-names/interrupt-names/",
- Add new patch "[PATCH v2 3/6] arm64: dts: lg1313: DT fix
s/#interrupts-cells/#interrupt-cells/".
Please apply where appropriate.
Thanks!
P.S. I used the following to detect misspellings:
words="(address|clock|cooling|dma|gpio|index|interrupt|mbox|msi|nvmem|phy|phys|power-domain|pwm|reset|size|sleep|sound-dai|thermal-sensor)"
git grep -Ew "${words}s-names"
git grep -E "[^-]\<${words}-name\>[^-]"
git grep -Ew "#${words}s-cells" # false positive phys-cells
git grep -E "#${words}-cell\>[^-]"
git grep -w adress-cells
git grep -Ew "interrupts-(map|parent)"
Geert Uytterhoeven (6):
ARM: dts: STiH407: DT fix s/interrupts-names/interrupt-names/
arm64: dts: lg1312: DT fix s/#interrupts-cells/#interrupt-cells/
arm64: dts: lg1313: DT fix s/#interrupts-cells/#interrupt-cells/
ASoC: davinci-mcbsp: DT fix s/interrupts-names/interrupt-names/
dt: booting-without-of: DT fix s/#interrupt-cell/#interrupt-cells/
powerpc: dts: acadia: DT fix s/#interrupts-parent/#interrupt-parent/
Documentation/devicetree/bindings/sound/davinci-mcbsp.txt | 2 +-
Documentation/devicetree/booting-without-of.txt | 2 +-
arch/arm/boot/dts/stih407-pinctrl.dtsi | 2 +-
arch/arm64/boot/dts/lg/lg1312.dtsi | 2 +-
arch/arm64/boot/dts/lg/lg1313.dtsi | 2 +-
arch/powerpc/boot/dts/acadia.dts | 2 +-
6 files changed, 6 insertions(+), 6 deletions(-)
--
1.9.1
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert at linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
^ permalink raw reply
* [PATCH v2 1/9] irqchip: meson: add support for gpio interrupt controller
From: Jerome Brunet @ 2016-10-21 8:49 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <ec297647-1ab7-7e6b-5945-be8360f92421@arm.com>
On Thu, 2016-10-20 at 17:33 +0100, Marc Zyngier wrote:
> Jerome,
>
> On 19/10/16 16:21, Jerome Brunet wrote:
> >
> > Add support for the interrupt gpio controller found on Amlogic's
> > meson
> > SoC family.
> >
> > Unlike what the IP name suggest, it is not directly linked to the
> > gpio
> > subsystem. It is actually an independent IP that is able to spy on
> > the
> > SoC pad. For that purpose, it can mux and filter (edge or level and
> > polarity) any single SoC pad to one of the 8 GIC's interrupts it
> > owns.
> >
> > Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
> > ---
> > ?drivers/irqchip/Kconfig??????????|???9 +
> > ?drivers/irqchip/Makefile?????????|???1 +
> > ?drivers/irqchip/irq-meson-gpio.c | 423
> > +++++++++++++++++++++++++++++++++++++++
> > ?3 files changed, 433 insertions(+)
> > ?create mode 100644 drivers/irqchip/irq-meson-gpio.c
> >
> > diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
> > index 82b0b5daf3f5..168837263e80 100644
> > --- a/drivers/irqchip/Kconfig
> > +++ b/drivers/irqchip/Kconfig
> > @@ -279,3 +279,12 @@ config EZNPS_GIC
> > ?config STM32_EXTI
> > ? bool
> > ? select IRQ_DOMAIN
> > +
> > +config MESON_GPIO_IRQ
> > +???????bool "Meson GPIO Interrupt Multiplexer"
> > +???????depends on ARCH_MESON || COMPILE_TEST
> > +???????select IRQ_DOMAIN
> > +???????select IRQ_DOMAIN_HIERARCHY
> > +???????help
> > +?????????Support Meson SoC Family GPIO Interrupt Multiplexer
> > +
> > diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
> > index e4dbfc85abdb..33f913d037d0 100644
> > --- a/drivers/irqchip/Makefile
> > +++ b/drivers/irqchip/Makefile
> > @@ -74,3 +74,4 @@ obj-$(CONFIG_LS_SCFG_MSI) += irq-
> > ls-scfg-msi.o
> > ?obj-$(CONFIG_EZNPS_GIC) += irq-eznps.o
> > ?obj-$(CONFIG_ARCH_ASPEED) += irq-aspeed-vic.o
> > ?obj-$(CONFIG_STM32_EXTI)? += irq-stm32-exti.o
> > +obj-$(CONFIG_MESON_GPIO_IRQ) += irq-meson-gpio.o
> > diff --git a/drivers/irqchip/irq-meson-gpio.c
> > b/drivers/irqchip/irq-meson-gpio.c
> > new file mode 100644
> > index 000000000000..869b4df8c483
> > --- /dev/null
> > +++ b/drivers/irqchip/irq-meson-gpio.c
> > @@ -0,0 +1,423 @@
> > +/*
> > + * Copyright (c) 2015 Endless Mobile, Inc.
> > + * Author: Carlo Caione <carlo@endlessm.com>
> > + * Copyright (c) 2016 BayLibre, SAS.
> > + * Author: Jerome Brunet <jbrunet@baylibre.com>
> > + *
> > + * This program is free software; you can redistribute it and/or
> > modify
> > + * it under the terms of version 2 of the GNU General Public
> > License as
> > + * published by the Free Software Foundation.
> > + *
> > + * 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, see <http://www.gnu.org/licens
> > es/>.
> > + * The full GNU General Public License is included in this
> > distribution
> > + * in the file called COPYING.
> > + */
> > +
> > +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
> > +
> > +#include <linux/io.h>
> > +#include <linux/module.h>
> > +#include <linux/irq.h>
> > +#include <linux/irqdomain.h>
> > +#include <linux/irqchip.h>
> > +#include <linux/of.h>
> > +#include <linux/of_address.h>
> > +
> > +#define IRQ_FREE (-1)
> > +
> > +#define REG_EDGE_POL 0x00
> > +#define REG_PIN_03_SEL 0x04
> > +#define REG_PIN_47_SEL 0x08
> > +#define REG_FILTER_SEL 0x0c
> > +
> > +#define REG_EDGE_POL_MASK(x) (BIT(x) | BIT(16 + (x)))
> > +#define REG_EDGE_POL_EDGE(x) BIT(x)
> > +#define REG_EDGE_POL_LOW(x) BIT(16 + (x))
> > +#define REG_PIN_SEL_SHIFT(x) (((x) % 4) * 8)
> > +#define REG_FILTER_SEL_SHIFT(x) ((x) * 4)
> > +
> > +struct meson_gpio_irq_params {
> > + unsigned int nhwirq;
> > + irq_hw_number_t *source;
> > + int nsource;
> > +};
> > +
> > +struct meson_gpio_irq_domain {
>
> The name of that structure is utterly confusing, as it doesn't
> contain
> anything related to an IRQ domain. Can you please clarify its usage?
This structure is holding the data of the controller. The name is
indeed misleading, I will change this. What about
'meson_gpio_irq_pdata' or 'meson_gpio_irq_controller' ?
>
> >
> > + void __iomem *base;
> > + int *map;
> > + const struct meson_gpio_irq_params *params;
> > +};
> > +
> > +struct meson_gpio_irq_chip_data {
> > + void __iomem *base;
> > + int index;
> > +};
> > +
> > +static irq_hw_number_t meson_parent_hwirqs[] = {
> > + 64, 65, 66, 67, 68, 69, 70, 71,
> > +};
>
> If that a guarantee that these numbers will always represent the
> parent interrupt?
At the moment, the 3 supported SoC use these parent interrupts, but we
have absolutely no idea (or guarantee) that is will remain the same, or
even contiguous, in the upcoming SoC (like the GXM or GXL)
I reckon, it is likely that manufacturer will keep on using these
parent irqs for a while but I would prefer not make an assumption about
it in the driver.
If a SoC get a different set of interrupts I would have added a new
table like this and passed it to the appropriate params :
static irq_hw_number_t meson_new_parent_hwirqs[] = {
143, 144, 150, 151, 152, 173, 178, 179,
};
> It feels a bit odd not to get that information directly from
> the device tree, in the form of a device specific property. Something
> like:
>
> upstream-interrupts = <64 65 66 ... >;
>
I wondered about putting this information in DT or in the driver for a
while. Maybe DT would be a more suitable place holder for these data
(parent irq and number of provided hwirq) but I was under the
understanding that we should now put these information in the driver
and use the compatible property to get the appropriate parameters.
I'd love to get the view of the DT guys on this.
Also, since we already need to put some information about the pin the
pinctrl driver (to get the appropriate mux value of each pad), I
thought It would make sense to have the same approach here.
If there is some kind of policy saying this should be in DT, I'd be
happy to make the change.
> or even as a base/range:
>
> upstream-interrupts = <64 8>;
I would prefer to avoid using ranges as we have no guarantee the
manufacturer will keep the parent irqs contiguous in the future.
>
> Also, how does it work if you have more than a single device like
> this?
> This driver seems a do a great deal of dynamic allocation, and yet
> its
> core resource is completely static... Please pick a side! ;-)
I don't think we could have more than one instance per device and I
certainly did not have this case in mind while writing the code. If it
was the case someday, I guess having two compatibles would do the trick
:)
>
> >
> > +
> > +static const struct meson_gpio_irq_params meson8_params = {
> > + .nhwirq??= 134,
> > + .source??= meson_parent_hwirqs,
> > + .nsource = ARRAY_SIZE(meson_parent_hwirqs),
>
> I find it utterly confusing that you are calling source something
> that is an output for this controller.
I had the call sequence (GIC->GPIO_IRQ->handler) in mind while writing
it. I see your point and it is indeed confusing, I'll find something
better
> It makes my brain melt, and I don't like the feeling.
Ohhhh !! it's Halloween season and you don't need a costume anymore ;)
>
> >
> > +};
> > +
> > +static const struct meson_gpio_irq_params meson8b_params = {
> > + .nhwirq??= 119,
> > + .source??= meson_parent_hwirqs,
> > + .nsource = ARRAY_SIZE(meson_parent_hwirqs),
> > +};
> > +
> > +static const struct meson_gpio_irq_params meson_gxbb_params = {
> > + .nhwirq??= 133,
> > + .source??= meson_parent_hwirqs,
> > + .nsource = ARRAY_SIZE(meson_parent_hwirqs),
> > +};
>
> Same thing. How big is the variability of these structures? Are we
> going to see more of those? or is that now set into stone?
The number of pad mapped to the controller seems to change with every
SoC version. The parent irqs have not changed so far, but as explained
above, there is no guarantee it will keep on being this way.
So i'd say probably more of those ...
>
> +Mark: what's the policy to describe this kind of things?
Very interested about this question as well.
>
> >
> > +
> > +static const struct of_device_id meson_irq_gpio_matches[] = {
> > + {
> > + .compatible = "amlogic,meson8-gpio-intc",
>
> If it's an independent IP (as described in the commit message),
> shouldn't in be rescribed in a more SoC-independent way?
Ok, I was probably not very clear (again). What I meant in the cover
letter is that the interrupt gpio controller is independent for the
pad/gpio controller. For example, it could work even you did not setup
anything in pinmux or you did not instantiate pinctrl at all.
But, at least from my point of view, it is SoC dependent since the
number of pad routed to it is changing with every SoC version.
>
> >
> > + .data = &meson8_params
> > + },
> > + {
> > + .compatible = "amlogic,meson8b-gpio-intc",
> > + .data = &meson8b_params
> > + },
> > + {
> > + .compatible = "amlogic,meson-gxbb-gpio-intc",
> > + .data = &meson_gxbb_params
> > + },
> > + {}
> > +};
> > +
> > +static void meson_gpio_irq_update_bits(void __iomem *base,
> > unsigned int reg,
> > + ???????u32 mask, u32 val)
> > +{
> > + u32 tmp;
> > +
> > + tmp = readl(base + reg);
> > + tmp &= ~mask;
> > + tmp |= val;
> > +
> > + writel(tmp, base + reg);
>
> Can't you use the relaxed accessors?
Indeed, this will be fixed.
>
> >
> > +}
> > +
> > +static int meson_gpio_irq_get_index(struct meson_gpio_irq_domain
> > *domain_data,
> > + ????int hwirq)
> > +{
> > + int i;
> > +
> > + for (i = 0; i < domain_data->params->nsource; i++) {
> > + if (domain_data->map[i] == hwirq)
> > + return i;
> > + }
> > +
> > + return -1;
>
> I'm a bit worried by this function. If you need an allocator, then
> having a simple bitmap is much better than iterating over an array.
>
> If you're using this to go from a hwirq to the structure describing
> your
> interrupt, this is wrong. You should never have to look-up something
> based on a hwirq, because that's what irq domains are for.
OK
>
> >
> > +}
> > +
> > +static int mesion_gpio_irq_map_source(struct meson_gpio_irq_domain
> > *domain_data,
> > + ??????irq_hw_number_t hwirq,
> > + ??????irq_hw_number_t *source)
> > +{
> > + int index;
> > + unsigned int reg;
> > +
> > + index = meson_gpio_irq_get_index(domain_data, IRQ_FREE);
>
> So assuming you turn this into a proper bitmap driven allocator...
>
> >
> > + if (index < 0) {
> > + pr_err("No irq available\n");
> > + return -ENOSPC;
> > + }
> > +
> > + domain_data->map[index] = hwirq;
>
> this can go away, as there is hardly any point in tracking the hwirq
> on
> its own. Actually, the whole map[] array looks totally useless.
>
> >
> > +
> > + reg = (index < 4) ? REG_PIN_03_SEL : REG_PIN_47_SEL;
> > + meson_gpio_irq_update_bits(domain_data->base, reg,
> > + ???0xff <<
> > REG_PIN_SEL_SHIFT(index),
> > + ???hwirq <<
> > REG_PIN_SEL_SHIFT(index));
> > +
> > + *source = domain_data->params->source[index];
> > +
> > + pr_debug("hwirq %lu assigned to channel %d - source
> > %lu\n",
> > + ?hwirq, index, *source);
> > +
> > + return index;
> > +}
> > +
> > +static int meson_gpio_irq_type_setup(unsigned int type, void
> > __iomem *base,
> > + ?????int index)
> > +{
> > + u32 val = 0;
> > +
> > + type &= IRQ_TYPE_SENSE_MASK;
> > +
> > + if (type == IRQ_TYPE_EDGE_BOTH)
> > + return -EINVAL;
> > +
> > + if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING))
> > + val |= REG_EDGE_POL_EDGE(index);
> > +
> > + if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_EDGE_FALLING))
> > + val |= REG_EDGE_POL_LOW(index);
> > +
> > + meson_gpio_irq_update_bits(base, REG_EDGE_POL,
> > + ???REG_EDGE_POL_MASK(index), val);
> > +
> > + return 0;
> > +}
> > +
> > +static unsigned int meson_gpio_irq_type_output(unsigned int type)
> > +{
> > + unsigned int sense = type & IRQ_TYPE_SENSE_MASK;
> > +
> > + type &= ~IRQ_TYPE_SENSE_MASK;
> > +
> > + /*
> > + ?* If the polarity of interrupt is low, the controller
> > will
> > + ?* invert the signal for gic
> > + ?*/
> > + if (sense & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW))
> > + type |= IRQ_TYPE_LEVEL_HIGH;
> > + else if (sense & (IRQ_TYPE_EDGE_RISING |
> > IRQ_TYPE_EDGE_FALLING))
> > + type |= IRQ_TYPE_EDGE_RISING;
> > +
> > + return type;
> > +}
> > +
> > +static int meson_gpio_irq_set_type(struct irq_data *data, unsigned
> > int type)
> > +{
> > + struct meson_gpio_irq_chip_data *cd =
> > irq_data_get_irq_chip_data(data);
> > + int ret;
> > +
> > + pr_debug("set type of hwirq %lu to %u\n", data->hwirq,
> > type);
> > +
> > + ret = meson_gpio_irq_type_setup(type, cd->base, cd-
> > >index);
> > + if (ret)
> > + return ret;
> > +
> > + return irq_chip_set_type_parent(data,
> > + meson_gpio_irq_type_output
> > (type));
> > +}
> > +
> > +static struct irq_chip meson_gpio_irq_chip = {
> > + .name = "meson-gpio-irqchip",
> > + .irq_mask = irq_chip_mask_parent,
> > + .irq_unmask = irq_chip_unmask_parent,
> > + .irq_eoi = irq_chip_eoi_parent,
> > + .irq_set_type = meson_gpio_irq_set_type,
> > + .irq_retrigger =
> > irq_chip_retrigger_hierarchy,
> > +#ifdef CONFIG_SMP
> > + .irq_set_affinity = irq_chip_set_affinity_parent,
> > +#endif
> > +};
> > +
> > +static int meson_gpio_irq_domain_translate(struct irq_domain
> > *domain,
> > + ???struct irq_fwspec
> > *fwspec,
> > + ???unsigned long *hwirq,
> > + ???unsigned int *type)
> > +{
> > + if (is_of_node(fwspec->fwnode)) {
> > + if (fwspec->param_count != 2)
> > + return -EINVAL;
>
> You can write this as:
>
> if (is_of_node() && fwspec->... == 2) {
OK
>
> >
> > +
> > + *hwirq = fwspec->param[0];
> > + *type = fwspec->param[1];
> > +
> > + return 0;
> > + }
> > +
> > + return -EINVAL;
> > +}
> > +
> > +static int meson_gpio_irq_allocate_gic_irq(struct irq_domain
> > *domain,
> > + ???unsigned int virq,
> > + ???irq_hw_number_t source,
> > + ???unsigned int type)
> > +{
> > + struct irq_fwspec fwspec;
> > +
> > + if (!irq_domain_get_of_node(domain->parent))
> > + return -EINVAL;
>
> How can you end-up here if the translate operation has failed?
You can't, will be removed
>
> >
> > +
> > + fwspec.fwnode = domain->parent->fwnode;
> > + fwspec.param_count = 3;
> > + fwspec.param[0] = 0; /* SPI */
> > + fwspec.param[1] = source;
> > + fwspec.param[2] = meson_gpio_irq_type_output(type);
> > +
> > + return irq_domain_alloc_irqs_parent(domain, virq, 1,
> > &fwspec);
> > +}
> > +
> > +static int meson_gpio_irq_domain_alloc(struct irq_domain *domain,
> > + ???????unsigned int virq,
> > + ???????unsigned int nr_irqs,
> > + ???????void *data)
> > +{
> > + struct irq_fwspec *fwspec = data;
> > + struct meson_gpio_irq_domain *domain_data = domain-
> > >host_data;
> > + struct meson_gpio_irq_chip_data *cd;
> > + unsigned long hwirq, source;
> > + unsigned int type;
> > + int i, index, ret;
> > +
> > + ret = meson_gpio_irq_domain_translate(domain, fwspec,
> > &hwirq, &type);
> > + if (ret)
> > + return ret;
> > +
> > + pr_debug("irq %d, nr_irqs %d, hwirqs %lu\n", virq,
> > nr_irqs, hwirq);
> > +
> > + for (i = 0; i < nr_irqs; i++) {
>
> This is a pattern that gets repeated over and over, for no good
> reason.
> The only reason we have this nr_irqs thing is to handle things like
> multi-MSI, where we have to *guarantee* that the hwirqs are allocated
> in
> a contiguous manner.
>
> Here, you don't enforce that guarantee, so you'd rather have a big
> fat:
>
> if (WARN_ON(nr_irqs != 1))
> return -EINVAL;
>
> and get rid of that loop, because I cannot imagine a case where you'd
> allocate more than a single interrupt at a time.
Thanks for this clarification. I was actually very confused about
getting a single fwspec and this 'nr_irqs' parameters. I could not
figure a case where one would want multiple irqs in one call, and
looking at the other irqchip drivers did not really help. In the end, I
tried to implement the API the best I could, thinking that somebody
probably had a very good reason for this.
I'm perfectly happy using your solution, it makes more sense.
>
> >
> > + index = mesion_gpio_irq_map_source(domain_data,
> > hwirq + i,
> > + ???&source);
> > + if (index < 0)
> > + return index;
> > +
> > + ret = meson_gpio_irq_type_setup(type, domain_data-
> > >base,
> > + index);
> > + if (ret)
> > + return ret;
>
> Why do you have to to this here? This should be handled by the core
> code already.
OK
>
> >
> > +
> > + cd = kzalloc(sizeof(*cd), GFP_KERNEL);
> > + if (!cd)
> > + return -ENOMEM;
> > +
> > + cd->base = domain_data->base;
> > + cd->index = index;
>
> So what is the exact purpose of this structure? The base address is
> essentially a global, or could be directly derived from the domain.
> The
> index is only used in set_type, and is the index of the pin connected
> to
> the GIC. It looks to me like you could have:
>
> irq_hw_number_t *out_line =
> &meson_parent_hwirqs[index];
meson_parent_hwirq is only declared this way to avoid writing the
parent irqs 3 times (in each SoC params).?
Using it this way would make it global and imply it is the same
whatever the SoC. This something I can't guarantee and I would prefer
to avoid that.
>
> >
> > +
> > + irq_domain_set_hwirq_and_chip(domain, virq + i,
> > hwirq + i,
> > + ??????&meson_gpio_irq_chip
> > , cd);
>
> and this written as
>
> irq_domain_set_hwirq_and_chip(domain, virq, hwirq,
> ??????out_line);
>
> In your set_type function, you just compute the index back:
>
> irq_hw_number_t *out_line = irq_data_get_irq_chip_data(data);
> irq_hw_number_t index = out_line - meson_parent_hwirqs;
>
> and you're done.
>
Since I can derive the base address, I only need the index in set_type.
I'll rework this to get rid of this structure.
> >
> > +
> > + ret = meson_gpio_irq_allocate_gic_irq(domain, virq
> > + i,
> > + ??????source,
> > type);
>
> Resource leak on error.
Ok, Thx.
>
> >
> > + if (ret < 0)
> > + return ret;
> > + }
> > +
> > + return 0;
> > +}
> > +
> > +static void meson_gpio_irq_domain_free(struct irq_domain *domain,
> > + ???????unsigned int virq,
> > + ???????unsigned int nr_irqs)
> > +{
> > + struct meson_gpio_irq_domain *domain_data = domain-
> > >host_data;
> > + struct meson_gpio_irq_chip_data *cd;
> > + struct irq_data *irq_data;
> > + int i;
> > +
> > + for (i = 0; i < nr_irqs; i++) {
>
> Same comment as above.
OK
>
> >
> > + irq_data = irq_domain_get_irq_data(domain, virq +
> > i);
> > + cd = irq_data_get_irq_chip_data(irq_data);
> > +
> > + domain_data->map[cd->index] = IRQ_FREE;
> > + kfree(cd);
> > + }
> > +
> > + irq_domain_free_irqs_parent(domain, virq, nr_irqs);
> > +
> > +}
> > +
> > +static const struct irq_domain_ops meson_gpio_irq_domain_ops = {
> > + .alloc = meson_gpio_irq_domain_alloc,
> > + .free = meson_gpio_irq_domain_free,
> > + .translate = meson_gpio_irq_domain_translate,
> > +};
> > +
> > +static int __init
> > +meson_gpio_irq_init_domain(struct device_node *node,
> > + ???struct meson_gpio_irq_domain
> > *domain_data,
> > + ???const struct meson_gpio_irq_params
> > *params)
> > +{
> > + int i;
> > + int nsource = params->nsource;
> > + int *map;
> > +
> > + map = kcalloc(nsource, sizeof(*map), GFP_KERNEL);
> > + if (!map)
> > + return -ENOMEM;
> > +
> > + for (i = 0; i < nsource; i++)
> > + map[i] = IRQ_FREE;
> > +
> > + domain_data->map = map;
>
> You should now be able to kill most or all of this.
>
> >
> > + domain_data->params = params;
> > +
> > + return 0;
> > +}
> > +
> > +static int __init meson_gpio_irq_of_init(struct device_node *node,
> > + ?struct device_node
> > *parent)
> > +{
> > + struct irq_domain *domain, *parent_domain;
> > + const struct of_device_id *match;
> > + const struct meson_gpio_irq_params *params;
> > + struct meson_gpio_irq_domain *domain_data;
> > + int ret;
> > +
> > + match = of_match_node(meson_irq_gpio_matches, node);
> > + if (!match)
> > + return -ENODEV;
> > + params = match->data;
> > +
> > + if (!parent) {
> > + pr_err("missing parent interrupt node\n");
> > + return -ENODEV;
> > + }
> > +
> > + parent_domain = irq_find_host(parent);
> > + if (!parent_domain) {
> > + pr_err("unable to obtain parent domain\n");
> > + return -ENXIO;
> > + }
> > +
> > + domain_data = kzalloc(sizeof(*domain_data), GFP_KERNEL);
> > + if (!domain_data)
> > + return -ENOMEM;
> > +
> > + domain_data->base = of_iomap(node, 0);
> > + if (!domain_data->base) {
> > + ret = -ENOMEM;
> > + goto out_free_dev;
> > + }
> > +
> > + ret = meson_gpio_irq_init_domain(node, domain_data,
> > params);
> > + if (ret < 0)
> > + goto out_free_dev_content;
> > +
> > + domain = irq_domain_add_hierarchy(parent_domain, 0,
> > params->nhwirq,
> > + ??node,
> > &meson_gpio_irq_domain_ops,
> > + ??domain_data);
>
> Please be consistent in using the fwnode API instead of the of_node
> one.
OK
>
> >
> > +
> > + if (!domain) {
> > + pr_err("failed to allocated domain\n");
> > + ret = -ENOMEM;
> > + goto out_free_dev_content;
> > + }
> > +
> > + pr_info("%d to %d gpio interrupt mux initialized\n",
> > + params->nhwirq, params->nsource);
> > +
> > + return 0;
> > +
> > +out_free_dev_content:
> > + kfree(domain_data->map);
> > + iounmap(domain_data->base);
> > +
> > +out_free_dev:
> > + kfree(domain_data);
> > +
> > + return ret;
> > +}
> > +
> > +IRQCHIP_DECLARE(meson8_gpio_intc, "amlogic,meson8-gpio-intc",
> > + meson_gpio_irq_of_init);
> > +IRQCHIP_DECLARE(meson8b_gpio_intc, "amlogic,meson8b-gpio-intc",
> > + meson_gpio_irq_of_init);
> > +IRQCHIP_DECLARE(gxbb_gpio_intc, "amlogic,meson-gxbb-gpio-intc",
> > + meson_gpio_irq_of_init);
> >
>
> Overall, this driver is a bit of a mess. Tons of structures that
> don't
> make much sense, and a false sense of being able to support multiple
> instances of the device.
>
> I'll let Mark comment on the DT side of things.
>
> Thanks,
>
> M.
^ permalink raw reply
* [PATCH] net: stmmac: Add OXNAS Glue Driver
From: Neil Armstrong @ 2016-10-21 8:44 UTC (permalink / raw)
To: linux-arm-kernel
Add Synopsys Designware MAC Glue layer for the Oxford Semiconductor OX820.
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
.../devicetree/bindings/net/oxnas-dwmac.txt | 44 +++++
drivers/net/ethernet/stmicro/stmmac/Kconfig | 11 ++
drivers/net/ethernet/stmicro/stmmac/Makefile | 1 +
drivers/net/ethernet/stmicro/stmmac/dwmac-oxnas.c | 219 +++++++++++++++++++++
4 files changed, 275 insertions(+)
create mode 100644 Documentation/devicetree/bindings/net/oxnas-dwmac.txt
create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwmac-oxnas.c
Changes since RFC at https://patchwork.kernel.org/patch/9387257 :
- Drop init/exit callbacks
- Implement proper remove and PM callback
- Call init from probe
- Disable/Unprepare clock if stmmac probe fails
diff --git a/Documentation/devicetree/bindings/net/oxnas-dwmac.txt b/Documentation/devicetree/bindings/net/oxnas-dwmac.txt
new file mode 100644
index 0000000..5d2696c
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/oxnas-dwmac.txt
@@ -0,0 +1,44 @@
+* Oxford Semiconductor OXNAS DWMAC Ethernet controller
+
+The device inherits all the properties of the dwmac/stmmac devices
+described in the file stmmac.txt in the current directory with the
+following changes.
+
+Required properties on all platforms:
+
+- compatible: Depending on the platform this should be one of:
+ - "oxsemi,ox820-dwmac"
+ Additionally "snps,dwmac" and any applicable more
+ detailed version number described in net/stmmac.txt
+ should be used.
+
+- reg: The first register range should be the one of the DWMAC
+ controller.
+
+- clocks: Should contain phandles to the following clocks
+- clock-names: Should contain the following:
+ - "stmmaceth" - see stmmac.txt
+ - "gmac" - peripheral gate clock
+
+- oxsemi,sys-ctrl: a phandle to the system controller syscon node
+
+Example :
+
+etha: ethernet at 40400000 {
+ compatible = "oxsemi,ox820-dwmac", "snps,dwmac";
+ reg = <0x40400000 0x2000>;
+ interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "macirq", "eth_wake_irq";
+ mac-address = [000000000000]; /* Filled in by U-Boot */
+ phy-mode = "rgmii";
+
+ clocks = <&stdclk CLK_820_ETHA>, <&gmacclk>;
+ clock-names = "gmac", "stmmaceth";
+ resets = <&reset RESET_MAC>;
+
+ /* Regmap for sys registers */
+ oxsemi,sys-ctrl = <&sys>;
+
+ status = "disabled";
+};
diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig
index 3818c5e..27ed913 100644
--- a/drivers/net/ethernet/stmicro/stmmac/Kconfig
+++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig
@@ -62,6 +62,7 @@ config DWMAC_MESON
tristate "Amlogic Meson dwmac support"
default ARCH_MESON
depends on OF && COMMON_CLK && (ARCH_MESON || COMPILE_TEST)
+ select MFD_SYSCON
help
Support for Ethernet controller on Amlogic Meson SoCs.
@@ -69,6 +70,16 @@ config DWMAC_MESON
the stmmac device driver. This driver is used for Meson6,
Meson8, Meson8b and GXBB SoCs.
+config DWMAC_OXNAS
+ tristate "Oxford Semiconductor OXNAS dwmac support"
+ default ARCH_OXNAS
+ depends on OF && COMMON_CLK && (ARCH_OXNAS || COMPILE_TEST)
+ help
+ Support for Ethernet controller on Oxford Semiconductor OXNAS SoCs.
+
+ This selects the Oxford Semiconductor OXNASSoC glue layer support for
+ the stmmac device driver. This driver is used for OX820.
+
config DWMAC_ROCKCHIP
tristate "Rockchip dwmac support"
default ARCH_ROCKCHIP
diff --git a/drivers/net/ethernet/stmicro/stmmac/Makefile b/drivers/net/ethernet/stmicro/stmmac/Makefile
index 5d6ece5..8f83a86 100644
--- a/drivers/net/ethernet/stmicro/stmmac/Makefile
+++ b/drivers/net/ethernet/stmicro/stmmac/Makefile
@@ -10,6 +10,7 @@ obj-$(CONFIG_STMMAC_PLATFORM) += stmmac-platform.o
obj-$(CONFIG_DWMAC_IPQ806X) += dwmac-ipq806x.o
obj-$(CONFIG_DWMAC_LPC18XX) += dwmac-lpc18xx.o
obj-$(CONFIG_DWMAC_MESON) += dwmac-meson.o dwmac-meson8b.o
+obj-$(CONFIG_DWMAC_OXNAS) += dwmac-oxnas.o
obj-$(CONFIG_DWMAC_ROCKCHIP) += dwmac-rk.o
obj-$(CONFIG_DWMAC_SOCFPGA) += dwmac-altr-socfpga.o
obj-$(CONFIG_DWMAC_STI) += dwmac-sti.o
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-oxnas.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-oxnas.c
new file mode 100644
index 0000000..40fd845
--- /dev/null
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-oxnas.c
@@ -0,0 +1,219 @@
+/*
+ * Oxford Semiconductor OXNAS DWMAC glue layer
+ *
+ * Copyright (C) 2016 Neil Armstrong <narmstrong@baylibre.com>
+ * Copyright (C) 2014 Daniel Golle <daniel@makrotopia.org>
+ * Copyright (C) 2013 Ma Haijun <mahaijuns@gmail.com>
+ * Copyright (C) 2012 John Crispin <blogic@openwrt.org>
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/mfd/syscon.h>
+#include <linux/stmmac.h>
+
+#include "stmmac_platform.h"
+
+/* System Control regmap offsets */
+#define OXNAS_DWMAC_CTRL_REGOFFSET 0x78
+#define OXNAS_DWMAC_DELAY_REGOFFSET 0x100
+
+/* Control Register */
+#define DWMAC_CKEN_RX_IN 14
+#define DWMAC_CKEN_RXN_OUT 13
+#define DWMAC_CKEN_RX_OUT 12
+#define DWMAC_CKEN_TX_IN 10
+#define DWMAC_CKEN_TXN_OUT 9
+#define DWMAC_CKEN_TX_OUT 8
+#define DWMAC_RX_SOURCE 7
+#define DWMAC_TX_SOURCE 6
+#define DWMAC_LOW_TX_SOURCE 4
+#define DWMAC_AUTO_TX_SOURCE 3
+#define DWMAC_RGMII 2
+#define DWMAC_SIMPLE_MUX 1
+#define DWMAC_CKEN_GTX 0
+
+/* Delay register */
+#define DWMAC_TX_VARDELAY_SHIFT 0
+#define DWMAC_TXN_VARDELAY_SHIFT 8
+#define DWMAC_RX_VARDELAY_SHIFT 16
+#define DWMAC_RXN_VARDELAY_SHIFT 24
+#define DWMAC_TX_VARDELAY(d) ((d) << DWMAC_TX_VARDELAY_SHIFT)
+#define DWMAC_TXN_VARDELAY(d) ((d) << DWMAC_TXN_VARDELAY_SHIFT)
+#define DWMAC_RX_VARDELAY(d) ((d) << DWMAC_RX_VARDELAY_SHIFT)
+#define DWMAC_RXN_VARDELAY(d) ((d) << DWMAC_RXN_VARDELAY_SHIFT)
+
+struct oxnas_dwmac {
+ struct device *dev;
+ struct clk *clk;
+ struct regmap *regmap;
+};
+
+static int oxnas_dwmac_init(struct oxnas_dwmac *dwmac)
+{
+ unsigned int value;
+ int ret;
+
+ /* Reset HW here before changing the glue configuration */
+ ret = device_reset(dwmac->dev);
+ if (ret)
+ return ret;
+
+ clk_prepare_enable(dwmac->clk);
+
+ ret = regmap_read(dwmac->regmap, OXNAS_DWMAC_CTRL_REGOFFSET, &value);
+ if (ret < 0)
+ return ret;
+
+ /* Enable GMII_GTXCLK to follow GMII_REFCLK, required for gigabit PHY */
+ value |= BIT(DWMAC_CKEN_GTX);
+ /* Use simple mux for 25/125 Mhz clock switching */
+ value |= BIT(DWMAC_SIMPLE_MUX);
+ /* set auto switch tx clock source */
+ value |= BIT(DWMAC_AUTO_TX_SOURCE);
+ /* enable tx & rx vardelay */
+ value |= BIT(DWMAC_CKEN_TX_OUT);
+ value |= BIT(DWMAC_CKEN_TXN_OUT);
+ value |= BIT(DWMAC_CKEN_TX_IN);
+ value |= BIT(DWMAC_CKEN_RX_OUT);
+ value |= BIT(DWMAC_CKEN_RXN_OUT);
+ value |= BIT(DWMAC_CKEN_RX_IN);
+ regmap_write(dwmac->regmap, OXNAS_DWMAC_CTRL_REGOFFSET, value);
+
+ /* set tx & rx vardelay */
+ value = DWMAC_TX_VARDELAY(4);
+ value |= DWMAC_TXN_VARDELAY(2);
+ value |= DWMAC_RX_VARDELAY(10);
+ value |= DWMAC_RXN_VARDELAY(8);
+ regmap_write(dwmac->regmap, OXNAS_DWMAC_DELAY_REGOFFSET, value);
+
+ return 0;
+}
+
+static int oxnas_dwmac_probe(struct platform_device *pdev)
+{
+ struct plat_stmmacenet_data *plat_dat;
+ struct stmmac_resources stmmac_res;
+ struct device_node *sysctrl;
+ struct oxnas_dwmac *dwmac;
+ int ret;
+
+ sysctrl = of_parse_phandle(pdev->dev.of_node, "oxsemi,sys-ctrl", 0);
+ if (!sysctrl) {
+ dev_err(&pdev->dev, "failed to get sys-ctrl node\n");
+ return -EINVAL;
+ }
+
+ ret = stmmac_get_platform_resources(pdev, &stmmac_res);
+ if (ret)
+ return ret;
+
+ plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac);
+ if (IS_ERR(plat_dat))
+ return PTR_ERR(plat_dat);
+
+ dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac), GFP_KERNEL);
+ if (!dwmac)
+ return -ENOMEM;
+
+ dwmac->dev = &pdev->dev;
+ plat_dat->bsp_priv = dwmac;
+
+ dwmac->regmap = syscon_node_to_regmap(sysctrl);
+ if (IS_ERR(dwmac->regmap)) {
+ dev_err(&pdev->dev, "failed to have sysctrl regmap\n");
+ return PTR_ERR(dwmac->regmap);
+ }
+
+ dwmac->clk = devm_clk_get(&pdev->dev, "gmac");
+ if (IS_ERR(dwmac->clk))
+ return PTR_ERR(dwmac->clk);
+
+ ret = oxnas_dwmac_init(dwmac);
+ if (ret)
+ return ret;
+
+ ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
+ if (ret)
+ clk_disable_unprepare(dwmac->clk);
+
+ return ret;
+}
+
+static int oxnas_dwmac_remove(struct platform_device *pdev)
+{
+ struct net_device *ndev = platform_get_drvdata(pdev);
+ struct stmmac_priv *priv = netdev_priv(ndev);
+ struct oxnas_dwmac *dwmac = priv->plat->bsp_priv;
+ int ret = stmmac_dvr_remove(&pdev->dev);
+
+ clk_disable_unprepare(dwmac->clk);
+
+ return ret;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int oxnas_dwmac_suspend(struct device *dev)
+{
+ struct net_device *ndev = dev_get_drvdata(dev);
+ struct stmmac_priv *priv = netdev_priv(ndev);
+ struct oxnas_dwmac *dwmac = priv->plat->bsp_priv;
+ int ret;
+
+ ret = stmmac_suspend(dev);
+ clk_disable_unprepare(dwmac->clk);
+
+ return ret;
+}
+
+static int oxnas_dwmac_resume(struct device *dev)
+{
+ struct net_device *ndev = dev_get_drvdata(dev);
+ struct stmmac_priv *priv = netdev_priv(ndev);
+ struct oxnas_dwmac *dwmac = priv->plat->bsp_priv;
+ int ret;
+
+ ret = oxnas_dwmac_init(dwmac);
+ if (ret)
+ return ret;
+
+ ret = stmmac_resume(dev);
+
+ return ret;
+}
+#endif /* CONFIG_PM_SLEEP */
+
+static SIMPLE_DEV_PM_OPS(oxnas_dwmac_pm_ops,
+ oxnas_dwmac_suspend, oxnas_dwmac_resume);
+
+static const struct of_device_id oxnas_dwmac_match[] = {
+ { .compatible = "oxsemi,ox820-dwmac" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, oxnas_dwmac_match);
+
+static struct platform_driver oxnas_dwmac_driver = {
+ .probe = oxnas_dwmac_probe,
+ .remove = oxnas_dwmac_remove,
+ .driver = {
+ .name = "oxnas-dwmac",
+ .pm = &oxnas_dwmac_pm_ops,
+ .of_match_table = oxnas_dwmac_match,
+ },
+};
+module_platform_driver(oxnas_dwmac_driver);
+
+MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>");
+MODULE_DESCRIPTION("Oxford Semiconductor OXNAS DWMAC glue layer");
+MODULE_LICENSE("GPL v2");
--
2.7.0
^ permalink raw reply related
* [PATCH] dmaengine: st_fdma: Update st_fdma to 'depends on REMOTEPROC'.
From: Peter Griffin @ 2016-10-21 8:44 UTC (permalink / raw)
To: linux-arm-kernel
During randconfig builds you can get the following warning
"warning: (ST_FDMA) selects ST_SLIM_REMOTEPROC which has unmet direct
dependencies (REMOTEPROC)"
randconfig builds should always build without any warnings so
update fdma to depend on REMOTEPROC so this can not happen.
Signed-off-by: Peter Griffin <peter.griffin@linaro.org>
Reported-by: Arnd Bergmann <arnd@arndb.de>
Tested-by: Arnd Bergmann <arnd@arndb.de>
---
drivers/dma/Kconfig | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index 661f217..6b96710 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -438,6 +438,7 @@ config STE_DMA40
config ST_FDMA
tristate "ST FDMA dmaengine support"
depends on ARCH_STI
+ depends on REMOTEPROC
select ST_SLIM_REMOTEPROC
select DMA_ENGINE
select DMA_VIRTUAL_CHANNELS
--
1.9.1
^ permalink raw reply related
* [PATCH v5 4/7] ASoC: sunxi: Add sun8i I2S driver
From: Jean-Francois Moine @ 2016-10-21 8:36 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1477142934.git.moinejf@free.fr>
This patch adds I2S support to sun8i SoCs as the A83T and H3.
Signed-off-by: Jean-Francois Moine <moinejf@free.fr>
---
Note: This driver is closed to the sun4i-i2s except that:
- it handles the H3
- it creates the sound card (with sun4i-i2s, the sound card is created
by the CODECs)
---
.../devicetree/bindings/sound/sun4i-i2s.txt | 38 +-
sound/soc/sunxi/Kconfig | 8 +
sound/soc/sunxi/Makefile | 3 +
sound/soc/sunxi/sun8i-i2s.c | 700 +++++++++++++++++++++
4 files changed, 744 insertions(+), 5 deletions(-)
create mode 100644 sound/soc/sunxi/sun8i-i2s.c
diff --git a/Documentation/devicetree/bindings/sound/sun4i-i2s.txt b/Documentation/devicetree/bindings/sound/sun4i-i2s.txt
index 7b526ec..2fb0a7a 100644
--- a/Documentation/devicetree/bindings/sound/sun4i-i2s.txt
+++ b/Documentation/devicetree/bindings/sound/sun4i-i2s.txt
@@ -1,4 +1,4 @@
-* Allwinner A10 I2S controller
+* Allwinner A10/A38T/H3 I2S controller
The I2S bus (Inter-IC sound bus) is a serial link for digital
audio data transfer between devices in the system.
@@ -6,20 +6,30 @@ audio data transfer between devices in the system.
Required properties:
- compatible: should be one of the followings
- - "allwinner,sun4i-a10-i2s"
+ - "allwinner,sun4i-a10-i2s"
+ "allwinner,sun8i-a83t-i2s"
+ "allwinner,sun8i-h3-i2s"
- reg: physical base address of the controller and length of memory mapped
region.
-- interrupts: should contain the I2S interrupt.
- dmas: DMA specifiers for tx and rx dma. See the DMA client binding,
Documentation/devicetree/bindings/dma/dma.txt
-- dma-names: should include "tx" and "rx".
+- dma-names: must include "tx" and/or "rx".
- clocks: a list of phandle + clock-specifer pairs, one for each entry in clock-names.
- clock-names: should contain followings:
- "apb" : clock for the I2S bus interface
- "mod" : module clock for the I2S controller
- #sound-dai-cells : Must be equal to 0
-Example:
+Optional properties:
+
+- interrupts: I2S interrupt
+- resets: phandle to the reset of the device
+
+Required nodes:
+
+ - port: link to the associated CODEC (DAC, HDMI...)
+
+Example 1:
i2s0: i2s at 01c22400 {
#sound-dai-cells = <0>;
@@ -32,3 +42,21 @@ i2s0: i2s at 01c22400 {
<&dma SUN4I_DMA_NORMAL 3>;
dma-names = "rx", "tx";
};
+
+Example 2:
+
+i2s2: i2s at 1c22800 {
+ compatible = "allwinner,sun8i-a83t-i2s";
+ reg = <0x01c22800 0x60>;
+ clocks = <&ccu CLK_BUS_I2S2>, <&ccu CLK_I2S2>;
+ clock-names = "apb", "mod";
+ resets = <&ccu RST_I2S2>;
+ dmas = <&dma 27>;
+ dma-names = "tx";
+ status = "disabled";
+ port {
+ i2s2_hdmi: endpoint {
+ remote-endpoint = <&hdmi_i2s2>;
+ };
+ };
+};
diff --git a/sound/soc/sunxi/Kconfig b/sound/soc/sunxi/Kconfig
index dd23682..d89b2da 100644
--- a/sound/soc/sunxi/Kconfig
+++ b/sound/soc/sunxi/Kconfig
@@ -26,4 +26,12 @@ config SND_SUN4I_SPDIF
help
Say Y or M to add support for the S/PDIF audio block in the Allwinner
A10 and affiliated SoCs.
+
+config SND_SUN8I_I2S
+ tristate "Allwinner sun8i I2S Support"
+ depends on OF
+ select SND_SOC_GENERIC_DMAENGINE_PCM
+ help
+ Say Y or M if you want to add support for SoC audio on
+ Allwinner sun8i boards.
endmenu
diff --git a/sound/soc/sunxi/Makefile b/sound/soc/sunxi/Makefile
index 604c7b84..bcb871b 100644
--- a/sound/soc/sunxi/Makefile
+++ b/sound/soc/sunxi/Makefile
@@ -1,3 +1,6 @@
obj-$(CONFIG_SND_SUN4I_CODEC) += sun4i-codec.o
obj-$(CONFIG_SND_SUN4I_I2S) += sun4i-i2s.o
obj-$(CONFIG_SND_SUN4I_SPDIF) += sun4i-spdif.o
+
+snd-soc-sun8i-i2s-objs := sun8i-i2s.o
+obj-$(CONFIG_SND_SUN8I_I2S) += snd-soc-sun8i-i2s.o
diff --git a/sound/soc/sunxi/sun8i-i2s.c b/sound/soc/sunxi/sun8i-i2s.c
new file mode 100644
index 0000000..ba15d62
--- /dev/null
+++ b/sound/soc/sunxi/sun8i-i2s.c
@@ -0,0 +1,700 @@
+/*
+ * Allwinner sun8i I2S sound card
+ *
+ * Copyright (C) 2016 Jean-Francois Moine <moinejf@free.fr>
+ *
+ * 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.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/reset.h>
+#include <sound/pcm_params.h>
+#include <sound/dmaengine_pcm.h>
+#include <linux/of_device.h>
+#include <linux/of_graph.h>
+
+/* --- hardware --- */
+
+#define I2S_CTL 0x00
+ /* common */
+ #define I2S_CTL_SDO3EN BIT(11)
+ #define I2S_CTL_SDO2EN BIT(10)
+ #define I2S_CTL_SDO1EN BIT(9)
+ #define I2S_CTL_SDO0EN BIT(8)
+ #define I2S_CTL_TXEN BIT(2)
+ #define I2S_CTL_RXEN BIT(1)
+ #define I2S_CTL_GEN BIT(0)
+ /* a83t */
+ #define I2S_CTL_A83T_MS BIT(5)
+ #define I2S_CTL_A83T_PCM BIT(4)
+ /* h3 */
+ #define I2S_CTL_H3_BCLKOUT BIT(18)
+ #define I2S_CTL_H3_LRCKOUT BIT(17)
+ #define I2S_CTL_H3_MODE_MSK (3 << 4)
+ #define I2S_CTL_H3_MODE_I2S (1 << 4)
+
+#define I2S_FAT0 0x04
+ /* common */
+ /* a83t */
+ #define I2S_FAT0_A83T_LRCP BIT(7)
+ #define I2S_FAT0_A83T_BCP BIT(6)
+ #define I2S_FAT0_A83T_SR_16BIT (0 << 4)
+ #define I2S_FAT0_A83T_SR_24BIT (2 << 4)
+ #define I2S_FAT0_A83T_SR_MSK (3 << 4)
+ #define I2S_FAT0_A83T_WSS_32BCLK (3 << 2)
+ #define I2S_FAT0_A83T_FMT_I2S1 (0 << 0)
+ #define I2S_FAT0_A83T_FMT_LFT (1 << 0)
+ #define I2S_FAT0_A83T_FMT_RGT (2 << 0)
+ #define I2S_FAT0_A83T_FMT_MSK (3 << 0)
+ /* h3 */
+ #define I2S_FAT0_H3_LRCKR_PERIOD(v) ((v) << 20)
+ #define I2S_FAT0_H3_LRCKR_PERIOD_MSK (0x3ff << 20)
+ #define I2S_FAT0_H3_LRCK_POLARITY BIT(19)
+ #define I2S_FAT0_H3_LRCK_PERIOD(v) ((v) << 8)
+ #define I2S_FAT0_H3_LRCK_PERIOD_MSK (0x3ff << 8)
+ #define I2S_FAT0_H3_BCLK_POLARITY BIT(7)
+ #define I2S_FAT0_H3_SR_16 (3 << 4)
+ #define I2S_FAT0_H3_SR_24 (5 << 4)
+ #define I2S_FAT0_H3_SR_MSK (7 << 4)
+ #define I2S_FAT0_H3_SW_16 (3 << 0)
+ #define I2S_FAT0_H3_SW_32 (7 << 0)
+ #define I2S_FAT0_H3_SW_MSK (7 << 0)
+
+#define I2S_FAT1 0x08
+
+#define I2S_FCTL 0x14
+ #define I2S_FCTL_FTX BIT(25)
+ #define I2S_FCTL_FRX BIT(24)
+ #define I2S_FCTL_TXTL(v) ((v) << 12)
+ #define I2S_FCTL_TXIM BIT(2)
+
+#define I2S_INT 0x1c
+ #define I2S_INT_TXDRQEN BIT(7)
+
+#define I2S_TXFIFO 0x20
+
+#define I2S_CLKD 0x24
+ /* common */
+ #define I2S_CLKD_BCLKDIV(v) ((v) << 4)
+ #define I2S_CLKD_MCLKDIV(v) ((v) << 0)
+ /* a83t */
+ #define I2S_CLKD_A83T_MCLKOEN BIT(7)
+ /* h3 */
+ #define I2S_CLKD_H3_MCLKOEN BIT(8)
+
+#define I2S_TXCNT 0x28
+
+#define I2S_RXCNT 0x2c
+
+/* --- A83T --- */
+#define I2S_TXCHSEL_A83T 0x30
+ #define I2S_TXCHSEL_A83T_CHNUM(v) (((v) - 1) << 0)
+ #define I2S_TXCHSEL_A83T_CHNUM_MSK (7 << 0)
+
+#define I2S_TXCHMAP_A83T 0x34
+
+/* --- H3 --- */
+#define I2S_TXCHCFG_H3 0x30
+ #define I2S_TXCHCFG_H3_TX_SLOT_NUM_MSK (7 << 0)
+ #define I2S_TXCHCFG_H3_TX_SLOT_NUM(v) ((v) << 0)
+
+#define I2S_TX0CHSEL_H3 0x34 /* 0..3 */
+ #define I2S_TXn_H3_OFFSET_MSK (3 << 12)
+ #define I2S_TXn_H3_OFFSET(v) ((v) << 12)
+ #define I2S_TXn_H3_CHEN_MSK (0xff << 4)
+ #define I2S_TXn_H3_CHEN(v) ((v) << 4)
+ #define I2S_TXn_H3_CHSEL_MSK (7 << 0)
+ #define I2S_TXn_H3_CHSEL(v) ((v) << 0)
+
+#define I2S_TX0CHMAP_H3 0x44 /* 0..3 */
+
+/* --- driver --- */
+
+#define DRV_NAME "sun8i-audio"
+
+#define I2S_FORMATS \
+ (SNDRV_PCM_FMTBIT_S16_LE | \
+ SNDRV_PCM_FMTBIT_S20_3LE | \
+ SNDRV_PCM_FMTBIT_S24_LE | \
+ SNDRV_PCM_FMTBIT_S32_LE)
+
+#define PCM_LRCK_PERIOD 32
+#define PCM_LRCKR_PERIOD 1
+
+struct priv {
+ void __iomem *mmio;
+ struct clk *clk;
+ struct clk *gate;
+ struct reset_control *rstc;
+ int type;
+#define SOC_A83T 0
+#define SOC_H3 1
+ struct snd_dmaengine_dai_dma_data dma_data;
+};
+
+static const struct of_device_id sun8i_i2s_of_match[] = {
+ { .compatible = "allwinner,sun8i-a83t-i2s",
+ .data = (void *) SOC_A83T },
+ { .compatible = "allwinner,sun8i-h3-i2s",
+ .data = (void *) SOC_H3 },
+ { }
+};
+MODULE_DEVICE_TABLE(of, sun8i_i2s_of_match);
+
+/* --- CPU DAI --- */
+
+static void sun8i_i2s_init(struct priv *priv)
+{
+ u32 reg;
+
+ /* disable global */
+ reg = readl(priv->mmio + I2S_CTL);
+ reg &= ~(I2S_CTL_GEN |
+ I2S_CTL_RXEN |
+ I2S_CTL_TXEN);
+ writel(reg, priv->mmio + I2S_CTL);
+
+ /* A83T */
+ if (priv->type == SOC_A83T) {
+ reg &= ~(I2S_CTL_A83T_MS | /* codec clk & FRM slave */
+ I2S_CTL_A83T_PCM); /* I2S mode */
+ writel(reg, priv->mmio + I2S_CTL);
+
+ reg = readl(priv->mmio + I2S_FAT0);
+ reg &= ~I2S_FAT0_A83T_FMT_MSK;
+ reg |= I2S_FAT0_A83T_FMT_I2S1;
+
+ reg &= ~(I2S_FAT0_A83T_LRCP | I2S_FAT0_A83T_BCP);
+ writel(reg, priv->mmio + I2S_FAT0);
+
+ reg = I2S_FCTL_TXIM | /* fifo */
+ I2S_FCTL_TXTL(0x40);
+ writel(reg, priv->mmio + I2S_FCTL);
+
+ reg = readl(priv->mmio + I2S_FAT0);
+ reg &= ~(I2S_FAT0_A83T_LRCP | /* normal bit clock + frame */
+ I2S_FAT0_A83T_BCP);
+ writel(reg, priv->mmio + I2S_FAT0);
+
+ /* H3 */
+ } else {
+ reg = readl(priv->mmio + I2S_FCTL);
+ reg &= ~(I2S_FCTL_FRX | I2S_FCTL_FTX); /* clear the FIFOs */
+ writel(reg, priv->mmio + I2S_FCTL);
+
+ writel(0, priv->mmio + I2S_TXCNT); /* FIFO counters */
+ writel(0, priv->mmio + I2S_RXCNT);
+
+ reg = readl(priv->mmio + I2S_CTL);
+ reg |= I2S_CTL_H3_LRCKOUT | I2S_CTL_H3_BCLKOUT;
+ /* codec clk & FRM slave */
+
+ reg &= ~I2S_CTL_H3_MODE_MSK;
+ reg |= I2S_CTL_H3_MODE_I2S; /* I2S mode */
+ writel(reg, priv->mmio + I2S_CTL);
+
+ reg = readl(priv->mmio + I2S_TX0CHSEL_H3) &
+ ~I2S_TXn_H3_OFFSET_MSK;
+ reg |= I2S_TXn_H3_OFFSET(1);
+ writel(reg, priv->mmio + I2S_TX0CHSEL_H3);
+
+ reg = readl(priv->mmio + I2S_FAT0);
+ reg &= ~(I2S_FAT0_H3_BCLK_POLARITY | /* normal bclk & frame */
+ I2S_FAT0_H3_LRCK_POLARITY);
+ writel(reg, priv->mmio + I2S_FAT0);
+ }
+}
+
+static int sun8i_i2s_set_clock(struct priv *priv,
+ unsigned long rate)
+{
+ unsigned long freq;
+ int ret, i, div;
+ u32 reg;
+ static const u8 div_tb[] = {
+ 1, 2, 4, 6, 8, 12, 16, 24,
+ };
+
+ /* compute the sys clock rate and divide values */
+ if (rate % 1000 == 0)
+ freq = 24576000;
+ else
+ freq = 22579200;
+ div = freq / 2 / PCM_LRCK_PERIOD / rate;
+ if (priv->type == SOC_A83T)
+ div /= 2; /* bclk_div==0 => mclk/2 */
+ for (i = 0; i < ARRAY_SIZE(div_tb) - 1; i++)
+ if (div_tb[i] >= div)
+ break;
+
+ ret = clk_set_rate(priv->clk, freq);
+ if (ret) {
+ pr_info("Setting sysclk rate failed %d\n", ret);
+ return ret;
+ }
+
+ /* set the mclk and bclk dividor register */
+ if (priv->type == SOC_A83T) {
+ reg = I2S_CLKD_A83T_MCLKOEN | I2S_CLKD_MCLKDIV(i);
+ } else {
+ reg = I2S_CLKD_H3_MCLKOEN | I2S_CLKD_MCLKDIV(1) |
+ I2S_CLKD_BCLKDIV(i + 1);
+ }
+ writel(reg, priv->mmio + I2S_CLKD);
+
+ /* format */
+ reg = readl(priv->mmio + I2S_FAT0);
+ if (priv->type == SOC_A83T) {
+ reg |= I2S_FAT0_A83T_WSS_32BCLK;
+ reg &= ~I2S_FAT0_A83T_SR_MSK;
+ reg |= I2S_FAT0_A83T_SR_16BIT;
+ } else {
+ reg &= ~(I2S_FAT0_H3_LRCKR_PERIOD_MSK |
+ I2S_FAT0_H3_LRCK_PERIOD_MSK);
+ reg |= I2S_FAT0_H3_LRCK_PERIOD(PCM_LRCK_PERIOD - 1) |
+ I2S_FAT0_H3_LRCKR_PERIOD(PCM_LRCKR_PERIOD - 1);
+
+ reg &= ~I2S_FAT0_H3_SW_MSK;
+ reg |= I2S_FAT0_H3_SW_16;
+
+ reg &= ~I2S_FAT0_H3_SR_MSK;
+ reg |= I2S_FAT0_H3_SR_16;
+ }
+ writel(reg, priv->mmio + I2S_FAT0);
+
+ writel(0, priv->mmio + I2S_FAT1);
+
+ return 0;
+}
+
+static int sun8i_i2s_prepare(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_card *card = snd_soc_dai_get_drvdata(dai);
+ struct priv *priv = snd_soc_card_get_drvdata(card);
+ int nchan = substream->runtime->channels;
+ u32 reg;
+
+ if (priv->type == SOC_A83T) {
+ reg = readl(priv->mmio + I2S_TXCHSEL_A83T);
+ reg &= ~I2S_TXCHSEL_A83T_CHNUM_MSK;
+ reg |= I2S_TXCHSEL_A83T_CHNUM(substream->runtime->channels);
+ writel(reg, priv->mmio + I2S_TXCHSEL_A83T);
+
+ switch (substream->runtime->channels) {
+ case 1:
+ reg = 0x76543200;
+ break;
+ case 8:
+ reg = 0x54762310;
+ break;
+ default:
+/* left/right inversion of channels 0 and 1 */
+ reg = 0x76543201;
+ break;
+ }
+ writel(reg, priv->mmio + I2S_TXCHMAP_A83T);
+ } else {
+ reg = readl(priv->mmio + I2S_TXCHCFG_H3) &
+ ~I2S_TXCHCFG_H3_TX_SLOT_NUM_MSK;
+ if (nchan != 1)
+ reg |= I2S_TXCHCFG_H3_TX_SLOT_NUM(1);
+ writel(reg, priv->mmio + I2S_TXCHCFG_H3);
+
+ reg = readl(priv->mmio + I2S_TX0CHSEL_H3);
+ reg &= ~(I2S_TXn_H3_CHEN_MSK |
+ I2S_TXn_H3_CHSEL_MSK);
+ reg |= I2S_TXn_H3_CHEN(3) |
+ I2S_TXn_H3_CHSEL(1);
+ writel(reg, priv->mmio + I2S_TX0CHSEL_H3);
+
+ reg = nchan == 1 ? 0 : 0x10;
+ writel(reg, priv->mmio + I2S_TX0CHMAP_H3);
+ }
+
+ reg = readl(priv->mmio + I2S_CTL);
+ reg &= ~(I2S_CTL_SDO3EN |
+ I2S_CTL_SDO2EN |
+ I2S_CTL_SDO1EN);
+ if (nchan >= 7)
+ reg |= I2S_CTL_SDO3EN;
+ if (nchan >= 5)
+ reg |= I2S_CTL_SDO2EN;
+ if (nchan >= 3)
+ reg |= I2S_CTL_SDO1EN;
+ reg |= I2S_CTL_SDO0EN;
+ writel(reg, priv->mmio + I2S_CTL);
+
+ writel(0, priv->mmio + I2S_TXCNT);
+
+ return 0;
+}
+
+static void sun8i_i2s_shutdown(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_card *card = snd_soc_dai_get_drvdata(dai);
+ struct priv *priv = snd_soc_card_get_drvdata(card);
+ u32 reg;
+
+ reg = readl(priv->mmio + I2S_CTL);
+ reg &= ~I2S_CTL_GEN;
+ writel(reg, priv->mmio + I2S_CTL);
+}
+
+static int sun8i_i2s_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_card *card = snd_soc_dai_get_drvdata(dai);
+ struct priv *priv = snd_soc_card_get_drvdata(card);
+ u32 reg, reg2;
+ int sample_resolution;
+ int ret;
+
+ ret = sun8i_i2s_set_clock(priv, params_rate(params));
+ if (ret)
+ return ret;
+
+ switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_S16_LE:
+ priv->dma_data.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
+ sample_resolution = 16;
+ break;
+ case SNDRV_PCM_FORMAT_S20_3LE:
+ case SNDRV_PCM_FORMAT_S24_LE:
+ case SNDRV_PCM_FORMAT_S32_LE:
+ priv->dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+ sample_resolution = 24;
+ break;
+ default:
+ return -EINVAL;
+ }
+ reg = readl(priv->mmio + I2S_FAT0);
+ reg2 = readl(priv->mmio + I2S_FCTL);
+ if (priv->type == SOC_A83T) {
+ reg &= ~I2S_FAT0_A83T_SR_MSK;
+ if (sample_resolution == 16) {
+ reg |= I2S_FAT0_A83T_SR_16BIT;
+ reg2 |= I2S_FCTL_TXIM;
+ } else {
+ reg |= I2S_FAT0_A83T_SR_24BIT;
+ reg2 &= ~I2S_FCTL_TXIM;
+ }
+ } else {
+ reg &= ~(I2S_FAT0_H3_SR_MSK | I2S_FAT0_H3_SW_MSK);
+ if (sample_resolution == 16) {
+ reg |= I2S_FAT0_H3_SR_16 |
+ I2S_FAT0_H3_SW_16;
+ reg2 |= I2S_FCTL_TXIM;
+ } else {
+ reg |= I2S_FAT0_H3_SR_24 |
+ I2S_FAT0_H3_SW_32;
+ reg2 &= ~I2S_FCTL_TXIM;
+ }
+ }
+ writel(reg, priv->mmio + I2S_FAT0);
+ writel(reg2, priv->mmio + I2S_FCTL);
+
+ /* enable audio interface */
+ reg = readl(priv->mmio + I2S_CTL);
+ reg |= I2S_CTL_GEN;
+ writel(reg, priv->mmio + I2S_CTL);
+ msleep(10);
+
+ /* flush TX FIFO */
+ reg = readl(priv->mmio + I2S_FCTL);
+ reg |= I2S_FCTL_FTX;
+ writel(reg, priv->mmio + I2S_FCTL);
+
+ return 0;
+}
+
+static int sun8i_i2s_trigger(struct snd_pcm_substream *substream,
+ int cmd, struct snd_soc_dai *dai)
+{
+ struct snd_soc_card *card = snd_soc_dai_get_drvdata(dai);
+ struct priv *priv = snd_soc_card_get_drvdata(card);
+ u32 reg;
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_RESUME:
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ reg = readl(priv->mmio + I2S_CTL);
+ reg |= I2S_CTL_TXEN;
+ writel(reg, priv->mmio + I2S_CTL);
+
+ /* enable DMA DRQ mode */
+ reg = readl(priv->mmio + I2S_INT);
+ reg |= I2S_INT_TXDRQEN;
+ writel(reg, priv->mmio + I2S_INT);
+ break;
+ case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ reg = readl(priv->mmio + I2S_INT);
+ reg &= ~I2S_INT_TXDRQEN;
+ writel(reg, priv->mmio + I2S_INT);
+
+ reg = readl(priv->mmio + I2S_CTL);
+ reg &= ~I2S_CTL_TXEN;
+ writel(reg, priv->mmio + I2S_CTL);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static const struct snd_soc_dai_ops sun8i_i2s_dai_ops = {
+ .hw_params = sun8i_i2s_hw_params,
+ .prepare = sun8i_i2s_prepare,
+ .trigger = sun8i_i2s_trigger,
+ .shutdown = sun8i_i2s_shutdown,
+};
+
+static int sun8i_i2s_dai_probe(struct snd_soc_dai *dai)
+{
+ struct snd_soc_card *card = snd_soc_dai_get_drvdata(dai);
+ struct priv *priv = snd_soc_card_get_drvdata(card);
+
+ snd_soc_dai_init_dma_data(dai, &priv->dma_data, NULL);
+
+ return 0;
+}
+
+static struct snd_soc_dai_driver sun8i_i2s_dai = {
+ .probe = sun8i_i2s_dai_probe,
+ .playback = {
+ .stream_name = "Playback",
+ .channels_min = 1,
+ .channels_max = 8,
+ .rates = SNDRV_PCM_RATE_CONTINUOUS,
+ .rate_min = 32000,
+ .rate_max = 192000,
+ .formats = I2S_FORMATS,
+ },
+ .ops = &sun8i_i2s_dai_ops,
+};
+
+static const struct snd_soc_component_driver i2s_component = {
+ .name = DRV_NAME,
+};
+
+/* --- dma --- */
+
+static const struct snd_pcm_hardware sun8i_i2s_pcm_hardware = {
+ .info = SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
+ SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
+ SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME,
+ .formats = I2S_FORMATS,
+ .rates = SNDRV_PCM_RATE_CONTINUOUS,
+ .rate_min = 32000,
+ .rate_max = 192000,
+ .channels_min = 1,
+ .channels_max = 8,
+ .buffer_bytes_max = 1024 * 1024,
+ .period_bytes_min = 156,
+ .period_bytes_max = 1024 * 1024,
+ .periods_min = 1,
+ .periods_max = 8,
+ .fifo_size = 128,
+};
+
+static const struct snd_dmaengine_pcm_config sun8i_i2s_config = {
+ .prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config,
+ .pcm_hardware = &sun8i_i2s_pcm_hardware,
+ .prealloc_buffer_size = 1024 * 1024,
+};
+
+/* --- audio card --- */
+
+static struct device_node *sun8i_get_codec(struct device *dev)
+{
+ struct device_node *ep, *remote;
+
+ ep = of_graph_get_next_endpoint(dev->of_node, NULL);
+ if (!ep)
+ return NULL;
+ remote = of_graph_get_remote_port_parent(ep);
+ of_node_put(ep);
+
+ return remote;
+}
+
+static int sun8i_card_create(struct device *dev, struct priv *priv)
+{
+ struct snd_soc_card *card;
+ struct snd_soc_dai_link *dai_link;
+ struct snd_soc_dai_link_component *codec;
+
+ card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL);
+ if (!card)
+ return -ENOMEM;
+ dai_link = devm_kzalloc(dev, sizeof(*dai_link), GFP_KERNEL);
+ if (!dai_link)
+ return -ENOMEM;
+ codec = devm_kzalloc(dev, sizeof(*codec), GFP_KERNEL);
+ if (!codec)
+ return -ENOMEM;
+
+ codec->of_node = sun8i_get_codec(dev);
+ if (!codec->of_node) {
+ dev_err(dev, "no port node\n");
+ return -ENXIO;
+ }
+
+ card->name = codec->of_node->name;
+ card->dai_link = dai_link;
+ card->num_links = 1;
+ dai_link->name = codec->of_node->name;
+ dai_link->stream_name = codec->of_node->name;
+ dai_link->platform_name = dev_name(dev);
+ dai_link->cpu_name = dev_name(dev);
+
+ dai_link->codecs = codec;
+ dai_link->num_codecs = 1;
+
+ /* the DAI name must be the name of codec node */
+ codec->dai_name = codec->of_node->name;
+
+ card->dev = dev;
+ dev_set_drvdata(dev, card);
+ snd_soc_card_set_drvdata(card, priv);
+
+ return devm_snd_soc_register_card(dev, card);
+}
+
+/* --- module init --- */
+
+static int sun8i_i2s_dev_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct priv *priv;
+ struct resource *mem;
+ int ret;
+
+ if (!dev->of_node) {
+ dev_err(dev, "no DT!\n");
+ return -EINVAL;
+ }
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ /* get the resources */
+ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ priv->mmio = devm_ioremap_resource(dev, mem);
+ if (IS_ERR(priv->mmio))
+ return PTR_ERR(priv->mmio);
+
+ /* get SoC type */
+ priv->type = (int) of_match_device(sun8i_i2s_of_match,
+ &pdev->dev)->data;
+
+ /* get and enable the clocks */
+ priv->gate = devm_clk_get(dev, "apb"); /* optional */
+ priv->clk = devm_clk_get(dev, "mod");
+ if (IS_ERR(priv->clk)) {
+ dev_err(dev, "no clock\n");
+ return PTR_ERR(priv->clk);
+ }
+ ret = clk_set_rate(priv->clk, 24576000);
+ if (ret) {
+ dev_err(dev, "cannot set rate of i2s clock %d\n", ret);
+ return ret;
+ }
+
+ priv->rstc = devm_reset_control_get_optional(dev, NULL);
+ if (!IS_ERR(priv->rstc)) {
+ ret = reset_control_deassert(priv->rstc);
+ if (ret < 0)
+ return ret;
+ }
+
+ if (!IS_ERR(priv->gate)) {
+ ret = clk_prepare_enable(priv->gate);
+ if (ret < 0)
+ goto err_gate;
+ }
+
+ ret = clk_prepare_enable(priv->clk);
+ if (ret < 0)
+ goto err_enable;
+
+ /* activate the audio subsystem */
+ sun8i_i2s_init(priv);
+
+ ret = devm_snd_soc_register_component(dev, &i2s_component,
+ &sun8i_i2s_dai, 1);
+ if (ret) {
+ dev_err(dev, "snd_soc_register_component failed %d\n", ret);
+ goto err_register;
+ }
+
+ ret = devm_snd_dmaengine_pcm_register(dev, &sun8i_i2s_config, 0);
+ if (ret) {
+ dev_err(dev, "pcm_register failed %d\n", ret);
+ goto err_register;
+ }
+
+ priv->dma_data.maxburst = priv->type == SOC_A83T ? 8 : 4;
+ priv->dma_data.addr = mem->start + I2S_TXFIFO;
+ priv->dma_data.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
+
+ ret = sun8i_card_create(dev, priv);
+ if (ret) {
+ if (ret != -EPROBE_DEFER)
+ dev_err(dev, "register card failed %d\n", ret);
+ goto err_register;
+ }
+
+ return 0;
+
+err_register:
+ clk_disable_unprepare(priv->clk);
+err_enable:
+ clk_disable_unprepare(priv->gate);
+err_gate:
+ if (!IS_ERR(priv->rstc))
+ reset_control_assert(priv->rstc);
+
+ return ret;
+}
+
+static int sun8i_i2s_dev_remove(struct platform_device *pdev)
+{
+ struct snd_soc_card *card = dev_get_drvdata(&pdev->dev);
+ struct priv *priv = snd_soc_card_get_drvdata(card);
+
+ clk_disable_unprepare(priv->clk);
+ clk_disable_unprepare(priv->gate);
+ if (!IS_ERR_OR_NULL(priv->rstc))
+ reset_control_assert(priv->rstc);
+
+ return 0;
+}
+
+static struct platform_driver sun8i_i2s_driver = {
+ .probe = sun8i_i2s_dev_probe,
+ .remove = sun8i_i2s_dev_remove,
+ .driver = {
+ .name = DRV_NAME,
+ .of_match_table = of_match_ptr(sun8i_i2s_of_match),
+ },
+};
+
+module_platform_driver(sun8i_i2s_driver);
+
+MODULE_AUTHOR("Jean-Francois Moine <moinejf@free.fr>");
+MODULE_DESCRIPTION("Allwinner sun8i I2S ASoC Interface");
+MODULE_LICENSE("GPL v2");
--
2.10.1
^ permalink raw reply related
* mbox-name vs. mbox-names (was: Re: [PATCH v4 1/5] mailbox: dt: Supply bindings for ST's Mailbox IP)
From: Geert Uytterhoeven @ 2016-10-21 8:30 UTC (permalink / raw)
To: linux-arm-kernel
On Fri, Oct 16, 2015 at 9:21 AM, Lee Jones <lee.jones@linaro.org> wrote:
> Signed-off-by: Lee Jones <lee.jones@linaro.org>
> ---
> .../devicetree/bindings/mailbox/sti-mailbox.txt | 51 ++++++++++++++++++++++
> 1 file changed, 51 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/mailbox/sti-mailbox.txt
>
> diff --git a/Documentation/devicetree/bindings/mailbox/sti-mailbox.txt b/Documentation/devicetree/bindings/mailbox/sti-mailbox.txt
> new file mode 100644
> index 0000000..b61eec9
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/mailbox/sti-mailbox.txt
> @@ -0,0 +1,51 @@
> +ST Microelectronics Mailbox Driver
> +
> +Each ST Mailbox IP currently consists of 4 instances of 32 channels. Messages
> +are passed between Application and Remote processors using shared memory.
> +
> +Controller
> +----------
> +
> +Required properties:
> +- compatible : Should be "st,stih407-mailbox"
> +- reg : Offset and length of the device's register set
> +- mbox-name : Name of the mailbox
All other mailbox drivers use "mbox-names". Oops, it's in v4.9-rc1...
Can we still fix that?
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert at linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
^ permalink raw reply
* [RFC PATCH] net: stmmac: Add OXNAS Glue Driver
From: Neil Armstrong @ 2016-10-21 8:28 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAGhQ9VxJ-gQTX1xjMOJ4spiL_RnhryyQ0=gUEQCHm3sHecTVuA@mail.gmail.com>
On 10/20/2016 06:26 PM, Joachim Eastwood wrote:
> Hi Neil,
>
> On 20 October 2016 at 17:54, Neil Armstrong <narmstrong@baylibre.com> wrote:
>> Add Synopsys Designware MAC Glue layer for the Oxford Semiconductor OX820.
>>
>> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
>> ---
>> .../devicetree/bindings/net/oxnas-dwmac.txt | 44 ++++++
>> drivers/net/ethernet/stmicro/stmmac/Kconfig | 11 ++
>> drivers/net/ethernet/stmicro/stmmac/Makefile | 1 +
>> drivers/net/ethernet/stmicro/stmmac/dwmac-oxnas.c | 173 +++++++++++++++++++++
>> 4 files changed, 229 insertions(+)
>> create mode 100644 Documentation/devicetree/bindings/net/oxnas-dwmac.txt
>> create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwmac-oxnas.c
> <snip>
>> +
>> +static int oxnas_dwmac_probe(struct platform_device *pdev)
>> +{
>> + struct plat_stmmacenet_data *plat_dat;
>> + struct stmmac_resources stmmac_res;
>> + struct device_node *sysctrl;
>> + struct oxnas_dwmac *dwmac;
>> + int ret;
>> +
>> + sysctrl = of_parse_phandle(pdev->dev.of_node, "oxsemi,sys-ctrl", 0);
>> + if (!sysctrl) {
>> + dev_err(&pdev->dev, "failed to get sys-ctrl node\n");
>> + return -EINVAL;
>> + }
>> +
>> + ret = stmmac_get_platform_resources(pdev, &stmmac_res);
>> + if (ret)
>> + return ret;
>> +
>> + plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac);
>> + if (IS_ERR(plat_dat))
>> + return PTR_ERR(plat_dat);
>> +
>> + dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac), GFP_KERNEL);
>> + if (!dwmac)
>> + return -ENOMEM;
>> +
>> + dwmac->regmap = syscon_node_to_regmap(sysctrl);
>> + if (IS_ERR(dwmac->regmap)) {
>> + dev_err(&pdev->dev, "failed to have sysctrl regmap\n");
>> + return PTR_ERR(dwmac->regmap);
>> + }
>> +
>> + dwmac->clk = devm_clk_get(&pdev->dev, "gmac");
>> + if (IS_ERR(dwmac->clk))
>> + return PTR_ERR(dwmac->clk);
>> +
>> + plat_dat->bsp_priv = dwmac;
>> + plat_dat->init = oxnas_dwmac_init;
>> + plat_dat->exit = oxnas_dwmac_exit;
>
> Please do not use the init/exit callbacks. Implement proper driver
> callbacks instead. I.e: PM resume/suspend and driver remove.
>
> Shouldn't you call oxnas_dwmac_init() from probe as well?
> As it is now it will only be called during PM resume and that can't be right.
>
>
>> +
>> + return stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
>
> If stmmac_dvr_probe() fails you should disable your clocks.
>
>
> regards,
> Joachim Eastwood
>
Hi Joachim,
Thanks for the hints, stm32 glue does that and I will sync on it.
Neil
^ permalink raw reply
* [PATCH] ARM: dts: rockchip: add i2c-bus subnode to edp
From: Heiko Stuebner @ 2016-10-21 8:25 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <6083453f-08e1-643a-9638-1db38c704aa5@collabora.com>
Am Donnerstag, 20. Oktober 2016, 15:47:56 CEST schrieb Tomeu Vizoso:
> On 10/20/2016 03:45 PM, Heiko St?bner wrote:
> > Am Donnerstag, 20. Oktober 2016, 10:07:25 schrieb Tomeu Vizoso:
> >> Add an empty 'i2c-bus' subnode to the edp node just so that the I2C core
> >> doesn't attemp to parse the 'ports' subnode as containing i2c devices.
> >>
> >> This is to avoid spurious failure messages such as:
> >>
> >> i2c i2c-6: of_i2c: modalias failure on /dp at ff970000/ports
> >
> > On the one hand, the edp really has an i2c bus - with its only client the
> > EDID listening at 0x50 (and maybe 0x30).
> >
> > On the other hand, adding an empty bus to the (implementation independent)
> > devicetree just to make the Linux i2c subsystem happy sounds heavily like
> > a
> > implementation-specific hack, as the edp i2c bus doesn't leak into the
> > outside world otherwise.
> >
> > I guess this empty i2c bus not being part of the binding document points
> > heavily into the implementation-specific corner :-) .
> >
> > My short search on other patches touching this didn't reveal anything but
> > maybe this was already discussed somewhere and found to be ok?
>
> Here it is:
>
> http://www.spinics.net/lists/linux-tegra/msg27862.html
thanks ... I'm still not sure about the placeholder though, aka needing an
undocumented subnode to make a Linux error message silent.
In the thread you pointed to I also did not see any dt-maintainer involvement
pointing one way or another, but spinics is often not easy to navigate
threads, so I may have missed that.
> > Another option could be to just make of_i2c_register_device silent if
> > of_modalias_node returns -ENODEV?
Heiko
> >> Signed-off-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
> >> Cc: Randy Li <randy.li@rock-chips.com>
> >> Cc: Jon Hunter <jonathanh@nvidia.com>
> >> ---
> >>
> >> arch/arm/boot/dts/rk3288.dtsi | 5 +++++
> >> 1 file changed, 5 insertions(+)
> >>
> >> diff --git a/arch/arm/boot/dts/rk3288.dtsi
> >> b/arch/arm/boot/dts/rk3288.dtsi
> >> index 2f814ffeb605..94f4b7eecca2 100644
> >> --- a/arch/arm/boot/dts/rk3288.dtsi
> >> +++ b/arch/arm/boot/dts/rk3288.dtsi
> >> @@ -1075,6 +1075,11 @@
> >>
> >> };
> >>
> >> };
> >>
> >> };
> >>
> >> +
> >> + i2c-bus {
> >> + #address-cells = <1>;
> >> + #size-cells = <0>;
> >> + };
> >>
> >> };
> >>
> >> hdmi: hdmi at ff980000 {
^ permalink raw reply
* [PATCH 1/2] mmc: mediatek: Fix module autoload
From: Ulf Hansson @ 2016-10-21 8:22 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1476720825-30442-1-git-send-email-javier@osg.samsung.com>
On 17 October 2016 at 18:13, Javier Martinez Canillas
<javier@osg.samsung.com> wrote:
> If the driver is built as a module, autoload won't work because the module
> alias information is not filled. So user-space can't match the registered
> device with the corresponding module.
>
> Export the module alias information using the MODULE_DEVICE_TABLE() macro.
>
> Before this patch:
>
> $ modinfo drivers/mmc/host/mtk-sd.ko | grep alias
> $
>
> After this patch:
>
> $ modinfo drivers/mmc/host/mtk-sd.ko | grep alias
> alias: of:N*T*Cmediatek,mt8135-mmcC*
> alias: of:N*T*Cmediatek,mt8135-mmc
>
> Signed-off-by: Javier Martinez Canillas <javier@osg.samsung.com>
Thanks, applied for next!
Kind regards
Uffe
> ---
>
> drivers/mmc/host/mtk-sd.c | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c
> index 84e9afcb5c09..86af0b199a54 100644
> --- a/drivers/mmc/host/mtk-sd.c
> +++ b/drivers/mmc/host/mtk-sd.c
> @@ -1713,6 +1713,7 @@ static const struct of_device_id msdc_of_ids[] = {
> { .compatible = "mediatek,mt8135-mmc", },
> {}
> };
> +MODULE_DEVICE_TABLE(of, msdc_of_ids);
>
> static struct platform_driver mt_msdc_driver = {
> .probe = msdc_drv_probe,
> --
> 2.7.4
>
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox