linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/7] initial suport for Alpscale ASM9260
@ 2014-09-13 22:13 Oleksij Rempel
  2014-09-13 22:13 ` [PATCH 1/7] ARM: add mach-asm9260 Oleksij Rempel
                   ` (6 more replies)
  0 siblings, 7 replies; 23+ messages in thread
From: Oleksij Rempel @ 2014-09-13 22:13 UTC (permalink / raw)
  To: linux-arm-kernel

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

Oleksij Rempel (7):
  ARM: add mach-asm9260
  add include/debug/asm9260.S
  ARM: dts: add DT for Alpscale ASM9260 SoC
  clk: add clk-asm9260 driver
  clocksource: add asm9260_timer driver
  irqchip: add irq-asm9260 driver
  tty/serial: add asm9260-serial driver

 arch/arm/Kconfig                     |   16 +
 arch/arm/Kconfig.debug               |   33 +-
 arch/arm/Makefile                    |    1 +
 arch/arm/boot/dts/Makefile           |    2 +
 arch/arm/boot/dts/asm9260-devkit.dts |   15 +
 arch/arm/boot/dts/asm9260.dtsi       |  425 ++++++++++++
 arch/arm/include/debug/asm9260.S     |   31 +
 arch/arm/mach-asm9260/Kconfig        |   66 ++
 arch/arm/mach-asm9260/Makefile       |   11 +
 arch/arm/mach-asm9260/Makefile.boot  |    2 +
 arch/arm/mach-asm9260/core.c         |   77 +++
 drivers/clk/Makefile                 |    1 +
 drivers/clk/clk-asm9260.c            |  159 +++++
 drivers/clocksource/Makefile         |    1 +
 drivers/clocksource/asm9260_timer.c  |  232 +++++++
 drivers/irqchip/Makefile             |    1 +
 drivers/irqchip/irq-asm9260.c        |  237 +++++++
 drivers/tty/serial/Kconfig           |   19 +
 drivers/tty/serial/Makefile          |    1 +
 drivers/tty/serial/asm9260_serial.c  | 1236 ++++++++++++++++++++++++++++++++++
 include/uapi/linux/serial_core.h     |    2 +
 21 files changed, 2565 insertions(+), 3 deletions(-)
 create mode 100644 arch/arm/boot/dts/asm9260-devkit.dts
 create mode 100644 arch/arm/boot/dts/asm9260.dtsi
 create mode 100644 arch/arm/include/debug/asm9260.S
 create mode 100644 arch/arm/mach-asm9260/Kconfig
 create mode 100644 arch/arm/mach-asm9260/Makefile
 create mode 100644 arch/arm/mach-asm9260/Makefile.boot
 create mode 100644 arch/arm/mach-asm9260/core.c
 create mode 100644 drivers/clk/clk-asm9260.c
 create mode 100644 drivers/clocksource/asm9260_timer.c
 create mode 100644 drivers/irqchip/irq-asm9260.c
 create mode 100644 drivers/tty/serial/asm9260_serial.c

-- 
1.9.1

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

* [PATCH 1/7] ARM: add mach-asm9260
  2014-09-13 22:13 [PATCH 0/7] initial suport for Alpscale ASM9260 Oleksij Rempel
@ 2014-09-13 22:13 ` Oleksij Rempel
  2014-09-14  7:12   ` Jason Cooper
  2014-09-13 22:13 ` [PATCH 2/7] add include/debug/asm9260.S Oleksij Rempel
                   ` (5 subsequent siblings)
  6 siblings, 1 reply; 23+ messages in thread
From: Oleksij Rempel @ 2014-09-13 22:13 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Oleksij Rempel <linux@rempel-privat.de>
---
 arch/arm/Kconfig                    | 16 ++++++++
 arch/arm/Makefile                   |  1 +
 arch/arm/mach-asm9260/Kconfig       | 66 +++++++++++++++++++++++++++++++
 arch/arm/mach-asm9260/Makefile      | 11 ++++++
 arch/arm/mach-asm9260/Makefile.boot |  2 +
 arch/arm/mach-asm9260/core.c        | 77 +++++++++++++++++++++++++++++++++++++
 6 files changed, 173 insertions(+)
 create mode 100644 arch/arm/mach-asm9260/Kconfig
 create mode 100644 arch/arm/mach-asm9260/Makefile
 create mode 100644 arch/arm/mach-asm9260/Makefile.boot
 create mode 100644 arch/arm/mach-asm9260/core.c

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 245058b..fb56189 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -373,6 +373,20 @@ config ARCH_AT91
 	  This enables support for systems based on Atmel
 	  AT91RM9200 and AT91SAM9* processors.
 
+config MACH_ASM9260
+	bool "Alpscale ASM9260"
+	select ARCH_REQUIRE_GPIOLIB
+	select COMMON_CLK
+	select IRQ_DOMAIN
+	select SPARSE_IRQ
+	select MULTI_IRQ_HANDLER
+	select GENERIC_IRQ_CHIP
+	select GENERIC_CLOCKEVENTS
+	select CLKSRC_MMIO
+	select CPU_ARM926T
+	help
+	  Support for Alpscale ASM9260 based platform.
+
 config ARCH_CLPS711X
 	bool "Cirrus Logic CLPS711x/EP721x/EP731x-based"
 	select ARCH_REQUIRE_GPIOLIB
@@ -915,6 +929,8 @@ source "arch/arm/mach-mvebu/Kconfig"
 
 source "arch/arm/mach-at91/Kconfig"
 
+source "arch/arm/mach-asm9260/Kconfig"
+
 source "arch/arm/mach-axxia/Kconfig"
 
 source "arch/arm/mach-bcm/Kconfig"
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 6721fab..c383d02 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -143,6 +143,7 @@ textofs-$(CONFIG_ARCH_AXXIA) := 0x00308000
 # Machine directory name.  This list is sorted alphanumerically
 # by CONFIG_* macro name.
 machine-$(CONFIG_ARCH_AT91)		+= at91
+machine-$(CONFIG_MACH_ASM9260)		+= asm9260
 machine-$(CONFIG_ARCH_AXXIA)		+= axxia
 machine-$(CONFIG_ARCH_BCM)		+= bcm
 machine-$(CONFIG_ARCH_BERLIN)		+= berlin
diff --git a/arch/arm/mach-asm9260/Kconfig b/arch/arm/mach-asm9260/Kconfig
new file mode 100644
index 0000000..f7240d8
--- /dev/null
+++ b/arch/arm/mach-asm9260/Kconfig
@@ -0,0 +1,66 @@
+if MACH_ASM9260
+
+menu "ASM9260T EVK Uart Enable"
+
+config ENABLE_UART0
+	bool "Enable UART0"
+	depends on SERIAL_ASM9260
+	default n
+
+config ENABLE_UART1
+	bool "Enable UART1"
+	depends on SERIAL_ASM9260
+	default n
+
+config ENABLE_UART2
+	bool "Enable UART2"
+	depends on SERIAL_ASM9260
+	default n
+
+
+config ENABLE_UART3
+	bool "Enable UART3"
+	depends on SERIAL_ASM9260
+	default n
+
+
+config ENABLE_UART4
+	bool "Enable UART4"
+	depends on SERIAL_ASM9260
+	default n
+
+
+config ENABLE_UART5
+	bool "Enable UART5"
+	depends on SERIAL_ASM9260
+	default n
+
+
+config ENABLE_UART6
+	bool "Enable UART6"
+	depends on SERIAL_ASM9260
+	default n
+
+
+config ENABLE_UART7
+	bool "Enable UART7"
+	depends on SERIAL_ASM9260
+	default n
+
+
+config ENABLE_UART8
+	bool "Enable UART8"
+	depends on SERIAL_ASM9260
+	default n
+
+
+config ENABLE_UART9
+	bool "Enable UART9"
+	depends on SERIAL_ASM9260
+	default n
+
+endmenu
+
+
+endif
+
diff --git a/arch/arm/mach-asm9260/Makefile b/arch/arm/mach-asm9260/Makefile
new file mode 100644
index 0000000..4bd8ebd
--- /dev/null
+++ b/arch/arm/mach-asm9260/Makefile
@@ -0,0 +1,11 @@
+#
+# Makefile for the linux kernel.
+#
+
+# Object file lists.
+
+obj-y			:= core.o
+obj-m			:=
+obj-n			:=
+obj-			:=
+
diff --git a/arch/arm/mach-asm9260/Makefile.boot b/arch/arm/mach-asm9260/Makefile.boot
new file mode 100644
index 0000000..c57b3b4
--- /dev/null
+++ b/arch/arm/mach-asm9260/Makefile.boot
@@ -0,0 +1,2 @@
+zreladdr-y	:= 0x20008000
+
diff --git a/arch/arm/mach-asm9260/core.c b/arch/arm/mach-asm9260/core.c
new file mode 100644
index 0000000..eee7a9d
--- /dev/null
+++ b/arch/arm/mach-asm9260/core.c
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2014 Oleksij Rempel <linux@rempel-privat.de>
+ *  Co-author: Du Huanpeng <u74147@gmail.com>
+ * map_desc based on:
+ *  linux/arch/arm/mach-asm9260/core.c
+ *  Copyright (C) 2011-2014 Alpscale
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/of_platform.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+static struct map_desc asm9260_io_desc[] __initdata = {
+	{	/* IO space */
+		.virtual	= (unsigned long)0xf0000000,
+		.pfn		= __phys_to_pfn(0x80000000),
+		.length		= 0x00800000,
+		.type		= MT_DEVICE
+	},
+	{	/* LCD IO space	*/
+		.virtual	= (unsigned long)0xf0a00000,
+		.pfn		= __phys_to_pfn(0x80800000),
+		.length		= 0x00009000,
+		.type		= MT_DEVICE
+	},
+	{	/* GPIO IO space */
+		.virtual	= (unsigned long)0xf0800000,
+		.pfn		= __phys_to_pfn(0x50000000),
+		.length		= 0x00100000,
+		.type		= MT_DEVICE
+	},
+	{	/* SRAM space Cacheable */
+		.virtual	= (unsigned long)0xd0000000,
+		.pfn		= __phys_to_pfn(0x40000000),
+		.length		= 0x00100000,
+#ifdef CONFIG_SRAM_MEM_CACHED
+		.type		= MT_MEMORY
+#else
+		.type		= MT_DEVICE
+#endif
+	},
+};
+
+static void __init asm9260_map_io(void)
+{
+	iotable_init(asm9260_io_desc, ARRAY_SIZE(asm9260_io_desc));
+}
+
+static void __init asm9260_init(void)
+{
+	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+}
+
+static const char * const asm9260_dt_board_compat[] __initconst = {
+	"alpscale,asm9260",
+	NULL
+};
+
+DT_MACHINE_START(ASM9260, "Alpscale ASM9260 (Device Tree Support)")
+	.map_io		= asm9260_map_io,
+	.init_machine	= asm9260_init,
+	.dt_compat	= asm9260_dt_board_compat,
+MACHINE_END
-- 
1.9.1

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

