linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v5 00/10] initial suport for Alphascale ASM9260
@ 2014-10-14  8:03 Oleksij Rempel
  2014-10-14  8:03 ` [PATCH v5 01/10] ARM: add mach-asm9260 Oleksij Rempel
                   ` (9 more replies)
  0 siblings, 10 replies; 16+ messages in thread
From: Oleksij Rempel @ 2014-10-14  8:03 UTC (permalink / raw)
  To: linux-arm-kernel

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

-- 
1.9.1

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCH v5 01/10] ARM: add mach-asm9260
  2014-10-14  8:03 [PATCH v5 00/10] initial suport for Alphascale ASM9260 Oleksij Rempel
@ 2014-10-14  8:03 ` Oleksij Rempel
  2014-10-14  8:03 ` [PATCH v5 02/10] ARM: add lolevel debug support for asm9260 Oleksij Rempel
                   ` (8 subsequent siblings)
  9 siblings, 0 replies; 16+ messages in thread
From: Oleksij Rempel @ 2014-10-14  8:03 UTC (permalink / raw)
  To: linux-arm-kernel

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.

Signed-off-by: Oleksij Rempel <linux@rempel-privat.de>
---
 arch/arm/Kconfig              | 2 ++
 arch/arm/mach-asm9260/Kconfig | 8 ++++++++
 2 files changed, 10 insertions(+)
 create mode 100644 arch/arm/mach-asm9260/Kconfig

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 5918d40..87373da 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -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
diff --git a/arch/arm/mach-asm9260/Kconfig b/arch/arm/mach-asm9260/Kconfig
new file mode 100644
index 0000000..eef90d9
--- /dev/null
+++ b/arch/arm/mach-asm9260/Kconfig
@@ -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.
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH v5 02/10] ARM: add lolevel debug support for asm9260
  2014-10-14  8:03 [PATCH v5 00/10] initial suport for Alphascale ASM9260 Oleksij Rempel
  2014-10-14  8:03 ` [PATCH v5 01/10] ARM: add mach-asm9260 Oleksij Rempel
@ 2014-10-14  8:03 ` Oleksij Rempel
  2014-10-14  8:03 ` [PATCH v5 03/10] ARM: clk: add clk-asm9260 driver Oleksij Rempel
                   ` (7 subsequent siblings)
  9 siblings, 0 replies; 16+ messages in thread
From: Oleksij Rempel @ 2014-10-14  8:03 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Oleksij Rempel <linux@rempel-privat.de>
---
 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

diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug
index b11ad54..6902a57 100644
--- a/arch/arm/Kconfig.debug
+++ b/arch/arm/Kconfig.debug
@@ -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
diff --git a/arch/arm/include/debug/asm9260.S b/arch/arm/include/debug/asm9260.S
new file mode 100644
index 0000000..c70d51f
--- /dev/null
+++ b/arch/arm/include/debug/asm9260.S
@@ -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 <linux@rempel-privat.de>
+ *
+ * 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
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH v5 03/10] ARM: clk: add clk-asm9260 driver
  2014-10-14  8:03 [PATCH v5 00/10] initial suport for Alphascale ASM9260 Oleksij Rempel
  2014-10-14  8:03 ` [PATCH v5 01/10] ARM: add mach-asm9260 Oleksij Rempel
  2014-10-14  8:03 ` [PATCH v5 02/10] ARM: add lolevel debug support for asm9260 Oleksij Rempel
@ 2014-10-14  8:03 ` Oleksij Rempel
  2014-10-14  8:03 ` [PATCH v5 04/10] ARM: irqchip: mxs: prepare driver for HW with different offsets Oleksij Rempel
                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 16+ messages in thread
From: Oleksij Rempel @ 2014-10-14  8:03 UTC (permalink / raw)
  To: linux-arm-kernel

Provide CLK support for Alphascale ASM9260 SoC.

Signed-off-by: Oleksij Rempel <linux@rempel-privat.de>
---
 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

diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index f537a0b..45bbf22 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -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
diff --git a/drivers/clk/clk-asm9260.c b/drivers/clk/clk-asm9260.c
new file mode 100644
index 0000000..9ef4e8d
--- /dev/null
+++ b/drivers/clk/clk-asm9260.c
@@ -0,0 +1,351 @@
+/*
+ * Copyright (c) 2014 Oleksij Rempel <linux@rempel-privat.de>.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/clk-provider.h>
+#include <linux/spinlock.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <dt-bindings/clock/alphascale,asm9260.h>
+
+#define HW_AHBCLKCTRL0		0x0020
+#define HW_AHBCLKCTRL1		0x0030
+#define HW_SYSPLLCTRL		0x0100
+#define HW_MAINCLKSEL		0x0120
+#define HW_MAINCLKUEN		0x0124
+#define HW_UARTCLKSEL		0x0128
+#define HW_UARTCLKUEN		0x012c
+#define HW_I2S0CLKSEL		0x0130
+#define HW_I2S0CLKUEN		0x0134
+#define HW_I2S1CLKSEL		0x0138
+#define HW_I2S1CLKUEN		0x013c
+#define HW_WDTCLKSEL		0x0160
+#define HW_WDTCLKUEN		0x0164
+#define HW_CLKOUTCLKSEL		0x0170
+#define HW_CLKOUTCLKUEN		0x0174
+#define HW_CPUCLKDIV		0x017c
+#define HW_SYSAHBCLKDIV		0x0180
+#define HW_I2S0MCLKDIV		0x0190
+#define HW_I2S0SCLKDIV		0x0194
+#define HW_I2S1MCLKDIV		0x0188
+#define HW_I2S1SCLKDIV		0x018c
+#define HW_UART0CLKDIV		0x0198
+#define HW_UART1CLKDIV		0x019c
+#define HW_UART2CLKDIV		0x01a0
+#define HW_UART3CLKDIV		0x01a4
+#define HW_UART4CLKDIV		0x01a8
+#define HW_UART5CLKDIV		0x01ac
+#define HW_UART6CLKDIV		0x01b0
+#define HW_UART7CLKDIV		0x01b4
+#define HW_UART8CLKDIV		0x01b8
+#define HW_UART9CLKDIV		0x01bc
+#define HW_SPI0CLKDIV		0x01c0
+#define HW_SPI1CLKDIV		0x01c4
+#define HW_QUADSPICLKDIV	0x01c8
+#define HW_SSP0CLKDIV		0x01d0
+#define HW_NANDCLKDIV		0x01d4
+#define HW_TRACECLKDIV		0x01e0
+#define HW_CAMMCLKDIV		0x01e8
+#define HW_WDTCLKDIV		0x01ec
+#define HW_CLKOUTCLKDIV		0x01f4
+#define HW_MACCLKDIV		0x01f8
+#define HW_LCDCLKDIV		0x01fc
+#define HW_ADCANACLKDIV		0x0200
+
+static struct clk *clks[MAX_CLKS];
+static struct clk_onecell_data clk_data;
+static DEFINE_SPINLOCK(asm9260_clk_lock);
+
+struct asm9260_div_clk {
+	unsigned int idx;
+	const char *name;
+	const char *parent_name;
+	u32 reg;
+};
+
+struct asm9260_gate_data {
+	unsigned int idx;
+	const char *name;
+	const char *parent_name;
+	u32 reg;
+	u8 bit_idx;
+	unsigned long flags;
+};
+
+struct asm9260_mux_clock {
+	u8			mask;
+	u32			*table;
+	const char		*name;
+	const char		**parent_names;
+	u8			num_parents;
+	unsigned long		offset;
+	unsigned long		flags;
+};
+
+static void __iomem *base;
+
+enum {
+	REFCLK, SYSPLL, I2S0_MCLK, I2S1_MCLK, RTC_OSC, USB_PLL,
+};
+
+static const char *clk_names[] = {
+	[REFCLK]	= "oscillator",
+	[SYSPLL]	= "pll",
+	[I2S0_MCLK]	= "i2s0_mclk",
+	[I2S1_MCLK]	= "i2s1_mclk",
+	[RTC_OSC]	= "rtc_osc",
+	[USB_PLL]	= "usb_pll",
+};
+
+static const struct asm9260_div_clk asm9260_div_clks[] __initconst = {
+	{ CLKID_SYS_CPU,	"cpu_div", "main_gate", HW_CPUCLKDIV },
+	{ CLKID_SYS_AHB,	"ahb_div", "cpu_div", HW_SYSAHBCLKDIV },
+
+	/* i2s has two deviders: one for only external mclk and internal
+	 * devider for all clks. */
+	{ CLKID_SYS_I2S0M,	"i2s0m_div", "i2s0_mclk",  HW_I2S0MCLKDIV },
+	{ CLKID_SYS_I2S1M,	"i2s1m_div", "i2s1_mclk",  HW_I2S1MCLKDIV },
+	{ CLKID_SYS_I2S0S,	"i2s0s_div", "i2s0_gate",  HW_I2S0SCLKDIV },
+	{ CLKID_SYS_I2S1S,	"i2s1s_div", "i2s0_gate",  HW_I2S1SCLKDIV },
+
+	{ CLKID_SYS_UART0,	"uart0_div", "uart_gate", HW_UART0CLKDIV },
+	{ CLKID_SYS_UART1,	"uart1_div", "uart_gate", HW_UART1CLKDIV },
+	{ CLKID_SYS_UART2,	"uart2_div", "uart_gate", HW_UART2CLKDIV },
+	{ CLKID_SYS_UART3,	"uart3_div", "uart_gate", HW_UART3CLKDIV },
+	{ CLKID_SYS_UART4,	"uart4_div", "uart_gate", HW_UART4CLKDIV },
+	{ CLKID_SYS_UART5,	"uart5_div", "uart_gate", HW_UART5CLKDIV },
+	{ CLKID_SYS_UART6,	"uart6_div", "uart_gate", HW_UART6CLKDIV },
+	{ CLKID_SYS_UART7,	"uart7_div", "uart_gate", HW_UART7CLKDIV },
+	{ CLKID_SYS_UART8,	"uart8_div", "uart_gate", HW_UART8CLKDIV },
+	{ CLKID_SYS_UART9,	"uart9_div", "uart_gate", HW_UART9CLKDIV },
+};
+
+static const struct asm9260_gate_data asm9260_mux_gates[] __initconst = {
+	{ 0, "main_gate",	"main_mux",	HW_MAINCLKUEN,	0 },
+	{ 0, "uart_gate",	"uart_mux",	HW_UARTCLKUEN,	0 },
+	{ 0, "i2s0_gate",	"i2s0_mux",	HW_I2S0CLKUEN,	0 },
+	{ 0, "i2s1_gate",	"i2s1_mux",	HW_I2S1CLKUEN,	0 },
+	{ 0, "wdt_gate",	"wdt_mux",	HW_WDTCLKUEN,	0 },
+	{ 0, "clkout_gate",	"clkout_mux",	HW_CLKOUTCLKUEN, 0 },
+};
+static const struct asm9260_gate_data asm9260_ahb_gates[] __initconst = {
+	/* ahb gates */
+	{ CLKID_AHB_ROM,	"rom",		"ahb_div",
+		HW_AHBCLKCTRL0,	1, CLK_IGNORE_UNUSED},
+	{ CLKID_AHB_RAM,	"ram",		"ahb_div",
+		HW_AHBCLKCTRL0,	2, CLK_IGNORE_UNUSED},
+	{ CLKID_AHB_GPIO,	"gpio",		"ahb_div",
+		HW_AHBCLKCTRL0,	4 },
+	{ CLKID_AHB_MAC,	"mac",		"ahb_div",
+		HW_AHBCLKCTRL0,	5 },
+	{ CLKID_AHB_EMI,	"emi",		"ahb_div",
+		HW_AHBCLKCTRL0,	6, CLK_IGNORE_UNUSED},
+	{ CLKID_AHB_USB0,	"usb0",		"ahb_div",
+		HW_AHBCLKCTRL0,	7 },
+	{ CLKID_AHB_USB1,	"usb1",		"ahb_div",
+		HW_AHBCLKCTRL0,	8 },
+	{ CLKID_AHB_DMA0,	"dma0",		"ahb_div",
+		HW_AHBCLKCTRL0,	9 },
+	{ CLKID_AHB_DMA1,	"dma1",		"ahb_div",
+		HW_AHBCLKCTRL0,	10 },
+	{ CLKID_AHB_UART0,	"uart0",	"ahb_div",
+		HW_AHBCLKCTRL0,	11 },
+	{ CLKID_AHB_UART1,	"uart1",	"ahb_div",
+		HW_AHBCLKCTRL0,	12 },
+	{ CLKID_AHB_UART2,	"uart2",	"ahb_div",
+		HW_AHBCLKCTRL0,	13 },
+	{ CLKID_AHB_UART3,	"uart3",	"ahb_div",
+		HW_AHBCLKCTRL0,	14 },
+	{ CLKID_AHB_UART4,	"uart4",	"ahb_div",
+		HW_AHBCLKCTRL0,	15 },
+	{ CLKID_AHB_UART5,	"uart5",	"ahb_div",
+		HW_AHBCLKCTRL0,	16 },
+	{ CLKID_AHB_UART6,	"uart6",	"ahb_div",
+		HW_AHBCLKCTRL0,	17 },
+	{ CLKID_AHB_UART7,	"uart7",	"ahb_div",
+		HW_AHBCLKCTRL0,	18 },
+	{ CLKID_AHB_UART8,	"uart8",	"ahb_div",
+		HW_AHBCLKCTRL0,	19 },
+	{ CLKID_AHB_UART9,	"uart9",	"ahb_div",
+		HW_AHBCLKCTRL0,	20 },
+	{ CLKID_AHB_I2S0,	"i2s0",		"ahb_div",
+		HW_AHBCLKCTRL0,	21 },
+	{ CLKID_AHB_I2C0,	"i2c0",		"ahb_div",
+		HW_AHBCLKCTRL0,	22 },
+	{ CLKID_AHB_I2C1,	"i2c1",		"ahb_div",
+		HW_AHBCLKCTRL0,	23 },
+	{ CLKID_AHB_SSP0,	"ssp0",		"ahb_div",
+		HW_AHBCLKCTRL0,	24 },
+	{ CLKID_AHB_IOCONFIG,	"ioconf",	"ahb_div",
+		HW_AHBCLKCTRL0,	25 },
+	{ CLKID_AHB_WDT,	"wdt",		"ahb_div",
+		HW_AHBCLKCTRL0,	26 },
+	{ CLKID_AHB_CAN0,	"can0",		"ahb_div",
+		HW_AHBCLKCTRL0,	27 },
+	{ CLKID_AHB_CAN1,	"can1",		"ahb_div",
+		HW_AHBCLKCTRL0,	28 },
+	{ CLKID_AHB_MPWM,	"mpwm",		"ahb_div",
+		HW_AHBCLKCTRL0,	29 },
+	{ CLKID_AHB_SPI0,	"spi0",		"ahb_div",
+		HW_AHBCLKCTRL0,	30 },
+	{ CLKID_AHB_SPI1,	"spi1",		"ahb_div",
+		HW_AHBCLKCTRL0,	31 },
+
+	{ CLKID_AHB_QEI,	"qei",		"ahb_div",
+		HW_AHBCLKCTRL1,	0 },
+	{ CLKID_AHB_QUADSPI0,	"quadspi0",	"ahb_div",
+		HW_AHBCLKCTRL1,	1 },
+	{ CLKID_AHB_CAMIF,	"capmif",	"ahb_div",
+		HW_AHBCLKCTRL1,	2 },
+	{ CLKID_AHB_LCDIF,	"lcdif",	"ahb_div",
+		HW_AHBCLKCTRL1,	3 },
+	{ CLKID_AHB_TIMER0,	"timer0",	"ahb_div",
+		HW_AHBCLKCTRL1,	4 },
+	{ CLKID_AHB_TIMER1,	"timer1",	"ahb_div",
+		HW_AHBCLKCTRL1,	5 },
+	{ CLKID_AHB_TIMER2,	"timer2",	"ahb_div",
+		HW_AHBCLKCTRL1,	6 },
+	{ CLKID_AHB_TIMER3,	"timer3",	"ahb_div",
+		HW_AHBCLKCTRL1,	7 },
+	{ CLKID_AHB_IRQ,	"irq",		"ahb_div",
+		HW_AHBCLKCTRL1,	8, CLK_IGNORE_UNUSED},
+	{ CLKID_AHB_RTC,	"rtc",		"ahb_div",
+		HW_AHBCLKCTRL1,	9 },
+	{ CLKID_AHB_NAND,	"nand",		"ahb_div",
+		HW_AHBCLKCTRL1,	10 },
+	{ CLKID_AHB_ADC0,	"adc0",		"ahb_div",
+		HW_AHBCLKCTRL1,	11 },
+	{ CLKID_AHB_LED,	"led",		"ahb_div",
+		HW_AHBCLKCTRL1,	12 },
+	{ CLKID_AHB_DAC0,	"dac0",		"ahb_div",
+		HW_AHBCLKCTRL1,	13 },
+	{ CLKID_AHB_LCD,	"lcd",		"ahb_div",
+		HW_AHBCLKCTRL1,	14 },
+	{ CLKID_AHB_I2S1,	"i2s1",		"ahb_div",
+		HW_AHBCLKCTRL1,	15 },
+	{ CLKID_AHB_MAC1,	"mac1",		"ahb_div",
+		HW_AHBCLKCTRL1,	16 },
+};
+
+static const char __initdata *main_mux_p[] = {"oscillator", "pll"};
+static const char __initdata *i2s0_mux_p[] = {"oscillator", "pll", "i2s0m_div"};
+static const char __initdata *i2s1_mux_p[] = {"oscillator", "pll", "i2s1m_div"};
+static const char __initdata *clkout_mux_p[] = {"oscillator", "pll", "rtc"};
+static u32 three_mux_table[] = {0, 1, 3};
+
+static struct asm9260_mux_clock asm9260_mux_clks[] __initdata = {
+	{ 1, three_mux_table, "main_mux",	main_mux_p,
+		ARRAY_SIZE(main_mux_p), HW_MAINCLKSEL, },
+	{ 1, three_mux_table, "uart_mux",	main_mux_p,
+		ARRAY_SIZE(main_mux_p), HW_UARTCLKSEL, },
+	{ 1, three_mux_table, "wdt_mux",	main_mux_p,
+		ARRAY_SIZE(main_mux_p), HW_WDTCLKSEL, },
+	{ 3, three_mux_table, "i2s0_mux",	i2s0_mux_p,
+		ARRAY_SIZE(i2s0_mux_p), HW_I2S0CLKSEL, },
+	{ 3, three_mux_table, "i2s1_mux",	i2s1_mux_p,
+		ARRAY_SIZE(i2s1_mux_p), HW_I2S1CLKSEL, },
+	{ 3, three_mux_table, "clkout_mux",	clkout_mux_p,
+		ARRAY_SIZE(clkout_mux_p), HW_CLKOUTCLKSEL, },
+};
+
+static void __init asm9260_acc_init(struct device_node *np)
+{
+	struct clk *clk;
+	struct resource res;
+	u32 rate;
+	int n;
+	u32 accuracy = 0;
+
+	of_address_to_resource(np, 0, &res);
+	if (!request_mem_region(res.start, resource_size(&res), np->name))
+		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);
+
+
+	/* register pll */
+	rate = (ioread32(base + HW_SYSPLLCTRL) & 0xffff) * 1000000;
+
+	clk_names[REFCLK] = of_clk_get_parent_name(np, 0);
+	accuracy = clk_get_accuracy(__clk_lookup(clk_names[REFCLK]));
+	clk = clk_register_fixed_rate_with_accuracy(NULL, clk_names[SYSPLL],
+			clk_names[REFCLK], 0, rate, accuracy);
+
+	if (IS_ERR(clk))
+		panic("%s: can't register REFCLK. Check DT!", np->name);
+
+	for (n = 0; n < ARRAY_SIZE(asm9260_mux_clks); n++) {
+		const struct asm9260_mux_clock *mc = &asm9260_mux_clks[n];
+
+		mc->parent_names[0] = clk_names[REFCLK];
+		clk = clk_register_mux_table(NULL, mc->name, mc->parent_names,
+				mc->num_parents, mc->flags, base + mc->offset,
+				0, mc->mask, 0, mc->table, &asm9260_clk_lock);
+	}
+
+	/* clock mux gate cells */
+	for (n = 0; n < ARRAY_SIZE(asm9260_mux_gates); n++) {
+		const struct asm9260_gate_data *gd = &asm9260_mux_gates[n];
+
+		clk = clk_register_gate(NULL, gd->name,
+			gd->parent_name, gd->flags | CLK_SET_RATE_PARENT,
+			base + gd->reg, gd->bit_idx, 0, &asm9260_clk_lock);
+	}
+
+	/* clock div cells */
+	for (n = 0; n < ARRAY_SIZE(asm9260_div_clks); n++) {
+		const struct asm9260_div_clk *dc = &asm9260_div_clks[n];
+
+		clks[dc->idx] = clk_register_divider(NULL, dc->name,
+				dc->parent_name, CLK_SET_RATE_PARENT,
+				base + dc->reg, 0, 8, CLK_DIVIDER_ONE_BASED,
+				&asm9260_clk_lock);
+	}
+
+	/* clock ahb gate cells */
+	for (n = 0; n < ARRAY_SIZE(asm9260_ahb_gates); n++) {
+		const struct asm9260_gate_data *gd = &asm9260_ahb_gates[n];
+
+		clks[gd->idx] = clk_register_gate(NULL, gd->name,
+				gd->parent_name, gd->flags, base + gd->reg,
+				gd->bit_idx, 0, &asm9260_clk_lock);
+	}
+
+	/* check for errors on leaf clocks */
+	for (n = 0; n < MAX_CLKS; n++) {
+		if (!IS_ERR(clks[n]))
+			continue;
+
+		pr_err("%s: Unable to register leaf clock %d\n",
+				np->full_name, n);
+		goto fail;
+	}
+
+	/* register clk-provider */
+	clk_data.clks = clks;
+	clk_data.clk_num = MAX_CLKS;
+	of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
+	return;
+fail:
+	iounmap(base);
+}
+CLK_OF_DECLARE(asm9260_acc, "alphascale,asm9260-clock-controller",
+		asm9260_acc_init);
diff --git a/include/dt-bindings/clock/alphascale,asm9260.h b/include/dt-bindings/clock/alphascale,asm9260.h
new file mode 100644
index 0000000..04e8db2
--- /dev/null
+++ b/include/dt-bindings/clock/alphascale,asm9260.h
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2014 Oleksij Rempel <linux@rempel-privat.de>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _DT_BINDINGS_CLK_ASM9260_H
+#define _DT_BINDINGS_CLK_ASM9260_H
+
+/* ahb gate */
+#define CLKID_AHB_ROM		0
+#define CLKID_AHB_RAM		1
+#define CLKID_AHB_GPIO		2
+#define CLKID_AHB_MAC		3
+#define CLKID_AHB_EMI		4
+#define CLKID_AHB_USB0		5
+#define CLKID_AHB_USB1		6
+#define CLKID_AHB_DMA0		7
+#define CLKID_AHB_DMA1		8
+#define CLKID_AHB_UART0		9
+#define CLKID_AHB_UART1		10
+#define CLKID_AHB_UART2		11
+#define CLKID_AHB_UART3		12
+#define CLKID_AHB_UART4		13
+#define CLKID_AHB_UART5		14
+#define CLKID_AHB_UART6		15
+#define CLKID_AHB_UART7		16
+#define CLKID_AHB_UART8		17
+#define CLKID_AHB_UART9		18
+#define CLKID_AHB_I2S0		19
+#define CLKID_AHB_I2C0		20
+#define CLKID_AHB_I2C1		21
+#define CLKID_AHB_SSP0		22
+#define CLKID_AHB_IOCONFIG	23
+#define CLKID_AHB_WDT		24
+#define CLKID_AHB_CAN0		25
+#define CLKID_AHB_CAN1		26
+#define CLKID_AHB_MPWM		27
+#define CLKID_AHB_SPI0		28
+#define CLKID_AHB_SPI1		29
+#define CLKID_AHB_QEI		30
+#define CLKID_AHB_QUADSPI0	31
+#define CLKID_AHB_CAMIF		32
+#define CLKID_AHB_LCDIF		33
+#define CLKID_AHB_TIMER0	34
+#define CLKID_AHB_TIMER1	35
+#define CLKID_AHB_TIMER2	36
+#define CLKID_AHB_TIMER3	37
+#define CLKID_AHB_IRQ		38
+#define CLKID_AHB_RTC		39
+#define CLKID_AHB_NAND		40
+#define CLKID_AHB_ADC0		41
+#define CLKID_AHB_LED		42
+#define CLKID_AHB_DAC0		43
+#define CLKID_AHB_LCD		44
+#define CLKID_AHB_I2S1		45
+#define CLKID_AHB_MAC1		46
+
+/* devider */
+#define CLKID_SYS_CPU		47
+#define CLKID_SYS_AHB		48
+#define CLKID_SYS_I2S0M		49
+#define CLKID_SYS_I2S0S		50
+#define CLKID_SYS_I2S1M		51
+#define CLKID_SYS_I2S1S		52
+#define CLKID_SYS_UART0		53
+#define CLKID_SYS_UART1		54
+#define CLKID_SYS_UART2		55
+#define CLKID_SYS_UART3		56
+#define CLKID_SYS_UART4		56
+#define CLKID_SYS_UART5		57
+#define CLKID_SYS_UART6		58
+#define CLKID_SYS_UART7		59
+#define CLKID_SYS_UART8		60
+#define CLKID_SYS_UART9		61
+#define CLKID_SYS_SPI0		62
+#define CLKID_SYS_SPI1		63
+#define CLKID_SYS_QUADSPI	64
+#define CLKID_SYS_SSP0		65
+#define CLKID_SYS_NAND		66
+#define CLKID_SYS_TRACE		67
+#define CLKID_SYS_CAMM		68
+#define CLKID_SYS_WDT		69
+#define CLKID_SYS_CLKOUT	70
+#define CLKID_SYS_MAC		71
+#define CLKID_SYS_LCD		72
+#define CLKID_SYS_ADCANA	73
+
+#define MAX_CLKS		74
+#endif
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH v5 04/10] ARM: irqchip: mxs: prepare driver for HW with different offsets
  2014-10-14  8:03 [PATCH v5 00/10] initial suport for Alphascale ASM9260 Oleksij Rempel
                   ` (2 preceding siblings ...)
  2014-10-14  8:03 ` [PATCH v5 03/10] ARM: clk: add clk-asm9260 driver Oleksij Rempel
@ 2014-10-14  8:03 ` Oleksij Rempel
  2014-10-14  8:03 ` [PATCH v5 05/10] ARM: irqchip: mxs: add Alpascale ASM9260 support Oleksij Rempel
                   ` (5 subsequent siblings)
  9 siblings, 0 replies; 16+ messages in thread
