* [PATCH] ARM: dt: sun6i: Add #address-cells and #size-cells to i2c controller nodes
From: Chen-Yu Tsai @ 2014-07-21 14:54 UTC (permalink / raw)
To: linux-arm-kernel
dtc was giving warnings for missing #address-cells and #size-cells for
the new sun6i-a31-hummingbird.dts, which has a i2c-based rtc device.
This patch adds the properties for all i2c controller nodes for sun6i.
Signed-off-by: Chen-Yu Tsai <wens@csie.org>
---
Hi Maxime,
This is a fix to get rid of warnings from dtc when building sun6i dts.
Sorry for now catching it earlier.
Cheers
ChenYu
---
arch/arm/boot/dts/sun6i-a31.dtsi | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/arch/arm/boot/dts/sun6i-a31.dtsi b/arch/arm/boot/dts/sun6i-a31.dtsi
index 44b07e5..e06fbfc 100644
--- a/arch/arm/boot/dts/sun6i-a31.dtsi
+++ b/arch/arm/boot/dts/sun6i-a31.dtsi
@@ -660,6 +660,8 @@
clock-frequency = <100000>;
resets = <&apb2_rst 0>;
status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
};
i2c1: i2c at 01c2b000 {
@@ -670,6 +672,8 @@
clock-frequency = <100000>;
resets = <&apb2_rst 1>;
status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
};
i2c2: i2c at 01c2b400 {
@@ -680,6 +684,8 @@
clock-frequency = <100000>;
resets = <&apb2_rst 2>;
status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
};
i2c3: i2c at 01c2b800 {
@@ -690,6 +696,8 @@
clock-frequency = <100000>;
resets = <&apb2_rst 3>;
status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
};
gmac: ethernet at 01c30000 {
--
2.0.1
^ permalink raw reply related
* [PATCH RFC 9/9] arm: imx: non-secure aliased mapping of GIC registers
From: Daniel Thompson @ 2014-07-21 14:47 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1405954040-30399-1-git-send-email-daniel.thompson@linaro.org>
Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org>
---
arch/arm/mach-imx/mach-imx6q.c | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/arch/arm/mach-imx/mach-imx6q.c b/arch/arm/mach-imx/mach-imx6q.c
index e60456d..192d268 100644
--- a/arch/arm/mach-imx/mach-imx6q.c
+++ b/arch/arm/mach-imx/mach-imx6q.c
@@ -381,10 +381,21 @@ static void __init imx6q_init_late(void)
}
}
+static struct map_desc gic_cpu_io_desc __initdata = {
+ .virtual = 0xff000000,
+ .pfn = __phys_to_pfn(0x00a00000),
+ .length = SZ_1M,
+ .type = MT_DEVICE_NS,
+};
+
static void __init imx6q_map_io(void)
{
debug_ll_io_init();
imx_scu_map_io();
+ /* TODO: Need to check we are running without a secure monitor before
+ * setting up this mapping.
+ */
+ iotable_init(&gic_cpu_io_desc, 1);
}
static void __init imx6q_init_irq(void)
--
1.9.3
^ permalink raw reply related
* [PATCH RFC 8/9] ARM: socfpga: Map the GIC CPU registers as MT_DEVICE_NS
From: Daniel Thompson @ 2014-07-21 14:47 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1405954040-30399-1-git-send-email-daniel.thompson@linaro.org>
From: Marek Vasut <marex@denx.de>
Statically map the SoCFPGA's memory space at PA 0xfff00000 +1MiB to 0xff000000
and set type of this VA to be MT_DEVICE_NS. This PA contains the SoCFPGA's GIC
CPU registers at offset +0xec100. This area is right past VMALLOC_END and well
below the optional start of per-CPU highmem entries. We can thus use this area
to place our mapping here and be sure it's not in anyone's way.
All accesses to VA 0xff000000 generate non-secure accesses on the bus and we
can leverage this property to generate non-secure read of the GIC INTACK (IAR)
register. This non-secure read will never return an FIQ interrupt number.
Signed-off-by: Marek Vasut <marex@denx.de>
Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org>
---
arch/arm/mach-socfpga/socfpga.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/arch/arm/mach-socfpga/socfpga.c b/arch/arm/mach-socfpga/socfpga.c
index adbf383..5b60f82 100644
--- a/arch/arm/mach-socfpga/socfpga.c
+++ b/arch/arm/mach-socfpga/socfpga.c
@@ -45,6 +45,13 @@ static struct map_desc uart_io_desc __initdata = {
.type = MT_DEVICE,
};
+static struct map_desc gic_cpu_io_desc __initdata = {
+ .virtual = 0xff000000,
+ .pfn = __phys_to_pfn(0xfff00000),
+ .length = SZ_1M,
+ .type = MT_DEVICE_NS,
+};
+
static void __init socfpga_scu_map_io(void)
{
unsigned long base;
@@ -60,6 +67,7 @@ static void __init socfpga_map_io(void)
{
socfpga_scu_map_io();
iotable_init(&uart_io_desc, 1);
+ iotable_init(&gic_cpu_io_desc, 1);
early_printk("Early printk initialized\n");
}
--
1.9.3
^ permalink raw reply related
* [PATCH RFC 7/9] irqchip: gic: Use non-secure aliased register set when FIQ is enabled
From: Daniel Thompson @ 2014-07-21 14:47 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1405954040-30399-1-git-send-email-daniel.thompson@linaro.org>
Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org>
---
drivers/irqchip/irq-gic.c | 76 ++++++++++++++++++++++++++++++++++++-----
include/linux/irqchip/arm-gic.h | 4 +--
2 files changed, 70 insertions(+), 10 deletions(-)
diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
index 5c934a4..8faa271 100644
--- a/drivers/irqchip/irq-gic.c
+++ b/drivers/irqchip/irq-gic.c
@@ -59,6 +59,7 @@ union gic_base {
struct gic_chip_data {
union gic_base dist_base;
union gic_base cpu_base;
+ union gic_base aliased_cpu_base;
#ifdef CONFIG_CPU_PM
u32 saved_spi_enable[DIV_ROUND_UP(1020, 32)];
u32 saved_spi_conf[DIV_ROUND_UP(1020, 16)];
@@ -126,6 +127,12 @@ static inline void __iomem *gic_data_cpu_base(struct gic_chip_data *data)
return data->get_base(&data->cpu_base);
}
+static inline void __iomem *gic_data_aliased_cpu_base(
+ struct gic_chip_data *data)
+{
+ return data->get_base(&data->aliased_cpu_base);
+}
+
static inline void gic_set_base_accessor(struct gic_chip_data *data,
void __iomem *(*f)(union gic_base *))
{
@@ -134,6 +141,7 @@ static inline void gic_set_base_accessor(struct gic_chip_data *data,
#else
#define gic_data_dist_base(d) ((d)->dist_base.common_base)
#define gic_data_cpu_base(d) ((d)->cpu_base.common_base)
+#define gic_data_aliased_cpu_base(d) ((d)->aliased_cpu_base.common_base)
#define gic_set_base_accessor(d, f)
#endif
@@ -159,6 +167,13 @@ static inline void __iomem *gic_cpu_base(struct irq_data *d)
return gic_data_cpu_base(gic_data);
}
+static inline void __iomem *gic_aliased_cpu_base(struct irq_data *d)
+{
+ struct gic_chip_data *gic_data = irq_data_get_irq_chip_data(d);
+
+ return gic_data_aliased_cpu_base(gic_data);
+}
+
static inline unsigned int gic_irq(struct irq_data *d)
{
return d->hwirq;
@@ -194,7 +209,7 @@ static void gic_eoi_irq(struct irq_data *d)
if (gic_arch_extn.irq_eoi)
gic_arch_extn.irq_eoi(d);
- writel_relaxed(gic_irq(d), gic_cpu_base(d) + GIC_CPU_EOI);
+ writel_relaxed(gic_irq(d), gic_aliased_cpu_base(d) + GIC_CPU_EOI);
}
static int gic_set_type(struct irq_data *d, unsigned int type)
@@ -300,7 +315,7 @@ static void __exception_irq_entry gic_handle_irq(struct pt_regs *regs)
{
u32 irqstat, irqnr;
struct gic_chip_data *gic = &gic_data[0];
- void __iomem *cpu_base = gic_data_cpu_base(gic);
+ void __iomem *cpu_base = gic_data_aliased_cpu_base(gic);
do {
irqstat = readl_relaxed(cpu_base + GIC_CPU_INTACK);
@@ -332,7 +347,8 @@ static void gic_handle_cascade_irq(unsigned int irq, struct irq_desc *desc)
chained_irq_enter(chip, desc);
raw_spin_lock(&irq_controller_lock);
- status = readl_relaxed(gic_data_cpu_base(chip_data) + GIC_CPU_INTACK);
+ status = readl_relaxed(gic_data_aliased_cpu_base(chip_data) +
+ GIC_CPU_INTACK);
raw_spin_unlock(&irq_controller_lock);
gic_irq = (status & 0x3ff);
@@ -419,11 +435,19 @@ static int gic_ack_fiq(struct irq_data *d)
return irq_find_mapping(gic->domain, irqnr);
}
+static void gic_eoi_fiq(struct irq_data *d)
+{
+ if (gic_arch_extn.irq_eoi)
+ gic_arch_extn.irq_eoi(d);
+
+ writel_relaxed(gic_irq(d), gic_cpu_base(d) + GIC_CPU_EOI);
+}
+
static struct fiq_chip gic_fiq = {
.fiq_enable = gic_enable_fiq,
.fiq_disable = gic_disable_fiq,
.fiq_ack = gic_ack_fiq,
- .fiq_eoi = gic_eoi_irq,
+ .fiq_eoi = gic_eoi_fiq,
};
static void __init gic_init_fiq(struct gic_chip_data *gic,
@@ -453,6 +477,10 @@ static void __init gic_init_fiq(struct gic_chip_data *gic,
*/
for (i = 0; i < num_irqs; i++)
fiq_register_mapping(first_irq + i, &gic_fiq);
+
+ /* This is not a fatal problem for some use-cases so WARN() is enough */
+ WARN(gic_data_cpu_base(gic_data) == gic_data_aliased_cpu_base(gic_data),
+ "No non-secure alias; IRQ handler may spuriously ack FIQs\n");
}
#else /* CONFIG_FIQ */
static inline void gic_init_fiq(struct gic_chip_data *gic,
@@ -1076,7 +1104,9 @@ const struct irq_domain_ops *gic_routable_irq_domain_ops =
void __init gic_init_bases(unsigned int gic_nr, int irq_start,
void __iomem *dist_base, void __iomem *cpu_base,
- u32 percpu_offset, struct device_node *node)
+ void __iomem *aliased_cpu_base,
+ u32 percpu_offset,
+ struct device_node *node)
{
irq_hw_number_t hwirq_base;
struct gic_chip_data *gic;
@@ -1085,6 +1115,9 @@ void __init gic_init_bases(unsigned int gic_nr, int irq_start,
BUG_ON(gic_nr >= MAX_GIC_NR);
+ if (!aliased_cpu_base)
+ aliased_cpu_base = cpu_base;
+
gic = &gic_data[gic_nr];
#ifdef CONFIG_GIC_NON_BANKED
if (percpu_offset) { /* Frankein-GIC without banked registers... */
@@ -1092,10 +1125,14 @@ void __init gic_init_bases(unsigned int gic_nr, int irq_start,
gic->dist_base.percpu_base = alloc_percpu(void __iomem *);
gic->cpu_base.percpu_base = alloc_percpu(void __iomem *);
+ gic->aliased_cpu_base.percpu_base =
+ alloc_percpu(void __iomem *);
if (WARN_ON(!gic->dist_base.percpu_base ||
- !gic->cpu_base.percpu_base)) {
+ !gic->cpu_base.percpu_base ||
+ !gic->aliased_cpu_base.percpu_base)) {
free_percpu(gic->dist_base.percpu_base);
free_percpu(gic->cpu_base.percpu_base);
+ free_percpu(gic->aliased_cpu_base.percpu_base);
return;
}
@@ -1103,6 +1140,8 @@ void __init gic_init_bases(unsigned int gic_nr, int irq_start,
unsigned long offset = percpu_offset * cpu_logical_map(cpu);
*per_cpu_ptr(gic->dist_base.percpu_base, cpu) = dist_base + offset;
*per_cpu_ptr(gic->cpu_base.percpu_base, cpu) = cpu_base + offset;
+ *per_cpu_ptr(gic->aliased_cpu_base.percpu_base, cpu) =
+ aliased_cpu_base + offset;
}
gic_set_base_accessor(gic, gic_get_percpu_base);
@@ -1114,6 +1153,7 @@ void __init gic_init_bases(unsigned int gic_nr, int irq_start,
percpu_offset);
gic->dist_base.common_base = dist_base;
gic->cpu_base.common_base = cpu_base;
+ gic->aliased_cpu_base.common_base = aliased_cpu_base;
gic_set_base_accessor(gic, gic_get_common_base);
}
@@ -1188,11 +1228,27 @@ void __init gic_init_bases(unsigned int gic_nr, int irq_start,
#ifdef CONFIG_OF
static int gic_cnt __initdata;
+static void __init __iomem *gic_arm_iomap_nonsecure(struct device_node *np,
+ int index)
+{
+#if defined(CONFIG_ARM) && defined(CONFIG_FIQ)
+ struct resource res;
+
+ if (of_address_to_resource(np, index, &res))
+ return NULL;
+
+ return __arm_ioremap(res.start, resource_size(&res), MT_DEVICE_NS);
+#else
+ return NULL;
+#endif
+}
+
static int __init
gic_of_init(struct device_node *node, struct device_node *parent)
{
- void __iomem *cpu_base;
void __iomem *dist_base;
+ void __iomem *cpu_base;
+ void __iomem *aliased_cpu_base;
u32 percpu_offset;
int irq;
@@ -1205,10 +1261,14 @@ gic_of_init(struct device_node *node, struct device_node *parent)
cpu_base = of_iomap(node, 1);
WARN(!cpu_base, "unable to map gic cpu registers\n");
+ aliased_cpu_base = gic_arm_iomap_nonsecure(node, 1);
+ /* no NULL check because NULL is a legimate value */
+
if (of_property_read_u32(node, "cpu-offset", &percpu_offset))
percpu_offset = 0;
- gic_init_bases(gic_cnt, -1, dist_base, cpu_base, percpu_offset, node);
+ gic_init_bases(gic_cnt, -1, dist_base, cpu_base, aliased_cpu_base,
+ percpu_offset, node);
if (!gic_cnt)
gic_init_physaddr(node);
diff --git a/include/linux/irqchip/arm-gic.h b/include/linux/irqchip/arm-gic.h
index 45e2d8c..15cf913 100644
--- a/include/linux/irqchip/arm-gic.h
+++ b/include/linux/irqchip/arm-gic.h
@@ -80,14 +80,14 @@ struct device_node;
extern struct irq_chip gic_arch_extn;
void gic_init_bases(unsigned int, int, void __iomem *, void __iomem *,
- u32 offset, struct device_node *);
+ void __iomem *, u32 offset, struct device_node *);
void gic_cascade_irq(unsigned int gic_nr, unsigned int irq);
void gic_cpu_if_down(void);
static inline void gic_init(unsigned int nr, int start,
void __iomem *dist , void __iomem *cpu)
{
- gic_init_bases(nr, start, dist, cpu, 0, NULL);
+ gic_init_bases(nr, start, dist, cpu, NULL, 0, NULL);
}
void gic_send_sgi(unsigned int cpu_id, unsigned int irq);
--
1.9.3
^ permalink raw reply related
* [PATCH RFC 6/9] arm: mm: Avoid ioremap_page_range() for non-secure mappings
From: Daniel Thompson @ 2014-07-21 14:47 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1405954040-30399-1-git-send-email-daniel.thompson@linaro.org>
ioremap_page_range() cannot provide us memory with the the non-secure
section flag set unfortunately at present ioremap+MT_DEVICE_NS will
fallback to this function and spuriously return a virtual pointer to
what is effectively MT_DEVICE memory.
This patch makes the fallback to ioremap_page_range() ineffective; to
allocate MT_DEVICE_NS memory we must rely instead on the platform startup
code providing a suitable static mapping.
Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org>
---
arch/arm/mm/ioremap.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c
index d1e5ad7..1cb12f8 100644
--- a/arch/arm/mm/ioremap.c
+++ b/arch/arm/mm/ioremap.c
@@ -319,6 +319,10 @@ void __iomem * __arm_ioremap_pfn_caller(unsigned long pfn,
err = remap_area_sections(addr, pfn, size, type);
} else
#endif
+ if (type->prot_sect & PMD_SECT_NS)
+ /* required section flag is not achievable; give up */
+ return NULL;
+ else
err = ioremap_page_range(addr, addr + size, paddr,
__pgprot(type->prot_pte));
--
1.9.3
^ permalink raw reply related
* [PATCH RFC 5/9] ARM: Add L1 PTE non-secure mapping
From: Daniel Thompson @ 2014-07-21 14:47 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1405954040-30399-1-git-send-email-daniel.thompson@linaro.org>
From: Marek Vasut <marex@denx.de>
Add new device type, MT_DEVICE_NS. This type sets the NS bit in L1 PTE [1].
Accesses to a memory region which is mapped this way generate non-secure
access to that memory area. One must be careful here, since the NS bit is
only available in L1 PTE, therefore when creating the mapping, the mapping
must be at least 1 MiB big and must be aligned to 1 MiB. If that condition
was false, the kernel would use regular L2 page mapping for this area instead
and the NS bit setting would be ineffective.
[1] See DDI0406B , Section B3 "Virtual Memory System Architecture (VMSA)",
Subsection B3.3.1 "Translation table entry formats", paragraph
"First-level descriptors", Table B3-1 and associated description
of the NS bit in the "Section" table entry.
Signed-off-by: Marek Vasut <marex@denx.de>
Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org>
---
arch/arm/include/asm/io.h | 5 ++++-
arch/arm/include/asm/mach/map.h | 4 ++--
arch/arm/include/asm/pgtable-2level-hwdef.h | 1 +
arch/arm/mm/mmu.c | 13 ++++++++++++-
4 files changed, 19 insertions(+), 4 deletions(-)
diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h
index 3d23418..22765e0 100644
--- a/arch/arm/include/asm/io.h
+++ b/arch/arm/include/asm/io.h
@@ -125,8 +125,10 @@ static inline u32 __raw_readl(const volatile void __iomem *addr)
#define MT_DEVICE_NONSHARED 1
#define MT_DEVICE_CACHED 2
#define MT_DEVICE_WC 3
+#define MT_DEVICE_NS 4
+
/*
- * types 4 onwards can be found in asm/mach/map.h and are undefined
+ * types 5 onwards can be found in asm/mach/map.h and are undefined
* for ioremap
*/
@@ -343,6 +345,7 @@ extern void _memset_io(volatile void __iomem *, int, size_t);
#define ioremap_nocache(cookie,size) __arm_ioremap((cookie), (size), MT_DEVICE)
#define ioremap_cache(cookie,size) __arm_ioremap((cookie), (size), MT_DEVICE_CACHED)
#define ioremap_wc(cookie,size) __arm_ioremap((cookie), (size), MT_DEVICE_WC)
+#define ioremap_ns(cookie,size) __arm_ioremap((cookie), (size), MT_DEVICE_NS)
#define iounmap __arm_iounmap
/*
diff --git a/arch/arm/include/asm/mach/map.h b/arch/arm/include/asm/mach/map.h
index f98c7f3..42be265 100644
--- a/arch/arm/include/asm/mach/map.h
+++ b/arch/arm/include/asm/mach/map.h
@@ -21,9 +21,9 @@ struct map_desc {
unsigned int type;
};
-/* types 0-3 are defined in asm/io.h */
+/* types 0-4 are defined in asm/io.h */
enum {
- MT_UNCACHED = 4,
+ MT_UNCACHED = 5,
MT_CACHECLEAN,
MT_MINICLEAN,
MT_LOW_VECTORS,
diff --git a/arch/arm/include/asm/pgtable-2level-hwdef.h b/arch/arm/include/asm/pgtable-2level-hwdef.h
index 5cfba15..d24e7ea 100644
--- a/arch/arm/include/asm/pgtable-2level-hwdef.h
+++ b/arch/arm/include/asm/pgtable-2level-hwdef.h
@@ -36,6 +36,7 @@
#define PMD_SECT_S (_AT(pmdval_t, 1) << 16) /* v6 */
#define PMD_SECT_nG (_AT(pmdval_t, 1) << 17) /* v6 */
#define PMD_SECT_SUPER (_AT(pmdval_t, 1) << 18) /* v6 */
+#define PMD_SECT_NS (_AT(pmdval_t, 1) << 19) /* v6 */
#define PMD_SECT_AF (_AT(pmdval_t, 0))
#define PMD_SECT_UNCACHED (_AT(pmdval_t, 0))
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index ab14b79..9baf1cb 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -268,6 +268,13 @@ static struct mem_type mem_types[] = {
.prot_sect = PROT_SECT_DEVICE,
.domain = DOMAIN_IO,
},
+ [MT_DEVICE_NS] = { /* Non-secure accesses from secure mode */
+ .prot_pte = PROT_PTE_DEVICE | L_PTE_MT_DEV_SHARED |
+ L_PTE_SHARED,
+ .prot_l1 = PMD_TYPE_TABLE,
+ .prot_sect = PROT_SECT_DEVICE | PMD_SECT_S | PMD_SECT_NS,
+ .domain = DOMAIN_IO,
+ },
[MT_UNCACHED] = {
.prot_pte = PROT_PTE_DEVICE,
.prot_l1 = PMD_TYPE_TABLE,
@@ -474,6 +481,7 @@ static void __init build_mem_type_table(void)
mem_types[MT_DEVICE_NONSHARED].prot_sect |= PMD_SECT_XN;
mem_types[MT_DEVICE_CACHED].prot_sect |= PMD_SECT_XN;
mem_types[MT_DEVICE_WC].prot_sect |= PMD_SECT_XN;
+ mem_types[MT_DEVICE_NS].prot_sect |= PMD_SECT_XN;
/* Also setup NX memory mapping */
mem_types[MT_MEMORY_RW].prot_sect |= PMD_SECT_XN;
@@ -489,6 +497,7 @@ static void __init build_mem_type_table(void)
mem_types[MT_DEVICE].prot_sect |= PMD_SECT_TEX(1);
mem_types[MT_DEVICE_NONSHARED].prot_sect |= PMD_SECT_TEX(1);
mem_types[MT_DEVICE_WC].prot_sect |= PMD_SECT_BUFFERABLE;
+ mem_types[MT_DEVICE_NS].prot_sect |= PMD_SECT_TEX(1);
} else if (cpu_is_xsc3()) {
/*
* For Xscale3,
@@ -500,6 +509,7 @@ static void __init build_mem_type_table(void)
mem_types[MT_DEVICE].prot_sect |= PMD_SECT_TEX(1) | PMD_SECT_BUFFERED;
mem_types[MT_DEVICE_NONSHARED].prot_sect |= PMD_SECT_TEX(2);
mem_types[MT_DEVICE_WC].prot_sect |= PMD_SECT_TEX(1);
+ mem_types[MT_DEVICE_NS].prot_sect |= PMD_SECT_TEX(1) | PMD_SECT_BUFFERED;
} else {
/*
* For ARMv6 and ARMv7 without TEX remapping,
@@ -511,6 +521,7 @@ static void __init build_mem_type_table(void)
mem_types[MT_DEVICE].prot_sect |= PMD_SECT_BUFFERED;
mem_types[MT_DEVICE_NONSHARED].prot_sect |= PMD_SECT_TEX(2);
mem_types[MT_DEVICE_WC].prot_sect |= PMD_SECT_TEX(1);
+ mem_types[MT_DEVICE_NS].prot_sect |= PMD_SECT_BUFFERED;
}
} else {
/*
@@ -856,7 +867,7 @@ static void __init create_mapping(struct map_desc *md)
return;
}
- if ((md->type == MT_DEVICE || md->type == MT_ROM) &&
+ if ((md->type == MT_DEVICE || md->type == MT_DEVICE_NS || md->type == MT_ROM) &&
md->virtual >= PAGE_OFFSET &&
(md->virtual < VMALLOC_START || md->virtual >= VMALLOC_END)) {
printk(KERN_WARNING "BUG: mapping for 0x%08llx"
--
1.9.3
^ permalink raw reply related
* [PATCH RFC 4/9] ARM: dump the status of NS bit in L1 PTE
From: Daniel Thompson @ 2014-07-21 14:47 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1405954040-30399-1-git-send-email-daniel.thompson@linaro.org>
From: Marek Vasut <marex@denx.de>
Add minor adjustment to the page table dumper to also print the status
of the L1 PTE NS bit.
Signed-off-by: Marek Vasut <marex@denx.de>
---
arch/arm/mm/dump.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/arch/arm/mm/dump.c b/arch/arm/mm/dump.c
index c508f41..0100edb 100644
--- a/arch/arm/mm/dump.c
+++ b/arch/arm/mm/dump.c
@@ -176,6 +176,11 @@ static const struct prot_bits section_bits[] = {
.val = PMD_SECT_S,
.set = "SHD",
.clear = " ",
+ }, {
+ .mask = PMD_SECT_NS,
+ .val = PMD_SECT_NS,
+ .set = "NS ",
+ .clear = "ns ",
},
};
--
1.9.3
^ permalink raw reply related
* [PATCH RFC 3/9] irqchip: gic: Remove spin locks from eoi_irq
From: Daniel Thompson @ 2014-07-21 14:47 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1405954040-30399-1-git-send-email-daniel.thompson@linaro.org>
This patch is motivated by the comment it removes from gic_init_fiq,
namely that the spin locks in eoi_irq preclude certain platforms from
supporting FIQ.
Currently there is only one upstream platform (tegra) that actually
hooks gic_arch_extn.irq_eoi and it does not require these spin locks.
Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Jason Cooper <jason@lakedaemon.net>
Cc: Peter De Schrijver <pdeschrijver@nvidia.com>
---
drivers/irqchip/irq-gic.c | 12 +-----------
1 file changed, 1 insertion(+), 11 deletions(-)
diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
index d3c7559..5c934a4 100644
--- a/drivers/irqchip/irq-gic.c
+++ b/drivers/irqchip/irq-gic.c
@@ -191,11 +191,8 @@ static void gic_unmask_irq(struct irq_data *d)
static void gic_eoi_irq(struct irq_data *d)
{
- if (gic_arch_extn.irq_eoi) {
- raw_spin_lock(&irq_controller_lock);
+ if (gic_arch_extn.irq_eoi)
gic_arch_extn.irq_eoi(d);
- raw_spin_unlock(&irq_controller_lock);
- }
writel_relaxed(gic_irq(d), gic_cpu_base(d) + GIC_CPU_EOI);
}
@@ -437,13 +434,6 @@ static void __init gic_init_fiq(struct gic_chip_data *gic,
unsigned int i;
/*
- * FIQ can only be supported on platforms without an extended irq_eoi
- * method (otherwise we take a lock during eoi handling).
- */
- if (gic_arch_extn.irq_eoi)
- return;
-
- /*
* If grouping is not available (not implemented or prohibited by
* security mode) these registers a read-as-zero/write-ignored.
* However as a precaution we restore the reset default regardless of
--
1.9.3
^ permalink raw reply related
* [PATCH RFC 2/9] irqchip: gic: Add support for FIQ management
From: Daniel Thompson @ 2014-07-21 14:47 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1405954040-30399-1-git-send-email-daniel.thompson@linaro.org>
This patch introduces callbacks to route interrupts to or away
from the FIQ signal and registers these callbacks with the FIQ
infrastructure (if the device can supports it).
Both these aspects combine and allow a driver to deploy a FIQ handler
without any machine specific knowledge; it can be used effectively on
multi-platform kernels.
Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Jason Cooper <jason@lakedaemon.net>
Cc: Nicolas Pitre <nicolas.pitre@linaro.org>
Cc: Christoffer Dall <christoffer.dall@linaro.org>
Cc: Sricharan R <r.sricharan@ti.com>
---
drivers/irqchip/irq-gic.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 69 insertions(+)
diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
index bbffca3..d3c7559 100644
--- a/drivers/irqchip/irq-gic.c
+++ b/drivers/irqchip/irq-gic.c
@@ -366,6 +366,69 @@ static struct irq_chip gic_chip = {
};
#ifdef CONFIG_FIQ
+/*
+ * Shift an interrupt between Group 0 and Group 1.
+ *
+ * In addition to changing the group we also modify the priority to
+ * match what "ARM strongly recommends" for a system where no Group 1
+ * interrupt must ever preempt a Group 0 interrupt.
+ */
+static void gic_set_group_irq(struct irq_data *d, int group)
+{
+ unsigned int grp_reg = gic_irq(d) / 32 * 4;
+ u32 grp_mask = 1 << (gic_irq(d) % 32);
+ u32 grp_val;
+
+ unsigned int pri_reg = (gic_irq(d) / 4) * 4;
+ u32 pri_mask = 1 << (7 + ((gic_irq(d) % 4) * 8));
+ u32 pri_val;
+
+ raw_spin_lock(&irq_controller_lock);
+
+ grp_val = readl_relaxed(gic_dist_base(d) + GIC_DIST_IGROUP + grp_reg);
+ pri_val = readl_relaxed(gic_dist_base(d) + GIC_DIST_PRI + pri_reg);
+
+ if (group) {
+ grp_val |= grp_mask;
+ pri_val |= pri_mask;
+ } else {
+ grp_val &= ~grp_mask;
+ pri_val &= ~pri_mask;
+ }
+
+ writel_relaxed(grp_val, gic_dist_base(d) + GIC_DIST_IGROUP + grp_reg);
+ writel_relaxed(pri_val, gic_dist_base(d) + GIC_DIST_PRI + pri_reg);
+
+ raw_spin_unlock(&irq_controller_lock);
+}
+
+static void gic_enable_fiq(struct irq_data *d)
+{
+ gic_set_group_irq(d, 0);
+}
+
+static void gic_disable_fiq(struct irq_data *d)
+{
+ gic_set_group_irq(d, 1);
+}
+
+static int gic_ack_fiq(struct irq_data *d)
+{
+ struct gic_chip_data *gic = irq_data_get_irq_chip_data(d);
+ u32 irqstat, irqnr;
+
+ irqstat = readl_relaxed(gic_data_cpu_base(gic) + GIC_CPU_INTACK);
+ irqnr = irqstat & GICC_IAR_INT_ID_MASK;
+ return irq_find_mapping(gic->domain, irqnr);
+}
+
+static struct fiq_chip gic_fiq = {
+ .fiq_enable = gic_enable_fiq,
+ .fiq_disable = gic_disable_fiq,
+ .fiq_ack = gic_ack_fiq,
+ .fiq_eoi = gic_eoi_irq,
+};
+
static void __init gic_init_fiq(struct gic_chip_data *gic,
irq_hw_number_t first_irq,
unsigned int num_irqs)
@@ -394,6 +457,12 @@ static void __init gic_init_fiq(struct gic_chip_data *gic,
if (!gic->fiq_enable)
return;
+
+ /*
+ * FIQ is supported on this device! Register our chip data.
+ */
+ for (i = 0; i < num_irqs; i++)
+ fiq_register_mapping(first_irq + i, &gic_fiq);
}
#else /* CONFIG_FIQ */
static inline void gic_init_fiq(struct gic_chip_data *gic,
--
1.9.3
^ permalink raw reply related
* [PATCH RFC 1/9] irqchip: gic: Provide support for interrupt grouping
From: Daniel Thompson @ 2014-07-21 14:47 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1405954040-30399-1-git-send-email-daniel.thompson@linaro.org>
All GIC hardware except GICv1-without-TrustZone support provides a means
to group exceptions into group 0 (which can optionally be signally using
use FIQ) and group 1. The kernel currently provides no means to exploit
this. This patch alters the initialization of the GIC to place all
interrupts into group 1 which is the foundational requirement to meaningfully
use FIQ.
Note that the hardware functionality is unavailable to the kernel when a
secure monitor is present because access to the grouping registers are
prohibited outside "secure world" (this feature allows grouping to be
used to allow hardware peripherals to send interrupts into the secure
world). The GIC driver will automatically detect this and disable its
attempts to group interrupts.
On systems without TrustZone support the kernel has the power to route
interrupt sources to FIQ, potentially allowing a driver to exploit the
NMI-like properties of FIQ.
Tested on Freescale i.MX6 (quad A9), STiH416 (dual A9) and a self-written
qemu GICv2 model.
Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Jason Cooper <jason@lakedaemon.net>
Cc: Nicolas Pitre <nicolas.pitre@linaro.org>
Cc: Christoffer Dall <christoffer.dall@linaro.org>
Cc: Sricharan R <r.sricharan@ti.com>
Acked-by: Dirk Behme <dirk.behme@de.bosch.com>
---
drivers/irqchip/irq-gic.c | 99 ++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 94 insertions(+), 5 deletions(-)
diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
index 7e11c9d..bbffca3 100644
--- a/drivers/irqchip/irq-gic.c
+++ b/drivers/irqchip/irq-gic.c
@@ -42,6 +42,9 @@
#include <linux/irqchip/chained_irq.h>
#include <linux/irqchip/arm-gic.h>
+#ifdef CONFIG_FIQ
+#include <asm/fiq.h>
+#endif
#include <asm/irq.h>
#include <asm/exception.h>
#include <asm/smp_plat.h>
@@ -68,6 +71,9 @@ struct gic_chip_data {
#ifdef CONFIG_GIC_NON_BANKED
void __iomem *(*get_base)(union gic_base *);
#endif
+#ifdef CONFIG_FIQ
+ bool fiq_enable;
+#endif
};
static DEFINE_RAW_SPINLOCK(irq_controller_lock);
@@ -131,6 +137,16 @@ static inline void gic_set_base_accessor(struct gic_chip_data *data,
#define gic_set_base_accessor(d, f)
#endif
+#ifdef CONFIG_FIQ
+static inline bool gic_data_fiq_enable(struct gic_chip_data *data)
+{
+ return data->fiq_enable;
+}
+#else
+static inline bool gic_data_fiq_enable(
+ struct gic_chip_data *data) { return false; }
+#endif
+
static inline void __iomem *gic_dist_base(struct irq_data *d)
{
struct gic_chip_data *gic_data = irq_data_get_irq_chip_data(d);
@@ -349,6 +365,42 @@ static struct irq_chip gic_chip = {
.irq_set_wake = gic_set_wake,
};
+#ifdef CONFIG_FIQ
+static void __init gic_init_fiq(struct gic_chip_data *gic,
+ irq_hw_number_t first_irq,
+ unsigned int num_irqs)
+{
+ void __iomem *dist_base = gic_data_dist_base(gic_data);
+ unsigned int i;
+
+ /*
+ * FIQ can only be supported on platforms without an extended irq_eoi
+ * method (otherwise we take a lock during eoi handling).
+ */
+ if (gic_arch_extn.irq_eoi)
+ return;
+
+ /*
+ * If grouping is not available (not implemented or prohibited by
+ * security mode) these registers a read-as-zero/write-ignored.
+ * However as a precaution we restore the reset default regardless of
+ * the result of the test.
+ */
+ writel_relaxed(1, dist_base + GIC_DIST_IGROUP + 0);
+ gic->fiq_enable = readl_relaxed(dist_base + GIC_DIST_IGROUP + 0);
+ writel_relaxed(0, dist_base + GIC_DIST_IGROUP + 0);
+ pr_debug("gic: FIQ support %s\n",
+ gic->fiq_enable ? "enabled" : "disabled");
+
+ if (!gic->fiq_enable)
+ return;
+}
+#else /* CONFIG_FIQ */
+static inline void gic_init_fiq(struct gic_chip_data *gic,
+ irq_hw_number_t first_irq,
+ unsigned int num_irqs) {}
+#endif /* CONFIG_FIQ */
+
void __init gic_cascade_irq(unsigned int gic_nr, unsigned int irq)
{
if (gic_nr >= MAX_GIC_NR)
@@ -408,13 +460,28 @@ static void __init gic_dist_init(struct gic_chip_data *gic)
writel_relaxed(0xa0a0a0a0, base + GIC_DIST_PRI + i * 4 / 4);
/*
+ * Optionally set all global interrupts to be group 1.
+ */
+ if (gic_data_fiq_enable(gic))
+ for (i = 32; i < gic_irqs; i += 32)
+ writel_relaxed(0xffffffff,
+ base + GIC_DIST_IGROUP + i * 4 / 32);
+
+ /*
* Disable all interrupts. Leave the PPI and SGIs alone
* as these enables are banked registers.
*/
for (i = 32; i < gic_irqs; i += 32)
writel_relaxed(0xffffffff, base + GIC_DIST_ENABLE_CLEAR + i * 4 / 32);
- writel_relaxed(1, base + GIC_DIST_CTRL);
+ /*
+ * Set EnableGrp1/EnableGrp0 (bit 1 and 0) or EnableGrp (bit 0 only,
+ * bit 1 ignored)
+ */
+ if (gic_data_fiq_enable(gic))
+ writel_relaxed(3, base + GIC_DIST_CTRL);
+ else
+ writel_relaxed(1, base + GIC_DIST_CTRL);
}
static void gic_cpu_init(struct gic_chip_data *gic)
@@ -452,8 +519,20 @@ static void gic_cpu_init(struct gic_chip_data *gic)
for (i = 0; i < 32; i += 4)
writel_relaxed(0xa0a0a0a0, dist_base + GIC_DIST_PRI + i * 4 / 4);
+ /*
+ * Set all PPI and SGI interrupts to be group 1.
+ *
+ * If grouping is not available (not implemented or prohibited by
+ * security mode) these registers are read-as-zero/write-ignored.
+ */
+ if (gic_data_fiq_enable(gic))
+ writel_relaxed(0xffffffff, dist_base + GIC_DIST_IGROUP + 0);
+
writel_relaxed(0xf0, base + GIC_CPU_PRIMASK);
- writel_relaxed(1, base + GIC_CPU_CTRL);
+ if (gic_data_fiq_enable(gic))
+ writel_relaxed(0x1f, base + GIC_CPU_CTRL);
+ else
+ writel_relaxed(1, base + GIC_CPU_CTRL);
}
void gic_cpu_if_down(void)
@@ -537,7 +616,10 @@ static void gic_dist_restore(unsigned int gic_nr)
writel_relaxed(gic_data[gic_nr].saved_spi_enable[i],
dist_base + GIC_DIST_ENABLE_SET + i * 4);
- writel_relaxed(1, dist_base + GIC_DIST_CTRL);
+ if (gic_data_fiq_enable(&gic_data[gic_nr]))
+ writel_relaxed(3, dist_base + GIC_DIST_CTRL);
+ else
+ writel_relaxed(1, dist_base + GIC_DIST_CTRL);
}
static void gic_cpu_save(unsigned int gic_nr)
@@ -594,7 +676,7 @@ static void gic_cpu_restore(unsigned int gic_nr)
writel_relaxed(0xa0a0a0a0, dist_base + GIC_DIST_PRI + i * 4);
writel_relaxed(0xf0, cpu_base + GIC_CPU_PRIMASK);
- writel_relaxed(1, cpu_base + GIC_CPU_CTRL);
+ writel_relaxed(0x1f, cpu_base + GIC_CPU_CTRL);
}
static int gic_notifier(struct notifier_block *self, unsigned long cmd, void *v)
@@ -656,6 +738,7 @@ static void gic_raise_softirq(const struct cpumask *mask, unsigned int irq)
{
int cpu;
unsigned long flags, map = 0;
+ unsigned long softint;
raw_spin_lock_irqsave(&irq_controller_lock, flags);
@@ -670,7 +753,11 @@ static void gic_raise_softirq(const struct cpumask *mask, unsigned int irq)
dmb(ishst);
/* this always happens on GIC0 */
- writel_relaxed(map << 16 | irq, gic_data_dist_base(&gic_data[0]) + GIC_DIST_SOFTINT);
+ softint = map << 16 | irq;
+ if (gic_data_fiq_enable(&gic_data[0]))
+ softint |= 0x8000;
+ writel_relaxed(softint,
+ gic_data_dist_base(&gic_data[0]) + GIC_DIST_SOFTINT);
raw_spin_unlock_irqrestore(&irq_controller_lock, flags);
}
@@ -1014,6 +1101,8 @@ void __init gic_init_bases(unsigned int gic_nr, int irq_start,
gic->domain = irq_domain_add_legacy(node, gic_irqs, irq_base,
hwirq_base, &gic_irq_domain_ops, gic);
+
+ gic_init_fiq(gic, irq_base, gic_irqs);
} else {
gic->domain = irq_domain_add_linear(node, nr_routable_irqs,
&gic_irq_domain_ops,
--
1.9.3
^ permalink raw reply related
* [PATCH RFC 0/9] Fix INTACK for FIQ support on ARM Cortex A9
From: Daniel Thompson @ 2014-07-21 14:47 UTC (permalink / raw)
To: linux-arm-kernel
Users of the recently proposed extensions to the FIQ infrastructure
have reported a problem which causes the interrupt dispatcher in
irq-gic.c (running as a normal IRQ handler) to try to acknowledge
group 0 interrupts (group 0 should raise FIQ).
The problem occurs because the GICv1 found in Cortex A9 implementations
explicitly uses the security state (normal or trusted world) to
determine whether the interrupt controller should acknowledge group 0
interrupts. For FIQ to be useful as an NMI on Cortex A9 the kernel must
run in in trusted world hence by default the GIC allows the CPU to
acknowledge group 0 interrupts.
Two workarounds have been proposed, one which retrospectively corrects
the problem if it is observed and one which uses the ARM MMU section
flags to ensure the GIC driver can read INTACK from the current security
context. The later workaround, which is both more invasive and higher
performance[1], is presented in this patchset.
This patchset depends upon my own patchset for ARM providing additional
FIQ infrastructure but does contain the changes to the GIC driver
required to support FIQ. The effect of this is that workaround code
is found primarily in patches 5, 6 and 7.
[1]
http://thread.gmane.org/gmane.linux.ports.arm.kernel/331027/focus=1748892
Daniel Thompson (6):
irqchip: gic: Provide support for interrupt grouping
irqchip: gic: Add support for FIQ management
irqchip: gic: Remove spin locks from eoi_irq
arm: mm: Avoid ioremap_page_range() for non-secure mappings
irqchip: gic: Use non-secure aliased register set when FIQ is enabled
arm: imx: non-secure aliased mapping of GIC registers
Marek Vasut (3):
ARM: dump the status of NS bit in L1 PTE
ARM: Add L1 PTE non-secure mapping
ARM: socfpga: Map the GIC CPU registers as MT_DEVICE_NS
arch/arm/include/asm/io.h | 5 +-
arch/arm/include/asm/mach/map.h | 4 +-
arch/arm/include/asm/pgtable-2level-hwdef.h | 1 +
arch/arm/mach-imx/mach-imx6q.c | 11 ++
arch/arm/mach-socfpga/socfpga.c | 8 +
arch/arm/mm/dump.c | 5 +
arch/arm/mm/ioremap.c | 4 +
arch/arm/mm/mmu.c | 13 +-
drivers/irqchip/irq-gic.c | 240 ++++++++++++++++++++++++++--
include/linux/irqchip/arm-gic.h | 4 +-
10 files changed, 273 insertions(+), 22 deletions(-)
--
1.9.3
^ permalink raw reply
* [PATCH RESEND 1/2] clocksource: Add CLPS711X clocksource driver
From: Daniel Lezcano @ 2014-07-21 14:46 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1405226713-5080-1-git-send-email-shc_work@mail.ru>
On 07/13/2014 06:45 AM, Alexander Shiyan wrote:
> This adds the clocksource driver for Cirrus Logic CLPS711X series SoCs.
> Designed primarily for migration CLPS711X subarch for multiplatform & DT,
> for this as the "OF" and "non-OF" calls implemented.
>
> Signed-off-by: Alexander Shiyan <shc_work@mail.ru>
> Acked-by: Arnd Bergmann <arnd@arndb.de>
> ---
Both patches applied to my tree for 3.17
Thanks
-- Daniel
--
<http://www.linaro.org/> Linaro.org ? Open source software for ARM SoCs
Follow Linaro: <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog
^ permalink raw reply
* [PATCH 1/5] rtc: sun6i: Add sun6i RTC driver
From: Chen-Yu Tsai @ 2014-07-21 14:46 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140718080718.GI20328@lukather>
Hi,
On Fri, Jul 18, 2014 at 4:07 PM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> Hi,
>
> On Mon, Jul 14, 2014 at 03:32:13PM +0800, Chen-Yu Tsai wrote:
>> This patch introduces the driver for the RTC in the Allwinner A31 and
>> A23 SoCs.
>>
>> Unlike the RTC found in A10/A20 SoCs, which was part of the timer, the
>> RTC in A31/A23 are a separate hardware block, which also contain a few
>> controls for the RTC block hardware (a regulator and RTC block GPIO pin
>> latches), while also having separate interrupts for the alarms.
>
> Do you plan on supporting those at some point?
I haven't seen any devices use the regulator (which has an output pin).
I suppose we shouldn't add drivers for things we can't verify.
As for the GPIO pin latches, I'll have to experiment some more to figure
out what they do exactly.
> It's also worth noting that the first registers are supposed to
> control the source of the low frequency oscillator in the SoC, which
> will probably be the most troublesome, since we need these clocks very
> early on.
That's true. I suppose the bootloader configures this. IIRC I've seen
code for this in boot0 or boot1 from Allwinner. I can't find the equivalent
for our sun4i u-boot though.
>>
>> The hardware is different enough to make a different driver for it.
>>
>> Signed-off-by: Chen-Yu Tsai <wens@csie.org>
>> ---
>> .../devicetree/bindings/rtc/sun6i-rtc.txt | 17 +
>> drivers/rtc/Kconfig | 7 +
>> drivers/rtc/Makefile | 1 +
>> drivers/rtc/rtc-sun6i.c | 466 +++++++++++++++++++++
>> 4 files changed, 491 insertions(+)
>> create mode 100644 Documentation/devicetree/bindings/rtc/sun6i-rtc.txt
>> create mode 100644 drivers/rtc/rtc-sun6i.c
>>
>> diff --git a/Documentation/devicetree/bindings/rtc/sun6i-rtc.txt b/Documentation/devicetree/bindings/rtc/sun6i-rtc.txt
>> new file mode 100644
>> index 0000000..b18927c
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/rtc/sun6i-rtc.txt
>> @@ -0,0 +1,17 @@
>> +* sun6i Real Time Clock
>> +
>> +RTC controller for the Allwinner A31
>> +
>> +Required properties:
>> +- compatible : Should be "allwinner,sun6i-a31-rtc"
>> +- reg: physical base address of the controller and length of memory mapped
>> + region.
>> +- interrupts: IRQ line for the RTC alarm 0.
>> +
>> +Example:
>> +
>> +rtc: rtc at 01f00000 {
>> + compatible = "allwinner,sun6i-a31-rtc";
>> + reg = <0x01f00000 0x54>;
>> + interrupts = <0 40 4>;
>> +};
>> diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
>> index 0754f5c..5b3910a 100644
>> --- a/drivers/rtc/Kconfig
>> +++ b/drivers/rtc/Kconfig
>> @@ -1167,6 +1167,13 @@ config RTC_DRV_SUN4V
>> If you say Y here you will get support for the Hypervisor
>> based RTC on SUN4V systems.
>>
>> +config RTC_DRV_SUN6I
>> + tristate "Allwinner sun6i/sun8i RTC"
>
> I'm half convinced about an exhaustive list here. That IP will also
> probably be used by sun9i, and sun10i if it ever exists, etc. And you
> exhaustive list won't be anymore.
>
> I'd rather just mention the A31, like we do for the DT.
Fixed.
>> + depends on MACH_SUN6I || MACH_SUN8I
>> + help
>> + If you say Y here you will get support for the RTC found on
>> + Allwinner A31/A23.
>> +
>> config RTC_DRV_SUNXI
>> tristate "Allwinner sun4i/sun7i RTC"
>> depends on ARCH_SUNXI
>> diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
>> index 70347d0..a47df29 100644
>> --- a/drivers/rtc/Makefile
>> +++ b/drivers/rtc/Makefile
>> @@ -123,6 +123,7 @@ obj-$(CONFIG_RTC_DRV_STARFIRE) += rtc-starfire.o
>> obj-$(CONFIG_RTC_DRV_STK17TA8) += rtc-stk17ta8.o
>> obj-$(CONFIG_RTC_DRV_STMP) += rtc-stmp3xxx.o
>> obj-$(CONFIG_RTC_DRV_SUN4V) += rtc-sun4v.o
>> +obj-$(CONFIG_RTC_DRV_SUN6I) += rtc-sun6i.o
>> obj-$(CONFIG_RTC_DRV_SUNXI) += rtc-sunxi.o
>> obj-$(CONFIG_RTC_DRV_TEGRA) += rtc-tegra.o
>> obj-$(CONFIG_RTC_DRV_TEST) += rtc-test.o
>> diff --git a/drivers/rtc/rtc-sun6i.c b/drivers/rtc/rtc-sun6i.c
>> new file mode 100644
>> index 0000000..fabd019
>> --- /dev/null
>> +++ b/drivers/rtc/rtc-sun6i.c
>> @@ -0,0 +1,466 @@
>> +/*
>> + * An RTC driver for Allwinner A31/A23
>> + *
>> + * Copyright (c) 2014, Chen-Yu Tsai <wens@csie.org>
>> + *
>> + * based on rtc-sunxi.c
>> + *
>> + * An RTC driver for Allwinner A10/A20
>> + *
>> + * Copyright (c) 2013, Carlo Caione <carlo.caione@gmail.com>
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License as published by
>> + * the Free Software Foundation; either version 2 of the License, or
>> + * (at your option) any later version.
>> + *
>> + * This program is distributed in the hope that it will be useful, but WITHOUT
>> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
>> + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
>> + * more details.
>> + */
>> +
>> +#include <linux/delay.h>
>> +#include <linux/err.h>
>> +#include <linux/fs.h>
>> +#include <linux/init.h>
>> +#include <linux/interrupt.h>
>> +#include <linux/io.h>
>> +#include <linux/kernel.h>
>> +#include <linux/module.h>
>> +#include <linux/of.h>
>> +#include <linux/of_address.h>
>> +#include <linux/of_device.h>
>> +#include <linux/platform_device.h>
>> +#include <linux/rtc.h>
>> +#include <linux/types.h>
>> +
>> +/* Control register */
>> +#define SUN6I_LOSC_CTRL 0x0000
>> +#define SUN6I_LOSC_CTRL_ALM_DHMS_ACC BIT(9)
>> +#define SUN6I_LOSC_CTRL_RTC_HMS_ACC BIT(8)
>> +#define SUN6I_LOSC_CTRL_RTC_YMD_ACC BIT(7)
>> +#define SUN6I_LOSC_CTRL_ACC_MASK (BIT(9) | BIT(8) | BIT(7))
>
> GENMASK maybe?
Fixed
>> +
>> +/* RTC */
>> +#define SUN6I_RTC_YMD 0x0010
>> +#define SUN6I_RTC_HMS 0x0014
>> +
>> +/* Alarm 0 (counter) */
>> +#define SUN6I_ALRM_COUNTER 0x0020
>> +#define SUN6I_ALRM_CUR_VAL 0x0024
>> +#define SUN6I_ALRM_EN 0x0028
>> +#define SUN6I_ALRM_EN_CNT_EN BIT(0)
>> +#define SUN6I_ALRM_IRQ_EN 0x002c
>> +#define SUN6I_ALRM_IRQ_EN_CNT_IRQ_EN BIT(0)
>> +#define SUN6I_ALRM_IRQ_STA 0x0030
>> +#define SUN6I_ALRM_IRQ_STA_CNT_IRQ_PEND BIT(0)
>> +
>> +/* Alarm 1 (wall clock) */
>> +#define SUN6I_ALRM1_EN 0x0044
>> +#define SUN6I_ALRM1_IRQ_EN 0x0048
>> +#define SUN6I_ALRM1_IRQ_STA 0x004c
>> +#define SUN6I_ALRM1_IRQ_STA_WEEK_IRQ_PEND BIT(0)
>> +
>> +/* Alarm config */
>> +#define SUN6I_ALARM_CONFIG 0x0050
>> +#define SUN6I_ALARM_CONFIG_WAKEUP BIT(0)
>> +
>> +/* days / hours are 5 bit wide */
>> +#define SUN6I_MASK_DH 0x0000001f
>> +/* seconds / minutes / years are 6 bit wide */
>> +#define SUN6I_MASK_SMY 0x0000003f
>> +/* months are 4 bit wide */
>> +#define SUN6I_MASK_M 0x0000000f
>> +/* leap year is single bit */
>> +#define SUN6I_MASK_LY 0x00000001
>
> Ditto
See below.
>> +
>> +#define SUN6I_GET(x, mask, shift) (((x) & ((mask) << (shift))) \
>> + >> (shift))
>> +
>> +#define SUN6I_SET(x, mask, shift) (((x) & (mask)) << (shift))
>
> Wouldn't it be easier to have the mask already shifted?
I'll just get rid of these 2 and the masks above, and inline them
(in hex format) in the GET/SET macros below. How does that sound?
>> +
>> +/*
>> + * Get date values
>> + */
>> +#define SUN6I_DATE_GET_DAY_VALUE(x) SUN6I_GET(x, SUN6I_MASK_DH, 0)
>> +#define SUN6I_DATE_GET_MON_VALUE(x) SUN6I_GET(x, SUN6I_MASK_M, 8)
>> +#define SUN6I_DATE_GET_YEAR_VALUE(x) SUN6I_GET(x, SUN6I_MASK_SMY, 16)
>> +
>> +/*
>> + * Get time values
>> + */
>> +#define SUN6I_TIME_GET_SEC_VALUE(x) SUN6I_GET(x, SUN6I_MASK_SMY, 0)
>> +#define SUN6I_TIME_GET_MIN_VALUE(x) SUN6I_GET(x, SUN6I_MASK_SMY, 8)
>> +#define SUN6I_TIME_GET_HOUR_VALUE(x) SUN6I_GET(x, SUN6I_MASK_DH, 16)
>> +
>> +/*
>> + * Set date values
>> + */
>> +#define SUN6I_DATE_SET_DAY_VALUE(x) SUN6I_DATE_GET_DAY_VALUE(x)
>> +#define SUN6I_DATE_SET_MON_VALUE(x) SUN6I_SET(x, SUN6I_MASK_M, 8)
>> +#define SUN6I_DATE_SET_YEAR_VALUE(x) SUN6I_SET(x, SUN6I_MASK_SMY, 16)
>> +#define SUN6I_LEAP_SET_VALUE(x) SUN6I_SET(x, SUN6I_MASK_LY, 22)
>> +
>> +/*
>> + * Set time values
>> + */
>> +#define SUN6I_TIME_SET_SEC_VALUE(x) SUN6I_TIME_GET_SEC_VALUE(x)
>> +#define SUN6I_TIME_SET_MIN_VALUE(x) SUN6I_SET(x, SUN6I_MASK_SMY, 8)
>> +#define SUN6I_TIME_SET_HOUR_VALUE(x) SUN6I_SET(x, SUN6I_MASK_DH, 16)
>> +
>> +/*
>> + * The year parameter passed to the driver is usually an offset relative to
>> + * the year 1900. This macro is used to convert this offset to another one
>> + * relative to the minimum year allowed by the hardware.
>> + *
>> + * The year range is 1970 - 2033. This range is selected to match Allwinner's
>> + * driver, even though it is somewhat limited.
>> + */
>> +#define SUN6I_YEAR_MIN 1970
>> +#define SUN6I_YEAR_MAX 2033
>> +#define SUN6I_YEAR_OFF (SUN6I_YEAR_MIN - 1900)
>> +
>> +struct sun6i_rtc_dev {
>> + struct rtc_device *rtc;
>> + struct device *dev;
>> + void __iomem *base;
>> + int irq;
>> + unsigned long alarm;
>> +};
>> +
>> +static irqreturn_t sun6i_rtc_alarmirq(int irq, void *id)
>> +{
>> + struct sun6i_rtc_dev *chip = (struct sun6i_rtc_dev *) id;
>> + u32 val;
>> +
>> + val = readl(chip->base + SUN6I_ALRM_IRQ_STA);
>> +
>> + if (val & SUN6I_ALRM_IRQ_STA_CNT_IRQ_PEND) {
>> + val |= SUN6I_ALRM_IRQ_STA_CNT_IRQ_PEND;
>> + writel(val, chip->base + SUN6I_ALRM_IRQ_STA);
>> +
>> + rtc_update_irq(chip->rtc, 1, RTC_AF | RTC_IRQF);
>> +
>> + return IRQ_HANDLED;
>> + }
>> +
>> + return IRQ_NONE;
>> +}
>> +
>> +static void sun6i_rtc_setaie(int to, struct sun6i_rtc_dev *chip)
>> +{
>> + u32 alrm_val = 0;
>> + u32 alrm_irq_val = 0;
>> + u32 alrm_wake_val = 0;
>> +
>> + if (to) {
>> + alrm_val = SUN6I_ALRM_EN_CNT_EN;
>> + alrm_irq_val = SUN6I_ALRM_IRQ_EN_CNT_IRQ_EN;
>> + alrm_wake_val = SUN6I_ALARM_CONFIG_WAKEUP;
>> + } else {
>> + writel(SUN6I_ALRM_IRQ_STA_CNT_IRQ_PEND,
>> + chip->base + SUN6I_ALRM_IRQ_STA);
>> + }
>> +
>> + writel(alrm_val, chip->base + SUN6I_ALRM_EN);
>> + writel(alrm_irq_val, chip->base + SUN6I_ALRM_IRQ_EN);
>> + writel(alrm_wake_val, chip->base + SUN6I_ALARM_CONFIG);
>> +}
>> +
>> +static int sun6i_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)
>> +{
>> + struct sun6i_rtc_dev *chip = dev_get_drvdata(dev);
>> + u32 date, time;
>> +
>> + /*
>> + * read again in case it changes
>> + */
>> + do {
>> + date = readl(chip->base + SUN6I_RTC_YMD);
>> + time = readl(chip->base + SUN6I_RTC_HMS);
>> + } while ((date != readl(chip->base + SUN6I_RTC_YMD)) ||
>> + (time != readl(chip->base + SUN6I_RTC_HMS)));
>> +
>> + rtc_tm->tm_sec = SUN6I_TIME_GET_SEC_VALUE(time);
>> + rtc_tm->tm_min = SUN6I_TIME_GET_MIN_VALUE(time);
>> + rtc_tm->tm_hour = SUN6I_TIME_GET_HOUR_VALUE(time);
>> +
>> + rtc_tm->tm_mday = SUN6I_DATE_GET_DAY_VALUE(date);
>> + rtc_tm->tm_mon = SUN6I_DATE_GET_MON_VALUE(date);
>> + rtc_tm->tm_year = SUN6I_DATE_GET_YEAR_VALUE(date);
>> +
>> + rtc_tm->tm_mon -= 1;
>> +
>> + /*
>> + * switch from (data_year->min)-relative offset to
>> + * a (1900)-relative one
>> + */
>
> I guess the reference to the structure field is not relevant anymore
Removed.
>> + rtc_tm->tm_year += SUN6I_YEAR_OFF;
>> +
>> + return rtc_valid_tm(rtc_tm);
>> +}
>> +
>> +static int sun6i_rtc_getalarm(struct device *dev, struct rtc_wkalrm *wkalrm)
>> +{
>> + struct sun6i_rtc_dev *chip = dev_get_drvdata(dev);
>> + u32 alrm_st;
>> + u32 alrm_en;
>> +
>> + alrm_en = readl(chip->base + SUN6I_ALRM_IRQ_EN);
>> + alrm_st = readl(chip->base + SUN6I_ALRM_IRQ_STA);
>> + wkalrm->enabled = !!(alrm_en & SUN6I_ALRM_EN_CNT_EN);
>> + wkalrm->pending = !!(alrm_st & SUN6I_ALRM_EN_CNT_EN);
>> + rtc_time_to_tm(chip->alarm, &wkalrm->time);
>> +
>> + return 0;
>> +}
>> +
>> +static int sun6i_rtc_setalarm(struct device *dev, struct rtc_wkalrm *wkalrm)
>> +{
>> + struct sun6i_rtc_dev *chip = dev_get_drvdata(dev);
>> + struct rtc_time *alrm_tm = &wkalrm->time;
>> + struct rtc_time tm_now;
>> + unsigned long time_now = 0;
>> + unsigned long time_set = 0;
>> + unsigned long time_gap = 0;
>> + int ret = 0;
>> +
>> + ret = sun6i_rtc_gettime(dev, &tm_now);
>> + if (ret < 0) {
>> + dev_err(dev, "Error in getting time\n");
>> + return -EINVAL;
>> + }
>> +
>> + rtc_tm_to_time(alrm_tm, &time_set);
>> + rtc_tm_to_time(&tm_now, &time_now);
>> + if (time_set <= time_now) {
>> + dev_err(dev, "Date to set in the past\n");
>> + return -EINVAL;
>> + }
>> +
>> + time_gap = time_set - time_now;
>> +
>> + if (time_gap > U32_MAX) {
>> + dev_err(dev, "Date too far in the future\n");
>> + return -EINVAL;
>> + }
>> +
>> + sun6i_rtc_setaie(0, chip);
>> + writel(0, chip->base + SUN6I_ALRM_COUNTER);
>> + usleep_range(100, 300);
>> +
>> + writel(time_gap, chip->base + SUN6I_ALRM_COUNTER);
>> + chip->alarm = time_set;
>> +
>> + sun6i_rtc_setaie(wkalrm->enabled, chip);
>> +
>> + return 0;
>> +}
>> +
>> +static int sun6i_rtc_wait(struct sun6i_rtc_dev *chip, int offset,
>> + unsigned int mask, unsigned int ms_timeout)
>> +{
>> + const unsigned long timeout = jiffies + msecs_to_jiffies(ms_timeout);
>> + u32 reg;
>> +
>> + do {
>> + reg = readl(chip->base + offset);
>> + reg &= mask;
>> +
>> + if (!reg)
>> + return 0;
>> +
>> + } while (time_before(jiffies, timeout));
>> +
>> + return -ETIMEDOUT;
>> +}
>> +
>> +static int sun6i_rtc_settime(struct device *dev, struct rtc_time *rtc_tm)
>> +{
>> + struct sun6i_rtc_dev *chip = dev_get_drvdata(dev);
>> + u32 date = 0;
>> + u32 time = 0;
>> + int year;
>> +
>> + /*
>> + * the input rtc_tm->tm_year is the offset relative to 1900. We use
>> + * the SUN6I_YEAR_OFF macro to rebase it with respect to the min year
>> + * allowed by the hardware
>> + */
>> +
>> + year = rtc_tm->tm_year + 1900;
>> + if (year < SUN6I_YEAR_MIN || year > SUN6I_YEAR_MAX) {
>> + dev_err(dev, "rtc only supports year in range %d - %d\n",
>> + SUN6I_YEAR_MIN, SUN6I_YEAR_MAX);
>> + return -EINVAL;
>> + }
>> +
>> + rtc_tm->tm_year -= SUN6I_YEAR_OFF;
>> + rtc_tm->tm_mon += 1;
>> +
>> + date = SUN6I_DATE_SET_DAY_VALUE(rtc_tm->tm_mday) |
>> + SUN6I_DATE_SET_MON_VALUE(rtc_tm->tm_mon) |
>> + SUN6I_DATE_SET_YEAR_VALUE(rtc_tm->tm_year);
>> +
>> + if (is_leap_year(year))
>> + date |= SUN6I_LEAP_SET_VALUE(1);
>> +
>> + time = SUN6I_TIME_SET_SEC_VALUE(rtc_tm->tm_sec) |
>> + SUN6I_TIME_SET_MIN_VALUE(rtc_tm->tm_min) |
>> + SUN6I_TIME_SET_HOUR_VALUE(rtc_tm->tm_hour);
>> +
>> + /* Check whether registers are writable */
>> + if (sun6i_rtc_wait(chip, SUN6I_LOSC_CTRL,
>> + SUN6I_LOSC_CTRL_ACC_MASK, 50)) {
>> + dev_err(dev, "rtc is still busy.\n");
>> + return -EBUSY;
>> + }
>> +
>> + writel(time, chip->base + SUN6I_RTC_HMS);
>> +
>> + /*
>> + * After writing the RTC HH-MM-SS register, the
>> + * SUN6I_LOSC_CTRL_RTC_HMS_ACC bit is set and it will not
>> + * be cleared until the real writing operation is finished
>> + */
>> +
>> + if (sun6i_rtc_wait(chip, SUN6I_LOSC_CTRL,
>> + SUN6I_LOSC_CTRL_RTC_HMS_ACC, 50)) {
>> + dev_err(dev, "Failed to set rtc time.\n");
>> + return -ETIMEDOUT;
>> + }
>> +
>> + writel(date, chip->base + SUN6I_RTC_YMD);
>> +
>> + /*
>> + * After writing the RTC YY-MM-DD register, the
>> + * SUN6I_LOSC_CTRL_RTC_YMD_ACC bit is set and it will not
>> + * be cleared until the real writing operation is finished
>> + */
>> +
>> + if (sun6i_rtc_wait(chip, SUN6I_LOSC_CTRL,
>> + SUN6I_LOSC_CTRL_RTC_YMD_ACC, 50)) {
>> + dev_err(dev, "Failed to set rtc time.\n");
>> + return -ETIMEDOUT;
>> + }
>> +
>> + return 0;
>> +}
>> +
>> +static int sun6i_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
>> +{
>> + struct sun6i_rtc_dev *chip = dev_get_drvdata(dev);
>> +
>> + if (!enabled)
>> + sun6i_rtc_setaie(enabled, chip);
>> +
>> + return 0;
>> +}
>> +
>> +static const struct rtc_class_ops sun6i_rtc_ops = {
>> + .read_time = sun6i_rtc_gettime,
>> + .set_time = sun6i_rtc_settime,
>> + .read_alarm = sun6i_rtc_getalarm,
>> + .set_alarm = sun6i_rtc_setalarm,
>> + .alarm_irq_enable = sun6i_rtc_alarm_irq_enable
>> +};
>> +
>> +static const struct of_device_id sun6i_rtc_dt_ids[] = {
>> + { .compatible = "allwinner,sun6i-a31-rtc" },
>> + { /* sentinel */ },
>> +};
>> +MODULE_DEVICE_TABLE(of, sun6i_rtc_dt_ids);
>
> I guess you can move this down just before the platform_driver
> declaration if you don't need it in probe.
Moved.
>> +
>> +static int sun6i_rtc_probe(struct platform_device *pdev)
>> +{
>> + struct sun6i_rtc_dev *chip;
>> + struct resource *res;
>> + int ret;
>> +
>> + chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL);
>> + if (!chip)
>> + return -ENOMEM;
>> +
>> + platform_set_drvdata(pdev, chip);
>> + chip->dev = &pdev->dev;
>> +
>> + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>> + chip->base = devm_ioremap_resource(&pdev->dev, res);
>> + if (IS_ERR(chip->base))
>> + return PTR_ERR(chip->base);
>> +
>> + chip->irq = platform_get_irq(pdev, 0);
>> + if (chip->irq < 0) {
>> + dev_err(&pdev->dev, "No IRQ resource\n");
>> + return chip->irq;
>> + }
>
> Newline
Added.
>> + ret = devm_request_irq(&pdev->dev, chip->irq, sun6i_rtc_alarmirq,
>> + 0, dev_name(&pdev->dev), chip);
>> + if (ret) {
>> + dev_err(&pdev->dev, "Could not request IRQ\n");
>> + return ret;
>> + }
>> +
>> + /* clear the alarm counter value */
>> + writel(0, chip->base + SUN6I_ALRM_COUNTER);
>> +
>> + /* disable counter alarm */
>> + writel(0, chip->base + SUN6I_ALRM_EN);
>> +
>> + /* disable counter alarm interrupt */
>> + writel(0, chip->base + SUN6I_ALRM_IRQ_EN);
>> +
>> + /* disable week alarm */
>> + writel(0, chip->base + SUN6I_ALRM1_EN);
>> +
>> + /* disable week alarm interrupt */
>> + writel(0, chip->base + SUN6I_ALRM1_IRQ_EN);
>> +
>> + /* clear counter alarm pending interrupts */
>> + writel(SUN6I_ALRM_IRQ_STA_CNT_IRQ_PEND, chip->base +
>> + SUN6I_ALRM_IRQ_STA);
>> +
>> + /* clear week alarm pending interrupts */
>> + writel(SUN6I_ALRM1_IRQ_STA_WEEK_IRQ_PEND, chip->base +
>> + SUN6I_ALRM1_IRQ_STA);
>> +
>> + /* disable alarm wakeup */
>> + writel(0, chip->base + SUN6I_ALARM_CONFIG);
>> +
>> + chip->rtc = rtc_device_register("rtc-sun6i", &pdev->dev,
>> + &sun6i_rtc_ops, THIS_MODULE);
>> + if (IS_ERR(chip->rtc)) {
>> + dev_err(&pdev->dev, "unable to register device\n");
>> + return PTR_ERR(chip->rtc);
>> + }
>> +
>> + dev_info(&pdev->dev, "RTC enabled\n");
>> +
>> + return 0;
>> +}
>> +
>> +static int sun6i_rtc_remove(struct platform_device *pdev)
>> +{
>> + struct sun6i_rtc_dev *chip = platform_get_drvdata(pdev);
>> +
>> + rtc_device_unregister(chip->rtc);
>> +
>> + return 0;
>> +}
>> +
>> +static struct platform_driver sun6i_rtc_driver = {
>> + .probe = sun6i_rtc_probe,
>> + .remove = sun6i_rtc_remove,
>> + .driver = {
>> + .name = "sun6i-rtc",
>> + .owner = THIS_MODULE,
>> + .of_match_table = sun6i_rtc_dt_ids,
>> + },
>> +};
>> +
>> +module_platform_driver(sun6i_rtc_driver);
>> +
>> +MODULE_DESCRIPTION("sun6i RTC driver");
>> +MODULE_AUTHOR("Chen-Yu Tsai <wens@csie.org>");
>> +MODULE_LICENSE("GPL");
>> --
>> 2.0.1
>>
>
> Thanks!
> Maxime
Thanks for the review!
ChenYu
^ permalink raw reply
* [PATCH] clocksource: sirf: fix incorrect clock enable counter for timer
From: Daniel Lezcano @ 2014-07-21 14:45 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1404391971-24214-1-git-send-email-21cnbao@gmail.com>
On 07/03/2014 02:52 PM, Barry Song wrote:
> From: Zhiwu Song <Zhiwu.Song@csr.com>
>
> in the clocksource driver, we didn't explicitly enable the clock.
> it makes the clk reference counter wrong.
> we didn't encounter any hang issue because the tick's clock input
> has been open and is shared by some other hardware components, but
> if we don't enable those components in kernel, in the stage of
> disabling unused clk in kernel boot, Linux tick hangs.
>
> this patch fixes it. it does an explicit prepare and enable to the
> clock input, and increases the usage counter of the clk.
>
> Signed-off-by: Zhiwu Song <Zhiwu.Song@csr.com>
> Signed-off-by: Barry Song <Baohua.Song@csr.com>
Applied to my tree for 3.17
Thanks!
-- Daniel
--
<http://www.linaro.org/> Linaro.org ? Open source software for ARM SoCs
Follow Linaro: <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog
^ permalink raw reply
* [PATCH 2/2] iio: exynos-adc: add experimental touchscreen support
From: Dmitry Torokhov @ 2014-07-21 14:44 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <5158672.dMAnnUQc7Z@wuerfel>
On Mon, Jul 21, 2014 at 12:23:58PM +0200, Arnd Bergmann wrote:
> On Sunday 20 July 2014 13:28:42 Dmitry Torokhov wrote:
> > On Sun, Jul 20, 2014 at 02:51:37PM +0100, Jonathan Cameron wrote:
> > > >>+
> > > >>+ do {
> > > >>+ ret =exynos_read_s3c64xx_ts(dev, NULL, &x, &y, IIO_CHAN_INFO_RAW);
> > > >= exynos
> > > >>+ if (ret == -ETIMEDOUT)
> > > >>+ break;
> > > >>+
> > > >>+ pressed = x & y & ADC_DATX_PRESSED;
> > > >>+ if (!pressed)
> > > >>+ break;
> > > >>+
> > > >>+ input_report_abs(info->input, ABS_X, x & ADC_DATX_MASK);
> > > >>+ input_report_abs(info->input, ABS_Y, y & ADC_DATX_MASK);
> > > >>+ input_report_key(info->input, BTN_TOUCH, 1);
> > > >>+ input_sync(info->input);
> > > >>+
> > > >>+ msleep(1);
> > > >>+ } while (1);
> >
> > It would be nice to actually close the device even if someone is
> > touching screen. Please implement open/close methods and have them set a
> > flag that you would check here.
>
> Ok. I think it's even better to move the request_irq() into the open function,
> which will avoid the flag and defer the error handling into the actual opening,
> as well as syncing the running irq with the close function.
I do not quite like acquiring resources needed in open. I think drivers should
do all resource acquisition in probe() and leave open()/close() to
activate/quiesce devices.
>
> > > >>+ /* data from s3c2410_ts driver */
> > > >>+ info->input->name = "S3C24xx TouchScreen";
> > > >>+ info->input->id.bustype = BUS_HOST;
> > > >>+ info->input->id.vendor = 0xDEAD;
> > > >>+ info->input->id.product = 0xBEEF;
> >
> > You do not need to fill these entries with fake data.
>
> Ok, I wondered about this, but didn't want to change too much from
> the old driver (I changed the version number).
>
> > > >>+ info->input->id.version = 0x0200;
>
> Do I need this?
Not really.
Thanks.
--
Dmitry
^ permalink raw reply
* [RFC V2] devicetree: Dialog Semiconductor consolidate existing vendor prefixes to standardise on 'dlg'
From: Opensource [Steve Twiss] @ 2014-07-21 14:40 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <201407151520.s6FFKcjB009745@swsrvapps-01.diasemi.com>
On 15 July 2014 16:04, Steve Twiss wrote:
>From: Opensource [Steve Twiss] [mailto:stwiss.opensource at diasemi.com]
>Sent: 15 July 2014 16:04
>Subject: [RFC V2] devicetree: Dialog Semiconductor consolidate existing vendor
>prefixes to standardise on 'dlg'
[...]
>This patch series updates the device tree vendor prefix for
>Dialog Semiconductor.
>Various methods are currently used throughout the kernel: 'diasemi',
>'dialog' and 'dlg'. Others have also been suggested.
>This patch set aims to consolidate the usage of the vendor prefix to
>use a common standard. The prefix 'dlg' is used.
[...]
Hello all,
Have there been any further thoughts on this? I would like move this issue forwards so
that this problem this does not keep arising.
>From my point of view, the argument is a simple one: what is the value of existing multiple
vendor prefixes if they do not work and are not used anywhere?
But, as usual I recognise that the kernel community have different aims and I am willing
to compromise with my patches in order to move ahead.
Regards,
Steve
^ permalink raw reply
* [PATCH v3 4/4] arm: pxa: add non device-tree timer link to clocksource
From: Daniel Lezcano @ 2014-07-21 14:37 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1405356724-32207-4-git-send-email-robert.jarzmik@free.fr>
On 07/14/2014 06:52 PM, Robert Jarzmik wrote:
> As clocksource pxa_timer was moved to clocksource framework, the
> pxa_timer initialization needs to be a bit amended, to pass the
> necessary informations to clocksource, ie :
> - the timer interrupt (mach specific)
> - the timer registers base (ditto)
> - the timer clockrate
>
> Signed-off-by: Robert Jarzmik <robert.jarzmik@free.fr>
>
> ---
> Since V2: Arnd's comment : moved extern declaration into .h file
> ---
Shall I take the patches 4-5 also ?
Arnd ?
Thanks
-- Daniel
> arch/arm/mach-pxa/generic.c | 11 +++++++++++
> include/clocksource/pxa.h | 18 ++++++++++++++++++
> 2 files changed, 29 insertions(+)
> create mode 100644 include/clocksource/pxa.h
>
> diff --git a/arch/arm/mach-pxa/generic.c b/arch/arm/mach-pxa/generic.c
> index 4225417..6f38e1a 100644
> --- a/arch/arm/mach-pxa/generic.c
> +++ b/arch/arm/mach-pxa/generic.c
> @@ -25,11 +25,13 @@
> #include <asm/mach/map.h>
> #include <asm/mach-types.h>
>
> +#include <mach/irqs.h>
> #include <mach/reset.h>
> #include <mach/smemc.h>
> #include <mach/pxa3xx-regs.h>
>
> #include "generic.h"
> +#include <clocksource/pxa.h>
>
> void clear_reset_status(unsigned int mask)
> {
> @@ -57,6 +59,15 @@ unsigned long get_clock_tick_rate(void)
> EXPORT_SYMBOL(get_clock_tick_rate);
>
> /*
> + * For non device-tree builds, keep legacy timer init
> + */
> +void pxa_timer_init(void)
> +{
> + pxa_timer_nodt_init(IRQ_OST0, io_p2v(0x40a00000),
> + get_clock_tick_rate());
> +}
> +
> +/*
> * Get the clock frequency as reflected by CCCR and the turbo flag.
> * We assume these values have been applied via a fcs.
> * If info is not 0 we also display the current settings.
> diff --git a/include/clocksource/pxa.h b/include/clocksource/pxa.h
> new file mode 100644
> index 0000000..1efbe5a
> --- /dev/null
> +++ b/include/clocksource/pxa.h
> @@ -0,0 +1,18 @@
> +/*
> + * PXA clocksource, clockevents, and OST interrupt handlers.
> + *
> + * Copyright (C) 2014 Robert Jarzmik
> + *
> + * 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; version 2 of the License.
> + *
> + */
> +
> +#ifndef _CLOCKSOURCE_PXA_H
> +#define _CLOCKSOURCE_PXA_H
> +
> +extern void pxa_timer_nodt_init(int irq, void __iomem *base,
> + unsigned long clock_tick_rate);
> +
> +#endif
>
--
<http://www.linaro.org/> Linaro.org ? Open source software for ARM SoCs
Follow Linaro: <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog
^ permalink raw reply
* [RESEND PATCH v3 06/11] drm: add DT bindings documentation for atmel-hlcdc-dc driver
From: Boris BREZILLON @ 2014-07-21 14:21 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140721135410.GA13770@ulmo>
On Mon, 21 Jul 2014 15:54:12 +0200
Thierry Reding <thierry.reding@gmail.com> wrote:
> On Mon, Jul 21, 2014 at 03:47:52PM +0200, Laurent Pinchart wrote:
> > Hi Boris,
> >
> > On Monday 21 July 2014 15:43:13 Boris BREZILLON wrote:
> > > On Mon, 21 Jul 2014 15:30:35 +0200 Thierry Reding wrote:
> > > > On Mon, Jul 21, 2014 at 03:22:05PM +0200, Laurent Pinchart wrote:
> > > >> On Monday 21 July 2014 14:55:23 Thierry Reding wrote:
> > > >>> On Mon, Jul 21, 2014 at 02:34:28PM +0200, Boris BREZILLON wrote:
> > > >>>> On Mon, 21 Jul 2014 14:16:42 +0200 Laurent Pinchart wrote:
> > > >>>>> On Monday 21 July 2014 14:12:47 Thierry Reding wrote:
> > > >>>>>> On Mon, Jul 21, 2014 at 11:57:37AM +0200, Boris BREZILLON wrote:
> > > >>
> > > >> [snip]
> > > >>
> > > >>>>>>> The new drm_display_info structure should look like this [2]
> > > >>>>>>> (except that color_formats and bpc have not be removed yet), and
> > > >>>>>>> [1] is just here to show how the video_bus_format enum would look
> > > >>>>>>> like.
> > > >>>>>>>
> > > >>>>>>> [1] http://code.bulix.org/rfd0yx-86557
> > > >>>>>>> [2] http://code.bulix.org/7n03b4-86556
> > > >>>>>>
> > > >>>>>> Quoting from your paste:
> > > >>>>>> + const enum video_bus_format *bus_formats;
> > > >>>>>> + int nbus_formats;
> > > >>>>>>
> > > >>>>>> Do we really need more than one?
> > > >>>>>
> > > >>>>> We do if we want to replace the color_formats and bpc fields.
> > > >>>>
> > > >>>> Yes, that's what I was about to answer :-).
> > > >>>
> > > >>> Maybe we don't need to replace color_formats and bpc field
> > > >>> immediately. That could be done in a follow-up patch.
> > > >>
> > > >> We don't need to replace them right now, but we should at least agree on
> > > >> how to replace them. Introducing a new field that would need to be
> > > >> replaced in the near future when removing color_formats and bpc would
> > > >> be a waste of time.
> > > >
> > > > Sure. One of the problems I see with replacing color_formats and bpc
> > > > with the above is that some of the bits within color_formats are set
> > > > when the EDID is parsed. That implies that if they are replaced with
> > > > an array of formats, the array would need to be reallocated during EDID
> > > > parsing. That sounds like ugliness.
> > > >
> > > > But if you can find a nice way to make it work that'd be great.
> > >
> > > How about using a list instead of an array ?
> > > This way we can add elements to this list when parsing the EDID.
> > >
> > > Or we can just define a maximum size for the bus_formats array when
> > > retrieving this info from EDID. If I'm correct we have at most 18 bus
> > > formats:
> > > - 3 color formats:
> > > * RGB 4:4:4
> > > * YCbCr 4:4:4
> > > * YCbCr 4:4:2
> > > - 6 color depths: 6, 8, 10, 12, 14 and 16 bits per color
> >
> > bpc isn't a bitmask, so EDID supports up to three formats only.
> >
> > The color_formats field is computed in the drm_add_display_info() function.
> > You could easily turn it into a local variable and allocate and fill the
> > formats array at the end of the function.
>
> But you also need to be careful to keep whatever formats the driver
> might have set explicitly.
Okay, in this case, using a list is a better idea, don't you think ?
--
Boris Brezillon, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
^ permalink raw reply
* [alsa-devel] [PATCH 2/4] ASoC: s3c64xx/smartq: use dynamic registration
From: Alexandre Courbot @ 2014-07-21 14:19 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140721100412.GT17528@sirena.org.uk>
On Mon, Jul 21, 2014 at 7:04 PM, Mark Brown <broonie@kernel.org> wrote:
> On Mon, Jul 21, 2014 at 12:36:43PM +0900, Alexandre Courbot wrote:
>> On Thu, Jul 17, 2014 at 8:05 PM, Mark Brown <broonie@kernel.org> wrote:
>
>> > For set and get, sure - but it's still useful to be able to do bulk
>> > requests for GPIOs especially since that's the only bit of the interface
>> > that requires error handling.
>
>> I foresee many problems if people start using gpiod_array_get() as a
>> way to spare a few lines of error-checking code. First all the GPIOs
>> would end into an array instead of members with meaningful names -
>> unless they are moved later on, but doing so would add extra code and
>> somewhat kill the purpose. It also becomes more difficult to maintain
>> as you are dealing with array indexes to update all over the code.
>
> You just need a few defines for the names, it's not a big deal.
>
>> Finally, it will make it more difficult to use gpiod_array_*() the way
>> it is intended to be used, as you would have to discriminate between
>> GPIOs of the same function and the rest by yourself.
>
> Yes, you probably shouldn't mix and match here but that's fine.
>
>> Also, if such a convenience function is legitimate for GPIO, shouldn't
>> it also apply to other sub-systems? E.g. regulator_array_get()?
>
> It's certainly a totally reasonable and expected way of using
> regulator_bulk_get().
>
>> Maybe I am missing your point, but I still think some error-handling
>> code really doesn't hurt here, and the few drivers that would actually
>> benefit from a more automated GPIO request error handling can easily
>> implement it themselves. Let's keep gpiod_array_*() single-purposed
>> and to the point.
>
> I'm not sure I see the massive complication TBH - it's not so much about
> complexity as it is about reducing the amount of boilerplate that people
> need to get right.
I guess our disagreement came from the fact that we want the same
function to perform two different things. GPIOs are different from
regulators in that the former are really requested using a (dev,
function, index) vs. a (dev, function) tuple for regulators. I want a
convenience function to easily request all the GPIOs that match (dev,
function) so that functionally identical GPIOs can be manipulated as
an "atomic" set using the rest of the gpiod_array API (which would
make no sense for regulators which have no "index". You want an
equivalent to regulator_bulk_get() so a driver can conveniently
request all its GPIOs no matter the function they fullfil.
These should really be two different functions for two different
use-cases - gpiod_array_get() that returns an array suitable for being
manipulated using the rest of the gpiod_array API ; gpiod_bulk_get()
that takes the equivalent of regulator_bulk_data for GPIOs and fills
it the same way.
^ permalink raw reply
* [RESEND PATCH v3 06/11] drm: add DT bindings documentation for atmel-hlcdc-dc driver
From: Boris BREZILLON @ 2014-07-21 14:18 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1605488.5CKVSJec67@avalon>
On Mon, 21 Jul 2014 15:47:52 +0200
Laurent Pinchart <laurent.pinchart@ideasonboard.com> wrote:
> Hi Boris,
>
> On Monday 21 July 2014 15:43:13 Boris BREZILLON wrote:
> > On Mon, 21 Jul 2014 15:30:35 +0200 Thierry Reding wrote:
> > > On Mon, Jul 21, 2014 at 03:22:05PM +0200, Laurent Pinchart wrote:
> > >> On Monday 21 July 2014 14:55:23 Thierry Reding wrote:
> > >>> On Mon, Jul 21, 2014 at 02:34:28PM +0200, Boris BREZILLON wrote:
> > >>>> On Mon, 21 Jul 2014 14:16:42 +0200 Laurent Pinchart wrote:
> > >>>>> On Monday 21 July 2014 14:12:47 Thierry Reding wrote:
> > >>>>>> On Mon, Jul 21, 2014 at 11:57:37AM +0200, Boris BREZILLON wrote:
> > >>
> > >> [snip]
> > >>
> > >>>>>>> The new drm_display_info structure should look like this [2]
> > >>>>>>> (except that color_formats and bpc have not be removed yet), and
> > >>>>>>> [1] is just here to show how the video_bus_format enum would look
> > >>>>>>> like.
> > >>>>>>>
> > >>>>>>> [1] http://code.bulix.org/rfd0yx-86557
> > >>>>>>> [2] http://code.bulix.org/7n03b4-86556
> > >>>>>>
> > >>>>>> Quoting from your paste:
> > >>>>>> + const enum video_bus_format *bus_formats;
> > >>>>>> + int nbus_formats;
> > >>>>>>
> > >>>>>> Do we really need more than one?
> > >>>>>
> > >>>>> We do if we want to replace the color_formats and bpc fields.
> > >>>>
> > >>>> Yes, that's what I was about to answer :-).
> > >>>
> > >>> Maybe we don't need to replace color_formats and bpc field
> > >>> immediately. That could be done in a follow-up patch.
> > >>
> > >> We don't need to replace them right now, but we should at least agree on
> > >> how to replace them. Introducing a new field that would need to be
> > >> replaced in the near future when removing color_formats and bpc would
> > >> be a waste of time.
> > >
> > > Sure. One of the problems I see with replacing color_formats and bpc
> > > with the above is that some of the bits within color_formats are set
> > > when the EDID is parsed. That implies that if they are replaced with
> > > an array of formats, the array would need to be reallocated during EDID
> > > parsing. That sounds like ugliness.
> > >
> > > But if you can find a nice way to make it work that'd be great.
> >
> > How about using a list instead of an array ?
> > This way we can add elements to this list when parsing the EDID.
> >
> > Or we can just define a maximum size for the bus_formats array when
> > retrieving this info from EDID. If I'm correct we have at most 18 bus
> > formats:
> > - 3 color formats:
> > * RGB 4:4:4
> > * YCbCr 4:4:4
> > * YCbCr 4:4:2
> > - 6 color depths: 6, 8, 10, 12, 14 and 16 bits per color
>
> bpc isn't a bitmask, so EDID supports up to three formats only.
Yes, bpc only contains a single value for now, and it fits the
DRM_EDID_DIGITAL_DEPTH field [1] (an enum defining the supported pixel
depth).
ITOH, DRM_EDID_HDMI_DC_XX [2] (which are referenced in the new
drm_assign_hdmi_deep_color_info function) are just bitmasks and thus a
display might support several color depth.
As a result, I wonder if we shouldn't start supporting several
color depths (as we do for color formats).
[1]http://lxr.free-electrons.com/source/drivers/gpu/drm/drm_edid.c#L3436
[2]https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/drivers/gpu/drm/drm_edid.c?id=refs/tags/v3.16-rc6#n3440
--
Boris Brezillon, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
^ permalink raw reply
* [PATCH 29/43] arm64: Use sigsp()
From: Richard Weinberger @ 2014-07-21 14:03 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1405951409-16953-1-git-send-email-richard@sigma-star.at>
From: Richard Weinberger <richard@nod.at>
Use sigsp() instead of the open coded variant.
Signed-off-by: Richard Weinberger <richard@nod.at>
---
arch/arm64/kernel/signal.c | 12 +++---------
arch/arm64/kernel/signal32.c | 14 ++++----------
2 files changed, 7 insertions(+), 19 deletions(-)
diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c
index b29f5da..6fa7921 100644
--- a/arch/arm64/kernel/signal.c
+++ b/arch/arm64/kernel/signal.c
@@ -209,19 +209,13 @@ static int setup_sigframe(struct rt_sigframe __user *sf,
return err;
}
-static struct rt_sigframe __user *get_sigframe(struct k_sigaction *ka,
+static struct rt_sigframe __user *get_sigframe(struct ksignal *ksig,
struct pt_regs *regs)
{
unsigned long sp, sp_top;
struct rt_sigframe __user *frame;
- sp = sp_top = regs->sp;
-
- /*
- * This is the X/Open sanctioned signal stack switching.
- */
- if ((ka->sa.sa_flags & SA_ONSTACK) && !sas_ss_flags(sp))
- sp = sp_top = current->sas_ss_sp + current->sas_ss_size;
+ sp = sp_top = sigsp(regs->sp, ksig);
sp = (sp - sizeof(struct rt_sigframe)) & ~15;
frame = (struct rt_sigframe __user *)sp;
@@ -259,7 +253,7 @@ static int setup_rt_frame(int usig, struct ksignal *ksig, sigset_t *set,
struct rt_sigframe __user *frame;
int err = 0;
- frame = get_sigframe(&ksig->ka, regs);
+ frame = get_sigframe(ksig, regs);
if (!frame)
return 1;
diff --git a/arch/arm64/kernel/signal32.c b/arch/arm64/kernel/signal32.c
index b69ee69..1a5c5bf 100644
--- a/arch/arm64/kernel/signal32.c
+++ b/arch/arm64/kernel/signal32.c
@@ -407,20 +407,14 @@ badframe:
return 0;
}
-static void __user *compat_get_sigframe(struct k_sigaction *ka,
+static void __user *compat_get_sigframe(struct ksignal *ksig,
struct pt_regs *regs,
int framesize)
{
- compat_ulong_t sp = regs->compat_sp;
+ compat_ulong_t sp = sigsp(regs->compat_sp, ksig);
void __user *frame;
/*
- * This is the X/Open sanctioned signal stack switching.
- */
- if ((ka->sa.sa_flags & SA_ONSTACK) && !sas_ss_flags(sp))
- sp = current->sas_ss_sp + current->sas_ss_size;
-
- /*
* ATPCS B01 mandates 8-byte alignment
*/
frame = compat_ptr((compat_uptr_t)((sp - framesize) & ~7));
@@ -526,7 +520,7 @@ int compat_setup_rt_frame(int usig, struct ksignal *ksig,
struct compat_rt_sigframe __user *frame;
int err = 0;
- frame = compat_get_sigframe(&ksig->ka, regs, sizeof(*frame));
+ frame = compat_get_sigframe(ksig, regs, sizeof(*frame));
if (!frame)
return 1;
@@ -555,7 +549,7 @@ int compat_setup_frame(int usig, struct ksignal *ksig, sigset_t *set,
struct compat_sigframe __user *frame;
int err = 0;
- frame = compat_get_sigframe(&ksig->ka, regs, sizeof(*frame));
+ frame = compat_get_sigframe(ksig, regs, sizeof(*frame));
if (!frame)
return 1;
--
1.8.4.5
^ permalink raw reply related
* [PATCH 02/43] arm64: Use get_signal() signal_setup_done()
From: Richard Weinberger @ 2014-07-21 14:02 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1405951409-16953-1-git-send-email-richard@sigma-star.at>
From: Richard Weinberger <richard@nod.at>
Use the more generic functions get_signal() signal_setup_done()
for signal delivery.
Signed-off-by: Richard Weinberger <richard@nod.at>
---
arch/arm64/include/asm/signal32.h | 11 ++++-----
arch/arm64/kernel/signal.c | 48 ++++++++++++++++-----------------------
arch/arm64/kernel/signal32.c | 14 ++++++------
3 files changed, 32 insertions(+), 41 deletions(-)
diff --git a/arch/arm64/include/asm/signal32.h b/arch/arm64/include/asm/signal32.h
index 7c275e3..eeaa975 100644
--- a/arch/arm64/include/asm/signal32.h
+++ b/arch/arm64/include/asm/signal32.h
@@ -24,22 +24,21 @@
extern const compat_ulong_t aarch32_sigret_code[6];
-int compat_setup_frame(int usig, struct k_sigaction *ka, sigset_t *set,
+int compat_setup_frame(int usig, struct ksignal *ksig, sigset_t *set,
struct pt_regs *regs);
-int compat_setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info,
- sigset_t *set, struct pt_regs *regs);
+int compat_setup_rt_frame(int usig, struct ksignal *ksig, sigset_t *set,
+ struct pt_regs *regs);
void compat_setup_restart_syscall(struct pt_regs *regs);
#else
-static inline int compat_setup_frame(int usid, struct k_sigaction *ka,
+static inline int compat_setup_frame(int usid, struct ksignal *ksig,
sigset_t *set, struct pt_regs *regs)
{
return -ENOSYS;
}
-static inline int compat_setup_rt_frame(int usig, struct k_sigaction *ka,
- siginfo_t *info, sigset_t *set,
+static inline int compat_setup_rt_frame(int usig, struct ksignal *ksig, sigset_t *set,
struct pt_regs *regs)
{
return -ENOSYS;
diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c
index 6357b9c..b29f5da 100644
--- a/arch/arm64/kernel/signal.c
+++ b/arch/arm64/kernel/signal.c
@@ -253,13 +253,13 @@ static void setup_return(struct pt_regs *regs, struct k_sigaction *ka,
regs->regs[30] = (unsigned long)sigtramp;
}
-static int setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info,
- sigset_t *set, struct pt_regs *regs)
+static int setup_rt_frame(int usig, struct ksignal *ksig, sigset_t *set,
+ struct pt_regs *regs)
{
struct rt_sigframe __user *frame;
int err = 0;
- frame = get_sigframe(ka, regs);
+ frame = get_sigframe(&ksig->ka, regs);
if (!frame)
return 1;
@@ -269,9 +269,9 @@ static int setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info,
err |= __save_altstack(&frame->uc.uc_stack, regs->sp);
err |= setup_sigframe(frame, regs, set);
if (err == 0) {
- setup_return(regs, ka, frame, usig);
- if (ka->sa.sa_flags & SA_SIGINFO) {
- err |= copy_siginfo_to_user(&frame->info, info);
+ setup_return(regs, &ksig->ka, frame, usig);
+ if (ksig->ka.sa.sa_flags & SA_SIGINFO) {
+ err |= copy_siginfo_to_user(&frame->info, &ksig->info);
regs->regs[1] = (unsigned long)&frame->info;
regs->regs[2] = (unsigned long)&frame->uc;
}
@@ -291,13 +291,12 @@ static void setup_restart_syscall(struct pt_regs *regs)
/*
* OK, we're invoking a handler
*/
-static void handle_signal(unsigned long sig, struct k_sigaction *ka,
- siginfo_t *info, struct pt_regs *regs)
+static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
{
struct thread_info *thread = current_thread_info();
struct task_struct *tsk = current;
sigset_t *oldset = sigmask_to_save();
- int usig = sig;
+ int usig = ksig->sig;
int ret;
/*
@@ -310,13 +309,12 @@ static void handle_signal(unsigned long sig, struct k_sigaction *ka,
* Set up the stack frame
*/
if (is_compat_task()) {
- if (ka->sa.sa_flags & SA_SIGINFO)
- ret = compat_setup_rt_frame(usig, ka, info, oldset,
- regs);
+ if (ksig->ka.sa.sa_flags & SA_SIGINFO)
+ ret = compat_setup_rt_frame(usig, ksig, oldset, regs);
else
- ret = compat_setup_frame(usig, ka, oldset, regs);
+ ret = compat_setup_frame(usig, ksig, oldset, regs);
} else {
- ret = setup_rt_frame(usig, ka, info, oldset, regs);
+ ret = setup_rt_frame(usig, ksig, oldset, regs);
}
/*
@@ -324,18 +322,14 @@ static void handle_signal(unsigned long sig, struct k_sigaction *ka,
*/
ret |= !valid_user_regs(®s->user_regs);
- if (ret != 0) {
- force_sigsegv(sig, tsk);
- return;
- }
-
/*
* Fast forward the stepping logic so we step into the signal
* handler.
*/
- user_fastforward_single_step(tsk);
+ if (!ret)
+ user_fastforward_single_step(tsk);
- signal_delivered(sig, info, ka, regs, 0);
+ signal_setup_done(ret, ksig, 0);
}
/*
@@ -350,10 +344,9 @@ static void handle_signal(unsigned long sig, struct k_sigaction *ka,
static void do_signal(struct pt_regs *regs)
{
unsigned long continue_addr = 0, restart_addr = 0;
- struct k_sigaction ka;
- siginfo_t info;
- int signr, retval = 0;
+ int retval = 0;
int syscall = (int)regs->syscallno;
+ struct ksignal ksig;
/*
* If we were from a system call, check for system call restarting...
@@ -387,8 +380,7 @@ static void do_signal(struct pt_regs *regs)
* Get the signal to deliver. When running under ptrace, at this point
* the debugger may change all of our registers.
*/
- signr = get_signal_to_deliver(&info, &ka, regs, NULL);
- if (signr > 0) {
+ if (get_signal(&ksig)) {
/*
* Depending on the signal settings, we may need to revert the
* decision to restart the system call, but skip this if a
@@ -398,12 +390,12 @@ static void do_signal(struct pt_regs *regs)
(retval == -ERESTARTNOHAND ||
retval == -ERESTART_RESTARTBLOCK ||
(retval == -ERESTARTSYS &&
- !(ka.sa.sa_flags & SA_RESTART)))) {
+ !(ksig.ka.sa.sa_flags & SA_RESTART)))) {
regs->regs[0] = -EINTR;
regs->pc = continue_addr;
}
- handle_signal(signr, &ka, &info, regs);
+ handle_signal(&ksig, regs);
return;
}
diff --git a/arch/arm64/kernel/signal32.c b/arch/arm64/kernel/signal32.c
index 3491c63..b69ee69 100644
--- a/arch/arm64/kernel/signal32.c
+++ b/arch/arm64/kernel/signal32.c
@@ -520,18 +520,18 @@ static int compat_setup_sigframe(struct compat_sigframe __user *sf,
/*
* 32-bit signal handling routines called from signal.c
*/
-int compat_setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info,
+int compat_setup_rt_frame(int usig, struct ksignal *ksig,
sigset_t *set, struct pt_regs *regs)
{
struct compat_rt_sigframe __user *frame;
int err = 0;
- frame = compat_get_sigframe(ka, regs, sizeof(*frame));
+ frame = compat_get_sigframe(&ksig->ka, regs, sizeof(*frame));
if (!frame)
return 1;
- err |= copy_siginfo_to_user32(&frame->info, info);
+ err |= copy_siginfo_to_user32(&frame->info, &ksig->info);
__put_user_error(0, &frame->sig.uc.uc_flags, err);
__put_user_error(0, &frame->sig.uc.uc_link, err);
@@ -541,7 +541,7 @@ int compat_setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info,
err |= compat_setup_sigframe(&frame->sig, regs, set);
if (err == 0) {
- compat_setup_return(regs, ka, frame->sig.retcode, frame, usig);
+ compat_setup_return(regs, &ksig->ka, frame->sig.retcode, frame, usig);
regs->regs[1] = (compat_ulong_t)(unsigned long)&frame->info;
regs->regs[2] = (compat_ulong_t)(unsigned long)&frame->sig.uc;
}
@@ -549,13 +549,13 @@ int compat_setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info,
return err;
}
-int compat_setup_frame(int usig, struct k_sigaction *ka, sigset_t *set,
+int compat_setup_frame(int usig, struct ksignal *ksig, sigset_t *set,
struct pt_regs *regs)
{
struct compat_sigframe __user *frame;
int err = 0;
- frame = compat_get_sigframe(ka, regs, sizeof(*frame));
+ frame = compat_get_sigframe(&ksig->ka, regs, sizeof(*frame));
if (!frame)
return 1;
@@ -564,7 +564,7 @@ int compat_setup_frame(int usig, struct k_sigaction *ka, sigset_t *set,
err |= compat_setup_sigframe(frame, regs, set);
if (err == 0)
- compat_setup_return(regs, ka, frame->retcode, frame, usig);
+ compat_setup_return(regs, &ksig->ka, frame->retcode, frame, usig);
return err;
}
--
1.8.4.5
^ permalink raw reply related
* [PATCH v2] ARM: dts: add CPU nodes for Exynos4 SoCs
From: Bartlomiej Zolnierkiewicz @ 2014-07-21 13:57 UTC (permalink / raw)
To: linux-arm-kernel
Recent patch by Tomasz Figa ("irqchip: gic: Fix core ID calculation
when topology is read from DT") fixed GIC driver to filter cluster ID
from values returned by cpu_logical_map() for SoCs having registers
mapped without per-CPU banking making it is possible to add CPU nodes
for Exynos4 SoCs. In case of Exynos SoCs these CPU nodes are also
required by future changes adding initialization of cpuidle states in
Exynos cpuidle driver through DT.
Tested on Origen board (Exynos4210 SoC) and Trats2 (Exynos4412 SoC).
Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
---
Based on next-20140717 branch of linux-next tree +
- [PATCH 2/6] ARM: EXYNOS: Fix core ID used by platsmp and hotplug code
http://www.mail-archive.com/linux-samsung-soc at vger.kernel.org/msg32811.html
- [PATCH] irqchip: gic: Fix core ID calculation when topology is read from DT
http://www.mail-archive.com/linux-samsung-soc at vger.kernel.org/msg34277.html
v2:
- match the unit-address with the reg
arch/arm/boot/dts/exynos4210.dtsi | 17 +++++++++++++++++
arch/arm/boot/dts/exynos4212.dtsi | 17 +++++++++++++++++
arch/arm/boot/dts/exynos4412.dtsi | 29 +++++++++++++++++++++++++++++
3 files changed, 63 insertions(+)
diff --git a/arch/arm/boot/dts/exynos4210.dtsi b/arch/arm/boot/dts/exynos4210.dtsi
index ee3001f..bc2b444 100644
--- a/arch/arm/boot/dts/exynos4210.dtsi
+++ b/arch/arm/boot/dts/exynos4210.dtsi
@@ -31,6 +31,23 @@
pinctrl2 = &pinctrl_2;
};
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu at 900 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a9";
+ reg = <0x900>;
+ };
+
+ cpu at 901 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a9";
+ reg = <0x901>;
+ };
+ };
+
sysram at 02020000 {
compatible = "mmio-sram";
reg = <0x02020000 0x20000>;
diff --git a/arch/arm/boot/dts/exynos4212.dtsi b/arch/arm/boot/dts/exynos4212.dtsi
index 3c00e6e..dd0a43e 100644
--- a/arch/arm/boot/dts/exynos4212.dtsi
+++ b/arch/arm/boot/dts/exynos4212.dtsi
@@ -22,6 +22,23 @@
/ {
compatible = "samsung,exynos4212", "samsung,exynos4";
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu at A00 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a9";
+ reg = <0xA00>;
+ };
+
+ cpu at A01 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a9";
+ reg = <0xA01>;
+ };
+ };
+
combiner: interrupt-controller at 10440000 {
samsung,combiner-nr = <18>;
};
diff --git a/arch/arm/boot/dts/exynos4412.dtsi b/arch/arm/boot/dts/exynos4412.dtsi
index c42a3e1..435a722 100644
--- a/arch/arm/boot/dts/exynos4412.dtsi
+++ b/arch/arm/boot/dts/exynos4412.dtsi
@@ -22,6 +22,35 @@
/ {
compatible = "samsung,exynos4412", "samsung,exynos4";
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu at A00 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a9";
+ reg = <0xA00>;
+ };
+
+ cpu at A01 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a9";
+ reg = <0xA01>;
+ };
+
+ cpu at A02 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a9";
+ reg = <0xA02>;
+ };
+
+ cpu at A03 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a9";
+ reg = <0xA03>;
+ };
+ };
+
combiner: interrupt-controller at 10440000 {
samsung,combiner-nr = <20>;
};
--
1.8.2.3
^ permalink raw reply related
* [RESEND PATCH v3 06/11] drm: add DT bindings documentation for atmel-hlcdc-dc driver
From: Thierry Reding @ 2014-07-21 13:54 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1605488.5CKVSJec67@avalon>
On Mon, Jul 21, 2014 at 03:47:52PM +0200, Laurent Pinchart wrote:
> Hi Boris,
>
> On Monday 21 July 2014 15:43:13 Boris BREZILLON wrote:
> > On Mon, 21 Jul 2014 15:30:35 +0200 Thierry Reding wrote:
> > > On Mon, Jul 21, 2014 at 03:22:05PM +0200, Laurent Pinchart wrote:
> > >> On Monday 21 July 2014 14:55:23 Thierry Reding wrote:
> > >>> On Mon, Jul 21, 2014 at 02:34:28PM +0200, Boris BREZILLON wrote:
> > >>>> On Mon, 21 Jul 2014 14:16:42 +0200 Laurent Pinchart wrote:
> > >>>>> On Monday 21 July 2014 14:12:47 Thierry Reding wrote:
> > >>>>>> On Mon, Jul 21, 2014 at 11:57:37AM +0200, Boris BREZILLON wrote:
> > >>
> > >> [snip]
> > >>
> > >>>>>>> The new drm_display_info structure should look like this [2]
> > >>>>>>> (except that color_formats and bpc have not be removed yet), and
> > >>>>>>> [1] is just here to show how the video_bus_format enum would look
> > >>>>>>> like.
> > >>>>>>>
> > >>>>>>> [1] http://code.bulix.org/rfd0yx-86557
> > >>>>>>> [2] http://code.bulix.org/7n03b4-86556
> > >>>>>>
> > >>>>>> Quoting from your paste:
> > >>>>>> + const enum video_bus_format *bus_formats;
> > >>>>>> + int nbus_formats;
> > >>>>>>
> > >>>>>> Do we really need more than one?
> > >>>>>
> > >>>>> We do if we want to replace the color_formats and bpc fields.
> > >>>>
> > >>>> Yes, that's what I was about to answer :-).
> > >>>
> > >>> Maybe we don't need to replace color_formats and bpc field
> > >>> immediately. That could be done in a follow-up patch.
> > >>
> > >> We don't need to replace them right now, but we should at least agree on
> > >> how to replace them. Introducing a new field that would need to be
> > >> replaced in the near future when removing color_formats and bpc would
> > >> be a waste of time.
> > >
> > > Sure. One of the problems I see with replacing color_formats and bpc
> > > with the above is that some of the bits within color_formats are set
> > > when the EDID is parsed. That implies that if they are replaced with
> > > an array of formats, the array would need to be reallocated during EDID
> > > parsing. That sounds like ugliness.
> > >
> > > But if you can find a nice way to make it work that'd be great.
> >
> > How about using a list instead of an array ?
> > This way we can add elements to this list when parsing the EDID.
> >
> > Or we can just define a maximum size for the bus_formats array when
> > retrieving this info from EDID. If I'm correct we have at most 18 bus
> > formats:
> > - 3 color formats:
> > * RGB 4:4:4
> > * YCbCr 4:4:4
> > * YCbCr 4:4:2
> > - 6 color depths: 6, 8, 10, 12, 14 and 16 bits per color
>
> bpc isn't a bitmask, so EDID supports up to three formats only.
>
> The color_formats field is computed in the drm_add_display_info() function.
> You could easily turn it into a local variable and allocate and fill the
> formats array at the end of the function.
But you also need to be careful to keep whatever formats the driver
might have set explicitly.
Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140721/2013db14/attachment.sig>
^ permalink raw reply
* [RESEND PATCH v3 06/11] drm: add DT bindings documentation for atmel-hlcdc-dc driver
From: Laurent Pinchart @ 2014-07-21 13:47 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140721154313.1de8bf6f@bbrezillon>
Hi Boris,
On Monday 21 July 2014 15:43:13 Boris BREZILLON wrote:
> On Mon, 21 Jul 2014 15:30:35 +0200 Thierry Reding wrote:
> > On Mon, Jul 21, 2014 at 03:22:05PM +0200, Laurent Pinchart wrote:
> >> On Monday 21 July 2014 14:55:23 Thierry Reding wrote:
> >>> On Mon, Jul 21, 2014 at 02:34:28PM +0200, Boris BREZILLON wrote:
> >>>> On Mon, 21 Jul 2014 14:16:42 +0200 Laurent Pinchart wrote:
> >>>>> On Monday 21 July 2014 14:12:47 Thierry Reding wrote:
> >>>>>> On Mon, Jul 21, 2014 at 11:57:37AM +0200, Boris BREZILLON wrote:
> >>
> >> [snip]
> >>
> >>>>>>> The new drm_display_info structure should look like this [2]
> >>>>>>> (except that color_formats and bpc have not be removed yet), and
> >>>>>>> [1] is just here to show how the video_bus_format enum would look
> >>>>>>> like.
> >>>>>>>
> >>>>>>> [1] http://code.bulix.org/rfd0yx-86557
> >>>>>>> [2] http://code.bulix.org/7n03b4-86556
> >>>>>>
> >>>>>> Quoting from your paste:
> >>>>>> + const enum video_bus_format *bus_formats;
> >>>>>> + int nbus_formats;
> >>>>>>
> >>>>>> Do we really need more than one?
> >>>>>
> >>>>> We do if we want to replace the color_formats and bpc fields.
> >>>>
> >>>> Yes, that's what I was about to answer :-).
> >>>
> >>> Maybe we don't need to replace color_formats and bpc field
> >>> immediately. That could be done in a follow-up patch.
> >>
> >> We don't need to replace them right now, but we should at least agree on
> >> how to replace them. Introducing a new field that would need to be
> >> replaced in the near future when removing color_formats and bpc would
> >> be a waste of time.
> >
> > Sure. One of the problems I see with replacing color_formats and bpc
> > with the above is that some of the bits within color_formats are set
> > when the EDID is parsed. That implies that if they are replaced with
> > an array of formats, the array would need to be reallocated during EDID
> > parsing. That sounds like ugliness.
> >
> > But if you can find a nice way to make it work that'd be great.
>
> How about using a list instead of an array ?
> This way we can add elements to this list when parsing the EDID.
>
> Or we can just define a maximum size for the bus_formats array when
> retrieving this info from EDID. If I'm correct we have at most 18 bus
> formats:
> - 3 color formats:
> * RGB 4:4:4
> * YCbCr 4:4:4
> * YCbCr 4:4:2
> - 6 color depths: 6, 8, 10, 12, 14 and 16 bits per color
bpc isn't a bitmask, so EDID supports up to three formats only.
The color_formats field is computed in the drm_add_display_info() function.
You could easily turn it into a local variable and allocate and fill the
formats array at the end of the function.
--
Regards,
Laurent Pinchart
^ 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