* [PATCH 2/7] add include/debug/asm9260.S
  2014-09-13 22:13 [PATCH 0/7] initial suport for Alpscale ASM9260 Oleksij Rempel
  2014-09-13 22:13 ` [PATCH 1/7] ARM: add mach-asm9260 Oleksij Rempel
@ 2014-09-13 22:13 ` Oleksij Rempel
  2014-09-13 22:13 ` [PATCH 3/7] ARM: dts: add DT for Alpscale ASM9260 SoC Oleksij Rempel
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 23+ messages in thread
From: Oleksij Rempel @ 2014-09-13 22:13 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 8f90595..d5e420c 100644
--- a/arch/arm/Kconfig.debug
+++ b/arch/arm/Kconfig.debug
@@ -937,6 +937,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
@@ -1017,6 +1038,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
@@ -1072,6 +1094,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
@@ -1103,7 +1126,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"
@@ -1111,6 +1135,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
@@ -1170,7 +1195,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"
@@ -1212,7 +1238,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] 23+ messages in thread

* [PATCH 3/7] ARM: dts: add DT for Alpscale ASM9260 SoC
  2014-09-13 22:13 [PATCH 0/7] initial suport for Alpscale ASM9260 Oleksij Rempel
  2014-09-13 22:13 ` [PATCH 1/7] ARM: add mach-asm9260 Oleksij Rempel
  2014-09-13 22:13 ` [PATCH 2/7] add include/debug/asm9260.S Oleksij Rempel
@ 2014-09-13 22:13 ` Oleksij Rempel
  2014-09-13 22:13 ` [PATCH 4/7] clk: add clk-asm9260 driver Oleksij Rempel
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 23+ messages in thread
From: Oleksij Rempel @ 2014-09-13 22:13 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Oleksij Rempel <linux@rempel-privat.de>
---
 arch/arm/boot/dts/Makefile           |   2 +
 arch/arm/boot/dts/asm9260-devkit.dts |  15 ++
 arch/arm/boot/dts/asm9260.dtsi       | 425 +++++++++++++++++++++++++++++++++++
 3 files changed, 442 insertions(+)
 create mode 100644 arch/arm/boot/dts/asm9260-devkit.dts
 create mode 100644 arch/arm/boot/dts/asm9260.dtsi

diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index adb5ed9..ff75287 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -446,6 +446,8 @@ dtb-$(CONFIG_MACH_DOVE) += dove-cm-a510.dtb \
 	dove-d3plug.dtb \
 	dove-dove-db.dtb
 
+dtb-$(CONFIG_MACH_ASM9260) += asm9260-devkit.dtb
+
 targets += dtbs dtbs_install
 targets += $(dtb-y)
 endif
diff --git a/arch/arm/boot/dts/asm9260-devkit.dts b/arch/arm/boot/dts/asm9260-devkit.dts
new file mode 100644
index 0000000..2cbc391
--- /dev/null
+++ b/arch/arm/boot/dts/asm9260-devkit.dts
@@ -0,0 +1,15 @@
+/dts-v1/;
+#include "asm9260.dtsi"
+
+/ {
+	model = "Alpscale asm9260 Development Kit";
+	compatible = "alpscale,asm9260devkit", "alpscale,asm9260";
+
+	chosen {
+		bootargs = "mem=32M earlyprintk=serial console=ttyS4,115200n8 root=/dev/mtdblock1 init=/linuxrc mtdparts=NAND:4M at 10M(logo)ro,60M at 14M(root)ro";
+	};
+
+};
+&uart4 {
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/asm9260.dtsi b/arch/arm/boot/dts/asm9260.dtsi
new file mode 100644
index 0000000..52bb8de
--- /dev/null
+++ b/arch/arm/boot/dts/asm9260.dtsi
@@ -0,0 +1,425 @@
+/*
+ * Copyright 2014 Oleksij Rempel <linux@rempel-privat.de>
+ *
+ * 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 "skeleton.dtsi"
+
+/ {
+	interrupt-parent = <&icoll>;
+
+        aliases {
+		serial0 = &uart0;
+		serial1 = &uart1;
+		serial2 = &uart2;
+		serial3 = &uart3;
+		serial4 = &uart4;
+		serial5 = &uart5;
+		serial6 = &uart6;
+		serial7 = &uart7;
+		serial8 = &uart8;
+		serial9 = &uart9;
+        };
+
+	cpus {
+		#address-cells = <0>;
+		#size-cells = <0>;
+
+		cpu {
+			compatible = "arm,arm926ej-s";
+			device_type = "cpu";
+			clocks = <&cpu_div>;
+		};
+	};
+
+	soc {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "simple-bus";
+                ranges;
+
+		icoll: interrupt-controller at 80054000 {
+			compatible = "alpscale,asm9260-icall";
+			interrupt-controller;
+			#interrupt-cells = <1>;
+			reg = <0x80054000 0x200>;
+		};
+
+		uart0: serial at 80000000 {
+			compatible = "alpscale,asm9260-uart";
+			reg = <0x80000000 0x4000>;
+			clocks = <&uart0_div>, <&ahb_uart0_gate>;
+			interrupts = <15>;
+			status = "disabled";
+		};
+		uart1: serial at 80004000 {
+			compatible = "alpscale,asm9260-uart";
+			reg = <0x80004000 0x4000>;
+			clocks = <&uart1_div>, <&ahb_uart1_gate>;
+			interrupts = <16>;
+			status = "disabled";
+		};
+		uart2: serial at 80008000 {
+			compatible = "alpscale,asm9260-uart";
+			reg = <0x80008000 0x4000>;
+			clocks = <&uart2_div>, <&ahb_uart2_gate>;
+			interrupts = <17>;
+			status = "disabled";
+		};
+		uart3: serial at 8000c000 {
+			compatible = "alpscale,asm9260-uart";
+			reg = <0x8000c000 0x4000>;
+			clocks = <&uart3_div>, <&ahb_uart3_gate>;
+			interrupts = <18>;
+			status = "disabled";
+		};
+		uart4: serial at 80010000 {
+			compatible = "alpscale,asm9260-uart";
+			reg = <0x80010000 0x4000>;
+			clocks = <&uart4_div>, <&ahb_uart4_gate>;
+			interrupts = <19>;
+			status = "disabled";
+		};
+		uart5: serial at 80014000 {
+			compatible = "alpscale,asm9260-uart";
+			reg = <0x80014000 0x4000>;
+			clocks = <&uart5_div>, <&ahb_uart5_gate>;
+			interrupts = <20>;
+			status = "disabled";
+		};
+		uart6: serial at 80018000 {
+			compatible = "alpscale,asm9260-uart";
+			reg = <0x80018000 0x4000>;
+			clocks = <&uart6_div>, <&ahb_uart6_gate>;
+			interrupts = <21>;
+			status = "disabled";
+		};
+		uart7: serial at 8001c000 {
+			compatible = "alpscale,asm9260-uart";
+			reg = <0x8001c000 0x4000>;
+			clocks = <&uart7_div>, <&ahb_uart7_gate>;
+			interrupts = <22>;
+			status = "disabled";
+		};
+		uart8: serial at 80020000 {
+			compatible = "alpscale,asm9260-uart";
+			reg = <0x80020000 0x4000>;
+			clocks = <&uart8_div>, <&ahb_uart8_gate>;
+			interrupts = <23>;
+			status = "disabled";
+		};
+		uart9: serial at 80024000 {
+			compatible = "alpscale,asm9260-uart";
+			reg = <0x80024000 0x4000>;
+			clocks = <&uart9_div>, <&ahb_uart9_gate>;
+			interrupts = <24>;
+			status = "disabled";
+		};
+
+		/* timers, should be moved after sregs */
+		timer0: timer at 80088000 {
+			compatible = "alpscale,asm9260-timer";
+			reg = <0x80088000 0x4000>;
+			clocks = <&ahb_timer0_gate>;
+			interrupts = <29>;
+			/* status = "disabled"; */
+		};
+
+		sregs at 80040000 {
+			compatible = "alpscale,asm9260-sregs";
+			reg = <0x80040000 0x504>;
+
+			clocks {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				osc24m: oscillator {
+					compatible = "fixed-clock";
+					#clock-cells = <0>;
+					clock-frequency = <24000000>;
+					clock-accuracy = <30000>;
+				};
+
+				pll: pll at 0100 {
+					compatible = "alpscale,asm9260-pll-clock";
+					#clock-cells = <0>;
+					clocks = <&osc24m>;
+					reg = <0x0100>;
+				};
+
+				main_mux: main_mux at 0120 {
+					compatible = "alpscale,asm9260-bimux-clock";
+					#clock-cells = <0>;
+					clocks = <&osc24m>, <&pll>;
+					mux-table = <0 1>;
+					reg = <0x0120>;
+				};
+
+				main_gate: main_gate at 0124 {
+					compatible = "alpscale,asm9260-gate-clock";
+					#clock-cells = <0>;
+					clocks = <&main_mux>;
+					reg = <0x0124>;
+					bit-index = <0>;
+				};
+
+				cpu_div: cpu_div at 017c {
+					compatible = "alpscale,asm9260-div-clock";
+					#clock-cells = <0>;
+					clocks = <&main_gate>;
+					reg = <0x017c>;
+				};
+
+				ahb_div: ahb_div at 0180 {
+					compatible = "alpscale,asm9260-div-clock";
+					#clock-cells = <0>;
+					clocks = <&cpu_div>;
+					reg = <0x0180>;
+				};
+
+				/* ahb devices start */
+
+/*
+				ahb_rom_gate: ahb_rom_gate at 0020 {
+					compatible = "alpscale,asm9260-gate-clock";
+					#clock-cells = <0>;
+					clocks = <&ahb_div>;
+					reg = <0x0020>;
+					bit-index = <1>;
+				};
+				ahb_ram_gate: ahb_ram_gate at 0020 {
+					compatible = "alpscale,asm9260-gate-clock";
+					#clock-cells = <0>;
+					clocks = <&ahb_div>;
+					reg = <0x0020>;
+					bit-index = <2>;
+				};
+				ahb_gpio_gate: ahb_gpio_gate at 0020 {
+					compatible = "alpscale,asm9260-gate-clock";
+					#clock-cells = <0>;
+					clocks = <&ahb_div>;
+					reg = <0x0020>;
+					bit-index = <4>;
+				};
+				ahb_mac_gate: ahb_mac_gate at 0020 {
+					compatible = "alpscale,asm9260-gate-clock";
+					#clock-cells = <0>;
+					clocks = <&ahb_div>;
+					reg = <0x0020>;
+					bit-index = <5>;
+				};
+				ahb_emi_gate: ahb_emi_gate at 0020 {
+					compatible = "alpscale,asm9260-gate-clock";
+					#clock-cells = <0>;
+					clocks = <&ahb_div>;
+					reg = <0x0020>;
+					bit-index = <6>;
+				};
+
+*/
+				ahb_usb0_gate: ahb_usb0_gate at 0020 {
+					compatible = "alpscale,asm9260-gate-clock";
+					#clock-cells = <0>;
+					clocks = <&ahb_div>;
+					reg = <0x0020>;
+					bit-index = <7>;
+				};
+				ahb_usb1_gate: ahb_usb1_gate at 0020 {
+					compatible = "alpscale,asm9260-gate-clock";
+					#clock-cells = <0>;
+					clocks = <&ahb_div>;
+					reg = <0x0020>;
+					bit-index = <8>;
+				};
+
+/*
+				ahb_dma0_gate: ahb_dma0_gate at 0020 {
+					compatible = "alpscale,asm9260-gate-clock";
+					#clock-cells = <0>;
+					clocks = <&ahb_div>;
+					reg = <0x0020>;
+					bit-index = <9>;
+				};
+				ahb_dma1_gate: ahb_dma1_gate at 0020 {
+					compatible = "alpscale,asm9260-gate-clock";
+					#clock-cells = <0>;
+					clocks = <&ahb_div>;
+					reg = <0x0020>;
+					bit-index = <10>;
+				};
+
+*/
+				ahb_uart0_gate: ahb_uart0_gate at 0020 {
+					compatible = "alpscale,asm9260-gate-clock";
+					#clock-cells = <0>;
+					clocks = <&ahb_div>;
+					reg = <0x0020>;
+					bit-index = <11>;
+				};
+				ahb_uart1_gate: ahb_uart1_gate at 0020 {
+					compatible = "alpscale,asm9260-gate-clock";
+					#clock-cells = <0>;
+					clocks = <&ahb_div>;
+					reg = <0x0020>;
+					bit-index = <12>;
+				};
+				ahb_uart2_gate: ahb_uart2_gate at 0020 {
+					compatible = "alpscale,asm9260-gate-clock";
+					#clock-cells = <0>;
+					clocks = <&ahb_div>;
+					reg = <0x0020>;
+					bit-index = <13>;
+				};
+				ahb_uart3_gate: ahb_uart3_gate at 0020 {
+					compatible = "alpscale,asm9260-gate-clock";
+					#clock-cells = <0>;
+					clocks = <&ahb_div>;
+					reg = <0x0020>;
+					bit-index = <14>;
+				};
+
+				ahb_uart4_gate: ahb_uart4_gate at 0020 {
+					compatible = "alpscale,asm9260-gate-clock";
+					#clock-cells = <0>;
+					clocks = <&ahb_div>;
+					reg = <0x0020>;
+					bit-index = <15>;
+				};
+
+				ahb_uart5_gate: ahb_uart5_gate at 0020 {
+					compatible = "alpscale,asm9260-gate-clock";
+					#clock-cells = <0>;
+					clocks = <&ahb_div>;
+					reg = <0x0020>;
+					bit-index = <16>;
+				};
+				ahb_uart6_gate: ahb_uart6_gate at 0020 {
+					compatible = "alpscale,asm9260-gate-clock";
+					#clock-cells = <0>;
+					clocks = <&ahb_div>;
+					reg = <0x0020>;
+					bit-index = <17>;
+				};
+				ahb_uart7_gate: ahb_uart7_gate at 0020 {
+					compatible = "alpscale,asm9260-gate-clock";
+					#clock-cells = <0>;
+					clocks = <&ahb_div>;
+					reg = <0x0020>;
+					bit-index = <18>;
+				};
+
+				ahb_uart8_gate: ahb_uart8_gate at 0020 {
+					compatible = "alpscale,asm9260-gate-clock";
+					#clock-cells = <0>;
+					clocks = <&ahb_div>;
+					reg = <0x0020>;
+					bit-index = <19>;
+				};
+				ahb_uart9_gate: ahb_uart9_gate at 0020 {
+					compatible = "alpscale,asm9260-gate-clock";
+					#clock-cells = <0>;
+					clocks = <&ahb_div>;
+					reg = <0x0020>;
+					bit-index = <20>;
+				};
+
+				ahb_timer0_gate: ahb_timer0_gate at 0030 {
+					compatible = "alpscale,asm9260-gate-clock";
+					#clock-cells = <0>;
+					clocks = <&ahb_div>;
+					reg = <0x0030>;
+					bit-index = <4>;
+				};
+
+
+
+				/* ahb devices end */
+
+				/* uart related clocks */
+				uart_mux: uart_mux at 0128 {
+					compatible = "alpscale,asm9260-bimux-clock";
+					#clock-cells = <0>;
+					clocks = <&osc24m>, <&pll>;
+					mux-table = <0 1>;
+					reg = <0x0128>;
+				};
+				uart_gate: uart_gate at 012c {
+					compatible = "alpscale,asm9260-gate-clock";
+					#clock-cells = <0>;
+					clocks = <&uart_mux>;
+					reg = <0x012c>;
+					bit-index = <0>;
+				};
+				uart0_div: uart0_div at 0198 {
+					compatible = "alpscale,asm9260-div-clock";
+					#clock-cells = <0>;
+					clocks = <&uart_gate>;
+					reg = <0x0198>;
+				};
+				uart1_div: uart1_div at 019c {
+					compatible = "alpscale,asm9260-div-clock";
+					#clock-cells = <0>;
+					clocks = <&uart_gate>;
+					reg = <0x019c>;
+				};
+				uart2_div: uart2_div at 01a0 {
+					compatible = "alpscale,asm9260-div-clock";
+					#clock-cells = <0>;
+					clocks = <&uart_gate>;
+					reg = <0x01a0>;
+				};
+				uart3_div: uart3_div at 01a4 {
+					compatible = "alpscale,asm9260-div-clock";
+					#clock-cells = <0>;
+					clocks = <&uart_gate>;
+					reg = <0x01a4>;
+				};
+				uart4_div: uart4_div at 01a8 {
+					compatible = "alpscale,asm9260-div-clock";
+					#clock-cells = <0>;
+					clocks = <&uart_gate>;
+					reg = <0x01a8>;
+				};
+				uart5_div: uart5_div at 01ac {
+					compatible = "alpscale,asm9260-div-clock";
+					#clock-cells = <0>;
+					clocks = <&uart_gate>;
+					reg = <0x01ac>;
+				};
+				uart6_div: uart6_div at 01b0 {
+					compatible = "alpscale,asm9260-div-clock";
+					#clock-cells = <0>;
+					clocks = <&uart_gate>;
+					reg = <0x01b0>;
+				};
+				uart7_div: uart7_div at 01b4 {
+					compatible = "alpscale,asm9260-div-clock";
+					#clock-cells = <0>;
+					clocks = <&uart_gate>;
+					reg = <0x01b4>;
+				};
+				uart8_div: uart8_div at 01b8 {
+					compatible = "alpscale,asm9260-div-clock";
+					#clock-cells = <0>;
+					clocks = <&uart_gate>;
+					reg = <0x01b8>;
+				};
+				uart9_div: uart9_div at 01bc {
+					compatible = "alpscale,asm9260-div-clock";
+					#clock-cells = <0>;
+					clocks = <&uart_gate>;
+					reg = <0x01bc>;
+				};
+				/* end of uart section */
+
+
+			};
+		};
+	};
+};
-- 
1.9.1

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

* [PATCH 4/7] clk: add clk-asm9260 driver
  2014-09-13 22:13 [PATCH 0/7] initial suport for Alpscale ASM9260 Oleksij Rempel
                   ` (2 preceding siblings ...)
  2014-09-13 22:13 ` [PATCH 3/7] ARM: dts: add DT for Alpscale ASM9260 SoC Oleksij Rempel
@ 2014-09-13 22:13 ` Oleksij Rempel
  2014-09-17 13:54   ` Alexandre Belloni
  2014-09-13 22:13 ` [PATCH 5/7] clocksource: add asm9260_timer driver Oleksij Rempel
                   ` (2 subsequent siblings)
  6 siblings, 1 reply; 23+ messages in thread
From: Oleksij Rempel @ 2014-09-13 22:13 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Oleksij Rempel <linux@rempel-privat.de>
---
 drivers/clk/Makefile      |   1 +
 drivers/clk/clk-asm9260.c | 159 ++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 160 insertions(+)
 create mode 100644 drivers/clk/clk-asm9260.c

diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 567f102..351dd48 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -38,6 +38,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..396cc09
--- /dev/null
+++ b/drivers/clk/clk-asm9260.c
@@ -0,0 +1,159 @@
+/*
+ * U300 clock implementation
+ * Copyright (C) 2007-2012 ST-Ericsson AB
+ * License terms: GNU General Public License (GPL) version 2
+ * Author: Linus Walleij <linus.walleij@stericsson.com>
+ * Author: Jonas Aaberg <jonas.aberg@stericsson.com>
+ */
+#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>
+
+static DEFINE_SPINLOCK(asm9260_clk_lock);
+
+struct asm9260_clk {
+	void __iomem    *reg;
+	char *parent_name;
+};
+
+static void __iomem *asm9260_get_sreg(struct device_node *node)
+{
+	u32 reg;
+	void __iomem *iomem;
+	struct device_node *srnp;
+	int ret;
+
+	ret = of_property_read_u32(node, "reg", &reg);
+	if (WARN_ON(ret))
+		return NULL;
+
+	srnp = of_find_compatible_node(NULL, NULL, "alpscale,asm9260-sregs");
+	iomem = of_iomap(srnp, 0);
+	iomem += reg;
+
+	return iomem;
+}
+
+/*
+ * On this chip gate used to disable or to update clock
+ * after new source was selected
+ */
+
+static void __init asm9260_gate_init(struct device_node *node)
+{
+	struct clk *clk;
+	const char *clk_name = node->name;
+	void __iomem *iomem;
+	const char *parent_name;
+	u32 bit;
+	int ret;
+
+	iomem = asm9260_get_sreg(node);
+	parent_name = of_clk_get_parent_name(node, 0);
+
+	ret = of_property_read_u32(node, "bit-index", &bit);
+	if (WARN_ON(ret))
+		return;
+
+	clk = clk_register_gate(NULL, clk_name, parent_name,
+			CLK_SET_RATE_PARENT, iomem, bit, 0,
+			&asm9260_clk_lock);
+
+	if (!IS_ERR(clk))
+		of_clk_add_provider(node, of_clk_src_simple_get, clk);
+}
+CLK_OF_DECLARE(asm9260_gate, "alpscale,asm9260-gate-clock", asm9260_gate_init);
+
+
+static void __init asm9260_div_init(struct device_node *node)
+{
+	struct clk *clk;
+	const char *clk_name = node->name;
+	void __iomem *iomem;
+	const char *parent_name;
+
+	iomem = asm9260_get_sreg(node);
+
+	parent_name = of_clk_get_parent_name(node, 0);
+	clk = clk_register_divider(NULL, clk_name, parent_name,
+			CLK_SET_RATE_PARENT, iomem, 0, 8, CLK_DIVIDER_ONE_BASED,
+			&asm9260_clk_lock);
+
+	if (!IS_ERR(clk))
+		of_clk_add_provider(node, of_clk_src_simple_get, clk);
+}
+CLK_OF_DECLARE(asm9260_div, "alpscale,asm9260-div-clock", asm9260_div_init);
+
+/*
+ * Simple one bit MUX for two sources
+ */
+static void __init asm9260_bimux_init(struct device_node *node)
+{
+	struct clk *clk;
+	const char *clk_name = node->name;
+	u8 num_parents;
+	void __iomem *iomem;
+	const char **parent_names;
+	int ret, i;
+	u32 *table;
+
+	iomem = asm9260_get_sreg(node);
+	if (!iomem)
+		return;
+
+	num_parents = of_clk_get_parent_count(node);
+	if (WARN_ON(!num_parents || num_parents > 2))
+		return;
+
+	parent_names = kzalloc(sizeof(char *) * num_parents, GFP_KERNEL);
+	if (WARN_ON(!parent_names))
+		return;
+
+	table = kzalloc(sizeof(u32) * num_parents, GFP_KERNEL);
+	if (WARN_ON(!table))
+		return;
+
+	ret = of_property_read_u32_array(node, "mux-table", table,
+			num_parents);
+	if (WARN_ON(ret))
+		return;
+
+	for (i = 0; i < num_parents; i++)
+		parent_names[i] = of_clk_get_parent_name(node, i);
+
+	clk = clk_register_mux_table(NULL, clk_name, parent_names,
+			num_parents, 0, iomem, 0, 1, 0, table,
+			&asm9260_clk_lock);
+
+	if (!IS_ERR(clk))
+		of_clk_add_provider(node, of_clk_src_simple_get, clk);
+}
+CLK_OF_DECLARE(asm9260_bimux, "alpscale,asm9260-bimux-clock", asm9260_bimux_init);
+
+static void __init asm9260_pll_init(struct device_node *node)
+{
+	struct clk *clk;
+	const char *clk_name = node->name;
+	u32 rate;
+	void __iomem *iomem;
+	const char *parent_name;
+	u32 accuracy = 0;
+
+	iomem = asm9260_get_sreg(node);
+	rate = (ioread32(iomem) & 0xffff) * 1000000;
+
+	parent_name = of_clk_get_parent_name(node, 0);
+	accuracy = clk_get_accuracy(__clk_lookup(parent_name));
+	clk = clk_register_fixed_rate_with_accuracy(NULL, clk_name, parent_name,
+			0, rate,
+			accuracy);
+
+	if (!IS_ERR(clk))
+		of_clk_add_provider(node, of_clk_src_simple_get, clk);
+}
+CLK_OF_DECLARE(asm9260_pll, "alpscale,asm9260-pll-clock", asm9260_pll_init);
-- 
1.9.1

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

* [PATCH 5/7] clocksource: add asm9260_timer driver
  2014-09-13 22:13 [PATCH 0/7] initial suport for Alpscale ASM9260 Oleksij Rempel
                   ` (3 preceding siblings ...)
  2014-09-13 22:13 ` [PATCH 4/7] clk: add clk-asm9260 driver Oleksij Rempel
@ 2014-09-13 22:13 ` Oleksij Rempel
  2014-09-13 22:13 ` [PATCH 6/7] irqchip: add irq-asm9260 driver Oleksij Rempel
  2014-09-13 22:13 ` [PATCH 7/7] tty/serial: add asm9260-serial driver Oleksij Rempel
  6 siblings, 0 replies; 23+ messages in thread
From: Oleksij Rempel @ 2014-09-13 22:13 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Oleksij Rempel <linux@rempel-privat.de>
---
 drivers/clocksource/Makefile        |   1 +
 drivers/clocksource/asm9260_timer.c | 232 ++++++++++++++++++++++++++++++++++++
 2 files changed, 233 insertions(+)
 create mode 100644 drivers/clocksource/asm9260_timer.c

diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index 800b130..521064b 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -41,3 +41,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_MACH_ASM9260)		+= asm9260_timer.o
diff --git a/drivers/clocksource/asm9260_timer.c b/drivers/clocksource/asm9260_timer.c
new file mode 100644
index 0000000..d15c9f5
--- /dev/null
+++ b/drivers/clocksource/asm9260_timer.c
@@ -0,0 +1,232 @@
+/*
+ * 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.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ */
+
+#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 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 */
+#define BM_MCR_INT_EN(n)	(1 << (n * 3 + 0)) /* enable interrupt on match */
+#define BM_MCR_RES_EN(n)	(1 << (n * 3 + 1)) /* enable TC reset on match */
+#define BM_MCR_STOP_EN(n)	(1 << (n * 3 + 2)) /* enable stop TC on match */
+
+#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, "alpscale,asm9260-timer",
+		asm9260_timer_init);
-- 
1.9.1

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

* [PATCH 6/7] irqchip: add irq-asm9260 driver
  2014-09-13 22:13 [PATCH 0/7] initial suport for Alpscale ASM9260 Oleksij Rempel
                   ` (4 preceding siblings ...)
  2014-09-13 22:13 ` [PATCH 5/7] clocksource: add asm9260_timer driver Oleksij Rempel