From: Oleksij Rempel @ 2014-10-14  8:03 UTC (permalink / raw)
  To: linux-arm-kernel

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

Signed-off-by: Oleksij Rempel <linux@rempel-privat.de>
---
 drivers/irqchip/irq-mxs.c | 55 ++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 42 insertions(+), 13 deletions(-)

diff --git a/drivers/irqchip/irq-mxs.c b/drivers/irqchip/irq-mxs.c
index e4acf1e..681125d 100644
--- a/drivers/irqchip/irq-mxs.c
+++ b/drivers/irqchip/irq-mxs.c
@@ -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);
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH v5 05/10] ARM: irqchip: mxs: add Alpascale ASM9260 support
  2014-10-14  8:03 [PATCH v5 00/10] initial suport for Alphascale ASM9260 Oleksij Rempel
                   ` (3 preceding siblings ...)
  2014-10-14  8:03 ` [PATCH v5 04/10] ARM: irqchip: mxs: prepare driver for HW with different offsets Oleksij Rempel
@ 2014-10-14  8:03 ` Oleksij Rempel
  2014-10-14  8:03 ` [PATCH v5 06/10] ARM: clocksource: add asm9260_timer driver Oleksij Rempel
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 16+ messages in thread
From: Oleksij Rempel @ 2014-10-14  8:03 UTC (permalink / raw)
  To: linux-arm-kernel

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.

Signed-off-by: Oleksij Rempel <linux@rempel-privat.de>
---
 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

diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index b8632bf..2ee202f 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -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
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index 73052ba..89c7042 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -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
diff --git a/drivers/irqchip/alphascale_asm9260-icoll.h b/drivers/irqchip/alphascale_asm9260-icoll.h
new file mode 100644
index 0000000..5cec108
--- /dev/null
+++ b/drivers/irqchip/alphascale_asm9260-icoll.h
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2014 Oleksij Rempel <linux@rempel-privat.de>
+ *
+ * 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.
+ */
+
+#ifndef _ALPHASCALE_ASM9260_ICOLL_H
+#define _ALPHASCALE_ASM9260_ICOLL_H
+
+#define ASM9260_NUM_IRQS		64
+/*
+ * 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 ASM9260_HW_ICOLL_VECTOR				0x0000
+/*
+ * bits 31:2
+ * This register presents the vector address for the interrupt currently
+ * active on the CPU IRQ input. Writing to this register notifies the
+ * interrupt collector that the interrupt service routine for the current
+ * interrupt has been entered.
+ * The exception trap should have a LDPC instruction from this address:
+ * LDPC ASM9260_HW_ICOLL_VECTOR_ADDR; IRQ exception at 0xffff0018
+ */
+
+/*
+ * The Interrupt Collector Level Acknowledge Register is used by software to
+ * indicate the completion of an interrupt on a specific level.
+ * This register is written at the very end of an interrupt service routine. If
+ * nesting is used then the CPU irq must be turned on before writing to this
+ * register to avoid a race condition in the CPU interrupt hardware.
+ */
+#define ASM9260_HW_ICOLL_LEVELACK			0x0010
+#define ASM9260_BM_LEVELn(nr)				BIT(nr)
+
+#define ASM9260_HW_ICOLL_CTRL				0x0020
+/*
+ * ASM9260_BM_CTRL_SFTRST and ASM9260_BM_CTRL_CLKGATE are not available on
+ * asm9260.
+ */
+#define ASM9260_BM_CTRL_SFTRST				BIT(31)
+#define ASM9260_BM_CTRL_CLKGATE				BIT(30)
+/* disable interrupt level nesting */
+#define ASM9260_BM_CTRL_NO_NESTING			BIT(19)
+/*
+ * Set this bit to one enable the RISC32-style read side effect associated with
+ * the vector address register. In this mode, interrupt in-service is signaled
+ * by the read of the ASM9260_HW_ICOLL_VECTOR register to acquire the interrupt
+ * vector address. Set this bit to zero for normal operation, in which the ISR
+ * signals in-service explicitly by means of a write to the
+ * ASM9260_HW_ICOLL_VECTOR register.
+ * 0 - Must Write to Vector register to go in-service.
+ * 1 - Go in-service as a read side effect
+ */
+#define ASM9260_BM_CTRL_ARM_RSE_MODE			BIT(18)
+#define ASM9260_BM_CTRL_IRQ_ENABLE			BIT(16)
+
+#define ASM9260_HW_ICOLL_STAT_OFFSET			0x0030
+/*
+ * bits 5:0
+ * Vector number of current interrupt. Multiply by 4 and add to vector base
+ * address to obtain the value in ASM9260_HW_ICOLL_VECTOR.
+ */
+
+/*
+ * RAW0 and RAW1 provides a read-only view of the raw interrupt request lines
+ * coming from various parts of the chip. Its purpose is to improve diagnostic
+ * observability.
+ */
+#define ASM9260_HW_ICOLL_RAW0				0x0040
+#define ASM9260_HW_ICOLL_RAW1				0x0050
+
+#define ASM9260_HW_ICOLL_INTERRUPT0			0x0060
+#define ASM9260_HW_ICOLL_INTERRUPTn(n)		(0x0060 + ((n) >> 2) * 0x10)
+/*
+ * WARNING: Modifying the priority of an enabled interrupt may result in
+ * undefined behavior.
+ */
+#define ASM9260_BM_INT_PRIORITY_MASK			0x3
+#define ASM9260_BM_INT_ENABLE				BIT(2)
+#define ASM9260_BM_INT_SOFTIRQ				BIT(3)
+
+#define ASM9260_BM_ICOLL_INTERRUPTn_SHIFT(n)		(((n) & 0x3) << 3)
+#define ASM9260_BM_ICOLL_INTERRUPTn_ENABLE(n)		(1 << (2 + \
+			ASM9260_BM_ICOLL_INTERRUPTn_SHIFT(n)))
+
+#define ASM9260_HW_ICOLL_VBASE				0x0160
+/*
+ * bits 31:2
+ * This bitfield holds the upper 30 bits of the base address of the vector
+ * table.
+ */
+
+#define ASM9260_HW_ICOLL_CLEAR0				0x01d0
+#define ASM9260_HW_ICOLL_CLEAR1				0x01e0
+#define ASM9260_HW_ICOLL_CLEARn(n)			(((n >> 5) * 0x10) \
+							+ SET_REG)
+#define ASM9260_BM_CLEAR_BIT(n)				BIT(n & 0x1f)
+
+/* Scratchpad */
+#define ASM9260_HW_ICOLL_UNDEF_VECTOR			0x01f0
+#endif
diff --git a/drivers/irqchip/irq-mxs.c b/drivers/irqchip/irq-mxs.c
index 681125d..8397c73 100644
--- a/drivers/irqchip/irq-mxs.c
+++ b/drivers/irqchip/irq-mxs.c
@@ -1,5 +1,7 @@
 /*
  * Copyright (C) 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2014 Oleksij Rempel <linux@rempel-privat.de>
+ *	Add Alphascale ASM9260 support.
  *
  * 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
@@ -28,6 +30,7 @@
 #include <asm/exception.h>
 
 #include "irqchip.h"
+#include "alphascale_asm9260-icoll.h"
 
 /*
  * this device provide 4 offsets for each register:
@@ -63,6 +66,33 @@ struct icoll_priv {
 
 static struct icoll_priv icoll_priv;
 static struct irq_domain *icoll_domain;
+static DEFINE_MUTEX(icoll_lock);
+
+/* calculate bit offset depending on number of intterupt per register */
+static u32 icoll_intr_bitshift(struct irq_data *d, u32 bit)
+{
+	/*
+	 * We expect intr_per_reg to be 4 or 1, it means
+	 * "n" will be 3 or 0.
+	 */
+	int n = icoll_priv.intr_per_reg - 1;
+
+	/*
+	 * If n = 0, "bit" is never shifted.
+	 * If n = 3, mask lower part of hwirq to convert it
+	 * in 0, 1, 2 or 3 and then multiply it by 8 (or shift by 3)
+	 */
+	return bit << ((d->hwirq & n) << n);
+}
+
+/* calculate mem offset depending on number of intterupt per register */
+static void __iomem *icoll_intr_reg(struct irq_data *d)
+{
+	int n = icoll_priv.intr_per_reg >> 1;
+
+	/* offset = hwirq / intr_per_reg * 0x10 */
+	return icoll_priv.intr + ((d->hwirq >> n) * 0x10);
+}
 
 static void icoll_ack_irq(struct irq_data *d)
 {
@@ -77,14 +107,21 @@ static void icoll_ack_irq(struct irq_data *d)
 
 static void icoll_mask_irq(struct irq_data *d)
 {
-	__raw_writel(BM_ICOLL_INTR_ENABLE,
-			icoll_priv.intr + CLR_REG + HW_ICOLL_INTERRUPTn(d->hwirq));
+	__raw_writel(icoll_intr_bitshift(d, BM_ICOLL_INTR_ENABLE),
+			icoll_intr_reg(d) + CLR_REG);
 }
 
 static void icoll_unmask_irq(struct irq_data *d)
 {
-	__raw_writel(BM_ICOLL_INTR_ENABLE,
-			icoll_priv.intr + SET_REG + HW_ICOLL_INTERRUPTn(d->hwirq));
+	mutex_lock(&icoll_lock);
+	if (icoll_priv.clear)
+		__raw_writel(ASM9260_BM_CLEAR_BIT(d->hwirq),
+				icoll_priv.clear +
+				ASM9260_HW_ICOLL_CLEARn(d->hwirq));
+
+	__raw_writel(icoll_intr_bitshift(d, BM_ICOLL_INTR_ENABLE),
+			icoll_intr_reg(d) + SET_REG);
+	mutex_unlock(&icoll_lock);
 }
 
 static struct irq_chip mxs_icoll_chip = {
@@ -116,12 +153,41 @@ static struct irq_domain_ops icoll_irq_domain_ops = {
 	.xlate = irq_domain_xlate_onecell,
 };
 
+static void __init icoll_add_domain(struct device_node *np,
+			  int num)
+{
+	icoll_domain = irq_domain_add_linear(np, num,
+					     &icoll_irq_domain_ops, NULL);
+
+	if (!icoll_domain)
+		panic("%s: unable add irq domain", np->full_name);
+	irq_set_default_host(icoll_domain);
+	set_handle_irq(icoll_handle_irq);
+}
+
+static void __iomem * __init icoll_init_iobase(struct device_node *np)
+{
+	struct resource res;
+	void __iomem *icoll_base;
+
+	if (of_address_to_resource(np, 0, &res))
+		panic("%s: unable to get resource", np->full_name);
+
+	if (!request_mem_region(res.start, resource_size(&res), np->name))
+		panic("%s: unable to request mem region", np->full_name);
+
+	icoll_base = ioremap_nocache(res.start, resource_size(&res));
+	if (!icoll_base)
+		panic("%s: unable to map resource", np->full_name);
+	return icoll_base;
+}
+
 static int __init icoll_of_init(struct device_node *np,
 			  struct device_node *interrupt_parent)
 {
-	void __iomem *icoll_base = of_iomap(np, 0);
-	WARN_ON(!icoll_base);
+	void __iomem *icoll_base;
 
+	icoll_base		= icoll_init_iobase(np);
 	icoll_priv.vector	= icoll_base + HW_ICOLL_VECTOR;
 	icoll_priv.levelack	= icoll_base + HW_ICOLL_LEVELACK;
 	icoll_priv.ctrl		= icoll_base + HW_ICOLL_CTRL;
@@ -136,8 +202,38 @@ static int __init icoll_of_init(struct device_node *np,
 	 */
 	stmp_reset_block(icoll_priv.ctrl);
 
-	icoll_domain = irq_domain_add_linear(np, ICOLL_NUM_IRQS,
-					     &icoll_irq_domain_ops, NULL);
+	icoll_add_domain(np, ICOLL_NUM_IRQS);
+
 	return icoll_domain ? 0 : -ENODEV;
 }
 IRQCHIP_DECLARE(mxs, "fsl,icoll", icoll_of_init);
+
+static int __init asm9260_of_init(struct device_node *np,
+			  struct device_node *interrupt_parent)
+{
+	void __iomem *icoll_base;
+	int i;
+
+	icoll_base = icoll_init_iobase(np);
+	icoll_priv.vector	= icoll_base + ASM9260_HW_ICOLL_VECTOR;
+	icoll_priv.levelack	= icoll_base + ASM9260_HW_ICOLL_LEVELACK;
+	icoll_priv.ctrl		= icoll_base + ASM9260_HW_ICOLL_CTRL;
+	icoll_priv.stat		= icoll_base + ASM9260_HW_ICOLL_STAT_OFFSET;
+	icoll_priv.intr		= icoll_base + ASM9260_HW_ICOLL_INTERRUPT0;
+	icoll_priv.intr_per_reg	= 4;
+	icoll_priv.clear	= icoll_base + ASM9260_HW_ICOLL_CLEAR0;
+
+	writel_relaxed(ASM9260_BM_CTRL_IRQ_ENABLE,
+			icoll_priv.ctrl);
+	/*
+	 * ASM9260 don't provide reset bit. So, we need to set level 0
+	 * manually.
+	 */
+	for (i = 0; i < 16 * 0x10; i += 0x10)
+		writel(0, icoll_priv.intr + i);
+
+	icoll_add_domain(np, ASM9260_NUM_IRQS);
+
+	return icoll_domain ? 0 : -ENODEV;
+}
+IRQCHIP_DECLARE(asm9260, "alphascale,asm9260-icoll", asm9260_of_init);
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH v5 06/10] ARM: clocksource: add asm9260_timer driver
  2014-10-14  8:03 [PATCH v5 00/10] initial suport for Alphascale ASM9260 Oleksij Rempel
                   ` (4 preceding siblings ...)
  2014-10-14  8:03 ` [PATCH v5 05/10] ARM: irqchip: mxs: add Alpascale ASM9260 support Oleksij Rempel
@ 2014-10-14  8:03 ` Oleksij Rempel
  2014-10-15 21:31   ` Matthias Brugger
  2014-10-14  8:03 ` [PATCH v5 07/10] ARM: tty: mxs-auart: add initial Alphascale ASM9260 support Oleksij Rempel
                   ` (3 subsequent siblings)
  9 siblings, 1 reply; 16+ messages in thread
From: Oleksij Rempel @ 2014-10-14  8:03 UTC (permalink / raw)
  To: linux-arm-kernel

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

Signed-off-by: Oleksij Rempel <linux@rempel-privat.de>
---
 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

diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index cfd6519..6a03d34 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -216,4 +216,8 @@ config CLKSRC_VERSATILE
 	  ARM Versatile, RealView and Versatile Express reference
 	  platforms.
 
+config ASM9260_TIMER
+	select CLKSRC_MMIO
+	bool
+
 endmenu
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index 7fd9fd1..fc93854 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -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
diff --git a/drivers/clocksource/asm9260_timer.c b/drivers/clocksource/asm9260_timer.c
new file mode 100644
index 0000000..1b16e00
--- /dev/null
+++ b/drivers/clocksource/asm9260_timer.c
@@ -0,0 +1,234 @@
+/*
+ * Copyright (C) 2014 Oleksij Rempel <linux@rempel-privat.de>
+ *
+ * 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 */
+#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 */
+
+static void __iomem *base;
+static unsigned long ticks_per_jiffy;
+
+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);
+
+	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);
+
+	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;
+	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);
+
+	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);
+
+	/* 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);
+	/* 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);
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH v5 07/10] ARM: tty: mxs-auart: add initial Alphascale ASM9260 support
  2014-10-14  8:03 [PATCH v5 00/10] initial suport for Alphascale ASM9260 Oleksij Rempel
                   ` (5 preceding siblings ...)
  2014-10-14  8:03 ` [PATCH v5 06/10] ARM: clocksource: add asm9260_timer driver Oleksij Rempel
@ 2014-10-14  8:03 ` Oleksij Rempel
  2014-10-14  8:03 ` [PATCH v5 08/10] ARM: dts: add DT for Alphascale ASM9260 SoC Oleksij Rempel
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 16+ messages in thread
From: Oleksij Rempel @ 2014-10-14  8:03 UTC (permalink / raw)
  To: linux-arm-kernel

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.

Signed-off-by: Oleksij Rempel <linux@rempel-privat.de>
---
 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

diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index 26cec64..11bbb76 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -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"
diff --git a/drivers/tty/serial/alphascale,asm9260_serial.h b/drivers/tty/serial/alphascale,asm9260_serial.h
new file mode 100644
index 0000000..eeed9c4
--- /dev/null
+++ b/drivers/tty/serial/alphascale,asm9260_serial.h
@@ -0,0 +1,373 @@
+/*
+ * Copyright (C) 2014 Oleksij Rempel <linux@rempel-privat.de>
+ *
+ * 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.
+ */
+
+#ifndef _ALPHASCALE_ASM9260_SERIAL_H
+#define _ALPHASCALE_ASM9260_SERIAL_H
+
+/* RX ctrl register */
+#define ASM9260_HW_CTRL0			0x0000
+/* RW. Set to zero for normal operation. */
+#define ASM9260_BM_CTRL0_SFTRST			BIT(31)
+/*
+ * RW. 0 for normal operation; 1 gates all of the block level clocks off for
+ * miniminizing AC energy consumption.
+ */
+#define ASM9260_BM_CTRL0_CLKGATE		BIT(30)
+/*
+ * RW. Tell the UART to execute the RX DMA Command. The
+ * UART will clear this bit at the end of receive execution.
+ */
+#define ASM9260_BM_CTRL0_RXDMA_RUN		BIT(28)
+/* RW. 0 use FIFO for status register; 1 use DMA */
+#define ASM9260_BM_CTRL0_RXTO_SOURCE_STATUS	BIT(25)
+/*
+ * RW. RX TIMEOUT Enable. Valid for FIFO and DMA.
+ * Warning: If this bit is set to 0, the RX timeout will not affect receive DMA
+ * operation. If this bit is set to 1, a receive timeout will cause the receive
+ * DMA logic to terminate by filling the remaining DMA bytes with garbage data.
+ */
+#define ASM9260_BM_CTRL0_RXTO_ENABLE		BIT(24)
+/*
+ * RW. Receive Timeout Counter Value: number of 8-bit-time to wait before
+ * asserting timeout on the RX input. If the RXFIFO is not empty and the RX
+ * input is idle, then the watchdog counter will decrement each bit-time. Note
+ * 7-bit-time is added to the programmed value, so a value of zero will set
+ * the counter to 7-bit-time, a value of 0x1 gives 15-bit-time and so on. Also
+ * note that the counter is reloaded at the end of each frame, so if the frame
+ * is 10 bits long and the timeout counter value is zero, then timeout will
+ * occur (when FIFO is not empty) even if the RX input is not idle. The default
+ * value is 0x3 (31 bit-time).
+ */
+#define ASM9260_BM_CTRL0_RXTO_MASK		(0xff<<16)
+/* TIMEOUT = (100*7+1)*(1/BAUD) */
+#define ASM9260_BM_CTRL0_DEFAULT_RXTIMEOUT	(20<<16)
+/* RW. Number of bytes to receive. This must be a multiple of 4 */
+#define ASM9260_BM_CTRL0_RXDMA_COUNT_MASK	(0xffff<<0)
+
+/* TX ctrl register */
+#define ASM9260_HW_CTRL1			0x0010
+/*
+ * RW. Tell the UART to execute the TX DMA Command. The
+ * UART will clear this bit at the end of transmit execution.
+ */
+#define ASM9260_BM_CTRL1_TXDMA_RUN		BIT(28)
+/* RW. Number of bytes to transmit. */
+#define ASM9260_BM_CTRL1_TXDMA_COUNT_MASK	(0xffff << 0)
+
+#define ASM9260_HW_CTRL2			0x0020
+/*
+ * RW. Receive dma will terminate on error. (Cmd_end signal may not be asserted
+ * when this occurs.)
+ */
+#define ASM9260_BM_CTRL2_DMAONERROR		BIT(26)
+/*
+ * RW. Transmit DMA Enable. Data Register can be loaded with up to 4 bytes per
+ * write. TXFIFO must be enabled in TXDMA mode.
+ */
+#define ASM9260_BM_CTRL2_TXDMAE			BIT(25)
+/*
+ * RW. Receive DMA Enable. Data Register can be contain up to 4 bytes per read.
+ * RXFIFO must be enabled in RXDMA mode.
+ */
+#define ASM9260_BM_CTRL2_RXDMAE			BIT(24)
+/*
+ * RW. Receive Interrupt FIFO Level Select.
+ * The trigger points for the receive interrupt are as follows:
+ * ONE_EIGHTHS = 0x0 Trigger on FIFO full to at least 2 of 16 entries.
+ * ONE_QUARTER = 0x1 Trigger on FIFO full to at least 4 of 16 entries.
+ * ONE_HALF = 0x2 Trigger on FIFO full to at least 8 of 16 entries.
+ * THREE_QUARTERS = 0x3 Trigger on FIFO full to at least 12 of 16 entries.
+ * SEVEN_EIGHTHS = 0x4 Trigger on FIFO full to at least 14 of 16 entries.
+ */
+#define ASM9260_BM_CTRL2_RXIFLSEL		(7<<20)
+#define ASM9260_BM_CTRL2_DEFAULT_RXIFLSEL	(3<<20)
+/* RW. Same as RXIFLSEL */
+#define ASM9260_BM_CTRL2_TXIFLSEL		(7<<16)
+#define ASM9260_BM_CTRL2_DEFAULT_TXIFLSEL	(2<<16)
+/* RW. CTS Enable */
+#define ASM9260_BM_CTRL2_CTSE			BIT(15)
+/* RW. RTS Enable */
+#define ASM9260_BM_CTRL2_RTSE			BIT(14)
+/*
+ * RW. Manually trigger RTS. Works only if ASM9260_BM_CTRL2_RTSE = 0.
+ * When this bit is 1, the output is 0.
+ */
+#define ASM9260_BM_CTRL2_RTS			BIT(11)
+/* RW. Set DTR. When this bit is 1, the output is 0. */
+#define ASM9260_BM_CTRL2_DTR			BIT(10)
+/* RW. RX Enable */
+#define ASM9260_BM_CTRL2_RXE			BIT(9)
+/* RW. TX Enable */
+#define ASM9260_BM_CTRL2_TXE			BIT(8)
+/* RW. Loop Back Enable */
+#define ASM9260_BM_CTRL2_LBE			BIT(7)
+#define ASM9260_BM_CTRL2_PORT_ENABLE		BIT(0)
+
+#define ASM9260_HW_LINECTRL			0x0030
+#define ASM9260_BM_LCTRL_BAUD_DIVINT		(0xFFFF<<16)
+#define ASM9260_BM_LCTRL_BAUD_DIVFRA		(0x3F<<8)
+/*
+ * RW. Stick Parity Select. When bits 1, 2, and 7 of this register are set, the
+ * parity bit is transmitted and checked as a 0. When bits 1 and 7 are set,
+ * and bit 2 is 0, the parity bit is transmitted and checked as a 1. When this
+ * bit is cleared stick parity is disabled.
+ */
+#define ASM9260_BM_LCTRL_SPS			BIT(7)
+/* RW. Word length */
+#define ASM9260_BM_LCTRL_WLEN			(3<<5)
+#define ASM9260_BM_LCTRL_CHRL_5			(0<<5)
+#define ASM9260_BM_LCTRL_CHRL_6			(1<<5)
+#define ASM9260_BM_LCTRL_CHRL_7			(2<<5)
+#define ASM9260_BM_LCTRL_CHRL_8			(3<<5)
+/*
+ * RW. Enable FIFOs. If this bit is set to 1, transmit and receive FIFO buffers
+ * are enabled (FIFO mode). When cleared to 0, the FIFOs are disabled (character
+ * mode); that is, the FIFOs become 1-byte-deep holding registers.
+ */
+#define ASM9260_BM_LCTRL_FEN			BIT(4)
+/*
+ * RW. Two Stop Bits Select. If this bit is set to 1, two stop bits are
+ * transmitted at the end of the frame. The receive logic does not check for
+ * two stop bits being received.
+ */
+#define ASM9260_BM_LCTRL_STP2			BIT(3)
+#define ASM9260_BM_LCTRL_NBSTOP_1		(0<<3)
+#define ASM9260_BM_LCTRL_NBSTOP_2		(1<<3)
+/* RW. Even Parity Select. If disabled, then odd parity is performed. */
+#define ASM9260_BM_LCTRL_EPS			BIT(2)
+/* Parity Enable. */
+#define ASM9260_BM_LCTRL_PEN			BIT(1)
+#define ASM9260_BM_LCTRL_PAR_MARK		((3<<1) | (1<<7))
+#define ASM9260_BM_LCTRL_PAR_SPACE		((1<<1) | (1<<7))
+#define ASM9260_BM_LCTRL_PAR_ODD		((1<<1) | (0<<7))
+#define ASM9260_BM_LCTRL_PAR_EVEN		((3<<1) | (0<<7))
+#define ASM9260_BM_LCTRL_PAR_NONE		(0<<1)
+/*
+ * RW. Send Break. If this bit is set to 1, a low-level is continually output on
+ * the UARTTXD output, after completing transmission of the current character.
+ * For the proper execution of the break command, the software must set this bit
+ * for@least two complete frames. For normal use, this bit must be cleared
+ * to 0.
+ */
+#define ASM9260_BM_LCTRL_BREAK			BIT(0)
+
+/*
+ * Interrupt register.
+ * contains the interrupt enables and the interrupt status bits
+ */
+#define ASM9260_HW_INTR				0x0040
+/* Tx FIFO EMPTY Raw Interrupt enable */
+#define ASM9260_BM_INTR_TFEIEN			BIT(27)
+/* Overrun Error Interrupt Enable. */
+#define ASM9260_BM_INTR_OEIEN			BIT(26)
+/* Break Error Interrupt Enable. */
+#define ASM9260_BM_INTR_BEIEN			BIT(25)
+/* Parity Error Interrupt Enable. */
+#define ASM9260_BM_INTR_PEIEN			BIT(24)
+/* Framing Error Interrupt Enable. */
+#define ASM9260_BM_INTR_FEIEN			BIT(23)
+/*
+ * RW. Receive Timeout Interrupt Enable.
+ * If not set and FIFO is enabled, then RX will be triggered only
+ * if FIFO is full.
+ */
+#define ASM9260_BM_INTR_RTIEN			BIT(22)
+/* Transmit Interrupt Enable. */
+#define ASM9260_BM_INTR_TXIEN			BIT(21)
+/* Receive Interrupt Enable. */
+#define ASM9260_BM_INTR_RXIEN			BIT(20)
+/* nUARTDSR Modem Interrupt Enable. */
+#define ASM9260_BM_INTR_DSRMIEN			BIT(19)
+/* nUARTDCD Modem Interrupt Enable. */
+#define ASM9260_BM_INTR_DCDMIEN			BIT(18)
+/* nUARTCTS Modem Interrupt Enable. */
+#define ASM9260_BM_INTR_CTSMIEN			BIT(17)
+/* nUARTRI Modem Interrupt Enable. */
+#define ASM9260_BM_INTR_RIMIEN			BIT(16)
+/* Auto-Boud Timeout */
+#define ASM9260_BM_INTR_ABTO			BIT(13)
+#define ASM9260_BM_INTR_ABEO			BIT(12)
+/* Tx FIFO EMPTY Raw Interrupt state */
+#define ASM9260_BM_INTR_TFEIS			BIT(11)
+/* Overrun Error */
+#define ASM9260_BM_INTR_OEIS			BIT(10)
+/* Break Error */
+#define ASM9260_BM_INTR_BEIS			BIT(9)
+/* Parity Error */
+#define ASM9260_BM_INTR_PEIS			BIT(8)
+/* Framing Error */
+#define ASM9260_BM_INTR_FEIS			BIT(7)
+/* Receive Timeout */
+#define ASM9260_BM_INTR_RTIS			BIT(6)
+/* Transmit done */
+#define ASM9260_BM_INTR_TXIS			BIT(5)
+/* Receive done */
+#define ASM9260_BM_INTR_RXIS			BIT(4)
+#define ASM9260_BM_INTR_DSRMIS			BIT(3)
+#define ASM9260_BM_INTR_DCDMIS			BIT(2)
+#define ASM9260_BM_INTR_CTSMIS			BIT(1)
+#define ASM9260_BM_INTR_RIMIS			BIT(0)
+#define ASM9260_BM_INTR_DEF_MASK	(ASM9260_BM_INTR_RXIEN \
+		| ASM9260_BM_INTR_TXIEN | ASM9260_BM_INTR_RTIEN \
+		| ASM9260_BM_INTR_FEIEN | ASM9260_BM_INTR_PEIEN \
+		| ASM9260_BM_INTR_BEIEN | ASM9260_BM_INTR_OEIEN)
+#define ASM9260_BM_INTR_DEF_IS_MASK		(BM_INTR_DEF_MASK >> 16)
+#define ASM9260_BM_INTR_EN_MASK			(0x3fff0000)
+#define ASM9260_BM_INTR_IS_MASK			(0x00003fff)
+
+/*
+ * RW. In DMA mode, up to 4 Received/Transmit characters can be accessed at a
+ * time. In PIO mode, only one character can be accessed at a time. The status
+ * register contains the receive data flags and valid bits.
+ */
+#define ASM9260_HW_DATA				0x0050
+
+#define ASM9260_HW_STAT				0x0060
+/* RO. If 1, UARTAPP is present in this product. */
+#define ASM9260_BM_STAT_PRESENT			BIT(31)
+/* RO. If 1, HISPEED is present in this product. */
+#define ASM9260_BM_STAT_HISPEED			BIT(30)
+/* RO. UART Busy. */
+#define ASM9260_BM_STAT_BUSY			BIT(29)
+/* RO. Clear To Send. */
+#define ASM9260_BM_STAT_CTS			BIT(28)
+/* RO. Transmit FIFO/PIO Empty */
+#define ASM9260_BM_STAT_TXEMPTY			BIT(27)
+/* RO. Receive FIFO Full. */
+#define ASM9260_BM_STAT_RXFULL			BIT(26)
+/* RO. Transmit FIFO Full. */
+#define ASM9260_BM_STAT_TXFULL			BIT(25)
+/* RO. Receive FIFO Empty. */
+#define ASM9260_BM_STAT_RXEMPTY			BIT(24)
+/*
+ * RW. The invalid state of the last read of Receive Data. Each
+ * bit corresponds to one byte of the RX data. (1 = invalid.)
+ */
+#define ASM9260_BM_STAT_RXBYTE_INVALID_MASK	(0xf<<20)
+/*
+ * RO. Overrun Error. This bit is set to 1 if data is received and the FIFO is
+ * already full. This bit is cleared to 0 by any write to the Status Register.
+ * The FIFO contents remain valid since no further data is written when the
+ * FIFO is full; only the contents of the shift register are overwritten. The
+ * CPU must now read the data in order to empty the FIFO.
+ */
+#define ASM9260_BM_STAT_OVERRUNERR		BIT(19)
+/*
+ * RW. Break Error. For PIO mode, this is for the last character read from the
+ * data register. For DMA mode, it will be set to 1 if any received character
+ * for a particular RXDMA command had a Break Error. To clear this bit, write a
+ * zero to it. Note that clearing this bit does not affect the interrupt status,
+ * which must be cleared by writing the interrupt register.
+ */
+#define ASM9260_BM_STAT_BREAKERR		BIT(18)
+/* RW. Parity Error. Same as BREAKERR. */
+#define ASM9260_BM_STAT_PARITYERR		BIT(17)
+/* RW. Framing Erro. Same as BREAKERR. */
+#define ASM9260_BM_STAT_FRAMEERR		BIT(16)
+/* RO. Number of bytes received during a Receive DMA command. */
+#define ASM9260_BM_STAT_RXCOUNT_MASK		(0xffff<<0)
+
+/* RO. The UART Debug Register contains the state of the DMA signals. */
+#define ASM9260_HW_DEBUG			0x0070
+/* DMA Command Run Status */
+#define ASM9260_BM_DEBUG_TXDMARUN		BIT(5)
+#define ASM9260_BM_DEBUG_RXDMARUN		BIT(4)
+/* DMA Command End Status */
+#define ASM9260_BM_DEBUG_TXCMDEND		BIT(3)
+#define ASM9260_BM_DEBUG_RXCMDEND		BIT(2)
+/* DMA Request Status */
+#define ASM9260_BM_DEBUG_TXDMARQ		BIT(1)
+#define ASM9260_BM_DEBUG_RXDMARQ		BIT(0)
+
+#define ASM9260_HW_ILPR				0x0080
+
+#define ASM9260_HW_RS485CTRL			0x0090
+/*
+ * RW. This bit reverses the polarity of the direction control signal on the RTS
+ * (or DTR) pin.
+ * If 0, The direction control pin will be driven to logic ?0? when the
+ * transmitter has data to be sent. It will be driven to logic ?1? after the
+ * last bit of data has been transmitted.
+ */
+#define ASM9260_BM_RS485CTRL_ONIV		BIT(5)
+/* RW. Enable Auto Direction Control. */
+#define ASM9260_BM_RS485CTRL_DIR_CTRL		BIT(4)
+/*
+ * RW. If 0 and DIR_CTRL = 1, pin RTS is used for direction control.
+ * If 1 and DIR_CTRL = 1, pin DTR is used for direction control.
+ */
+#define ASM9260_BM_RS485CTRL_PINSEL		BIT(3)
+/* RW. Enable Auto Address Detect (AAD). */
+#define ASM9260_BM_RS485CTRL_AADEN		BIT(2)
+/* RW. Disable receiver. */
+#define ASM9260_BM_RS485CTRL_RXDIS		BIT(1)
+/* RW. Enable RS-485/EIA-485 Normal Multidrop Mode (NMM) */
+#define ASM9260_BM_RS485CTRL_RS485EN		BIT(0)
+
+#define ASM9260_HW_RS485ADRMATCH		0x00a0
+/* Contains the address match value. */
+#define ASM9260_BM_RS485ADRMATCH_MASK		(0xff<<0)
+
+#define ASM9260_HW_RS485DLY			0x00b0
+/*
+ * RW. Contains the direction control (RTS or DTR) delay value. This delay time
+ * is in periods of the baud clock.
+ */
+#define ASM9260_BM_RS485DLY_MASK		(0xff<<0)
+
+#define ASM9260_HW_AUTOBAUD			0x00c0
+/* WO. Auto-baud time-out interrupt clear bit. */
+#define ASM9260_BM_AUTOBAUD_ABTOIntClr		BIT(9)
+/* WO. End of auto-baud interrupt clear bit. */
+#define ASM9260_BM_AUTOBAUD_ABEOIntClr		BIT(8)
+/* Restart in case of timeout (counter restarts at next UART Rx falling edge) */
+#define ASM9260_BM_AUTOBAUD_AUTORESTART		BIT(2)
+/* Auto-baud mode select bit. 0 - Mode 0, 1 - Mode 1. */
+#define ASM9260_BM_AUTOBAUD_MODE		BIT(1)
+/*
+ * Auto-baud start (auto-baud is running). Auto-baud run bit. This bit is
+ * automatically cleared after auto-baud completion.
+ */
+#define ASM9260_BM_AUTOBAUD_START		BIT(0)
+
+#define ASM9260_HW_CTRL3			0x00d0
+#define ASM9260_BM_CTRL3_OUTCLK_DIV_MASK	(0xffff<<16)
+/*
+ * RW. Provide clk over OUTCLK pin. In case of asm9260 it can be configured on
+ * pins 137 and 144.
+ */
+#define ASM9260_BM_CTRL3_MASTERMODE		BIT(6)
+/* RW. Baud Rate Mode: 1 - Enable sync mode. 0 - async mode. */
+#define ASM9260_BM_CTRL3_SYNCMODE		BIT(4)
+/* RW. 1 - MSB bit send frist; 0 - LSB bit frist. */
+#define ASM9260_BM_CTRL3_MSBF			BIT(2)
+/* RW. 1 - sample rate = 8 x Baudrate; 0 - sample rate = 16 x Baudrate. */
+#define ASM9260_BM_CTRL3_BAUD8			BIT(1)
+/* RW. 1 - Set word lenght to 9bit. 0 - use ASM9260_BM_LCTRL_WLEN */
+#define ASM9260_BM_CTRL3_9BIT			BIT(0)
+
+#define ASM9260_HW_ISO7816_CTRL			0x00e0
+/* RW. Enable High Speed mode. */
+#define ASM9260_BM_ISO7816CTRL_HS		BIT(12)
+/* Disable Successive Receive NACK */
+#define ASM9260_BM_ISO7816CTRL_DS_NACK		BIT(8)
+#define ASM9260_BM_ISO7816CTRL_MAX_ITER_MASK	(0xff<<4)
+/* Receive NACK Inhibit */
+#define ASM9260_BM_ISO7816CTRL_INACK		BIT(3)
+#define ASM9260_BM_ISO7816CTRL_NEG_DATA		BIT(2)
+/* RW. 1 - ISO7816 mode; 0 - USART mode */
+#define ASM9260_BM_ISO7816CTRL_ENABLE		BIT(0)
+
+#define ASM9260_HW_ISO7816_ERRCNT		0x00f0
+/* Parity error counter. Will be cleared after reading */
+#define ASM9260_BM_ISO7816_NB_ERRORS_MASK	(0xff<<0)
+
+#define ASM9260_HW_ISO7816_STATUS		0x0100
+/* Max number of Repetitions Reached */
+#define ASM9260_BM_ISO7816_STAT_ITERATION	BIT(0)
+#endif
diff --git a/drivers/tty/serial/mxs-auart.c b/drivers/tty/serial/mxs-auart.c
index b5c3292..b5a1455 100644
--- a/drivers/tty/serial/mxs-auart.c
+++ b/drivers/tty/serial/mxs-auart.c
@@ -1,17 +1,18 @@
 /*
- * Freescale STMP37XX/STMP378X Application UART driver
+ * Application UART driver for:
+ *	Freescale STMP37XX/STMP378X
+ *	Alphascale ASM9260
  *
  * Author: dmitry pervushin <dimka@embeddedalley.com>
  *
+ * Copyright 2014 Oleksij Rempel <linux@rempel-privat.de>
+ *	Provide Alphascale ASM9260 support.
  * Copyright 2008-2010 Freescale Semiconductor, Inc.
  * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
  *
  * The code contained herein is licensed under the GNU General Public
  * License. You may obtain a copy of the GNU General Public License
  * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
  */
 
 #include <linux/kernel.h>
