Skip to contentSkip to conversation

initial suport for Alphascale ASM9260

PATCH Superseded Oleksij Rempel 3 participants 16 messages Oct 14, 2014 – Oct 19, 2014

Subsystems (10)

v5 of 8 Superseded Latest is v8 →

lore
Share & tools
lore
#0 lore raw

v5 cover initial suport for Alphascale ASM9260

This patchset provide initial support for Alpascale ASM9260, ARM based SoC.

Oleksij Rempel (10):
ARM: add mach-asm9260
ARM: add lolevel debug support for asm9260
ARM: clk: add clk-asm9260 driver
ARM: irqchip: mxs: prepare driver for HW with different offsets
ARM: irqchip: mxs: add Alpascale ASM9260 support
ARM: clocksource: add asm9260_timer driver
ARM: tty: mxs-auart: add initial Alphascale ASM9260 support
ARM: dts: add DT for Alphascale ASM9260 SoC
ARM: add alphascale,acc.txt bindings documentation add Alphascale to vendor-prefixes.txt

 .../devicetree/bindings/clock/alphascale,acc.txt   | 115 +++++++
 .../devicetree/bindings/vendor-prefixes.txt        |   1 +
 arch/arm/Kconfig                                   |   2 +
 arch/arm/Kconfig.debug                             |  33 +-
 arch/arm/boot/dts/Makefile                         |   2 +
 arch/arm/boot/dts/alphascale-asm9260-devkit.dts    |  21 ++
 arch/arm/boot/dts/alphascale-asm9260.dtsi          | 134 ++++++++
 arch/arm/include/debug/asm9260.S                   |  31 ++
 arch/arm/mach-asm9260/Kconfig                      |   8 +
 drivers/clk/Makefile                               |   1 +
 drivers/clk/clk-asm9260.c                          | 351 +++++++++++++++++++
 drivers/clocksource/Kconfig                        |   4 +
 drivers/clocksource/Makefile                       |   1 +
 drivers/clocksource/asm9260_timer.c                | 234 +++++++++++++
 drivers/irqchip/Kconfig                            |   5 +
 drivers/irqchip/Makefile                           |   2 +-
 drivers/irqchip/alphascale_asm9260-icoll.h         | 109 ++++++
 drivers/irqchip/irq-mxs.c                          | 157 ++++++++-
 drivers/tty/serial/Kconfig                         |   5 +-
 drivers/tty/serial/alphascale,asm9260_serial.h     | 373 +++++++++++++++++++++
 drivers/tty/serial/mxs-auart.c                     | 344 ++++++++++++-------
 include/dt-bindings/clock/alphascale,asm9260.h     |  97 ++++++
 22 files changed, 1887 insertions(+), 143 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/clock/alphascale,acc.txt
 create mode 100644 arch/arm/boot/dts/alphascale-asm9260-devkit.dts
 create mode 100644 arch/arm/boot/dts/alphascale-asm9260.dtsi
 create mode 100644 arch/arm/include/debug/asm9260.S
 create mode 100644 arch/arm/mach-asm9260/Kconfig
 create mode 100644 drivers/clk/clk-asm9260.c
 create mode 100644 drivers/clocksource/asm9260_timer.c
 create mode 100644 drivers/irqchip/alphascale_asm9260-icoll.h
 create mode 100644 drivers/tty/serial/alphascale,asm9260_serial.h
 create mode 100644 include/dt-bindings/clock/alphascale,asm9260.h
Signature · 1 line
1.9.1
#1 lore raw

PATCH v5 1/10 ARM: add mach-asm9260

it is low cost (?) SoC targeted for market in China and India which trying to compete with AT91SAM9G25.

Here is some info:
http://www.alphascale.com/index.asp?ics/615.html

One of products:
http://www.aliexpress.com/store/product/2014-hot-sales-FREE-SHIPPING-new-Purple-core-ARM9-development-board-ASM9260T-SDRAM-power-line/433637_1931495721.html

In some cases this SoC looks similar to iMX23/iMX28. But currently it makes no sense to merge mach code of this devices. Especially because most differences are already collected mach-mxs folder.

---
 arch/arm/Kconfig              | 2 ++
 arch/arm/mach-asm9260/Kconfig | 8 ++++++++
 2 files changed, 10 insertions(+)
 create mode 100644 arch/arm/mach-asm9260/Kconfig
arch/arm/Kconfig +2 -0
index 5918d40..87373da 100644
@@ -968,6 +968,8 @@ source "arch/arm/mach-w90x900/Kconfig"
 
 source "arch/arm/mach-zynq/Kconfig"
 
+source "arch/arm/mach-asm9260/Kconfig"
+
 # Definitions to make life easier
 config ARCH_ACORN
 	bool
arch/arm/mach-asm9260/Kconfig new file +8 -0
new file mode 100644
index 0000000..eef90d9
@@ -0,0 +1,8 @@
+config MACH_ASM9260
+	bool "Alphascale ASM9260"
+	depends on ARCH_MULTI_V5
+	select IRQ_MXS
+	select ASM9260_TIMER
+	select CPU_ARM926T
+	help
+	  Support for Alpascale ASM9260 based platform.
Signature · 1 line
1.9.1
#2 lore raw

PATCH v5 2/10 ARM: add lolevel debug support for asm9260

In reply to Oleksij Rempel
---
 arch/arm/Kconfig.debug           | 33 ++++++++++++++++++++++++++++++---
 arch/arm/include/debug/asm9260.S | 31 +++++++++++++++++++++++++++++++
 2 files changed, 61 insertions(+), 3 deletions(-)
 create mode 100644 arch/arm/include/debug/asm9260.S
arch/arm/Kconfig.debug +30 -3
index b11ad54..6902a57 100644
@@ -953,6 +953,27 @@ choice
 		  options; the platform specific options are deprecated
 		  and will be soon removed.
 
+	config DEBUG_ASM9260_UART
+		bool "Kernel low-level debugging via asm9260 UART"
+		depends on MACH_ASM9260
+		help
+		  Say Y here if you want the debug print routines to direct
+		  their output to an UART or USART port on asm9260 based
+		  machines.
+
+		    DEBUG_UART_PHYS | DEBUG_UART_VIRT
+
+		    0x80000000      | 0xf0000000     | UART0
+		    0x80004000      | 0xf0004000     | UART1
+		    0x80008000      | 0xf0008000     | UART2
+		    0x8000c000      | 0xf000c000     | UART3
+		    0x80010000      | 0xf0010000     | UART4
+		    0x80014000      | 0xf0014000     | UART5
+		    0x80018000      | 0xf0018000     | UART6
+		    0x8001c000      | 0xf001c000     | UART7
+		    0x80020000      | 0xf0020000     | UART8
+		    0x80024000      | 0xf0024000     | UART9
+
 endchoice
 
 config DEBUG_EXYNOS_UART
@@ -1038,6 +1059,7 @@ config DEBUG_LL_INCLUDE
 	default "debug/vf.S" if DEBUG_VF_UART
 	default "debug/vt8500.S" if DEBUG_VT8500_UART0
 	default "debug/zynq.S" if DEBUG_ZYNQ_UART0 || DEBUG_ZYNQ_UART1
+	default "debug/asm9260.S" if DEBUG_ASM9260_UART
 	default "mach/debug-macro.S"
 
 # Compatibility options for PL01x
@@ -1094,6 +1116,7 @@ config DEBUG_UART_PHYS
 	default 0x50008000 if DEBUG_S3C24XX_UART && (DEBUG_S3C_UART2 || \
 				DEBUG_S3C2410_UART2)
 	default 0x7c0003f8 if FOOTBRIDGE
+	default 0x80010000 if DEBUG_ASM9260_UART
 	default 0x80070000 if DEBUG_IMX23_UART
 	default 0x80074000 if DEBUG_IMX28_UART
 	default 0x80230000 if DEBUG_PICOXCELL_UART
@@ -1126,7 +1149,8 @@ config DEBUG_UART_PHYS
 	depends on DEBUG_LL_UART_8250 || DEBUG_LL_UART_PL01X || \
 		DEBUG_LL_UART_EFM32 || \
 		DEBUG_UART_8250 || DEBUG_UART_PL01X || \
-		DEBUG_MSM_UART || DEBUG_QCOM_UARTDM || DEBUG_S3C24XX_UART
+		DEBUG_MSM_UART || DEBUG_QCOM_UARTDM || \
+		DEBUG_S3C24XX_UART || DEBUG_ASM9260_UART
 
 config DEBUG_UART_VIRT
 	hex "Virtual base address of debug UART"
@@ -1134,6 +1158,7 @@ config DEBUG_UART_VIRT
 	default 0xe1000000 if DEBUG_MSM_UART
 	default 0xf0000be0 if ARCH_EBSA110
 	default 0xf0009000 if DEBUG_CNS3XXX