@ 2014-09-13 22:13 ` Oleksij Rempel
  2014-09-14  7:37   ` Jason Cooper
  2014-09-13 22:13 ` [PATCH 7/7] tty/serial: add asm9260-serial driver Oleksij Rempel
  6 siblings, 1 reply; 23+ messages in thread
From: Oleksij Rempel @ 2014-09-13 22:13 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Oleksij Rempel <linux@rempel-privat.de>
---
 drivers/irqchip/Makefile      |   1 +
 drivers/irqchip/irq-asm9260.c | 237 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 238 insertions(+)
 create mode 100644 drivers/irqchip/irq-asm9260.c

diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index 62a13e5..3400ec8 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -30,3 +30,4 @@ obj-$(CONFIG_XTENSA)			+= irq-xtensa-pic.o
 obj-$(CONFIG_XTENSA_MX)			+= irq-xtensa-mx.o
 obj-$(CONFIG_IRQ_CROSSBAR)		+= irq-crossbar.o
 obj-$(CONFIG_BRCMSTB_L2_IRQ)		+= irq-brcmstb-l2.o
+obj-$(CONFIG_MACH_ASM9260)		+= irq-asm9260.o
diff --git a/drivers/irqchip/irq-asm9260.c b/drivers/irqchip/irq-asm9260.c
new file mode 100644
index 0000000..62e0607
--- /dev/null
+++ b/drivers/irqchip/irq-asm9260.c
@@ -0,0 +1,237 @@
+/*
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <asm/exception.h>
+#include <linux/bitops.h>
+#include <linux/delay.h>
+
+#include "irqchip.h"
+
+#define SET_REG 4
+#define CLR_REG 8
+
+#define 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 HW_ICOLL_VECTOR_ADDR; IRQ exception at 0xffff0018
+ */
+
+#define HW_ICOLL_LEVELACK			0x0010
+/* 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 BM_LEVELn(nr)				BIT(nr)
+
+#define HW_ICOLL_CTRL				0x0020
+/* BM_CTRL_SFTRST and BM_CTRL_CLKGATE are not available on asm9260. */
+#define BM_CTRL_SFTRST				BIT(31)
+#define BM_CTRL_CLKGATE				BIT(30)
+#define BM_CTRL_NO_NESTING			BIT(19)
+/* disable interrupt level nesting */
+#define BM_CTRL_ARM_RSE_MODE			BIT(18)
+/* 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 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 HW_ICOLL_VECTOR register.
+ * 0 - Must Write to Vector register to go in-service.
+ * 1 - Go in-service as a read side effect
+ */
+#define BM_CTRL_IRQ_ENABLE			BIT(16)
+
+#define 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 HW_ICOLL_VECTOR.
+ */
+
+#define HW_ICOLL_RAW0				0x0040
+#define HW_ICOLL_RAW1				0x0050
+/* This register 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	HW_ICOLL_INTERRUPT0			0x0060
+#define	HW_ICOLL_INTERRUPTn(n)			(0x0060 + ((n) >> 2) * 0x10)
+#define	HW_ICOLL_INTERRUPTn_SET(n)		(HW_ICOLL_INTERRUPTn(n) \
+		+ SET_REG)
+#define	HW_ICOLL_INTERRUPTn_CLR(n)		(HW_ICOLL_INTERRUPTn(n) \
+		+ CLR_REG)
+#define BM_INT_PRIORITY_MASK			0x3
+/* WARNING: Modifying the priority of an enabled interrupt may result in
+ * undefined behavior. */
+#define BM_INT_ENABLE				BIT(2)
+#define BM_INT_SOFTIRQ				BIT(3)
+
+#define BM_ICOLL_INTERRUPTn_SHIFT(n)		(((n) & 0x3) << 3)
+#define BM_ICOLL_INTERRUPTn_ENABLE(n)		(1 << (2 + \
+			BM_ICOLL_INTERRUPTn_SHIFT(n)))
+
+#define HW_ICOLL_VBASE				0x0160
+/* bits 31:2
+ * This bitfield holds the upper 30 bits of the base address of the vector
+ * table. */
+
+#define HW_ICOLL_CLEAR0				0x01d0
+#define	HW_ICOLL_CLEAR1				0x01e0
+#define HW_ICOLL_CLEARn(n)			(0x01d0 + ((n >> 5) * 0x10) \
+							+ SET_REG)
+#define BM_CLEAR_BIT(n)				BIT(n & 0x1f)
+
+#define HW_ICOLL_UNDEF_VECTOR			0x01f0
+/* Scratchpad */
+
+#define ICOLL_NUM_IRQS		64
+
+static void __iomem *icoll_base;
+static struct irq_domain *icoll_domain;
+static int use_cached_level = 1;
+static u8 level_cache[ICOLL_NUM_IRQS];
+
+static unsigned int irq_get_level(struct irq_data *d)
+{
+	unsigned int tmp;
+
+	if (use_cached_level)
+		return level_cache[d->hwirq];
+
+	tmp = readl_relaxed(icoll_base + HW_ICOLL_INTERRUPTn_SET(d->hwirq));
+	return (tmp >> BM_ICOLL_INTERRUPTn_SHIFT(d->hwirq)) & 0x3;
+}
+
+static void irq_set_level(int hwirq, int level)
+{
+	if (unlikely(level < 0 || level > 3)) {
+		pr_err("%s Wrong level (%i) for irq (%i)!", __func__, level,
+				hwirq);
+		return;
+	}
+	if (use_cached_level)
+		level_cache[hwirq] = level;
+
+	writel_relaxed(level << BM_ICOLL_INTERRUPTn_SHIFT(hwirq),
+			icoll_base + HW_ICOLL_INTERRUPTn(hwirq));
+}
+
+static void icoll_ack_irq(struct irq_data *d)
+{
+	readl_relaxed(icoll_base + HW_ICOLL_VECTOR);
+}
+
+static void icoll_mask_irq(struct irq_data *d)
+{
+	writel_relaxed(BM_ICOLL_INTERRUPTn_ENABLE(d->hwirq),
+			icoll_base + HW_ICOLL_INTERRUPTn_CLR(d->hwirq));
+}
+
+static void icoll_unmask_irq(struct irq_data *d)
+{
+	u32 level;
+
+	writel_relaxed(BM_CLEAR_BIT(d->hwirq),
+			icoll_base + HW_ICOLL_CLEARn(d->hwirq));
+
+	level = irq_get_level(d);
+	writel_relaxed(BM_LEVELn(level), icoll_base + HW_ICOLL_LEVELACK);
+
+	writel_relaxed(BM_ICOLL_INTERRUPTn_ENABLE(d->hwirq),
+			icoll_base + HW_ICOLL_INTERRUPTn_SET(d->hwirq));
+}
+
+static struct irq_chip asm9260_icoll_chip = {
+	.irq_ack = icoll_ack_irq,
+	.irq_mask = icoll_mask_irq,
+	.irq_unmask = icoll_unmask_irq,
+};
+
+asmlinkage void __exception_irq_entry icoll_handle_irq(struct pt_regs *regs)
+{
+	u32 irqnr;
+
+	irqnr = irq_find_mapping(icoll_domain,
+			readl_relaxed(icoll_base + HW_ICOLL_STAT_OFFSET));
+
+	handle_IRQ(irqnr, regs);
+}
+
+static int icoll_irq_domain_map(struct irq_domain *d, unsigned int virq,
+				irq_hw_number_t hw)
+{
+	irq_set_chip_and_handler(virq, &asm9260_icoll_chip, handle_level_irq);
+	set_irq_flags(virq, IRQF_VALID);
+
+	return 0;
+}
+
+static struct irq_domain_ops icoll_irq_domain_ops = {
+	.map = icoll_irq_domain_map,
+	.xlate = irq_domain_xlate_onecell,
+};
+
+static int __init icoll_of_init(struct device_node *np,
+			  struct device_node *interrupt_parent)
+{
+	struct resource res;
+	int i;
+
+	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);
+
+	icoll_base = ioremap_nocache(res.start, resource_size(&res));
+	if (!icoll_base)
+		panic("%s: unable to map resource", np->name);
+
+	/* enable IRQ controller */
+	writel_relaxed(BM_CTRL_ARM_RSE_MODE | BM_CTRL_IRQ_ENABLE,
+			icoll_base + HW_ICOLL_CTRL);
+
+	/* This ICOLL has no reset option. So, set all priorities
+	 * manually to 0. */
+	for (i = 0; i < 16 * 0x10; i += 0x10)
+		writel(0, icoll_base + HW_ICOLL_INTERRUPT0 + i);
+
+	/* set timer 0 priority level high. TODO: should be done by DT  */
+	irq_set_level(29, 3);
+
+	icoll_domain = irq_domain_add_linear(np, ICOLL_NUM_IRQS,
+					     &icoll_irq_domain_ops, NULL);
+
+	irq_set_default_host(icoll_domain);
+
+	set_handle_irq(icoll_handle_irq);
+
+	return icoll_domain ? 0 : -ENODEV;
+}
+IRQCHIP_DECLARE(asm9260, "alpscale,asm9260-icall", icoll_of_init);
-- 
1.9.1

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

* [PATCH 7/7] tty/serial: add asm9260-serial driver
  2014-09-13 22:13 [PATCH 0/7] initial suport for Alpscale ASM9260 Oleksij Rempel
                   ` (5 preceding siblings ...)
  2014-09-13 22:13 ` [PATCH 6/7] irqchip: add irq-asm9260 driver Oleksij Rempel
@ 2014-09-13 22:13 ` Oleksij Rempel
  6 siblings, 0 replies; 23+ messages in thread
From: Oleksij Rempel @ 2014-09-13 22:13 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Oleksij Rempel <linux@rempel-privat.de>
---
 drivers/tty/serial/Kconfig          |   19 +
 drivers/tty/serial/Makefile         |    1 +
 drivers/tty/serial/asm9260_serial.c | 1236 +++++++++++++++++++++++++++++++++++
 include/uapi/linux/serial_core.h    |    2 +
 4 files changed, 1258 insertions(+)
 create mode 100644 drivers/tty/serial/asm9260_serial.c

diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index fb57159..02adb75 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -1552,6 +1552,25 @@ config SERIAL_MEN_Z135
 	  This driver can also be build as a module. If so, the module will be called
 	  men_z135_uart.ko
 
+config SERIAL_ASM9260
+	tristate "ASM9260 controller serial support"
+	depends on MACH_ASM9260
+	select SERIAL_CORE
+	help
+		If you have an asm9260 based Base IO card
+		and wish to use the serial ports on this card, say Y.
+		Otherwise, say N.
+
+config SERIAL_ASM9260_CONSOLE
+	bool "ASM9260 console support"
+	depends on SERIAL_ASM9260
+	select SERIAL_CORE_CONSOLE
+	help
+		If you want to support serial console on borad asm9260
+		say Y. Otherwise, say N.
+
+source "arch/arm/mach-asm9260/Kconfig"
+
 endmenu
 
 config SERIAL_MCTRL_GPIO
diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile
index 0080cc3..80940d4 100644
--- a/drivers/tty/serial/Makefile
+++ b/drivers/tty/serial/Makefile
@@ -95,3 +95,4 @@ obj-$(CONFIG_SERIAL_MEN_Z135)	+= men_z135_uart.o
 
 # GPIOLIB helpers for modem control lines
 obj-$(CONFIG_SERIAL_MCTRL_GPIO)	+= serial_mctrl_gpio.o