@@ -37,34 +38,23 @@
 #include <linux/dmaengine.h>
 
 #include <asm/cacheflush.h>
+#include "alphascale,asm9260_serial.h"
 
 #define MXS_AUART_PORTS 5
 #define MXS_AUART_FIFO_SIZE		16
+#define MXS_DEVICENAME			"ttyAPP"
+#define DRIVER_NAME			"mxs-auart"
+
+#define SET_REG				0x4
+#define CLR_REG				0x8
+#define TOG_REG				0xc
 
 #define AUART_CTRL0			0x00000000
-#define AUART_CTRL0_SET			0x00000004
-#define AUART_CTRL0_CLR			0x00000008
-#define AUART_CTRL0_TOG			0x0000000c
 #define AUART_CTRL1			0x00000010
-#define AUART_CTRL1_SET			0x00000014
-#define AUART_CTRL1_CLR			0x00000018
-#define AUART_CTRL1_TOG			0x0000001c
 #define AUART_CTRL2			0x00000020
-#define AUART_CTRL2_SET			0x00000024
-#define AUART_CTRL2_CLR			0x00000028
-#define AUART_CTRL2_TOG			0x0000002c
 #define AUART_LINECTRL			0x00000030
-#define AUART_LINECTRL_SET		0x00000034
-#define AUART_LINECTRL_CLR		0x00000038
-#define AUART_LINECTRL_TOG		0x0000003c
 #define AUART_LINECTRL2			0x00000040