+	default 0xf0010000 if DEBUG_ASM9260_UART
 	default 0xf01fb000 if DEBUG_NOMADIK_UART
 	default 0xf0201000 if DEBUG_BCM2835
 	default 0xf1000300 if DEBUG_BCM_5301X
@@ -1194,7 +1219,8 @@ config DEBUG_UART_VIRT
 	default DEBUG_UART_PHYS if !MMU
 	depends on DEBUG_LL_UART_8250 || DEBUG_LL_UART_PL01X || \
 		DEBUG_UART_8250 || DEBUG_UART_PL01X || \
-		DEBUG_MSM_UART || DEBUG_QCOM_UARTDM || DEBUG_S3C24XX_UART
+		DEBUG_MSM_UART || DEBUG_QCOM_UARTDM || \
+		DEBUG_S3C24XX_UART || DEBUG_ASM9260_UART
 
 config DEBUG_UART_8250_SHIFT
 	int "Register offset shift for the 8250 debug UART"
@@ -1236,7 +1262,8 @@ config DEBUG_UNCOMPRESS
 config UNCOMPRESS_INCLUDE
 	string
 	default "debug/uncompress.h" if ARCH_MULTIPLATFORM || ARCH_MSM || \
-					PLAT_SAMSUNG || ARCH_EFM32
+					PLAT_SAMSUNG || ARCH_EFM32 || \
+					MACH_ASM9260
 	default "mach/uncompress.h"
 
 config EARLY_PRINTK
arch/arm/include/debug/asm9260.S new file +31 -0
new file mode 100644
index 0000000..c70d51f
@@ -0,0 +1,31 @@
+/* arch/arm/mach-imx/include/mach/debug-macro.S
+ *
+ * Debugging macro include header
+ *
+ *  Copyright (C) 1994-1999 Russell King
+ *  Moved from linux/arch/arm/kernel/debug.S by Ben Dooks
+ *  Modified for ASM9260 by Oleksij Remepl <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+		.macro	addruart, rp, rv, tmp
+		ldr	\rp, = CONFIG_DEBUG_UART_PHYS
+		ldr	\rv, = CONFIG_DEBUG_UART_VIRT
+		.endm
+
+		.macro	waituart,rd,rx
+		.endm
+
+		.macro	senduart,rd,rx
+		str	\rd, [\rx, #0x50]	@ TXDATA
+		.endm
+
+		.macro	busyuart,rd,rx
+1002:		ldr	\rd, [\rx, #0x60]	@ STAT
+		tst	\rd, #1 << 27		@ TXEMPTY
+		beq	1002b			@ wait until transmit done
+		.endm
Signature · 1 line
1.9.1
#3 lore raw

PATCH v5 3/10 ARM: clk: add clk-asm9260 driver

In reply to Oleksij Rempel

Provide CLK support for Alphascale ASM9260 SoC.

---
 drivers/clk/Makefile                           |   1 +
 drivers/clk/clk-asm9260.c                      | 351 +++++++++++++++++++++++++
 include/dt-bindings/clock/alphascale,asm9260.h |  97 +++++++
 3 files changed, 449 insertions(+)
 create mode 100644 drivers/clk/clk-asm9260.c
 create mode 100644 include/dt-bindings/clock/alphascale,asm9260.h
drivers/clk/Makefile +1 -0
index f537a0b..45bbf22 100644
@@ -43,6 +43,7 @@ obj-$(CONFIG_ARCH_HI3xxx)		+= hisilicon/
 obj-$(CONFIG_ARCH_HIP04)		+= hisilicon/
 obj-$(CONFIG_ARCH_HIX5HD2)		+= hisilicon/
 obj-$(CONFIG_COMMON_CLK_KEYSTONE)	+= keystone/
+obj-$(CONFIG_MACH_ASM9260)		+= clk-asm9260.o
 ifeq ($(CONFIG_COMMON_CLK), y)
 obj-$(CONFIG_ARCH_MMP)			+= mmp/
 endif
drivers/clk/clk-asm9260.c new file +351 -0

351 lines not on this page · raw message

include/dt-bindings/clock/alphascale,asm9260.h new file +97 -0

97 lines not on this page · raw message

Signature · 1 line
1.9.1
#4 lore raw

PATCH v5 4/10 ARM: irqchip: mxs: prepare driver for HW with different offsets

In reply to Oleksij Rempel

Some HW has similar functionality but different register offsets. Make sure we can change offsets dynamically.

---
 drivers/irqchip/irq-mxs.c | 55 ++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 42 insertions(+), 13 deletions(-)
drivers/irqchip/irq-mxs.c +42 -13
index e4acf1e..681125d 100644
@@ -29,18 +29,39 @@
 
 #include "irqchip.h"
 
+/*
+ * this device provide 4 offsets for each register:
+ * 0x0 - plain read write mode
+ * 0x4 - set mode, OR logic.
+ * 0x8 - clr mode, XOR logic.
+ * 0xc - togle mode.
+ */
+#define SET_REG 4
+#define CLR_REG 8
+
 #define HW_ICOLL_VECTOR				0x0000
 #define HW_ICOLL_LEVELACK			0x0010
 #define HW_ICOLL_CTRL				0x0020
 #define HW_ICOLL_STAT_OFFSET			0x0070
-#define HW_ICOLL_INTERRUPTn_SET(n)		(0x0124 + (n) * 0x10)
-#define HW_ICOLL_INTERRUPTn_CLR(n)		(0x0128 + (n) * 0x10)
-#define BM_ICOLL_INTERRUPTn_ENABLE		0x00000004
+#define HW_ICOLL_INTERRUPT0			0x0120
+#define HW_ICOLL_INTERRUPTn(n)			((n) * 0x10)
+#define BM_ICOLL_INTR_ENABLE			BIT(2)
 #define BV_ICOLL_LEVELACK_IRQLEVELACK__LEVEL0	0x1
 
 #define ICOLL_NUM_IRQS		128
 
-static void __iomem *icoll_base;
+struct icoll_priv {
+	void __iomem *vector;
+	void __iomem *levelack;
+	void __iomem *ctrl;
+	void __iomem *stat;
+	void __iomem *intr;
+	/* number of interrupts per register */
+	int intr_per_reg;
+	void __iomem *clear;
+};
+
+static struct icoll_priv icoll_priv;
 static struct irq_domain *icoll_domain;
 
 static void icoll_ack_irq(struct irq_data *d)