+obj-$(CONFIG_SERIAL_ASM9260) += asm9260_serial.o
diff --git a/drivers/tty/serial/asm9260_serial.c b/drivers/tty/serial/asm9260_serial.c
new file mode 100644
index 0000000..1d18439
--- /dev/null
+++ b/drivers/tty/serial/asm9260_serial.c
@@ -0,0 +1,1236 @@
+/*
+ * asm9260_serial.c Alpscale ASM9260 UART driver
+ *
+ * Mostly rewritten with irq_thread, clk and DT suppor:
+ * Copyright (C) 2014 Oleksij Rempel <linux@rempel-privat.de>
+ *
+ * 		 2014 Cleaned by Du Huanpeng <u74147@gmail.com>
+ *
+ * Copyright (C) 2013, Alpscale Tech. Co., Ltd.
+ * Initial code has been inspired/copied from atmel_serial.c (kernel v2.4) and
+ * adopted for asm9260 (kernel v2.4) by Chen Dongdong.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/clk.h>
+#include <linux/console.h>
+#include <linux/platform_device.h>
+#include <linux/uaccess.h>
+
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/serial_core.h>
+#include <linux/tty_flip.h>
+
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/of_platform.h>
+
+#define SERIAL_ASM9260_MAJOR		204
+#define MINOR_START			64
+#define ASM9260_DEVICENAME		"ttyS"
+#define DRIVER_NAME			"asm9260_uart"
+#define ASM9260_UART_FIFOSIZE		16
+#define ASM9260_BUS_RATE		100000000
+#define ASM9260_MAX_UART		10
+
+#define UART_BAUD_DIVINT_MASK		((unsigned int)0x003FFFC0)
+#define UART_BAUD_DIVFRAC_MASK		((unsigned int)0x0000003F)
+#define	UART_BAUD_DIV_MAX		0x3FFFFF
+
+#define SET_REG 0x4
+#define CLR_REG 0x8
+
+#define HW_CTRL0			0x00
+#define BM_CTRL0_RXTO_SOURCE_STATUS	BIT(25)
+#define BM_CTRL0_RXTO_ENABLE		BIT(24)
+#define BM_CTRL0_RXTO_MASK		(0xFF<<16)
+#define BM_CTRL0_DEFAULT_RXTIMEOUT	(20<<16) /* TIMEOUT = (100*7+1)*(1/BAUD) */
+
+#define HW_CTRL1			0x10
+
+#define HW_CTRL2			0x20
+#define BM_CTRL2_CTSE			BIT(15)
+#define BM_CTRL2_RTSE			BIT(14)
+#define BM_CTRL2_RXE			BIT(9)
+#define BM_CTRL2_TXE			BIT(8)
+#define BM_CTRL2_LBE			BIT(7)
+#define BM_CTRL2_PORT_ENABLE		BIT(0)
+#define BM_CTRL2_TXIFLSEL		(7<<16)
+#define BM_CTRL2_RXIFLSEL		(7<<20)
+#define BM_CTRL2_DEFAULT_TXIFLSEL	(2<<16)
+#define BM_CTRL2_DEFAULT_RXIFLSEL	(3<<20)
+
+#define HW_LINECTRL			0x30
+#define BM_LCTRL_BAUD_DIVINT		(0xFFFF<<16)
+#define BM_LCTRL_BAUD_DIVFRA		(0x3F<<8)
+#define BM_LCTRL_SPS			BIT(7)
+#define BM_LCTRL_WLEN			(3<<5)
+#define BM_LCTRL_FEN			BIT(4)
+#define BM_LCTRL_STP2			BIT(3)
+#define BM_LCTRL_EPS			BIT(2)
+#define BM_LCTRL_PEN			BIT(1)
+#define BM_LCTRL_BREAK			BIT(0)
+#define BM_LCTRL_CHRL_5			(0<<5)
+#define BM_LCTRL_CHRL_6			(1<<5)
+#define BM_LCTRL_CHRL_7			(2<<5)
+#define BM_LCTRL_CHRL_8			(3<<5)
+#define BM_LCTRL_NBSTOP_1		(0<<3)
+#define BM_LCTRL_NBSTOP_2		(1<<3)
+#define BM_LCTRL_PAR_MARK		((3<<1) | (1<<7))
+#define BM_LCTRL_PAR_SPACE		((1<<1) | (1<<7))
+#define BM_LCTRL_PAR_ODD		((1<<1) | (0<<7))
+#define BM_LCTRL_PAR_EVEN		((3<<1) | (0<<7))
+#define BM_LCTRL_PAR_NONE		(0<<1)
+
+/* Interrupt register.
+ * contains the interrupt enables and the interrupt status bits */
+#define HW_INTR				0x40
+/* Tx FIFO EMPTY Raw Interrupt enable */
+#define BM_INTR_TFEIEN			BIT(27)
+/* Overrun Error Interrupt Enable. */
+#define BM_INTR_OEIEN			BIT(26)
+/* Break Error Interrupt Enable. */
+#define BM_INTR_BEIEN			BIT(25)
+/* Parity Error Interrupt Enable. */
+#define BM_INTR_PEIEN			BIT(24)
+/* Framing Error Interrupt Enable. */
+#define BM_INTR_FEIEN			BIT(23)
+/* Receive Timeout Interrupt Enable.
+ * If not set and FIFO is enabled, then RX will be triggered only
+ * if FIFO is full. */
+#define BM_INTR_RTIEN			BIT(22)
+/* Transmit Interrupt Enable. */
+#define BM_INTR_TXIEN			BIT(21)
+/* Receive Interrupt Enable. */
+#define BM_INTR_RXIEN			BIT(20)
+/* nUARTDSR Modem Interrupt Enable. */
+#define BM_INTR_DSRMIEN			BIT(19)
+/* nUARTDCD Modem Interrupt Enable. */
+#define BM_INTR_DCDMIEN			BIT(18)
+/* nUARTCTS Modem Interrupt Enable. */
+#define BM_INTR_CTSMIEN			BIT(17)
+/* nUARTRI Modem Interrupt Enable. */
+#define BM_INTR_RIMIEN			BIT(16)
+/* Auto-Boud Timeout */
+#define BM_INTR_ABTO			BIT(13)
+#define BM_INTR_ABEO			BIT(12)
+/* Tx FIFO EMPTY Raw Interrupt state */
+#define BM_INTR_TFEIS			BIT(11)
+/* Overrun Error */
+#define BM_INTR_OEIS			BIT(10)
+/* Break Error */
+#define BM_INTR_BEIS			BIT(9)
+/* Parity Error */
+#define BM_INTR_PEIS			BIT(8)
+/* Framing Error */
+#define BM_INTR_FEIS			BIT(7)
+/* Receive Timeout */
+#define BM_INTR_RTIS			BIT(6)
+/* Transmit done */
+#define BM_INTR_TXIS			BIT(5)
+/* Receive done */
+#define BM_INTR_RXIS			BIT(4)
+#define BM_INTR_DSRMIS			BIT(3)
+#define BM_INTR_DCDMIS			BIT(2)
+#define BM_INTR_CTSMIS			BIT(1)
+#define BM_INTR_RIMIS			BIT(0)
+
+
+#define BM_INTR_DEF_MASK	(BM_INTR_RXIEN | BM_INTR_TXIEN | BM_INTR_RTIEN \
+		| BM_INTR_FEIEN | BM_INTR_PEIEN | BM_INTR_BEIEN | BM_INTR_OEIEN)
+
+#define BM_INTR_DEF_IS_MASK		(BM_INTR_DEF_MASK >> 16)
+#define BM_INTR_EN_MASK			(0x3fff0000)
+#define BM_INTR_IS_MASK			(0x00003fff)
+
+#define HW_DATA				0x50
+
+#define HW_STAT				0x60
+#define BM_STAT_BUSY			BIT(29)
+#define BM_STAT_CTS			BIT(28)
+#define BM_STAT_TXEMPTY			BIT(27)
+#define BM_STAT_RXFULL			BIT(26)
+#define BM_STAT_TXFULL			BIT(25)
+#define BM_STAT_RXEMPTY			BIT(24)
+#define BM_STAT_OVERRUNERR		BIT(19)
+#define BM_STAT_BREAKERR		BIT(18)
+#define BM_STAT_PARITYERR		BIT(17)
+#define BM_STAT_FRAMEERR		BIT(16)
+
+#define HW_ILPR				0x80
+
+#define HW_RS485CTRL			0x90
+#define	BM_RS485CTRL_RS485EN		BIT(0)
+#define	BM_RS485CTRL_RXDIS		BIT(1)
+#define	BM_RS485CTRL_AADEN		BIT(2)
+#define	BM_RS485CTRL_PINSEL		BIT(3)
+#define	BM_RS485CTRL_DIR_CTRL		BIT(4)
+#define	BM_RS485CTRL_ONIV		BIT(5)
+
+#define HW_RS485ADRMATCH		0xA0
+#define HW_RS485DLY			0xB0
+#define HW_AUTOBAUD			0xC0
+#define HW_CTRL3			0xD0
+
+
+/*
+ * We wrap our port structure around the generic uart_port.
+ */
+struct asm9260_uart_port {
+	struct uart_port	uart;		/* uart */
+	struct clk		*clk;		/* uart clock */
+	struct clk		*clk_ahb;
+	int			clk_on;
+
+	struct serial_rs485	rs485;		/* rs485 settings */
+
+	uint32_t intmask;
+	int init_ok;
+};
+
+static struct asm9260_uart_port *asm9260_ports;
+static int asm9260_ports_num;
+
+static void asm9260_start_rx(struct uart_port *uport);
+static void asm9260_tx_chars(struct uart_port *uport);
+static int asm9260_get_of_clks(struct asm9260_uart_port *port,
+		struct device_node *np);
+static void asm9260_enable_clks(struct asm9260_uart_port *port);
+static void asm9260_uart_of_enumerate(void);
+
+static inline struct asm9260_uart_port *
+to_asm9260_uart_port(struct uart_port *uart)
+{
+	return container_of(uart, struct asm9260_uart_port, uart);
+}
+
+static inline void asm9260_intr_mask(struct uart_port *uport)
+{
+	iowrite32(BM_INTR_DEF_MASK,
+			uport->membase + HW_INTR + CLR_REG);
+}
+
+static inline void asm9260_intr_unmask(struct uart_port *uport)
+{
+	iowrite32(BM_INTR_DEF_MASK,
+			uport->membase + HW_INTR + SET_REG);
+}
+
+/*
+ * Return TIOCSER_TEMT when transmitter FIFO and Shift register is empty.
+ */
+static u_int asm9260_tx_empty(struct uart_port *uport)
+{
+	return (ioread32(uport->membase + HW_STAT)
+			& BM_STAT_TXEMPTY) ? TIOCSER_TEMT : 0;
+}
+
+static void asm9260_set_mctrl(struct uart_port *uport, u_int mctrl)
+{
+}
+
+static u_int asm9260_get_mctrl(struct uart_port *uport)
+{
+	return 0;
+}
+
+/*
+ * Stop transmitting.
+ */
+static void asm9260_stop_tx(struct uart_port *uport)
+{
+	struct asm9260_uart_port *asm9260_port = to_asm9260_uart_port(uport);
+
+	/* seems like it was take over from atmel_serial.c
+	 * do we need it too? */
+	if ((asm9260_port->rs485.flags & SER_RS485_ENABLED) &&
+	    !(asm9260_port->rs485.flags & SER_RS485_RX_DURING_TX))
+		asm9260_start_rx(uport);
+}
+
+static void asm9260_start_tx(struct uart_port *uport)
+{
+	asm9260_tx_chars(uport);
+}
+
+static void asm9260_start_rx(struct uart_port *uport)
+{
+	/* enable receive */
+	iowrite32(BM_CTRL2_RXE,
+			uport->membase + HW_CTRL2 + SET_REG);
+}
+
+static void asm9260_stop_rx(struct uart_port *uport)
+{
+	/* disable receive */
+	iowrite32(BM_CTRL2_RXE,
+			uport->membase + HW_CTRL2 + CLR_REG);
+}
+
+static void asm9260_enable_ms(struct uart_port *uport)
+{
+}
+
+/*
+ * Control the transmission of a break signal
+ */
+static void asm9260_break_ctl(struct uart_port *uport, int break_state)
+{
+	if (break_state != 0)
+		iowrite32(BM_LCTRL_BREAK,
+				uport->membase + HW_LINECTRL + SET_REG);
+	else
+		iowrite32(BM_LCTRL_BREAK,
+				uport->membase + HW_LINECTRL + CLR_REG);
+}
+
+static void asm9260_rx_chars(struct uart_port *uport, unsigned int intr)
+{
+	unsigned int status, ch;
+
+	status = ioread32(uport->membase + HW_STAT);
+	while (!(status & BM_STAT_RXEMPTY)) {
+		unsigned int flg;
+		ch = ioread32(uport->membase + HW_DATA);
+
+		uport->icount.rx++;
+		flg = TTY_NORMAL;
+
+		if (unlikely(intr & (BM_INTR_PEIS | BM_INTR_FEIS
+				       | BM_INTR_OEIS | BM_INTR_BEIS))) {
+
+			/* clear error */
+			iowrite32(0, uport->membase + HW_STAT);
+
+			if (intr & BM_INTR_BEIS) {
+				uport->icount.brk++;
+				if (uart_handle_break(uport))
+					continue;
+			} else if (intr & BM_INTR_PEIS)
+				uport->icount.parity++;
+			else if (intr & BM_INTR_FEIS)
+				uport->icount.frame++;
+
+			if (intr & BM_INTR_OEIS)
+				uport->icount.overrun++;
+
+			intr &= uport->read_status_mask;
+
+			if (intr & BM_INTR_BEIS)
+				flg = TTY_BREAK;
+			else if (intr & BM_INTR_PEIS)
+				flg = TTY_PARITY;
+			else if (intr & BM_INTR_FEIS)
+				flg = TTY_FRAME;
+
+		}
+
+		if (uart_handle_sysrq_char(uport, ch))
+			continue;
+
+		uart_insert_char(uport, intr, BM_INTR_OEIS, ch, flg);
+		status = ioread32(uport->membase + HW_STAT);
+	}
+
+	tty_flip_buffer_push(&uport->state->port);
+}
+
+static void asm9260_tx_chars(struct uart_port *uport)
+{
+	struct circ_buf *xmit = &uport->state->xmit;
+
+	if (uport->x_char && !(ioread32(uport->membase + HW_STAT)
+				& BM_STAT_TXFULL)) {
+		iowrite32(uport->x_char, uport->membase + HW_DATA);
+		uport->icount.tx++;
+		uport->x_char = 0;
+	}
+	if (uart_circ_empty(xmit) || uart_tx_stopped(uport))
+		return;
+
+	while (!uart_circ_empty(xmit)) {
+		if (ioread32(uport->membase + HW_STAT)
+				& BM_STAT_TXFULL) {
+			break;;
+		}
+		iowrite32(xmit->buf[xmit->tail],
+				uport->membase + HW_DATA);
+		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+		uport->icount.tx++;
+	}
+
+	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+		uart_write_wakeup(uport);
+}
+
+static void
+asm9260_handle_receive(struct uart_port *uport, unsigned int pending)
+{
+	/* Interrupt receive */
+	if ((pending & BM_INTR_RXIS) || (pending & BM_INTR_RTIS))
+		asm9260_rx_chars(uport, pending);
+	else if (pending & BM_INTR_BEIS) {
+		/*
+		 * End of break detected. If it came along with a
+		 * character, asm9260_rx_chars will handle it.
+		 */
+		iowrite32(0, uport->membase + HW_STAT);
+	}
+}
+
+static void
+asm9260_handle_transmit(struct uart_port *uport, unsigned int pending)
+{
+	if (pending & BM_INTR_TXIS)
+		asm9260_tx_chars(uport);
+}
+
+/*
+ * Interrupt handler
+ */
+static irqreturn_t asm9260_interrupt(int irq, void *dev_id)
+{
+	struct uart_port *uport = dev_id;
+	unsigned int status;
+
+	status = ioread32(uport->membase + HW_INTR);
+	status &= BM_INTR_DEF_IS_MASK;
+
+	asm9260_handle_receive(uport, status);
+	asm9260_handle_transmit(uport, status);
+
+	iowrite32(status,
+			uport->membase + HW_INTR + CLR_REG);
+
+	asm9260_intr_unmask(uport);
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t asm9260_fast_int(int irq, void *dev_id)
+{
+	struct uart_port *uport = dev_id;
+	unsigned int status;
+
+	status = ioread32(uport->membase + HW_INTR);
+	if (!(status & BM_INTR_DEF_IS_MASK))
+		return IRQ_NONE;
+
+	asm9260_intr_mask(uport);
+	return IRQ_WAKE_THREAD;
+}
+
+/*
+ * Perform initialization and enable port for reception
+ */
+static int asm9260_startup(struct uart_port *uport)
+{
+	int retval;
+
+	/*
+	 * Ensure that no interrupts are enabled otherwise when
+	 * request_irq() is called we could get stuck trying to
+	 * handle an unexpected interrupt
+	 */
+	iowrite32(0, uport->membase + HW_INTR);
+
+	retval = devm_request_threaded_irq(uport->dev, uport->irq,
+			asm9260_fast_int, asm9260_interrupt, IRQF_SHARED,
+			dev_name(uport->dev), uport);
+	if (retval) {
+		dev_err(uport->dev, "Can't get irq\n");
+		return retval;
+	}
+
+	/* enable rx timeout */
+	iowrite32(BM_CTRL0_RXTO_MASK | BM_CTRL0_RXTO_SOURCE_STATUS,
+			uport->membase + HW_CTRL0 + CLR_REG);
+	iowrite32(BM_CTRL0_DEFAULT_RXTIMEOUT | BM_CTRL0_RXTO_ENABLE,
+			uport->membase + HW_CTRL0 + SET_REG);
+
+
+	/*
+	 * Finally, enable the serial port
+	 * enable tx & rx
+	 */
+	iowrite32(BM_CTRL2_RXIFLSEL | BM_CTRL2_TXIFLSEL,
+			uport->membase + HW_CTRL2 + CLR_REG);
+	iowrite32(BM_CTRL2_PORT_ENABLE | BM_CTRL2_TXE | BM_CTRL2_RXE |
+			BM_CTRL2_DEFAULT_TXIFLSEL |
+			BM_CTRL2_DEFAULT_RXIFLSEL,
+			uport->membase + HW_CTRL2);
+
+	asm9260_intr_unmask(uport);
+	return 0;
+}
+
+/*
+ * Disable the port
+ */
+static void asm9260_shutdown(struct uart_port *uport)
+{
+	int timeout = 10000;
+
+	/*wait for controller finish tx*/
+	while (!(ioread32(uport->membase + HW_STAT)
+				& BM_STAT_TXEMPTY)) {
+		if (--timeout < 0)
+			break;
+	}
+
+	/*
+	 * Ensure everything is stopped.
+	 */
+	asm9260_stop_tx(uport);
+	asm9260_stop_rx(uport);
+}
+
+/*
+ * Flush any TX data submitted for DMA. Called when the TX circular
+ * buffer is reset.
+ */
+static void asm9260_flush_buffer(struct uart_port *uport)
+{
+}
+
+/*
+ * Power / Clock management.
+ */
+static void asm9260_serial_pm(struct uart_port *uport, unsigned int state,
+			    unsigned int oldstate)
+{
+}
+
+static void asm9260_set_rs485(struct uart_port *uport)
+{
+	struct asm9260_uart_port *port = to_asm9260_uart_port(uport);
+	unsigned int rs485_ctrl;
+	/* set RS485 */
+	rs485_ctrl = ioread32(uport->membase + HW_RS485CTRL);
+
+	/* Resetting serial mode to RS232 (0x0) */
+	rs485_ctrl &= ~BM_RS485CTRL_RS485EN;
+
+	if (port->rs485.flags & SER_RS485_ENABLED) {
+		dev_dbg(uport->dev, "Setting UART to RS485\n");
+		if ((port->rs485.delay_rts_after_send) > 0) {
+			/* delay is (rs485conf->delay_rts_after_send * Bit Period * 1/16) */
+			iowrite32(port->rs485.delay_rts_after_send,
+					uport->membase + HW_RS485DLY);
+		}
+
+		if ((port->rs485.flags & SER_RS485_RTS_ON_SEND) &&
+			!(port->rs485.flags & SER_RS485_RTS_AFTER_SEND)) {
+			/*
+			 * Set logical level for RTS pin equal to 1 when sending,
+			 * and set logical level for RTS pin equal to 0 after sending
+			*/
+			rs485_ctrl |= BM_RS485CTRL_ONIV;
+		} else if (!(port->rs485.flags & SER_RS485_RTS_ON_SEND) &&
+			(port->rs485.flags & SER_RS485_RTS_AFTER_SEND)) {
+			/*
+			 * Set logical level for RTS pin equal to 0 when sending,
+			 * and set logical level for RTS pin equal to 1 after sending
+			*/
+			rs485_ctrl &= ~BM_RS485CTRL_ONIV;
+		} else
+			dev_info(uport->dev,
+					"Please view RS485CTRL register in datasheet for more details.\n");
+
+		/* Enable RS485 and RTS is used to control direction automatically,  */
+		rs485_ctrl |= BM_RS485CTRL_RS485EN | BM_RS485CTRL_DIR_CTRL;
+		rs485_ctrl &= ~BM_RS485CTRL_PINSEL;
+
+		if (port->rs485.flags & SER_RS485_RX_DURING_TX)
+			dev_dbg(uport->dev, "hardware should support SER_RS485_RX_DURING_TX.\n");
+	} else
+		dev_dbg(uport->dev, "Setting UART to RS232\n");
+
+	iowrite32(rs485_ctrl, uport->membase + HW_RS485CTRL);
+}
+/*
+ * Change the port parameters
+ */
+static void asm9260_set_termios(struct uart_port *uport, struct ktermios *termios,
+			      struct ktermios *old)
+{
+	unsigned int mode, baud;
+	unsigned int bauddivint, bauddivfrac;
+
+
+	asm9260_intr_mask(uport);
+
+	/*
+	 * We don't support modem control lines.
+	*/
+	termios->c_cflag &= ~(HUPCL | CMSPAR);
+	termios->c_cflag |= CLOCAL;
+
+	/* Get current mode register */
+	mode = ioread32(uport->membase + HW_LINECTRL);
+	mode &= ~(BM_LCTRL_PEN | BM_LCTRL_EPS
+			| BM_LCTRL_STP2 | BM_LCTRL_FEN
+			| BM_LCTRL_WLEN | BM_LCTRL_SPS
+			| BM_LCTRL_BAUD_DIVFRA | BM_LCTRL_BAUD_DIVINT);
+
+	baud = uart_get_baud_rate(uport, termios, old,
+			uport->uartclk * 4 / UART_BAUD_DIV_MAX, uport->uartclk / 16);
+	bauddivint =
+		(((uport->uartclk << 2) / baud) & UART_BAUD_DIVINT_MASK) << 10;
+	bauddivfrac =
+		(((uport->uartclk << 2) / baud) & UART_BAUD_DIVFRAC_MASK) << 8;
+	/* byte size */
+	switch (termios->c_cflag & CSIZE) {
+	case CS5:
+		mode |= BM_LCTRL_CHRL_5;
+		break;
+	case CS6:
+		mode |= BM_LCTRL_CHRL_6;
+		break;
+	case CS7:
+		mode |= BM_LCTRL_CHRL_7;
+		break;
+	default:
+		mode |= BM_LCTRL_CHRL_8;
+		break;
+	}
+
+	/* enable fifo */
+	mode |= BM_LCTRL_FEN;
+
+	/* stop bits */
+	if (termios->c_cflag & CSTOPB)
+		mode |= BM_LCTRL_NBSTOP_2;
+	else
+		mode |= BM_LCTRL_NBSTOP_1;
+
+	/* parity */
+	if (termios->c_cflag & PARENB) {
+		/* Mark or Space parity */
+		if (termios->c_cflag & CMSPAR) {
+			if (termios->c_cflag & PARODD)
+				mode |= BM_LCTRL_PAR_MARK;
+			else
+				mode |= BM_LCTRL_PAR_SPACE;
+		} else if (termios->c_cflag & PARODD)
+			mode |= BM_LCTRL_PAR_ODD;
+		else
+			mode |= BM_LCTRL_PAR_EVEN;
+	} else
+		mode |= BM_LCTRL_PAR_NONE;
+
+	spin_lock(&uport->lock);
+
+	uport->read_status_mask = BM_INTR_OEIS;
+	if (termios->c_iflag & INPCK)
+		uport->read_status_mask |= (BM_INTR_FEIS | BM_INTR_PEIS);
+	if (termios->c_iflag & (IGNBRK | BRKINT | PARMRK))
+		uport->read_status_mask |= BM_INTR_BEIS;
+
+	/*
+	 * Characters to ignore
+	 */
+	uport->ignore_status_mask = 0;
+	if (termios->c_iflag & IGNPAR)
+		uport->ignore_status_mask |=
+			(BM_INTR_FEIS  | BM_INTR_PEIS);
+	if (termios->c_iflag & IGNBRK) {
+		uport->ignore_status_mask |= BM_INTR_BEIS;
+		/*
+		 * If we're ignoring parity and break indicators,
+		 * ignore overruns too (for real raw support).
+		 */
+		if (termios->c_iflag & IGNPAR)
+			uport->ignore_status_mask |= BM_INTR_OEIS;
+	}
+
+	/* update the per-port timeout */
+	uart_update_timeout(uport, termios->c_cflag, baud);
+
+	/* drain transmitter */
+	while (!(ioread32(uport->membase + HW_STAT)
+				& BM_STAT_TXEMPTY))
+		cpu_relax();
+
+	while (!(ioread32(uport->membase + HW_STAT)
+				& BM_STAT_RXEMPTY))
+		ioread32(uport->membase + HW_DATA);
+
+	asm9260_set_rs485(uport);
+
+	/* set hardware flow control */
+	if (termios->c_cflag & CRTSCTS)
+		iowrite32(BM_CTRL2_CTSE | BM_CTRL2_RTSE,
+				uport->membase + HW_CTRL2 + SET_REG);
+	else
+		iowrite32(BM_CTRL2_CTSE | BM_CTRL2_RTSE,
+				uport->membase + HW_CTRL2 + CLR_REG);
+
+	/* set the parity, stop bits, data size and baud rate*/
+	iowrite32(mode | bauddivint | bauddivfrac,
+			uport->membase + HW_LINECTRL);
+
+	/* CTS flow-control and modem-status interrupts */
+	if (UART_ENABLE_MS(uport, termios->c_cflag))
+		uport->ops->enable_ms(uport);
+
+	spin_unlock(&uport->lock);
+
+	dev_dbg(uport->dev,
+			"mode:0x%x, baud:%d, bauddivint:0x%x, bauddivfrac:0x%x, ctrl2:0x%x\n",
+			mode, baud, bauddivint, bauddivfrac,
+			ioread32(uport->membase + HW_CTRL2));
+
+	asm9260_intr_unmask(uport);
+}
+
+/*
+ * Return string describing the specified port
+ */
+static const char *asm9260_type(struct uart_port *uport)
+{
+	return (uport->type == PORT_ASM9260) ? DRIVER_NAME : NULL;
+}
+
+/*
+ * Release the memory region(s) being used by 'port'.
+ */
+static void asm9260_release_port(struct uart_port *uport)
+{
+}
+
+/*
+ * Request the memory region(s) being used by 'port'.
+ */
+static int asm9260_request_port(struct uart_port *uport)
+{
+	return 0;
+}
+
+/*
+ * Configure/autoconfigure the port.
+ */
+static void asm9260_config_port(struct uart_port *uport, int flags)
+{
+	if (flags & UART_CONFIG_TYPE) {
+		uport->type = PORT_ASM9260;
+		asm9260_request_port(uport);
+	}
+}
+
+/*
+ * Verify the new serial_struct (for TIOCSSERIAL).
+ */
+static int asm9260_verify_port(struct uart_port *uport,
+		struct serial_struct *ser)
+{
+	int ret = 0;
+
+	if (ser->type != PORT_UNKNOWN && ser->type != PORT_ASM9260)
+		ret = -EINVAL;
+	if (uport->irq != ser->irq)
+		ret = -EINVAL;
+	if (ser->io_type != SERIAL_IO_MEM)
+		ret = -EINVAL;
+	if (uport->uartclk / 16 != ser->baud_base)
+		ret = -EINVAL;
+	if ((void *)uport->mapbase != ser->iomem_base)
+		ret = -EINVAL;
+	if (uport->iobase != ser->port)
+		ret = -EINVAL;
+	if (ser->hub6 != 0)
+		ret = -EINVAL;
+	return ret;
+}
+
+/* Enable or disable the rs485 support */
+void asm9260_config_rs485(struct uart_port *uport,
+		struct serial_rs485 *rs485conf)
+{
+	struct asm9260_uart_port *port = to_asm9260_uart_port(uport);
+
+	asm9260_intr_mask(uport);
+	spin_lock(&uport->lock);
+
+	/* Disable interrupts */
+
+	port->rs485 = *rs485conf;
+
+	asm9260_set_rs485(uport);
+
+	/* Enable tx interrupts */
+	spin_unlock(&uport->lock);
+	asm9260_intr_unmask(uport);
+
+}
+
+static int asm9260_ioctl(struct uart_port *uport,
+		unsigned int cmd, unsigned long arg)
+{
+	struct serial_rs485 rs485conf;
+
+	switch (cmd) {
+	case TIOCSRS485:
+		if (copy_from_user(&rs485conf, (struct serial_rs485 *) arg,
+					sizeof(rs485conf)))
+			return -EFAULT;
+
+		asm9260_config_rs485(uport, &rs485conf);
+		break;
+
+	case TIOCGRS485:
+		if (copy_to_user((struct serial_rs485 *) arg,
+					&(to_asm9260_uart_port(uport)->rs485),
+					sizeof(rs485conf)))
+			return -EFAULT;
+		break;
+
+	default:
+		return -ENOIOCTLCMD;
+	}
+	return 0;
+}
+
+static struct uart_ops asm9260_pops = {
+	.tx_empty	= asm9260_tx_empty,
+	.set_mctrl	= asm9260_set_mctrl,
+	.get_mctrl	= asm9260_get_mctrl,
+	.stop_tx	= asm9260_stop_tx,
+	.start_tx	= asm9260_start_tx,
+	.stop_rx	= asm9260_stop_rx,
+	.enable_ms	= asm9260_enable_ms,
+	.break_ctl	= asm9260_break_ctl,
+	.startup	= asm9260_startup,
+	.shutdown	= asm9260_shutdown,
+	.flush_buffer	= asm9260_flush_buffer,
+	.set_termios	= asm9260_set_termios,
+	.type		= asm9260_type,
+	.release_port	= asm9260_release_port,
+	.request_port	= asm9260_request_port,
+	.config_port	= asm9260_config_port,
+	.verify_port	= asm9260_verify_port,
+	.pm		= asm9260_serial_pm,
+	.ioctl	= asm9260_ioctl,
+};
+
+#ifdef CONFIG_SERIAL_ASM9260_CONSOLE
+
+static struct asm9260_uart_port *get_asm9260_uart_port(int line);
+static struct console asm9260_console;
+
+static void asm9260_console_putchar(struct uart_port *uport, int ch)
+{
+	while (ioread32(uport->membase + HW_STAT)
+			& BM_STAT_TXFULL)
+		cpu_relax();
+	iowrite32(ch, uport->membase + HW_DATA);
+}
+
+/*
+ * Interrupts are disabled on entering
+ */
+static void asm9260_console_write(struct console *co, const char *s,
+		u_int count)
+{
+	struct uart_port *uport;
+	struct asm9260_uart_port *port;
+	unsigned int status;
+	int locked = 1;
+
+	port = get_asm9260_uart_port(co->index);
+	uport = &port->uart;
+
+	asm9260_intr_mask(uport);
+
+	if (oops_in_progress)
+		locked = spin_trylock(&uport->lock);
+	else
+		spin_lock(&uport->lock);
+
+
+	uart_console_write(uport, s, count, asm9260_console_putchar);
+
+	/*
+	 * Finally, wait for transmitter to become empty
+	 * and restore IMR
+	 */
+	do {
+		status = ioread32(uport->membase + HW_STAT);
+	} while (!(status & BM_STAT_TXEMPTY));
+
+	if (locked)
+		spin_unlock(&uport->lock);
+
+	asm9260_intr_unmask(uport);
+}
+
+/*
+ * If the port was already initialised (eg, by a boot loader),
+ * try to determine the current setup.
+ */
+static void __init asm9260_console_get_options(struct uart_port *port,
+		int *baud, int *parity, int *bits)
+{
+	unsigned int mr, quot, linectrl, bauddivint, bauddivfrc;
+
+	/*
+	 * If the baud rate generator isn't running, the port wasn't
+	 * initialized by the boot loader.
+	 */
+	linectrl = ioread32(port->membase + HW_LINECTRL);
+	bauddivint = (linectrl & BM_LCTRL_BAUD_DIVINT) >> 16;
+	bauddivfrc = (linectrl & BM_LCTRL_BAUD_DIVFRA) >> 8;
+	quot = (bauddivint << 6) | bauddivfrc;
+
+	if (!quot)
+		return;
+
+	mr = linectrl & BM_LCTRL_WLEN;
+	if (mr == BM_LCTRL_CHRL_8)
+		*bits = 8;
+	else
+		*bits = 7;
+
+	mr = linectrl &
+		(BM_LCTRL_PEN | BM_LCTRL_EPS | BM_LCTRL_SPS);
+	if (mr == BM_LCTRL_PAR_EVEN)
+		*parity = 'e';
+	else if (mr == BM_LCTRL_PAR_ODD)
+		*parity = 'o';
+
+	/*
+	 * The serial core only rounds down when matching this to a
+	 * supported baud rate. Make sure we don't end up slightly
+	 * lower than one of those, as it would make us fall through
+	 * to a much lower baud rate than we really want.
+	 */
+	*baud = (port->uartclk * 4) / quot;
+}
+
+static int __init asm9260_console_setup(struct console *co, char *options)
+{
+	struct uart_port *uport;
+	struct asm9260_uart_port *port;
+	int baud = 115200;
+	int bits = 8;
+	int parity = 'n';
+	int flow = 'n';
+
+	asm9260_uart_of_enumerate();
+
+	port = get_asm9260_uart_port(co->index);
+	uport = &port->uart;
+
+	asm9260_enable_clks(port);
+
+	iowrite32(BM_CTRL2_TXE | BM_CTRL2_RXE | BM_CTRL2_PORT_ENABLE,
+			uport->membase + HW_CTRL2 + SET_REG);
+
+	if (options)
+		uart_parse_options(options, &baud, &parity, &bits, &flow);
+	else
+		asm9260_console_get_options(uport, &baud, &parity, &bits);
+
+	return uart_set_options(uport, co, baud, parity, bits, flow);
+}
+
+static struct uart_driver asm9260_uart;
+
+static struct console asm9260_console = {
+	.name		= ASM9260_DEVICENAME,
+	.write		= asm9260_console_write,
+	.device		= uart_console_device,
+	.setup		= asm9260_console_setup,
+	.flags		= CON_PRINTBUFFER,
+	.index		= -1,
+	.data		= &asm9260_uart,
+};
+
+#define ASM9260_CONSOLE_DEVICE	(&asm9260_console)
+
+/*
+ * Early console initialization (before VM subsystem initialized).
+ */
+static int __init asm9260_console_init(void)
+{
+	register_console(&asm9260_console);
+	return 0;
+}
+
+console_initcall(asm9260_console_init);
+#else
+#define ASM9260_CONSOLE_DEVICE	NULL
+#endif
+
+static struct uart_driver asm9260_uart = {
+	.owner			= THIS_MODULE,
+	.driver_name		= DRIVER_NAME,
+	.dev_name		= ASM9260_DEVICENAME,
+	.nr			= ASM9260_MAX_UART,
+	.cons			= ASM9260_CONSOLE_DEVICE,
+};
+
+/* Match table for of_platform binding */
+static struct of_device_id asm9260_of_match[] = {
+	{ .compatible = "alpscale,asm9260-uart", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, asm9260_of_match);
+
+static void asm9260_enable_clks(struct asm9260_uart_port *port)
+{
+	struct uart_port *uport = &port->uart;
+	int err;
+
+	if (port->clk_on)
+		return;
+
+	err = clk_set_rate(port->clk, ASM9260_BUS_RATE);
+	if (err)
+		dev_err(uport->dev, "Failed to set rate!\n");
+
+	err = clk_prepare_enable(port->clk);
+	if (err)
+		dev_err(uport->dev, "Failed to enable clk!\n");
+
+	err = clk_prepare_enable(port->clk_ahb);
+	if (err)
+		dev_err(uport->dev, "Failed to enable ahb_clk!\n");
+
+	uport->uartclk = clk_get_rate(port->clk);
+	port->clk_on = 1;
+}
+
+
+/* get devicetree clocks, if some thing wrong, warn about it */
+static int asm9260_get_of_clks(struct asm9260_uart_port *port,
+		struct device_node *np)
+{
+	int clk_idx = 0;
+
+	port->clk = of_clk_get(np, clk_idx);
+	if (IS_ERR(port->clk))
+		goto out_err;
+
+	/* configure AHB clock */
+	clk_idx = 1;
+	port->clk_ahb = of_clk_get(np, clk_idx);
+	if (IS_ERR(port->clk_ahb))
+		goto out_err;
+
+	return 0;
+out_err:
+	pr_err("%s: Failed to get clk (%i)\n", __func__, clk_idx);
+	return 1;
+}
+
+static int asm9260_get_count_of_nodes(const struct of_device_id *matches)
+{
+	int count = 0;
+	struct device_node *np;
+
+	for_each_matching_node(np, matches)
+		count++;
+
+	return count;
+}
+
+static struct asm9260_uart_port *get_asm9260_uart_port(int line)
+{
+	if (line >= asm9260_ports_num) {
+		pr_err("%s: Line number overflow. Check DeviceTree!!",
+				__func__);
+		return NULL;
+	}
+
+	return &asm9260_ports[line];
+}
+
+static void asm9260_uart_of_enumerate(void)
+{
+	static int enum_done;
+	struct device_node *np;
+
+	if (enum_done)
+		return;
+
+	asm9260_ports_num = asm9260_get_count_of_nodes(asm9260_of_match);
+	asm9260_ports = kcalloc(asm9260_ports_num,
+				sizeof(struct asm9260_uart_port), GFP_KERNEL);
+
+	for_each_matching_node(np, asm9260_of_match) {
+		struct uart_port *uport;
+		struct asm9260_uart_port *port;
+		int line;
+
+		line = of_alias_get_id(np, "serial");
+		if (line < 0) {
+			pr_err("Error! Devicetree has no \"serial\" aliases\n");
+			continue;
+		}
+
+		port = get_asm9260_uart_port(line);
+		if (!port)
+			continue;
+
+		uport = &port->uart;
+		if(asm9260_get_of_clks(port, np))
+			return;
+
+		uport->iotype	= UPIO_MEM;
+		uport->flags	= UPF_BOOT_AUTOCONF;
+		uport->ops	= &asm9260_pops;
+		uport->fifosize	= ASM9260_UART_FIFOSIZE;
+		uport->line	= line;
+
+		/* Since of_map don't do actual request of memory region,
+		 * it is save to use it for all, enabled and disabled uarts. */
+		uport->membase = of_iomap(np, 0);
+		if (!uport->membase) {
+			pr_err("Unable to map registers\n");
+			continue;
+		}
+		port->init_ok = 1;
+	}
+
+	enum_done = 1;
+}
+
+/*
+ * Configure the port from the platform device resource info.
+ */
+static void asm9260_init_port(struct asm9260_uart_port *asm9260_port,
+				      struct platform_device *pdev)
+{
+	struct uart_port *uport = &asm9260_port->uart;
+	struct device_node *np = pdev->dev.of_node;
+	struct resource res;
+
+	uport->dev = &pdev->dev;
+
+	uport->irq = irq_of_parse_and_map(np, 0);
+
+	of_address_to_resource(np, 0, &res);
+	if (!devm_request_mem_region(uport->dev, res.start,
+				resource_size(&res), dev_name(uport->dev)))
+		dev_err(uport->dev, "unable to request mem region\n");
+
+	uport->mapbase	= res.start;
+
+	asm9260_enable_clks(asm9260_port);
+}
+
+static int asm9260_serial_probe(struct platform_device *pdev)
+{
+	struct asm9260_uart_port *port;
+	struct device_node *np = pdev->dev.of_node;
+	int ret, line;
+
+	asm9260_uart_of_enumerate();
+
+	if (!np) {
+		dev_err(&pdev->dev, "Error! We support only DeviceTree!\n");
+		return -EPERM;
+	}
+
+	line = of_alias_get_id(np, "serial");
+	if (line < 0) {
+		dev_err(&pdev->dev,
+				"Error! Devicetree has no \"serial\" aliases\n");
+		return -EPERM;
+	}
+
+	port = get_asm9260_uart_port(line);
+
+	if (!port->init_ok) {
+		dev_err(&pdev->dev, "Bad init!\n");
+	}
+
+	asm9260_init_port(port, pdev);
+
+	ret = uart_add_one_port(&asm9260_uart, &port->uart);
+	if (ret) {
+		dev_err(&pdev->dev, "Filed to add uart port\n");
+		goto err_add_port;
+	}
+
+	platform_set_drvdata(pdev, port);
+
+	return 0;
+
+err_add_port:
+	if (!uart_console(&port->uart)) {
+		clk_put(port->clk);
+		port->clk = NULL;
+	}
+	dev_err(&pdev->dev, "Filed to probe device\n");
+	return ret;
+}
+
+static int asm9260_serial_remove(struct platform_device *pdev)
+{
+	struct uart_port *port = platform_get_drvdata(pdev);
+	struct asm9260_uart_port *asm9260_port = to_asm9260_uart_port(port);
+	int ret = 0;
+
+	uart_remove_one_port(&asm9260_uart, port);
+	uart_unregister_driver(&asm9260_uart);
+
+	/* TODO: how should we handle clks here */
+	clk_put(asm9260_port->clk);
+
+	return ret;
+}
+
+static struct platform_driver asm9260_serial_driver = {
+	.driver		= {
+		.name	= DRIVER_NAME,
+		.owner	= THIS_MODULE,
+		.of_match_table = of_match_ptr(asm9260_of_match),
+	},
+	.probe		= asm9260_serial_probe,
+	.remove		= asm9260_serial_remove,
+};
+
+static int __init asm9260_serial_init(void)
+{
+	int ret;
+	ret = uart_register_driver(&asm9260_uart);
+	if (ret)
+		return ret;
+
+	ret = platform_driver_register(&asm9260_serial_driver);
+	if (ret)
+		uart_unregister_driver(&asm9260_uart);
+
+	return ret;
+}
+
+static void __exit asm9260_serial_exit(void)
+{
+	platform_driver_unregister(&asm9260_serial_driver);
+	uart_unregister_driver(&asm9260_uart);
+}
+
+module_init(asm9260_serial_init);
+module_exit(asm9260_serial_exit);
+
+MODULE_DESCRIPTION("ASM9260 serial port driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:" DRIVER_NAME);
diff --git a/include/uapi/linux/serial_core.h b/include/uapi/linux/serial_core.h
index 5820269..ed68009 100644
--- a/include/uapi/linux/serial_core.h
+++ b/include/uapi/linux/serial_core.h
@@ -244,4 +244,6 @@
 /* SC16IS74xx */
 #define PORT_SC16IS7XX   108
 
+/* Alpscale ASM9260 */
+#define PORT_ASM9260	109
 #endif /* _UAPILINUX_SERIAL_CORE_H */
-- 
1.9.1

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

* [PATCH 1/7] ARM: add mach-asm9260
  2014-09-13 22:13 ` [PATCH 1/7] ARM: add mach-asm9260 Oleksij Rempel
@ 2014-09-14  7:12   ` Jason Cooper
  2014-09-14  7:45     ` Oleksij Rempel
  0 siblings, 1 reply; 23+ messages in thread
From: Jason Cooper @ 2014-09-14  7:12 UTC (permalink / raw)
  To: linux-arm-kernel

On Sun, Sep 14, 2014 at 12:13:22AM +0200, Oleksij Rempel wrote:

Could you please add a description of the SoC?  Perhaps a link to
documentation, or at least a slick sheet?  Also, are there any products
on the market with this SoC, which ones?

thx,

Jason.

> Signed-off-by: Oleksij Rempel <linux@rempel-privat.de>
> ---
>  arch/arm/Kconfig                    | 16 ++++++++
>  arch/arm/Makefile                   |  1 +
>  arch/arm/mach-asm9260/Kconfig       | 66 +++++++++++++++++++++++++++++++
>  arch/arm/mach-asm9260/Makefile      | 11 ++++++
>  arch/arm/mach-asm9260/Makefile.boot |  2 +
>  arch/arm/mach-asm9260/core.c        | 77 +++++++++++++++++++++++++++++++++++++
>  6 files changed, 173 insertions(+)
>  create mode 100644 arch/arm/mach-asm9260/Kconfig
>  create mode 100644 arch/arm/mach-asm9260/Makefile
>  create mode 100644 arch/arm/mach-asm9260/Makefile.boot
>  create mode 100644 arch/arm/mach-asm9260/core.c
> 
> diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
> index 245058b..fb56189 100644
> --- a/arch/arm/Kconfig
> +++ b/arch/arm/Kconfig
> @@ -373,6 +373,20 @@ config ARCH_AT91
>  	  This enables support for systems based on Atmel
>  	  AT91RM9200 and AT91SAM9* processors.
>  
> +config MACH_ASM9260
> +	bool "Alpscale ASM9260"
> +	select ARCH_REQUIRE_GPIOLIB
> +	select COMMON_CLK
> +	select IRQ_DOMAIN
> +	select SPARSE_IRQ
> +	select MULTI_IRQ_HANDLER
> +	select GENERIC_IRQ_CHIP
> +	select GENERIC_CLOCKEVENTS
> +	select CLKSRC_MMIO
> +	select CPU_ARM926T
> +	help
> +	  Support for Alpscale ASM9260 based platform.
> +
>  config ARCH_CLPS711X
>  	bool "Cirrus Logic CLPS711x/EP721x/EP731x-based"
>  	select ARCH_REQUIRE_GPIOLIB
> @@ -915,6 +929,8 @@ source "arch/arm/mach-mvebu/Kconfig"
>  
>  source "arch/arm/mach-at91/Kconfig"
>  
> +source "arch/arm/mach-asm9260/Kconfig"
> +
>  source "arch/arm/mach-axxia/Kconfig"
>  
>  source "arch/arm/mach-bcm/Kconfig"
> diff --git a/arch/arm/Makefile b/arch/arm/Makefile
> index 6721fab..c383d02 100644
> --- a/arch/arm/Makefile
> +++ b/arch/arm/Makefile
> @@ -143,6 +143,7 @@ textofs-$(CONFIG_ARCH_AXXIA) := 0x00308000
>  # Machine directory name.  This list is sorted alphanumerically
>  # by CONFIG_* macro name.
>  machine-$(CONFIG_ARCH_AT91)		+= at91
> +machine-$(CONFIG_MACH_ASM9260)		+= asm9260
>  machine-$(CONFIG_ARCH_AXXIA)		+= axxia
>  machine-$(CONFIG_ARCH_BCM)		+= bcm
>  machine-$(CONFIG_ARCH_BERLIN)		+= berlin
> diff --git a/arch/arm/mach-asm9260/Kconfig b/arch/arm/mach-asm9260/Kconfig
> new file mode 100644
> index 0000000..f7240d8
> --- /dev/null
> +++ b/arch/arm/mach-asm9260/Kconfig
> @@ -0,0 +1,66 @@
> +if MACH_ASM9260
> +
> +menu "ASM9260T EVK Uart Enable"
> +
> +config ENABLE_UART0
> +	bool "Enable UART0"
> +	depends on SERIAL_ASM9260
> +	default n
> +
> +config ENABLE_UART1
> +	bool "Enable UART1"
> +	depends on SERIAL_ASM9260
> +	default n
> +
> +config ENABLE_UART2
> +	bool "Enable UART2"
> +	depends on SERIAL_ASM9260
> +	default n
> +
> +
> +config ENABLE_UART3
> +	bool "Enable UART3"
> +	depends on SERIAL_ASM9260
> +	default n
> +
> +
> +config ENABLE_UART4
> +	bool "Enable UART4"
> +	depends on SERIAL_ASM9260
> +	default n
> +
> +
> +config ENABLE_UART5
> +	bool "Enable UART5"
> +	depends on SERIAL_ASM9260
> +	default n
> +
> +
> +config ENABLE_UART6
> +	bool "Enable UART6"
> +	depends on SERIAL_ASM9260
> +	default n
> +
> +
> +config ENABLE_UART7
> +	bool "Enable UART7"
> +	depends on SERIAL_ASM9260
> +	default n
> +
> +
> +config ENABLE_UART8
> +	bool "Enable UART8"
> +	depends on SERIAL_ASM9260
> +	default n
> +
> +
> +config ENABLE_UART9
> +	bool "Enable UART9"
> +	depends on SERIAL_ASM9260
> +	default n
> +
> +endmenu
> +
> +
> +endif
> +
> diff --git a/arch/arm/mach-asm9260/Makefile b/arch/arm/mach-asm9260/Makefile
> new file mode 100644
> index 0000000..4bd8ebd
> --- /dev/null
> +++ b/arch/arm/mach-asm9260/Makefile
> @@ -0,0 +1,11 @@
> +#
> +# Makefile for the linux kernel.
> +#
> +
> +# Object file lists.
> +
> +obj-y			:= core.o
> +obj-m			:=
> +obj-n			:=
> +obj-			:=
> +
> diff --git a/arch/arm/mach-asm9260/Makefile.boot b/arch/arm/mach-asm9260/Makefile.boot
> new file mode 100644
> index 0000000..c57b3b4
> --- /dev/null
> +++ b/arch/arm/mach-asm9260/Makefile.boot
> @@ -0,0 +1,2 @@
> +zreladdr-y	:= 0x20008000
> +
> diff --git a/arch/arm/mach-asm9260/core.c b/arch/arm/mach-asm9260/core.c
> new file mode 100644
> index 0000000..eee7a9d
> --- /dev/null
> +++ b/arch/arm/mach-asm9260/core.c
> @@ -0,0 +1,77 @@
> +/*
> + * Copyright (C) 2014 Oleksij Rempel <linux@rempel-privat.de>
> + *  Co-author: Du Huanpeng <u74147@gmail.com>
> + * map_desc based on:
> + *  linux/arch/arm/mach-asm9260/core.c
> + *  Copyright (C) 2011-2014 Alpscale
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License along
> + * with this program; if not, write to the Free Software Foundation, Inc.,
> + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
> + */
> +
> +#include <linux/of_platform.h>
> +#include <asm/mach/arch.h>
> +#include <asm/mach/map.h>
> +
> +static struct map_desc asm9260_io_desc[] __initdata = {
> +	{	/* IO space */
> +		.virtual	= (unsigned long)0xf0000000,
> +		.pfn		= __phys_to_pfn(0x80000000),
> +		.length		= 0x00800000,
> +		.type		= MT_DEVICE
> +	},
> +	{	/* LCD IO space	*/
> +		.virtual	= (unsigned long)0xf0a00000,
> +		.pfn		= __phys_to_pfn(0x80800000),
> +		.length		= 0x00009000,
> +		.type		= MT_DEVICE
> +	},
> +	{	/* GPIO IO space */
> +		.virtual	= (unsigned long)0xf0800000,
> +		.pfn		= __phys_to_pfn(0x50000000),
> +		.length		= 0x00100000,
> +		.type		= MT_DEVICE
> +	},
> +	{	/* SRAM space Cacheable */
> +		.virtual	= (unsigned long)0xd0000000,
> +		.pfn		= __phys_to_pfn(0x40000000),
> +		.length		= 0x00100000,
> +#ifdef CONFIG_SRAM_MEM_CACHED
> +		.type		= MT_MEMORY
> +#else
> +		.type		= MT_DEVICE
> +#endif
> +	},
> +};
> +
> +static void __init asm9260_map_io(void)
> +{
> +	iotable_init(asm9260_io_desc, ARRAY_SIZE(asm9260_io_desc));
> +}
> +
> +static void __init asm9260_init(void)
> +{
> +	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
> +}
> +
> +static const char * const asm9260_dt_board_compat[] __initconst = {
> +	"alpscale,asm9260",
> +	NULL
> +};
> +
> +DT_MACHINE_START(ASM9260, "Alpscale ASM9260 (Device Tree Support)")
> +	.map_io		= asm9260_map_io,
> +	.init_machine	= asm9260_init,
> +	.dt_compat	= asm9260_dt_board_compat,
> +MACHINE_END
> -- 
> 1.9.1
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH 6/7] irqchip: add irq-asm9260 driver
  2014-09-13 22:13 ` [PATCH 6/7] irqchip: add irq-asm9260 driver Oleksij Rempel
@ 2014-09-14  7:37   ` Jason Cooper
  2014-09-15  5:52     ` Oleksij Rempel
  0 siblings, 1 reply; 23+ messages in thread
From: Jason Cooper @ 2014-09-14  7:37 UTC (permalink / raw)
  To: linux-arm-kernel

Oleksij,

On Sun, Sep 14, 2014 at 12:13:27AM +0200, Oleksij Rempel wrote:
> Signed-off-by: Oleksij Rempel <linux@rempel-privat.de>
> ---
>  drivers/irqchip/Makefile      |   1 +
>  drivers/irqchip/irq-asm9260.c | 237 ++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 238 insertions(+)
>  create mode 100644 drivers/irqchip/irq-asm9260.c

Please don't forget to Cc me, I'm helping tglx with irqchip-related
stuff.

> diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
> index 62a13e5..3400ec8 100644
> --- a/drivers/irqchip/Makefile
> +++ b/drivers/irqchip/Makefile
> @@ -30,3 +30,4 @@ obj-$(CONFIG_XTENSA)			+= irq-xtensa-pic.o
>  obj-$(CONFIG_XTENSA_MX)			+= irq-xtensa-mx.o
>  obj-$(CONFIG_IRQ_CROSSBAR)		+= irq-crossbar.o
>  obj-$(CONFIG_BRCMSTB_L2_IRQ)		+= irq-brcmstb-l2.o
> +obj-$(CONFIG_MACH_ASM9260)		+= irq-asm9260.o
> diff --git a/drivers/irqchip/irq-asm9260.c b/drivers/irqchip/irq-asm9260.c
> new file mode 100644
> index 0000000..62e0607
> --- /dev/null
> +++ b/drivers/irqchip/irq-asm9260.c
> @@ -0,0 +1,237 @@
> +/*
> + * 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.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License along
> + * with this program; if not, write to the Free Software Foundation, Inc.,
> + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/init.h>
> +#include <linux/irq.h>
> +#include <linux/irqdomain.h>
> +#include <linux/io.h>
> +#include <linux/of.h>
> +#include <linux/of_address.h>
> +#include <linux/of_irq.h>
> +#include <asm/exception.h>
> +#include <linux/bitops.h>
> +#include <linux/delay.h>
> +
> +#include "irqchip.h"
> +
> +#define SET_REG 4
> +#define CLR_REG 8
> +
> +#define 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 HW_ICOLL_VECTOR_ADDR; IRQ exception at 0xffff0018
> + */
> +
> +#define HW_ICOLL_LEVELACK			0x0010
> +/* 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 BM_LEVELn(nr)				BIT(nr)
> +
> +#define HW_ICOLL_CTRL				0x0020
> +/* BM_CTRL_SFTRST and BM_CTRL_CLKGATE are not available on asm9260. */
> +#define BM_CTRL_SFTRST				BIT(31)
> +#define BM_CTRL_CLKGATE				BIT(30)
> +#define BM_CTRL_NO_NESTING			BIT(19)
> +/* disable interrupt level nesting */
> +#define BM_CTRL_ARM_RSE_MODE			BIT(18)
> +/* 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 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 HW_ICOLL_VECTOR register.
> + * 0 - Must Write to Vector register to go in-service.
> + * 1 - Go in-service as a read side effect
> + */
> +#define BM_CTRL_IRQ_ENABLE			BIT(16)
> +
> +#define 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 HW_ICOLL_VECTOR.
> + */
> +
> +#define HW_ICOLL_RAW0				0x0040
> +#define HW_ICOLL_RAW1				0x0050
> +/* This register 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.
> + */

wrt all of the above comment, please follow the kernel coding style:

  /*
   * Begin multi-line text.
   */

Also, please place the comment _above_ the code it is referring to.

> +
> +#define	HW_ICOLL_INTERRUPT0			0x0060
> +#define	HW_ICOLL_INTERRUPTn(n)			(0x0060 + ((n) >> 2) * 0x10)
> +#define	HW_ICOLL_INTERRUPTn_SET(n)		(HW_ICOLL_INTERRUPTn(n) \
> +		+ SET_REG)
> +#define	HW_ICOLL_INTERRUPTn_CLR(n)		(HW_ICOLL_INTERRUPTn(n) \
> +		+ CLR_REG)
> +#define BM_INT_PRIORITY_MASK			0x3
> +/* WARNING: Modifying the priority of an enabled interrupt may result in
> + * undefined behavior. */