-#define AUART_LINECTRL2_SET		0x00000044
-#define AUART_LINECTRL2_CLR		0x00000048
-#define AUART_LINECTRL2_TOG		0x0000004c
 #define AUART_INTR			0x00000050
-#define AUART_INTR_SET			0x00000054
-#define AUART_INTR_CLR			0x00000058
-#define AUART_INTR_TOG			0x0000005c
 #define AUART_DATA			0x00000060
 #define AUART_STAT			0x00000070
 #define AUART_DEBUG			0x00000080
@@ -129,6 +119,17 @@ static struct uart_driver auart_driver;
 enum mxs_auart_type {
 	IMX23_AUART,
 	IMX28_AUART,
+	ASM9260_AUART,
+};
+
+struct mxs_auart_regs {
+	void __iomem *ctrl0;
+	void __iomem *ctrl1;
+	void __iomem *ctrl2;
+	void __iomem *linectrl;
+	void __iomem *intr;
+	void __iomem *data;
+	void __iomem *stat;
 };
 
 struct mxs_auart_port {
@@ -142,9 +143,11 @@ struct mxs_auart_port {
 	unsigned int ctrl;
 	enum mxs_auart_type devtype;
 
+	struct mxs_auart_regs regs;
 	unsigned int irq;
 
 	struct clk *clk;
+	struct clk *clk_ahb;
 	struct device *dev;
 
 	/* for DMA */
@@ -160,6 +163,7 @@ struct mxs_auart_port {
 static struct platform_device_id mxs_auart_devtype[] = {
 	{ .name = "mxs-auart-imx23", .driver_data = IMX23_AUART },
 	{ .name = "mxs-auart-imx28", .driver_data = IMX28_AUART },
+	{ .name = "as-auart-asm9260", .driver_data = ASM9260_AUART },
 	{ /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(platform, mxs_auart_devtype);
@@ -171,7 +175,11 @@ static struct of_device_id mxs_auart_dt_ids[] = {
 	}, {
 		.compatible = "fsl,imx23-auart",
 		.data = &mxs_auart_devtype[IMX23_AUART]
+	}, {
+		.compatible = "alphascale,asm9260-auart",
+		.data = &mxs_auart_devtype[ASM9260_AUART]
 	}, { /* sentinel */ }
+
 };
 MODULE_DEVICE_TABLE(of, mxs_auart_dt_ids);
 
@@ -180,6 +188,11 @@ static inline int is_imx28_auart(struct mxs_auart_port *s)
 	return s->devtype == IMX28_AUART;
 }
 
+static inline int is_asm9260_auart(struct mxs_auart_port *s)
+{
+	return s->devtype == ASM9260_AUART;
+}
+
 static inline bool auart_dma_enabled(struct mxs_auart_port *s)
 {
 	return s->flags & MXS_AUART_DMA_ENABLED;
@@ -281,19 +294,19 @@ static void mxs_auart_tx_chars(struct mxs_auart_port *s)
 	}
 
 
-	while (!(readl(s->port.membase + AUART_STAT) &
+	while (!(readl(s->regs.stat) &
 		 AUART_STAT_TXFF)) {
 		if (s->port.x_char) {
 			s->port.icount.tx++;
 			writel(s->port.x_char,
-				     s->port.membase + AUART_DATA);
+				     s->regs.data);
 			s->port.x_char = 0;
 			continue;
 		}
 		if (!uart_circ_empty(xmit) && !uart_tx_stopped(&s->port)) {
 			s->port.icount.tx++;
 			writel(xmit->buf[xmit->tail],
-				     s->port.membase + AUART_DATA);
+				     s->regs.data);
 			xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
 		} else
 			break;
@@ -303,10 +316,10 @@ static void mxs_auart_tx_chars(struct mxs_auart_port *s)
 
 	if (uart_circ_empty(&(s->port.state->xmit)))
 		writel(AUART_INTR_TXIEN,
-			     s->port.membase + AUART_INTR_CLR);
+			     s->regs.intr + CLR_REG);
 	else
 		writel(AUART_INTR_TXIEN,
-			     s->port.membase + AUART_INTR_SET);
+			     s->regs.intr + SET_REG);
 
 	if (uart_tx_stopped(&s->port))
 		mxs_auart_stop_tx(&s->port);
@@ -318,8 +331,8 @@ static void mxs_auart_rx_char(struct mxs_auart_port *s)
 	u32 stat;
 	u8 c;
 
-	c = readl(s->port.membase + AUART_DATA);
-	stat = readl(s->port.membase + AUART_STAT);
+	c = readl(s->regs.data);
+	stat = readl(s->regs.stat);
 
 	flag = TTY_NORMAL;
 	s->port.icount.rx++;
@@ -354,7 +367,7 @@ static void mxs_auart_rx_char(struct mxs_auart_port *s)
 
 	uart_insert_char(&s->port, stat, AUART_STAT_OERR, c, flag);
 out:
-	writel(stat, s->port.membase + AUART_STAT);
+	writel(stat, s->regs.stat);
 }
 
 static void mxs_auart_rx_chars(struct mxs_auart_port *s)
@@ -362,13 +375,13 @@ static void mxs_auart_rx_chars(struct mxs_auart_port *s)
 	u32 stat = 0;
 
 	for (;;) {
-		stat = readl(s->port.membase + AUART_STAT);
+		stat = readl(s->regs.stat);
 		if (stat & AUART_STAT_RXFE)
 			break;
 		mxs_auart_rx_char(s);
 	}
 
-	writel(stat, s->port.membase + AUART_STAT);
+	writel(stat, s->regs.stat);
 	tty_flip_buffer_push(&s->port.state->port);
 }
 
@@ -404,7 +417,7 @@ static void mxs_auart_set_mctrl(struct uart_port *u, unsigned mctrl)
 {
 	struct mxs_auart_port *s = to_auart_port(u);
 
-	u32 ctrl = readl(u->membase + AUART_CTRL2);
+	u32 ctrl = readl(s->regs.ctrl2);
 
 	ctrl &= ~(AUART_CTRL2_RTSEN | AUART_CTRL2_RTS);
 	if (mctrl & TIOCM_RTS) {
@@ -415,14 +428,14 @@ static void mxs_auart_set_mctrl(struct uart_port *u, unsigned mctrl)
 	}
 
 	s->ctrl = mctrl;
-	writel(ctrl, u->membase + AUART_CTRL2);
+	writel(ctrl, s->regs.ctrl2);
 }
 
 static u32 mxs_auart_get_mctrl(struct uart_port *u)
 {
 	struct mxs_auart_port *s = to_auart_port(u);
-	u32 stat = readl(u->membase + AUART_STAT);
-	int ctrl2 = readl(u->membase + AUART_CTRL2);
+	u32 stat = readl(s->regs.stat);
+	int ctrl2 = readl(s->regs.ctrl2);
 	u32 mctrl = s->ctrl;
 
 	mctrl &= ~TIOCM_CTS;
@@ -445,14 +458,14 @@ static void dma_rx_callback(void *arg)
 
 	dma_unmap_sg(s->dev, &s->rx_sgl, 1, DMA_FROM_DEVICE);
 
-	stat = readl(s->port.membase + AUART_STAT);
+	stat = readl(s->regs.stat);
 	stat &= ~(AUART_STAT_OERR | AUART_STAT_BERR |
 			AUART_STAT_PERR | AUART_STAT_FERR);
 
 	count = stat & AUART_STAT_RXCOUNT_MASK;
 	tty_insert_flip_string(port, s->rx_dma_buf, count);
 
-	writel(stat, s->port.membase + AUART_STAT);
+	writel(stat, s->regs.stat);
 	tty_flip_buffer_push(port);
 
 	/* start the next DMA for RX. */
@@ -506,8 +519,8 @@ static void mxs_auart_dma_exit_channel(struct mxs_auart_port *s)
 		s->rx_dma_chan = NULL;
 	}
 
-	kfree(s->tx_dma_buf);
-	kfree(s->rx_dma_buf);
+	devm_kfree(s->dev, s->tx_dma_buf);
+	devm_kfree(s->dev, s->rx_dma_buf);
 	s->tx_dma_buf = NULL;
 	s->rx_dma_buf = NULL;
 }
@@ -516,7 +529,7 @@ static void mxs_auart_dma_exit(struct mxs_auart_port *s)
 {
 
 	writel(AUART_CTRL2_TXDMAE | AUART_CTRL2_RXDMAE | AUART_CTRL2_DMAONERR,
-		s->port.membase + AUART_CTRL2_CLR);
+		s->regs.ctrl2 + CLR_REG);
 
 	mxs_auart_dma_exit_channel(s);
 	s->flags &= ~MXS_AUART_DMA_ENABLED;
@@ -533,7 +546,8 @@ static int mxs_auart_dma_init(struct mxs_auart_port *s)
 	s->rx_dma_chan = dma_request_slave_channel(s->dev, "rx");
 	if (!s->rx_dma_chan)
 		goto err_out;
-	s->rx_dma_buf = kzalloc(UART_XMIT_SIZE, GFP_KERNEL | GFP_DMA);
+	s->rx_dma_buf = devm_kzalloc(s->dev,
+			UART_XMIT_SIZE, GFP_KERNEL | GFP_DMA);
 	if (!s->rx_dma_buf)
 		goto err_out;
 