@@ -51,19 +72,19 @@ static void icoll_ack_irq(struct irq_data *d)
 	 * BV_ICOLL_LEVELACK_IRQLEVELACK__LEVEL0 unconditionally.
 	 */
 	__raw_writel(BV_ICOLL_LEVELACK_IRQLEVELACK__LEVEL0,
-			icoll_base + HW_ICOLL_LEVELACK);
+			icoll_priv.levelack);
 }
 
 static void icoll_mask_irq(struct irq_data *d)
 {
-	__raw_writel(BM_ICOLL_INTERRUPTn_ENABLE,
-			icoll_base + HW_ICOLL_INTERRUPTn_CLR(d->hwirq));
+	__raw_writel(BM_ICOLL_INTR_ENABLE,
+			icoll_priv.intr + CLR_REG + HW_ICOLL_INTERRUPTn(d->hwirq));
 }
 
 static void icoll_unmask_irq(struct irq_data *d)
 {
-	__raw_writel(BM_ICOLL_INTERRUPTn_ENABLE,
-			icoll_base + HW_ICOLL_INTERRUPTn_SET(d->hwirq));
+	__raw_writel(BM_ICOLL_INTR_ENABLE,
+			icoll_priv.intr + SET_REG + HW_ICOLL_INTERRUPTn(d->hwirq));
 }
 
 static struct irq_chip mxs_icoll_chip = {
@@ -76,8 +97,8 @@ asmlinkage void __exception_irq_entry icoll_handle_irq(struct pt_regs *regs)
 {
 	u32 irqnr;
 
-	irqnr = __raw_readl(icoll_base + HW_ICOLL_STAT_OFFSET);
-	__raw_writel(irqnr, icoll_base + HW_ICOLL_VECTOR);
+	irqnr = __raw_readl(icoll_priv.stat);
+	__raw_writel(irqnr, icoll_priv.vector);
 	handle_domain_irq(icoll_domain, irqnr, regs);
 }
 
@@ -98,14 +119,22 @@ static struct irq_domain_ops icoll_irq_domain_ops = {
 static int __init icoll_of_init(struct device_node *np,
 			  struct device_node *interrupt_parent)
 {
-	icoll_base = of_iomap(np, 0);
+	void __iomem *icoll_base = of_iomap(np, 0);
 	WARN_ON(!icoll_base);
 
+	icoll_priv.vector	= icoll_base + HW_ICOLL_VECTOR;
+	icoll_priv.levelack	= icoll_base + HW_ICOLL_LEVELACK;
+	icoll_priv.ctrl		= icoll_base + HW_ICOLL_CTRL;
+	icoll_priv.stat		= icoll_base + HW_ICOLL_STAT_OFFSET;
+	icoll_priv.intr		= icoll_base + HW_ICOLL_INTERRUPT0;
+	icoll_priv.intr_per_reg	= 1;
+	icoll_priv.clear	= NULL;
+
 	/*
 	 * Interrupt Collector reset, which initializes the priority
 	 * for each irq to level 0.
 	 */
-	stmp_reset_block(icoll_base + HW_ICOLL_CTRL);
+	stmp_reset_block(icoll_priv.ctrl);
 
 	icoll_domain = irq_domain_add_linear(np, ICOLL_NUM_IRQS,
 					     &icoll_irq_domain_ops, NULL);
Signature · 1 line
1.9.1
#5 lore raw

PATCH v5 5/10 ARM: irqchip: mxs: add Alpascale ASM9260 support

In reply to Oleksij Rempel

Freescale iMX23/iMX28 and Alphascale ASM9260 have similar interrupt collectors. It makes easy to reuse irq-mxs code for ASM9260. Differences between this devices are fallowing:
- different register offsets
- different count of intterupt lines per register
- ASM9260 don't provide reset bit
- ASM9260 don't support FIQ.

---
 drivers/irqchip/Kconfig                    |   5 ++
 drivers/irqchip/Makefile                   |   2 +-
 drivers/irqchip/alphascale_asm9260-icoll.h | 109 ++++++++++++++++++++++++++++
 drivers/irqchip/irq-mxs.c                  | 112 ++++++++++++++++++++++++++---
 4 files changed, 219 insertions(+), 9 deletions(-)
 create mode 100644 drivers/irqchip/alphascale_asm9260-icoll.h
drivers/irqchip/Kconfig +5 -0
index b8632bf..2ee202f 100644
@@ -113,3 +113,8 @@ config IRQ_CROSSBAR
 	  The primary irqchip invokes the crossbar's callback which inturn allocates
 	  a free irq and configures the IP. Thus the peripheral interrupts are
 	  routed to one of the free irqchip interrupt lines.
+
+config IRQ_MXS
+	bool
+	select IRQ_DOMAIN
+	select STMP_DEVICE
drivers/irqchip/Makefile +1 -1
index 73052ba..89c7042 100644
@@ -4,7 +4,7 @@ obj-$(CONFIG_ARCH_BCM2835)		+= irq-bcm2835.o
 obj-$(CONFIG_ARCH_EXYNOS)		+= exynos-combiner.o
 obj-$(CONFIG_ARCH_MMP)			+= irq-mmp.o
 obj-$(CONFIG_ARCH_MVEBU)		+= irq-armada-370-xp.o
-obj-$(CONFIG_ARCH_MXS)			+= irq-mxs.o
+obj-$(CONFIG_IRQ_MXS)			+= irq-mxs.o
 obj-$(CONFIG_ARCH_S3C24XX)		+= irq-s3c24xx.o
 obj-$(CONFIG_DW_APB_ICTL)		+= irq-dw-apb-ictl.o
 obj-$(CONFIG_METAG)			+= irq-metag-ext.o
drivers/irqchip/alphascale_asm9260-icoll.h new file +109 -0

109 lines not on this page · raw message

drivers/irqchip/irq-mxs.c +104 -8

155 lines not on this page · raw message

Signature · 1 line
1.9.1
#6 lore raw

PATCH v5 6/10 ARM: clocksource: add asm9260_timer driver

In reply to Oleksij Rempel

In some cases asm9260 looks similar to iMX2x. One of exceptions is timer controller. So this patch introduces new driver for this special case.

---
 drivers/clocksource/Kconfig         |   4 +
 drivers/clocksource/Makefile        |   1 +
 drivers/clocksource/asm9260_timer.c | 234 ++++++++++++++++++++++++++++++++++++
 3 files changed, 239 insertions(+)
 create mode 100644 drivers/clocksource/asm9260_timer.c
drivers/clocksource/Kconfig +4 -0
index cfd6519..6a03d34 100644
@@ -216,4 +216,8 @@ config CLKSRC_VERSATILE
 	  ARM Versatile, RealView and Versatile Express reference
 	  platforms.
 
+config ASM9260_TIMER
+	select CLKSRC_MMIO
+	bool
+
 endmenu
drivers/clocksource/Makefile +1 -0
index 7fd9fd1..fc93854 100644
@@ -44,3 +44,4 @@ obj-$(CONFIG_CLKSRC_METAG_GENERIC)	+= metag_generic.o
 obj-$(CONFIG_ARCH_HAS_TICK_BROADCAST)	+= dummy_timer.o
 obj-$(CONFIG_ARCH_KEYSTONE)		+= timer-keystone.o
 obj-$(CONFIG_CLKSRC_VERSATILE)		+= versatile.o
+obj-$(CONFIG_ASM9260_TIMER)		+= asm9260_timer.o
drivers/clocksource/asm9260_timer.c new file +234 -0

234 lines not on this page · raw message

Signature · 1 line
1.9.1
#7 lore raw

PATCH v5 6/10 ARM: clocksource: add asm9260_timer driver

Quoted 128 lines · Oleksij Rempel

In some cases asm9260 looks similar to iMX2x. One of exceptions is timer controller. So this patch introduces new driver for this special case.

---
 drivers/clocksource/Kconfig         |   4 +
 drivers/clocksource/Makefile        |   1 +
 drivers/clocksource/asm9260_timer.c | 234 ++++++++++++++++++++++++++++++++++++
 3 files changed, 239 insertions(+)
 create mode 100644 drivers/clocksource/asm9260_timer.c
drivers/clocksource/Kconfig +4 -0
index cfd6519..6a03d34 100644
@@ -216,4 +216,8 @@ config CLKSRC_VERSATILE
 	  ARM Versatile, RealView and Versatile Express reference
 	  platforms.
 
+config ASM9260_TIMER
+	select CLKSRC_MMIO
+	bool
+
 endmenu
drivers/clocksource/Makefile +1 -0
index 7fd9fd1..fc93854 100644
@@ -44,3 +44,4 @@ obj-$(CONFIG_CLKSRC_METAG_GENERIC)	+= metag_generic.o
 obj-$(CONFIG_ARCH_HAS_TICK_BROADCAST)	+= dummy_timer.o
 obj-$(CONFIG_ARCH_KEYSTONE)		+= timer-keystone.o
 obj-$(CONFIG_CLKSRC_VERSATILE)		+= versatile.o
+obj-$(CONFIG_ASM9260_TIMER)		+= asm9260_timer.o
drivers/clocksource/asm9260_timer.c new file +89 -0
new file mode 100644
index 0000000..1b16e00
@@ -0,0 +1,234 @@
+/*
+ * Copyright (C) 2014 Oleksij Rempel <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/clk.h>
+#include <linux/clocksource.h>
+#include <linux/clockchips.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/bitops.h>
+
+
+/*
+ * this device provide 4 offsets for each register:
+ * 0x0 - plain read write mode
+ * 0x4 - set mode, OR logic.
+ * 0x8 - clr mode, XOR logic.
+ * 0xc - togle mode.
+ */
+#define SET_REG 4
+#define CLR_REG 8
+
+#define HW_IR           0x0000 /* RW. Interrupt */
+#define BM_IR_CR0	BIT(4)
+#define BM_IR_MR3	BIT(3)
+#define BM_IR_MR2	BIT(2)
+#define BM_IR_MR1	BIT(1)
+#define BM_IR_MR0	BIT(0)
+
+#define HW_TCR		0x0010 /* RW. Timer controller */
+/* BM_C*_RST
+ * Timer Counter and the Prescale Counter are synchronously reset on the
+ * next positive edge of PCLK. The counters remain reset until TCR[1] is
+ * returned to zero. */
+#define BM_C3_RST	BIT(7)
+#define BM_C2_RST	BIT(6)
+#define BM_C1_RST	BIT(5)
+#define BM_C0_RST	BIT(4)
+/* BM_C*_EN
+ * 1 - Timer Counter and Prescale Counter are enabled for counting
+ * 0 - counters are disabled */
+#define BM_C3_EN	BIT(3)
+#define BM_C2_EN	BIT(2)
+#define BM_C1_EN	BIT(1)
+#define BM_C0_EN	BIT(0)
+
+#define HW_DIR		0x0020 /* RW. Direction? */
+/* 00 - count up
+ * 01 - count down
+ * 10 - ?? 2^n/2 */
+#define BM_DIR0_SHIFT	0
+#define BM_DIR1_SHIFT	4
+#define BM_DIR2_SHIFT	8
+#define BM_DIR3_SHIFT	12
+
+#define HW_TC0		0x0030 /* RO. Timer counter 0 */
+/* HW_TC*. Timer counter owerflow (0xffff.ffff to 0x0000.0000) do not generate
+ * interrupt. This registers can be used to detect overflow */
+#define HW_TC1          0x0040
+#define HW_TC2		0x0050
+#define HW_TC3		0x0060
+
+#define HW_PR		0x0070 /* RW. prescaler */
+#define HW_PC		0x0080 /* RO. Prescaler counter */
+#define HW_MCR		0x0090 /* RW. Match control */
+/* enable interrupt on match */
+#define BM_MCR_INT_EN(n)	(1 << (n * 3 + 0))
+/* enable TC reset on match */
+#define BM_MCR_RES_EN(n)	(1 << (n * 3 + 1))
+/* enable stop TC on match */
+#define BM_MCR_STOP_EN(n)	(1 << (n * 3 + 2))
+
+#define HW_MR0		0x00a0 /* RW. Match reg */
+#define HW_MR1		0x00b0
+#define HW_MR2		0x00C0
+#define HW_MR3		0x00D0
+#define HW_CCR		0x00E0 /* RW. Capture control */
+#define HW_CR0		0x00F0 /* RO. Capture reg */

drivers/clocksource/asm9260_timer.c line 99

Quoted 10 lines
drivers/clocksource/asm9260_timer.c new file +10 -0
+#define HW_CR1		0x0100
+#define HW_CR2		0x0110
+#define HW_CR3		0x0120
+#define HW_EMR		0x0130 /* RW. External Match */
+#define HW_PWMTH0	0x0140 /* RW. PWM width */
+#define HW_PWMTH1	0x0150
+#define HW_PWMTH2	0x0160
+#define HW_PWMTH3	0x0170
+#define HW_CTCR		0x0180 /* Counter control */
+#define HW_PWMC		0x0190 /* PWM control */

Please delete unused defines.

drivers/clocksource/asm9260_timer.c line 102

Quoted 3 lines
drivers/clocksource/asm9260_timer.c new file +3 -0
+
+static void __iomem *base;
+static unsigned long ticks_per_jiffy;

More elegant would be to put this in a struct which you pass to the functions.

Quoted 71 lines
drivers/clocksource/asm9260_timer.c new file +71 -0
+
+static int asm9260_timer_set_next_event(unsigned long delta,
+					 struct clock_event_device *dev)
+{
+	/* configure match count for TC0 */
+	writel_relaxed(delta, base + HW_MR0);
+	/* enable TC0 */
+	writel_relaxed(BM_C0_EN, base + HW_TCR + SET_REG);
+	return 0;
+}
+
+static void asm9260_timer_set_mode(enum clock_event_mode mode,
+				    struct clock_event_device *evt)
+{
+	/* stop timer0 */
+	writel_relaxed(BM_C0_EN, base + HW_TCR + CLR_REG);
+
+	switch (mode) {
+	case CLOCK_EVT_MODE_PERIODIC:
+		/* disable reset and stop on match */
+		writel_relaxed(BM_MCR_RES_EN(0) | BM_MCR_STOP_EN(0),
+				base + HW_MCR + CLR_REG);
+		/* configure match count for TC0 */
+		writel_relaxed(ticks_per_jiffy, base + HW_MR0);
+		/* enable TC0 */
+		writel_relaxed(BM_C0_EN, base + HW_TCR + SET_REG);
+		break;
+	case CLOCK_EVT_MODE_ONESHOT:
+		/* enable reset and stop on match */
+		writel_relaxed(BM_MCR_RES_EN(0) | BM_MCR_STOP_EN(0),
+				base + HW_MCR + SET_REG);
+		break;
+	default:
+		break;
+	}
+}
+
+static struct clock_event_device asm9260_clockevent_device = {
+	.name		= "asm9260-clockevent-dev",
+	.rating		= 200,
+	.features       = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
+	.set_next_event	= asm9260_timer_set_next_event,
+	.set_mode	= asm9260_timer_set_mode,
+};
+
+static irqreturn_t asm9260_timer_interrupt(int irq, void *dev_id)
+{
+	struct clock_event_device *evt = &asm9260_clockevent_device;
+
+	evt->event_handler(evt);
+
+	writel_relaxed(BM_IR_MR0, base + HW_IR);
+
+	return IRQ_HANDLED;
+}
+
+static struct irqaction asm9260_timer_irq = {
+	.name		= "asm9260-clockevent-dev",
+	.flags		= IRQF_TIMER | IRQF_IRQPOLL,
+	.handler	= asm9260_timer_interrupt,
+};
+
+/*
+ * ---------------------------------------------------------------------------
+ * Timer initialization
+ * ---------------------------------------------------------------------------
+ */
+
+static void __init asm9260_clockevent_init(struct clk *clk)
+{
+	unsigned long rate = clk_get_rate(clk);

drivers/clocksource/asm9260_timer.c line 183

Quoted 10 lines
drivers/clocksource/asm9260_timer.c new file +10 -0
+
+	ticks_per_jiffy = DIV_ROUND_CLOSEST(rate, HZ);
+	asm9260_clockevent_device.cpumask = cpumask_of(0);
+	clockevents_config_and_register(&asm9260_clockevent_device,
+					rate, 0x2c00, 0xfffffffe);
+}
+
+static void __init asm9260_clocksource_init(struct clk *clk)
+{
+	unsigned long hz = clk_get_rate(clk);

Why not call this in the asm9260_timer_init functions and pass the rate to clockevent_init and clocksource_init?

Quoted 17 lines
drivers/clocksource/asm9260_timer.c new file +17 -0
+
+	clocksource_mmio_init(base + HW_TC1,
+			"asm9260-clocksource", hz,
+			200, 32, clocksource_mmio_readl_up);
+
+	/* Seems like we can't use counter without match register even if
+	 * actions for MR are disabled. */
+	writel_relaxed(0xffffffff, base + HW_MR1);
+	/* enable TC1 */
+	writel_relaxed(BM_C1_EN, base + HW_TCR + SET_REG);
+}
+
+static void __init asm9260_timer_init(struct device_node *np)
+{
+	int irq;
+	struct clk *clk;
+	struct resource res;

drivers/clocksource/asm9260_timer.c line 210

Quoted 10 lines
drivers/clocksource/asm9260_timer.c new file +10 -0
+	int ret;
+
+	of_address_to_resource(np, 0, &res);
+	if (!request_mem_region(res.start, resource_size(&res),
+				"asm9260-timer"))
+		panic("%s: unable to request mem region", np->name);
+
+	base = ioremap_nocache(res.start, resource_size(&res));
+	if (!base)
+		panic("%s: unable to map resource", np->name);

Why don't you use of_io_request_and_map instead of this block?

drivers/clocksource/asm9260_timer.c line 219

Quoted 9 lines
drivers/clocksource/asm9260_timer.c new file +9 -0
+
+	clk = of_clk_get(np, 0);
+
+	ret = clk_prepare_enable(clk);
+	if (ret)
+		panic("Failed to enable clk!\n");
+
+	irq = irq_of_parse_and_map(np, 0);
+	setup_irq(irq, &asm9260_timer_irq);

Please use request_irq instead.

drivers/clocksource/asm9260_timer.c line 226

Quoted 7 lines
drivers/clocksource/asm9260_timer.c new file +7 -0
+
+	/* set all timers for count-up */
+	writel_relaxed(0, base + HW_DIR);
+	/* disable divider */
+	writel_relaxed(0, base + HW_PR);
+	/* make sure all timers use every rising PCLK edge. */
+	writel_relaxed(0, base + HW_CTCR);

Please use a define for this.

Quoted 9 lines
drivers/clocksource/asm9260_timer.c new file +8 -0
+	/* enable interrupt for TC0 and clean setting for all other lines */
+	writel_relaxed(BM_MCR_INT_EN(0) , base + HW_MCR);
+
+	asm9260_clocksource_init(clk);
+	asm9260_clockevent_init(clk);
+}
+CLOCKSOURCE_OF_DECLARE(asm9260_timer, "alphascale,asm9260-timer",
+		asm9260_timer_init);
#8 lore raw

PATCH v5 6/10 ARM: clocksource: add asm9260_timer driver

Hi Matthias,

of_io_request_and_map should use "const char *name" instead of "char *name".

And thank you for your feed back. Well for all suggestions of all of you :)

Am 15.10.2014 um 23:31 schrieb Matthias Brugger:

Quoted 297 lines · Oleksij Rempel
Quoted 128 lines

In some cases asm9260 looks similar to iMX2x. One of exceptions is timer controller. So this patch introduces new driver for this special case.

---
 drivers/clocksource/Kconfig         |   4 +
 drivers/clocksource/Makefile        |   1 +
 drivers/clocksource/asm9260_timer.c | 234 ++++++++++++++++++++++++++++++++++++
 3 files changed, 239 insertions(+)
 create mode 100644 drivers/clocksource/asm9260_timer.c
drivers/clocksource/Kconfig +4 -0
index cfd6519..6a03d34 100644
@@ -216,4 +216,8 @@ config CLKSRC_VERSATILE
 	  ARM Versatile, RealView and Versatile Express reference
 	  platforms.
 
+config ASM9260_TIMER
+	select CLKSRC_MMIO
+	bool
+
 endmenu
drivers/clocksource/Makefile +1 -0
index 7fd9fd1..fc93854 100644
@@ -44,3 +44,4 @@ obj-$(CONFIG_CLKSRC_METAG_GENERIC)	+= metag_generic.o
 obj-$(CONFIG_ARCH_HAS_TICK_BROADCAST)	+= dummy_timer.o
 obj-$(CONFIG_ARCH_KEYSTONE)		+= timer-keystone.o
 obj-$(CONFIG_CLKSRC_VERSATILE)		+= versatile.o
+obj-$(CONFIG_ASM9260_TIMER)		+= asm9260_timer.o
drivers/clocksource/asm9260_timer.c new file +89 -0
new file mode 100644
index 0000000..1b16e00
@@ -0,0 +1,234 @@
+/*
+ * Copyright (C) 2014 Oleksij Rempel <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/clk.h>
+#include <linux/clocksource.h>
+#include <linux/clockchips.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/bitops.h>
+
+
+/*
+ * this device provide 4 offsets for each register:
+ * 0x0 - plain read write mode
+ * 0x4 - set mode, OR logic.
+ * 0x8 - clr mode, XOR logic.
+ * 0xc - togle mode.
+ */
+#define SET_REG 4
+#define CLR_REG 8
+
+#define HW_IR           0x0000 /* RW. Interrupt */
+#define BM_IR_CR0	BIT(4)
+#define BM_IR_MR3	BIT(3)
+#define BM_IR_MR2	BIT(2)
+#define BM_IR_MR1	BIT(1)
+#define BM_IR_MR0	BIT(0)
+
+#define HW_TCR		0x0010 /* RW. Timer controller */
+/* BM_C*_RST
+ * Timer Counter and the Prescale Counter are synchronously reset on the
+ * next positive edge of PCLK. The counters remain reset until TCR[1] is
+ * returned to zero. */
+#define BM_C3_RST	BIT(7)
+#define BM_C2_RST	BIT(6)
+#define BM_C1_RST	BIT(5)
+#define BM_C0_RST	BIT(4)
+/* BM_C*_EN
+ * 1 - Timer Counter and Prescale Counter are enabled for counting
+ * 0 - counters are disabled */
+#define BM_C3_EN	BIT(3)
+#define BM_C2_EN	BIT(2)
+#define BM_C1_EN	BIT(1)
+#define BM_C0_EN	BIT(0)
+
+#define HW_DIR		0x0020 /* RW. Direction? */
+/* 00 - count up
+ * 01 - count down
+ * 10 - ?? 2^n/2 */
+#define BM_DIR0_SHIFT	0
+#define BM_DIR1_SHIFT	4
+#define BM_DIR2_SHIFT	8
+#define BM_DIR3_SHIFT	12
+
+#define HW_TC0		0x0030 /* RO. Timer counter 0 */
+/* HW_TC*. Timer counter owerflow (0xffff.ffff to 0x0000.0000) do not generate
+ * interrupt. This registers can be used to detect overflow */
+#define HW_TC1          0x0040
+#define HW_TC2		0x0050
+#define HW_TC3		0x0060
+
+#define HW_PR		0x0070 /* RW. prescaler */
+#define HW_PC		0x0080 /* RO. Prescaler counter */
+#define HW_MCR		0x0090 /* RW. Match control */
+/* enable interrupt on match */
+#define BM_MCR_INT_EN(n)	(1 << (n * 3 + 0))
+/* enable TC reset on match */
+#define BM_MCR_RES_EN(n)	(1 << (n * 3 + 1))
+/* enable stop TC on match */
+#define BM_MCR_STOP_EN(n)	(1 << (n * 3 + 2))
+
+#define HW_MR0		0x00a0 /* RW. Match reg */
+#define HW_MR1		0x00b0
+#define HW_MR2		0x00C0
+#define HW_MR3		0x00D0
+#define HW_CCR		0x00E0 /* RW. Capture control */
+#define HW_CR0		0x00F0 /* RO. Capture reg */

drivers/clocksource/asm9260_timer.c line 99

Quoted 10 lines
drivers/clocksource/asm9260_timer.c new file +10 -0
+#define HW_CR1		0x0100
+#define HW_CR2		0x0110
+#define HW_CR3		0x0120
+#define HW_EMR		0x0130 /* RW. External Match */
+#define HW_PWMTH0	0x0140 /* RW. PWM width */
+#define HW_PWMTH1	0x0150
+#define HW_PWMTH2	0x0160
+#define HW_PWMTH3	0x0170
+#define HW_CTCR		0x0180 /* Counter control */
+#define HW_PWMC		0x0190 /* PWM control */

Please delete unused defines.

drivers/clocksource/asm9260_timer.c line 102

Quoted 3 lines
drivers/clocksource/asm9260_timer.c new file +3 -0
+
+static void __iomem *base;
+static unsigned long ticks_per_jiffy;

More elegant would be to put this in a struct which you pass to the functions.

Quoted 71 lines
drivers/clocksource/asm9260_timer.c new file +71 -0
+
+static int asm9260_timer_set_next_event(unsigned long delta,
+					 struct clock_event_device *dev)
+{
+	/* configure match count for TC0 */
+	writel_relaxed(delta, base + HW_MR0);
+	/* enable TC0 */
+	writel_relaxed(BM_C0_EN, base + HW_TCR + SET_REG);
+	return 0;
+}
+
+static void asm9260_timer_set_mode(enum clock_event_mode mode,
+				    struct clock_event_device *evt)
+{
+	/* stop timer0 */
+	writel_relaxed(BM_C0_EN, base + HW_TCR + CLR_REG);
+
+	switch (mode) {
+	case CLOCK_EVT_MODE_PERIODIC:
+		/* disable reset and stop on match */
+		writel_relaxed(BM_MCR_RES_EN(0) | BM_MCR_STOP_EN(0),
+				base + HW_MCR + CLR_REG);
+		/* configure match count for TC0 */
+		writel_relaxed(ticks_per_jiffy, base + HW_MR0);
+		/* enable TC0 */
+		writel_relaxed(BM_C0_EN, base + HW_TCR + SET_REG);
+		break;
+	case CLOCK_EVT_MODE_ONESHOT:
+		/* enable reset and stop on match */
+		writel_relaxed(BM_MCR_RES_EN(0) | BM_MCR_STOP_EN(0),
+				base + HW_MCR + SET_REG);
+		break;
+	default:
+		break;
+	}
+}
+
+static struct clock_event_device asm9260_clockevent_device = {
+	.name		= "asm9260-clockevent-dev",
+	.rating		= 200,
+	.features       = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
+	.set_next_event	= asm9260_timer_set_next_event,
+	.set_mode	= asm9260_timer_set_mode,
+};
+
+static irqreturn_t asm9260_timer_interrupt(int irq, void *dev_id)
+{
+	struct clock_event_device *evt = &asm9260_clockevent_device;
+
+	evt->event_handler(evt);
+
+	writel_relaxed(BM_IR_MR0, base + HW_IR);
+
+	return IRQ_HANDLED;
+}
+
+static struct irqaction asm9260_timer_irq = {
+	.name		= "asm9260-clockevent-dev",
+	.flags		= IRQF_TIMER | IRQF_IRQPOLL,
+	.handler	= asm9260_timer_interrupt,
+};
+
+/*
+ * ---------------------------------------------------------------------------
+ * Timer initialization
+ * ---------------------------------------------------------------------------
+ */
+
+static void __init asm9260_clockevent_init(struct clk *clk)
+{
+	unsigned long rate = clk_get_rate(clk);

drivers/clocksource/asm9260_timer.c line 183

Quoted 10 lines
drivers/clocksource/asm9260_timer.c new file +10 -0
+
+	ticks_per_jiffy = DIV_ROUND_CLOSEST(rate, HZ);
+	asm9260_clockevent_device.cpumask = cpumask_of(0);
+	clockevents_config_and_register(&asm9260_clockevent_device,
+					rate, 0x2c00, 0xfffffffe);
+}
+
+static void __init asm9260_clocksource_init(struct clk *clk)
+{
+	unsigned long hz = clk_get_rate(clk);

Why not call this in the asm9260_timer_init functions and pass the rate to clockevent_init and clocksource_init?

Quoted 17 lines
drivers/clocksource/asm9260_timer.c new file +17 -0
+
+	clocksource_mmio_init(base + HW_TC1,
+			"asm9260-clocksource", hz,
+			200, 32, clocksource_mmio_readl_up);
+
+	/* Seems like we can't use counter without match register even if
+	 * actions for MR are disabled. */
+	writel_relaxed(0xffffffff, base + HW_MR1);
+	/* enable TC1 */
+	writel_relaxed(BM_C1_EN, base + HW_TCR + SET_REG);
+}
+
+static void __init asm9260_timer_init(struct device_node *np)
+{
+	int irq;
+	struct clk *clk;
+	struct resource res;

drivers/clocksource/asm9260_timer.c line 210

Quoted 10 lines
drivers/clocksource/asm9260_timer.c new file +10 -0
+	int ret;
+
+	of_address_to_resource(np, 0, &res);
+	if (!request_mem_region(res.start, resource_size(&res),
+				"asm9260-timer"))
+		panic("%s: unable to request mem region", np->name);
+
+	base = ioremap_nocache(res.start, resource_size(&res));
+	if (!base)
+		panic("%s: unable to map resource", np->name);

Why don't you use of_io_request_and_map instead of this block?

drivers/clocksource/asm9260_timer.c line 219

Quoted 9 lines
drivers/clocksource/asm9260_timer.c new file +9 -0
+
+	clk = of_clk_get(np, 0);
+
+	ret = clk_prepare_enable(clk);
+	if (ret)
+		panic("Failed to enable clk!\n");
+
+	irq = irq_of_parse_and_map(np, 0);
+	setup_irq(irq, &asm9260_timer_irq);

Please use request_irq instead.

drivers/clocksource/asm9260_timer.c line 226

Quoted 7 lines
drivers/clocksource/asm9260_timer.c new file +7 -0
+
+	/* set all timers for count-up */
+	writel_relaxed(0, base + HW_DIR);
+	/* disable divider */
+	writel_relaxed(0, base + HW_PR);
+	/* make sure all timers use every rising PCLK edge. */
+	writel_relaxed(0, base + HW_CTCR);

Please use a define for this.

Quoted 9 lines
drivers/clocksource/asm9260_timer.c new file +8 -0
+	/* enable interrupt for TC0 and clean setting for all other lines */
+	writel_relaxed(BM_MCR_INT_EN(0) , base + HW_MCR);
+
+	asm9260_clocksource_init(clk);
+	asm9260_clockevent_init(clk);
+}
+CLOCKSOURCE_OF_DECLARE(asm9260_timer, "alphascale,asm9260-timer",
+		asm9260_timer_init);
Signature · 10 lines
Regards,
Oleksij

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 213 bytes
Desc: OpenPGP digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20141016/46527b13/attachment.sig>
#9 lore raw

PATCH v5 6/10 ARM: clocksource: add asm9260_timer driver

Hi Oleksij,

2014-10-16 12:46 GMT+02:00 Oleksij Rempel <[email protected]>:

Quoted 3 lines

Hi Matthias,

of_io_request_and_map should use "const char *name" instead of "char *name".

You are right, I will provide a patch for it these days.

Cheers,
Matthias

Quoted 307 lines

And thank you for your feed back. Well for all suggestions of all of you :)

Am 15.10.2014 um 23:31 schrieb Matthias Brugger:

Quoted 288 lines · Oleksij Rempel
Quoted 128 lines

In some cases asm9260 looks similar to iMX2x. One of exceptions is timer controller. So this patch introduces new driver for this special case.

---
 drivers/clocksource/Kconfig         |   4 +
 drivers/clocksource/Makefile        |   1 +
 drivers/clocksource/asm9260_timer.c | 234 ++++++++++++++++++++++++++++++++++++
 3 files changed, 239 insertions(+)
 create mode 100644 drivers/clocksource/asm9260_timer.c
drivers/clocksource/Kconfig +4 -0
index cfd6519..6a03d34 100644
@@ -216,4 +216,8 @@ config CLKSRC_VERSATILE
       ARM Versatile, RealView and Versatile Express reference
       platforms.
 
+config ASM9260_TIMER
+    select CLKSRC_MMIO
+    bool
+
 endmenu
drivers/clocksource/Makefile +1 -0
index 7fd9fd1..fc93854 100644
@@ -44,3 +44,4 @@ obj-$(CONFIG_CLKSRC_METAG_GENERIC) += metag_generic.o
 obj-$(CONFIG_ARCH_HAS_TICK_BROADCAST)       += dummy_timer.o
 obj-$(CONFIG_ARCH_KEYSTONE)         += timer-keystone.o
 obj-$(CONFIG_CLKSRC_VERSATILE)              += versatile.o
+obj-$(CONFIG_ASM9260_TIMER)         += asm9260_timer.o
drivers/clocksource/asm9260_timer.c new file +89 -0
new file mode 100644
index 0000000..1b16e00
@@ -0,0 +1,234 @@
+/*
+ * Copyright (C) 2014 Oleksij Rempel <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/clk.h>
+#include <linux/clocksource.h>
+#include <linux/clockchips.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/bitops.h>
+
+
+/*
+ * this device provide 4 offsets for each register:
+ * 0x0 - plain read write mode
+ * 0x4 - set mode, OR logic.
+ * 0x8 - clr mode, XOR logic.
+ * 0xc - togle mode.
+ */
+#define SET_REG 4
+#define CLR_REG 8
+
+#define HW_IR           0x0000 /* RW. Interrupt */
+#define BM_IR_CR0   BIT(4)
+#define BM_IR_MR3   BIT(3)
+#define BM_IR_MR2   BIT(2)
+#define BM_IR_MR1   BIT(1)
+#define BM_IR_MR0   BIT(0)
+
+#define HW_TCR              0x0010 /* RW. Timer controller */
+/* BM_C*_RST
+ * Timer Counter and the Prescale Counter are synchronously reset on the
+ * next positive edge of PCLK. The counters remain reset until TCR[1] is
+ * returned to zero. */
+#define BM_C3_RST   BIT(7)
+#define BM_C2_RST   BIT(6)
+#define BM_C1_RST   BIT(5)
+#define BM_C0_RST   BIT(4)
+/* BM_C*_EN
+ * 1 - Timer Counter and Prescale Counter are enabled for counting
+ * 0 - counters are disabled */
+#define BM_C3_EN    BIT(3)
+#define BM_C2_EN    BIT(2)
+#define BM_C1_EN    BIT(1)
+#define BM_C0_EN    BIT(0)
+
+#define HW_DIR              0x0020 /* RW. Direction? */
+/* 00 - count up
+ * 01 - count down
+ * 10 - ?? 2^n/2 */
+#define BM_DIR0_SHIFT       0
+#define BM_DIR1_SHIFT       4
+#define BM_DIR2_SHIFT       8
+#define BM_DIR3_SHIFT       12
+
+#define HW_TC0              0x0030 /* RO. Timer counter 0 */
+/* HW_TC*. Timer counter owerflow (0xffff.ffff to 0x0000.0000) do not generate
+ * interrupt. This registers can be used to detect overflow */
+#define HW_TC1          0x0040
+#define HW_TC2              0x0050
+#define HW_TC3              0x0060
+
+#define HW_PR               0x0070 /* RW. prescaler */
+#define HW_PC               0x0080 /* RO. Prescaler counter */
+#define HW_MCR              0x0090 /* RW. Match control */
+/* enable interrupt on match */
+#define BM_MCR_INT_EN(n)    (1 << (n * 3 + 0))
+/* enable TC reset on match */
+#define BM_MCR_RES_EN(n)    (1 << (n * 3 + 1))
+/* enable stop TC on match */
+#define BM_MCR_STOP_EN(n)   (1 << (n * 3 + 2))
+
+#define HW_MR0              0x00a0 /* RW. Match reg */
+#define HW_MR1              0x00b0
+#define HW_MR2              0x00C0
+#define HW_MR3              0x00D0
+#define HW_CCR              0x00E0 /* RW. Capture control */
+#define HW_CR0              0x00F0 /* RO. Capture reg */

drivers/clocksource/asm9260_timer.c line 99

Quoted 10 lines
drivers/clocksource/asm9260_timer.c new file +10 -0
+#define HW_CR1              0x0100
+#define HW_CR2              0x0110
+#define HW_CR3              0x0120
+#define HW_EMR              0x0130 /* RW. External Match */
+#define HW_PWMTH0   0x0140 /* RW. PWM width */
+#define HW_PWMTH1   0x0150
+#define HW_PWMTH2   0x0160
+#define HW_PWMTH3   0x0170
+#define HW_CTCR             0x0180 /* Counter control */
+#define HW_PWMC             0x0190 /* PWM control */

Please delete unused defines.

drivers/clocksource/asm9260_timer.c line 102

Quoted 3 lines
drivers/clocksource/asm9260_timer.c new file +3 -0
+
+static void __iomem *base;
+static unsigned long ticks_per_jiffy;

More elegant would be to put this in a struct which you pass to the functions.

Quoted 71 lines
drivers/clocksource/asm9260_timer.c new file +71 -0
+
+static int asm9260_timer_set_next_event(unsigned long delta,
+                                     struct clock_event_device *dev)
+{
+    /* configure match count for TC0 */
+    writel_relaxed(delta, base + HW_MR0);
+    /* enable TC0 */
+    writel_relaxed(BM_C0_EN, base + HW_TCR + SET_REG);
+    return 0;
+}
+
+static void asm9260_timer_set_mode(enum clock_event_mode mode,
+                                struct clock_event_device *evt)
+{
+    /* stop timer0 */
+    writel_relaxed(BM_C0_EN, base + HW_TCR + CLR_REG);
+
+    switch (mode) {
+    case CLOCK_EVT_MODE_PERIODIC:
+            /* disable reset and stop on match */
+            writel_relaxed(BM_MCR_RES_EN(0) | BM_MCR_STOP_EN(0),
+                            base + HW_MCR + CLR_REG);
+            /* configure match count for TC0 */
+            writel_relaxed(ticks_per_jiffy, base + HW_MR0);
+            /* enable TC0 */
+            writel_relaxed(BM_C0_EN, base + HW_TCR + SET_REG);
+            break;
+    case CLOCK_EVT_MODE_ONESHOT:
+            /* enable reset and stop on match */
+            writel_relaxed(BM_MCR_RES_EN(0) | BM_MCR_STOP_EN(0),
+                            base + HW_MCR + SET_REG);
+            break;
+    default:
+            break;
+    }
+}
+
+static struct clock_event_device asm9260_clockevent_device = {
+    .name           = "asm9260-clockevent-dev",
+    .rating         = 200,
+    .features       = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
+    .set_next_event = asm9260_timer_set_next_event,
+    .set_mode       = asm9260_timer_set_mode,
+};
+
+static irqreturn_t asm9260_timer_interrupt(int irq, void *dev_id)
+{
+    struct clock_event_device *evt = &asm9260_clockevent_device;
+
+    evt->event_handler(evt);
+
+    writel_relaxed(BM_IR_MR0, base + HW_IR);
+
+    return IRQ_HANDLED;
+}
+
+static struct irqaction asm9260_timer_irq = {
+    .name           = "asm9260-clockevent-dev",
+    .flags          = IRQF_TIMER | IRQF_IRQPOLL,
+    .handler        = asm9260_timer_interrupt,
+};
+
+/*
+ * ---------------------------------------------------------------------------
+ * Timer initialization
+ * ---------------------------------------------------------------------------
+ */
+
+static void __init asm9260_clockevent_init(struct clk *clk)
+{
+    unsigned long rate = clk_get_rate(clk);

drivers/clocksource/asm9260_timer.c line 183

Quoted 10 lines
drivers/clocksource/asm9260_timer.c new file +10 -0
+
+    ticks_per_jiffy = DIV_ROUND_CLOSEST(rate, HZ);
+    asm9260_clockevent_device.cpumask = cpumask_of(0);
+    clockevents_config_and_register(&asm9260_clockevent_device,
+                                    rate, 0x2c00, 0xfffffffe);
+}
+
+static void __init asm9260_clocksource_init(struct clk *clk)
+{
+    unsigned long hz = clk_get_rate(clk);

Why not call this in the asm9260_timer_init functions and pass the rate to clockevent_init and clocksource_init?

Quoted 17 lines
drivers/clocksource/asm9260_timer.c new file +17 -0
+
+    clocksource_mmio_init(base + HW_TC1,
+                    "asm9260-clocksource", hz,
+                    200, 32, clocksource_mmio_readl_up);
+
+    /* Seems like we can't use counter without match register even if
+     * actions for MR are disabled. */
+    writel_relaxed(0xffffffff, base + HW_MR1);
+    /* enable TC1 */
+    writel_relaxed(BM_C1_EN, base + HW_TCR + SET_REG);
+}
+
+static void __init asm9260_timer_init(struct device_node *np)
+{
+    int irq;
+    struct clk *clk;
+    struct resource res;

drivers/clocksource/asm9260_timer.c line 210

Quoted 10 lines
drivers/clocksource/asm9260_timer.c new file +10 -0
+    int ret;
+
+    of_address_to_resource(np, 0, &res);
+    if (!request_mem_region(res.start, resource_size(&res),
+                            "asm9260-timer"))
+            panic("%s: unable to request mem region", np->name);
+
+    base = ioremap_nocache(res.start, resource_size(&res));
+    if (!base)
+            panic("%s: unable to map resource", np->name);

Why don't you use of_io_request_and_map instead of this block?

drivers/clocksource/asm9260_timer.c line 219

Quoted 9 lines
drivers/clocksource/asm9260_timer.c new file +9 -0
+
+    clk = of_clk_get(np, 0);
+
+    ret = clk_prepare_enable(clk);
+    if (ret)
+            panic("Failed to enable clk!\n");
+
+    irq = irq_of_parse_and_map(np, 0);
+    setup_irq(irq, &asm9260_timer_irq);

Please use request_irq instead.

drivers/clocksource/asm9260_timer.c line 226

Quoted 7 lines
drivers/clocksource/asm9260_timer.c new file +7 -0
+
+    /* set all timers for count-up */
+    writel_relaxed(0, base + HW_DIR);
+    /* disable divider */
+    writel_relaxed(0, base + HW_PR);
+    /* make sure all timers use every rising PCLK edge. */
+    writel_relaxed(0, base + HW_CTCR);

Please use a define for this.

Quoted 9 lines

drivers/clocksource/asm9260_timer.c line 234

Quoted 9 lines
drivers/clocksource/asm9260_timer.c new file +8 -0
+    /* enable interrupt for TC0 and clean setting for all other lines */
+    writel_relaxed(BM_MCR_INT_EN(0) , base + HW_MCR);
+
+    asm9260_clocksource_init(clk);
+    asm9260_clockevent_init(clk);
+}
+CLOCKSOURCE_OF_DECLARE(asm9260_timer, "alphascale,asm9260-timer",
+            asm9260_timer_init);

--
Regards,
Oleksij

Signature · 1 line
motzblog.wordpress.com
#10 lore raw

PATCH v6 1/1 ARM: clocksource: add asm9260_timer driver

In reply to Matthias Brugger

In some cases asm9260 looks similar to iMX2x. One of exceptions is timer controller. So this patch introduces new driver for this special case.

---
 drivers/clocksource/Kconfig         |   4 +
 drivers/clocksource/Makefile        |   1 +
 drivers/clocksource/asm9260_timer.c | 220 ++++++++++++++++++++++++++++++++++++
 3 files changed, 225 insertions(+)
 create mode 100644 drivers/clocksource/asm9260_timer.c
drivers/clocksource/Kconfig +4 -0
index cfd6519..6a03d34 100644
@@ -216,4 +216,8 @@ config CLKSRC_VERSATILE
 	  ARM Versatile, RealView and Versatile Express reference
 	  platforms.
 
+config ASM9260_TIMER
+	select CLKSRC_MMIO
+	bool
+
 endmenu
drivers/clocksource/Makefile +1 -0
index 7fd9fd1..fc93854 100644
@@ -44,3 +44,4 @@ obj-$(CONFIG_CLKSRC_METAG_GENERIC)	+= metag_generic.o
 obj-$(CONFIG_ARCH_HAS_TICK_BROADCAST)	+= dummy_timer.o
 obj-$(CONFIG_ARCH_KEYSTONE)		+= timer-keystone.o
 obj-$(CONFIG_CLKSRC_VERSATILE)		+= versatile.o
+obj-$(CONFIG_ASM9260_TIMER)		+= asm9260_timer.o
drivers/clocksource/asm9260_timer.c new file +220 -0

220 lines not on this page · raw message

Signature · 1 line
1.9.1
maintainer
#11 lore raw

PATCH v6 1/1 ARM: clocksource: add asm9260_timer driver

drivers/clocksource/asm9260_timer.c line 220

Quoted 3 lines · On Friday 17 October 2014 11:46:05 Oleksij Rempel wrote:
drivers/clocksource/asm9260_timer.c new file +2 -0
+CLOCKSOURCE_OF_DECLARE(asm9260_timer, "alphascale," DRIVER_NAME,
+               asm9260_timer_init);

Please avoid the use of the DRIVER_NAME macro here, it makes it very hard to grep for uses of the compatible string.

You forgot to put Daniel Lezcano <[email protected]> on Cc for the submission.

Arnd

#12 lore raw

PATCH v5 7/10 ARM: tty: mxs-auart: add initial Alphascale ASM9260 support

In reply to Oleksij Rempel

Alphascale ASM9260 uart IP has some common registers with Freescale STMP37XX. This patch provide initial changes which allow to reuse mxs-auart.c code for ASM9260.

---
 drivers/tty/serial/Kconfig                     |   5 +-
 drivers/tty/serial/alphascale,asm9260_serial.h | 373 +++++++++++++++++++++++++
 drivers/tty/serial/mxs-auart.c                 | 344 +++++++++++++++--------
 3 files changed, 599 insertions(+), 123 deletions(-)
 create mode 100644 drivers/tty/serial/alphascale,asm9260_serial.h
drivers/tty/serial/Kconfig +3 -2
index 26cec64..11bbb76 100644
@@ -1385,11 +1385,12 @@ config SERIAL_MSM_SMD
 	  ports via tty device interface for MSM chipset.
 
 config SERIAL_MXS_AUART
-	depends on ARCH_MXS
+	depends on ARCH_MXS || MACH_ASM9260
 	tristate "MXS AUART support"
 	select SERIAL_CORE
 	help
-	  This driver supports the MXS Application UART (AUART) port.
+	  This driver supports the MXS and Alphascale ASM9260 Application
+	  UART (AUART) port.
 
 config SERIAL_MXS_AUART_CONSOLE
 	bool "MXS AUART console support"
drivers/tty/serial/alphascale,asm9260_serial.h new file +373 -0

373 lines not on this page · raw message

drivers/tty/serial/mxs-auart.c +223 -121

764 lines not on this page · raw message

Signature · 1 line
1.9.1
#13 lore raw

PATCH v5 8/10 ARM: dts: add DT for Alphascale ASM9260 SoC

In reply to Oleksij Rempel

for now it is wary basic SoC description with most important IPs needed to make this device work

---
 arch/arm/boot/dts/Makefile                      |   2 +
 arch/arm/boot/dts/alphascale-asm9260-devkit.dts |  21 ++++
 arch/arm/boot/dts/alphascale-asm9260.dtsi       | 134 ++++++++++++++++++++++++
 3 files changed, 157 insertions(+)
 create mode 100644 arch/arm/boot/dts/alphascale-asm9260-devkit.dts
 create mode 100644 arch/arm/boot/dts/alphascale-asm9260.dtsi
arch/arm/boot/dts/Makefile +2 -0
index b8c5cd3..8943d72 100644
@@ -492,6 +492,8 @@ dtb-$(CONFIG_MACH_DOVE) += dove-cm-a510.dtb \
 	dove-d3plug.dtb \
 	dove-dove-db.dtb
 
+dtb-$(CONFIG_MACH_ASM9260) += alphascale-asm9260-devkit.dtb
+
 targets += dtbs dtbs_install
 targets += $(dtb-y)
 endif
arch/arm/boot/dts/alphascale-asm9260-devkit.dts new file +21 -0
new file mode 100644
index 0000000..bf63dd2
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2014 Oleksij Rempel <[email protected]>
+ *
+ * Licensed under the X11 license or the GPL v2 (or later)
+ */
+
+/dts-v1/;
+#include "alphascale-asm9260.dtsi"
+
+/ {
+	model = "Alphascale asm9260 Development Kit";
+	compatible = "alphascale,asm9260devkit", "alphascale,asm9260";
+
+	aliases {
+		serial0 = &uart4;
+	};
+};
+
+&uart4 {
+	status = "okay";
+};
arch/arm/boot/dts/alphascale-asm9260.dtsi new file +134 -0

134 lines not on this page · raw message

Signature · 1 line
1.9.1
#14 lore raw

PATCH v5 9/10 ARM: add alphascale,acc.txt bindings documentation

In reply to Oleksij Rempel

ACC is for AlphaScale Clock Controller.

---
 .../devicetree/bindings/clock/alphascale,acc.txt   | 115 +++++++++++++++++++++
 1 file changed, 115 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/alphascale,acc.txt
Documentation/devicetree/bindings/clock/alphascale,acc.txt new file +115 -0
new file mode 100644
index 0000000..62e67e8
@@ -0,0 +1,115 @@
+Alphascale Clock Controller
+
+The ACC (Alphascale Clock Controller) is responsible of choising proper
+clock source, setting deviders and clock gates.
+
+Required properties for the ACC node:
+ - compatible: must be "alphascale,asm9260-clock-controller"
+ - reg: must contain the ACC register base and size
+ - #clock-cells : shall be set to 1.
+
+Simple one-cell clock specifier format is used, where the only cell is used
+as an index of the clock inside the provider.
+It is encouraged to use dt-binding for clock index definitions. SoC specific
+dt-binding should be included to the device tree descriptor. For example
+Alphascale ASM9260:
+#include <dt-bindings/clock/alphascale,asm9260.h>
+
+This binding contains two types of clock providers:
+ _AHB_ - AHB gate;
+ _SYS_ - adjustable clock source. Not all peripheral have _SYS_ clock provider.
+All clock specific details can be found in the SoC documentation.
+CLKID_AHB_ROM		0
+CLKID_AHB_RAM		1
+CLKID_AHB_GPIO		2
+CLKID_AHB_MAC		3
+CLKID_AHB_EMI		4
+CLKID_AHB_USB0		5
+CLKID_AHB_USB1		6
+CLKID_AHB_DMA0		7
+CLKID_AHB_DMA1		8
+CLKID_AHB_UART0		9
+CLKID_AHB_UART1		10
+CLKID_AHB_UART2		11
+CLKID_AHB_UART3		12
+CLKID_AHB_UART4		13
+CLKID_AHB_UART5		14
+CLKID_AHB_UART6		15
+CLKID_AHB_UART7		16
+CLKID_AHB_UART8		17
+CLKID_AHB_UART9		18
+CLKID_AHB_I2S0		19
+CLKID_AHB_I2C0		20
+CLKID_AHB_I2C1		21
+CLKID_AHB_SSP0		22
+CLKID_AHB_IOCONFIG	23
+CLKID_AHB_WDT		24
+CLKID_AHB_CAN0		25
+CLKID_AHB_CAN1		26
+CLKID_AHB_MPWM		27
+CLKID_AHB_SPI0		28
+CLKID_AHB_SPI1		29
+CLKID_AHB_QEI		30
+CLKID_AHB_QUADSPI0	31
+CLKID_AHB_CAMIF		32
+CLKID_AHB_LCDIF		33
+CLKID_AHB_TIMER0	34
+CLKID_AHB_TIMER1	35
+CLKID_AHB_TIMER2	36
+CLKID_AHB_TIMER3	37
+CLKID_AHB_IRQ		38
+CLKID_AHB_RTC		39
+CLKID_AHB_NAND		40
+CLKID_AHB_ADC0		41
+CLKID_AHB_LED		42
+CLKID_AHB_DAC0		43
+CLKID_AHB_LCD		44
+CLKID_AHB_I2S1		45
+CLKID_AHB_MAC1		46
+
+CLKID_SYS_CPU		47
+CLKID_SYS_AHB		48
+CLKID_SYS_I2S0M		49
+CLKID_SYS_I2S0S		50
+CLKID_SYS_I2S1M		51
+CLKID_SYS_I2S1S		52
+CLKID_SYS_UART0		53
+CLKID_SYS_UART1		54
+CLKID_SYS_UART2		55
+CLKID_SYS_UART3		56
+CLKID_SYS_UART4		56
+CLKID_SYS_UART5		57
+CLKID_SYS_UART6		58
+CLKID_SYS_UART7		59
+CLKID_SYS_UART8		60
+CLKID_SYS_UART9		61
+CLKID_SYS_SPI0		62
+CLKID_SYS_SPI1		63
+CLKID_SYS_QUADSPI	64
+CLKID_SYS_SSP0		65
+CLKID_SYS_NAND		66
+CLKID_SYS_TRACE		67
+CLKID_SYS_CAMM		68
+CLKID_SYS_WDT		69
+CLKID_SYS_CLKOUT	70
+CLKID_SYS_MAC		71
+CLKID_SYS_LCD		72
+CLKID_SYS_ADCANA	73
+
+Example of clock consumer with _SYS_ and _AHB_ sinks.
+uart4: serial at 80010000 {
+	compatible = "alphascale,asm9260-uart";
+	reg = <0x80010000 0x4000>;
+	clocks = <&acc CLKID_SYS_UART4>, <&acc CLKID_AHB_UART4>;
+	interrupts = <19>;
+	status = "disabled";
+};
+
+Clock consumer with only one, _AHB_ sink.
+timer0: timer at 80088000 {
+	compatible = "alphascale,asm9260-timer";
+	reg = <0x80088000 0x4000>;
+	clocks = <&acc CLKID_AHB_TIMER0>;
+	interrupts = <29>;
+};
+
Signature · 1 line
1.9.1
#15 lore raw

PATCH v5 10/10 add Alphascale to vendor-prefixes.txt

In reply to Oleksij Rempel

this company already provided some products, so it make sense to add them to vendor-prefixes.txt list

---
 Documentation/devicetree/bindings/vendor-prefixes.txt | 1 +
 1 file changed, 1 insertion(+)
Documentation/devicetree/bindings/vendor-prefixes.txt +1 -0
index ac7269f..23c862f 100644
@@ -11,6 +11,7 @@ adi	Analog Devices, Inc.
 aeroflexgaisler	Aeroflex Gaisler AB
 ak	Asahi Kasei Corp.
 allwinner	Allwinner Technology Co., Ltd.
+alphascale	AlphaScale Integrated Circuits Systems, Inc.
 altr	Altera Corp.
 amcc	Applied Micro Circuits Corporation (APM, formally AMCC)
 amd	Advanced Micro Devices (AMD), Inc.
Signature · 1 line
1.9.1