multi-line comment style.

> +#define BM_INT_ENABLE				BIT(2)
> +#define BM_INT_SOFTIRQ				BIT(3)
> +
> +#define BM_ICOLL_INTERRUPTn_SHIFT(n)		(((n) & 0x3) << 3)
> +#define BM_ICOLL_INTERRUPTn_ENABLE(n)		(1 << (2 + \
> +			BM_ICOLL_INTERRUPTn_SHIFT(n)))
> +
> +#define HW_ICOLL_VBASE				0x0160
> +/* bits 31:2
> + * This bitfield holds the upper 30 bits of the base address of the vector
> + * table. */
> +
> +#define HW_ICOLL_CLEAR0				0x01d0
> +#define	HW_ICOLL_CLEAR1				0x01e0
> +#define HW_ICOLL_CLEARn(n)			(0x01d0 + ((n >> 5) * 0x10) \
> +							+ SET_REG)
> +#define BM_CLEAR_BIT(n)				BIT(n & 0x1f)
> +
> +#define HW_ICOLL_UNDEF_VECTOR			0x01f0
> +/* Scratchpad */
> +
> +#define ICOLL_NUM_IRQS		64
> +
> +static void __iomem *icoll_base;
> +static struct irq_domain *icoll_domain;
> +static int use_cached_level = 1;
> +static u8 level_cache[ICOLL_NUM_IRQS];
> +
> +static unsigned int irq_get_level(struct irq_data *d)
> +{
> +	unsigned int tmp;
> +
> +	if (use_cached_level)
> +		return level_cache[d->hwirq];
> +
> +	tmp = readl_relaxed(icoll_base + HW_ICOLL_INTERRUPTn_SET(d->hwirq));
> +	return (tmp >> BM_ICOLL_INTERRUPTn_SHIFT(d->hwirq)) & 0x3;
> +}
> +
> +static void irq_set_level(int hwirq, int level)
> +{
> +	if (unlikely(level < 0 || level > 3)) {
> +		pr_err("%s Wrong level (%i) for irq (%i)!", __func__, level,
> +				hwirq);
> +		return;
> +	}
> +	if (use_cached_level)
> +		level_cache[hwirq] = level;
> +
> +	writel_relaxed(level << BM_ICOLL_INTERRUPTn_SHIFT(hwirq),
> +			icoll_base + HW_ICOLL_INTERRUPTn(hwirq));
> +}
> +
> +static void icoll_ack_irq(struct irq_data *d)
> +{
> +	readl_relaxed(icoll_base + HW_ICOLL_VECTOR);
> +}
> +
> +static void icoll_mask_irq(struct irq_data *d)
> +{
> +	writel_relaxed(BM_ICOLL_INTERRUPTn_ENABLE(d->hwirq),
> +			icoll_base + HW_ICOLL_INTERRUPTn_CLR(d->hwirq));
> +}
> +
> +static void icoll_unmask_irq(struct irq_data *d)
> +{
> +	u32 level;
> +
> +	writel_relaxed(BM_CLEAR_BIT(d->hwirq),
> +			icoll_base + HW_ICOLL_CLEARn(d->hwirq));
> +
> +	level = irq_get_level(d);
> +	writel_relaxed(BM_LEVELn(level), icoll_base + HW_ICOLL_LEVELACK);
> +
> +	writel_relaxed(BM_ICOLL_INTERRUPTn_ENABLE(d->hwirq),
> +			icoll_base + HW_ICOLL_INTERRUPTn_SET(d->hwirq));

mutex?

> +}
> +
> +static struct irq_chip asm9260_icoll_chip = {
> +	.irq_ack = icoll_ack_irq,
> +	.irq_mask = icoll_mask_irq,
> +	.irq_unmask = icoll_unmask_irq,
> +};
> +
> +asmlinkage void __exception_irq_entry icoll_handle_irq(struct pt_regs *regs)
> +{
> +	u32 irqnr;
> +
> +	irqnr = irq_find_mapping(icoll_domain,
> +			readl_relaxed(icoll_base + HW_ICOLL_STAT_OFFSET));

Please check the return value of irq_find_mapping()

> +
> +	handle_IRQ(irqnr, regs);

We're in the progress of converting to handle_domain_irq(), please take
a look at the series in

  git://git.infradead.org/users/jcooper/linux.git irqchip/handle_domain

> +}
> +
> +static int icoll_irq_domain_map(struct irq_domain *d, unsigned int virq,
> +				irq_hw_number_t hw)
> +{
> +	irq_set_chip_and_handler(virq, &asm9260_icoll_chip, handle_level_irq);
> +	set_irq_flags(virq, IRQF_VALID);
> +
> +	return 0;
> +}
> +
> +static struct irq_domain_ops icoll_irq_domain_ops = {
> +	.map = icoll_irq_domain_map,
> +	.xlate = irq_domain_xlate_onecell,
> +};
> +
> +static int __init icoll_of_init(struct device_node *np,
> +			  struct device_node *interrupt_parent)
> +{
> +	struct resource res;
> +	int i;
> +
> +	of_address_to_resource(np, 0, &res);

Please check the return value of of_address_to_resource().

> +	if (!request_mem_region(res.start, resource_size(&res), np->name))
> +		panic("%s: unable to request mem region", np->name);
> +
> +	icoll_base = ioremap_nocache(res.start, resource_size(&res));
> +	if (!icoll_base)
> +		panic("%s: unable to map resource", np->name);
> +
> +	/* enable IRQ controller */
> +	writel_relaxed(BM_CTRL_ARM_RSE_MODE | BM_CTRL_IRQ_ENABLE,
> +			icoll_base + HW_ICOLL_CTRL);
> +
> +	/* This ICOLL has no reset option. So, set all priorities
> +	 * manually to 0. */
> +	for (i = 0; i < 16 * 0x10; i += 0x10)
> +		writel(0, icoll_base + HW_ICOLL_INTERRUPT0 + i);
> +
> +	/* set timer 0 priority level high. TODO: should be done by DT  */
> +	irq_set_level(29, 3);
> +
> +	icoll_domain = irq_domain_add_linear(np, ICOLL_NUM_IRQS,
> +					     &icoll_irq_domain_ops, NULL);

Please check return value of irq_domain_add_linear().

thx,

Jason.

> +
> +	irq_set_default_host(icoll_domain);
> +
> +	set_handle_irq(icoll_handle_irq);
> +
> +	return icoll_domain ? 0 : -ENODEV;
> +}
> +IRQCHIP_DECLARE(asm9260, "alpscale,asm9260-icall", icoll_of_init);
> -- 
> 1.9.1
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH 1/7] ARM: add mach-asm9260
  2014-09-14  7:12   ` Jason Cooper
@ 2014-09-14  7:45     ` Oleksij Rempel
  2014-09-14  9:05       ` Jason Cooper
  0 siblings, 1 reply; 23+ messages in thread
From: Oleksij Rempel @ 2014-09-14  7:45 UTC (permalink / raw)
  To: linux-arm-kernel

Am 14.09.2014 um 09:12 schrieb Jason Cooper:
> On Sun, Sep 14, 2014 at 12:13:22AM +0200, Oleksij Rempel wrote:
> 
> Could you please add a description of the SoC?  Perhaps a link to
> documentation, or at least a slick sheet?  Also, are there any products
> on the market with this SoC, which ones?
> 
> thx,

Hi,

it is low cost (?) SoC targeted for market in China and India which
trying to "replace" 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


> 
> Jason.
> 
>> Signed-off-by: Oleksij Rempel <linux@rempel-privat.de>
>> ---
>>  arch/arm/Kconfig                    | 16 ++++++++
>>  arch/arm/Makefile                   |  1 +
>>  arch/arm/mach-asm9260/Kconfig       | 66 +++++++++++++++++++++++++++++++
>>  arch/arm/mach-asm9260/Makefile      | 11 ++++++
>>  arch/arm/mach-asm9260/Makefile.boot |  2 +
>>  arch/arm/mach-asm9260/core.c        | 77 +++++++++++++++++++++++++++++++++++++
>>  6 files changed, 173 insertions(+)
>>  create mode 100644 arch/arm/mach-asm9260/Kconfig
>>  create mode 100644 arch/arm/mach-asm9260/Makefile
>>  create mode 100644 arch/arm/mach-asm9260/Makefile.boot
>>  create mode 100644 arch/arm/mach-asm9260/core.c
>>
>> diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
>> index 245058b..fb56189 100644
>> --- a/arch/arm/Kconfig
>> +++ b/arch/arm/Kconfig
>> @@ -373,6 +373,20 @@ config ARCH_AT91
>>  	  This enables support for systems based on Atmel
>>  	  AT91RM9200 and AT91SAM9* processors.
>>  
>> +config MACH_ASM9260
>> +	bool "Alpscale ASM9260"
>> +	select ARCH_REQUIRE_GPIOLIB
>> +	select COMMON_CLK
>> +	select IRQ_DOMAIN
>> +	select SPARSE_IRQ
>> +	select MULTI_IRQ_HANDLER
>> +	select GENERIC_IRQ_CHIP
>> +	select GENERIC_CLOCKEVENTS
>> +	select CLKSRC_MMIO
>> +	select CPU_ARM926T
>> +	help
>> +	  Support for Alpscale ASM9260 based platform.
>> +
>>  config ARCH_CLPS711X
>>  	bool "Cirrus Logic CLPS711x/EP721x/EP731x-based"
>>  	select ARCH_REQUIRE_GPIOLIB
>> @@ -915,6 +929,8 @@ source "arch/arm/mach-mvebu/Kconfig"
>>  
>>  source "arch/arm/mach-at91/Kconfig"
>>  
>> +source "arch/arm/mach-asm9260/Kconfig"
>> +
>>  source "arch/arm/mach-axxia/Kconfig"
>>  
>>  source "arch/arm/mach-bcm/Kconfig"
>> diff --git a/arch/arm/Makefile b/arch/arm/Makefile
>> index 6721fab..c383d02 100644
>> --- a/arch/arm/Makefile
>> +++ b/arch/arm/Makefile
>> @@ -143,6 +143,7 @@ textofs-$(CONFIG_ARCH_AXXIA) := 0x00308000
>>  # Machine directory name.  This list is sorted alphanumerically
>>  # by CONFIG_* macro name.
>>  machine-$(CONFIG_ARCH_AT91)		+= at91
>> +machine-$(CONFIG_MACH_ASM9260)		+= asm9260
>>  machine-$(CONFIG_ARCH_AXXIA)		+= axxia
>>  machine-$(CONFIG_ARCH_BCM)		+= bcm
>>  machine-$(CONFIG_ARCH_BERLIN)		+= berlin
>> diff --git a/arch/arm/mach-asm9260/Kconfig b/arch/arm/mach-asm9260/Kconfig
>> new file mode 100644
>> index 0000000..f7240d8
>> --- /dev/null
>> +++ b/arch/arm/mach-asm9260/Kconfig
>> @@ -0,0 +1,66 @@
>> +if MACH_ASM9260
>> +
>> +menu "ASM9260T EVK Uart Enable"
>> +
>> +config ENABLE_UART0
>> +	bool "Enable UART0"
>> +	depends on SERIAL_ASM9260
>> +	default n
>> +
>> +config ENABLE_UART1
>> +	bool "Enable UART1"
>> +	depends on SERIAL_ASM9260
>> +	default n
>> +
>> +config ENABLE_UART2
>> +	bool "Enable UART2"
>> +	depends on SERIAL_ASM9260
>> +	default n
>> +
>> +
>> +config ENABLE_UART3
>> +	bool "Enable UART3"
>> +	depends on SERIAL_ASM9260
>> +	default n
>> +
>> +
>> +config ENABLE_UART4
>> +	bool "Enable UART4"
>> +	depends on SERIAL_ASM9260
>> +	default n
>> +
>> +
>> +config ENABLE_UART5
>> +	bool "Enable UART5"
>> +	depends on SERIAL_ASM9260
>> +	default n
>> +
>> +
>> +config ENABLE_UART6
>> +	bool "Enable UART6"
>> +	depends on SERIAL_ASM9260
>> +	default n
>> +
>> +
>> +config ENABLE_UART7
>> +	bool "Enable UART7"
>> +	depends on SERIAL_ASM9260
>> +	default n
>> +
>> +
>> +config ENABLE_UART8
>> +	bool "Enable UART8"
>> +	depends on SERIAL_ASM9260
>> +	default n
>> +
>> +
>> +config ENABLE_UART9
>> +	bool "Enable UART9"
>> +	depends on SERIAL_ASM9260
>> +	default n
>> +
>> +endmenu
>> +
>> +
>> +endif
>> +
>> diff --git a/arch/arm/mach-asm9260/Makefile b/arch/arm/mach-asm9260/Makefile
>> new file mode 100644
>> index 0000000..4bd8ebd
>> --- /dev/null
>> +++ b/arch/arm/mach-asm9260/Makefile
>> @@ -0,0 +1,11 @@
>> +#
>> +# Makefile for the linux kernel.
>> +#
>> +
>> +# Object file lists.
>> +
>> +obj-y			:= core.o
>> +obj-m			:=
>> +obj-n			:=
>> +obj-			:=
>> +
>> diff --git a/arch/arm/mach-asm9260/Makefile.boot b/arch/arm/mach-asm9260/Makefile.boot
>> new file mode 100644
>> index 0000000..c57b3b4
>> --- /dev/null
>> +++ b/arch/arm/mach-asm9260/Makefile.boot
>> @@ -0,0 +1,2 @@
>> +zreladdr-y	:= 0x20008000
>> +
>> diff --git a/arch/arm/mach-asm9260/core.c b/arch/arm/mach-asm9260/core.c
>> new file mode 100644
>> index 0000000..eee7a9d
>> --- /dev/null
>> +++ b/arch/arm/mach-asm9260/core.c
>> @@ -0,0 +1,77 @@
>> +/*
>> + * Copyright (C) 2014 Oleksij Rempel <linux@rempel-privat.de>
>> + *  Co-author: Du Huanpeng <u74147@gmail.com>
>> + * map_desc based on:
>> + *  linux/arch/arm/mach-asm9260/core.c
>> + *  Copyright (C) 2011-2014 Alpscale
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License as published by
>> + * the Free Software Foundation; either version 2 of the License, or
>> + * (at your option) any later version.
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> + * GNU General Public License for more details.
>> + *
>> + * You should have received a copy of the GNU General Public License along
>> + * with this program; if not, write to the Free Software Foundation, Inc.,
>> + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
>> + */
>> +
>> +#include <linux/of_platform.h>
>> +#include <asm/mach/arch.h>
>> +#include <asm/mach/map.h>
>> +
>> +static struct map_desc asm9260_io_desc[] __initdata = {
>> +	{	/* IO space */
>> +		.virtual	= (unsigned long)0xf0000000,
>> +		.pfn		= __phys_to_pfn(0x80000000),
>> +		.length		= 0x00800000,
>> +		.type		= MT_DEVICE
>> +	},
>> +	{	/* LCD IO space	*/
>> +		.virtual	= (unsigned long)0xf0a00000,
>> +		.pfn		= __phys_to_pfn(0x80800000),
>> +		.length		= 0x00009000,
>> +		.type		= MT_DEVICE
>> +	},
>> +	{	/* GPIO IO space */
>> +		.virtual	= (unsigned long)0xf0800000,
>> +		.pfn		= __phys_to_pfn(0x50000000),
>> +		.length		= 0x00100000,
>> +		.type		= MT_DEVICE
>> +	},
>> +	{	/* SRAM space Cacheable */
>> +		.virtual	= (unsigned long)0xd0000000,
>> +		.pfn		= __phys_to_pfn(0x40000000),
>> +		.length		= 0x00100000,
>> +#ifdef CONFIG_SRAM_MEM_CACHED
>> +		.type		= MT_MEMORY
>> +#else
>> +		.type		= MT_DEVICE
>> +#endif
>> +	},
>> +};
>> +
>> +static void __init asm9260_map_io(void)
>> +{
>> +	iotable_init(asm9260_io_desc, ARRAY_SIZE(asm9260_io_desc));
>> +}
>> +
>> +static void __init asm9260_init(void)
>> +{
>> +	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
>> +}
>> +
>> +static const char * const asm9260_dt_board_compat[] __initconst = {
>> +	"alpscale,asm9260",
>> +	NULL
>> +};
>> +
>> +DT_MACHINE_START(ASM9260, "Alpscale ASM9260 (Device Tree Support)")
>> +	.map_io		= asm9260_map_io,
>> +	.init_machine	= asm9260_init,
>> +	.dt_compat	= asm9260_dt_board_compat,
>> +MACHINE_END
>> -- 
>> 1.9.1
>>
>>
>> _______________________________________________
>> linux-arm-kernel mailing list
>> linux-arm-kernel at lists.infradead.org
>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel


-- 
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/20140914/e58968e1/attachment.sig>

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

* [PATCH 1/7] ARM: add mach-asm9260
  2014-09-14  7:45     ` Oleksij Rempel