@@ -541,7 +555,8 @@ static int mxs_auart_dma_init(struct mxs_auart_port *s)
 	s->tx_dma_chan = dma_request_slave_channel(s->dev, "tx");
 	if (!s->tx_dma_chan)
 		goto err_out;
-	s->tx_dma_buf = kzalloc(UART_XMIT_SIZE, GFP_KERNEL | GFP_DMA);
+	s->tx_dma_buf = devm_kzalloc(s->dev,
+			UART_XMIT_SIZE, GFP_KERNEL | GFP_DMA);
 	if (!s->tx_dma_buf)
 		goto err_out;
 
@@ -571,7 +586,7 @@ static void mxs_auart_settermios(struct uart_port *u,
 	cflag = termios->c_cflag;
 
 	ctrl = AUART_LINECTRL_FEN;
-	ctrl2 = readl(u->membase + AUART_CTRL2);
+	ctrl2 = readl(s->regs.ctrl2);
 
 	/* byte size */
 	switch (cflag & CSIZE) {
@@ -656,13 +671,21 @@ static void mxs_auart_settermios(struct uart_port *u,
 	}
 
 	/* set baud rate */
-	baud = uart_get_baud_rate(u, termios, old, 0, u->uartclk);
-	div = u->uartclk * 32 / baud;
+	if (is_asm9260_auart(s)) {
+		baud = uart_get_baud_rate(u, termios, old,
+				u->uartclk * 4 / 0x3FFFFF,
+				u->uartclk / 16);
+		div = u->uartclk * 4 / baud;
+	} else {
+		baud = uart_get_baud_rate(u, termios, old, 0, u->uartclk);
+		div = u->uartclk * 32 / baud;
+	}
+
 	ctrl |= AUART_LINECTRL_BAUD_DIVFRAC(div & 0x3F);
 	ctrl |= AUART_LINECTRL_BAUD_DIVINT(div >> 6);
+	writel(ctrl, s->regs.linectrl);
 
-	writel(ctrl, u->membase + AUART_LINECTRL);
-	writel(ctrl2, u->membase + AUART_CTRL2);
+	writel(ctrl2, s->regs.ctrl2);
 
 	uart_update_timeout(u, termios->c_cflag, baud);
 
@@ -672,7 +695,7 @@ static void mxs_auart_settermios(struct uart_port *u,
 		if (!mxs_auart_dma_prep_rx(s)) {
 			/* Disable the normal RX interrupt. */
 			writel(AUART_INTR_RXIEN | AUART_INTR_RTIEN,
-					u->membase + AUART_INTR_CLR);
+					s->regs.intr + CLR_REG);
 		} else {
 			mxs_auart_dma_exit(s);
 			dev_err(s->dev, "We can not start up the DMA.\n");
@@ -684,21 +707,21 @@ static irqreturn_t mxs_auart_irq_handle(int irq, void *context)
 {
 	u32 istat;
 	struct mxs_auart_port *s = context;
-	u32 stat = readl(s->port.membase + AUART_STAT);
+	u32 stat = readl(s->regs.stat);
 
-	istat = readl(s->port.membase + AUART_INTR);
+	istat = readl(s->regs.intr);
 
 	/* ack irq */
 	writel(istat & (AUART_INTR_RTIS
 		| AUART_INTR_TXIS
 		| AUART_INTR_RXIS
 		| AUART_INTR_CTSMIS),
-			s->port.membase + AUART_INTR_CLR);
+			s->regs.intr + CLR_REG);
 
 	if (istat & AUART_INTR_CTSMIS) {
 		uart_handle_cts_change(&s->port, stat & AUART_STAT_CTS);
 		writel(AUART_INTR_CTSMIS,
-				s->port.membase + AUART_INTR_CLR);
+				s->regs.intr + CLR_REG);
 		istat &= ~AUART_INTR_CTSMIS;
 	}
 
@@ -716,20 +739,20 @@ static irqreturn_t mxs_auart_irq_handle(int irq, void *context)
 	return IRQ_HANDLED;
 }
 
-static void mxs_auart_reset(struct uart_port *u)
+static void mxs_auart_reset(struct mxs_auart_port *s)
 {
 	int i;
 	unsigned int reg;
 
-	writel(AUART_CTRL0_SFTRST, u->membase + AUART_CTRL0_CLR);
+	writel(AUART_CTRL0_SFTRST, s->regs.ctrl0 + CLR_REG);
 
 	for (i = 0; i < 10000; i++) {
-		reg = readl(u->membase + AUART_CTRL0);
+		reg = readl(s->regs.ctrl0);
 		if (!(reg & AUART_CTRL0_SFTRST))
 			break;
 		udelay(3);
 	}
-	writel(AUART_CTRL0_CLKGATE, u->membase + AUART_CTRL0_CLR);
+	writel(AUART_CTRL0_CLKGATE, s->regs.ctrl0 + CLR_REG);
 }
 
 static int mxs_auart_startup(struct uart_port *u)
@@ -741,12 +764,12 @@ static int mxs_auart_startup(struct uart_port *u)
 	if (ret)
 		return ret;
 
-	writel(AUART_CTRL0_CLKGATE, u->membase + AUART_CTRL0_CLR);
+	writel(AUART_CTRL0_CLKGATE, s->regs.ctrl0 + CLR_REG);
 
-	writel(AUART_CTRL2_UARTEN, u->membase + AUART_CTRL2_SET);
+	writel(AUART_CTRL2_UARTEN, s->regs.ctrl2 + SET_REG);
 
 	writel(AUART_INTR_RXIEN | AUART_INTR_RTIEN | AUART_INTR_CTSMIEN,
-			u->membase + AUART_INTR);
+			s->regs.intr);
 
 	/* Reset FIFO size (it could have changed if DMA was enabled) */
 	u->fifosize = MXS_AUART_FIFO_SIZE;
@@ -755,7 +778,7 @@ static int mxs_auart_startup(struct uart_port *u)
 	 * Enable fifo so all four bytes of a DMA word are written to
 	 * output (otherwise, only the LSB is written, ie. 1 in 4 bytes)
 	 */
-	writel(AUART_LINECTRL_FEN, u->membase + AUART_LINECTRL_SET);
+	writel(AUART_LINECTRL_FEN, s->regs.linectrl + SET_REG);
 
 	return 0;
 }
@@ -767,19 +790,21 @@ static void mxs_auart_shutdown(struct uart_port *u)
 	if (auart_dma_enabled(s))
 		mxs_auart_dma_exit(s);
 
-	writel(AUART_CTRL2_UARTEN, u->membase + AUART_CTRL2_CLR);
+	writel(AUART_CTRL2_UARTEN, s->regs.ctrl2 + CLR_REG);
 
 	writel(AUART_INTR_RXIEN | AUART_INTR_RTIEN | AUART_INTR_CTSMIEN,
-			u->membase + AUART_INTR_CLR);
+			s->regs.intr + CLR_REG);
 
-	writel(AUART_CTRL0_CLKGATE, u->membase + AUART_CTRL0_SET);
+	writel(AUART_CTRL0_CLKGATE, s->regs.ctrl0 + SET_REG);
 
 	clk_disable_unprepare(s->clk);
 }
 
 static unsigned int mxs_auart_tx_empty(struct uart_port *u)
 {
-	if (readl(u->membase + AUART_STAT) & AUART_STAT_TXFE)
+	struct mxs_auart_port *s = to_auart_port(u);
+
+	if (readl(s->regs.stat) & AUART_STAT_TXFE)
 		return TIOCSER_TEMT;
 	else
 		return 0;
@@ -790,29 +815,35 @@ static void mxs_auart_start_tx(struct uart_port *u)
 	struct mxs_auart_port *s = to_auart_port(u);
 
 	/* enable transmitter */
-	writel(AUART_CTRL2_TXE, u->membase + AUART_CTRL2_SET);
+	writel(AUART_CTRL2_TXE, s->regs.ctrl2 + SET_REG);
 
 	mxs_auart_tx_chars(s);
 }
 
 static void mxs_auart_stop_tx(struct uart_port *u)
 {
-	writel(AUART_CTRL2_TXE, u->membase + AUART_CTRL2_CLR);
+	struct mxs_auart_port *s = to_auart_port(u);
+
+	writel(AUART_CTRL2_TXE, s->regs.ctrl2 + CLR_REG);
 }
 
 static void mxs_auart_stop_rx(struct uart_port *u)
 {
-	writel(AUART_CTRL2_RXE, u->membase + AUART_CTRL2_CLR);
+	struct mxs_auart_port *s = to_auart_port(u);
+
+	writel(AUART_CTRL2_RXE, s->regs.ctrl2 + CLR_REG);
 }
 
 static void mxs_auart_break_ctl(struct uart_port *u, int ctl)
 {
+	struct mxs_auart_port *s = to_auart_port(u);
+
 	if (ctl)
 		writel(AUART_LINECTRL_BRK,
-			     u->membase + AUART_LINECTRL_SET);
+			     s->regs.linectrl + SET_REG);
 	else
 		writel(AUART_LINECTRL_BRK,
-			     u->membase + AUART_LINECTRL_CLR);
+			     s->regs.linectrl + CLR_REG);
 }
 
 static struct uart_ops mxs_auart_ops = {
@@ -838,15 +869,16 @@ static struct mxs_auart_port *auart_port[MXS_AUART_PORTS];
 #ifdef CONFIG_SERIAL_MXS_AUART_CONSOLE
 static void mxs_auart_console_putchar(struct uart_port *port, int ch)
 {
+	struct mxs_auart_port *s = to_auart_port(port);
 	unsigned int to = 1000;
 
-	while (readl(port->membase + AUART_STAT) & AUART_STAT_TXFF) {
+	while (readl(s->regs.stat) & AUART_STAT_TXFF) {
 		if (!to--)
 			break;
 		udelay(1);
 	}
 
-	writel(ch, port->membase + AUART_DATA);
+	writel(ch, s->regs.data);
 }
 
 static void
@@ -866,18 +898,18 @@ auart_console_write(struct console *co, const char *str, unsigned int count)
 	clk_enable(s->clk);
 
 	/* First save the CR then disable the interrupts */
-	old_ctrl2 = readl(port->membase + AUART_CTRL2);
-	old_ctrl0 = readl(port->membase + AUART_CTRL0);
+	old_ctrl2 = readl(s->regs.ctrl2);
+	old_ctrl0 = readl(s->regs.ctrl0);
 
 	writel(AUART_CTRL0_CLKGATE,
-		     port->membase + AUART_CTRL0_CLR);
+		     s->regs.ctrl0 + CLR_REG);
 	writel(AUART_CTRL2_UARTEN | AUART_CTRL2_TXE,
-		     port->membase + AUART_CTRL2_SET);
+		     s->regs.ctrl2 + SET_REG);
 
 	uart_console_write(port, str, count, mxs_auart_console_putchar);
 
 	/* Finally, wait for transmitter to become empty ... */
