* [PATCH v3 11/21] ARM: pxa: support ICP DAS LP-8x4x FPGA irq
From: Sergei Ianovich @ 2014-01-15 13:17 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CACRpkda_6P3s3LBwV5ve+=_JhxehephvpPT=pKPk3NzEKQLa9g@mail.gmail.com>
On Wed, 2014-01-15 at 08:39 +0100, Linus Walleij wrote:
> On Wed, Jan 8, 2014 at 8:01 PM, Sergei Ianovich <ynvich@gmail.com> wrote:
> Hm I don't know why I was deluded into thinking this had something to
> do with GPIO. I must have been soft in the head. Sorry about all those
> comments ...
It's not your fault for sure. My commit message wasn't clear enough and
needed clarifications. It is better now.
Thanks for constructive reviewing.
^ permalink raw reply
* [PATCH repost] at91: dt: i2c: add a new compatibility string for the at91sam9261
From: Jean-Jacques Hiblot @ 2014-01-15 13:17 UTC (permalink / raw)
To: linux-arm-kernel
Signed-off-by: Jean-Jacques Hiblot <jjhiblot@traphandler.com>
---
drivers/i2c/busses/i2c-at91.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/i2c/busses/i2c-at91.c b/drivers/i2c/busses/i2c-at91.c
index 8edba9d..843d012 100644
--- a/drivers/i2c/busses/i2c-at91.c
+++ b/drivers/i2c/busses/i2c-at91.c
@@ -589,6 +589,9 @@ static const struct of_device_id atmel_twi_dt_ids[] = {
.compatible = "atmel,at91sam9260-i2c",
.data = &at91sam9260_config,
} , {
+ .compatible = "atmel,at91sam9261-i2c",
+ .data = &at91sam9261_config,
+ } , {
.compatible = "atmel,at91sam9g20-i2c",
.data = &at91sam9g20_config,
} , {
--
1.8.5.2
^ permalink raw reply related
* [PATCH v3.2 11/21] ARM: pxa: support ICP DAS LP-8x4x FPGA irq
From: Sergei Ianovich @ 2014-01-15 13:12 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1389308855-32588-1-git-send-email-ynvich@gmail.com>
ICP DAS LP-8x4x contains FPGA chip. The chip functions as an interrupt
source providing 16 additional interrupts among other things. The
interrupt lines are muxed to a GPIO pin of a 2nd level PXA-GPIO
interrupt controller. GPIO pins of the 2nd level controller are in turn
muxed to a CPU interrupt line.
Until pxa is completely converted to device tree, it is impossible
to use IRQCHIP_DECLARE() and the irqdomain needs to added manually.
Drivers for the on-CPU IRQs and GPIO-IRQs are loaded using
postcore_initcall(). We need to have all irq domain drivers loaded prior
to DT parsing in order to allow normal initialization of IRQ resources
with DT.
Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
CC: Arnd Bergmann <arnd@arndb.de>
---
v3.1..v3.2
fixes to apply Linus Walleij's "Reviewed-by":
* add kerneldoc comment for state container struct
* rename irq -> hwirq for clarity
* drop overzealous error checks from the hotpaths
v3..v3.1
fixes according to Linus Walleij review comments:
* update commit message
* use state container instead of global variables
* get hardware irq nums from irq_data, don't calculate them
* use BIT() macro
* add defines for system irq register masks
* replace cycle control variable with break
* use better names for resource variables
* add a linear domain instead of a legacy one
* use irq_create_mapping() instead of irq_alloc_desc()
v2..v3
* no changes (except number 09/16 -> 11/21)
v0..v2
* extract irqchip and move to drivers/irqchip/
* use device tree
* use devm helpers where possible
.../bindings/interrupt-controller/irq-lp8x4x.txt | 49 +++++
arch/arm/boot/dts/pxa27x-lp8x4x.dts | 10 +
drivers/irqchip/Kconfig | 5 +
drivers/irqchip/Makefile | 1 +
drivers/irqchip/irq-lp8x4x.c | 227 +++++++++++++++++++++
5 files changed, 292 insertions(+)
create mode 100644 Documentation/devicetree/bindings/interrupt-controller/irq-lp8x4x.txt
create mode 100644 drivers/irqchip/irq-lp8x4x.c
diff --git a/Documentation/devicetree/bindings/interrupt-controller/irq-lp8x4x.txt b/Documentation/devicetree/bindings/interrupt-controller/irq-lp8x4x.txt
new file mode 100644
index 0000000..c8940d2
--- /dev/null
+++ b/Documentation/devicetree/bindings/interrupt-controller/irq-lp8x4x.txt
@@ -0,0 +1,49 @@
+ICP DAS LP-8x4x FPGA Interrupt Controller
+
+ICP DAS LP-8x4x contains FPGA chip. The chip functions as a interrupt
+source providing 16 additional interrupts among other things.
+
+Required properties:
+- compatible : should be "icpdas,irq-lp8x4x"
+
+- reg: physical base address of the controller and length of memory mapped
+ region.
+
+- interrupt-controller : identifies the node as an interrupt controller
+
+- #interrupt-cells : should be 1
+
+- interrupts : should provide interrupt
+
+- interrupt-parent : should provide a link to interrupt controller either
+ explicitly and implicitly from a parent node
+
+Example:
+
+ fpga: fpga at 17000006 {
+ compatible = "icpdas,irq-lp8x4x";
+ reg = <0x17000006 0x16>;
+ interrupt-parent = <&gpio>;
+ interrupts = <3 IRQ_TYPE_EDGE_RISING>;
+ #interrupt-cells = <1>;
+ interrupt-controller;
+ status = "okay";
+ };
+
+ uart at 17009050 {
+ compatible = "icpdas,uart-lp8x4x";
+ reg = <0x17009050 0x10
+ 0x17009030 0x02>;
+ interrupt-parent = <&fpga>;
+ interrupts = <13>;
+ status = "okay";
+ };
+
+ uart at 17009060 {
+ compatible = "icpdas,uart-lp8x4x";
+ reg = <0x17009060 0x10
+ 0x17009032 0x02>;
+ interrupt-parent = <&fpga>;
+ interrupts = <14>;
+ status = "okay";
+ };
diff --git a/arch/arm/boot/dts/pxa27x-lp8x4x.dts b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
index 07856e0..78dfd2e 100644
--- a/arch/arm/boot/dts/pxa27x-lp8x4x.dts
+++ b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
@@ -167,6 +167,16 @@
reg = <0xa000 0x1000
0x901e 0x1>;
};
+
+ fpgairq: irq at 9006 {
+ compatible = "icpdas,irq-lp8x4x";
+ reg = <0x9006 0x16>;
+ interrupt-parent = <&gpio>;
+ interrupts = <3 IRQ_TYPE_EDGE_FALLING>;
+ #interrupt-cells = <1>;
+ interrupt-controller;
+ status = "okay";
+ };
};
};
};
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index 3792a1a..7e22729 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -35,6 +35,11 @@ config IMGPDC_IRQ
select GENERIC_IRQ_CHIP
select IRQ_DOMAIN
+config LP8X4X_IRQ
+ bool
+ depends on OF
+ select IRQ_DOMAIN
+
config ORION_IRQCHIP
bool
select IRQ_DOMAIN
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index c60b901..8a28927 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -22,3 +22,4 @@ obj-$(CONFIG_RENESAS_IRQC) += irq-renesas-irqc.o
obj-$(CONFIG_VERSATILE_FPGA_IRQ) += irq-versatile-fpga.o
obj-$(CONFIG_ARCH_VT8500) += irq-vt8500.o
obj-$(CONFIG_TB10X_IRQC) += irq-tb10x.o
+obj-$(CONFIG_LP8X4X_IRQ) += irq-lp8x4x.o
diff --git a/drivers/irqchip/irq-lp8x4x.c b/drivers/irqchip/irq-lp8x4x.c
new file mode 100644
index 0000000..12ccbb03
--- /dev/null
+++ b/drivers/irqchip/irq-lp8x4x.c
@@ -0,0 +1,227 @@
+/*
+ * linux/drivers/irqchip/irq-lp8x4x.c
+ *
+ * Support for ICP DAS LP-8x4x FPGA irq
+ * Copyright (C) 2013 Sergei Ianovich <ynvich@gmail.com>
+ *
+ * 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 or any later version.
+ */
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/irqchip/chained_irq.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+#define EOI 0x00000000
+#define INSINT 0x00000002
+#define ENSYSINT 0x00000004
+#define PRIMINT 0x00000006
+#define PRIMINT_MASK 0xe0
+#define SECOINT 0x00000008
+#define SECOINT_MASK 0x1f
+#define ENRISEINT 0x0000000A
+#define CLRRISEINT 0x0000000C
+#define ENHILVINT 0x0000000E
+#define CLRHILVINT 0x00000010
+#define ENFALLINT 0x00000012
+#define CLRFALLINT 0x00000014
+#define IRQ_MEM_SIZE 0x00000016
+#define LP8X4X_NUM_IRQ_DEFAULT 16
+
+/**
+ * struct lp8x4x_irq_data - LP8X4X custom irq controller state container
+ * @base: base IO memory address
+ * @irq_domain: Interrupt translation domain; responsible for mapping
+ * between hwirq number and linux irq number
+ * @irq_sys_enabled: mask keeping track of interrupts enabled in the
+ * register which vendor calls 'system'
+ * @irq_high_enabled: mask keeping track of interrupts enabled in the
+ * register which vendor calls 'high'
+ *
+ * The structure implements State Container from
+ * Documentation/driver-model/design-patterns.txt
+ */
+
+struct lp8x4x_irq_data {
+ void *base;
+ struct irq_domain *domain;
+ unsigned char irq_sys_enabled;
+ unsigned char irq_high_enabled;
+};
+
+static void lp8x4x_mask_irq(struct irq_data *d)
+{
+ unsigned mask;
+ unsigned long hwirq = d->hwirq;
+ struct lp8x4x_irq_data *host = irq_data_get_irq_chip_data(d);
+
+ if (hwirq < 8) {
+ host->irq_high_enabled &= ~BIT(hwirq);
+
+ mask = ioread8(host->base + ENHILVINT);
+ mask &= ~BIT(hwirq);
+ iowrite8(mask, host->base + ENHILVINT);
+ } else {
+ hwirq -= 8;
+ host->irq_sys_enabled &= ~BIT(hwirq);
+
+ mask = ioread8(host->base + ENSYSINT);
+ mask &= ~BIT(hwirq);
+ iowrite8(mask, host->base + ENSYSINT);
+ }
+}
+
+static void lp8x4x_unmask_irq(struct irq_data *d)
+{
+ unsigned mask;
+ unsigned long hwirq = d->hwirq;
+ struct lp8x4x_irq_data *host = irq_data_get_irq_chip_data(d);
+
+ if (hwirq < 8) {
+ host->irq_high_enabled |= BIT(hwirq);
+ mask = ioread8(host->base + CLRHILVINT);
+ mask |= BIT(hwirq);
+ iowrite8(mask, host->base + CLRHILVINT);
+
+ mask = ioread8(host->base + ENHILVINT);
+ mask |= BIT(hwirq);
+ iowrite8(mask, host->base + ENHILVINT);
+ } else {
+ hwirq -= 8;
+ host->irq_sys_enabled |= BIT(hwirq);
+
+ mask = ioread8(host->base + SECOINT);
+ mask |= BIT(hwirq);
+ iowrite8(mask, host->base + SECOINT);
+
+ mask = ioread8(host->base + ENSYSINT);
+ mask |= BIT(hwirq);
+ iowrite8(mask, host->base + ENSYSINT);
+ }
+}
+
+static struct irq_chip lp8x4x_irq_chip = {
+ .name = "FPGA",
+ .irq_ack = lp8x4x_mask_irq,
+ .irq_mask = lp8x4x_mask_irq,
+ .irq_mask_ack = lp8x4x_mask_irq,
+ .irq_unmask = lp8x4x_unmask_irq,
+};
+
+static void lp8x4x_irq_handler(unsigned int irq, struct irq_desc *desc)
+{
+ int n;
+ unsigned long mask;
+ struct irq_chip *chip = irq_desc_get_chip(desc);
+ struct lp8x4x_irq_data *host = irq_desc_get_handler_data(desc);
+
+ chained_irq_enter(chip, desc);
+
+ for (;;) {
+ mask = ioread8(host->base + CLRHILVINT) & 0xff;
+ mask |= (ioread8(host->base + SECOINT) & SECOINT_MASK) << 8;
+ mask |= (ioread8(host->base + PRIMINT) & PRIMINT_MASK) << 8;
+ mask &= host->irq_high_enabled | (host->irq_sys_enabled << 8);
+ if (mask == 0)
+ break;
+ for_each_set_bit(n, &mask, BITS_PER_LONG)
+ generic_handle_irq(irq_find_mapping(host->domain, n));
+ }
+
+ iowrite8(0, host->base + EOI);
+ chained_irq_exit(chip, desc);
+}
+
+static int lp8x4x_irq_domain_map(struct irq_domain *d, unsigned int irq,
+ irq_hw_number_t hw)
+{
+ struct lp8x4x_irq_data *host = d->host_data;
+ int err;
+
+ err = irq_set_chip_data(irq, host);
+ if (err < 0)
+ return err;
+
+ irq_set_chip_and_handler(irq, &lp8x4x_irq_chip, handle_level_irq);
+ set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+ return 0;
+}
+
+const struct irq_domain_ops lp8x4x_irq_domain_ops = {
+ .map = lp8x4x_irq_domain_map,
+ .xlate = irq_domain_xlate_onecell,
+};
+
+static struct of_device_id lp8x4x_irq_dt_ids[] = {
+ { .compatible = "icpdas,irq-lp8x4x", },
+ {}
+};
+
+static int lp8x4x_irq_probe(struct platform_device *pdev)
+{
+ struct resource *res_mem, *res_irq;
+ struct device_node *np = pdev->dev.of_node;
+ struct lp8x4x_irq_data *host;
+ int i, err;
+
+ res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ if (!res_mem || !res_irq || resource_size(res_mem) < IRQ_MEM_SIZE)
+ return -ENODEV;
+
+ host = devm_kzalloc(&pdev->dev, sizeof(*host), GFP_KERNEL);
+ if (!host)
+ return -ENODEV;
+
+ host->base = devm_ioremap_resource(&pdev->dev, res_mem);
+ if (!host->base) {
+ dev_err(&pdev->dev, "Failed to ioremap %p\n", host->base);
+ return -EFAULT;
+ }
+
+ host->domain = irq_domain_add_linear(np, LP8X4X_NUM_IRQ_DEFAULT,
+ &lp8x4x_irq_domain_ops, host);
+ if (!host->domain) {
+ dev_err(&pdev->dev, "Failed to add IRQ domain\n");
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < LP8X4X_NUM_IRQ_DEFAULT; i++) {
+ err = irq_create_mapping(host->domain, i);
+ if (err < 0)
+ dev_err(&pdev->dev, "Failed to map IRQ %i\n", i);
+ }
+
+ /* Initialize chip registers */
+ iowrite8(0, host->base + CLRRISEINT);
+ iowrite8(0, host->base + ENRISEINT);
+ iowrite8(0, host->base + CLRFALLINT);
+ iowrite8(0, host->base + ENFALLINT);
+ iowrite8(0, host->base + CLRHILVINT);
+ iowrite8(0, host->base + ENHILVINT);
+ iowrite8(0, host->base + ENSYSINT);
+ iowrite8(0, host->base + SECOINT);
+
+ irq_set_handler_data(res_irq->start, host);
+ irq_set_chained_handler(res_irq->start, lp8x4x_irq_handler);
+
+ return 0;
+}
+
+static struct platform_driver lp8x4x_irq_driver = {
+ .probe = lp8x4x_irq_probe,
+ .driver = {
+ .name = "irq-lp8x4x",
+ .of_match_table = lp8x4x_irq_dt_ids,
+ },
+};
+
+static int __init lp8x4x_irq_init(void)
+{
+ return platform_driver_register(&lp8x4x_irq_driver);
+}
+postcore_initcall(lp8x4x_irq_init);
--
1.8.4.2
^ permalink raw reply related
* [PATCH v3 7/7] ARM: brcmstb: dts: add a reference DTS for Broadcom 7445
From: Arnd Bergmann @ 2014-01-15 13:10 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1389743333-16741-8-git-send-email-marc.ceeeee@gmail.com>
On Wednesday 15 January 2014, Marc Carino wrote:
> + gen-ctrl {
> + compatible = "brcm,brcmstb-gen-ctrl-v1";
> + reg = <0xf0404304 0x4
> + 0xf0404308 0x4
> + 0xf03e2578 0x4
> + 0xf03e2488 0x10
> + 0xf0452000 0x20>;
> + };
Sorry I didn't get back to you on this when we discussed the previous
version. I'm actually less happy with this DT representation than the
original. What I take from your description is that you have multiple
register ranges that basically combine more-or-less random registers
that belong into different Linux subsystems.
I think the best way to deal with this is to have the "syscon" driver
handle the multiplexing between the various drivers that need access
to the registers. It would look something like (taking the numbers
from your previous patch):
ahb {
ranges = <0 0xf0000000 0x1000000>; /* 16 MB remapped registers */
hif-cpubuictrl: syscon at 3e2400 {
compatible = "brcm,7445-cpubioctrl", "syscon";
reg = <0x3e2000, 0x1000>;
};
hif-continuation: syscon at 45200 {
compatible = "brcm,7445-hif-continuation", "syscon";
reg = <0x452000, 0x1000>;
};
sun-top-ctrl: ...
};
This lets the syscon driver find and map the three register areas.
Drivers that need access to the registers then do
reset {
compatible = "brcm,7445-reset-ctrl";
syscon = <&sun-top-ctrl 0x300 0x100>;
#reset-cells = <1>;
};
And then you can add a regular device driver to drivers/reset that provides
a device_reset() API to other drivers, or a system-reset function to be
registered as arm_pm_restart. This driver would use
syscon_regmap_lookup_by_phandle() to get access to a regmap pointer,
and then use either hardcoded offsets into the regmap, or get those
offsets from numbers in the devicetree, as provided in the example
above.
Arnd
^ permalink raw reply
* [linux-sunxi] [PATCH] pinctrl: sunxi: Honor GPIO output initial vaules
From: Chen-Yu Tsai @ 2014-01-15 13:10 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140115100241.GI3377@lukather>
Hi,
On Wed, Jan 15, 2014 at 6:02 PM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> Hi Chen-Yu,
>
> Nice catch :)
>
> On Wed, Jan 15, 2014 at 04:21:12PM +0800, Chen-Yu Tsai wrote:
>> Hi,
>>
>> On Wed, Jan 15, 2014 at 8:37 AM, Ma Haijun <mahaijuns@gmail.com> wrote:
>> > Hi,
>> >
>> > I think it is better to set the output value first to avoid glitch.
>>
>> If I understand the user manual correctly, setting the output value
>> before changing the pin to output function first will have no effect.
>
> I just tested it on my A31, and it is working as expected (the output
> value isn't output until the direction is changed).
>
> It would be great if you could test this as well on your device, and
> change it like suggested.
Tested on A20, works as you described. Output value is queued and changed
when pin function is changed to output.
I will rearrange the function calls and resend.
Cheers
ChenYu
^ permalink raw reply
* [PATCH] arch_timer: Move delay timer to drivers clocksource
From: Prashant Gaikwad @ 2014-01-15 13:07 UTC (permalink / raw)
To: linux-arm-kernel
Now arch timer is registerd using generic sched timer, delay
timer registration is the only part remaining in arch ports.
Move this part to drivers clocksource and remove arch timer
from arch ports.
Signed-off-by: Prashant Gaikwad <pgaikwad@nvidia.com>
---
arch/arm/include/asm/arch_timer.h | 1 -
arch/arm/kernel/Makefile | 1 -
arch/arm/kernel/arch_timer.c | 44 ----------------------------------
arch/arm64/include/asm/arch_timer.h | 5 ----
arch/arm64/include/asm/delay.h | 32 ++++++++++++++++++++++++
arch/arm64/include/asm/timex.h | 5 +--
arch/arm64/kernel/time.c | 9 -------
arch/arm64/lib/delay.c | 26 ++++++++++++++++++++
drivers/clocksource/arm_arch_timer.c | 12 ++++++++-
9 files changed, 71 insertions(+), 64 deletions(-)
delete mode 100644 arch/arm/kernel/arch_timer.c
create mode 100644 arch/arm64/include/asm/delay.h
diff --git a/arch/arm/include/asm/arch_timer.h b/arch/arm/include/asm/arch_timer.h
index 0704e0c..61ad692 100644
--- a/arch/arm/include/asm/arch_timer.h
+++ b/arch/arm/include/asm/arch_timer.h
@@ -10,7 +10,6 @@
#include <clocksource/arm_arch_timer.h>
#ifdef CONFIG_ARM_ARCH_TIMER
-int arch_timer_arch_init(void);
/*
* These register accessors are marked inline so the compiler can
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
index a30fc9b..6b51cf9 100644
--- a/arch/arm/kernel/Makefile
+++ b/arch/arm/kernel/Makefile
@@ -45,7 +45,6 @@ obj-$(CONFIG_SMP) += smp_tlb.o
endif
obj-$(CONFIG_HAVE_ARM_SCU) += smp_scu.o
obj-$(CONFIG_HAVE_ARM_TWD) += smp_twd.o
-obj-$(CONFIG_ARM_ARCH_TIMER) += arch_timer.o
obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o insn.o
obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o insn.o
obj-$(CONFIG_JUMP_LABEL) += jump_label.o insn.o patch.o
diff --git a/arch/arm/kernel/arch_timer.c b/arch/arm/kernel/arch_timer.c
deleted file mode 100644
index 1791f12..0000000
--- a/arch/arm/kernel/arch_timer.c
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * linux/arch/arm/kernel/arch_timer.c
- *
- * Copyright (C) 2011 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/init.h>
-#include <linux/types.h>
-#include <linux/errno.h>
-
-#include <asm/delay.h>
-
-#include <clocksource/arm_arch_timer.h>
-
-static unsigned long arch_timer_read_counter_long(void)
-{
- return arch_timer_read_counter();
-}
-
-static struct delay_timer arch_delay_timer;
-
-static void __init arch_timer_delay_timer_register(void)
-{
- /* Use the architected timer for the delay loop. */
- arch_delay_timer.read_current_timer = arch_timer_read_counter_long;
- arch_delay_timer.freq = arch_timer_get_rate();
- register_current_timer_delay(&arch_delay_timer);
-}
-
-int __init arch_timer_arch_init(void)
-{
- u32 arch_timer_rate = arch_timer_get_rate();
-
- if (arch_timer_rate == 0)
- return -ENXIO;
-
- arch_timer_delay_timer_register();
-
- return 0;
-}
diff --git a/arch/arm64/include/asm/arch_timer.h b/arch/arm64/include/asm/arch_timer.h
index 9400596..48e06bd 100644
--- a/arch/arm64/include/asm/arch_timer.h
+++ b/arch/arm64/include/asm/arch_timer.h
@@ -145,9 +145,4 @@ static inline u64 arch_counter_get_cntvct(void)
return cval;
}
-static inline int arch_timer_arch_init(void)
-{
- return 0;
-}
-
#endif
diff --git a/arch/arm64/include/asm/delay.h b/arch/arm64/include/asm/delay.h
new file mode 100644
index 0000000..ea90d99
--- /dev/null
+++ b/arch/arm64/include/asm/delay.h
@@ -0,0 +1,32 @@
+
+/*
+ * Copyright (c) 2014, NVIDIA Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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/licenses/>.
+ */
+
+#ifndef __ASM_ARM64_DELAY_H
+#define __ASM_ARM64_DELAY_H
+
+#include <asm-generic/delay.h>
+
+struct delay_timer {
+ unsigned long (*read_current_timer)(void);
+ unsigned long freq;
+};
+
+/* Delay-loop timer registration. */
+#define ARCH_HAS_READ_CURRENT_TIMER
+extern void register_current_timer_delay(const struct delay_timer *timer);
+
+#endif /* defined(_ARM64_DELAY_H) */
diff --git a/arch/arm64/include/asm/timex.h b/arch/arm64/include/asm/timex.h
index 81a076e..ca4bdfb 100644
--- a/arch/arm64/include/asm/timex.h
+++ b/arch/arm64/include/asm/timex.h
@@ -16,13 +16,12 @@
#ifndef __ASM_TIMEX_H
#define __ASM_TIMEX_H
-#include <asm/arch_timer.h>
-
/*
* Use the current timer as a cycle counter since this is what we use for
* the delay loop.
*/
-#define get_cycles() arch_counter_get_cntvct()
+typedef unsigned long cycles_t;
+#define get_cycles() ({ cycles_t c; read_current_timer(&c) ? 0 : c; })
#include <asm-generic/timex.h>
diff --git a/arch/arm64/kernel/time.c b/arch/arm64/kernel/time.c
index 29c39d5..213d1a3 100644
--- a/arch/arm64/kernel/time.c
+++ b/arch/arm64/kernel/time.c
@@ -63,14 +63,5 @@ EXPORT_SYMBOL(profile_pc);
void __init time_init(void)
{
- u32 arch_timer_rate;
-
clocksource_of_init();
-
- arch_timer_rate = arch_timer_get_rate();
- if (!arch_timer_rate)
- panic("Unable to initialise architected timer.\n");
-
- /* Calibrate the delay loop directly */
- lpj_fine = arch_timer_rate / HZ;
}
diff --git a/arch/arm64/lib/delay.c b/arch/arm64/lib/delay.c
index dad4ec9..cde0a28 100644
--- a/arch/arm64/lib/delay.c
+++ b/arch/arm64/lib/delay.c
@@ -24,6 +24,19 @@
#include <linux/module.h>
#include <linux/timex.h>
+static const struct delay_timer *delay_timer;
+static bool delay_calibrated;
+
+int read_current_timer(unsigned long *timer_val)
+{
+ if (!delay_timer)
+ return -ENXIO;
+
+ *timer_val = delay_timer->read_current_timer();
+ return 0;
+}
+EXPORT_SYMBOL(read_current_timer);
+
void __delay(unsigned long cycles)
{
cycles_t start = get_cycles();
@@ -53,3 +66,16 @@ void __ndelay(unsigned long nsecs)
__const_udelay(nsecs * 0x5UL); /* 2**32 / 1000000000 (rounded up) */
}
EXPORT_SYMBOL(__ndelay);
+
+void register_current_timer_delay(const struct delay_timer *timer)
+{
+ if (!delay_calibrated) {
+ pr_info("Switching to timer-based delay loop\n");
+ delay_timer = timer;
+ lpj_fine = timer->freq / HZ;
+
+ delay_calibrated = true;
+ } else {
+ pr_info("Ignoring duplicate/late registration of read_current_timer delay\n");
+ }
+}
diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
index 57e823c..8ee9918 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -422,6 +422,16 @@ struct timecounter *arch_timer_get_timecounter(void)
return &timecounter;
}
+static struct delay_timer arch_delay_timer;
+
+static void __init arch_delay_timer_register(void)
+{
+ /* Use the architected timer for the delay loop. */
+ arch_delay_timer.read_current_timer = arch_timer_read_counter();
+ arch_delay_timer.freq = arch_timer_rate;
+ register_current_timer_delay(&arch_delay_timer);
+}
+
static void __init arch_counter_register(unsigned type)
{
u64 start_count;
@@ -630,7 +640,7 @@ static void __init arch_timer_common_init(void)
arch_timer_banner(arch_timers_present);
arch_counter_register(arch_timers_present);
- arch_timer_arch_init();
+ arch_delay_timer_register();
}
static void __init arch_timer_init(struct device_node *np)
--
1.7.4.1
^ permalink raw reply related
* device-tree: at91: irq and gpios: problem while requesting a gpio used as an interrupt source.
From: Jean-Jacques Hiblot @ 2014-01-15 13:04 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140115123338.GC9558@ns203013.ovh.net>
2014/1/15 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>:
> On 12:05 Mon 13 Jan , Jean-Jacques Hiblot wrote:
>> Hi Boris,
>>
>> 2014/1/13 boris brezillon <b.brezillon@overkiz.com>:
>> > On 13/01/2014 11:29, Jean-Jacques Hiblot wrote:
>> >>
>> >> Hello Nicolas, Jean-Christophe,
>> >>
>> >> As I was trying to enable the touchscreen on the at91sam9261ek with
>> >> device-tree support, I ran into an issue. The touchscreen driver needs
>> >> to know the state of the pendown gpio and also needs it as an
>> >> interrupt source.
>> >>
>> >> The problem is that when a gpio is used as an interrupt, it's
>> >> requested by the pinctrl driver during the xlate stage, marking it
>> >> unavaliable for the other driver.
>> >> It looks like the at91 pinctrl driver is the only one to use
>> >> gpio_request() in the xlate stage. Maybe we should remove this:
>> >
>> >
>> > You should only request it as a GPIO and then use gpio_to_irq to get the
>> > related IRQ.
>> > Because what is done here, is to solve the case where only the irq
>> > is request, and in this specific case we need to request the pin as a
>> > GPIO.
>> >
>>
>> That's what I did first, and was about to submit the patch for the
>> touchscreen driver.
>> However it doesn't feel right. Being able to get the state of a gpio
>> that is also an interrupt seems very useful to me, not only for a
>> touchscreen controller.
>>
>> I understand why it's being done here. It's a matter of being sure
>> that the GPIO is an input and that it'll not be configured otherwise
>> latter.
>> But:
>> 1) I'm wondering why the atmel pinctrl is the only one to do that.
>
> because this the only to start to do it right
> I had a very long discussion woth LinusW and Grant the Gpio need to stop to
> use gpio_to_irq & co for irq.
How can you get the value of the gpio that is also an interrupt source then ?
Can you give a short example?
>
> I even send a proposition to do this work across the kernel t the CE-Linux for
> funding
>> 2) I believe that configuration of the direction can be done by
>> describing the GPIO in the DT. (pinctrl-at91.c line 592).
> No pinctrl is for pinmux ONLY not gpio direction & co
>
> Best Regards,
> J.
>
>> 3) If all the GPIOs are described in the DT with a proper pinmux
>> description, i believe the exclusion is also handled. It's probably
>> not the case today though.
>
>>
>> >
>> > Best Regards,
>> >
>> > Boris
>> >
>> >>
>> >> diff --git a/drivers/pinctrl/pinctrl-at91.c
>> >> b/drivers/pinctrl/pinctrl-at91.c
>> >> index a7549c4..cf91a35 100644
>> >> --- a/drivers/pinctrl/pinctrl-at91.c
>> >> +++ b/drivers/pinctrl/pinctrl-at91.c
>> >> @@ -1463,14 +1463,6 @@ static int at91_gpio_irq_domain_xlate(struct
>> >> irq_domain *d,
>> >> *out_hwirq = intspec[0];
>> >> *out_type = intspec[1] & IRQ_TYPE_SENSE_MASK;
>> >>
>> >> - ret = gpio_request(pin, ctrlr->full_name);
>> >> - if (ret)
>> >> - return ret;
>> >> -
>> >> - ret = gpio_direction_input(pin);
>> >> - if (ret)
>> >> - return ret;
>> >> -
>> >> return 0;
>> >> }
>> >>
>> >> Jean-Jacques
>> >
>> >
>>
>> _______________________________________________
>> linux-arm-kernel mailing list
>> linux-arm-kernel at lists.infradead.org
>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [PATCH] ARM: S3C[24|64]xx: move includes back under <mach/> scope
From: Linus Walleij @ 2014-01-15 12:58 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <6144980.CZru2D3yJB@wuerfel>
On Wed, Jan 15, 2014 at 10:43 AM, Arnd Bergmann <arnd@arndb.de> wrote:
> On Wednesday 15 January 2014 14:41:01 Tushar Behera wrote:
>> > diff --git a/arch/arm/plat-samsung/pm-gpio.c b/arch/arm/plat-samsung/pm-gpio.c
>> > index c4efa1c2a5d1..a9f7a37c4173 100644
>> > --- a/arch/arm/plat-samsung/pm-gpio.c
>> > +++ b/arch/arm/plat-samsung/pm-gpio.c
>> > @@ -19,12 +19,7 @@
>> > #include <linux/io.h>
>> > #include <linux/gpio.h>
>> >
>> > -#ifdef CONFIG_ARCH_S3C24XX
>> > -#include <linux/platform_data/gpio-samsung-s3c24xx.h>
>> > -#endif
>> > -#ifdef CONFIG_ARCH_S3C64XX
>> > -#include <linux/platform_data/gpio-samsung-s3c64xx.h>
>> > -#endif
>> > +#include <mach/gpio-samsung.h>
>>
>> This inclusion should be protected by a check for CONFIG_ARCH_S3C24XX
>> || CONFIG_ARCH_S3C64XX. Currently generating build errors for
>> s5p64x0_defconfig, s5pc100_defconfig and s5pv210_defconfig on
>> next-20140115.
>>
>
> I noticed the same problem, but I think a better solution would
> be to do the same change for s5p that Linus has done for s3c,
> which is to move the nonstandard contents of mach/gpio.h to
> mach/gpio-samsung.h.
When I look at it, the issue also exist in e.g.
drivers/gpio/gpio-samsung.c which can be compiled
(like for allyesconfig) when PLAT_SAMSUNG is set.
And it is also set to y for ARCH_EXYNOS... which
doesn't have any custom GPIO header. So this would
involve something like creating an empty
<mach/gpio-samsung.h> for Exynos which doesn't
seem like the right thing to do.
So I'm sticking with the #ifdef patch for now as it
seems to be the lesser evil :-/
Yours,
Linus Walleij
^ permalink raw reply
* [PATCH] ARM: S3C[24|64]xx: move includes back under <mach/> scope
From: Linus Walleij @ 2014-01-15 12:51 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <6144980.CZru2D3yJB@wuerfel>
On Wed, Jan 15, 2014 at 10:43 AM, Arnd Bergmann <arnd@arndb.de> wrote:
> On Wednesday 15 January 2014 14:41:01 Tushar Behera wrote:
>>
>> This inclusion should be protected by a check for CONFIG_ARCH_S3C24XX
>> || CONFIG_ARCH_S3C64XX. Currently generating build errors for
>> s5p64x0_defconfig, s5pc100_defconfig and s5pv210_defconfig on
>> next-20140115.
>
> I noticed the same problem, but I think a better solution would
> be to do the same change for s5p that Linus has done for s3c,
> which is to move the nonstandard contents of mach/gpio.h to
> mach/gpio-samsung.h.
Hm I just applied a fixup from Sachin adding #ifdefs back in
but maybe I should try to fix it up like that instead. Just a minute...
Yours,
Linus Walleij
^ permalink raw reply
* [PATCH v3 0/3] Fix SATA disk hotplug for Armada 370/XP SoCs
From: Tejun Heo @ 2014-01-15 12:44 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1389726281-8731-1-git-send-email-simon.guinot@sequanux.org>
On Tue, Jan 14, 2014 at 08:04:38PM +0100, Simon Guinot wrote:
> Hello,
>
> This patch series fixes a SATA disk hotplug issue for the Armada 370/XP
> SoCs: once a disk is removed from a SATA port, then the re-plug events
> are not detected by the sata_mv driver.
>
> As this hotplug issue have been emphasized by 9ae6f740b49f
> "arm: mach-mvebu: add support for Armada 370 and Armada XP with DT",
> then this patches should be applied to the -stable kernels 3.6 and
> onwards.
Applied to libata/for-3.14.
Thanks.
--
tejun
^ permalink raw reply
* [RFC PATCH 1/1] of/irq: create interrupts-extended-2 property
From: Jean-Christophe PLAGNIOL-VILLARD @ 2014-01-15 12:40 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140115121750.GE25824@e106331-lin.cambridge.arm.com>
On 12:17 Wed 15 Jan , Mark Rutland wrote:
> On Wed, Jan 15, 2014 at 11:47:25AM +0000, Jean-Christophe PLAGNIOL-VILLARD wrote:
> > The new interrupts-extended property, which reuses the phandle+arguments
> > pattern used by GPIOs and other core bindings, still have some issue.
> >
> > If an SoC have already specifiy interrupt and a board want to add specific
> > interrupt such as GPIO (which can be optionnal) be need to re-define
> > interrupts-extended. So allow to have an optionnale interrupts-extended-2
> > property.
> >
>
> NAK.
>
> This is a hack that works around a dts organisation issue. This is _not_
> a binding or parsing issue.
So the DT is stupid. Yes w have board and SoC information
so we do not want to duplicate them. Having a way to descript SoC vs board
specific information need to be provided.
>
> Properties can be overridden - just describe all of the interrupts in
> the final dts file.
this is wrong, which mean you duplicate informaation and duplicate bug and
fixes
>
> > Today the problem is ofen solve by defining a gpio-xxx property and then do a gpio_to_irq
> > in the C code. *Which is wrong!!*. We need to describe the IRQ.
> >
> > Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
> > Cc: Grant Likely <grant.likely@linaro.org>
> > Cc: Rob Herring <rob.herring@calxeda.com>
> > ---
> >
> > We have the same issue on pinctrl
> > .../devicetree/bindings/interrupt-controller/interrupts.txt | 4 ++++
> > drivers/of/irq.c | 10 ++++++++--
> > 2 files changed, 12 insertions(+), 2 deletions(-)
> >
> > diff --git a/Documentation/devicetree/bindings/interrupt-controller/interrupts.txt b/Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
> > index 1486497..5d559fd 100644
> > --- a/Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
> > +++ b/Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
> > @@ -25,8 +25,12 @@ to reference multiple interrupt parents. Each entry in this property contains
> > both the parent phandle and the interrupt specifier. "interrupts-extended"
> > should only be used when a device has multiple interrupt parents.
> >
> > +The "interrupts-extended-2" allow to extend at board level node interrupt without
> > +having to re-define the SoC interrupts.
> > +
> > Example:
> > interrupts-extended = <&intc1 5 1>, <&intc2 1 0>;
> > + interrupts-extended-2 = <&intc1 6 1>
> >
> > A device node may contain either "interrupts" or "interrupts-extended", but not
> > both. If both properties are present, then the operating system should log an
> > diff --git a/drivers/of/irq.c b/drivers/of/irq.c
> > index 786b0b4..bc36710 100644
> > --- a/drivers/of/irq.c
> > +++ b/drivers/of/irq.c
> > @@ -307,8 +307,14 @@ int of_irq_parse_one(struct device_node *device, int index, struct of_phandle_ar
> > /* Try the new-style interrupts-extended */
> > res = of_parse_phandle_with_args(device, "interrupts-extended",
> > "#interrupt-cells", index, out_irq);
> > - if (res)
> > - return -EINVAL;
> > + if (res) {
> > + /* Try the new-style interrupts-extended-2 */
> > + res = of_parse_phandle_with_args(device, "interrupts-extended-2",
> > + "#interrupt-cells", index, out_irq);
>
> This also breaks error reporting.
>
> What if you have an interrupt in the middle of interrupts-extended which
> fails to parse? This will jump to the interrupts-extended-2 property and
> grab the wrong interrupt rather than propagating the error.
>
> Thanks,
> Mark.
^ permalink raw reply
* [RFC PATCH V2 1/4] pci: APM X-Gene PCIe controller driver
From: Arnd Bergmann @ 2014-01-15 12:39 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1389742458-7693-2-git-send-email-tinamdar@apm.com>
On Wednesday 15 January 2014, Tanmay Inamdar wrote:
> This patch adds the AppliedMicro X-Gene SOC PCIe controller driver.
> X-Gene PCIe controller supports maxmum upto 8 lanes and GEN3 speed.
> X-Gene has maximum 5 PCIe ports supported.
>
> Signed-off-by: Tanmay Inamdar <tinamdar@apm.com>
This already looks much better than the first version, but I have a more
comments. Most importantly, it would help to know how the root ports
are structured. Is this a standard root complex and multiple ports,
multiple root complexes with one port each, or a nonstandard organization
that is a mix of those two models?
> +
> +/* When the address bit [17:16] is 2'b01, the Configuration access will be
> + * treated as Type 1 and it will be forwarded to external PCIe device.
> + */
> +static void __iomem *xgene_pcie_get_cfg_base(struct pci_bus *bus)
> +{
> + struct xgene_pcie_port *port = xgene_pcie_bus_to_port(bus);
> + u64 addr = (u64)port->cfg_base;
> +
> + if (bus->number >= (port->first_busno + 1))
> + addr |= AXI_EP_CFG_ACCESS;
> +
> + return (void *)addr;
> +}
Wrong type, it should be 'void __iomem *'. Also you can't assume that
bit operations work on virtual __iomem addresses, so it should be better
to just add a constant integer to the pointer, which is a valid
operation.
I also wonder why you need to do this at all. If there isn't a global
config space for all ports, but rather a separate type0/type1 config
cycle based on the bus number, I see that as an indication that the
ports are in fact separate domains and should each start with bus 0.
> +static void xgene_pcie_setup_lanes(struct xgene_pcie_port *port)
> +{
> + void *csr_base = port->csr_base;
> + u32 val;
> +
> + val = readl(csr_base + BRIDGE_8G_CFG_8);
> + val = eq_pre_cursor_lane0_set(val, 0x7);
> + val = eq_pre_cursor_lane1_set(val, 0x7);
> + writel(val, csr_base + BRIDGE_8G_CFG_8);
> +
> + val = readl(csr_base + BRIDGE_8G_CFG_9);
> + val = eq_pre_cursor_lane0_set(val, 0x7);
> + val = eq_pre_cursor_lane1_set(val, 0x7);
> + writel(val, csr_base + BRIDGE_8G_CFG_9);
> +
> + val = readl(csr_base + BRIDGE_8G_CFG_10);
> + val = eq_pre_cursor_lane0_set(val, 0x7);
> + val = eq_pre_cursor_lane1_set(val, 0x7);
> + writel(val, csr_base + BRIDGE_8G_CFG_10);
> +
> + val = readl(csr_base + BRIDGE_8G_CFG_11);
> + val = eq_pre_cursor_lane0_set(val, 0x7);
> + val = eq_pre_cursor_lane1_set(val, 0x7);
> + writel(val, csr_base + BRIDGE_8G_CFG_11);
> +
> + val = readl(csr_base + BRIDGE_8G_CFG_4);
> + val = (val & ~0x30) | (1 << 4);
> + writel(val, csr_base + BRIDGE_8G_CFG_4);
> +}
Please document what you are actually setting here. If the configuration
of the lanes is always the same, why do you have to set it here. If not,
why do you set constant values?
> +static void xgene_pcie_setup_link(struct xgene_pcie_port *port)
> +{
> + void *csr_base = port->csr_base;
> + u32 val;
> +
> + val = readl(csr_base + BRIDGE_CFG_14);
> + val |= DIRECT_TO_8GTS_MASK;
> + val |= SUPPORT_5GTS_MASK;
> + val |= SUPPORT_8GTS_MASK;
> + val |= DIRECT_TO_5GTS_MASK;
> + writel(val, csr_base + BRIDGE_CFG_14);
> +
> + val = readl(csr_base + BRIDGE_CFG_14);
> + val &= ~ADVT_INFINITE_CREDITS;
> + writel(val, csr_base + BRIDGE_CFG_14);
> +
> + val = readl(csr_base + BRIDGE_8G_CFG_0);
> + val |= (val & ~0xf) | 7;
> + val |= (val & ~0xf00) | ((7 << 8) & 0xf00);
> + writel(val, csr_base + BRIDGE_8G_CFG_0);
> +
> + val = readl(csr_base + BRIDGE_8G_CFG_0);
> + val |= DWNSTRM_EQ_SKP_PHS_2_3;
> + writel(val, csr_base + BRIDGE_8G_CFG_0);
> +}
Same here.
> +static void xgene_pcie_program_core(void *csr_base)
> +{
> + u32 val;
> +
> + val = readl(csr_base + BRIDGE_CFG_0);
> + val |= AER_OPTIONAL_ERROR_EN;
> + writel(val, csr_base + BRIDGE_CFG_0);
> + writel(0x0, csr_base + INTXSTATUSMASK);
> + val = readl(csr_base + BRIDGE_CTRL_1);
> + val = (val & ~0xffff) | XGENE_PCIE_DEV_CTRL;
> + writel(val, csr_base + BRIDGE_CTRL_1);
> +}
'program_core'?
> +static void xgene_pcie_poll_linkup(struct xgene_pcie_port *port, u32 *lanes)
> +{
> + void *csr_base = port->csr_base;
> + u32 val32;
> + u64 start_time, time;
> +
> + /*
> + * A component enters the LTSSM Detect state within
> + * 20ms of the end of fundamental core reset.
> + */
> + msleep(XGENE_LTSSM_DETECT_WAIT);
> + port->link_up = 0;
> + start_time = jiffies;
> + do {
> + val32 = readl(csr_base + PCIECORE_CTLANDSTATUS);
> + if (val32 & LINK_UP_MASK) {
> + port->link_up = 1;
> + port->link_speed = PIPE_PHY_RATE_RD(val32);
> + val32 = readl(csr_base + BRIDGE_STATUS_0);
> + *lanes = val32 >> 26;
> + }
> + time = jiffies_to_msecs(jiffies - start_time);
> + } while ((!port->link_up) || (time <= XGENE_LTSSM_L0_WAIT));
> +}
Maybe another msleep() in the loop? It seems weird to first do an
unconditional sleep but then busy-wait for the result.
> +static void xgene_pcie_setup_primary_bus(struct xgene_pcie_port *port,
> + u32 first_busno, u32 last_busno)
> +{
> + u32 val;
> + void *cfg_addr = port->cfg_base;
> +
> + val = readl(cfg_addr + PCI_PRIMARY_BUS);
> + val &= ~PCI_PRIMARY_BUS_MASK;
> + val |= (last_busno << 16) | ((first_busno + 1) << 8) | (first_busno);
> + writel(val, cfg_addr + PCI_PRIMARY_BUS);
> +}
Please explain what you are doing here. As mentioned above, I would expect
that each domain has visibility of all 255 buses. You shouldn't need any hacks
where you try to artificially squeeze the ports into a single domain when
they are separate in hardware.
> +/*
> + * read configuration values from DTS
> + */
> +static int xgene_pcie_read_dts_config(struct xgene_pcie_port *port)
The comment and function name don't seem to match what the function
does. The main purpose of this function seems to be to ioremap
the resources, which have nothing to with configuration.
> +{
> + struct device_node *np = port->node;
> + struct resource csr_res;
> + struct resource cfg_res;
> +
> + /* Get CSR space registers address */
> + if (of_address_to_resource(np, 0, &csr_res))
> + return -EINVAL;
> +
> + port->csr_base = devm_ioremap_nocache(port->dev, csr_res.start,
> + resource_size(&csr_res));
You can also use platform_get_resource() to access the resource
that is already there, rather than creating another one.
> +static void xgene_pcie_setup_ob_reg(struct xgene_pcie_port *port,
> + u32 addr, u32 restype)
> +{
> + struct resource *res = NULL;
> + void *base = port->csr_base + addr;
> + resource_size_t size;
> + u64 cpu_addr = 0;
> + u64 pci_addr = 0;
> + u64 mask = 0;
> + u32 min_size = 0;
A general note: don't initialize local variables to a bogus valus (e.g. 0)
in their declaration. It prevents the compiler from warning about
incorrect uses.
> + u32 flag = EN_REG;
This one on the other hand is ok, because you are actually going to
use that value.
> + switch (restype) {
> + case IORESOURCE_MEM:
> + res = &port->mem.res;
> + pci_addr = port->mem.pci_addr;
> + min_size = SZ_128M;
> + break;
> + case IORESOURCE_IO:
> + res = &port->io.res;
> + pci_addr = port->io.pci_addr;
> + min_size = 128;
> + flag |= OB_LO_IO;
> + break;
> + }
I assume this works ok, but seems wrong in one detail: If the resource
is marked IORESOURCE_IO, res->start is supposed to be in I/O space, not
in memory space, which would make it the wrong number to program
into the hardware registers.
> +static int xgene_pcie_parse_map_ranges(struct xgene_pcie_port *port)
> +{
> + struct device_node *np = port->node;
> + struct of_pci_range range;
> + struct of_pci_range_parser parser;
> + struct device *dev = port->dev;
> +
> + if (of_pci_range_parser_init(&parser, np)) {
> + dev_err(dev, "missing ranges property\n");
> + return -EINVAL;
> + }
> +
> + /* Get the I/O, memory, config ranges from DT */
The comment needs updating now that you don't read config space here any more.
> +/* X-Gene PCIe support maximum 3 inbound memory regions
> + * This function helps to select a region based on size of region
> + */
> +static int xgene_pcie_select_ib_reg(u64 size)
> +{
> + static u8 ib_reg_mask;
> +
> + if ((size > 4) && (size < SZ_16M) && !(ib_reg_mask & (1 << 1))) {
> + ib_reg_mask |= (1 << 1);
> + return 1;
> + }
> +
> + if ((size > SZ_1K) && (size < SZ_1T) && !(ib_reg_mask & (1 << 0))) {
> + ib_reg_mask |= (1 << 0);
> + return 0;
> + }
> +
> + if ((size > SZ_1M) && (size < SZ_1T) && !(ib_reg_mask & (1 << 2))) {
> + ib_reg_mask |= (1 << 2);
> + return 2;
> + }
> + return -EINVAL;
> +}
Shouldn't the ib_reg_mask variable be per host bridge? Static variables
are dangerous if you ever get multiple instances of the hardware in one
system.
> +static int xgene_pcie_parse_map_dma_ranges(struct xgene_pcie_port *port)
> +{
> + struct device_node *np = port->node;
> + struct of_pci_range range;
> + struct of_pci_range_parser parser;
> + struct device *dev = port->dev;
> + int region;
> +
> + if (pci_dma_range_parser_init(&parser, np)) {
> + dev_err(dev, "missing dma-ranges property\n");
> + return -EINVAL;
> + }
> +
> + /* Get the dma-ranges from DT */
> + for_each_of_pci_range(&parser, &range) {
> + u64 restype = range.flags & IORESOURCE_TYPE_BITS;
> + u64 end = range.cpu_addr + range.size - 1;
> + dev_dbg(port->dev, "0x%08x 0x%016llx..0x%016llx -> 0x%016llx\n",
> + range.flags, range.cpu_addr, end, range.pci_addr);
> + region = xgene_pcie_select_ib_reg(range.size);
> + if (region == -EINVAL) {
> + dev_warn(port->dev, "invalid pcie dma-range config\n");
> + continue;
> + }
> + xgene_pcie_setup_ib_reg(port, &range, restype, region);
> + }
> + return 0;
> +}
I guess is could even be a local variable in this function, which you pass
by reference.
> +
> +static int xgene_pcie_setup(int nr, struct pci_sys_data *sys)
> +{
> + struct xgene_pcie_port *pp = xgene_pcie_sys_to_port(sys);
> +
> + if (pp == NULL)
> + return 0;
> +
> + sys->mem_offset = pp->mem.res.start - pp->mem.pci_addr;
> + pci_add_resource_offset(&sys->resources, &pp->mem.res,
> + sys->mem_offset);
> + return 1;
> +}
Please follow the regular error handling conventions, which are to
pass a negative errno value on error and zero on success.
Also, what would be a reason for the port to be zero here? If
it's something that can't happen in practice, don't try to handle
it gracefully. You can use BUG_ON() for fatal conditions that
are supposed to be impossible to reach.
> +static struct pci_bus __init *xgene_pcie_scan_bus(int nr,
> + struct pci_sys_data *sys)
> +{
> + struct xgene_pcie_port *pp = xgene_pcie_sys_to_port(sys);
> +
> + pp->first_busno = sys->busnr;
> + xgene_pcie_setup_primary_bus(pp, sys->busnr, 0xff);
> + return pci_scan_root_bus(NULL, sys->busnr, &xgene_pcie_ops,
> + sys, &sys->resources);
> +}
You have a number of helper functions that don't seem to gain
much at all. Just move the call to pci_scan_root_bus() into
xgene_pcie_setup_primary_bus() here, and use that as the .scan
callback.
> + if (!port->link_up)
> + dev_info(port->dev, "(rc) link down\n");
> + else
> + dev_info(port->dev, "(rc) x%d gen-%d link up\n",
> + lanes, port->link_speed + 1);
> +#ifdef CONFIG_PCI_DOMAINS
> + xgene_pcie_hw.domain++;
> +#endif
> + xgene_pcie_hw.private_data[index++] = port;
> + platform_set_drvdata(pdev, port);
> + return 0;
> +}
Do you have multiple domains or not? I don't see how it can work if you
make the domain setup conditional on a kernel configuration option.
If you in fact have multiple domains, make sure in Kconfig that
CONFIG_PCI_DOMAINS is enabled. Otherwise don't mess with the domain
number...
> +static const struct of_device_id xgene_pcie_match_table[] __initconst = {
> + {.compatible = "apm,xgene-pcie",},
> + {},
> +};
Another general note: Your "compatible" strings are rather unspecific.
Do you have a version number for this IP block? I suppose that it's related
to one that has been used in other chips before, or will be used in future
chips, if it's not actually licensed from some other company.
> +static int __init xgene_pcie_init(void)
> +{
> + void *private;
> + int ret;
> +
> + pr_info("X-Gene: PCIe driver\n");
> +
> + /* allocate private data to keep xgene_pcie_port information */
> + private = kzalloc((XGENE_PCIE_MAX_PORTS * sizeof(void *)), GFP_KERNEL);
This should not be done unconditionally: There is no point in printing
a message or allocating memory if you don't actually run on a system
with this device.
> + if (private == NULL)
> + return -ENOMEM;
Style: if you are testing for an object, just write 'if (private)' or
'if (!private)', but don't compare against NULL.
> + xgene_pcie_hw.private_data = private;
> + ret = platform_driver_probe(&xgene_pcie_driver,
> + xgene_pcie_probe_bridge);
> + if (ret)
> + return ret;
> + pci_common_init(&xgene_pcie_hw);
> + return 0;
This seems wrong: You should not use platform_driver_probe() because
that has issues with deferred probing.
Arnd
^ permalink raw reply
* [PATCHv9 1/4] clk: socfpga: Add a clk-phase property to the "altr, socfpga-gate-clk"
From: Dinh Nguyen @ 2014-01-15 12:36 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <52CF6D67.1000803@samsung.com>
Hi Mike,
On 1/9/14 9:47 PM, Jaehoon Chung wrote:
> Acked-by: Jaehoon Chung <jh80.chung@samsung.com>
>
> On 01/10/2014 06:31 AM, dinguyen at altera.com wrote:
>> From: Dinh Nguyen <dinguyen@altera.com>
>>
>> The clk-phase property is used to represent the 2 clock phase values that is
>> needed for the SD/MMC driver. Add a prepare function to the clk_ops, that will
>> use the syscon driver to set sdmmc_clk's phase shift that is located in the
>> system manager.
>>
>> Signed-off-by: Dinh Nguyen <dinguyen@altera.com>
>> Acked-by: Zhangfei Gao <zhangfei.gao@linaro.org>
>> ---
>> v9: none
>> v8: Use degrees in the clk-phase binding property
>> v7: Add dts property to represent the clk phase of the sdmmc_clk. Add a
>> prepare function to the gate clk that will toggle clock phase setting.
>> Remove the "altr,socfpga-sdmmc-sdr-clk" clock type.
>> v6: Add a new clock type "altr,socfpga-sdmmc-sdr-clk" that will be used to
>> set the phase shift settings.
>> v5: Use the "snps,dw-mshc" binding
>> v4: Use the sdmmc_clk prepare function to set the phase shift settings
>> v3: Not use the syscon driver because as of 3.13-rc1, the syscon driver is
>> loaded after the clock driver.
>> v2: Use the syscon driver
>> ---
>> .../devicetree/bindings/clock/altr_socfpga.txt | 5 ++
>> arch/arm/boot/dts/socfpga.dtsi | 1 +
>> drivers/clk/socfpga/clk-gate.c | 68 ++++++++++++++++++++
>> 3 files changed, 74 insertions(+)
>>
>> diff --git a/Documentation/devicetree/bindings/clock/altr_socfpga.txt b/Documentation/devicetree/bindings/clock/altr_socfpga.txt
>> index 0045433..5dfd145 100644
>> --- a/Documentation/devicetree/bindings/clock/altr_socfpga.txt
>> +++ b/Documentation/devicetree/bindings/clock/altr_socfpga.txt
>> @@ -23,3 +23,8 @@ Optional properties:
>> and the bit index.
>> - div-reg : For "socfpga-gate-clk", div-reg contains the divider register, bit shift,
>> and width.
>> +- clk-phase : For the sdmmc_clk, contains the value of the clock phase that controls
>> + the SDMMC CIU clock. The first value is the clk_sample(smpsel), and the second
>> + value is the cclk_in_drv(drvsel). The clk-phase is used to enable the correct
>> + hold/delay times that is needed for the SD/MMC CIU clock. The values of both
>> + can be 0-315 degrees, in 45 degree increments.
>> diff --git a/arch/arm/boot/dts/socfpga.dtsi b/arch/arm/boot/dts/socfpga.dtsi
>> index f936476..e776512 100644
>> --- a/arch/arm/boot/dts/socfpga.dtsi
>> +++ b/arch/arm/boot/dts/socfpga.dtsi
>> @@ -413,6 +413,7 @@
>> compatible = "altr,socfpga-gate-clk";
>> clocks = <&f2s_periph_ref_clk>, <&main_nand_sdmmc_clk>, <&per_nand_mmc_clk>;
>> clk-gate = <0xa0 8>;
>> + clk-phase = <0 135>;
>> };
>>
>> nand_x_clk: nand_x_clk {
>> diff --git a/drivers/clk/socfpga/clk-gate.c b/drivers/clk/socfpga/clk-gate.c
>> index 4efcf4e..501d513 100644
>> --- a/drivers/clk/socfpga/clk-gate.c
>> +++ b/drivers/clk/socfpga/clk-gate.c
>> @@ -19,7 +19,9 @@
>> #include <linux/clkdev.h>
>> #include <linux/clk-provider.h>
>> #include <linux/io.h>
>> +#include <linux/mfd/syscon.h>
>> #include <linux/of.h>
>> +#include <linux/regmap.h>
>>
>> #include "clk.h"
>>
>> @@ -35,6 +37,11 @@
>>
>> #define to_socfpga_gate_clk(p) container_of(p, struct socfpga_gate_clk, hw.hw)
>>
>> +/* SDMMC Group for System Manager defines */
>> +#define SYSMGR_SDMMCGRP_CTRL_OFFSET 0x108
>> +#define SYSMGR_SDMMC_CTRL_SET(smplsel, drvsel) \
>> + ((((smplsel) & 0x7) << 3) | (((drvsel) & 0x7) << 0))
>> +
>> static u8 socfpga_clk_get_parent(struct clk_hw *hwclk)
>> {
>> u32 l4_src;
>> @@ -115,7 +122,61 @@ static unsigned long socfpga_clk_recalc_rate(struct clk_hw *hwclk,
>> return parent_rate / div;
>> }
>>
>> +static int socfpga_clk_prepare(struct clk_hw *hwclk)
>> +{
>> + struct socfpga_gate_clk *socfpgaclk = to_socfpga_gate_clk(hwclk);
>> + struct regmap *sys_mgr_base_addr;
>> + int i;
>> + u32 hs_timing;
>> + u32 clk_phase[2];
>> +
>> + if (socfpgaclk->clk_phase[0] || socfpgaclk->clk_phase[1]) {
>> + sys_mgr_base_addr = syscon_regmap_lookup_by_compatible("altr,sys-mgr");
>> + if (IS_ERR(sys_mgr_base_addr)) {
>> + pr_err("%s: failed to find altr,sys-mgr regmap!\n", __func__);
>> + return -EINVAL;
>> + }
>> +
>> + for (i = 0; i < 2; i++) {
>> + switch (socfpgaclk->clk_phase[i]) {
>> + case 0:
>> + clk_phase[i] = 0;
>> + break;
>> + case 45:
>> + clk_phase[i] = 1;
>> + break;
>> + case 90:
>> + clk_phase[i] = 2;
>> + break;
>> + case 135:
>> + clk_phase[i] = 3;
>> + break;
>> + case 180:
>> + clk_phase[i] = 4;
>> + break;
>> + case 225:
>> + clk_phase[i] = 5;
>> + break;
>> + case 270:
>> + clk_phase[i] = 6;
>> + break;
>> + case 315:
>> + clk_phase[i] = 7;
>> + break;
>> + default:
>> + clk_phase[i] = 0;
>> + break;
>> + }
>> + }
>> + hs_timing = SYSMGR_SDMMC_CTRL_SET(clk_phase[0], clk_phase[1]);
>> + regmap_write(sys_mgr_base_addr, SYSMGR_SDMMCGRP_CTRL_OFFSET,
>> + hs_timing);
>> + }
>> + return 0;
>> +}
>> +
>> static struct clk_ops gateclk_ops = {
>> + .prepare = socfpga_clk_prepare,
>> .recalc_rate = socfpga_clk_recalc_rate,
>> .get_parent = socfpga_clk_get_parent,
>> .set_parent = socfpga_clk_set_parent,
>> @@ -126,6 +187,7 @@ static void __init __socfpga_gate_init(struct device_node *node,
>> {
>> u32 clk_gate[2];
>> u32 div_reg[3];
>> + u32 clk_phase[2];
>> u32 fixed_div;
>> struct clk *clk;
>> struct socfpga_gate_clk *socfpga_clk;
>> @@ -166,6 +228,12 @@ static void __init __socfpga_gate_init(struct device_node *node,
>> socfpga_clk->div_reg = 0;
>> }
>>
>> + rc = of_property_read_u32_array(node, "clk-phase", clk_phase, 2);
>> + if (!rc) {
>> + socfpga_clk->clk_phase[0] = clk_phase[0];
>> + socfpga_clk->clk_phase[1] = clk_phase[1];
>> + }
>> +
>> of_property_read_string(node, "clock-output-names", &clk_name);
>>
>> init.name = clk_name;
>>
Can you apply this to your clk tree?
Thanks,
Dinh
^ permalink raw reply
* device-tree: at91: irq and gpios: problem while requesting a gpio used as an interrupt source.
From: Jean-Christophe PLAGNIOL-VILLARD @ 2014-01-15 12:33 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CACh+v5OHtPXrUWQE82qsj7ajSVHFRnHTs7e1s4EUFQi7oxcgfA@mail.gmail.com>
On 12:05 Mon 13 Jan , Jean-Jacques Hiblot wrote:
> Hi Boris,
>
> 2014/1/13 boris brezillon <b.brezillon@overkiz.com>:
> > On 13/01/2014 11:29, Jean-Jacques Hiblot wrote:
> >>
> >> Hello Nicolas, Jean-Christophe,
> >>
> >> As I was trying to enable the touchscreen on the at91sam9261ek with
> >> device-tree support, I ran into an issue. The touchscreen driver needs
> >> to know the state of the pendown gpio and also needs it as an
> >> interrupt source.
> >>
> >> The problem is that when a gpio is used as an interrupt, it's
> >> requested by the pinctrl driver during the xlate stage, marking it
> >> unavaliable for the other driver.
> >> It looks like the at91 pinctrl driver is the only one to use
> >> gpio_request() in the xlate stage. Maybe we should remove this:
> >
> >
> > You should only request it as a GPIO and then use gpio_to_irq to get the
> > related IRQ.
> > Because what is done here, is to solve the case where only the irq
> > is request, and in this specific case we need to request the pin as a
> > GPIO.
> >
>
> That's what I did first, and was about to submit the patch for the
> touchscreen driver.
> However it doesn't feel right. Being able to get the state of a gpio
> that is also an interrupt seems very useful to me, not only for a
> touchscreen controller.
>
> I understand why it's being done here. It's a matter of being sure
> that the GPIO is an input and that it'll not be configured otherwise
> latter.
> But:
> 1) I'm wondering why the atmel pinctrl is the only one to do that.
because this the only to start to do it right
I had a very long discussion woth LinusW and Grant the Gpio need to stop to
use gpio_to_irq & co for irq.
I even send a proposition to do this work across the kernel t the CE-Linux for
funding
> 2) I believe that configuration of the direction can be done by
> describing the GPIO in the DT. (pinctrl-at91.c line 592).
No pinctrl is for pinmux ONLY not gpio direction & co
Best Regards,
J.
> 3) If all the GPIOs are described in the DT with a proper pinmux
> description, i believe the exclusion is also handled. It's probably
> not the case today though.
>
> >
> > Best Regards,
> >
> > Boris
> >
> >>
> >> diff --git a/drivers/pinctrl/pinctrl-at91.c
> >> b/drivers/pinctrl/pinctrl-at91.c
> >> index a7549c4..cf91a35 100644
> >> --- a/drivers/pinctrl/pinctrl-at91.c
> >> +++ b/drivers/pinctrl/pinctrl-at91.c
> >> @@ -1463,14 +1463,6 @@ static int at91_gpio_irq_domain_xlate(struct
> >> irq_domain *d,
> >> *out_hwirq = intspec[0];
> >> *out_type = intspec[1] & IRQ_TYPE_SENSE_MASK;
> >>
> >> - ret = gpio_request(pin, ctrlr->full_name);
> >> - if (ret)
> >> - return ret;
> >> -
> >> - ret = gpio_direction_input(pin);
> >> - if (ret)
> >> - return ret;
> >> -
> >> return 0;
> >> }
> >>
> >> Jean-Jacques
> >
> >
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [PATCH] mmc: dw_mmc: fix dw_mci_get_cd
From: Seungwon Jeon @ 2014-01-15 12:26 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <52D67A9B.4090607@linaro.org>
On Wed, January 15, 2014, Zhangfei Gao wrote:
> On 01/15/2014 07:58 PM, Seungwon Jeon wrote:
> > On Wed, January 15, 2014, Zhangfei Gao wrote:
> >> Introduced from commit bf626e5550f24aec24975a0e85ad8e572ca76a6b
> >> CDETECT is ignored since negated return value of mmc_gpio_get_cd(mmc)
> >> can not be checked by IS_ERR_VALUE.
> >> Add spin_lock_bh(&host->lock) for atomic accessing DW_MMC_CARD_PRESENT,
> >> otherwise sd detect may occasionally fail.
> >>
> >> Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
> >> Reported-by: Kevin Hilman <khilman@linaro.org>
> >> Reviewed-by: Sachin Kamat <sachin.kamat@linaro.org>
> >> Tested-by: Sachin Kamat <sachin.kamat@linaro.org>
> >> ---
> >> drivers/mmc/host/dw_mmc.c | 9 ++++++---
> >> 1 file changed, 6 insertions(+), 3 deletions(-)
> >>
> >> diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
> >> index a776f24f4311..9ded62c8225e 100644
> >> --- a/drivers/mmc/host/dw_mmc.c
> >> +++ b/drivers/mmc/host/dw_mmc.c
> >> @@ -1033,7 +1033,8 @@ static int dw_mci_get_cd(struct mmc_host *mmc)
> >> int present;
> >> struct dw_mci_slot *slot = mmc_priv(mmc);
> >> struct dw_mci_board *brd = slot->host->pdata;
> >> - int gpio_cd = !mmc_gpio_get_cd(mmc);
> >> + struct dw_mci *host = slot->host;
> >> + int gpio_cd = mmc_gpio_get_cd(mmc);
> >>
> >> /* Use platform get_cd function, else try onboard card detect */
> >> if (brd->quirks & DW_MCI_QUIRK_BROKEN_CARD_DETECTION)
> >> @@ -1041,11 +1042,12 @@ static int dw_mci_get_cd(struct mmc_host *mmc)
> >> else if (brd->get_cd)
> >> present = !brd->get_cd(slot->id);
> >> else if (!IS_ERR_VALUE(gpio_cd))
> >> - present = !!gpio_cd;
> >> + present = !gpio_cd;
> > !!gpio_cd or gpio_cd is correct, isn't it?
> >
>
> No, mmc_gpio_get_cd(mmc) has to revert.
I'm missing something?
If card is detected, mmc_gpio_get_cd() returns non-zero, right?
I guess gpio_cd should be kept.
> !!gpio_cd is used before since gpio_cd = !mmc_gpio_get_cd(mmc) is used
> before.
>
> Thanks
> --
> To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [PATCH 04/04] ARM: shmobile: r8a7790 CCI configuration
From: Magnus Damm @ 2014-01-15 12:26 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140115122539.9437.63968.sendpatchset@w520>
From: Gaku Inami <gaku.inami.xw@bp.renesas.com>
Add the settings of CCI-400 for enabling ca15/ca7 snoop on r8a7790.
Signed-off-by: Gaku Inami <gaku.inami.xw@bp.renesas.com>
Signed-off-by: Magnus Damm <damm@opensource.se>
---
arch/arm/mach-shmobile/smp-r8a7790.c | 15 +++++++++++++++
1 file changed, 15 insertions(+)
--- 0005/arch/arm/mach-shmobile/smp-r8a7790.c
+++ work/arch/arm/mach-shmobile/smp-r8a7790.c 2014-01-15 15:40:56.000000000 +0900
@@ -28,6 +28,11 @@
#define CA15RESCNT 0x0040
#define CA7RESCNT 0x0044
#define MERAM 0xe8080000
+#define CCI_BASE 0xf0090000
+#define CCI_SLAVE3 0x4000
+#define CCI_SLAVE4 0x5000
+#define CCI_SNOOP 0x0000
+#define CCI_STATUS 0x000c
static struct rcar_sysc_ch r8a7790_ca15_scu = {
.chan_offs = 0x180, /* PWRSR5 .. PWRER5 */
@@ -71,6 +76,16 @@ static void __init r8a7790_smp_prepare_c
r8a7790_pm_init();
rcar_sysc_power_up(&r8a7790_ca15_scu);
rcar_sysc_power_up(&r8a7790_ca7_scu);
+
+ /* enable snoop and DVM */
+ p = ioremap_nocache(CCI_BASE, 0x8000);
+ writel_relaxed(readl_relaxed(p + CCI_SLAVE3 + CCI_SNOOP) | 0x3,
+ p + CCI_SLAVE3 + CCI_SNOOP); /* ca15 */
+ writel_relaxed(readl_relaxed(p + CCI_SLAVE4 + CCI_SNOOP) | 0x3,
+ p + CCI_SLAVE4 + CCI_SNOOP); /* ca7 */
+ while (__raw_readl(p + CCI_STATUS));
+ /* wait for pending bit low */
+ iounmap(p);
}
struct smp_operations r8a7790_smp_ops __initdata = {
^ permalink raw reply
* [PATCH 03/04] ARM: shmobile: r8a7790 CA15-SCU enablement
From: Magnus Damm @ 2014-01-15 12:26 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140115122539.9437.63968.sendpatchset@w520>
From: Keita Kobayashi <keita.kobayashi.ym@renesas.com>
Power on CA15 SCU in case of booting from a CA7 core.
Signed-off-by: Keita Kobayashi <keita.kobayashi.ym@renesas.com>
[damm at opensource.se: Converted to use broken out SYSC code]
Signed-off-by: Magnus Damm <damm@opensource.se>
---
arch/arm/mach-shmobile/smp-r8a7790.c | 6 ++++++
1 file changed, 6 insertions(+)
--- 0004/arch/arm/mach-shmobile/smp-r8a7790.c
+++ work/arch/arm/mach-shmobile/smp-r8a7790.c 2014-01-15 14:41:47.000000000 +0900
@@ -29,6 +29,11 @@
#define CA7RESCNT 0x0044
#define MERAM 0xe8080000
+static struct rcar_sysc_ch r8a7790_ca15_scu = {
+ .chan_offs = 0x180, /* PWRSR5 .. PWRER5 */
+ .isr_bit = 12, /* CA15-SCU */
+};
+
static struct rcar_sysc_ch r8a7790_ca7_scu = {
.chan_offs = 0x100, /* PWRSR3 .. PWRER3 */
.isr_bit = 21, /* CA7-SCU */
@@ -64,6 +69,7 @@ static void __init r8a7790_smp_prepare_c
/* turn on power to SCU */
r8a7790_pm_init();
+ rcar_sysc_power_up(&r8a7790_ca15_scu);
rcar_sysc_power_up(&r8a7790_ca7_scu);
}
^ permalink raw reply
* [PATCH 02/04] ARM: shmobile: r8a7790 CA7-SCU enablement
From: Magnus Damm @ 2014-01-15 12:26 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140115122539.9437.63968.sendpatchset@w520>
From: Gaku Inami <gaku.inami.xw@bp.renesas.com>
Power on CA7 SCU in case of booting from a CA15 core.
Signed-off-by: Gaku Inami <gaku.inami.xw@bp.renesas.com>
[damm at opensource.se: Converted to use broken out SYSC code]
Signed-off-by: Magnus Damm <damm@opensource.se>
---
arch/arm/mach-shmobile/smp-r8a7790.c | 11 +++++++++++
1 file changed, 11 insertions(+)
--- 0001/arch/arm/mach-shmobile/smp-r8a7790.c
+++ work/arch/arm/mach-shmobile/smp-r8a7790.c 2014-01-15 14:34:03.000000000 +0900
@@ -19,6 +19,8 @@
#include <linux/io.h>
#include <asm/smp_plat.h>
#include <mach/common.h>
+#include <mach/pm-rcar.h>
+#include <mach/r8a7790.h>
#define RST 0xe6160000
#define CA15BAR 0x0020
@@ -27,6 +29,11 @@
#define CA7RESCNT 0x0044
#define MERAM 0xe8080000
+static struct rcar_sysc_ch r8a7790_ca7_scu = {
+ .chan_offs = 0x100, /* PWRSR3 .. PWRER3 */
+ .isr_bit = 21, /* CA7-SCU */
+};
+
static void __init r8a7790_smp_prepare_cpus(unsigned int max_cpus)
{
void __iomem *p;
@@ -54,6 +61,10 @@ static void __init r8a7790_smp_prepare_c
writel_relaxed((readl_relaxed(p + CA7RESCNT) & ~0x0f) | 0x5a5a0000,
p + CA7RESCNT);
iounmap(p);
+
+ /* turn on power to SCU */
+ r8a7790_pm_init();
+ rcar_sysc_power_up(&r8a7790_ca7_scu);
}
struct smp_operations r8a7790_smp_ops __initdata = {
^ permalink raw reply
* [PATCH 01/04] ARM: shmobile: r8a7790 SYSC setup code
From: Magnus Damm @ 2014-01-15 12:25 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140115122539.9437.63968.sendpatchset@w520>
From: Hisashi Nakamura <hisashi.nakamura.ak@renesas.com>
Add r8a7790 SYSC power management support.
Signed-off-by: Hisashi Nakamura <hisashi.nakamura.ak@renesas.com>
Signed-off-by: Ryo Kataoka <ryo.kataoka.wt@renesas.com>
[damm at opensource.se: Converted to use broken out SYSC code]
Signed-off-by: Magnus Damm <damm@opensource.se>
---
arch/arm/mach-shmobile/Makefile | 1
arch/arm/mach-shmobile/include/mach/r8a7790.h | 1
arch/arm/mach-shmobile/pm-r8a7790.c | 45 +++++++++++++++++++++++++
3 files changed, 47 insertions(+)
--- 0002/arch/arm/mach-shmobile/Makefile
+++ work/arch/arm/mach-shmobile/Makefile 2014-01-15 14:21:49.000000000 +0900
@@ -53,6 +53,7 @@ obj-$(CONFIG_ARCH_SH7372) += pm-sh7372.o
obj-$(CONFIG_ARCH_SH73A0) += pm-sh73a0.o
obj-$(CONFIG_ARCH_R8A7740) += pm-r8a7740.o pm-rmobile.o
obj-$(CONFIG_ARCH_R8A7779) += pm-r8a7779.o pm-rcar.o
+obj-$(CONFIG_ARCH_R8A7790) += pm-r8a7790.o pm-rcar.o
# Board objects
ifdef CONFIG_ARCH_SHMOBILE_MULTI
--- 0001/arch/arm/mach-shmobile/include/mach/r8a7790.h
+++ work/arch/arm/mach-shmobile/include/mach/r8a7790.h 2014-01-15 14:26:29.000000000 +0900
@@ -32,6 +32,7 @@ void r8a7790_add_standard_devices(void);
void r8a7790_add_dt_devices(void);
void r8a7790_clock_init(void);
void r8a7790_pinmux_init(void);
+void r8a7790_pm_init(void);
void r8a7790_init_early(void);
extern struct smp_operations r8a7790_smp_ops;
--- /dev/null
+++ work/arch/arm/mach-shmobile/pm-r8a7790.c 2014-01-15 14:23:40.000000000 +0900
@@ -0,0 +1,45 @@
+/*
+ * r8a7790 Power management support
+ *
+ * Copyright (C) 2013 Renesas Electronics Corporation
+ * Copyright (C) 2011 Renesas Solutions Corp.
+ * Copyright (C) 2011 Magnus Damm
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/kernel.h>
+#include <asm/io.h>
+#include <mach/pm-rcar.h>
+#include <mach/r8a7790.h>
+
+/* SYSC */
+#define SYSCIER 0x0c
+#define SYSCIMR 0x10
+
+#if defined(CONFIG_SMP)
+
+static void __init r8a7790_sysc_init(void)
+{
+ void __iomem *base = rcar_sysc_init(0xe6180000);
+
+ /* enable all interrupt sources, but do not use interrupt handler */
+ iowrite32(0x0131000e, base + SYSCIER);
+ iowrite32(0, base + SYSCIMR);
+}
+
+#else /* CONFIG_SMP */
+
+static inline void r8a7790_sysc_init(void) {}
+
+#endif /* CONFIG_SMP */
+
+void __init r8a7790_pm_init(void)
+{
+ static int once;
+
+ if (!once++)
+ r8a7790_sysc_init();
+}
^ permalink raw reply
* [PATCH 00/04] ARM: shmobile: r8a7790 SYSC, SCU and CCI setup code
From: Magnus Damm @ 2014-01-15 12:25 UTC (permalink / raw)
To: linux-arm-kernel
ARM: shmobile: r8a7790 SYSC, SCU and CCI setup code
[PATCH 01/04] ARM: shmobile: r8a7790 SYSC setup code
[PATCH 02/04] ARM: shmobile: r8a7790 CA7-SCU enablement
[PATCH 03/04] ARM: shmobile: r8a7790 CA15-SCU enablement
[PATCH 04/04] ARM: shmobile: r8a7790 CCI configuration
Add r8a7790 specific SYSC, SCU and CCI setup code.
Signed-off-by: Hisashi Nakamura <hisashi.nakamura.ak@renesas.com>
Signed-off-by: Ryo Kataoka <ryo.kataoka.wt@renesas.com>
Signed-off-by: Gaku Inami <gaku.inami.xw@bp.renesas.com>
Signed-off-by: Keita Kobayashi <keita.kobayashi.ym@renesas.com>
[damm at opensource.se: Converted to use broken out SYSC code]
Signed-off-by: Magnus Damm <damm@opensource.se>
---
Written against renesas.git tag renesas-devel-v3.13-rc8-20140115,
also requires "[PATCH] ARM: shmobile: Break out R-Car SYSC PM code"
arch/arm/mach-shmobile/Makefile | 1
arch/arm/mach-shmobile/include/mach/r8a7790.h | 1
arch/arm/mach-shmobile/pm-r8a7790.c | 45 +++++++++++++++++++++++++
arch/arm/mach-shmobile/smp-r8a7790.c | 32 +++++++++++++++++
4 files changed, 79 insertions(+)
^ permalink raw reply
* [GIT PULL] clk: socfpga: Clean-ups for 3.14
From: Dinh Nguyen @ 2014-01-15 12:24 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140115043206.4167.50892@quantum>
On 1/14/14 10:32 PM, Mike Turquette wrote:
> Quoting dinguyen at altera.com (2014-01-06 09:27:26)
>> Hi Mike,
>>
>> Please pull in these patches that cleans up the SOCFPGA clock driver. This is
>> V2 of the pull request that includes 4 patches from Steffen Trumtrar.
>>
>> Thanks,
>>
>> Dinh
>>
>> The following changes since commit 6ce4eac1f600b34f2f7f58f9cd8f0503d79e42ae:
>>
>> Linux 3.13-rc1 (2013-11-22 11:30:55 -0800)
>>
>> are available in the git repository at:
>>
>> git://git.rocketboards.org/linux-socfpga-next.git tags/socfpga-clk-for-3.14_v2
>>
>> for you to fetch changes up to d5387681665e58bafc1a9c745182f03aab0579c3:
>>
>> clk: socfpga: split clk code (2014-01-06 11:22:22 -0600)
>>
>> ----------------------------------------------------------------
>> v2: SOCFPGA clk cleanups for 3.14
>>
>> ----------------------------------------------------------------
>> Dinh Nguyen (3):
>> clk: socfpga: Map the clk manager base address in the clock driver
>> clk: socfpga: Look for the GPIO_DB_CLK by its offset
> Hi Dinh,
>
> Patch "clk: socfpga: Look for the GPIO_DB_CLK by its offset" still
> causes a compilation error. I know it gets fixed by "clk: socfpga: fix
> compile error" later on but this still breaks git bisect.
>
> Can you please fold the fixes into the patches that introduce the bugs?
> No need to keep them separate since they are all part of the same pull
> request.
I have sent you a v3 of the pull request that folds in the fix. Thanks
for the
advice. I'll be sure to do that in the future.
Dinh
>
> Regards,
> Mike
>
>> clk: socfpga: Remove socfpga_init_clocks
>>
>> Steffen Trumtrar (4):
>> clk: socfpga: remove unused field
>> clk: socfpga: fix define typo
>> clk: socfpga: fix compile error
>> clk: socfpga: split clk code
>>
>> arch/arm/mach-socfpga/socfpga.c | 5 -
>> drivers/clk/socfpga/Makefile | 3 +
>> drivers/clk/socfpga/clk-gate.c | 223 ++++++++++++++++++++++++++
>> drivers/clk/socfpga/clk-periph.c | 94 +++++++++++
>> drivers/clk/socfpga/clk-pll.c | 111 +++++++++++++
>> drivers/clk/socfpga/clk.c | 328 ++------------------------------------
>> drivers/clk/socfpga/clk.h | 57 +++++++
>> 7 files changed, 500 insertions(+), 321 deletions(-)
>> create mode 100644 drivers/clk/socfpga/clk-gate.c
>> create mode 100644 drivers/clk/socfpga/clk-periph.c
>> create mode 100644 drivers/clk/socfpga/clk-pll.c
>> create mode 100644 drivers/clk/socfpga/clk.h
>>
^ permalink raw reply
* [GIT PULLv3] clk: socfpga: Clean-ups for 3.14
From: dinguyen at altera.com @ 2014-01-15 12:18 UTC (permalink / raw)
To: linux-arm-kernel
Hi Mike,
Please pull in these patches that cleans up the SOCFPGA clock driver. This is
v3 of the pull request that includes 3 patches from Steffen Trumtrar. I have
squashed the compiler error fix patch into the patch that introduced the error.
Bisectability should now be fix.
Thanks,
Dinh
The following changes since commit 6ce4eac1f600b34f2f7f58f9cd8f0503d79e42ae:
Linux 3.13-rc1 (2013-11-22 11:30:55 -0800)
are available in the git repository at:
git://git.rocketboards.org/linux-socfpga-next.git tags/socfpga-clk-for-3.14_v3
for you to fetch changes up to 5710d11ab5230dce43e5edc09d9d5506d3d49663:
clk: socfpga: split clk code (2014-01-15 05:56:07 -0600)
----------------------------------------------------------------
v3: SOCFPGA clk cleanups for 3.14
----------------------------------------------------------------
Dinh Nguyen (3):
clk: socfpga: Map the clk manager base address in the clock driver
clk: socfpga: Look for the GPIO_DB_CLK by its offset
clk: socfpga: Remove socfpga_init_clocks
Steffen Trumtrar (3):
clk: socfpga: remove unused field
clk: socfpga: fix define typo
clk: socfpga: split clk code
arch/arm/mach-socfpga/socfpga.c | 5 -
drivers/clk/socfpga/Makefile | 3 +
drivers/clk/socfpga/clk-gate.c | 195 ++++++++++++++++++++++
drivers/clk/socfpga/clk-periph.c | 94 +++++++++++
drivers/clk/socfpga/clk-pll.c | 111 +++++++++++++
drivers/clk/socfpga/clk.c | 328 ++------------------------------------
drivers/clk/socfpga/clk.h | 57 +++++++
7 files changed, 472 insertions(+), 321 deletions(-)
create mode 100644 drivers/clk/socfpga/clk-gate.c
create mode 100644 drivers/clk/socfpga/clk-periph.c
create mode 100644 drivers/clk/socfpga/clk-pll.c
create mode 100644 drivers/clk/socfpga/clk.h
^ permalink raw reply
* [RFC PATCH 1/1] of/irq: create interrupts-extended-2 property
From: Mark Rutland @ 2014-01-15 12:17 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1389786445-10598-1-git-send-email-plagnioj@jcrosoft.com>
On Wed, Jan 15, 2014 at 11:47:25AM +0000, Jean-Christophe PLAGNIOL-VILLARD wrote:
> The new interrupts-extended property, which reuses the phandle+arguments
> pattern used by GPIOs and other core bindings, still have some issue.
>
> If an SoC have already specifiy interrupt and a board want to add specific
> interrupt such as GPIO (which can be optionnal) be need to re-define
> interrupts-extended. So allow to have an optionnale interrupts-extended-2
> property.
>
NAK.
This is a hack that works around a dts organisation issue. This is _not_
a binding or parsing issue.
Properties can be overridden - just describe all of the interrupts in
the final dts file.
> Today the problem is ofen solve by defining a gpio-xxx property and then do a gpio_to_irq
> in the C code. *Which is wrong!!*. We need to describe the IRQ.
>
> Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
> Cc: Grant Likely <grant.likely@linaro.org>
> Cc: Rob Herring <rob.herring@calxeda.com>
> ---
>
> We have the same issue on pinctrl
> .../devicetree/bindings/interrupt-controller/interrupts.txt | 4 ++++
> drivers/of/irq.c | 10 ++++++++--
> 2 files changed, 12 insertions(+), 2 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/interrupt-controller/interrupts.txt b/Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
> index 1486497..5d559fd 100644
> --- a/Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
> +++ b/Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
> @@ -25,8 +25,12 @@ to reference multiple interrupt parents. Each entry in this property contains
> both the parent phandle and the interrupt specifier. "interrupts-extended"
> should only be used when a device has multiple interrupt parents.
>
> +The "interrupts-extended-2" allow to extend at board level node interrupt without
> +having to re-define the SoC interrupts.
> +
> Example:
> interrupts-extended = <&intc1 5 1>, <&intc2 1 0>;
> + interrupts-extended-2 = <&intc1 6 1>
>
> A device node may contain either "interrupts" or "interrupts-extended", but not
> both. If both properties are present, then the operating system should log an
> diff --git a/drivers/of/irq.c b/drivers/of/irq.c
> index 786b0b4..bc36710 100644
> --- a/drivers/of/irq.c
> +++ b/drivers/of/irq.c
> @@ -307,8 +307,14 @@ int of_irq_parse_one(struct device_node *device, int index, struct of_phandle_ar
> /* Try the new-style interrupts-extended */
> res = of_parse_phandle_with_args(device, "interrupts-extended",
> "#interrupt-cells", index, out_irq);
> - if (res)
> - return -EINVAL;
> + if (res) {
> + /* Try the new-style interrupts-extended-2 */
> + res = of_parse_phandle_with_args(device, "interrupts-extended-2",
> + "#interrupt-cells", index, out_irq);
This also breaks error reporting.
What if you have an interrupt in the middle of interrupts-extended which
fails to parse? This will jump to the interrupts-extended-2 property and
grab the wrong interrupt rather than propagating the error.
Thanks,
Mark.
^ permalink raw reply
* [PATCH] mmc: dw_mmc: fix dw_mci_get_cd
From: zhangfei @ 2014-01-15 12:10 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <001701cf11e9$25b5fe50$7121faf0$%jun@samsung.com>
On 01/15/2014 07:58 PM, Seungwon Jeon wrote:
> On Wed, January 15, 2014, Zhangfei Gao wrote:
>> Introduced from commit bf626e5550f24aec24975a0e85ad8e572ca76a6b
>> CDETECT is ignored since negated return value of mmc_gpio_get_cd(mmc)
>> can not be checked by IS_ERR_VALUE.
>> Add spin_lock_bh(&host->lock) for atomic accessing DW_MMC_CARD_PRESENT,
>> otherwise sd detect may occasionally fail.
>>
>> Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
>> Reported-by: Kevin Hilman <khilman@linaro.org>
>> Reviewed-by: Sachin Kamat <sachin.kamat@linaro.org>
>> Tested-by: Sachin Kamat <sachin.kamat@linaro.org>
>> ---
>> drivers/mmc/host/dw_mmc.c | 9 ++++++---
>> 1 file changed, 6 insertions(+), 3 deletions(-)
>>
>> diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
>> index a776f24f4311..9ded62c8225e 100644
>> --- a/drivers/mmc/host/dw_mmc.c
>> +++ b/drivers/mmc/host/dw_mmc.c
>> @@ -1033,7 +1033,8 @@ static int dw_mci_get_cd(struct mmc_host *mmc)
>> int present;
>> struct dw_mci_slot *slot = mmc_priv(mmc);
>> struct dw_mci_board *brd = slot->host->pdata;
>> - int gpio_cd = !mmc_gpio_get_cd(mmc);
>> + struct dw_mci *host = slot->host;
>> + int gpio_cd = mmc_gpio_get_cd(mmc);
>>
>> /* Use platform get_cd function, else try onboard card detect */
>> if (brd->quirks & DW_MCI_QUIRK_BROKEN_CARD_DETECTION)
>> @@ -1041,11 +1042,12 @@ static int dw_mci_get_cd(struct mmc_host *mmc)
>> else if (brd->get_cd)
>> present = !brd->get_cd(slot->id);
>> else if (!IS_ERR_VALUE(gpio_cd))
>> - present = !!gpio_cd;
>> + present = !gpio_cd;
> !!gpio_cd or gpio_cd is correct, isn't it?
>
No, mmc_gpio_get_cd(mmc) has to revert.
!!gpio_cd is used before since gpio_cd = !mmc_gpio_get_cd(mmc) is used
before.
Thanks
^ permalink raw reply
* [PATCH v7 3/4] PHY: add APM X-Gene SoC 15Gbps Multi-purpose PHY driver
From: Mark Rutland @ 2014-01-15 12:09 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1389769840-15469-4-git-send-email-lho@apm.com>
On Wed, Jan 15, 2014 at 07:10:39AM +0000, Loc Ho wrote:
[...]
> + * The APM X-Gene PHY consists of two PLL clock macro's (CMU) and lanes.
> + * The first PLL clock macro is used for internal reference clock. The second
> + * PLL clock macro is used to generate the clock for the PHY. This driver
> + * configures the first PLL CMU, the second PLL CMU, and programs the PHY to
> + * operate according to the mode of operation. The first PLL CMU is only
> + * required if internal clock is enabled.
> + *
> + * Logical Layer Out Of HW module units:
> + *
> + * -----------------
> + * | Internal | |------|
> + * | Ref PLL CMU |----| | ------------- ---------
> + * ------------ ---- | MUX |-----|PHY PLL CMU|----| Serdes|
> + * | | | | ---------
> + * External Clock ------| | -------------
> + * |------|
> + *
> + * The Ref PLL CMU CSR (Configureation System Registers) is accessed
> + * indirectly from the SDS offset at 0x2000. It is only required for
> + * internal reference clock.
> + * The PHY PLL CMU CSR is accessed indirectly from the SDS offset at 0x0000.
> + * The Serdes CSR is accessed indirectly from the SDS offset at 0x0400.
> + *
> + * The Ref PLL CMU can be located within the same PHY IP or outside the PHY IP
> + * due to shared Ref PLL CMU. For PHY with Ref PLL CMU shared with another IP,
> + * it is located outside the PHY IP. This is the case for the PHY located
> + * at 0x1f23a000 (SATA Port 4/5). For such PHY, another resource is required
> + * to located the SDS/Ref PLL CMU module and its clock for that IP enabled.
> + *
> + * Currently, this driver only supports SATA mode with external clock.
> + */
Having looked at this and the binding, I'm confused as to why we need an
additional reg entry when we're using the external clock.
Surely the second resource (the external CMU base) is a property of the
shared ref PLL clock, rather than the PHY itself. How do you handle two
units trying to use the shared PLL?
I think makes sense to model the ref PLL CMU as a separate clock, and
use clock-names to differentiate between the two inputs to the mux:
external: external_clock {
compatible = "fixed-clock";
clock-frequency = < ... >;
#clock-cells = <0>;
};
ref_pll: reference_clock {
compatible = "apm,xgene-ref-pll";
reg = < .... >;
#clock-cells = <0>;
};
phy {
compatible = "apm,xgene-phy";
reg = < ... >;
clocks = <&ref_pll>, <&external>;
clock-names = "ref-pll", "external";
...
};
That also means the phy only needs a single compatible string -- you can
figure out what to do by probing the set of clocks.
Does that make sense? Is there something I'm missing?
[...]
> + /* Retrieve optional clock */
> + ctx->clk = clk_get(&pdev->dev, NULL);
There's no clocks proeprty in the binding. Please add one.
Cheers,
Mark.
^ 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