@ 2014-09-14  9:05       ` Jason Cooper
  2014-09-17 13:46         ` Alexandre Belloni
  0 siblings, 1 reply; 23+ messages in thread
From: Jason Cooper @ 2014-09-14  9:05 UTC (permalink / raw)
  To: linux-arm-kernel

On Sun, Sep 14, 2014 at 09:45:04AM +0200, Oleksij Rempel wrote:
> Am 14.09.2014 um 09:12 schrieb Jason Cooper:
> > On Sun, Sep 14, 2014 at 12:13:22AM +0200, Oleksij Rempel wrote:
> > 
> > Could you please add a description of the SoC?  Perhaps a link to
> > documentation, or at least a slick sheet?  Also, are there any products
> > on the market with this SoC, which ones?
> > 
> > thx,
> 
> Hi,
> 
> it is low cost (?) SoC targeted for market in China and India which
> trying to "replace" 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

Ok, please include this information is the commit log of the next
version of this patch.

thx,

Jason.

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

* [PATCH 6/7] irqchip: add irq-asm9260 driver
  2014-09-14  7:37   ` Jason Cooper
@ 2014-09-15  5:52     ` Oleksij Rempel
  2014-09-17 12:59       ` Jason Cooper
  0 siblings, 1 reply; 23+ messages in thread
From: Oleksij Rempel @ 2014-09-15  5:52 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Jason,

thx for review.
How about irq priority system which provide this controller, do it make
sense to implement it? Or it es better to allow kernel make needed decision?

Am 14.09.2014 um 09:37 schrieb Jason Cooper:
> Oleksij,
> 
> On Sun, Sep 14, 2014 at 12:13:27AM +0200, Oleksij Rempel wrote:
>> Signed-off-by: Oleksij Rempel <linux@rempel-privat.de>
>> ---
>>  drivers/irqchip/Makefile      |   1 +
>>  drivers/irqchip/irq-asm9260.c | 237 ++++++++++++++++++++++++++++++++++++++++++
>>  2 files changed, 238 insertions(+)
>>  create mode 100644 drivers/irqchip/irq-asm9260.c
> 
> Please don't forget to Cc me, I'm helping tglx with irqchip-related
> stuff.
> 
>> diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
>> index 62a13e5..3400ec8 100644
>> --- a/drivers/irqchip/Makefile
>> +++ b/drivers/irqchip/Makefile
>> @@ -30,3 +30,4 @@ obj-$(CONFIG_XTENSA)			+= irq-xtensa-pic.o
>>  obj-$(CONFIG_XTENSA_MX)			+= irq-xtensa-mx.o
>>  obj-$(CONFIG_IRQ_CROSSBAR)		+= irq-crossbar.o
>>  obj-$(CONFIG_BRCMSTB_L2_IRQ)		+= irq-brcmstb-l2.o
>> +obj-$(CONFIG_MACH_ASM9260)		+= irq-asm9260.o
>> diff --git a/drivers/irqchip/irq-asm9260.c b/drivers/irqchip/irq-asm9260.c
>> new file mode 100644
>> index 0000000..62e0607
>> --- /dev/null
>> +++ b/drivers/irqchip/irq-asm9260.c
>> @@ -0,0 +1,237 @@
>> +/*
>> + * 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.
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> + * GNU General Public License for more details.
>> + *
>> + * You should have received a copy of the GNU General Public License along
>> + * with this program; if not, write to the Free Software Foundation, Inc.,
>> + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
>> + */
>> +
>> +#include <linux/kernel.h>
>> +#include <linux/init.h>
>> +#include <linux/irq.h>
>> +#include <linux/irqdomain.h>
>> +#include <linux/io.h>
>> +#include <linux/of.h>
>> +#include <linux/of_address.h>
>> +#include <linux/of_irq.h>
>> +#include <asm/exception.h>
>> +#include <linux/bitops.h>
>> +#include <linux/delay.h>
>> +
>> +#include "irqchip.h"
>> +
>> +#define SET_REG 4
>> +#define CLR_REG 8
>> +
>> +#define 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 HW_ICOLL_VECTOR_ADDR; IRQ exception at 0xffff0018
>> + */
>> +
>> +#define HW_ICOLL_LEVELACK			0x0010
>> +/* 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 BM_LEVELn(nr)				BIT(nr)
>> +
>> +#define HW_ICOLL_CTRL				0x0020
>> +/* BM_CTRL_SFTRST and BM_CTRL_CLKGATE are not available on asm9260. */
>> +#define BM_CTRL_SFTRST				BIT(31)
>> +#define BM_CTRL_CLKGATE				BIT(30)
>> +#define BM_CTRL_NO_NESTING			BIT(19)
>> +/* disable interrupt level nesting */
>> +#define BM_CTRL_ARM_RSE_MODE			BIT(18)
>> +/* 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 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 HW_ICOLL_VECTOR register.
>> + * 0 - Must Write to Vector register to go in-service.
>> + * 1 - Go in-service as a read side effect
>> + */
>> +#define BM_CTRL_IRQ_ENABLE			BIT(16)
>> +
>> +#define 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 HW_ICOLL_VECTOR.
>> + */
>> +
>> +#define HW_ICOLL_RAW0				0x0040
>> +#define HW_ICOLL_RAW1				0x0050
>> +/* This register 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.
>> + */
> 
> wrt all of the above comment, please follow the kernel coding style:
> 
>   /*
>    * Begin multi-line text.
>    */
> 
> Also, please place the comment _above_ the code it is referring to.
> 
>> +
>> +#define	HW_ICOLL_INTERRUPT0			0x0060
>> +#define	HW_ICOLL_INTERRUPTn(n)			(0x0060 + ((n) >> 2) * 0x10)
>> +#define	HW_ICOLL_INTERRUPTn_SET(n)		(HW_ICOLL_INTERRUPTn(n) \
>> +		+ SET_REG)
>> +#define	HW_ICOLL_INTERRUPTn_CLR(n)		(HW_ICOLL_INTERRUPTn(n) \
>> +		+ CLR_REG)
>> +#define BM_INT_PRIORITY_MASK			0x3
>> +/* WARNING: Modifying the priority of an enabled interrupt may result in
>> + * undefined behavior. */
> 
> multi-line comment style.
> 
>> +#define BM_INT_ENABLE				BIT(2)
>> +#define BM_INT_SOFTIRQ				BIT(3)
>> +
>> +#define BM_ICOLL_INTERRUPTn_SHIFT(n)		(((n) & 0x3) << 3)
>> +#define BM_ICOLL_INTERRUPTn_ENABLE(n)		(1 << (2 + \
>> +			BM_ICOLL_INTERRUPTn_SHIFT(n)))
>> +
>> +#define HW_ICOLL_VBASE				0x0160
>> +/* bits 31:2
>> + * This bitfield holds the upper 30 bits of the base address of the vector
>> + * table. */
>> +
>> +#define HW_ICOLL_CLEAR0				0x01d0
>> +#define	HW_ICOLL_CLEAR1				0x01e0
>> +#define HW_ICOLL_CLEARn(n)			(0x01d0 + ((n >> 5) * 0x10) \
>> +							+ SET_REG)
>> +#define BM_CLEAR_BIT(n)				BIT(n & 0x1f)
>> +
>> +#define HW_ICOLL_UNDEF_VECTOR			0x01f0
>> +/* Scratchpad */
>> +
>> +#define ICOLL_NUM_IRQS		64
>> +
>> +static void __iomem *icoll_base;
>> +static struct irq_domain *icoll_domain;
>> +static int use_cached_level = 1;
>> +static u8 level_cache[ICOLL_NUM_IRQS];
>> +
>> +static unsigned int irq_get_level(struct irq_data *d)
>> +{
>> +	unsigned int tmp;
>> +
>> +	if (use_cached_level)
>> +		return level_cache[d->hwirq];
>> +
>> +	tmp = readl_relaxed(icoll_base + HW_ICOLL_INTERRUPTn_SET(d->hwirq));
>> +	return (tmp >> BM_ICOLL_INTERRUPTn_SHIFT(d->hwirq)) & 0x3;
>> +}
>> +
>> +static void irq_set_level(int hwirq, int level)
>> +{
>> +	if (unlikely(level < 0 || level > 3)) {
>> +		pr_err("%s Wrong level (%i) for irq (%i)!", __func__, level,
>> +				hwirq);
>> +		return;
>> +	}
>> +	if (use_cached_level)
>> +		level_cache[hwirq] = level;
>> +
>> +	writel_relaxed(level << BM_ICOLL_INTERRUPTn_SHIFT(hwirq),
>> +			icoll_base + HW_ICOLL_INTERRUPTn(hwirq));
>> +}
>> +
>> +static void icoll_ack_irq(struct irq_data *d)
>> +{
>> +	readl_relaxed(icoll_base + HW_ICOLL_VECTOR);
>> +}
>> +
>> +static void icoll_mask_irq(struct irq_data *d)
>> +{
>> +	writel_relaxed(BM_ICOLL_INTERRUPTn_ENABLE(d->hwirq),
>> +			icoll_base + HW_ICOLL_INTERRUPTn_CLR(d->hwirq));
>> +}
>> +
>> +static void icoll_unmask_irq(struct irq_data *d)
>> +{
>> +	u32 level;
>> +
>> +	writel_relaxed(BM_CLEAR_BIT(d->hwirq),
>> +			icoll_base + HW_ICOLL_CLEARn(d->hwirq));
>> +
>> +	level = irq_get_level(d);
>> +	writel_relaxed(BM_LEVELn(level), icoll_base + HW_ICOLL_LEVELACK);
>> +
>> +	writel_relaxed(BM_ICOLL_INTERRUPTn_ENABLE(d->hwirq),
>> +			icoll_base + HW_ICOLL_INTERRUPTn_SET(d->hwirq));
> 
> mutex?
> 
>> +}
>> +
>> +static struct irq_chip asm9260_icoll_chip = {
>> +	.irq_ack = icoll_ack_irq,
>> +	.irq_mask = icoll_mask_irq,
>> +	.irq_unmask = icoll_unmask_irq,
>> +};
>> +
>> +asmlinkage void __exception_irq_entry icoll_handle_irq(struct pt_regs *regs)
>> +{
>> +	u32 irqnr;
>> +
>> +	irqnr = irq_find_mapping(icoll_domain,
>> +			readl_relaxed(icoll_base + HW_ICOLL_STAT_OFFSET));
> 
> Please check the return value of irq_find_mapping()
> 
>> +
>> +	handle_IRQ(irqnr, regs);
> 
> We're in the progress of converting to handle_domain_irq(), please take
> a look at the series in
> 
>   git://git.infradead.org/users/jcooper/linux.git irqchip/handle_domain
> 
>> +}
>> +
>> +static int icoll_irq_domain_map(struct irq_domain *d, unsigned int virq,
>> +				irq_hw_number_t hw)
>> +{
>> +	irq_set_chip_and_handler(virq, &asm9260_icoll_chip, handle_level_irq);
>> +	set_irq_flags(virq, IRQF_VALID);
>> +
>> +	return 0;
>> +}
>> +
>> +static struct irq_domain_ops icoll_irq_domain_ops = {
>> +	.map = icoll_irq_domain_map,
>> +	.xlate = irq_domain_xlate_onecell,
>> +};
>> +
>> +static int __init icoll_of_init(struct device_node *np,
>> +			  struct device_node *interrupt_parent)
>> +{
>> +	struct resource res;
>> +	int i;
>> +
>> +	of_address_to_resource(np, 0, &res);
> 
> Please check the return value of of_address_to_resource().
> 
>> +	if (!request_mem_region(res.start, resource_size(&res), np->name))
>> +		panic("%s: unable to request mem region", np->name);
>> +
>> +	icoll_base = ioremap_nocache(res.start, resource_size(&res));
>> +	if (!icoll_base)
>> +		panic("%s: unable to map resource", np->name);
>> +
>> +	/* enable IRQ controller */
>> +	writel_relaxed(BM_CTRL_ARM_RSE_MODE | BM_CTRL_IRQ_ENABLE,
>> +			icoll_base + HW_ICOLL_CTRL);
>> +
>> +	/* This ICOLL has no reset option. So, set all priorities
>> +	 * manually to 0. */
>> +	for (i = 0; i < 16 * 0x10; i += 0x10)
>> +		writel(0, icoll_base + HW_ICOLL_INTERRUPT0 + i);
>> +
>> +	/* set timer 0 priority level high. TODO: should be done by DT  */
>> +	irq_set_level(29, 3);
>> +
>> +	icoll_domain = irq_domain_add_linear(np, ICOLL_NUM_IRQS,
>> +					     &icoll_irq_domain_ops, NULL);
> 
> Please check return value of irq_domain_add_linear().
> 
> thx,
> 
> Jason.
> 
>> +
>> +	irq_set_default_host(icoll_domain);
>> +
>> +	set_handle_irq(icoll_handle_irq);
>> +
>> +	return icoll_domain ? 0 : -ENODEV;
>> +}
>> +IRQCHIP_DECLARE(asm9260, "alpscale,asm9260-icall", icoll_of_init);
>> -- 
>> 1.9.1
>>
>>
>> _______________________________________________
>> linux-arm-kernel mailing list
>> linux-arm-kernel at lists.infradead.org
>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel


-- 
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/20140915/2b51b1fa/attachment.sig>

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

* [PATCH 6/7] irqchip: add irq-asm9260 driver
  2014-09-15  5:52     ` Oleksij Rempel