-	while (readl(port->membase + AUART_STAT) & AUART_STAT_BUSY) {
+	while (readl(s->regs.stat) & AUART_STAT_BUSY) {
 		udelay(1);
 		if (!to--)
 			break;
@@ -889,24 +921,25 @@ auart_console_write(struct console *co, const char *str, unsigned int count)
 	 * unused, but that is better than to disable it while it is still
 	 * transmitting.
 	 */
-	if (!(readl(port->membase + AUART_STAT) & AUART_STAT_BUSY)) {
-		writel(old_ctrl0, port->membase + AUART_CTRL0);
-		writel(old_ctrl2, port->membase + AUART_CTRL2);
+	if (!(readl(s->regs.stat) & AUART_STAT_BUSY)) {
+		writel(old_ctrl0, s->regs.ctrl0);
+		writel(old_ctrl2, s->regs.ctrl2);
 	}
 
 	clk_disable(s->clk);
 }
 
 static void __init
-auart_console_get_options(struct uart_port *port, int *baud,
+auart_console_get_options(struct mxs_auart_port *s, int *baud,
 			  int *parity, int *bits)
 {
+	struct uart_port *port = &s->port;
 	unsigned int lcr_h, quot;
 
-	if (!(readl(port->membase + AUART_CTRL2) & AUART_CTRL2_UARTEN))
+	if (!(readl(s->regs.ctrl2) & AUART_CTRL2_UARTEN))
 		return;
 
-	lcr_h = readl(port->membase + AUART_LINECTRL);
+	lcr_h = readl(s->regs.linectrl);
 
 	*parity = 'n';
 	if (lcr_h & AUART_LINECTRL_PEN) {
@@ -921,10 +954,10 @@ auart_console_get_options(struct uart_port *port, int *baud,
 	else
 		*bits = 8;
 
-	quot = ((readl(port->membase + AUART_LINECTRL)
+	quot = ((readl(s->regs.linectrl)
 			& AUART_LINECTRL_BAUD_DIVINT_MASK))
 			    >> (AUART_LINECTRL_BAUD_DIVINT_SHIFT - 6);
-	quot |= ((readl(port->membase + AUART_LINECTRL)
+	quot |= ((readl(s->regs.linectrl)
 			& AUART_LINECTRL_BAUD_DIVFRAC_MASK))
 				>> AUART_LINECTRL_BAUD_DIVFRAC_SHIFT;
 	if (quot == 0)
@@ -950,6 +983,7 @@ auart_console_setup(struct console *co, char *options)
 	 */
 	if (co->index == -1 || co->index >= ARRAY_SIZE(auart_port))
 		co->index = 0;
+
 	s = auart_port[co->index];
 	if (!s)
 		return -ENODEV;
@@ -961,7 +995,7 @@ auart_console_setup(struct console *co, char *options)
 	if (options)
 		uart_parse_options(options, &baud, &parity, &bits, &flow);
 	else
-		auart_console_get_options(&s->port, &baud, &parity, &bits);
+		auart_console_get_options(s, &baud, &parity, &bits);
 
 	ret = uart_set_options(&s->port, co, baud, parity, bits, flow);
 
@@ -971,7 +1005,7 @@ auart_console_setup(struct console *co, char *options)
 }
 
 static struct console auart_console = {
-	.name		= "ttyAPP",
+	.name		= MXS_DEVICENAME,
 	.write		= auart_console_write,
 	.device		= uart_console_device,
 	.setup		= auart_console_setup,
@@ -983,8 +1017,8 @@ static struct console auart_console = {
 
 static struct uart_driver auart_driver = {
 	.owner		= THIS_MODULE,
-	.driver_name	= "ttyAPP",
-	.dev_name	= "ttyAPP",
+	.driver_name	= MXS_DEVICENAME,
+	.dev_name	= MXS_DEVICENAME,
 	.major		= 0,
 	.minor		= 0,
 	.nr		= MXS_AUART_PORTS,
@@ -993,6 +1027,58 @@ static struct uart_driver auart_driver = {
 #endif
 };
 
+static void mxs_init_regs(struct mxs_auart_port *s)
+{
+	s->regs.ctrl0	= s->port.membase + AUART_CTRL0;
+	s->regs.ctrl1	= s->port.membase + AUART_CTRL1;
+	s->regs.ctrl2	= s->port.membase + AUART_CTRL2;
+	s->regs.linectrl	= s->port.membase + AUART_LINECTRL;
+
+	if (is_asm9260_auart(s)) {
+		s->regs.intr	= s->port.membase + ASM9260_HW_INTR;
+		s->regs.data	= s->port.membase + ASM9260_HW_DATA;
+		s->regs.stat	= s->port.membase + ASM9260_HW_STAT;
+	} else {
+		s->regs.intr	= s->port.membase + AUART_INTR;
+		s->regs.data	= s->port.membase + AUART_DATA;
+		s->regs.stat	= s->port.membase + AUART_STAT;
+	}
+}
+
+static int mxs_get_dt_clks(struct mxs_auart_port *s,
+		struct platform_device *pdev)
+{
+	struct device_node *np = pdev->dev.of_node;
+	int clk_idx = 0, err;
+
+	s->clk = of_clk_get(np, clk_idx);
+	if (IS_ERR(s->clk))
+		goto out_err;
+
+	/* configure AHB clock */
+	clk_idx = 1;
+	s->clk_ahb = of_clk_get(np, clk_idx);
+	if (IS_ERR(s->clk_ahb))
+		goto out_err;
+
+	err = clk_prepare_enable(s->clk_ahb);
+	if (err)
+		dev_err(s->dev, "Failed to enable ahb_clk!\n");
+
+	err = clk_set_rate(s->clk, clk_get_rate(s->clk_ahb));
+	if (err)
+		dev_err(s->dev, "Failed to set rate!\n");
+
+	err = clk_prepare_enable(s->clk);
+	if (err)
+		dev_err(s->dev, "Failed to enable clk!\n");
+
+	return 0;
+out_err:
+	dev_err(s->dev, "%s: Failed to get clk (%i)\n", __func__, clk_idx);
+	return 1;
+}
+
 /*
  * This function returns 1 if pdev isn't a device instatiated by dt, 0 if it
  * could successfully get all information from dt or a negative errno.
@@ -1029,77 +1115,98 @@ static int mxs_auart_probe(struct platform_device *pdev)
 	int ret = 0;
 	struct resource *r;
 
-	s = kzalloc(sizeof(struct mxs_auart_port), GFP_KERNEL);
+	s = devm_kzalloc(&pdev->dev,
+			sizeof(struct mxs_auart_port), GFP_KERNEL);
 	if (!s) {
 		ret = -ENOMEM;
 		goto out;
 	}
 
+	s->port.dev = s->dev = &pdev->dev;
+
 	ret = serial_mxs_probe_dt(s, pdev);
 	if (ret > 0)
 		s->port.line = pdev->id < 0 ? 0 : pdev->id;
 	else if (ret < 0)
-		goto out_free;
+		return ret;
 
 	if (of_id) {
 		pdev->id_entry = of_id->data;
 		s->devtype = pdev->id_entry->driver_data;
 	}
 
-	s->clk = clk_get(&pdev->dev, NULL);
-	if (IS_ERR(s->clk)) {
-		ret = PTR_ERR(s->clk);
-		goto out_free;
+	if (is_asm9260_auart(s)) {
+		if (mxs_get_dt_clks(s, pdev))
+			return -ENODEV;
+	} else {
+		s->clk = devm_clk_get(&pdev->dev, NULL);
+		if (IS_ERR(s->clk))
+			return PTR_ERR(s->clk);
 	}
 
 	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!r) {
-		ret = -ENXIO;
-		goto out_free_clk;
+		dev_err(s->dev, "platform_get_resource filed!\n");
+		return -ENXIO;
+	}
+
+	if (!devm_request_mem_region(s->dev, r->start, resource_size(r),
+				dev_name(s->dev))) {
+		dev_err(s->dev, "request_mem_region filed!\n");
+		return -ENXIO;
+	}
+
+	s->port.membase = devm_ioremap_nocache(s->dev, r->start,
+			resource_size(r));
+	if (!s->port.membase) {
+		dev_err(s->dev, "ioremap filed!\n");
+		return -ENXIO;
 	}
 
 	s->port.mapbase = r->start;
-	s->port.membase = ioremap(r->start, resource_size(r));
 	s->port.ops = &mxs_auart_ops;
 	s->port.iotype = UPIO_MEM;
 	s->port.fifosize = MXS_AUART_FIFO_SIZE;
 	s->port.uartclk = clk_get_rate(s->clk);
 	s->port.type = PORT_IMX;
-	s->port.dev = s->dev = &pdev->dev;
+
+	mxs_init_regs(s);
 
 	s->ctrl = 0;
 
 	s->irq = platform_get_irq(pdev, 0);
 	s->port.irq = s->irq;
-	ret = request_irq(s->irq, mxs_auart_irq_handle, 0, dev_name(&pdev->dev), s);
+	ret = devm_request_threaded_irq(s->dev, s->irq, NULL,
+			mxs_auart_irq_handle, IRQF_ONESHOT,
+			dev_name(&pdev->dev), s);
 	if (ret)
-		goto out_free_clk;
+		return ret;
 
 	platform_set_drvdata(pdev, s);
 
 	auart_port[s->port.line] = s;
 
-	mxs_auart_reset(&s->port);
+	mxs_auart_reset(s);
 
 	ret = uart_add_one_port(&auart_driver, &s->port);
 	if (ret)
-		goto out_free_irq;
+		goto out;
+
 
-	version = readl(s->port.membase + AUART_VERSION);
-	dev_info(&pdev->dev, "Found APPUART %d.%d.%d\n",
-	       (version >> 24) & 0xff,
-	       (version >> 16) & 0xff, version & 0xffff);
+	/* ASM9260 don't have version reg */
+	if (is_asm9260_auart(s))
+		dev_info(&pdev->dev, "Found APPUART ASM9260\n");
+	else {
+		version = readl(s->port.membase + AUART_VERSION);
+		dev_info(&pdev->dev, "Found APPUART %d.%d.%d\n",
+			 (version >> 24) & 0xff,
+			 (version >> 16) & 0xff, version & 0xffff);
+	}
 
 	return 0;
 
-out_free_irq:
-	auart_port[pdev->id] = NULL;
-	free_irq(s->irq, s);
-out_free_clk:
-	clk_put(s->clk);
-out_free:
-	kfree(s);
 out:
+	auart_port[pdev->id] = NULL;
 	return ret;
 }
 
@@ -1110,11 +1217,6 @@ static int mxs_auart_remove(struct platform_device *pdev)
 	uart_remove_one_port(&auart_driver, &s->port);
 
 	auart_port[pdev->id] = NULL;
-
-	clk_put(s->clk);
-	free_irq(s->irq, s);
-	kfree(s);
-
 	return 0;
 }
 
@@ -1122,7 +1224,7 @@ static struct platform_driver mxs_auart_driver = {
 	.probe = mxs_auart_probe,
 	.remove = mxs_auart_remove,
 	.driver = {
-		.name = "mxs-auart",
+		.name = DRIVER_NAME,
 		.owner = THIS_MODULE,
 		.of_match_table = mxs_auart_dt_ids,
 	},
@@ -1157,4 +1259,4 @@ module_init(mxs_auart_init);
 module_exit(mxs_auart_exit);
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Freescale MXS application uart driver");
-MODULE_ALIAS("platform:mxs-auart");
+MODULE_ALIAS("platform:" DRIVER_NAME);
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH v5 08/10] ARM: dts: add DT for Alphascale ASM9260 SoC
  2014-10-14  8:03 [PATCH v5 00/10] initial suport for Alphascale ASM9260 Oleksij Rempel
                   ` (6 preceding siblings ...)
  2014-10-14  8:03 ` [PATCH v5 07/10] ARM: tty: mxs-auart: add initial Alphascale ASM9260 support Oleksij Rempel
@ 2014-10-14  8:03 ` Oleksij Rempel
  2014-10-14  8:03 ` [PATCH v5 09/10] ARM: add alphascale,acc.txt bindings documentation Oleksij Rempel
  2014-10-14  8:03 ` [PATCH v5 10/10] add Alphascale to vendor-prefixes.txt Oleksij Rempel
  9 siblings, 0 replies; 16+ messages in thread
From: Oleksij Rempel @ 2014-10-14  8:03 UTC (permalink / raw)
  To: linux-arm-kernel

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

Signed-off-by: Oleksij Rempel <linux@rempel-privat.de>
---
 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

diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index b8c5cd3..8943d72 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -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
diff --git a/arch/arm/boot/dts/alphascale-asm9260-devkit.dts b/arch/arm/boot/dts/alphascale-asm9260-devkit.dts
new file mode 100644
index 0000000..bf63dd2
--- /dev/null
+++ b/arch/arm/boot/dts/alphascale-asm9260-devkit.dts
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2014 Oleksij Rempel <linux@rempel-privat.de>
+ *
+ * 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";
+};
diff --git a/arch/arm/boot/dts/alphascale-asm9260.dtsi b/arch/arm/boot/dts/alphascale-asm9260.dtsi
new file mode 100644
index 0000000..8ab7c67
--- /dev/null
+++ b/arch/arm/boot/dts/alphascale-asm9260.dtsi
@@ -0,0 +1,134 @@
+/*
+ * Copyright 2014 Oleksij Rempel <linux@rempel-privat.de>
+ *
+ * Licensed under the X11 license or the GPL v2 (or later)
+ */
+
+#include "skeleton.dtsi"
+#include <dt-bindings/clock/alphascale,asm9260.h>
+
+/ {
+	interrupt-parent = <&icoll>;
+
+	memory {
+		device_type = "memory";
+		reg = <0x20000000 0x2000000>;
+	};
+
+	cpus {
+		#address-cells = <0>;
+		#size-cells = <0>;
+
+		cpu {
+			compatible = "arm,arm926ej-s";
+			device_type = "cpu";
+			clocks = <&acc CLKID_SYS_CPU>;
+		};
+	};
+
+	osc24m: oscillator {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <24000000>;
+		clock-accuracy = <30000>;
+	};
+
+	soc {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "simple-bus";
+		ranges;
+
+		acc: clock-controller at 80040000 {
+			compatible = "alphascale,asm9260-clock-controller";
+			#clock-cells = <1>;
+			clocks = <&osc24m>;
+			reg = <0x80040000 0x204>;
+		};
+
+		icoll: interrupt-controller at 80054000 {
+			compatible = "alphascale,asm9260-icoll";
+			interrupt-controller;
+			#interrupt-cells = <1>;
+			reg = <0x80054000 0x200>;
+		};
+
+		uart0: serial at 80000000 {
+			compatible = "alphascale,asm9260-auart";
+			reg = <0x80000000 0x4000>;
+			clocks = <&acc CLKID_SYS_UART0>, <&acc CLKID_AHB_UART0>;
+			interrupts = <15>;
+			status = "disabled";
+		};
+		uart1: serial at 80004000 {
+			compatible = "alphascale,asm9260-auart";
+			reg = <0x80004000 0x4000>;
+			clocks = <&acc CLKID_SYS_UART1>, <&acc CLKID_AHB_UART1>;
+			interrupts = <16>;
+			status = "disabled";
+		};
+		uart2: serial at 80008000 {
+			compatible = "alphascale,asm9260-auart";
+			reg = <0x80008000 0x4000>;
+			clocks = <&acc CLKID_SYS_UART2>, <&acc CLKID_AHB_UART2>;
+			interrupts = <17>;
+			status = "disabled";
+		};
+		uart3: serial at 8000c000 {
+			compatible = "alphascale,asm9260-auart";
+			reg = <0x8000c000 0x4000>;
+			clocks = <&acc CLKID_SYS_UART3>, <&acc CLKID_AHB_UART3>;
+			interrupts = <18>;
+			status = "disabled";
+		};
+		uart4: serial at 80010000 {
+			compatible = "alphascale,asm9260-auart";
+			reg = <0x80010000 0x4000>;
+			clocks = <&acc CLKID_SYS_UART4>, <&acc CLKID_AHB_UART4>;
+			interrupts = <19>;
+			status = "disabled";
+		};
+		uart5: serial at 80014000 {
+			compatible = "alphascale,asm9260-auart";
+			reg = <0x80014000 0x4000>;
+			clocks = <&acc CLKID_SYS_UART5>, <&acc CLKID_AHB_UART5>;
+			interrupts = <20>;
+			status = "disabled";
+		};
+		uart6: serial at 80018000 {
+			compatible = "alphascale,asm9260-auart";
+			reg = <0x80018000 0x4000>;
+			clocks = <&acc CLKID_SYS_UART6>, <&acc CLKID_AHB_UART6>;
+			interrupts = <21>;
+			status = "disabled";
+		};
+		uart7: serial at 8001c000 {
+			compatible = "alphascale,asm9260-auart";
+			reg = <0x8001c000 0x4000>;
+			clocks = <&acc CLKID_SYS_UART7>, <&acc CLKID_AHB_UART7>;
+			interrupts = <22>;
+			status = "disabled";
+		};
+		uart8: serial at 80020000 {
+			compatible = "alphascale,asm9260-auart";
+			reg = <0x80020000 0x4000>;
+			clocks = <&acc CLKID_SYS_UART8>, <&acc CLKID_AHB_UART8>;
+			interrupts = <23>;
+			status = "disabled";
+		};
+		uart9: serial at 80024000 {
+			compatible = "alphascale,asm9260-auart";
+			reg = <0x80024000 0x4000>;
+			clocks = <&acc CLKID_SYS_UART9>, <&acc CLKID_AHB_UART9>;
+			interrupts = <24>;
+			status = "disabled";
+		};
+
+		timer0: timer at 80088000 {
+			compatible = "alphascale,asm9260-timer";
+			reg = <0x80088000 0x4000>;
+			clocks = <&acc CLKID_AHB_TIMER0>;
+			interrupts = <29>;
+		};
+	};
+};
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH v5 09/10] ARM: add alphascale,acc.txt bindings documentation
  2014-10-14  8:03 [PATCH v5 00/10] initial suport for Alphascale ASM9260 Oleksij Rempel
                   ` (7 preceding siblings ...)
  2014-10-14  8:03 ` [PATCH v5 08/10] ARM: dts: add DT for Alphascale ASM9260 SoC Oleksij Rempel
@ 2014-10-14  8:03 ` Oleksij Rempel
  2014-10-14  8:03 ` [PATCH v5 10/10] add Alphascale to vendor-prefixes.txt Oleksij Rempel
  9 siblings, 0 replies; 16+ messages in thread
From: Oleksij Rempel @ 2014-10-14  8:03 UTC (permalink / raw)
  To: linux-arm-kernel

ACC is for AlphaScale Clock Controller.

Signed-off-by: Oleksij Rempel <linux@rempel-privat.de>
---
 .../devicetree/bindings/clock/alphascale,acc.txt   | 115 +++++++++++++++++++++
 1 file changed, 115 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/alphascale,acc.txt

diff --git a/Documentation/devicetree/bindings/clock/alphascale,acc.txt b/Documentation/devicetree/bindings/clock/alphascale,acc.txt
new file mode 100644
index 0000000..62e67e8
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/alphascale,acc.txt
@@ -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>;
+};
+
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH v5 10/10] add Alphascale to vendor-prefixes.txt
  2014-10-14  8:03 [PATCH v5 00/10] initial suport for Alphascale ASM9260 Oleksij Rempel
                   ` (8 preceding siblings ...)
  2014-10-14  8:03 ` [PATCH v5 09/10] ARM: add alphascale,acc.txt bindings documentation Oleksij Rempel
@ 2014-10-14  8:03 ` Oleksij Rempel
  9 siblings, 0 replies; 16+ messages in thread
From: Oleksij Rempel @ 2014-10-14  8:03 UTC (permalink / raw)
  To: linux-arm-kernel

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

Signed-off-by: Oleksij Rempel <linux@rempel-privat.de>
---
 Documentation/devicetree/bindings/vendor-prefixes.txt | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index ac7269f..23c862f 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -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.
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH v5 06/10] ARM: clocksource: add asm9260_timer driver
  2014-10-14  8:03 ` [PATCH v5 06/10] ARM: clocksource: add asm9260_timer driver Oleksij Rempel
@ 2014-10-15 21:31   ` Matthias Brugger
  2014-10-16 10:46     ` Oleksij Rempel
  2014-10-17  9:46     ` [PATCH v6] " Oleksij Rempel
  0 siblings, 2 replies; 16+ messages in thread
From: Matthias Brugger @ 2014-10-15 21:31 UTC (permalink / raw)
  To: linux-arm-kernel



On 14/10/14 10:03, Oleksij Rempel wrote:
> In some cases asm9260 looks similar to iMX2x. One of exceptions is
> timer controller. So this patch introduces new driver for this special case.
> 
> Signed-off-by: Oleksij Rempel <linux@rempel-privat.de>
> ---
>  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
> 
> diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
> index cfd6519..6a03d34 100644
> --- a/drivers/clocksource/Kconfig
> +++ b/drivers/clocksource/Kconfig
> @@ -216,4 +216,8 @@ config CLKSRC_VERSATILE
>  	  ARM Versatile, RealView and Versatile Express reference
>  	  platforms.
>  
> +config ASM9260_TIMER
> +	select CLKSRC_MMIO
> +	bool
> +
>  endmenu
> diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
> index 7fd9fd1..fc93854 100644
> --- a/drivers/clocksource/Makefile
> +++ b/drivers/clocksource/Makefile
> @@ -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
> diff --git a/drivers/clocksource/asm9260_timer.c b/drivers/clocksource/asm9260_timer.c
> new file mode 100644
> index 0000000..1b16e00
> --- /dev/null
> +++ b/drivers/clocksource/asm9260_timer.c
> @@ -0,0 +1,234 @@
> +/*
> + * Copyright (C) 2014 Oleksij Rempel <linux@rempel-privat.de>
> + *
> + * 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 */
> +#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.

> +
> +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.

> +
> +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);
> +
> +	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?

> +
> +	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;
> +	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?

> +
> +	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.

> +
> +	/* 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.

> +	/* 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);
> 

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCH v5 06/10] ARM: clocksource: add asm9260_timer driver
  2014-10-15 21:31   ` Matthias Brugger
@ 2014-10-16 10:46     ` Oleksij Rempel
  2014-10-16 14:49       ` Matthias Brugger
  2014-10-17  9:46     ` [PATCH v6] " Oleksij Rempel
  1 sibling, 1 reply; 16+ messages in thread
From: Oleksij Rempel @ 2014-10-16 10:46 UTC (permalink / raw)
  To: linux-arm-kernel

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:
> 
> 
> On 14/10/14 10:03, Oleksij Rempel wrote:
>> In some cases asm9260 looks similar to iMX2x. One of exceptions is
>> timer controller. So this patch introduces new driver for this special case.
>>
>> Signed-off-by: Oleksij Rempel <linux@rempel-privat.de>
>> ---
>>  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
>>
>> diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
>> index cfd6519..6a03d34 100644
>> --- a/drivers/clocksource/Kconfig
>> +++ b/drivers/clocksource/Kconfig
>> @@ -216,4 +216,8 @@ config CLKSRC_VERSATILE
>>  	  ARM Versatile, RealView and Versatile Express reference
>>  	  platforms.
>>  
>> +config ASM9260_TIMER
>> +	select CLKSRC_MMIO
>> +	bool
>> +
>>  endmenu
>> diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
>> index 7fd9fd1..fc93854 100644
>> --- a/drivers/clocksource/Makefile
>> +++ b/drivers/clocksource/Makefile
>> @@ -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
>> diff --git a/drivers/clocksource/asm9260_timer.c b/drivers/clocksource/asm9260_timer.c
>> new file mode 100644
>> index 0000000..1b16e00
>> --- /dev/null
>> +++ b/drivers/clocksource/asm9260_timer.c
>> @@ -0,0 +1,234 @@
>> +/*
>> + * Copyright (C) 2014 Oleksij Rempel <linux@rempel-privat.de>
>> + *
>> + * 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 */
>> +#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.
> 
>> +
>> +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.
> 
>> +
>> +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);
>> +
>> +	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?
> 
>> +
>> +	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;
>> +	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?
> 
>> +
>> +	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.
> 
>> +
>> +	/* 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.
> 
>> +	/* 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

-------------- 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>

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCH v5 06/10] ARM: clocksource: add asm9260_timer driver
  2014-10-16 10:46     ` Oleksij Rempel
@ 2014-10-16 14:49       ` Matthias Brugger
  0 siblings, 0 replies; 16+ messages in thread
From: Matthias Brugger @ 2014-10-16 14:49 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Oleksij,

2014-10-16 12:46 GMT+02:00 Oleksij Rempel <linux@rempel-privat.de>:
> 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

>
> 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:
>>
>>
>> On 14/10/14 10:03, Oleksij Rempel wrote:
>>> In some cases asm9260 looks similar to iMX2x. One of exceptions is
>>> timer controller. So this patch introduces new driver for this special case.
>>>
>>> Signed-off-by: Oleksij Rempel <linux@rempel-privat.de>
>>> ---
>>>  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
>>>
>>> diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
>>> index cfd6519..6a03d34 100644
>>> --- a/drivers/clocksource/Kconfig
>>> +++ b/drivers/clocksource/Kconfig
>>> @@ -216,4 +216,8 @@ config CLKSRC_VERSATILE
>>>        ARM Versatile, RealView and Versatile Express reference
>>>        platforms.
>>>
>>> +config ASM9260_TIMER
>>> +    select CLKSRC_MMIO
>>> +    bool
>>> +
>>>  endmenu
>>> diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
>>> index 7fd9fd1..fc93854 100644
>>> --- a/drivers/clocksource/Makefile
>>> +++ b/drivers/clocksource/Makefile
>>> @@ -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
>>> diff --git a/drivers/clocksource/asm9260_timer.c b/drivers/clocksource/asm9260_timer.c
>>> new file mode 100644
>>> index 0000000..1b16e00
>>> --- /dev/null
>>> +++ b/drivers/clocksource/asm9260_timer.c
>>> @@ -0,0 +1,234 @@
>>> +/*
>>> + * Copyright (C) 2014 Oleksij Rempel <linux@rempel-privat.de>
>>> + *
>>> + * 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 */
>>> +#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.
>>
>>> +
>>> +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.
>>
>>> +
>>> +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);
>>> +
>>> +    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?
>>
>>> +
>>> +    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;
>>> +    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?
>>
>>> +
>>> +    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.
>>
>>> +
>>> +    /* 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.
>>
>>> +    /* 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
>



-- 
motzblog.wordpress.com

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCH v6] ARM: clocksource: add asm9260_timer driver
  2014-10-15 21:31   ` Matthias Brugger
  2014-10-16 10:46     ` Oleksij Rempel
@ 2014-10-17  9:46     ` Oleksij Rempel
  2014-10-19 20:13       ` Arnd Bergmann
  1 sibling, 1 reply; 16+ messages in thread
From: Oleksij Rempel @ 2014-10-17  9:46 UTC (permalink / raw)
  To: linux-arm-kernel

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

Signed-off-by: Oleksij Rempel <linux@rempel-privat.de>
---
 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

diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index cfd6519..6a03d34 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -216,4 +216,8 @@ config CLKSRC_VERSATILE
 	  ARM Versatile, RealView and Versatile Express reference
 	  platforms.
 
+config ASM9260_TIMER
+	select CLKSRC_MMIO
+	bool
+
 endmenu
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index 7fd9fd1..fc93854 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -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
diff --git a/drivers/clocksource/asm9260_timer.c b/drivers/clocksource/asm9260_timer.c
new file mode 100644
index 0000000..fc8b885
--- /dev/null
+++ b/drivers/clocksource/asm9260_timer.c
@@ -0,0 +1,220 @@
+/*
+ * Copyright (C) 2014 Oleksij Rempel <linux@rempel-privat.de>
+ *
+ * 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>
+
+#define DRIVER_NAME	"asm9260-timer"
+
+/*
+ * 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_DIR_COUNT_UP		0
+#define BM_DIR_COUNT_DOWN	1
+#define BM_DIR0_SHIFT	0
+#define BM_DIR1_SHIFT	4
+#define BM_DIR2_SHIFT	8
+#define BM_DIR3_SHIFT	12
+#define BM_DIR_DEFAULT		(BM_DIR_COUNT_UP << BM_DIR0_SHIFT | \
+				 BM_DIR_COUNT_UP << BM_DIR1_SHIFT | \
+				 BM_DIR_COUNT_UP << BM_DIR2_SHIFT | \
+				 BM_DIR_COUNT_UP << BM_DIR3_SHIFT)
+
+#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 BM_PR_DISABLE	0
+#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_CTCR		0x0180 /* Counter control */
+#define BM_CTCR0_SHIFT	0
+#define BM_CTCR1_SHIFT	2
+#define BM_CTCR2_SHIFT	4
+#define BM_CTCR3_SHIFT	6
+#define BM_CTCR_TM	0	/* Timer mode. Every rising PCLK edge. */
+#define BM_CTCR_DEFAULT	(BM_CTCR_TM << BM_CTCR0_SHIFT | \
+			 BM_CTCR_TM << BM_CTCR1_SHIFT | \
+			 BM_CTCR_TM << BM_CTCR2_SHIFT | \
+			 BM_CTCR_TM << BM_CTCR3_SHIFT)
+
+static struct asm9260_timer_priv {
+	void __iomem *base;
+	unsigned long ticks_per_jiffy;
+} priv;
+
+static int asm9260_timer_set_next_event(unsigned long delta,
+					 struct clock_event_device *evt)
+{
+	/* configure match count for TC0 */
+	writel_relaxed(delta, priv.base + HW_MR0);
+	/* enable TC0 */
+	writel_relaxed(BM_C0_EN, priv.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, priv.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),
+				priv.base + HW_MCR + CLR_REG);
+		/* configure match count for TC0 */
+		writel_relaxed(priv.ticks_per_jiffy, priv.base + HW_MR0);
+		/* enable TC0 */
+		writel_relaxed(BM_C0_EN, priv.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),
+				priv.base + HW_MCR + SET_REG);
+		break;
+	default:
+		break;
+	}
+}
+
+static struct clock_event_device event_dev = {
+	.name		= DRIVER_NAME,
+	.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 = dev_id;
+
+	evt->event_handler(evt);
+
+	writel_relaxed(BM_IR_MR0, priv.base + HW_IR);
+
+	return IRQ_HANDLED;
+}
+
+/*
+ * ---------------------------------------------------------------------------
+ * Timer initialization
+ * ---------------------------------------------------------------------------
+ */
+static void __init asm9260_timer_init(struct device_node *np)
+{
+	int irq;
+	struct clk *clk;
+	int ret;
+	unsigned long rate;
+
+	priv.base = of_io_request_and_map(np, 0, DRIVER_NAME);
+	if (!priv.base)
+		panic("%s: unable to map resource", DRIVER_NAME);
+
+	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);
+	ret = request_irq(irq, asm9260_timer_interrupt, IRQF_TIMER,
+			DRIVER_NAME, &event_dev);
+	if (ret)
+		panic("Failed to setup irq!\n");
+
+	/* set all timers for count-up */
+	writel_relaxed(BM_DIR_DEFAULT, priv.base + HW_DIR);
+	/* disable divider */
+	writel_relaxed(BM_PR_DISABLE, priv.base + HW_PR);
+	/* make sure all timers use every rising PCLK edge. */
+	writel_relaxed(BM_CTCR_DEFAULT, priv.base + HW_CTCR);
+	/* enable interrupt for TC0 and clean setting for all other lines */
+	writel_relaxed(BM_MCR_INT_EN(0) , priv.base + HW_MCR);
+
+	rate = clk_get_rate(clk);
+	clocksource_mmio_init(priv.base + HW_TC1, DRIVER_NAME, rate,
+			200, 32, clocksource_mmio_readl_up);
+
+	/* Seems like we can't use counter without match register even if
+	 * actions for MR are disabled. So, set MR to max value. */
+	writel_relaxed(0xffffffff, priv.base + HW_MR1);
+	/* enable TC1 */
+	writel_relaxed(BM_C1_EN, priv.base + HW_TCR + SET_REG);
+
+	priv.ticks_per_jiffy = DIV_ROUND_CLOSEST(rate, HZ);
+	event_dev.cpumask = cpumask_of(0);
+	clockevents_config_and_register(&event_dev, rate, 0x2c00, 0xfffffffe);
+}
+CLOCKSOURCE_OF_DECLARE(asm9260_timer, "alphascale," DRIVER_NAME,
+		asm9260_timer_init);
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH v6] ARM: clocksource: add asm9260_timer driver
  2014-10-17  9:46     ` [PATCH v6] " Oleksij Rempel
@ 2014-10-19 20:13       ` Arnd Bergmann
  0 siblings, 0 replies; 16+ messages in thread
From: Arnd Bergmann @ 2014-10-19 20:13 UTC (permalink / raw)
  To: linux-arm-kernel

On Friday 17 October 2014 11:46:05 Oleksij Rempel wrote:
> +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 <daniel.lezcano@linaro.org> on Cc
for the submission.

	Arnd

^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2014-10-19 20:13 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-10-14  8:03 [PATCH v5 00/10] initial suport for Alphascale ASM9260 Oleksij Rempel
2014-10-14  8:03 ` [PATCH v5 01/10] ARM: add mach-asm9260 Oleksij Rempel
2014-10-14  8:03 ` [PATCH v5 02/10] ARM: add lolevel debug support for asm9260 Oleksij Rempel
2014-10-14  8:03 ` [PATCH v5 03/10] ARM: clk: add clk-asm9260 driver Oleksij Rempel
2014-10-14  8:03 ` [PATCH v5 04/10] ARM: irqchip: mxs: prepare driver for HW with different offsets Oleksij Rempel
2014-10-14  8:03 ` [PATCH v5 05/10] ARM: irqchip: mxs: add Alpascale ASM9260 support Oleksij Rempel
2014-10-14  8:03 ` [PATCH v5 06/10] ARM: clocksource: add asm9260_timer driver Oleksij Rempel
2014-10-15 21:31   ` Matthias Brugger
2014-10-16 10:46     ` Oleksij Rempel
2014-10-16 14:49       ` Matthias Brugger
2014-10-17  9:46     ` [PATCH v6] " Oleksij Rempel
2014-10-19 20:13       ` Arnd Bergmann
2014-10-14  8:03 ` [PATCH v5 07/10] ARM: tty: mxs-auart: add initial Alphascale ASM9260 support Oleksij Rempel
2014-10-14  8:03 ` [PATCH v5 08/10] ARM: dts: add DT for Alphascale ASM9260 SoC Oleksij Rempel
2014-10-14  8:03 ` [PATCH v5 09/10] ARM: add alphascale,acc.txt bindings documentation Oleksij Rempel
2014-10-14  8:03 ` [PATCH v5 10/10] add Alphascale to vendor-prefixes.txt Oleksij Rempel

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).