@ 2014-09-17 12:59       ` Jason Cooper
  0 siblings, 0 replies; 23+ messages in thread
From: Jason Cooper @ 2014-09-17 12:59 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Sep 15, 2014 at 07:52:54AM +0200, Oleksij Rempel wrote:
> How about irq priority system which provide this controller, do it make
> sense to implement it? Or it es better to allow kernel make needed decision?

Let's keep it simple for now.  If you discover a problem down the road,
we can address it at the time.

thx,

Jason.

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

* [PATCH 1/7] ARM: add mach-asm9260
  2014-09-14  9:05       ` Jason Cooper
@ 2014-09-17 13:46         ` Alexandre Belloni
  2014-09-17 13:53           ` Nicolas Ferre
  0 siblings, 1 reply; 23+ messages in thread
From: Alexandre Belloni @ 2014-09-17 13:46 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

On 14/09/2014 at 05:05:45 -0400, Jason Cooper wrote :
> On Sun, Sep 14, 2014 at 09:45:04AM +0200, Oleksij Rempel wrote:
> > Am 14.09.2014 um 09:12 schrieb Jason Cooper:
> > > On Sun, Sep 14, 2014 at 12:13:22AM +0200, Oleksij Rempel wrote:
> > > 
> > > Could you please add a description of the SoC?  Perhaps a link to
> > > documentation, or at least a slick sheet?  Also, are there any products
> > > on the market with this SoC, which ones?
> > > 
> > > thx,
> > 
> > Hi,
> > 
> > it is low cost (?) SoC targeted for market in China and India which
> > trying to "replace" 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
> 
> Ok, please include this information is the commit log of the next
> version of this patch.
> 

I would also suggest to call it AlphaScale instead of Alpscale as it
allows to get more useful information when searching the web.

-- 
Alexandre Belloni, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com

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

* [PATCH 1/7] ARM: add mach-asm9260
  2014-09-17 13:46         ` Alexandre Belloni
@ 2014-09-17 13:53           ` Nicolas Ferre
  2014-09-18  6:29             ` Oleksij Rempel
  0 siblings, 1 reply; 23+ messages in thread
From: Nicolas Ferre @ 2014-09-17 13:53 UTC (permalink / raw)
  To: linux-arm-kernel

On 17/09/2014 15:46, Alexandre Belloni :
> Hi,
> 
> On 14/09/2014 at 05:05:45 -0400, Jason Cooper wrote :
>> On Sun, Sep 14, 2014 at 09:45:04AM +0200, Oleksij Rempel wrote:
>>> Am 14.09.2014 um 09:12 schrieb Jason Cooper:
>>>> On Sun, Sep 14, 2014 at 12:13:22AM +0200, Oleksij Rempel wrote:
>>>>
>>>> Could you please add a description of the SoC?  Perhaps a link to
>>>> documentation, or at least a slick sheet?  Also, are there any products
>>>> on the market with this SoC, which ones?
>>>>
>>>> thx,
>>>
>>> Hi,
>>>
>>> it is low cost (?) SoC targeted for market in China and India which
>>> trying to "replace" AT91SAM9G25.

Well, I won't say "replace" but "compete with" Atmel AT91SAM9G25.
AT91SAM9G25 is here to stay ;-)

>>> 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
>>
>> Ok, please include this information is the commit log of the next
>> version of this patch.
>>
> 
> I would also suggest to call it AlphaScale instead of Alpscale as it
> allows to get more useful information when searching the web.
> 


-- 
Nicolas Ferre

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

* [PATCH 4/7] clk: add clk-asm9260 driver
  2014-09-13 22:13 ` [PATCH 4/7] clk: add clk-asm9260 driver Oleksij Rempel
@ 2014-09-17 13:54   ` Alexandre Belloni
  2014-09-18  6:46     ` Oleksij Rempel
  0 siblings, 1 reply; 23+ messages in thread
From: Alexandre Belloni @ 2014-09-17 13:54 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

Please have a look at https://lkml.org/lkml/2014/5/14/598 which describe
the preferred way of implementing clocks in the CCF where you only
declare the clock generator in the DT instead of each separate clocks.

On 14/09/2014 at 00:13:25 +0200, Oleksij Rempel wrote :
> Signed-off-by: Oleksij Rempel <linux@rempel-privat.de>
> ---
>  drivers/clk/Makefile      |   1 +
>  drivers/clk/clk-asm9260.c | 159 ++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 160 insertions(+)
>  create mode 100644 drivers/clk/clk-asm9260.c
> 
> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
> index 567f102..351dd48 100644
> --- a/drivers/clk/Makefile
> +++ b/drivers/clk/Makefile
> @@ -38,6 +38,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..396cc09
> --- /dev/null
> +++ b/drivers/clk/clk-asm9260.c
> @@ -0,0 +1,159 @@
> +/*
> + * U300 clock implementation
> + * Copyright (C) 2007-2012 ST-Ericsson AB
> + * License terms: GNU General Public License (GPL) version 2
> + * Author: Linus Walleij <linus.walleij@stericsson.com>
> + * Author: Jonas Aaberg <jonas.aberg@stericsson.com>
> + */
> +#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>
> +
> +static DEFINE_SPINLOCK(asm9260_clk_lock);
> +
> +struct asm9260_clk {
> +	void __iomem    *reg;
> +	char *parent_name;
> +};
> +
> +static void __iomem *asm9260_get_sreg(struct device_node *node)
> +{
> +	u32 reg;
> +	void __iomem *iomem;
> +	struct device_node *srnp;
> +	int ret;
> +
> +	ret = of_property_read_u32(node, "reg", &reg);
> +	if (WARN_ON(ret))
> +		return NULL;
> +
> +	srnp = of_find_compatible_node(NULL, NULL, "alpscale,asm9260-sregs");
> +	iomem = of_iomap(srnp, 0);
> +	iomem += reg;
> +
> +	return iomem;
> +}
> +
> +/*
> + * On this chip gate used to disable or to update clock
> + * after new source was selected
> + */
> +
> +static void __init asm9260_gate_init(struct device_node *node)
> +{
> +	struct clk *clk;
> +	const char *clk_name = node->name;
> +	void __iomem *iomem;
> +	const char *parent_name;
> +	u32 bit;
> +	int ret;
> +
> +	iomem = asm9260_get_sreg(node);
> +	parent_name = of_clk_get_parent_name(node, 0);
> +
> +	ret = of_property_read_u32(node, "bit-index", &bit);
> +	if (WARN_ON(ret))
> +		return;
> +
> +	clk = clk_register_gate(NULL, clk_name, parent_name,
> +			CLK_SET_RATE_PARENT, iomem, bit, 0,
> +			&asm9260_clk_lock);
> +
> +	if (!IS_ERR(clk))
> +		of_clk_add_provider(node, of_clk_src_simple_get, clk);
> +}
> +CLK_OF_DECLARE(asm9260_gate, "alpscale,asm9260-gate-clock", asm9260_gate_init);
> +
> +
> +static void __init asm9260_div_init(struct device_node *node)
> +{
> +	struct clk *clk;
> +	const char *clk_name = node->name;
> +	void __iomem *iomem;
> +	const char *parent_name;
> +
> +	iomem = asm9260_get_sreg(node);
> +
> +	parent_name = of_clk_get_parent_name(node, 0);
> +	clk = clk_register_divider(NULL, clk_name, parent_name,
> +			CLK_SET_RATE_PARENT, iomem, 0, 8, CLK_DIVIDER_ONE_BASED,
> +			&asm9260_clk_lock);
> +
> +	if (!IS_ERR(clk))
> +		of_clk_add_provider(node, of_clk_src_simple_get, clk);
> +}
> +CLK_OF_DECLARE(asm9260_div, "alpscale,asm9260-div-clock", asm9260_div_init);
> +
> +/*
> + * Simple one bit MUX for two sources
> + */
> +static void __init asm9260_bimux_init(struct device_node *node)
> +{
> +	struct clk *clk;
> +	const char *clk_name = node->name;
> +	u8 num_parents;
> +	void __iomem *iomem;
> +	const char **parent_names;
> +	int ret, i;
> +	u32 *table;
> +
> +	iomem = asm9260_get_sreg(node);
> +	if (!iomem)
> +		return;
> +
> +	num_parents = of_clk_get_parent_count(node);
> +	if (WARN_ON(!num_parents || num_parents > 2))
> +		return;
> +
> +	parent_names = kzalloc(sizeof(char *) * num_parents, GFP_KERNEL);
> +	if (WARN_ON(!parent_names))
> +		return;
> +
> +	table = kzalloc(sizeof(u32) * num_parents, GFP_KERNEL);
> +	if (WARN_ON(!table))
> +		return;
> +
> +	ret = of_property_read_u32_array(node, "mux-table", table,
> +			num_parents);
> +	if (WARN_ON(ret))
> +		return;
> +
> +	for (i = 0; i < num_parents; i++)
> +		parent_names[i] = of_clk_get_parent_name(node, i);
> +
> +	clk = clk_register_mux_table(NULL, clk_name, parent_names,
> +			num_parents, 0, iomem, 0, 1, 0, table,
> +			&asm9260_clk_lock);
> +
> +	if (!IS_ERR(clk))
> +		of_clk_add_provider(node, of_clk_src_simple_get, clk);
> +}
> +CLK_OF_DECLARE(asm9260_bimux, "alpscale,asm9260-bimux-clock", asm9260_bimux_init);
> +
> +static void __init asm9260_pll_init(struct device_node *node)
> +{
> +	struct clk *clk;
> +	const char *clk_name = node->name;
> +	u32 rate;
> +	void __iomem *iomem;
> +	const char *parent_name;
> +	u32 accuracy = 0;
> +
> +	iomem = asm9260_get_sreg(node);
> +	rate = (ioread32(iomem) & 0xffff) * 1000000;
> +
> +	parent_name = of_clk_get_parent_name(node, 0);
> +	accuracy = clk_get_accuracy(__clk_lookup(parent_name));
> +	clk = clk_register_fixed_rate_with_accuracy(NULL, clk_name, parent_name,
> +			0, rate,
> +			accuracy);
> +
> +	if (!IS_ERR(clk))
> +		of_clk_add_provider(node, of_clk_src_simple_get, clk);
> +}
> +CLK_OF_DECLARE(asm9260_pll, "alpscale,asm9260-pll-clock", asm9260_pll_init);
> -- 
> 1.9.1
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

-- 
Alexandre Belloni, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com

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

* [PATCH 1/7] ARM: add mach-asm9260
  2014-09-17 13:53           ` Nicolas Ferre
@ 2014-09-18  6:29             ` Oleksij Rempel
  0 siblings, 0 replies; 23+ messages in thread
From: Oleksij Rempel @ 2014-09-18  6:29 UTC (permalink / raw)
  To: linux-arm-kernel

Am 17.09.2014 um 15:53 schrieb Nicolas Ferre:
> On 17/09/2014 15:46, Alexandre Belloni :
>> Hi,
>>
>> On 14/09/2014 at 05:05:45 -0400, Jason Cooper wrote :
>>> On Sun, Sep 14, 2014 at 09:45:04AM +0200, Oleksij Rempel wrote:
>>>> Am 14.09.2014 um 09:12 schrieb Jason Cooper:
>>>>> On Sun, Sep 14, 2014 at 12:13:22AM +0200, Oleksij Rempel wrote:
>>>>>
>>>>> Could you please add a description of the SoC?  Perhaps a link to
>>>>> documentation, or at least a slick sheet?  Also, are there any products
>>>>> on the market with this SoC, which ones?
>>>>>
>>>>> thx,
>>>>
>>>> Hi,
>>>>
>>>> it is low cost (?) SoC targeted for market in China and India which
>>>> trying to "replace" AT91SAM9G25.
> 
> Well, I won't say "replace" but "compete with" Atmel AT91SAM9G25.
> AT91SAM9G25 is here to stay ;-)

Hehe.. :D sure. I like this version.

>>>> 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
>>>
>>> Ok, please include this information is the commit log of the next
>>> version of this patch.
>>>
>>
>> I would also suggest to call it AlphaScale instead of Alpscale as it
>> allows to get more useful information when searching the web.

Ok will fix it. Seems like they had this name confusion for some time.
There is even www.alpscale.cn website mirrored with www.alphascale.com.


-- 
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/20140918/8b8f7423/attachment.sig>

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

* [PATCH 4/7] clk: add clk-asm9260 driver
  2014-09-17 13:54   ` Alexandre Belloni
@ 2014-09-18  6:46     ` Oleksij Rempel
  2014-09-18  7:56       ` Alexandre Belloni
  0 siblings, 1 reply; 23+ messages in thread
From: Oleksij Rempel @ 2014-09-18  6:46 UTC (permalink / raw)
  To: linux-arm-kernel

Am 17.09.2014 um 15:54 schrieb Alexandre Belloni:
> Hi,
> 
> Please have a look at https://lkml.org/lkml/2014/5/14/598 which describe
> the preferred way of implementing clocks in the CCF where you only
> declare the clock generator in the DT instead of each separate clocks.

hm... if i see it correctly. i will need to move almost everything from
DT to clk-driver. And i will need to create separate driver for other
SoC provided by AlphaScale. On other side with current (generic) driver
i will need only to change DT and it will work.

May be instead of going qcom way, it will be better to have generic
gate, div and mux bindings for DT? Sure it will make DT a bit fuzzy, but
it will dramatically reduce kernel code and reduce the time of providing
code to upstream.

I don't think drivers/clk/qcom/gcc-msm8974.c is less complicated solution.
-- 
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/20140918/a206d61a/attachment.sig>

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

* [PATCH 4/7] clk: add clk-asm9260 driver
  2014-09-18  6:46     ` Oleksij Rempel
@ 2014-09-18  7:56       ` Alexandre Belloni
  2014-09-18  8:46         ` Oleksij Rempel
  2014-09-20 18:06         ` Oleksij Rempel
  0 siblings, 2 replies; 23+ messages in thread
From: Alexandre Belloni @ 2014-09-18  7:56 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

On 18/09/2014 at 08:46:57 +0200, Oleksij Rempel wrote :
> Am 17.09.2014 um 15:54 schrieb Alexandre Belloni:
> > Hi,
> > 
> > Please have a look at https://lkml.org/lkml/2014/5/14/598 which describe
> > the preferred way of implementing clocks in the CCF where you only
> > declare the clock generator in the DT instead of each separate clocks.
> 
> hm... if i see it correctly. i will need to move almost everything from
> DT to clk-driver. And i will need to create separate driver for other
> SoC provided by AlphaScale. On other side with current (generic) driver
> i will need only to change DT and it will work.
> 
> May be instead of going qcom way, it will be better to have generic
> gate, div and mux bindings for DT? Sure it will make DT a bit fuzzy, but
> it will dramatically reduce kernel code and reduce the time of providing
> code to upstream.
> 
> I don't think drivers/clk/qcom/gcc-msm8974.c is less complicated solution.

IT is not less complicated but it is more flexible (for exemple when
setting flags on individual clocks, like CLK_SET_RATE_PARENT or
CLK_IGNORE_UNUSED). Describing all the individual clocks in DT is a
mistake we made in at91 and it will definitely bother you in the future,
for example when you realize that your clock controller is also taking
care of reset or power management.

Also, this is the kind of driver you write only once per SoC so it is
about the same doing it in DT or in C with the added advantage that
doing it in C takes less memory and is probably faster.

You can have a look at how it has been done for the berlin SoCs to see
how you can easily reuse code between drivers.

-- 
Alexandre Belloni, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com

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

* [PATCH 4/7] clk: add clk-asm9260 driver
  2014-09-18  7:56       ` Alexandre Belloni
@ 2014-09-18  8:46         ` Oleksij Rempel
  2014-09-20 18:06         ` Oleksij Rempel
  1 sibling, 0 replies; 23+ messages in thread
From: Oleksij Rempel @ 2014-09-18  8:46 UTC (permalink / raw)
  To: linux-arm-kernel

Am 18.09.2014 um 09:56 schrieb Alexandre Belloni:
> Hi,
> 
> On 18/09/2014 at 08:46:57 +0200, Oleksij Rempel wrote :
>> Am 17.09.2014 um 15:54 schrieb Alexandre Belloni:
>>> Hi,
>>>
>>> Please have a look at https://lkml.org/lkml/2014/5/14/598 which describe
>>> the preferred way of implementing clocks in the CCF where you only
>>> declare the clock generator in the DT instead of each separate clocks.
>>
>> hm... if i see it correctly. i will need to move almost everything from
>> DT to clk-driver. And i will need to create separate driver for other
>> SoC provided by AlphaScale. On other side with current (generic) driver
>> i will need only to change DT and it will work.
>>
>> May be instead of going qcom way, it will be better to have generic
>> gate, div and mux bindings for DT? Sure it will make DT a bit fuzzy, but
>> it will dramatically reduce kernel code and reduce the time of providing
>> code to upstream.
>>
>> I don't think drivers/clk/qcom/gcc-msm8974.c is less complicated solution.
> 
> IT is not less complicated but it is more flexible (for exemple when
> setting flags on individual clocks, like CLK_SET_RATE_PARENT or
> CLK_IGNORE_UNUSED). Describing all the individual clocks in DT is a
> mistake we made in at91 and it will definitely bother you in the future,
> for example when you realize that your clock controller is also taking
> care of reset or power management.
> 
> Also, this is the kind of driver you write only once per SoC so it is
> about the same doing it in DT or in C with the added advantage that
> doing it in C takes less memory and is probably faster.
> 
> You can have a look at how it has been done for the berlin SoCs to see
> how you can easily reuse code between drivers.

Ok, thank you. i'll rewrite it.

-- 
Regards,
Oleksij

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

* [PATCH 4/7] clk: add clk-asm9260 driver
  2014-09-18  7:56       ` Alexandre Belloni
  2014-09-18  8:46         ` Oleksij Rempel
@ 2014-09-20 18:06         ` Oleksij Rempel
  2014-09-20 18:43           ` Alexandre Belloni
  1 sibling, 1 reply; 23+ messages in thread
From: Oleksij Rempel @ 2014-09-20 18:06 UTC (permalink / raw)
  To: linux-arm-kernel

Am 18.09.2014 um 09:56 schrieb Alexandre Belloni:
> Hi,
> 
> On 18/09/2014 at 08:46:57 +0200, Oleksij Rempel wrote :
>> Am 17.09.2014 um 15:54 schrieb Alexandre Belloni:
>>> Hi,
>>>
>>> Please have a look at https://lkml.org/lkml/2014/5/14/598 which describe
>>> the preferred way of implementing clocks in the CCF where you only
>>> declare the clock generator in the DT instead of each separate clocks.
>>
>> hm... if i see it correctly. i will need to move almost everything from
>> DT to clk-driver. And i will need to create separate driver for other
>> SoC provided by AlphaScale. On other side with current (generic) driver
>> i will need only to change DT and it will work.
>>
>> May be instead of going qcom way, it will be better to have generic
>> gate, div and mux bindings for DT? Sure it will make DT a bit fuzzy, but
>> it will dramatically reduce kernel code and reduce the time of providing
>> code to upstream.
>>
>> I don't think drivers/clk/qcom/gcc-msm8974.c is less complicated solution.
> 
> IT is not less complicated but it is more flexible (for exemple when
> setting flags on individual clocks, like CLK_SET_RATE_PARENT or
> CLK_IGNORE_UNUSED). Describing all the individual clocks in DT is a
> mistake we made in at91 and it will definitely bother you in the future,
> for example when you realize that your clock controller is also taking
> care of reset or power management.
> 
> Also, this is the kind of driver you write only once per SoC so it is
> about the same doing it in DT or in C with the added advantage that
> doing it in C takes less memory and is probably faster.
> 
> You can have a look at how it has been done for the berlin SoCs to see
> how you can easily reuse code between drivers.

What is the correct way to handle/define i2s MCLK input? I have I2S mux
clock with choice of 3 sources: Xtal, PLL and MCLK. One of pins can be
configured as MCLK src. Should i define fixedrate-clk?

-- 
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/20140920/0b0c4daf/attachment.sig>

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

* [PATCH 4/7] clk: add clk-asm9260 driver
  2014-09-20 18:06         ` Oleksij Rempel
@ 2014-09-20 18:43           ` Alexandre Belloni
  0 siblings, 0 replies; 23+ messages in thread
From: Alexandre Belloni @ 2014-09-20 18:43 UTC (permalink / raw)
  To: linux-arm-kernel

On 20/09/2014 at 20:06:21 +0200, Oleksij Rempel wrote :
> Am 18.09.2014 um 09:56 schrieb Alexandre Belloni:
> > You can have a look at how it has been done for the berlin SoCs to see
> > how you can easily reuse code between drivers.
> 
> What is the correct way to handle/define i2s MCLK input? I have I2S mux
> clock with choice of 3 sources: Xtal, PLL and MCLK. One of pins can be
> configured as MCLK src. Should i define fixedrate-clk?
> 

It depends on where is your mux, if it is in the I2S controller adress
range, I would simply give 3 parent clocks to your I2S controller, like:

i2s at 8fffffff {
 compatible = "...";
 reg = <0x8fffffff 0x100>;
 clocks = <&xtal, &clkc CLKID_MCK, &clkc CLKID_PLL>;
}

If it is part of your clock generator, then simply register a clock mux
with 3 parents as part of your clock controller binding. And use
something like:
 clocks = <&clck CLKID_I2S>;

Have a look at how this is done for berlin2, search for
clk_register_mux()

-- 
Alexandre Belloni, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com

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

end of thread, other threads:[~2014-09-20 18:43 UTC | newest]

Thread overview: 23+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-09-13 22:13 [PATCH 0/7] initial suport for Alpscale ASM9260 Oleksij Rempel
2014-09-13 22:13 ` [PATCH 1/7] ARM: add mach-asm9260 Oleksij Rempel
2014-09-14  7:12   ` Jason Cooper
2014-09-14  7:45     ` Oleksij Rempel
2014-09-14  9:05       ` Jason Cooper
2014-09-17 13:46         ` Alexandre Belloni
2014-09-17 13:53           ` Nicolas Ferre
2014-09-18  6:29             ` Oleksij Rempel
2014-09-13 22:13 ` [PATCH 2/7] add include/debug/asm9260.S Oleksij Rempel
2014-09-13 22:13 ` [PATCH 3/7] ARM: dts: add DT for Alpscale ASM9260 SoC Oleksij Rempel
2014-09-13 22:13 ` [PATCH 4/7] clk: add clk-asm9260 driver Oleksij Rempel
2014-09-17 13:54   ` Alexandre Belloni
2014-09-18  6:46     ` Oleksij Rempel
2014-09-18  7:56       ` Alexandre Belloni
2014-09-18  8:46         ` Oleksij Rempel
2014-09-20 18:06         ` Oleksij Rempel
2014-09-20 18:43           ` Alexandre Belloni
2014-09-13 22:13 ` [PATCH 5/7] clocksource: add asm9260_timer driver Oleksij Rempel
2014-09-13 22:13 ` [PATCH 6/7] irqchip: add irq-asm9260 driver Oleksij Rempel
2014-09-14  7:37   ` Jason Cooper
2014-09-15  5:52     ` Oleksij Rempel
2014-09-17 12:59       ` Jason Cooper
2014-09-13 22:13 ` [PATCH 7/7] tty/serial: add asm9260-serial driver 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).