All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/11] ARM: support for ICP DAS LP-8x4x
@ 2013-12-01  6:26 ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-01  6:26 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel; +Cc: Sergei Ianovich

ICP DAS calls LP-8x4x 'programmable automation controller'. It is
an industrial computer based on PXA270 SoC. They ship it with a 2.6.19
kernel and proprietary kernel module and userspace library to access its
industrial IO.

This patch series allows to boot the device with a modern kernel. It adds
support for:
* FPGA irq chip
* MMC card interface on PXA270
* USB 1.1 port on PXA270
* 2 NOR flash devices
* VGA interface on PXA270
* 2 onboard ethernet Davicom DM9000 devices
* 3 serial UART ports on PXA270
* DS1302 RTC
* 512kiB SRAM with double battery-backup
* 3 built-in 16550 serial UART ports
* industrial IO parallel bus
* serial interface for digital and analog industrial IO modules on
  parallel bus (any I-870xx series)
* digital and analog industrial IO modules for parallel bus:
  * I-8024 (analog output)
  * I-8041 (digital output)
  * I-8042 (digital input-output)

Sergei Ianovich (11):
  resolve PXA<->8250 serial device address conflict
  arm: pxa27x: support ICP DAS LP-8x4x
  rtc: support DS1302 RTC on ICP DAS LP-8x4x
  mtd: support BB SRAM on ICP DAS LP-8x4x
  serial: support for 16550 serial ports on LP-8x4x
  misc: support for LP-8x4x custom parallel bus
  misc: support for serial slots in LP-8x4x
  misc: support for parallel slots in LP-8x4x
  misc: support for I-8041 in LP-8x4x
  misc: support for I-8042 in LP-8x4x
  misc: support for I-8024 in LP-8x4x

 Documentation/misc-devices/lp8x4x_bus.txt |   74 +
 arch/arm/configs/lp8x4x_defconfig         | 2324 +++++++++++++++++++++++++++++
 arch/arm/mach-pxa/Kconfig                 |    8 +
 arch/arm/mach-pxa/Makefile                |    1 +
 arch/arm/mach-pxa/include/mach/lp8x4x.h   |   95 ++
 arch/arm/mach-pxa/lp8x4x.c                |  557 +++++++
 drivers/misc/Kconfig                      |   12 +
 drivers/misc/Makefile                     |    1 +
 drivers/misc/lp8x4x_bus.c                 |  581 ++++++++
 drivers/mtd/devices/Kconfig               |   13 +
 drivers/mtd/devices/Makefile              |    1 +
 drivers/mtd/devices/lp8x4x_sram.c         |  229 +++
 drivers/rtc/Kconfig                       |    2 +-
 drivers/rtc/rtc-ds1302.c                  |   85 ++
 drivers/tty/serial/8250/8250_lp8x4x.c     |  181 +++
 drivers/tty/serial/8250/Kconfig           |   11 +
 drivers/tty/serial/8250/Makefile          |    1 +
 drivers/tty/serial/Kconfig                |   19 +
 drivers/tty/serial/pxa.c                  |   22 +-
 19 files changed, 4212 insertions(+), 5 deletions(-)
 create mode 100644 Documentation/misc-devices/lp8x4x_bus.txt
 create mode 100644 arch/arm/configs/lp8x4x_defconfig
 create mode 100644 arch/arm/mach-pxa/include/mach/lp8x4x.h
 create mode 100644 arch/arm/mach-pxa/lp8x4x.c
 create mode 100644 drivers/misc/lp8x4x_bus.c
 create mode 100644 drivers/mtd/devices/lp8x4x_sram.c
 create mode 100644 drivers/tty/serial/8250/8250_lp8x4x.c

-- 
1.8.4.2


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

* [PATCH 00/11] ARM: support for ICP DAS LP-8x4x
@ 2013-12-01  6:26 ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-01  6:26 UTC (permalink / raw)
  To: linux-arm-kernel

ICP DAS calls LP-8x4x 'programmable automation controller'. It is
an industrial computer based on PXA270 SoC. They ship it with a 2.6.19
kernel and proprietary kernel module and userspace library to access its
industrial IO.

This patch series allows to boot the device with a modern kernel. It adds
support for:
* FPGA irq chip
* MMC card interface on PXA270
* USB 1.1 port on PXA270
* 2 NOR flash devices
* VGA interface on PXA270
* 2 onboard ethernet Davicom DM9000 devices
* 3 serial UART ports on PXA270
* DS1302 RTC
* 512kiB SRAM with double battery-backup
* 3 built-in 16550 serial UART ports
* industrial IO parallel bus
* serial interface for digital and analog industrial IO modules on
  parallel bus (any I-870xx series)
* digital and analog industrial IO modules for parallel bus:
  * I-8024 (analog output)
  * I-8041 (digital output)
  * I-8042 (digital input-output)

Sergei Ianovich (11):
  resolve PXA<->8250 serial device address conflict
  arm: pxa27x: support ICP DAS LP-8x4x
  rtc: support DS1302 RTC on ICP DAS LP-8x4x
  mtd: support BB SRAM on ICP DAS LP-8x4x
  serial: support for 16550 serial ports on LP-8x4x
  misc: support for LP-8x4x custom parallel bus
  misc: support for serial slots in LP-8x4x
  misc: support for parallel slots in LP-8x4x
  misc: support for I-8041 in LP-8x4x
  misc: support for I-8042 in LP-8x4x
  misc: support for I-8024 in LP-8x4x

 Documentation/misc-devices/lp8x4x_bus.txt |   74 +
 arch/arm/configs/lp8x4x_defconfig         | 2324 +++++++++++++++++++++++++++++
 arch/arm/mach-pxa/Kconfig                 |    8 +
 arch/arm/mach-pxa/Makefile                |    1 +
 arch/arm/mach-pxa/include/mach/lp8x4x.h   |   95 ++
 arch/arm/mach-pxa/lp8x4x.c                |  557 +++++++
 drivers/misc/Kconfig                      |   12 +
 drivers/misc/Makefile                     |    1 +
 drivers/misc/lp8x4x_bus.c                 |  581 ++++++++
 drivers/mtd/devices/Kconfig               |   13 +
 drivers/mtd/devices/Makefile              |    1 +
 drivers/mtd/devices/lp8x4x_sram.c         |  229 +++
 drivers/rtc/Kconfig                       |    2 +-
 drivers/rtc/rtc-ds1302.c                  |   85 ++
 drivers/tty/serial/8250/8250_lp8x4x.c     |  181 +++
 drivers/tty/serial/8250/Kconfig           |   11 +
 drivers/tty/serial/8250/Makefile          |    1 +
 drivers/tty/serial/Kconfig                |   19 +
 drivers/tty/serial/pxa.c                  |   22 +-
 19 files changed, 4212 insertions(+), 5 deletions(-)
 create mode 100644 Documentation/misc-devices/lp8x4x_bus.txt
 create mode 100644 arch/arm/configs/lp8x4x_defconfig
 create mode 100644 arch/arm/mach-pxa/include/mach/lp8x4x.h
 create mode 100644 arch/arm/mach-pxa/lp8x4x.c
 create mode 100644 drivers/misc/lp8x4x_bus.c
 create mode 100644 drivers/mtd/devices/lp8x4x_sram.c
 create mode 100644 drivers/tty/serial/8250/8250_lp8x4x.c

-- 
1.8.4.2

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

* [PATCH 01/11] resolve PXA<->8250 serial device address conflict
  2013-12-01  6:26 ` Sergei Ianovich
  (?)
@ 2013-12-01  6:26   ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-01  6:26 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Greg Kroah-Hartman, Jiri Slaby,
	open list:SERIAL DRIVERS

PXA serial ports have "standard" UART names (ttyS[0-3]), major
device number (4) and first minor device number (64) by default.

If the system has extra 8250 serial port hardware in addition
to onboard PXA serial ports, default settings produce a device
allocation conflict.

The patch provides a configuration option which can move onboard
ports out of the way of 8250_core by assigning a different (204)
major number and corresponding device names (ttySA[0-3]).

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
 drivers/tty/serial/Kconfig | 19 +++++++++++++++++++
 drivers/tty/serial/pxa.c   | 22 ++++++++++++++++++----
 2 files changed, 37 insertions(+), 4 deletions(-)

diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index a3817ab..328b716 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -419,6 +419,25 @@ config SERIAL_PXA_CONSOLE
 	  your boot loader (lilo or loadlin) about how to pass options to the
 	  kernel at boot time.)
 
+config SERIAL_PXA_AS_TTYSA
+	bool "PXA serial ports with SA-1100 name and major number"
+	depends on SERIAL_PXA
+	default N
+	help
+	  PXA serial ports have "standard" UART names (ttyS[0-3]), major
+	  device number (4) and first minor device number (64) by default.
+
+	  If the system has extra 8250 serial port hardware in addition
+	  to onboard PXA serial ports, default settings produce a device
+	  allocation conflict.
+
+	  Selecting this option will move onboard ports out of the way of
+	  8250_core by assigning a different (204) major number and
+	  corresponding device names (ttySA[0-3]).
+
+	  Say Y here, if you need to support extra 8250 serial port hardware
+	  on a PXA system.
+
 config SERIAL_SA1100
 	bool "SA1100 serial port support"
 	depends on ARCH_SA1100
diff --git a/drivers/tty/serial/pxa.c b/drivers/tty/serial/pxa.c
index f9f20f3..2b5a8ad 100644
--- a/drivers/tty/serial/pxa.c
+++ b/drivers/tty/serial/pxa.c
@@ -593,6 +593,20 @@ serial_pxa_type(struct uart_port *port)
 static struct uart_pxa_port *serial_pxa_ports[4];
 static struct uart_driver serial_pxa_reg;
 
+#ifndef CONFIG_SERIAL_PXA_AS_TTYSA
+
+#define PXA_TTY_NAME	"ttyS"
+#define PXA_TTY_MAJOR	TTY_MAJOR
+#define PXA_TTY_MINOR	64
+
+#else
+
+#define PXA_TTY_NAME	"ttySA"
+#define PXA_TTY_MAJOR	204
+#define PXA_TTY_MINOR	5
+
+#endif
+
 #ifdef CONFIG_SERIAL_PXA_CONSOLE
 
 #define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
@@ -751,7 +765,7 @@ serial_pxa_console_setup(struct console *co, char *options)
 }
 
 static struct console serial_pxa_console = {
-	.name		= "ttyS",
+	.name		= PXA_TTY_NAME,
 	.write		= serial_pxa_console_write,
 	.device		= uart_console_device,
 	.setup		= serial_pxa_console_setup,
@@ -792,9 +806,9 @@ static struct uart_ops serial_pxa_pops = {
 static struct uart_driver serial_pxa_reg = {
 	.owner		= THIS_MODULE,
 	.driver_name	= "PXA serial",
-	.dev_name	= "ttyS",
-	.major		= TTY_MAJOR,
-	.minor		= 64,
+	.dev_name	= PXA_TTY_NAME,
+	.major		= PXA_TTY_MAJOR,
+	.minor		= PXA_TTY_MINOR,
 	.nr		= 4,
 	.cons		= PXA_CONSOLE,
 };
-- 
1.8.4.2


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

* [PATCH 01/11] resolve PXA<->8250 serial device address conflict
@ 2013-12-01  6:26   ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-01  6:26 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Greg Kroah-Hartman, Jiri Slaby,
	open list:SERIAL DRIVERS

PXA serial ports have "standard" UART names (ttyS[0-3]), major
device number (4) and first minor device number (64) by default.

If the system has extra 8250 serial port hardware in addition
to onboard PXA serial ports, default settings produce a device
allocation conflict.

The patch provides a configuration option which can move onboard
ports out of the way of 8250_core by assigning a different (204)
major number and corresponding device names (ttySA[0-3]).

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
 drivers/tty/serial/Kconfig | 19 +++++++++++++++++++
 drivers/tty/serial/pxa.c   | 22 ++++++++++++++++++----
 2 files changed, 37 insertions(+), 4 deletions(-)

diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index a3817ab..328b716 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -419,6 +419,25 @@ config SERIAL_PXA_CONSOLE
 	  your boot loader (lilo or loadlin) about how to pass options to the
 	  kernel at boot time.)
 
+config SERIAL_PXA_AS_TTYSA
+	bool "PXA serial ports with SA-1100 name and major number"
+	depends on SERIAL_PXA
+	default N
+	help
+	  PXA serial ports have "standard" UART names (ttyS[0-3]), major
+	  device number (4) and first minor device number (64) by default.
+
+	  If the system has extra 8250 serial port hardware in addition
+	  to onboard PXA serial ports, default settings produce a device
+	  allocation conflict.
+
+	  Selecting this option will move onboard ports out of the way of
+	  8250_core by assigning a different (204) major number and
+	  corresponding device names (ttySA[0-3]).
+
+	  Say Y here, if you need to support extra 8250 serial port hardware
+	  on a PXA system.
+
 config SERIAL_SA1100
 	bool "SA1100 serial port support"
 	depends on ARCH_SA1100
diff --git a/drivers/tty/serial/pxa.c b/drivers/tty/serial/pxa.c
index f9f20f3..2b5a8ad 100644
--- a/drivers/tty/serial/pxa.c
+++ b/drivers/tty/serial/pxa.c
@@ -593,6 +593,20 @@ serial_pxa_type(struct uart_port *port)
 static struct uart_pxa_port *serial_pxa_ports[4];
 static struct uart_driver serial_pxa_reg;
 
+#ifndef CONFIG_SERIAL_PXA_AS_TTYSA
+
+#define PXA_TTY_NAME	"ttyS"
+#define PXA_TTY_MAJOR	TTY_MAJOR
+#define PXA_TTY_MINOR	64
+
+#else
+
+#define PXA_TTY_NAME	"ttySA"
+#define PXA_TTY_MAJOR	204
+#define PXA_TTY_MINOR	5
+
+#endif
+
 #ifdef CONFIG_SERIAL_PXA_CONSOLE
 
 #define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
@@ -751,7 +765,7 @@ serial_pxa_console_setup(struct console *co, char *options)
 }
 
 static struct console serial_pxa_console = {
-	.name		= "ttyS",
+	.name		= PXA_TTY_NAME,
 	.write		= serial_pxa_console_write,
 	.device		= uart_console_device,
 	.setup		= serial_pxa_console_setup,
@@ -792,9 +806,9 @@ static struct uart_ops serial_pxa_pops = {
 static struct uart_driver serial_pxa_reg = {
 	.owner		= THIS_MODULE,
 	.driver_name	= "PXA serial",
-	.dev_name	= "ttyS",
-	.major		= TTY_MAJOR,
-	.minor		= 64,
+	.dev_name	= PXA_TTY_NAME,
+	.major		= PXA_TTY_MAJOR,
+	.minor		= PXA_TTY_MINOR,
 	.nr		= 4,
 	.cons		= PXA_CONSOLE,
 };
-- 
1.8.4.2


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

* [PATCH 01/11] resolve PXA<->8250 serial device address conflict
@ 2013-12-01  6:26   ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-01  6:26 UTC (permalink / raw)
  To: linux-arm-kernel

PXA serial ports have "standard" UART names (ttyS[0-3]), major
device number (4) and first minor device number (64) by default.

If the system has extra 8250 serial port hardware in addition
to onboard PXA serial ports, default settings produce a device
allocation conflict.

The patch provides a configuration option which can move onboard
ports out of the way of 8250_core by assigning a different (204)
major number and corresponding device names (ttySA[0-3]).

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
 drivers/tty/serial/Kconfig | 19 +++++++++++++++++++
 drivers/tty/serial/pxa.c   | 22 ++++++++++++++++++----
 2 files changed, 37 insertions(+), 4 deletions(-)

diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index a3817ab..328b716 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -419,6 +419,25 @@ config SERIAL_PXA_CONSOLE
 	  your boot loader (lilo or loadlin) about how to pass options to the
 	  kernel at boot time.)
 
+config SERIAL_PXA_AS_TTYSA
+	bool "PXA serial ports with SA-1100 name and major number"
+	depends on SERIAL_PXA
+	default N
+	help
+	  PXA serial ports have "standard" UART names (ttyS[0-3]), major
+	  device number (4) and first minor device number (64) by default.
+
+	  If the system has extra 8250 serial port hardware in addition
+	  to onboard PXA serial ports, default settings produce a device
+	  allocation conflict.
+
+	  Selecting this option will move onboard ports out of the way of
+	  8250_core by assigning a different (204) major number and
+	  corresponding device names (ttySA[0-3]).
+
+	  Say Y here, if you need to support extra 8250 serial port hardware
+	  on a PXA system.
+
 config SERIAL_SA1100
 	bool "SA1100 serial port support"
 	depends on ARCH_SA1100
diff --git a/drivers/tty/serial/pxa.c b/drivers/tty/serial/pxa.c
index f9f20f3..2b5a8ad 100644
--- a/drivers/tty/serial/pxa.c
+++ b/drivers/tty/serial/pxa.c
@@ -593,6 +593,20 @@ serial_pxa_type(struct uart_port *port)
 static struct uart_pxa_port *serial_pxa_ports[4];
 static struct uart_driver serial_pxa_reg;
 
+#ifndef CONFIG_SERIAL_PXA_AS_TTYSA
+
+#define PXA_TTY_NAME	"ttyS"
+#define PXA_TTY_MAJOR	TTY_MAJOR
+#define PXA_TTY_MINOR	64
+
+#else
+
+#define PXA_TTY_NAME	"ttySA"
+#define PXA_TTY_MAJOR	204
+#define PXA_TTY_MINOR	5
+
+#endif
+
 #ifdef CONFIG_SERIAL_PXA_CONSOLE
 
 #define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
@@ -751,7 +765,7 @@ serial_pxa_console_setup(struct console *co, char *options)
 }
 
 static struct console serial_pxa_console = {
-	.name		= "ttyS",
+	.name		= PXA_TTY_NAME,
 	.write		= serial_pxa_console_write,
 	.device		= uart_console_device,
 	.setup		= serial_pxa_console_setup,
@@ -792,9 +806,9 @@ static struct uart_ops serial_pxa_pops = {
 static struct uart_driver serial_pxa_reg = {
 	.owner		= THIS_MODULE,
 	.driver_name	= "PXA serial",
-	.dev_name	= "ttyS",
-	.major		= TTY_MAJOR,
-	.minor		= 64,
+	.dev_name	= PXA_TTY_NAME,
+	.major		= PXA_TTY_MAJOR,
+	.minor		= PXA_TTY_MINOR,
 	.nr		= 4,
 	.cons		= PXA_CONSOLE,
 };
-- 
1.8.4.2

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

* [PATCH 02/11] arm: pxa27x: support ICP DAS LP-8x4x
  2013-12-01  6:26 ` Sergei Ianovich
@ 2013-12-01  6:26   ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-01  6:26 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Russell King, Eric Miao, Haojian Zhuang

ICP DAS calls LP-8x4x 'programmable automation controller'. It is
an industrial computer based on PXA270 SoC. They ship it with a 2.6.19
kernel and proprietary kernel module and userspace library to access
its industrial IO.

This patch allows to boot the device with a modern kernel. It adds
support for:
* FPGA irq chip
* MMC card interface on PXA270
* USB 1.1 port on PXA270
* 2 NOR flash devices
* VGA interface on PXA270
* 2 onboard ethernet Davicom DM9000 devices
* 3 serial UART ports on PXA270

Support for these devices will be added in separate patches, since
they are not currently supported by the kernel:
* DS1302 RTC
* 512kiB SRAM
* 3 built-in and up to 32 pluggable 8250 serial UART ports
* industrial IO parallel bus
* digital and analog industrial IO modules for parallel bus
* serial interface for digital and analog industrial IO modules on
  parallel bus

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
 arch/arm/configs/lp8x4x_defconfig       | 2320 +++++++++++++++++++++++++++++++
 arch/arm/mach-pxa/Kconfig               |   16 +
 arch/arm/mach-pxa/Makefile              |    1 +
 arch/arm/mach-pxa/include/mach/lp8x4x.h |   74 +
 arch/arm/mach-pxa/lp8x4x.c              |  460 ++++++
 5 files changed, 2871 insertions(+)
 create mode 100644 arch/arm/configs/lp8x4x_defconfig
 create mode 100644 arch/arm/mach-pxa/include/mach/lp8x4x.h
 create mode 100644 arch/arm/mach-pxa/lp8x4x.c

diff --git a/arch/arm/configs/lp8x4x_defconfig b/arch/arm/configs/lp8x4x_defconfig
new file mode 100644
index 0000000..5cd6d38
--- /dev/null
+++ b/arch/arm/configs/lp8x4x_defconfig
@@ -0,0 +1,2320 @@
+#
+# Automatically generated file; DO NOT EDIT.
+# Linux/arm 3.13.0-rc1 Kernel Configuration
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_HAVE_PROC_CPU=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_ARCH_HAS_CPUFREQ=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_NEED_DMA_MAP_STATE=y
+CONFIG_ARCH_MTD_XIP=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_ARM_PATCH_PHYS_VIRT=y
+CONFIG_GENERIC_BUG=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_IRQ_WORK=y
+CONFIG_BUILDTIME_EXTABLE_SORT=y
+
+#
+# General setup
+#
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_CROSS_COMPILE="arm-linux-gnueabi-"
+# CONFIG_COMPILE_TEST is not set
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_LZMA=y
+CONFIG_HAVE_KERNEL_XZ=y
+CONFIG_HAVE_KERNEL_LZO=y
+CONFIG_HAVE_KERNEL_LZ4=y
+CONFIG_KERNEL_GZIP=y
+# CONFIG_KERNEL_LZMA is not set
+# CONFIG_KERNEL_XZ is not set
+# CONFIG_KERNEL_LZO is not set
+# CONFIG_KERNEL_LZ4 is not set
+CONFIG_DEFAULT_HOSTNAME="(none)"
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_FHANDLE is not set
+# CONFIG_AUDIT is not set
+
+#
+# IRQ subsystem
+#
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_IRQ_SHOW=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_IRQ_FORCED_THREADING=y
+CONFIG_SPARSE_IRQ=y
+CONFIG_KTIME_SCALAR=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+
+#
+# Timers subsystem
+#
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ_COMMON=y
+# CONFIG_HZ_PERIODIC is not set
+CONFIG_NO_HZ_IDLE=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+
+#
+# CPU/Task time and stats accounting
+#
+CONFIG_TICK_CPU_ACCOUNTING=y
+# CONFIG_VIRT_CPU_ACCOUNTING_GEN is not set
+# CONFIG_IRQ_TIME_ACCOUNTING is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_TREE_PREEMPT_RCU=y
+CONFIG_PREEMPT_RCU=y
+CONFIG_RCU_STALL_COMMON=y
+CONFIG_RCU_FANOUT=32
+CONFIG_RCU_FANOUT_LEAF=16
+# CONFIG_RCU_FANOUT_EXACT is not set
+# CONFIG_TREE_RCU_TRACE is not set
+CONFIG_RCU_BOOST=y
+CONFIG_RCU_BOOST_PRIO=1
+CONFIG_RCU_BOOST_DELAY=500
+# CONFIG_RCU_NOCB_CPU is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_GENERIC_SCHED_CLOCK=y
+# CONFIG_CGROUPS is not set
+# CONFIG_CHECKPOINT_RESTORE is not set
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_NS is not set
+# CONFIG_IPC_NS is not set
+# CONFIG_USER_NS is not set
+CONFIG_PID_NS=y
+CONFIG_NET_NS=y
+# CONFIG_UIDGID_STRICT_TYPE_CHECKS is not set
+# CONFIG_SCHED_AUTOGROUP is not set
+# CONFIG_SYSFS_DEPRECATED is not set
+# CONFIG_RELAY is not set
+# CONFIG_BLK_DEV_INITRD is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_HAVE_UID16=y
+CONFIG_EXPERT=y
+# CONFIG_UID16 is not set
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+# CONFIG_SHMEM is not set
+CONFIG_AIO=y
+CONFIG_EMBEDDED=y
+CONFIG_HAVE_PERF_EVENTS=y
+CONFIG_PERF_USE_VMALLOC=y
+
+#
+# Kernel Performance Events And Counters
+#
+# CONFIG_PERF_EVENTS is not set
+CONFIG_VM_EVENT_COUNTERS=y
+# CONFIG_COMPAT_BRK is not set
+# CONFIG_SLAB is not set
+# CONFIG_SLUB is not set
+CONFIG_SLOB=y
+# CONFIG_PROFILING is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_JUMP_LABEL=y
+# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_DMA_ATTRS=y
+CONFIG_HAVE_DMA_CONTIGUOUS=y
+CONFIG_GENERIC_SMP_IDLE_THREAD=y
+CONFIG_GENERIC_IDLE_POLL_SETUP=y
+CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+CONFIG_HAVE_PERF_REGS=y
+CONFIG_HAVE_PERF_USER_STACK_DUMP=y
+CONFIG_HAVE_ARCH_JUMP_LABEL=y
+CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y
+CONFIG_HAVE_ARCH_SECCOMP_FILTER=y
+CONFIG_HAVE_CONTEXT_TRACKING=y
+CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y
+CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y
+CONFIG_MODULES_USE_ELF_REL=y
+CONFIG_CLONE_BACKWARDS=y
+CONFIG_OLD_SIGSUSPEND3=y
+CONFIG_OLD_SIGACTION=y
+
+#
+# GCOV-based kernel profiling
+#
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+# CONFIG_SYSTEM_TRUSTED_KEYRING is not set
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_MODVERSIONS=y
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+# CONFIG_MODULE_SIG is not set
+CONFIG_BLOCK=y
+# CONFIG_LBDAF is not set
+CONFIG_BLK_DEV_BSG=y
+# CONFIG_BLK_DEV_BSGLIB is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+CONFIG_BLK_CMDLINE_PARSER=y
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_AIX_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_MINIX_SUBPARTITION=y
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_UNIXWARE_DISKLABEL=y
+CONFIG_LDM_PARTITION=y
+CONFIG_LDM_DEBUG=y
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
+# CONFIG_CMDLINE_PARTITION is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+CONFIG_UNINLINE_SPIN_UNLOCK=y
+# CONFIG_FREEZER is not set
+
+#
+# System Type
+#
+CONFIG_MMU=y
+# CONFIG_ARCH_MULTIPLATFORM is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_GEMINI is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_DOVE is not set
+# CONFIG_ARCH_KIRKWOOD is not set
+# CONFIG_ARCH_MV78XX0 is not set
+# CONFIG_ARCH_ORION5X is not set
+# CONFIG_ARCH_MMP is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_W90X900 is not set
+# CONFIG_ARCH_LPC32XX is not set
+CONFIG_ARCH_PXA=y
+# CONFIG_ARCH_MSM is not set
+# CONFIG_ARCH_SHMOBILE is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C24XX is not set
+# CONFIG_ARCH_S3C64XX is not set
+# CONFIG_ARCH_S5P64X0 is not set
+# CONFIG_ARCH_S5PC100 is not set
+# CONFIG_ARCH_S5PV210 is not set
+# CONFIG_ARCH_EXYNOS is not set
+# CONFIG_ARCH_DAVINCI is not set
+# CONFIG_ARCH_OMAP1 is not set
+# CONFIG_GPIO_PCA953X is not set
+
+#
+# Intel PXA2xx/PXA3xx Implementations
+#
+
+#
+# Intel/Marvell Dev Platforms (sorted by hardware release time)
+#
+# CONFIG_MACH_PXA3XX_DT is not set
+# CONFIG_ARCH_LUBBOCK is not set
+# CONFIG_MACH_MAINSTONE is not set
+# CONFIG_MACH_ZYLONITE300 is not set
+# CONFIG_MACH_ZYLONITE320 is not set
+# CONFIG_MACH_LITTLETON is not set
+# CONFIG_MACH_TAVOREVB is not set
+# CONFIG_MACH_SAAR is not set
+
+#
+# Third Party Dev Platforms (sorted by vendor name)
+#
+# CONFIG_ARCH_PXA_IDP is not set
+# CONFIG_ARCH_VIPER is not set
+# CONFIG_MACH_ARCOM_ZEUS is not set
+# CONFIG_MACH_BALLOON3 is not set
+# CONFIG_MACH_CSB726 is not set
+# CONFIG_MACH_ARMCORE is not set
+# CONFIG_MACH_EM_X270 is not set
+# CONFIG_MACH_EXEDA is not set
+# CONFIG_MACH_CM_X300 is not set
+# CONFIG_MACH_CAPC7117 is not set
+# CONFIG_ARCH_GUMSTIX is not set
+# CONFIG_MACH_INTELMOTE2 is not set
+# CONFIG_MACH_STARGATE2 is not set
+# CONFIG_MACH_XCEP is not set
+# CONFIG_TRIZEPS_PXA is not set
+# CONFIG_MACH_LOGICPD_PXA270 is not set
+# CONFIG_MACH_PCM027 is not set
+# CONFIG_MACH_COLIBRI is not set
+# CONFIG_MACH_COLIBRI300 is not set
+# CONFIG_MACH_COLIBRI320 is not set
+# CONFIG_MACH_VPAC270 is not set
+
+#
+# End-user Products (sorted by vendor name)
+#
+CONFIG_MACH_LP8X4X=y
+# CONFIG_MACH_H4700 is not set
+# CONFIG_MACH_H5000 is not set
+# CONFIG_MACH_HIMALAYA is not set
+# CONFIG_MACH_MAGICIAN is not set
+# CONFIG_MACH_MIOA701 is not set
+# CONFIG_PXA_EZX is not set
+# CONFIG_MACH_MP900C is not set
+# CONFIG_ARCH_PXA_PALM is not set
+# CONFIG_MACH_RAUMFELD_RC is not set
+# CONFIG_MACH_RAUMFELD_CONNECTOR is not set
+# CONFIG_MACH_RAUMFELD_SPEAKER is not set
+# CONFIG_PXA_SHARPSL is not set
+# CONFIG_MACH_ICONTROL is not set
+# CONFIG_ARCH_PXA_ESERIES is not set
+# CONFIG_MACH_ZIPIT2 is not set
+CONFIG_PXA27x=y
+# CONFIG_PLAT_SPEAR is not set
+CONFIG_PLAT_PXA=y
+
+#
+# Processor Type
+#
+CONFIG_CPU_XSCALE=y
+CONFIG_CPU_32v5=y
+CONFIG_CPU_ABRT_EV5T=y
+CONFIG_CPU_PABRT_LEGACY=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_TLB_V4WBI=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+CONFIG_CPU_USE_DOMAINS=y
+
+#
+# Processor Features
+#
+# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
+# CONFIG_ARM_THUMB is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+CONFIG_NEED_KUSER_HELPERS=y
+CONFIG_KUSER_HELPERS=y
+# CONFIG_CACHE_L2X0 is not set
+CONFIG_ARM_L1_CACHE_SHIFT=5
+CONFIG_ARM_NR_BANKS=8
+CONFIG_IWMMXT=y
+CONFIG_MULTI_IRQ_HANDLER=y
+
+#
+# Bus support
+#
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+CONFIG_ARCH_NR_GPIO=0
+# CONFIG_PREEMPT_NONE is not set
+# CONFIG_PREEMPT_VOLUNTARY is not set
+CONFIG_PREEMPT=y
+CONFIG_PREEMPT_COUNT=y
+CONFIG_HZ_FIXED=0
+CONFIG_HZ_100=y
+# CONFIG_HZ_200 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_500 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=100
+CONFIG_SCHED_HRTICK=y
+CONFIG_AEABI=y
+# CONFIG_OABI_COMPAT is not set
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+CONFIG_HAVE_ARCH_PFN_VALID=y
+# CONFIG_HIGHMEM is not set
+CONFIG_ARCH_WANT_GENERAL_HUGETLB=y
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_HAVE_MEMBLOCK=y
+# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=999999
+# CONFIG_COMPACTION is not set
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+# CONFIG_KSM is not set
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+# CONFIG_CROSS_MEMORY_ATTACH is not set
+CONFIG_NEED_PER_CPU_KM=y
+# CONFIG_CLEANCACHE is not set
+# CONFIG_CMA is not set
+# CONFIG_ZBUD is not set
+CONFIG_FORCE_MAX_ZONEORDER=11
+CONFIG_ALIGNMENT_TRAP=y
+# CONFIG_UACCESS_WITH_MEMCPY is not set
+# CONFIG_SECCOMP is not set
+# CONFIG_CC_STACKPROTECTOR is not set
+CONFIG_SWIOTLB=y
+CONFIG_IOMMU_HELPER=y
+
+#
+# Boot options
+#
+# CONFIG_USE_OF is not set
+CONFIG_ATAGS=y
+# CONFIG_DEPRECATED_PARAM_STRUCT is not set
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="init=/sbin/init root=/dev/mmcblk0p1 rw rootfstype=ext4 console=ttySA0,115200 mem=128M rootwait"
+CONFIG_CMDLINE_FROM_BOOTLOADER=y
+# CONFIG_CMDLINE_EXTEND is not set
+# CONFIG_CMDLINE_FORCE is not set
+# CONFIG_XIP_KERNEL is not set
+# CONFIG_KEXEC is not set
+# CONFIG_CRASH_DUMP is not set
+CONFIG_AUTO_ZRELADDR=y
+
+#
+# CPU Power Management
+#
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# CPU Idle
+#
+# CONFIG_CPU_IDLE is not set
+# CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y
+CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y
+CONFIG_BINFMT_SCRIPT=y
+# CONFIG_HAVE_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+CONFIG_COREDUMP=y
+
+#
+# Power management options
+#
+# CONFIG_SUSPEND is not set
+# CONFIG_PM_RUNTIME is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+# CONFIG_ARM_CPU_SUSPEND is not set
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_DIAG=m
+CONFIG_UNIX=y
+CONFIG_UNIX_DIAG=m
+CONFIG_XFRM=y
+CONFIG_XFRM_ALGO=m
+# CONFIG_XFRM_USER is not set
+CONFIG_XFRM_SUB_POLICY=y
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+CONFIG_XFRM_IPCOMP=m
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+# CONFIG_IP_FIB_TRIE_STATS is not set
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_IP_ROUTE_CLASSID=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+CONFIG_NET_IPIP=y
+CONFIG_NET_IPGRE_DEMUX=m
+CONFIG_NET_IP_TUNNEL=y
+CONFIG_NET_IPGRE=m
+# CONFIG_NET_IPGRE_BROADCAST is not set
+# CONFIG_IP_MROUTE is not set
+CONFIG_SYN_COOKIES=y
+CONFIG_NET_IPVTI=m
+CONFIG_INET_AH=m
+CONFIG_INET_ESP=m
+CONFIG_INET_IPCOMP=m
+CONFIG_INET_XFRM_TUNNEL=m
+CONFIG_INET_TUNNEL=y
+CONFIG_INET_XFRM_MODE_TRANSPORT=m
+CONFIG_INET_XFRM_MODE_TUNNEL=m
+CONFIG_INET_XFRM_MODE_BEET=m
+CONFIG_INET_LRO=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_INET_UDP_DIAG is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+CONFIG_IPV6=m
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_IPV6_OPTIMISTIC_DAD is not set
+# CONFIG_INET6_AH is not set
+# CONFIG_INET6_ESP is not set
+# CONFIG_INET6_IPCOMP is not set
+# CONFIG_IPV6_MIP6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+CONFIG_INET6_XFRM_MODE_TRANSPORT=m
+CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_BEET=m
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+# CONFIG_IPV6_VTI is not set
+CONFIG_IPV6_SIT=m
+# CONFIG_IPV6_SIT_6RD is not set
+CONFIG_IPV6_NDISC_NODETYPE=y
+# CONFIG_IPV6_TUNNEL is not set
+# CONFIG_IPV6_GRE is not set
+# CONFIG_IPV6_MULTIPLE_TABLES is not set
+# CONFIG_IPV6_MROUTE is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETWORK_PHY_TIMESTAMPING is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_NETFILTER_ADVANCED=y
+CONFIG_BRIDGE_NETFILTER=y
+
+#
+# Core Netfilter Configuration
+#
+# CONFIG_NETFILTER_NETLINK_ACCT is not set
+# CONFIG_NETFILTER_NETLINK_QUEUE is not set
+# CONFIG_NETFILTER_NETLINK_LOG is not set
+# CONFIG_NF_CONNTRACK is not set
+CONFIG_NETFILTER_XTABLES=y
+
+#
+# Xtables combined modules
+#
+CONFIG_NETFILTER_XT_MARK=y
+
+#
+# Xtables targets
+#
+# CONFIG_NETFILTER_XT_TARGET_CHECKSUM is not set
+# CONFIG_NETFILTER_XT_TARGET_CLASSIFY is not set
+# CONFIG_NETFILTER_XT_TARGET_DSCP is not set
+CONFIG_NETFILTER_XT_TARGET_HL=m
+# CONFIG_NETFILTER_XT_TARGET_HMARK is not set
+# CONFIG_NETFILTER_XT_TARGET_IDLETIMER is not set
+# CONFIG_NETFILTER_XT_TARGET_LOG is not set
+CONFIG_NETFILTER_XT_TARGET_MARK=y
+# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set
+# CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set
+# CONFIG_NETFILTER_XT_TARGET_RATEEST is not set
+# CONFIG_NETFILTER_XT_TARGET_TEE is not set
+# CONFIG_NETFILTER_XT_TARGET_TPROXY is not set
+# CONFIG_NETFILTER_XT_TARGET_TRACE is not set
+# CONFIG_NETFILTER_XT_TARGET_TCPMSS is not set
+# CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP is not set
+
+#
+# Xtables matches
+#
+# CONFIG_NETFILTER_XT_MATCH_ADDRTYPE is not set
+# CONFIG_NETFILTER_XT_MATCH_BPF is not set
+# CONFIG_NETFILTER_XT_MATCH_COMMENT is not set
+# CONFIG_NETFILTER_XT_MATCH_CPU is not set
+# CONFIG_NETFILTER_XT_MATCH_DCCP is not set
+# CONFIG_NETFILTER_XT_MATCH_DEVGROUP is not set
+CONFIG_NETFILTER_XT_MATCH_DSCP=y
+CONFIG_NETFILTER_XT_MATCH_ECN=y
+CONFIG_NETFILTER_XT_MATCH_ESP=y
+# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set
+CONFIG_NETFILTER_XT_MATCH_HL=y
+# CONFIG_NETFILTER_XT_MATCH_IPRANGE is not set
+# CONFIG_NETFILTER_XT_MATCH_LENGTH is not set
+CONFIG_NETFILTER_XT_MATCH_LIMIT=y
+CONFIG_NETFILTER_XT_MATCH_MAC=y
+CONFIG_NETFILTER_XT_MATCH_MARK=y
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y
+# CONFIG_NETFILTER_XT_MATCH_NFACCT is not set
+# CONFIG_NETFILTER_XT_MATCH_OWNER is not set
+# CONFIG_NETFILTER_XT_MATCH_POLICY is not set
+# CONFIG_NETFILTER_XT_MATCH_PHYSDEV is not set
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
+# CONFIG_NETFILTER_XT_MATCH_QUOTA is not set
+# CONFIG_NETFILTER_XT_MATCH_RATEEST is not set
+# CONFIG_NETFILTER_XT_MATCH_REALM is not set
+# CONFIG_NETFILTER_XT_MATCH_RECENT is not set
+# CONFIG_NETFILTER_XT_MATCH_SCTP is not set
+# CONFIG_NETFILTER_XT_MATCH_SOCKET is not set
+# CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set
+# CONFIG_NETFILTER_XT_MATCH_STRING is not set
+CONFIG_NETFILTER_XT_MATCH_TCPMSS=y
+# CONFIG_NETFILTER_XT_MATCH_TIME is not set
+# CONFIG_NETFILTER_XT_MATCH_U32 is not set
+# CONFIG_IP_SET is not set
+# CONFIG_IP_VS is not set
+
+#
+# IP: Netfilter Configuration
+#
+# CONFIG_NF_DEFRAG_IPV4 is not set
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_AH=m
+CONFIG_IP_NF_MATCH_ECN=m
+# CONFIG_IP_NF_MATCH_RPFILTER is not set
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+# CONFIG_IP_NF_TARGET_ULOG is not set
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_TTL=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_ARPTABLES=y
+CONFIG_IP_NF_ARPFILTER=y
+CONFIG_IP_NF_ARP_MANGLE=y
+
+#
+# IPv6: Netfilter Configuration
+#
+# CONFIG_NF_DEFRAG_IPV6 is not set
+# CONFIG_IP6_NF_IPTABLES is not set
+# CONFIG_BRIDGE_NF_EBTABLES is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_RDS is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+CONFIG_L2TP=m
+CONFIG_L2TP_V3=y
+CONFIG_L2TP_IP=m
+CONFIG_L2TP_ETH=m
+CONFIG_STP=m
+CONFIG_BRIDGE=m
+CONFIG_BRIDGE_IGMP_SNOOPING=y
+# CONFIG_BRIDGE_VLAN_FILTERING is not set
+CONFIG_HAVE_NET_DSA=y
+CONFIG_VLAN_8021Q=y
+# CONFIG_VLAN_8021Q_GVRP is not set
+# CONFIG_VLAN_8021Q_MVRP is not set
+# CONFIG_DECNET is not set
+CONFIG_LLC=y
+CONFIG_LLC2=y
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+CONFIG_X25=y
+CONFIG_LAPB=m
+# CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
+CONFIG_NET_SCHED=y
+
+#
+# Queueing/Scheduling
+#
+CONFIG_NET_SCH_CBQ=y
+CONFIG_NET_SCH_HTB=y
+CONFIG_NET_SCH_HFSC=y
+CONFIG_NET_SCH_PRIO=y
+# CONFIG_NET_SCH_MULTIQ is not set
+CONFIG_NET_SCH_RED=y
+# CONFIG_NET_SCH_SFB is not set
+CONFIG_NET_SCH_SFQ=y
+CONFIG_NET_SCH_TEQL=y
+CONFIG_NET_SCH_TBF=y
+CONFIG_NET_SCH_GRED=y
+CONFIG_NET_SCH_DSMARK=y
+CONFIG_NET_SCH_NETEM=y
+# CONFIG_NET_SCH_DRR is not set
+# CONFIG_NET_SCH_MQPRIO is not set
+# CONFIG_NET_SCH_CHOKE is not set
+# CONFIG_NET_SCH_QFQ is not set
+# CONFIG_NET_SCH_CODEL is not set
+# CONFIG_NET_SCH_FQ_CODEL is not set
+# CONFIG_NET_SCH_FQ is not set
+CONFIG_NET_SCH_INGRESS=y
+# CONFIG_NET_SCH_PLUG is not set
+
+#
+# Classification
+#
+CONFIG_NET_CLS=y
+CONFIG_NET_CLS_BASIC=y
+CONFIG_NET_CLS_TCINDEX=y
+CONFIG_NET_CLS_ROUTE4=y
+CONFIG_NET_CLS_FW=y
+CONFIG_NET_CLS_U32=y
+CONFIG_CLS_U32_PERF=y
+CONFIG_CLS_U32_MARK=y
+CONFIG_NET_CLS_RSVP=y
+CONFIG_NET_CLS_RSVP6=y
+# CONFIG_NET_CLS_FLOW is not set
+# CONFIG_NET_CLS_BPF is not set
+CONFIG_NET_EMATCH=y
+CONFIG_NET_EMATCH_STACK=32
+CONFIG_NET_EMATCH_CMP=y
+CONFIG_NET_EMATCH_NBYTE=y
+CONFIG_NET_EMATCH_U32=y
+CONFIG_NET_EMATCH_META=y
+CONFIG_NET_EMATCH_TEXT=y
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_ACT_POLICE=y
+CONFIG_NET_ACT_GACT=y
+CONFIG_GACT_PROB=y
+CONFIG_NET_ACT_MIRRED=y
+CONFIG_NET_ACT_IPT=m
+# CONFIG_NET_ACT_NAT is not set
+CONFIG_NET_ACT_PEDIT=y
+# CONFIG_NET_ACT_SIMP is not set
+# CONFIG_NET_ACT_SKBEDIT is not set
+# CONFIG_NET_ACT_CSUM is not set
+CONFIG_NET_CLS_IND=y
+CONFIG_NET_SCH_FIFO=y
+# CONFIG_DCB is not set
+CONFIG_DNS_RESOLVER=y
+# CONFIG_BATMAN_ADV is not set
+# CONFIG_OPENVSWITCH is not set
+# CONFIG_VSOCKETS is not set
+# CONFIG_NETLINK_MMAP is not set
+# CONFIG_NETLINK_DIAG is not set
+# CONFIG_NET_MPLS_GSO is not set
+# CONFIG_HSR is not set
+CONFIG_NET_RX_BUSY_POLL=y
+CONFIG_BQL=y
+# CONFIG_BPF_JIT is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+CONFIG_FIB_RULES=y
+# CONFIG_WIRELESS is not set
+# CONFIG_WIMAX is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+# CONFIG_CAIF is not set
+# CONFIG_CEPH_LIB is not set
+# CONFIG_NFC is not set
+CONFIG_HAVE_BPF_JIT=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH=""
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_GENERIC_CPU_DEVICES is not set
+# CONFIG_DMA_SHARED_BUFFER is not set
+
+#
+# Bus devices
+#
+# CONFIG_ARM_CCI is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_TESTS is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_SM_FTL is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_CFI_NOSWAP=y
+# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
+# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
+CONFIG_MTD_CFI_GEOMETRY=y
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_OTP is not set
+CONFIG_MTD_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_XIP is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+CONFIG_MTD_PXA2XX=y
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOCG3 is not set
+# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+# CONFIG_MTD_UBI is not set
+# CONFIG_PARPORT is not set
+CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_NULL_BLK is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_LOOP_MIN_COUNT=2
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_DRBD is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_MG_DISK is not set
+# CONFIG_BLK_DEV_RBD is not set
+
+#
+# Misc devices
+#
+# CONFIG_SENSORS_LIS3LV02D is not set
+# CONFIG_AD525X_DPOT is not set
+# CONFIG_ATMEL_PWM is not set
+# CONFIG_DUMMY_IRQ is not set
+# CONFIG_ICS932S401 is not set
+# CONFIG_ATMEL_SSC is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_APDS9802ALS is not set
+# CONFIG_ISL29003 is not set
+# CONFIG_ISL29020 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_SENSORS_BH1780 is not set
+# CONFIG_SENSORS_BH1770 is not set
+# CONFIG_SENSORS_APDS990X is not set
+# CONFIG_HMC6352 is not set
+# CONFIG_DS1682 is not set
+# CONFIG_BMP085_I2C is not set
+# CONFIG_USB_SWITCH_FSA9480 is not set
+# CONFIG_SRAM is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
+# CONFIG_EEPROM_93CX6 is not set
+
+#
+# Texas Instruments shared transport line discipline
+#
+# CONFIG_TI_ST is not set
+# CONFIG_SENSORS_LIS3_I2C is not set
+
+#
+# Altera FPGA firmware download module
+#
+# CONFIG_ALTERA_STAPL is not set
+
+#
+# Intel MIC Host Driver
+#
+
+#
+# Intel MIC Card Driver
+#
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI_MOD=y
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_SCSI_PROC_FS is not set
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+# CONFIG_SCSI_LOWLEVEL is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+# CONFIG_TARGET_CORE is not set
+CONFIG_NETDEVICES=y
+CONFIG_MII=m
+CONFIG_NET_CORE=y
+CONFIG_BONDING=m
+# CONFIG_DUMMY is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_IFB is not set
+# CONFIG_NET_TEAM is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_VXLAN is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+CONFIG_TUN=m
+# CONFIG_VETH is not set
+# CONFIG_NLMON is not set
+
+#
+# CAIF transport drivers
+#
+
+#
+# Distributed Switch Architecture drivers
+#
+# CONFIG_NET_DSA_MV88E6XXX is not set
+# CONFIG_NET_DSA_MV88E6060 is not set
+# CONFIG_NET_DSA_MV88E6XXX_NEED_PPU is not set
+# CONFIG_NET_DSA_MV88E6131 is not set
+# CONFIG_NET_DSA_MV88E6123_61_65 is not set
+CONFIG_ETHERNET=y
+# CONFIG_NET_VENDOR_ARC is not set
+# CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_CALXEDA_XGMAC is not set
+# CONFIG_NET_VENDOR_CIRRUS is not set
+CONFIG_DM9000=m
+CONFIG_DM9000_FORCE_SIMPLE_PHY_POLL=y
+# CONFIG_DNET is not set
+# CONFIG_NET_VENDOR_FARADAY is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_ETHOC is not set
+# CONFIG_SH_ETH is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+# CONFIG_PHYLIB is not set
+CONFIG_PPP=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_DEFLATE=m
+# CONFIG_PPP_FILTER is not set
+# CONFIG_PPP_MPPE is not set
+# CONFIG_PPP_MULTILINK is not set
+CONFIG_PPPOE=m
+CONFIG_PPTP=m
+CONFIG_PPPOL2TP=m
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_SLIP=m
+CONFIG_SLHC=m
+CONFIG_SLIP_COMPRESSED=y
+# CONFIG_SLIP_SMART is not set
+# CONFIG_SLIP_MODE_SLIP6 is not set
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_RTL8152 is not set
+# CONFIG_USB_USBNET is not set
+# CONFIG_USB_IPHETH is not set
+# CONFIG_WLAN is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+# CONFIG_WAN is not set
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+# CONFIG_INPUT_SPARSEKMAP is not set
+# CONFIG_INPUT_MATRIXKMAP is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=800
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=600
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_TTY=y
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_N_GSM is not set
+# CONFIG_TRACE_SINK is not set
+# CONFIG_DEVKMEM is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=m
+CONFIG_SERIAL_8250_DEPRECATED_OPTIONS=y
+CONFIG_SERIAL_8250_NR_UARTS=36
+CONFIG_SERIAL_8250_RUNTIME_UARTS=36
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+# CONFIG_SERIAL_8250_DETECT_IRQ is not set
+# CONFIG_SERIAL_8250_RSA is not set
+# CONFIG_SERIAL_8250_DW is not set
+# CONFIG_SERIAL_8250_EM is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_PXA=y
+CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_PXA_AS_TTYSA=y
+# CONFIG_SERIAL_SH_SCI is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_SCCNXP is not set
+# CONFIG_SERIAL_TIMBERDALE is not set
+# CONFIG_SERIAL_ALTERA_JTAGUART is not set
+# CONFIG_SERIAL_ALTERA_UART is not set
+# CONFIG_SERIAL_ARC is not set
+# CONFIG_SERIAL_FSL_LPUART is not set
+# CONFIG_SERIAL_ST_ASC is not set
+# CONFIG_TTY_PRINTK is not set
+# CONFIG_HVC_DCC is not set
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_HW_RANDOM_TIMERIOMEM is not set
+# CONFIG_HW_RANDOM_ATMEL is not set
+# CONFIG_HW_RANDOM_EXYNOS is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_I2C=m
+CONFIG_I2C_BOARDINFO=y
+# CONFIG_I2C_COMPAT is not set
+# CONFIG_I2C_CHARDEV is not set
+# CONFIG_I2C_MUX is not set
+CONFIG_I2C_HELPER_AUTO=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_CBUS_GPIO is not set
+# CONFIG_I2C_DESIGNWARE_PLATFORM is not set
+# CONFIG_I2C_GPIO is not set
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_PCA_PLATFORM is not set
+CONFIG_I2C_PXA=m
+# CONFIG_I2C_PXA_PCI is not set
+CONFIG_I2C_PXA_SLAVE=y
+# CONFIG_I2C_SH_MOBILE is not set
+# CONFIG_I2C_SIMTEC is not set
+# CONFIG_I2C_XILINX is not set
+# CONFIG_I2C_RCAR is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_DIOLAN_U2C is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_SPI is not set
+# CONFIG_HSI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
+
+#
+# PPS generators support
+#
+
+#
+# PTP clock support
+#
+# CONFIG_PTP_1588_CLOCK is not set
+
+#
+# Enable PHYLIB and NETWORK_PHY_TIMESTAMPING to see the additional clocks.
+#
+CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+CONFIG_GPIO_DEVRES=y
+# CONFIG_DEBUG_GPIO is not set
+# CONFIG_GPIO_SYSFS is not set
+
+#
+# Memory mapped GPIO drivers:
+#
+# CONFIG_GPIO_GENERIC_PLATFORM is not set
+CONFIG_GPIO_PXA=y
+# CONFIG_GPIO_RCAR is not set
+# CONFIG_GPIO_TS5500 is not set
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_MAX7300 is not set
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCF857X is not set
+# CONFIG_GPIO_ADP5588 is not set
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_GPIO_MCP23S08 is not set
+
+#
+# AC97 GPIO expanders:
+#
+
+#
+# LPC GPIO expanders:
+#
+
+#
+# MODULbus GPIO expanders:
+#
+
+#
+# USB GPIO expanders:
+#
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_POWER_AVS is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_CORE is not set
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_SA1100_WATCHDOG=m
+# CONFIG_DW_WATCHDOG is not set
+# CONFIG_MAX63XX_WATCHDOG is not set
+# CONFIG_MEN_A21_WDT is not set
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+CONFIG_BCMA_POSSIBLE=y
+
+#
+# Broadcom specific AMBA
+#
+# CONFIG_BCMA is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_CROS_EC is not set
+# CONFIG_MFD_ASIC3 is not set
+# CONFIG_MFD_MC13XXX_I2C is not set
+# CONFIG_HTC_EGPIO is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_KEMPLD is not set
+# CONFIG_MFD_VIPERBOARD is not set
+# CONFIG_MFD_RETU is not set
+# CONFIG_MFD_PCF50633 is not set
+# CONFIG_MFD_SI476X_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_ABX500_CORE is not set
+# CONFIG_MFD_SYSCON is not set
+# CONFIG_MFD_TI_AM335X_TSCADC is not set
+# CONFIG_TPS6105X is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_TPS6507X is not set
+# CONFIG_MFD_TPS65217 is not set
+# CONFIG_MFD_TPS65912 is not set
+# CONFIG_MFD_WL1273_CORE is not set
+# CONFIG_MFD_LM3533 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_MFD_TC6393XB is not set
+# CONFIG_MFD_ARIZONA_I2C is not set
+# CONFIG_VEXPRESS_CONFIG is not set
+# CONFIG_REGULATOR is not set
+# CONFIG_MEDIA_SUPPORT is not set
+
+#
+# Graphics support
+#
+# CONFIG_DRM is not set
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
+CONFIG_FB_CFB_FILLRECT=m
+CONFIG_FB_CFB_COPYAREA=m
+CONFIG_FB_CFB_IMAGEBLIT=m
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_S1D13XXX is not set
+CONFIG_FB_PXA=m
+# CONFIG_FB_PXA_OVERLAY is not set
+# CONFIG_FB_PXA_SMARTPANEL is not set
+# CONFIG_FB_PXA_PARAMETERS is not set
+# CONFIG_PXA3XX_GCU is not set
+# CONFIG_FB_MBX is not set
+# CONFIG_FB_W100 is not set
+# CONFIG_FB_SMSCUFX is not set
+# CONFIG_FB_UDL is not set
+# CONFIG_FB_GOLDFISH is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_BROADSHEET is not set
+# CONFIG_FB_AUO_K190X is not set
+# CONFIG_FB_SIMPLE is not set
+# CONFIG_EXYNOS_VIDEO is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Console display driver support
+#
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=m
+# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+CONFIG_LOGO=y
+CONFIG_LOGO_LINUX_MONO=y
+CONFIG_LOGO_LINUX_VGA16=y
+CONFIG_LOGO_LINUX_CLUT224=y
+# CONFIG_SOUND is not set
+
+#
+# HID support
+#
+CONFIG_HID=y
+# CONFIG_HIDRAW is not set
+# CONFIG_UHID is not set
+CONFIG_HID_GENERIC=m
+
+#
+# Special HID drivers
+#
+CONFIG_HID_A4TECH=m
+# CONFIG_HID_ACRUX is not set
+# CONFIG_HID_APPLE is not set
+# CONFIG_HID_APPLEIR is not set
+# CONFIG_HID_AUREAL is not set
+# CONFIG_HID_BELKIN is not set
+# CONFIG_HID_CHERRY is not set
+# CONFIG_HID_CHICONY is not set
+CONFIG_HID_CYPRESS=m
+# CONFIG_HID_DRAGONRISE is not set
+# CONFIG_HID_EMS_FF is not set
+# CONFIG_HID_ELECOM is not set
+# CONFIG_HID_ELO is not set
+# CONFIG_HID_EZKEY is not set
+# CONFIG_HID_HOLTEK is not set
+# CONFIG_HID_HUION is not set
+CONFIG_HID_KEYTOUCH=m
+# CONFIG_HID_KYE is not set
+# CONFIG_HID_UCLOGIC is not set
+# CONFIG_HID_WALTOP is not set
+# CONFIG_HID_GYRATION is not set
+# CONFIG_HID_ICADE is not set
+# CONFIG_HID_TWINHAN is not set
+CONFIG_HID_KENSINGTON=m
+# CONFIG_HID_LCPOWER is not set
+# CONFIG_HID_LENOVO_TPKBD is not set
+CONFIG_HID_LOGITECH=m
+# CONFIG_HID_LOGITECH_DJ is not set
+# CONFIG_LOGITECH_FF is not set
+# CONFIG_LOGIRUMBLEPAD2_FF is not set
+# CONFIG_LOGIG940_FF is not set
+# CONFIG_LOGIWHEELS_FF is not set
+# CONFIG_HID_MAGICMOUSE is not set
+CONFIG_HID_MICROSOFT=m
+CONFIG_HID_MONTEREY=m
+# CONFIG_HID_MULTITOUCH is not set
+# CONFIG_HID_NTRIG is not set
+# CONFIG_HID_ORTEK is not set
+# CONFIG_HID_PANTHERLORD is not set
+# CONFIG_HID_PETALYNX is not set
+# CONFIG_HID_PICOLCD is not set
+# CONFIG_HID_PRIMAX is not set
+# CONFIG_HID_ROCCAT is not set
+# CONFIG_HID_SAITEK is not set
+# CONFIG_HID_SAMSUNG is not set
+# CONFIG_HID_SPEEDLINK is not set
+# CONFIG_HID_STEELSERIES is not set
+# CONFIG_HID_SUNPLUS is not set
+# CONFIG_HID_GREENASIA is not set
+# CONFIG_HID_SMARTJOYPLUS is not set
+# CONFIG_HID_TIVO is not set
+# CONFIG_HID_TOPSEED is not set
+# CONFIG_HID_THRUSTMASTER is not set
+# CONFIG_HID_XINMO is not set
+# CONFIG_HID_ZEROPLUS is not set
+# CONFIG_HID_ZYDACRON is not set
+# CONFIG_HID_SENSOR_HUB is not set
+
+#
+# USB HID support
+#
+CONFIG_USB_HID=m
+# CONFIG_HID_PID is not set
+CONFIG_USB_HIDDEV=y
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+
+#
+# I2C HID support
+#
+CONFIG_I2C_HID=m
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_COMMON=m
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB=m
+# CONFIG_USB_DEBUG is not set
+# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEFAULT_PERSIST=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+# CONFIG_USB_MON is not set
+# CONFIG_USB_WUSB_CBAF is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_XHCI_HCD is not set
+# CONFIG_USB_EHCI_HCD is not set
+# CONFIG_USB_OXU210HP_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1760_HCD is not set
+# CONFIG_USB_ISP1362_HCD is not set
+# CONFIG_USB_FUSBH200_HCD is not set
+# CONFIG_USB_FOTG210_HCD is not set
+CONFIG_USB_OHCI_HCD=m
+CONFIG_USB_OHCI_HCD_PXA27X=m
+# CONFIG_USB_OHCI_HCD_PLATFORM is not set
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_HCD_TEST_MODE is not set
+
+#
+# USB Device Class drivers
+#
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+# CONFIG_USB_WDM is not set
+# CONFIG_USB_TMC is not set
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
+#
+
+#
+# also be needed; see USB_STORAGE Help for more info
+#
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+CONFIG_USB_STORAGE_REALTEK=m
+CONFIG_USB_STORAGE_DATAFAB=m
+CONFIG_USB_STORAGE_FREECOM=m
+CONFIG_USB_STORAGE_ISD200=m
+CONFIG_USB_STORAGE_USBAT=m
+CONFIG_USB_STORAGE_SDDR09=m
+CONFIG_USB_STORAGE_SDDR55=m
+CONFIG_USB_STORAGE_JUMPSHOT=m
+CONFIG_USB_STORAGE_ALAUDA=m
+CONFIG_USB_STORAGE_ONETOUCH=m
+CONFIG_USB_STORAGE_KARMA=m
+CONFIG_USB_STORAGE_CYPRESS_ATACB=m
+CONFIG_USB_STORAGE_ENE_UB6250=m
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+# CONFIG_USB_DWC3 is not set
+
+#
+# USB port drivers
+#
+CONFIG_USB_SERIAL=m
+CONFIG_USB_SERIAL_GENERIC=y
+CONFIG_USB_SERIAL_SIMPLE=m
+CONFIG_USB_SERIAL_AIRCABLE=m
+CONFIG_USB_SERIAL_ARK3116=m
+CONFIG_USB_SERIAL_BELKIN=m
+CONFIG_USB_SERIAL_CH341=m
+CONFIG_USB_SERIAL_WHITEHEAT=m
+CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
+CONFIG_USB_SERIAL_CP210X=m
+CONFIG_USB_SERIAL_CYPRESS_M8=m
+CONFIG_USB_SERIAL_EMPEG=m
+CONFIG_USB_SERIAL_FTDI_SIO=m
+CONFIG_USB_SERIAL_VISOR=m
+CONFIG_USB_SERIAL_IPAQ=m
+CONFIG_USB_SERIAL_IR=m
+CONFIG_USB_SERIAL_EDGEPORT=m
+CONFIG_USB_SERIAL_EDGEPORT_TI=m
+CONFIG_USB_SERIAL_F81232=m
+CONFIG_USB_SERIAL_GARMIN=m
+CONFIG_USB_SERIAL_IPW=m
+CONFIG_USB_SERIAL_IUU=m
+CONFIG_USB_SERIAL_KEYSPAN_PDA=m
+CONFIG_USB_SERIAL_KEYSPAN=m
+CONFIG_USB_SERIAL_KLSI=m
+CONFIG_USB_SERIAL_KOBIL_SCT=m
+CONFIG_USB_SERIAL_MCT_U232=m
+CONFIG_USB_SERIAL_METRO=m
+CONFIG_USB_SERIAL_MOS7720=m
+CONFIG_USB_SERIAL_MOS7840=m
+CONFIG_USB_SERIAL_NAVMAN=m
+CONFIG_USB_SERIAL_PL2303=m
+CONFIG_USB_SERIAL_OTI6858=m
+CONFIG_USB_SERIAL_QCAUX=m
+CONFIG_USB_SERIAL_QUALCOMM=m
+CONFIG_USB_SERIAL_SPCP8X5=m
+CONFIG_USB_SERIAL_SAFE=m
+CONFIG_USB_SERIAL_SAFE_PADDED=y
+CONFIG_USB_SERIAL_SIERRAWIRELESS=m
+CONFIG_USB_SERIAL_SYMBOL=m
+CONFIG_USB_SERIAL_TI=m
+CONFIG_USB_SERIAL_CYBERJACK=m
+CONFIG_USB_SERIAL_XIRCOM=m
+CONFIG_USB_SERIAL_WWAN=m
+CONFIG_USB_SERIAL_OPTION=m
+CONFIG_USB_SERIAL_OMNINET=m
+CONFIG_USB_SERIAL_OPTICON=m
+CONFIG_USB_SERIAL_XSENS_MT=m
+CONFIG_USB_SERIAL_WISHBONE=m
+CONFIG_USB_SERIAL_ZTE=m
+CONFIG_USB_SERIAL_SSU100=m
+CONFIG_USB_SERIAL_QT2=m
+# CONFIG_USB_SERIAL_DEBUG is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_TEST is not set
+# CONFIG_USB_EHSET_TEST_FIXTURE is not set
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_YUREX is not set
+CONFIG_USB_EZUSB_FX2=m
+# CONFIG_USB_HSIC_USB3503 is not set
+
+#
+# USB Physical Layer drivers
+#
+# CONFIG_USB_PHY is not set
+# CONFIG_NOP_USB_XCEIV is not set
+# CONFIG_AM335X_PHY_USB is not set
+# CONFIG_SAMSUNG_USB2PHY is not set
+# CONFIG_SAMSUNG_USB3PHY is not set
+# CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_USB_ISP1301 is not set
+# CONFIG_USB_RCAR_PHY is not set
+# CONFIG_USB_ULPI is not set
+# CONFIG_USB_GADGET is not set
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+# CONFIG_MMC_UNSAFE_RESUME is not set
+# CONFIG_MMC_CLKGATE is not set
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_MINORS=8
+CONFIG_MMC_BLOCK_BOUNCE=y
+# CONFIG_SDIO_UART is not set
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+CONFIG_MMC_PXA=y
+# CONFIG_MMC_SDHCI is not set
+# CONFIG_MMC_SDHCI_PXAV3 is not set
+# CONFIG_MMC_SDHCI_PXAV2 is not set
+# CONFIG_MMC_DW is not set
+# CONFIG_MMC_VUB300 is not set
+# CONFIG_MMC_USHC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_EDAC is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_SYSTOHC=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_DS3232 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_ISL12022 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF2127 is not set
+# CONFIG_RTC_DRV_PCF8523 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_BQ32K is not set
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
+# CONFIG_RTC_DRV_EM3027 is not set
+# CONFIG_RTC_DRV_RV3029C2 is not set
+
+#
+# SPI RTC drivers
+#
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_MSM6242 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_RP5C01 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+# CONFIG_RTC_DRV_DS2404 is not set
+
+#
+# on-CPU RTC drivers
+#
+# CONFIG_RTC_DRV_SA1100 is not set
+# CONFIG_RTC_DRV_PXA is not set
+# CONFIG_RTC_DRV_MOXART is not set
+
+#
+# HID Sensor RTC drivers
+#
+# CONFIG_RTC_DRV_HID_SENSOR_TIME is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_UIO is not set
+# CONFIG_VIRT_DRIVERS is not set
+
+#
+# Virtio drivers
+#
+# CONFIG_VIRTIO_MMIO is not set
+
+#
+# Microsoft Hyper-V guest support
+#
+# CONFIG_STAGING is not set
+CONFIG_CLKDEV_LOOKUP=y
+
+#
+# Hardware Spinlock drivers
+#
+CONFIG_CLKSRC_MMIO=y
+# CONFIG_ARM_ARCH_TIMER_EVTSTREAM is not set
+# CONFIG_MAILBOX is not set
+# CONFIG_IOMMU_SUPPORT is not set
+
+#
+# Remoteproc drivers
+#
+# CONFIG_STE_MODEM_RPROC is not set
+
+#
+# Rpmsg drivers
+#
+# CONFIG_PM_DEVFREQ is not set
+# CONFIG_EXTCON is not set
+# CONFIG_MEMORY is not set
+# CONFIG_IIO is not set
+# CONFIG_PWM is not set
+# CONFIG_IPACK_BUS is not set
+# CONFIG_RESET_CONTROLLER is not set
+# CONFIG_FMC is not set
+
+#
+# PHY Subsystem
+#
+# CONFIG_GENERIC_PHY is not set
+# CONFIG_PHY_EXYNOS_MIPI_VIDEO is not set
+# CONFIG_POWERCAP is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=m
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+CONFIG_EXT2_FS_XIP=y
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_DEFAULTS_TO_ORDERED=y
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_EXT4_FS=y
+CONFIG_EXT4_FS_POSIX_ACL=y
+CONFIG_EXT4_FS_SECURITY=y
+# CONFIG_EXT4_DEBUG is not set
+CONFIG_FS_XIP=y
+CONFIG_JBD=y
+CONFIG_JBD2=y
+# CONFIG_JBD2_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+CONFIG_REISERFS_PROC_INFO=y
+CONFIG_REISERFS_FS_XATTR=y
+CONFIG_REISERFS_FS_POSIX_ACL=y
+CONFIG_REISERFS_FS_SECURITY=y
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_BTRFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+CONFIG_FS_POSIX_ACL=y
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_FANOTIFY is not set
+# CONFIG_QUOTA is not set
+# CONFIG_QUOTACTL is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+CONFIG_NTFS_FS=m
+# CONFIG_NTFS_DEBUG is not set
+CONFIG_NTFS_RW=y
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_ECRYPT_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_JFFS2_ZLIB=y
+# CONFIG_JFFS2_LZO is not set
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_JFFS2_CMODE_NONE is not set
+CONFIG_JFFS2_CMODE_PRIORITY=y
+# CONFIG_JFFS2_CMODE_SIZE is not set
+# CONFIG_JFFS2_CMODE_FAVOURLZO is not set
+# CONFIG_LOGFS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX6FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_PSTORE is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_F2FS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=m
+CONFIG_NFS_V2=m
+CONFIG_NFS_V3=m
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=m
+# CONFIG_NFS_SWAP is not set
+CONFIG_NFS_V4_1=y
+CONFIG_NFS_V4_2=y
+CONFIG_PNFS_FILE_LAYOUT=m
+CONFIG_NFS_V4_1_IMPLEMENTATION_ID_DOMAIN="kernel.org"
+# CONFIG_NFS_V4_1_MIGRATION is not set
+# CONFIG_NFS_USE_LEGACY_DNS is not set
+CONFIG_NFS_USE_KERNEL_DNS=y
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_ACL_SUPPORT=m
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=m
+CONFIG_SUNRPC_GSS=m
+CONFIG_SUNRPC_BACKCHANNEL=y
+CONFIG_RPCSEC_GSS_KRB5=m
+# CONFIG_SUNRPC_DEBUG is not set
+# CONFIG_CEPH_FS is not set
+CONFIG_CIFS=m
+CONFIG_CIFS_STATS=y
+# CONFIG_CIFS_STATS2 is not set
+# CONFIG_CIFS_WEAK_PW_HASH is not set
+# CONFIG_CIFS_UPCALL is not set
+# CONFIG_CIFS_XATTR is not set
+CONFIG_CIFS_DEBUG=y
+# CONFIG_CIFS_DEBUG2 is not set
+# CONFIG_CIFS_DFS_UPCALL is not set
+# CONFIG_CIFS_SMB2 is not set
+# CONFIG_NCP_FS is not set
+CONFIG_CODA_FS=m
+# CONFIG_AFS_FS is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="cp1251"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+CONFIG_NLS_CODEPAGE_850=y
+CONFIG_NLS_CODEPAGE_852=y
+CONFIG_NLS_CODEPAGE_855=y
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+CONFIG_NLS_CODEPAGE_863=y
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+CONFIG_NLS_CODEPAGE_866=y
+# CONFIG_NLS_CODEPAGE_869 is not set
+CONFIG_NLS_CODEPAGE_936=y
+CONFIG_NLS_CODEPAGE_950=y
+CONFIG_NLS_CODEPAGE_932=y
+CONFIG_NLS_CODEPAGE_949=y
+CONFIG_NLS_CODEPAGE_874=y
+CONFIG_NLS_ISO8859_8=y
+# CONFIG_NLS_CODEPAGE_1250 is not set
+CONFIG_NLS_CODEPAGE_1251=y
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+CONFIG_NLS_ISO8859_15=y
+CONFIG_NLS_KOI8_R=y
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_MAC_ROMAN is not set
+# CONFIG_NLS_MAC_CELTIC is not set
+# CONFIG_NLS_MAC_CENTEURO is not set
+# CONFIG_NLS_MAC_CROATIAN is not set
+# CONFIG_NLS_MAC_CYRILLIC is not set
+# CONFIG_NLS_MAC_GAELIC is not set
+# CONFIG_NLS_MAC_GREEK is not set
+# CONFIG_NLS_MAC_ICELAND is not set
+# CONFIG_NLS_MAC_INUIT is not set
+# CONFIG_NLS_MAC_ROMANIAN is not set
+# CONFIG_NLS_MAC_TURKISH is not set
+CONFIG_NLS_UTF8=y
+
+#
+# Kernel hacking
+#
+
+#
+# printk and dmesg options
+#
+CONFIG_PRINTK_TIME=y
+CONFIG_DEFAULT_MESSAGE_LOGLEVEL=4
+# CONFIG_BOOT_PRINTK_DELAY is not set
+
+#
+# Compile-time checks and compiler options
+#
+# CONFIG_DEBUG_INFO is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+# CONFIG_STRIP_ASM_SYMS is not set
+# CONFIG_READABLE_ASM is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_SECTION_MISMATCH is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set
+# CONFIG_MAGIC_SYSRQ is not set
+CONFIG_DEBUG_KERNEL=y
+
+#
+# Memory Debugging
+#
+# CONFIG_DEBUG_PAGEALLOC is not set
+# CONFIG_DEBUG_OBJECTS is not set
+CONFIG_HAVE_DEBUG_KMEMLEAK=y
+# CONFIG_DEBUG_KMEMLEAK is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_DEBUG_SHIRQ is not set
+
+#
+# Debug Lockups and Hangs
+#
+# CONFIG_LOCKUP_DETECTOR is not set
+# CONFIG_DETECT_HUNG_TASK is not set
+# CONFIG_PANIC_ON_OOPS is not set
+CONFIG_PANIC_ON_OOPS_VALUE=0
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_PREEMPT is not set
+
+#
+# Lock Debugging (spinlocks, mutexes, etc...)
+#
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_ATOMIC_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+# CONFIG_DEBUG_CREDENTIALS is not set
+
+#
+# RCU Debugging
+#
+# CONFIG_PROVE_RCU_DELAY is not set
+# CONFIG_SPARSE_RCU_POINTER is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+CONFIG_RCU_CPU_STALL_TIMEOUT=21
+CONFIG_RCU_CPU_STALL_VERBOSE=y
+# CONFIG_RCU_CPU_STALL_INFO is not set
+# CONFIG_RCU_TRACE is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_NOTIFIER_ERROR_INJECTION is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
+CONFIG_HAVE_C_RECORDMCOUNT=y
+CONFIG_TRACING_SUPPORT=y
+# CONFIG_FTRACE is not set
+
+#
+# Runtime Testing
+#
+# CONFIG_TEST_LIST_SORT is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_RBTREE_TEST is not set
+# CONFIG_INTERVAL_TREE_TEST is not set
+# CONFIG_PERCPU_TEST is not set
+# CONFIG_ATOMIC64_SELFTEST is not set
+# CONFIG_TEST_STRING_HELPERS is not set
+# CONFIG_TEST_KSTRTOX is not set
+# CONFIG_DMA_API_DEBUG is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+# CONFIG_STRICT_DEVMEM is not set
+# CONFIG_ARM_UNWIND is not set
+# CONFIG_DEBUG_USER is not set
+# CONFIG_DEBUG_LL is not set
+CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S"
+# CONFIG_DEBUG_UART_PL01X is not set
+# CONFIG_DEBUG_UART_8250 is not set
+CONFIG_UNCOMPRESS_INCLUDE="mach/uncompress.h"
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+# CONFIG_PERSISTENT_KEYRINGS is not set
+# CONFIG_ENCRYPTED_KEYS is not set
+# CONFIG_KEYS_DEBUG_PROC_KEYS is not set
+# CONFIG_SECURITY_DMESG_RESTRICT is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+CONFIG_DEFAULT_SECURITY_DAC=y
+CONFIG_DEFAULT_SECURITY=""
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD=m
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG=m
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_PCOMP2=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+# CONFIG_CRYPTO_USER is not set
+CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y
+CONFIG_CRYPTO_GF128MUL=m
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_WORKQUEUE=y
+# CONFIG_CRYPTO_CRYPTD is not set
+CONFIG_CRYPTO_AUTHENC=m
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+CONFIG_CRYPTO_CCM=m
+CONFIG_CRYPTO_GCM=m
+CONFIG_CRYPTO_SEQIV=m
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_CTR=m
+CONFIG_CRYPTO_CTS=m
+CONFIG_CRYPTO_ECB=y
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+CONFIG_CRYPTO_CMAC=y
+CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_VMAC is not set
+
+#
+# Digest
+#
+CONFIG_CRYPTO_CRC32C=y
+# CONFIG_CRYPTO_CRC32 is not set
+# CONFIG_CRYPTO_CRCT10DIF is not set
+CONFIG_CRYPTO_GHASH=m
+CONFIG_CRYPTO_MD4=y
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA1_ARM=y
+CONFIG_CRYPTO_SHA256=y
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=y
+CONFIG_CRYPTO_AES_ARM=y
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_ARC4=y
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+CONFIG_CRYPTO_DEFLATE=m
+# CONFIG_CRYPTO_ZLIB is not set
+# CONFIG_CRYPTO_LZO is not set
+# CONFIG_CRYPTO_LZ4 is not set
+# CONFIG_CRYPTO_LZ4HC is not set
+
+#
+# Random Number Generation
+#
+CONFIG_CRYPTO_ANSI_CPRNG=m
+# CONFIG_CRYPTO_USER_API_HASH is not set
+# CONFIG_CRYPTO_USER_API_SKCIPHER is not set
+CONFIG_CRYPTO_HW=y
+# CONFIG_ASYMMETRIC_KEY_TYPE is not set
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_STRNCPY_FROM_USER=y
+CONFIG_GENERIC_STRNLEN_USER=y
+CONFIG_GENERIC_NET_UTILS=y
+CONFIG_GENERIC_PCI_IOMAP=y
+CONFIG_GENERIC_IO=y
+CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y
+CONFIG_CRC_CCITT=y
+CONFIG_CRC16=y
+# CONFIG_CRC_T10DIF is not set
+CONFIG_CRC_ITU_T=y
+CONFIG_CRC32=y
+# CONFIG_CRC32_SELFTEST is not set
+CONFIG_CRC32_SLICEBY8=y
+# CONFIG_CRC32_SLICEBY4 is not set
+# CONFIG_CRC32_SARWATE is not set
+# CONFIG_CRC32_BIT is not set
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+# CONFIG_CRC8 is not set
+# CONFIG_RANDOM32_SELFTEST is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+# CONFIG_XZ_DEC is not set
+# CONFIG_XZ_DEC_BCJ is not set
+CONFIG_TEXTSEARCH=y
+CONFIG_TEXTSEARCH_KMP=y
+CONFIG_TEXTSEARCH_BM=y
+CONFIG_TEXTSEARCH_FSM=y
+CONFIG_ASSOCIATIVE_ARRAY=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_DQL=y
+CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
+CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y
+# CONFIG_AVERAGE is not set
+# CONFIG_CORDIC is not set
+# CONFIG_DDR is not set
+CONFIG_OID_REGISTRY=m
+CONFIG_FONT_SUPPORT=m
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+# CONFIG_VIRTUALIZATION is not set
diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig
index 96100db..efaf2d0 100644
--- a/arch/arm/mach-pxa/Kconfig
+++ b/arch/arm/mach-pxa/Kconfig
@@ -273,6 +273,22 @@ config MACH_VPAC270
 
 comment "End-user Products (sorted by vendor name)"
 
+config MACH_LP8X4X
+	bool "ICP DAS LP-8X4X"
+	select IWMMXT
+	select PXA27x
+	help
+	  Say Y here if you intend to run this kernel on an ICP DAS
+	  LP-8x4x programmable automation controller.
+
+	  LP-8x4x is ARM-based and built around PXA270 SoC. The device
+	  has 128 MiB SDRAM, 48 or 96 MiB NOR flash, VGA port with
+	  800x600 resolution, MMC card slot, 2 Ethernet ports, 1 USB
+	  port, 5 serial ports (1 on them is wired internally to
+	  expansion slots). The device has a range of digital and
+	  analog expansion IO modules which can be installed in 1, 4 or
+	  8 slots depending on the model.
+
 config MACH_H4700
 	bool "HP iPAQ hx4700"
 	select HAVE_PWM
diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile
index 648867a..b264325 100644
--- a/arch/arm/mach-pxa/Makefile
+++ b/arch/arm/mach-pxa/Makefile
@@ -63,6 +63,7 @@ obj-$(CONFIG_MACH_COLIBRI320)	+= colibri-pxa3xx.o colibri-pxa320.o
 obj-$(CONFIG_MACH_VPAC270)	+= vpac270.o
 
 # End-user Products
+obj-$(CONFIG_MACH_LP8X4X)	+= lp8x4x.o
 obj-$(CONFIG_MACH_H4700)	+= hx4700.o
 obj-$(CONFIG_MACH_H5000)	+= h5000.o
 obj-$(CONFIG_MACH_HIMALAYA)	+= himalaya.o
diff --git a/arch/arm/mach-pxa/include/mach/lp8x4x.h b/arch/arm/mach-pxa/include/mach/lp8x4x.h
new file mode 100644
index 0000000..8c501fd
--- /dev/null
+++ b/arch/arm/mach-pxa/include/mach/lp8x4x.h
@@ -0,0 +1,74 @@
+/*
+ *  arch/arm/mach-pxa/include/mach/lp8x4x.h
+ *
+ *  Support for ICP DAS LP-8x4x programmable automation controller
+ *  Copyright (C) 2013 Sergei Ianovich <ynvich@gmail.com>
+ *
+ *  borrowed heavily from
+ *  Support for the Intel HCDDBBVA0 Development Platform.
+ *
+ *  Author:	Nicolas Pitre
+ *  Created:	Nov 14, 2002
+ *  Copyright:	MontaVista Software Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef ASM_ARCH_LP8X4X_H
+#define ASM_ARCH_LP8X4X_H
+
+#include <asm/io.h>
+#include <mach/irqs.h>
+
+#define LP8X4X_ETH0_BASE        0x0c000000
+#define LP8X4X_ETH0_IO          0x0c004000
+#define LP8X4X_ETH0_IRQ         PXA_GPIO_TO_IRQ(9)
+
+#define LP8X4X_ETH1_BASE        0x0d000000
+#define LP8X4X_ETH1_IO          0x0d004000
+#define LP8X4X_ETH1_IRQ         PXA_GPIO_TO_IRQ(82)
+
+#define LP8X4X_FPGA_PHYS	0x17000000
+#define LP8X4X_FPGA_VIRT	0xf1000000
+#define LP8X4X_P2V(x)		IOMEM((x) - LP8X4X_FPGA_PHYS + LP8X4X_FPGA_VIRT)
+#define LP8X4X_V2P(x)		((x) - LP8X4X_FPGA_VIRT + LP8X4X_FPGA_PHYS)
+
+/* board level registers in the FPGA */
+
+#define LP8X4X_EOI		LP8X4X_P2V(0x17009006)
+#define LP8X4X_INSINT		LP8X4X_P2V(0x17009008)
+#define LP8X4X_ENSYSINT		LP8X4X_P2V(0x1700900A)
+#define LP8X4X_PRIMINT		LP8X4X_P2V(0x1700900C)
+#define LP8X4X_SECOINT		LP8X4X_P2V(0x1700900E)
+#define LP8X4X_ENRISEINT	LP8X4X_P2V(0x17009010)
+#define LP8X4X_CLRRISEINT	LP8X4X_P2V(0x17009012)
+#define LP8X4X_ENHILVINT	LP8X4X_P2V(0x17009014)
+#define LP8X4X_CLRHILVINT	LP8X4X_P2V(0x17009016)
+#define LP8X4X_ENFALLINT	LP8X4X_P2V(0x17009018)
+#define LP8X4X_CLRFALLINT	LP8X4X_P2V(0x1700901a)
+
+/* board specific IRQs */
+
+#define LP8X4X_IRQ(x)		(IRQ_BOARD_START + (x))
+#define LP8X4X_SLOT1_IRQ	LP8X4X_IRQ(0)
+#define LP8X4X_SLOT2_IRQ	LP8X4X_IRQ(1)
+#define LP8X4X_SLOT3_IRQ	LP8X4X_IRQ(2)
+#define LP8X4X_SLOT4_IRQ	LP8X4X_IRQ(3)
+#define LP8X4X_SLOT5_IRQ	LP8X4X_IRQ(4)
+#define LP8X4X_SLOT6_IRQ	LP8X4X_IRQ(5)
+#define LP8X4X_SLOT7_IRQ	LP8X4X_IRQ(6)
+#define LP8X4X_SLOT8_IRQ	LP8X4X_IRQ(7)
+#define LP8X4X_TIMER1_IRQ	LP8X4X_IRQ(8)
+#define LP8X4X_TIMER2_IRQ	LP8X4X_IRQ(9)
+#define LP8X4X_TIMEROUT_IRQ	LP8X4X_IRQ(10)
+#define LP8X4X_HOTPLUG_IRQ	LP8X4X_IRQ(11)
+#define LP8X4X_BATLOW_IRQ	LP8X4X_IRQ(12)
+#define LP8X4X_TTYS0_IRQ	LP8X4X_IRQ(13)
+#define LP8X4X_TTYS1_IRQ	LP8X4X_IRQ(14)
+#define LP8X4X_TTYS2_IRQ	LP8X4X_IRQ(15)
+
+#define LP8X4X_NR_IRQS		(IRQ_BOARD_START + 16)
+
+#endif
diff --git a/arch/arm/mach-pxa/lp8x4x.c b/arch/arm/mach-pxa/lp8x4x.c
new file mode 100644
index 0000000..0b77e7a
--- /dev/null
+++ b/arch/arm/mach-pxa/lp8x4x.c
@@ -0,0 +1,460 @@
+/*
+ *  linux/arch/arm/mach-pxa/lp8x4x.c
+ *
+ *  Support for ICP DAS LP-8x4x programmable automation controller
+ *  Copyright (C) 2013 Sergei Ianovich <ynvich@gmail.com>
+ *
+ *  borrowed heavily from
+ *  Support for the Intel HCDDBBVA0 Development Platform.
+ *
+ *  Author:	Nicolas Pitre
+ *  Created:	Nov 05, 2002
+ *  Copyright:	MontaVista Software Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation or any later version.
+ */
+#include <linux/gpio.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/syscore_ops.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/bitops.h>
+#include <linux/fb.h>
+#include <linux/ioport.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/input.h>
+#include <linux/dm9000.h>
+#include <linux/slab.h>
+#include <linux/leds.h>
+#include <linux/ktime.h>
+#include <linux/irqchip/chained_irq.h>
+
+#include <asm/types.h>
+#include <asm/setup.h>
+#include <asm/memory.h>
+#include <asm/mach-types.h>
+#include <mach/hardware.h>
+#include <asm/irq.h>
+#include <asm/sizes.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+#include <asm/mach/flash.h>
+
+#include <mach/pxa27x.h>
+#include <mach/lp8x4x.h>
+#include <linux/platform_data/video-pxafb.h>
+#include <linux/platform_data/mmc-pxamci.h>
+#include <linux/platform_data/usb-ohci-pxa27x.h>
+#include <mach/smemc.h>
+
+#include "generic.h"
+#include "devices.h"
+
+static unsigned char lp8x4x_irq_sys_enabled;
+static unsigned char lp8x4x_irq_high_enabled;
+
+static void lp8x4x_ack_irq(struct irq_data *d)
+{
+	unsigned mask;
+	int irq = d->irq - IRQ_BOARD_START;
+
+	if (irq < 0 || irq > 15) {
+		pr_err("lp8x4x: wrong irq handler for irq %i\n", d->irq);
+		return;
+	}
+
+	if (irq < 8) {
+		mask = ioread8(LP8X4X_CLRHILVINT);
+		mask |= 1 << irq;
+		iowrite8(mask, LP8X4X_CLRHILVINT);
+	} else if (irq < 13) {
+		irq -= 8;
+		mask = ioread8(LP8X4X_SECOINT);
+		mask |= 1 << irq;
+		iowrite8(mask, LP8X4X_SECOINT);
+	} else {
+		irq -= 8;
+		mask = ioread8(LP8X4X_PRIMINT);
+		mask |= 1 << irq;
+		iowrite8(mask, LP8X4X_PRIMINT);
+	}
+}
+
+static void lp8x4x_mask_irq(struct irq_data *d)
+{
+	int irq = d->irq - IRQ_BOARD_START;
+
+	if (irq < 0 || irq > 15) {
+		pr_err("lp8x4x: wrong irq handler for irq %i\n", d->irq);
+		return;
+	}
+
+	if (irq < 8) {
+		lp8x4x_irq_high_enabled &= ~(1 << irq);
+		iowrite8(lp8x4x_irq_high_enabled, LP8X4X_ENHILVINT);
+	} else {
+		irq -= 8;
+		lp8x4x_irq_sys_enabled &= ~(1 << irq);
+		iowrite8(lp8x4x_irq_sys_enabled, LP8X4X_ENSYSINT);
+	}
+}
+
+static void lp8x4x_unmask_irq(struct irq_data *d)
+{
+	unsigned mask;
+	int irq = d->irq - IRQ_BOARD_START;
+
+	if (irq < 0 || irq > 15) {
+		pr_err("wrong irq handler for irq %i\n", d->irq);
+		return;
+	}
+
+	if (irq < 8) {
+		lp8x4x_irq_high_enabled |= 1 << irq;
+		mask = ioread8(LP8X4X_CLRHILVINT);
+		mask |= 1 << irq;
+		iowrite8(mask, LP8X4X_CLRHILVINT);
+		iowrite8(lp8x4x_irq_high_enabled, LP8X4X_ENHILVINT);
+	} else if (irq < 13) {
+		irq -= 8;
+		lp8x4x_irq_sys_enabled |= 1 << irq;
+		mask = ioread8(LP8X4X_SECOINT);
+		mask |= 1 << irq;
+		iowrite8(mask, LP8X4X_SECOINT);
+		iowrite8(lp8x4x_irq_sys_enabled, LP8X4X_ENSYSINT);
+	} else {
+		irq -= 8;
+		lp8x4x_irq_sys_enabled |= 1 << irq;
+		mask = ioread8(LP8X4X_PRIMINT);
+		mask |= 1 << irq;
+		iowrite8(mask, LP8X4X_PRIMINT);
+		iowrite8(lp8x4x_irq_sys_enabled, LP8X4X_ENSYSINT);
+	}
+}
+
+static struct irq_chip lp8x4x_irq_chip = {
+	.name			= "FPGA",
+	.irq_ack		= lp8x4x_ack_irq,
+	.irq_mask		= lp8x4x_mask_irq,
+	.irq_unmask		= lp8x4x_unmask_irq,
+};
+
+static spinlock_t fpga_irq_lock;
+
+static void lp8x4x_irq_handler(unsigned int irq, struct irq_desc *desc)
+{
+	int loop, n;
+	unsigned long mask;
+	unsigned long flags;
+	struct irq_chip *chip = irq_desc_get_chip(desc);
+
+	spin_lock_irqsave(&fpga_irq_lock, flags);
+	chained_irq_enter(chip, desc);
+
+	do {
+		loop = 0;
+		mask = ioread8(LP8X4X_CLRHILVINT) & 0xff;
+		mask |= (ioread8(LP8X4X_SECOINT) & 0x1f) << 8;
+		mask |= (ioread8(LP8X4X_PRIMINT) & 0xe0) << 8;
+		mask &= (lp8x4x_irq_high_enabled
+				| (lp8x4x_irq_sys_enabled << 8));
+		for_each_set_bit(n, &mask, BITS_PER_LONG) {
+			loop = 1;
+
+			generic_handle_irq(IRQ_BOARD_START + n);
+		}
+	} while (loop);
+
+	chained_irq_exit(chip, desc);
+	iowrite8(0, LP8X4X_EOI);
+	spin_unlock_irqrestore(&fpga_irq_lock, flags);
+}
+
+static void __init lp8x4x_init_irq(void)
+{
+	int irq;
+	int err;
+
+	err = irq_set_irq_type(PXA_GPIO_TO_IRQ(3), IRQ_TYPE_EDGE_RISING);
+	if (err < 0) {
+		pr_err("lp8x4x: irq init failed\n");
+		return;
+	}
+
+	spin_lock_init(&fpga_irq_lock);
+	irq_set_chained_handler(PXA_GPIO_TO_IRQ(3), lp8x4x_irq_handler);
+
+	for (irq = IRQ_BOARD_START; irq < LP8X4X_NR_IRQS; irq++) {
+		irq_set_chip_and_handler(irq, &lp8x4x_irq_chip,
+					 handle_level_irq);
+		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+	}
+
+	iowrite8(0, LP8X4X_CLRRISEINT);
+	iowrite8(0, LP8X4X_ENRISEINT);
+	iowrite8(0, LP8X4X_CLRFALLINT);
+	iowrite8(0, LP8X4X_ENFALLINT);
+	iowrite8(0, LP8X4X_CLRHILVINT);
+	iowrite8(0, LP8X4X_ENHILVINT);
+	iowrite8(0, LP8X4X_ENSYSINT);
+	iowrite8(0, LP8X4X_PRIMINT);
+	iowrite8(0, LP8X4X_SECOINT);
+
+	return;
+}
+
+static unsigned long lp8x4x_pin_config[] = {
+	/* MMC */
+	GPIO32_MMC_CLK,
+	GPIO112_MMC_CMD,
+	GPIO92_MMC_DAT_0,
+	GPIO109_MMC_DAT_1,
+	GPIO110_MMC_DAT_2,
+	GPIO111_MMC_DAT_3,
+
+	/* USB Host Port 1 */
+	GPIO88_USBH1_PWR,
+	GPIO89_USBH1_PEN,
+};
+
+static struct resource lp8x4x_flash_resources[] = {
+	[0] = {
+		.start	= PXA_CS0_PHYS,
+		.end	= PXA_CS0_PHYS + SZ_64M - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= PXA_CS1_PHYS,
+		.end	= PXA_CS1_PHYS + SZ_32M - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct mtd_partition lp8x4x_flash0_partitions[] = {
+	{
+		.name =		"Bootloader",
+		.size =		0x00040000,
+		.offset =	0,
+	}, {
+		.name =		"Settings",
+		.size =		0x00040000,
+		.offset =	0x00040000,
+	}, {
+		.name =		"Kernel",
+		.size =		0x00280000,
+		.offset =	0x00080000,
+	}, {
+		.name =		"Filesystem",
+		.size =		MTDPART_SIZ_FULL,
+		.offset =	0x00300000
+	}
+};
+
+static struct flash_platform_data lp8x4x_flash_data[] = {
+	{
+		.map_name	= "cfi_probe",
+		.parts		= lp8x4x_flash0_partitions,
+		.nr_parts	= ARRAY_SIZE(lp8x4x_flash0_partitions),
+		.width		= 4,
+	}, {
+		.map_name	= "cfi_probe",
+		.parts		= NULL,
+		.nr_parts	= 0,
+		.width		= 2,
+	}
+};
+
+static struct platform_device lp8x4x_flash_device[] = {
+	{
+		.name		= "pxa2xx-flash",
+		.id		= 0,
+		.dev = {
+			.platform_data = &lp8x4x_flash_data[0],
+		},
+		.resource = &lp8x4x_flash_resources[0],
+		.num_resources = 1,
+	},
+	{
+		.name		= "pxa2xx-flash",
+		.id		= 1,
+		.dev = {
+			.platform_data = &lp8x4x_flash_data[1],
+		},
+		.resource = &lp8x4x_flash_resources[1],
+		.num_resources = 1,
+	},
+};
+
+static struct pxafb_mode_info lp8x4x_vga_60_mode = {
+	.pixclock       = 38461,
+	.xres           = 640,
+	.yres           = 480,
+	.bpp            = 16,
+	.hsync_len      = 64,
+	.left_margin    = 78,
+	.right_margin   = 46,
+	.vsync_len      = 12,
+	.upper_margin   = 22,
+	.lower_margin   = 10,
+	.sync           = 0,
+};
+
+static struct pxafb_mach_info lp8x4x_pxafb_info = {
+	.num_modes		= 1,
+	.lccr0			= LCCR0_Act,
+	.lccr3			= LCCR3_PCP,
+};
+
+static int lp8x4x_mci_init(struct device *dev,
+		irq_handler_t mstone_detect_int, void *data)
+{
+	return 0;
+}
+
+static int lp8x4x_mci_setpower(struct device *dev, unsigned int vdd)
+{
+	return 0;
+}
+
+static void lp8x4x_mci_exit(struct device *dev, void *data)
+{
+}
+
+static struct pxamci_platform_data lp8x4x_mci_platform_data = {
+	.ocr_mask		= MMC_VDD_32_33|MMC_VDD_33_34,
+	.init			= lp8x4x_mci_init,
+	.setpower               = lp8x4x_mci_setpower,
+	.exit			= lp8x4x_mci_exit,
+	.gpio_card_detect	= -1,
+	.gpio_card_ro		= -1,
+	.gpio_power		= -1,
+};
+
+static struct resource lp8x4x_dm9000_resources[] = {
+	[0] = {
+		.start  = LP8X4X_ETH0_BASE,
+		.end    = LP8X4X_ETH0_BASE + 2 - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start  = LP8X4X_ETH0_IO,
+		.end    = LP8X4X_ETH0_IO + 2 - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	[2] = {
+		.start  = LP8X4X_ETH0_IRQ,
+		.end    = LP8X4X_ETH0_IRQ,
+		.flags	= IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE,
+	},
+	[3] = {
+		.start  = LP8X4X_ETH1_BASE,
+		.end    = LP8X4X_ETH1_BASE + 2 - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	[4] = {
+		.start  = LP8X4X_ETH1_IO,
+		.end    = LP8X4X_ETH1_IO + 2 - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	[5] = {
+		.start  = LP8X4X_ETH1_IRQ,
+		.end    = LP8X4X_ETH1_IRQ,
+		.flags	= IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE,
+	},
+};
+
+static struct platform_device lp8x4x_dm9000_device[2] = {
+	{
+		.name           = "dm9000",
+		.id             = 0,
+		.dev = {},
+		.resource = &lp8x4x_dm9000_resources[0],
+		.num_resources = 3,
+	},
+	{
+		.name           = "dm9000",
+		.id             = 1,
+		.dev = {},
+		.resource = &lp8x4x_dm9000_resources[3],
+		.num_resources = 3,
+	},
+};
+
+static struct platform_device *lp8x4x_devices[] __initdata = {
+	&lp8x4x_flash_device[0],
+	&lp8x4x_flash_device[1],
+	&lp8x4x_dm9000_device[0],
+	&lp8x4x_dm9000_device[1],
+};
+
+static struct pxaohci_platform_data lp8x4x_ohci_platform_data = {
+	.port_mode	= PMM_PERPORT_MODE,
+	.flags		= ENABLE_PORT1 | OC_MODE_PERPORT,
+};
+
+static void lp8x4x_restart(enum reboot_mode mode, const char *cmd)
+{
+	/* Switch off fast-bus and turbo mode */
+	asm volatile("mcr       p14, 0, %0, c6, c0, 0" : :
+			"r"(2));
+	/* SDRAM hangs on watchdog reset on Marvell PXA270 (erratum 71) */
+	pxa_restart(REBOOT_SOFT, cmd);
+}
+
+static void __init lp8x4x_init(void)
+{
+	pxa2xx_mfp_config(ARRAY_AND_SIZE(lp8x4x_pin_config));
+
+	pxa_set_ffuart_info(NULL);
+	pxa_set_btuart_info(NULL);
+	pxa_set_stuart_info(NULL);
+
+	/* system bus arbiter setting
+	 * - Core_Park
+	 * - LCD_wt:DMA_wt:CORE_Wt = 2:3:4
+	 */
+	ARB_CNTRL = ARB_CORE_PARK | 0x234;
+
+	pxa_set_mci_info(&lp8x4x_mci_platform_data);
+	pxa_set_ohci_info(&lp8x4x_ohci_platform_data);
+
+	platform_add_devices(ARRAY_AND_SIZE(lp8x4x_devices));
+
+	lp8x4x_pxafb_info.modes = &lp8x4x_vga_60_mode;
+	pxa_set_fb_info(NULL, &lp8x4x_pxafb_info);
+
+	/* Could not do this in MACHINE since GPIO is not ready then */
+	lp8x4x_init_irq();
+}
+
+static struct map_desc lp8x4x_io_desc[] __initdata = {
+	{	/* CPLD */
+		.virtual	=  LP8X4X_FPGA_VIRT,
+		.pfn		= __phys_to_pfn(LP8X4X_FPGA_PHYS),
+		.length		= 0x00100000,
+		.type		= MT_DEVICE
+	}
+};
+
+static void __init lp8x4x_map_io(void)
+{
+	pxa27x_map_io();
+	iotable_init(lp8x4x_io_desc, ARRAY_SIZE(lp8x4x_io_desc));
+}
+
+MACHINE_START(LP8X4X, "ICP DAS LP-8x4x programmable automation controller")
+	.atag_offset	= 0x100,
+	.map_io		= lp8x4x_map_io,
+	.nr_irqs	= LP8X4X_NR_IRQS,
+	.init_irq	= pxa27x_init_irq,
+	.handle_irq	= pxa27x_handle_irq,
+	.init_time	= pxa_timer_init,
+	.init_machine	= lp8x4x_init,
+	.restart	= lp8x4x_restart,
+MACHINE_END
-- 
1.8.4.2


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

* [PATCH 02/11] arm: pxa27x: support ICP DAS LP-8x4x
@ 2013-12-01  6:26   ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-01  6:26 UTC (permalink / raw)
  To: linux-arm-kernel

ICP DAS calls LP-8x4x 'programmable automation controller'. It is
an industrial computer based on PXA270 SoC. They ship it with a 2.6.19
kernel and proprietary kernel module and userspace library to access
its industrial IO.

This patch allows to boot the device with a modern kernel. It adds
support for:
* FPGA irq chip
* MMC card interface on PXA270
* USB 1.1 port on PXA270
* 2 NOR flash devices
* VGA interface on PXA270
* 2 onboard ethernet Davicom DM9000 devices
* 3 serial UART ports on PXA270

Support for these devices will be added in separate patches, since
they are not currently supported by the kernel:
* DS1302 RTC
* 512kiB SRAM
* 3 built-in and up to 32 pluggable 8250 serial UART ports
* industrial IO parallel bus
* digital and analog industrial IO modules for parallel bus
* serial interface for digital and analog industrial IO modules on
  parallel bus

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
 arch/arm/configs/lp8x4x_defconfig       | 2320 +++++++++++++++++++++++++++++++
 arch/arm/mach-pxa/Kconfig               |   16 +
 arch/arm/mach-pxa/Makefile              |    1 +
 arch/arm/mach-pxa/include/mach/lp8x4x.h |   74 +
 arch/arm/mach-pxa/lp8x4x.c              |  460 ++++++
 5 files changed, 2871 insertions(+)
 create mode 100644 arch/arm/configs/lp8x4x_defconfig
 create mode 100644 arch/arm/mach-pxa/include/mach/lp8x4x.h
 create mode 100644 arch/arm/mach-pxa/lp8x4x.c

diff --git a/arch/arm/configs/lp8x4x_defconfig b/arch/arm/configs/lp8x4x_defconfig
new file mode 100644
index 0000000..5cd6d38
--- /dev/null
+++ b/arch/arm/configs/lp8x4x_defconfig
@@ -0,0 +1,2320 @@
+#
+# Automatically generated file; DO NOT EDIT.
+# Linux/arm 3.13.0-rc1 Kernel Configuration
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_HAVE_PROC_CPU=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_ARCH_HAS_CPUFREQ=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_NEED_DMA_MAP_STATE=y
+CONFIG_ARCH_MTD_XIP=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_ARM_PATCH_PHYS_VIRT=y
+CONFIG_GENERIC_BUG=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_IRQ_WORK=y
+CONFIG_BUILDTIME_EXTABLE_SORT=y
+
+#
+# General setup
+#
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_CROSS_COMPILE="arm-linux-gnueabi-"
+# CONFIG_COMPILE_TEST is not set
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_LZMA=y
+CONFIG_HAVE_KERNEL_XZ=y
+CONFIG_HAVE_KERNEL_LZO=y
+CONFIG_HAVE_KERNEL_LZ4=y
+CONFIG_KERNEL_GZIP=y
+# CONFIG_KERNEL_LZMA is not set
+# CONFIG_KERNEL_XZ is not set
+# CONFIG_KERNEL_LZO is not set
+# CONFIG_KERNEL_LZ4 is not set
+CONFIG_DEFAULT_HOSTNAME="(none)"
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_FHANDLE is not set
+# CONFIG_AUDIT is not set
+
+#
+# IRQ subsystem
+#
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_IRQ_SHOW=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_IRQ_FORCED_THREADING=y
+CONFIG_SPARSE_IRQ=y
+CONFIG_KTIME_SCALAR=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+
+#
+# Timers subsystem
+#
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ_COMMON=y
+# CONFIG_HZ_PERIODIC is not set
+CONFIG_NO_HZ_IDLE=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+
+#
+# CPU/Task time and stats accounting
+#
+CONFIG_TICK_CPU_ACCOUNTING=y
+# CONFIG_VIRT_CPU_ACCOUNTING_GEN is not set
+# CONFIG_IRQ_TIME_ACCOUNTING is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_TREE_PREEMPT_RCU=y
+CONFIG_PREEMPT_RCU=y
+CONFIG_RCU_STALL_COMMON=y
+CONFIG_RCU_FANOUT=32
+CONFIG_RCU_FANOUT_LEAF=16
+# CONFIG_RCU_FANOUT_EXACT is not set
+# CONFIG_TREE_RCU_TRACE is not set
+CONFIG_RCU_BOOST=y
+CONFIG_RCU_BOOST_PRIO=1
+CONFIG_RCU_BOOST_DELAY=500
+# CONFIG_RCU_NOCB_CPU is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_GENERIC_SCHED_CLOCK=y
+# CONFIG_CGROUPS is not set
+# CONFIG_CHECKPOINT_RESTORE is not set
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_NS is not set
+# CONFIG_IPC_NS is not set
+# CONFIG_USER_NS is not set
+CONFIG_PID_NS=y
+CONFIG_NET_NS=y
+# CONFIG_UIDGID_STRICT_TYPE_CHECKS is not set
+# CONFIG_SCHED_AUTOGROUP is not set
+# CONFIG_SYSFS_DEPRECATED is not set
+# CONFIG_RELAY is not set
+# CONFIG_BLK_DEV_INITRD is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_HAVE_UID16=y
+CONFIG_EXPERT=y
+# CONFIG_UID16 is not set
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+# CONFIG_SHMEM is not set
+CONFIG_AIO=y
+CONFIG_EMBEDDED=y
+CONFIG_HAVE_PERF_EVENTS=y
+CONFIG_PERF_USE_VMALLOC=y
+
+#
+# Kernel Performance Events And Counters
+#
+# CONFIG_PERF_EVENTS is not set
+CONFIG_VM_EVENT_COUNTERS=y
+# CONFIG_COMPAT_BRK is not set
+# CONFIG_SLAB is not set
+# CONFIG_SLUB is not set
+CONFIG_SLOB=y
+# CONFIG_PROFILING is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_JUMP_LABEL=y
+# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_DMA_ATTRS=y
+CONFIG_HAVE_DMA_CONTIGUOUS=y
+CONFIG_GENERIC_SMP_IDLE_THREAD=y
+CONFIG_GENERIC_IDLE_POLL_SETUP=y
+CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+CONFIG_HAVE_PERF_REGS=y
+CONFIG_HAVE_PERF_USER_STACK_DUMP=y
+CONFIG_HAVE_ARCH_JUMP_LABEL=y
+CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y
+CONFIG_HAVE_ARCH_SECCOMP_FILTER=y
+CONFIG_HAVE_CONTEXT_TRACKING=y
+CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y
+CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y
+CONFIG_MODULES_USE_ELF_REL=y
+CONFIG_CLONE_BACKWARDS=y
+CONFIG_OLD_SIGSUSPEND3=y
+CONFIG_OLD_SIGACTION=y
+
+#
+# GCOV-based kernel profiling
+#
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+# CONFIG_SYSTEM_TRUSTED_KEYRING is not set
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_MODVERSIONS=y
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+# CONFIG_MODULE_SIG is not set
+CONFIG_BLOCK=y
+# CONFIG_LBDAF is not set
+CONFIG_BLK_DEV_BSG=y
+# CONFIG_BLK_DEV_BSGLIB is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+CONFIG_BLK_CMDLINE_PARSER=y
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_AIX_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_MINIX_SUBPARTITION=y
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_UNIXWARE_DISKLABEL=y
+CONFIG_LDM_PARTITION=y
+CONFIG_LDM_DEBUG=y
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
+# CONFIG_CMDLINE_PARTITION is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+CONFIG_UNINLINE_SPIN_UNLOCK=y
+# CONFIG_FREEZER is not set
+
+#
+# System Type
+#
+CONFIG_MMU=y
+# CONFIG_ARCH_MULTIPLATFORM is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_GEMINI is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_DOVE is not set
+# CONFIG_ARCH_KIRKWOOD is not set
+# CONFIG_ARCH_MV78XX0 is not set
+# CONFIG_ARCH_ORION5X is not set
+# CONFIG_ARCH_MMP is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_W90X900 is not set
+# CONFIG_ARCH_LPC32XX is not set
+CONFIG_ARCH_PXA=y
+# CONFIG_ARCH_MSM is not set
+# CONFIG_ARCH_SHMOBILE is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C24XX is not set
+# CONFIG_ARCH_S3C64XX is not set
+# CONFIG_ARCH_S5P64X0 is not set
+# CONFIG_ARCH_S5PC100 is not set
+# CONFIG_ARCH_S5PV210 is not set
+# CONFIG_ARCH_EXYNOS is not set
+# CONFIG_ARCH_DAVINCI is not set
+# CONFIG_ARCH_OMAP1 is not set
+# CONFIG_GPIO_PCA953X is not set
+
+#
+# Intel PXA2xx/PXA3xx Implementations
+#
+
+#
+# Intel/Marvell Dev Platforms (sorted by hardware release time)
+#
+# CONFIG_MACH_PXA3XX_DT is not set
+# CONFIG_ARCH_LUBBOCK is not set
+# CONFIG_MACH_MAINSTONE is not set
+# CONFIG_MACH_ZYLONITE300 is not set
+# CONFIG_MACH_ZYLONITE320 is not set
+# CONFIG_MACH_LITTLETON is not set
+# CONFIG_MACH_TAVOREVB is not set
+# CONFIG_MACH_SAAR is not set
+
+#
+# Third Party Dev Platforms (sorted by vendor name)
+#
+# CONFIG_ARCH_PXA_IDP is not set
+# CONFIG_ARCH_VIPER is not set
+# CONFIG_MACH_ARCOM_ZEUS is not set
+# CONFIG_MACH_BALLOON3 is not set
+# CONFIG_MACH_CSB726 is not set
+# CONFIG_MACH_ARMCORE is not set
+# CONFIG_MACH_EM_X270 is not set
+# CONFIG_MACH_EXEDA is not set
+# CONFIG_MACH_CM_X300 is not set
+# CONFIG_MACH_CAPC7117 is not set
+# CONFIG_ARCH_GUMSTIX is not set
+# CONFIG_MACH_INTELMOTE2 is not set
+# CONFIG_MACH_STARGATE2 is not set
+# CONFIG_MACH_XCEP is not set
+# CONFIG_TRIZEPS_PXA is not set
+# CONFIG_MACH_LOGICPD_PXA270 is not set
+# CONFIG_MACH_PCM027 is not set
+# CONFIG_MACH_COLIBRI is not set
+# CONFIG_MACH_COLIBRI300 is not set
+# CONFIG_MACH_COLIBRI320 is not set
+# CONFIG_MACH_VPAC270 is not set
+
+#
+# End-user Products (sorted by vendor name)
+#
+CONFIG_MACH_LP8X4X=y
+# CONFIG_MACH_H4700 is not set
+# CONFIG_MACH_H5000 is not set
+# CONFIG_MACH_HIMALAYA is not set
+# CONFIG_MACH_MAGICIAN is not set
+# CONFIG_MACH_MIOA701 is not set
+# CONFIG_PXA_EZX is not set
+# CONFIG_MACH_MP900C is not set
+# CONFIG_ARCH_PXA_PALM is not set
+# CONFIG_MACH_RAUMFELD_RC is not set
+# CONFIG_MACH_RAUMFELD_CONNECTOR is not set
+# CONFIG_MACH_RAUMFELD_SPEAKER is not set
+# CONFIG_PXA_SHARPSL is not set
+# CONFIG_MACH_ICONTROL is not set
+# CONFIG_ARCH_PXA_ESERIES is not set
+# CONFIG_MACH_ZIPIT2 is not set
+CONFIG_PXA27x=y
+# CONFIG_PLAT_SPEAR is not set
+CONFIG_PLAT_PXA=y
+
+#
+# Processor Type
+#
+CONFIG_CPU_XSCALE=y
+CONFIG_CPU_32v5=y
+CONFIG_CPU_ABRT_EV5T=y
+CONFIG_CPU_PABRT_LEGACY=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_TLB_V4WBI=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+CONFIG_CPU_USE_DOMAINS=y
+
+#
+# Processor Features
+#
+# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
+# CONFIG_ARM_THUMB is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+CONFIG_NEED_KUSER_HELPERS=y
+CONFIG_KUSER_HELPERS=y
+# CONFIG_CACHE_L2X0 is not set
+CONFIG_ARM_L1_CACHE_SHIFT=5
+CONFIG_ARM_NR_BANKS=8
+CONFIG_IWMMXT=y
+CONFIG_MULTI_IRQ_HANDLER=y
+
+#
+# Bus support
+#
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+CONFIG_ARCH_NR_GPIO=0
+# CONFIG_PREEMPT_NONE is not set
+# CONFIG_PREEMPT_VOLUNTARY is not set
+CONFIG_PREEMPT=y
+CONFIG_PREEMPT_COUNT=y
+CONFIG_HZ_FIXED=0
+CONFIG_HZ_100=y
+# CONFIG_HZ_200 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_500 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=100
+CONFIG_SCHED_HRTICK=y
+CONFIG_AEABI=y
+# CONFIG_OABI_COMPAT is not set
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+CONFIG_HAVE_ARCH_PFN_VALID=y
+# CONFIG_HIGHMEM is not set
+CONFIG_ARCH_WANT_GENERAL_HUGETLB=y
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_HAVE_MEMBLOCK=y
+# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=999999
+# CONFIG_COMPACTION is not set
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+# CONFIG_KSM is not set
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+# CONFIG_CROSS_MEMORY_ATTACH is not set
+CONFIG_NEED_PER_CPU_KM=y
+# CONFIG_CLEANCACHE is not set
+# CONFIG_CMA is not set
+# CONFIG_ZBUD is not set
+CONFIG_FORCE_MAX_ZONEORDER=11
+CONFIG_ALIGNMENT_TRAP=y
+# CONFIG_UACCESS_WITH_MEMCPY is not set
+# CONFIG_SECCOMP is not set
+# CONFIG_CC_STACKPROTECTOR is not set
+CONFIG_SWIOTLB=y
+CONFIG_IOMMU_HELPER=y
+
+#
+# Boot options
+#
+# CONFIG_USE_OF is not set
+CONFIG_ATAGS=y
+# CONFIG_DEPRECATED_PARAM_STRUCT is not set
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="init=/sbin/init root=/dev/mmcblk0p1 rw rootfstype=ext4 console=ttySA0,115200 mem=128M rootwait"
+CONFIG_CMDLINE_FROM_BOOTLOADER=y
+# CONFIG_CMDLINE_EXTEND is not set
+# CONFIG_CMDLINE_FORCE is not set
+# CONFIG_XIP_KERNEL is not set
+# CONFIG_KEXEC is not set
+# CONFIG_CRASH_DUMP is not set
+CONFIG_AUTO_ZRELADDR=y
+
+#
+# CPU Power Management
+#
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# CPU Idle
+#
+# CONFIG_CPU_IDLE is not set
+# CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y
+CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y
+CONFIG_BINFMT_SCRIPT=y
+# CONFIG_HAVE_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+CONFIG_COREDUMP=y
+
+#
+# Power management options
+#
+# CONFIG_SUSPEND is not set
+# CONFIG_PM_RUNTIME is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+# CONFIG_ARM_CPU_SUSPEND is not set
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_DIAG=m
+CONFIG_UNIX=y
+CONFIG_UNIX_DIAG=m
+CONFIG_XFRM=y
+CONFIG_XFRM_ALGO=m
+# CONFIG_XFRM_USER is not set
+CONFIG_XFRM_SUB_POLICY=y
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+CONFIG_XFRM_IPCOMP=m
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+# CONFIG_IP_FIB_TRIE_STATS is not set
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_IP_ROUTE_CLASSID=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+CONFIG_NET_IPIP=y
+CONFIG_NET_IPGRE_DEMUX=m
+CONFIG_NET_IP_TUNNEL=y
+CONFIG_NET_IPGRE=m
+# CONFIG_NET_IPGRE_BROADCAST is not set
+# CONFIG_IP_MROUTE is not set
+CONFIG_SYN_COOKIES=y
+CONFIG_NET_IPVTI=m
+CONFIG_INET_AH=m
+CONFIG_INET_ESP=m
+CONFIG_INET_IPCOMP=m
+CONFIG_INET_XFRM_TUNNEL=m
+CONFIG_INET_TUNNEL=y
+CONFIG_INET_XFRM_MODE_TRANSPORT=m
+CONFIG_INET_XFRM_MODE_TUNNEL=m
+CONFIG_INET_XFRM_MODE_BEET=m
+CONFIG_INET_LRO=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_INET_UDP_DIAG is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+CONFIG_IPV6=m
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_IPV6_OPTIMISTIC_DAD is not set
+# CONFIG_INET6_AH is not set
+# CONFIG_INET6_ESP is not set
+# CONFIG_INET6_IPCOMP is not set
+# CONFIG_IPV6_MIP6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+CONFIG_INET6_XFRM_MODE_TRANSPORT=m
+CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_BEET=m
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+# CONFIG_IPV6_VTI is not set
+CONFIG_IPV6_SIT=m
+# CONFIG_IPV6_SIT_6RD is not set
+CONFIG_IPV6_NDISC_NODETYPE=y
+# CONFIG_IPV6_TUNNEL is not set
+# CONFIG_IPV6_GRE is not set
+# CONFIG_IPV6_MULTIPLE_TABLES is not set
+# CONFIG_IPV6_MROUTE is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETWORK_PHY_TIMESTAMPING is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_NETFILTER_ADVANCED=y
+CONFIG_BRIDGE_NETFILTER=y
+
+#
+# Core Netfilter Configuration
+#
+# CONFIG_NETFILTER_NETLINK_ACCT is not set
+# CONFIG_NETFILTER_NETLINK_QUEUE is not set
+# CONFIG_NETFILTER_NETLINK_LOG is not set
+# CONFIG_NF_CONNTRACK is not set
+CONFIG_NETFILTER_XTABLES=y
+
+#
+# Xtables combined modules
+#
+CONFIG_NETFILTER_XT_MARK=y
+
+#
+# Xtables targets
+#
+# CONFIG_NETFILTER_XT_TARGET_CHECKSUM is not set
+# CONFIG_NETFILTER_XT_TARGET_CLASSIFY is not set
+# CONFIG_NETFILTER_XT_TARGET_DSCP is not set
+CONFIG_NETFILTER_XT_TARGET_HL=m
+# CONFIG_NETFILTER_XT_TARGET_HMARK is not set
+# CONFIG_NETFILTER_XT_TARGET_IDLETIMER is not set
+# CONFIG_NETFILTER_XT_TARGET_LOG is not set
+CONFIG_NETFILTER_XT_TARGET_MARK=y
+# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set
+# CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set
+# CONFIG_NETFILTER_XT_TARGET_RATEEST is not set
+# CONFIG_NETFILTER_XT_TARGET_TEE is not set
+# CONFIG_NETFILTER_XT_TARGET_TPROXY is not set
+# CONFIG_NETFILTER_XT_TARGET_TRACE is not set
+# CONFIG_NETFILTER_XT_TARGET_TCPMSS is not set
+# CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP is not set
+
+#
+# Xtables matches
+#
+# CONFIG_NETFILTER_XT_MATCH_ADDRTYPE is not set
+# CONFIG_NETFILTER_XT_MATCH_BPF is not set
+# CONFIG_NETFILTER_XT_MATCH_COMMENT is not set
+# CONFIG_NETFILTER_XT_MATCH_CPU is not set
+# CONFIG_NETFILTER_XT_MATCH_DCCP is not set
+# CONFIG_NETFILTER_XT_MATCH_DEVGROUP is not set
+CONFIG_NETFILTER_XT_MATCH_DSCP=y
+CONFIG_NETFILTER_XT_MATCH_ECN=y
+CONFIG_NETFILTER_XT_MATCH_ESP=y
+# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set
+CONFIG_NETFILTER_XT_MATCH_HL=y
+# CONFIG_NETFILTER_XT_MATCH_IPRANGE is not set
+# CONFIG_NETFILTER_XT_MATCH_LENGTH is not set
+CONFIG_NETFILTER_XT_MATCH_LIMIT=y
+CONFIG_NETFILTER_XT_MATCH_MAC=y
+CONFIG_NETFILTER_XT_MATCH_MARK=y
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y
+# CONFIG_NETFILTER_XT_MATCH_NFACCT is not set
+# CONFIG_NETFILTER_XT_MATCH_OWNER is not set
+# CONFIG_NETFILTER_XT_MATCH_POLICY is not set
+# CONFIG_NETFILTER_XT_MATCH_PHYSDEV is not set
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
+# CONFIG_NETFILTER_XT_MATCH_QUOTA is not set
+# CONFIG_NETFILTER_XT_MATCH_RATEEST is not set
+# CONFIG_NETFILTER_XT_MATCH_REALM is not set
+# CONFIG_NETFILTER_XT_MATCH_RECENT is not set
+# CONFIG_NETFILTER_XT_MATCH_SCTP is not set
+# CONFIG_NETFILTER_XT_MATCH_SOCKET is not set
+# CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set
+# CONFIG_NETFILTER_XT_MATCH_STRING is not set
+CONFIG_NETFILTER_XT_MATCH_TCPMSS=y
+# CONFIG_NETFILTER_XT_MATCH_TIME is not set
+# CONFIG_NETFILTER_XT_MATCH_U32 is not set
+# CONFIG_IP_SET is not set
+# CONFIG_IP_VS is not set
+
+#
+# IP: Netfilter Configuration
+#
+# CONFIG_NF_DEFRAG_IPV4 is not set
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_AH=m
+CONFIG_IP_NF_MATCH_ECN=m
+# CONFIG_IP_NF_MATCH_RPFILTER is not set
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+# CONFIG_IP_NF_TARGET_ULOG is not set
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_TTL=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_ARPTABLES=y
+CONFIG_IP_NF_ARPFILTER=y
+CONFIG_IP_NF_ARP_MANGLE=y
+
+#
+# IPv6: Netfilter Configuration
+#
+# CONFIG_NF_DEFRAG_IPV6 is not set
+# CONFIG_IP6_NF_IPTABLES is not set
+# CONFIG_BRIDGE_NF_EBTABLES is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_RDS is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+CONFIG_L2TP=m
+CONFIG_L2TP_V3=y
+CONFIG_L2TP_IP=m
+CONFIG_L2TP_ETH=m
+CONFIG_STP=m
+CONFIG_BRIDGE=m
+CONFIG_BRIDGE_IGMP_SNOOPING=y
+# CONFIG_BRIDGE_VLAN_FILTERING is not set
+CONFIG_HAVE_NET_DSA=y
+CONFIG_VLAN_8021Q=y
+# CONFIG_VLAN_8021Q_GVRP is not set
+# CONFIG_VLAN_8021Q_MVRP is not set
+# CONFIG_DECNET is not set
+CONFIG_LLC=y
+CONFIG_LLC2=y
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+CONFIG_X25=y
+CONFIG_LAPB=m
+# CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
+CONFIG_NET_SCHED=y
+
+#
+# Queueing/Scheduling
+#
+CONFIG_NET_SCH_CBQ=y
+CONFIG_NET_SCH_HTB=y
+CONFIG_NET_SCH_HFSC=y
+CONFIG_NET_SCH_PRIO=y
+# CONFIG_NET_SCH_MULTIQ is not set
+CONFIG_NET_SCH_RED=y
+# CONFIG_NET_SCH_SFB is not set
+CONFIG_NET_SCH_SFQ=y
+CONFIG_NET_SCH_TEQL=y
+CONFIG_NET_SCH_TBF=y
+CONFIG_NET_SCH_GRED=y
+CONFIG_NET_SCH_DSMARK=y
+CONFIG_NET_SCH_NETEM=y
+# CONFIG_NET_SCH_DRR is not set
+# CONFIG_NET_SCH_MQPRIO is not set
+# CONFIG_NET_SCH_CHOKE is not set
+# CONFIG_NET_SCH_QFQ is not set
+# CONFIG_NET_SCH_CODEL is not set
+# CONFIG_NET_SCH_FQ_CODEL is not set
+# CONFIG_NET_SCH_FQ is not set
+CONFIG_NET_SCH_INGRESS=y
+# CONFIG_NET_SCH_PLUG is not set
+
+#
+# Classification
+#
+CONFIG_NET_CLS=y
+CONFIG_NET_CLS_BASIC=y
+CONFIG_NET_CLS_TCINDEX=y
+CONFIG_NET_CLS_ROUTE4=y
+CONFIG_NET_CLS_FW=y
+CONFIG_NET_CLS_U32=y
+CONFIG_CLS_U32_PERF=y
+CONFIG_CLS_U32_MARK=y
+CONFIG_NET_CLS_RSVP=y
+CONFIG_NET_CLS_RSVP6=y
+# CONFIG_NET_CLS_FLOW is not set
+# CONFIG_NET_CLS_BPF is not set
+CONFIG_NET_EMATCH=y
+CONFIG_NET_EMATCH_STACK=32
+CONFIG_NET_EMATCH_CMP=y
+CONFIG_NET_EMATCH_NBYTE=y
+CONFIG_NET_EMATCH_U32=y
+CONFIG_NET_EMATCH_META=y
+CONFIG_NET_EMATCH_TEXT=y
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_ACT_POLICE=y
+CONFIG_NET_ACT_GACT=y
+CONFIG_GACT_PROB=y
+CONFIG_NET_ACT_MIRRED=y
+CONFIG_NET_ACT_IPT=m
+# CONFIG_NET_ACT_NAT is not set
+CONFIG_NET_ACT_PEDIT=y
+# CONFIG_NET_ACT_SIMP is not set
+# CONFIG_NET_ACT_SKBEDIT is not set
+# CONFIG_NET_ACT_CSUM is not set
+CONFIG_NET_CLS_IND=y
+CONFIG_NET_SCH_FIFO=y
+# CONFIG_DCB is not set
+CONFIG_DNS_RESOLVER=y
+# CONFIG_BATMAN_ADV is not set
+# CONFIG_OPENVSWITCH is not set
+# CONFIG_VSOCKETS is not set
+# CONFIG_NETLINK_MMAP is not set
+# CONFIG_NETLINK_DIAG is not set
+# CONFIG_NET_MPLS_GSO is not set
+# CONFIG_HSR is not set
+CONFIG_NET_RX_BUSY_POLL=y
+CONFIG_BQL=y
+# CONFIG_BPF_JIT is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+CONFIG_FIB_RULES=y
+# CONFIG_WIRELESS is not set
+# CONFIG_WIMAX is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+# CONFIG_CAIF is not set
+# CONFIG_CEPH_LIB is not set
+# CONFIG_NFC is not set
+CONFIG_HAVE_BPF_JIT=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH=""
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_GENERIC_CPU_DEVICES is not set
+# CONFIG_DMA_SHARED_BUFFER is not set
+
+#
+# Bus devices
+#
+# CONFIG_ARM_CCI is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_TESTS is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_SM_FTL is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_CFI_NOSWAP=y
+# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
+# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
+CONFIG_MTD_CFI_GEOMETRY=y
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_OTP is not set
+CONFIG_MTD_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_XIP is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+CONFIG_MTD_PXA2XX=y
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOCG3 is not set
+# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+# CONFIG_MTD_UBI is not set
+# CONFIG_PARPORT is not set
+CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_NULL_BLK is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_LOOP_MIN_COUNT=2
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_DRBD is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_MG_DISK is not set
+# CONFIG_BLK_DEV_RBD is not set
+
+#
+# Misc devices
+#
+# CONFIG_SENSORS_LIS3LV02D is not set
+# CONFIG_AD525X_DPOT is not set
+# CONFIG_ATMEL_PWM is not set
+# CONFIG_DUMMY_IRQ is not set
+# CONFIG_ICS932S401 is not set
+# CONFIG_ATMEL_SSC is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_APDS9802ALS is not set
+# CONFIG_ISL29003 is not set
+# CONFIG_ISL29020 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_SENSORS_BH1780 is not set
+# CONFIG_SENSORS_BH1770 is not set
+# CONFIG_SENSORS_APDS990X is not set
+# CONFIG_HMC6352 is not set
+# CONFIG_DS1682 is not set
+# CONFIG_BMP085_I2C is not set
+# CONFIG_USB_SWITCH_FSA9480 is not set
+# CONFIG_SRAM is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
+# CONFIG_EEPROM_93CX6 is not set
+
+#
+# Texas Instruments shared transport line discipline
+#
+# CONFIG_TI_ST is not set
+# CONFIG_SENSORS_LIS3_I2C is not set
+
+#
+# Altera FPGA firmware download module
+#
+# CONFIG_ALTERA_STAPL is not set
+
+#
+# Intel MIC Host Driver
+#
+
+#
+# Intel MIC Card Driver
+#
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI_MOD=y
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_SCSI_PROC_FS is not set
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+# CONFIG_SCSI_LOWLEVEL is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+# CONFIG_TARGET_CORE is not set
+CONFIG_NETDEVICES=y
+CONFIG_MII=m
+CONFIG_NET_CORE=y
+CONFIG_BONDING=m
+# CONFIG_DUMMY is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_IFB is not set
+# CONFIG_NET_TEAM is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_VXLAN is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+CONFIG_TUN=m
+# CONFIG_VETH is not set
+# CONFIG_NLMON is not set
+
+#
+# CAIF transport drivers
+#
+
+#
+# Distributed Switch Architecture drivers
+#
+# CONFIG_NET_DSA_MV88E6XXX is not set
+# CONFIG_NET_DSA_MV88E6060 is not set
+# CONFIG_NET_DSA_MV88E6XXX_NEED_PPU is not set
+# CONFIG_NET_DSA_MV88E6131 is not set
+# CONFIG_NET_DSA_MV88E6123_61_65 is not set
+CONFIG_ETHERNET=y
+# CONFIG_NET_VENDOR_ARC is not set
+# CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_CALXEDA_XGMAC is not set
+# CONFIG_NET_VENDOR_CIRRUS is not set
+CONFIG_DM9000=m
+CONFIG_DM9000_FORCE_SIMPLE_PHY_POLL=y
+# CONFIG_DNET is not set
+# CONFIG_NET_VENDOR_FARADAY is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_ETHOC is not set
+# CONFIG_SH_ETH is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+# CONFIG_PHYLIB is not set
+CONFIG_PPP=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_DEFLATE=m
+# CONFIG_PPP_FILTER is not set
+# CONFIG_PPP_MPPE is not set
+# CONFIG_PPP_MULTILINK is not set
+CONFIG_PPPOE=m
+CONFIG_PPTP=m
+CONFIG_PPPOL2TP=m
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_SLIP=m
+CONFIG_SLHC=m
+CONFIG_SLIP_COMPRESSED=y
+# CONFIG_SLIP_SMART is not set
+# CONFIG_SLIP_MODE_SLIP6 is not set
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_RTL8152 is not set
+# CONFIG_USB_USBNET is not set
+# CONFIG_USB_IPHETH is not set
+# CONFIG_WLAN is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+# CONFIG_WAN is not set
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+# CONFIG_INPUT_SPARSEKMAP is not set
+# CONFIG_INPUT_MATRIXKMAP is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=800
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=600
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_TTY=y
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_N_GSM is not set
+# CONFIG_TRACE_SINK is not set
+# CONFIG_DEVKMEM is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=m
+CONFIG_SERIAL_8250_DEPRECATED_OPTIONS=y
+CONFIG_SERIAL_8250_NR_UARTS=36
+CONFIG_SERIAL_8250_RUNTIME_UARTS=36
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+# CONFIG_SERIAL_8250_DETECT_IRQ is not set
+# CONFIG_SERIAL_8250_RSA is not set
+# CONFIG_SERIAL_8250_DW is not set
+# CONFIG_SERIAL_8250_EM is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_PXA=y
+CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_PXA_AS_TTYSA=y
+# CONFIG_SERIAL_SH_SCI is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_SCCNXP is not set
+# CONFIG_SERIAL_TIMBERDALE is not set
+# CONFIG_SERIAL_ALTERA_JTAGUART is not set
+# CONFIG_SERIAL_ALTERA_UART is not set
+# CONFIG_SERIAL_ARC is not set
+# CONFIG_SERIAL_FSL_LPUART is not set
+# CONFIG_SERIAL_ST_ASC is not set
+# CONFIG_TTY_PRINTK is not set
+# CONFIG_HVC_DCC is not set
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_HW_RANDOM_TIMERIOMEM is not set
+# CONFIG_HW_RANDOM_ATMEL is not set
+# CONFIG_HW_RANDOM_EXYNOS is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_I2C=m
+CONFIG_I2C_BOARDINFO=y
+# CONFIG_I2C_COMPAT is not set
+# CONFIG_I2C_CHARDEV is not set
+# CONFIG_I2C_MUX is not set
+CONFIG_I2C_HELPER_AUTO=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_CBUS_GPIO is not set
+# CONFIG_I2C_DESIGNWARE_PLATFORM is not set
+# CONFIG_I2C_GPIO is not set
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_PCA_PLATFORM is not set
+CONFIG_I2C_PXA=m
+# CONFIG_I2C_PXA_PCI is not set
+CONFIG_I2C_PXA_SLAVE=y
+# CONFIG_I2C_SH_MOBILE is not set
+# CONFIG_I2C_SIMTEC is not set
+# CONFIG_I2C_XILINX is not set
+# CONFIG_I2C_RCAR is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_DIOLAN_U2C is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_SPI is not set
+# CONFIG_HSI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
+
+#
+# PPS generators support
+#
+
+#
+# PTP clock support
+#
+# CONFIG_PTP_1588_CLOCK is not set
+
+#
+# Enable PHYLIB and NETWORK_PHY_TIMESTAMPING to see the additional clocks.
+#
+CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+CONFIG_GPIO_DEVRES=y
+# CONFIG_DEBUG_GPIO is not set
+# CONFIG_GPIO_SYSFS is not set
+
+#
+# Memory mapped GPIO drivers:
+#
+# CONFIG_GPIO_GENERIC_PLATFORM is not set
+CONFIG_GPIO_PXA=y
+# CONFIG_GPIO_RCAR is not set
+# CONFIG_GPIO_TS5500 is not set
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_MAX7300 is not set
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCF857X is not set
+# CONFIG_GPIO_ADP5588 is not set
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_GPIO_MCP23S08 is not set
+
+#
+# AC97 GPIO expanders:
+#
+
+#
+# LPC GPIO expanders:
+#
+
+#
+# MODULbus GPIO expanders:
+#
+
+#
+# USB GPIO expanders:
+#
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_POWER_AVS is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_CORE is not set
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_SA1100_WATCHDOG=m
+# CONFIG_DW_WATCHDOG is not set
+# CONFIG_MAX63XX_WATCHDOG is not set
+# CONFIG_MEN_A21_WDT is not set
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+CONFIG_BCMA_POSSIBLE=y
+
+#
+# Broadcom specific AMBA
+#
+# CONFIG_BCMA is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_CROS_EC is not set
+# CONFIG_MFD_ASIC3 is not set
+# CONFIG_MFD_MC13XXX_I2C is not set
+# CONFIG_HTC_EGPIO is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_KEMPLD is not set
+# CONFIG_MFD_VIPERBOARD is not set
+# CONFIG_MFD_RETU is not set
+# CONFIG_MFD_PCF50633 is not set
+# CONFIG_MFD_SI476X_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_ABX500_CORE is not set
+# CONFIG_MFD_SYSCON is not set
+# CONFIG_MFD_TI_AM335X_TSCADC is not set
+# CONFIG_TPS6105X is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_TPS6507X is not set
+# CONFIG_MFD_TPS65217 is not set
+# CONFIG_MFD_TPS65912 is not set
+# CONFIG_MFD_WL1273_CORE is not set
+# CONFIG_MFD_LM3533 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_MFD_TC6393XB is not set
+# CONFIG_MFD_ARIZONA_I2C is not set
+# CONFIG_VEXPRESS_CONFIG is not set
+# CONFIG_REGULATOR is not set
+# CONFIG_MEDIA_SUPPORT is not set
+
+#
+# Graphics support
+#
+# CONFIG_DRM is not set
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
+CONFIG_FB_CFB_FILLRECT=m
+CONFIG_FB_CFB_COPYAREA=m
+CONFIG_FB_CFB_IMAGEBLIT=m
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_S1D13XXX is not set
+CONFIG_FB_PXA=m
+# CONFIG_FB_PXA_OVERLAY is not set
+# CONFIG_FB_PXA_SMARTPANEL is not set
+# CONFIG_FB_PXA_PARAMETERS is not set
+# CONFIG_PXA3XX_GCU is not set
+# CONFIG_FB_MBX is not set
+# CONFIG_FB_W100 is not set
+# CONFIG_FB_SMSCUFX is not set
+# CONFIG_FB_UDL is not set
+# CONFIG_FB_GOLDFISH is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_BROADSHEET is not set
+# CONFIG_FB_AUO_K190X is not set
+# CONFIG_FB_SIMPLE is not set
+# CONFIG_EXYNOS_VIDEO is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Console display driver support
+#
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=m
+# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+CONFIG_LOGO=y
+CONFIG_LOGO_LINUX_MONO=y
+CONFIG_LOGO_LINUX_VGA16=y
+CONFIG_LOGO_LINUX_CLUT224=y
+# CONFIG_SOUND is not set
+
+#
+# HID support
+#
+CONFIG_HID=y
+# CONFIG_HIDRAW is not set
+# CONFIG_UHID is not set
+CONFIG_HID_GENERIC=m
+
+#
+# Special HID drivers
+#
+CONFIG_HID_A4TECH=m
+# CONFIG_HID_ACRUX is not set
+# CONFIG_HID_APPLE is not set
+# CONFIG_HID_APPLEIR is not set
+# CONFIG_HID_AUREAL is not set
+# CONFIG_HID_BELKIN is not set
+# CONFIG_HID_CHERRY is not set
+# CONFIG_HID_CHICONY is not set
+CONFIG_HID_CYPRESS=m
+# CONFIG_HID_DRAGONRISE is not set
+# CONFIG_HID_EMS_FF is not set
+# CONFIG_HID_ELECOM is not set
+# CONFIG_HID_ELO is not set
+# CONFIG_HID_EZKEY is not set
+# CONFIG_HID_HOLTEK is not set
+# CONFIG_HID_HUION is not set
+CONFIG_HID_KEYTOUCH=m
+# CONFIG_HID_KYE is not set
+# CONFIG_HID_UCLOGIC is not set
+# CONFIG_HID_WALTOP is not set
+# CONFIG_HID_GYRATION is not set
+# CONFIG_HID_ICADE is not set
+# CONFIG_HID_TWINHAN is not set
+CONFIG_HID_KENSINGTON=m
+# CONFIG_HID_LCPOWER is not set
+# CONFIG_HID_LENOVO_TPKBD is not set
+CONFIG_HID_LOGITECH=m
+# CONFIG_HID_LOGITECH_DJ is not set
+# CONFIG_LOGITECH_FF is not set
+# CONFIG_LOGIRUMBLEPAD2_FF is not set
+# CONFIG_LOGIG940_FF is not set
+# CONFIG_LOGIWHEELS_FF is not set
+# CONFIG_HID_MAGICMOUSE is not set
+CONFIG_HID_MICROSOFT=m
+CONFIG_HID_MONTEREY=m
+# CONFIG_HID_MULTITOUCH is not set
+# CONFIG_HID_NTRIG is not set
+# CONFIG_HID_ORTEK is not set
+# CONFIG_HID_PANTHERLORD is not set
+# CONFIG_HID_PETALYNX is not set
+# CONFIG_HID_PICOLCD is not set
+# CONFIG_HID_PRIMAX is not set
+# CONFIG_HID_ROCCAT is not set
+# CONFIG_HID_SAITEK is not set
+# CONFIG_HID_SAMSUNG is not set
+# CONFIG_HID_SPEEDLINK is not set
+# CONFIG_HID_STEELSERIES is not set
+# CONFIG_HID_SUNPLUS is not set
+# CONFIG_HID_GREENASIA is not set
+# CONFIG_HID_SMARTJOYPLUS is not set
+# CONFIG_HID_TIVO is not set
+# CONFIG_HID_TOPSEED is not set
+# CONFIG_HID_THRUSTMASTER is not set
+# CONFIG_HID_XINMO is not set
+# CONFIG_HID_ZEROPLUS is not set
+# CONFIG_HID_ZYDACRON is not set
+# CONFIG_HID_SENSOR_HUB is not set
+
+#
+# USB HID support
+#
+CONFIG_USB_HID=m
+# CONFIG_HID_PID is not set
+CONFIG_USB_HIDDEV=y
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+
+#
+# I2C HID support
+#
+CONFIG_I2C_HID=m
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_COMMON=m
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB=m
+# CONFIG_USB_DEBUG is not set
+# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEFAULT_PERSIST=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+# CONFIG_USB_MON is not set
+# CONFIG_USB_WUSB_CBAF is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_XHCI_HCD is not set
+# CONFIG_USB_EHCI_HCD is not set
+# CONFIG_USB_OXU210HP_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1760_HCD is not set
+# CONFIG_USB_ISP1362_HCD is not set
+# CONFIG_USB_FUSBH200_HCD is not set
+# CONFIG_USB_FOTG210_HCD is not set
+CONFIG_USB_OHCI_HCD=m
+CONFIG_USB_OHCI_HCD_PXA27X=m
+# CONFIG_USB_OHCI_HCD_PLATFORM is not set
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_HCD_TEST_MODE is not set
+
+#
+# USB Device Class drivers
+#
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+# CONFIG_USB_WDM is not set
+# CONFIG_USB_TMC is not set
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
+#
+
+#
+# also be needed; see USB_STORAGE Help for more info
+#
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+CONFIG_USB_STORAGE_REALTEK=m
+CONFIG_USB_STORAGE_DATAFAB=m
+CONFIG_USB_STORAGE_FREECOM=m
+CONFIG_USB_STORAGE_ISD200=m
+CONFIG_USB_STORAGE_USBAT=m
+CONFIG_USB_STORAGE_SDDR09=m
+CONFIG_USB_STORAGE_SDDR55=m
+CONFIG_USB_STORAGE_JUMPSHOT=m
+CONFIG_USB_STORAGE_ALAUDA=m
+CONFIG_USB_STORAGE_ONETOUCH=m
+CONFIG_USB_STORAGE_KARMA=m
+CONFIG_USB_STORAGE_CYPRESS_ATACB=m
+CONFIG_USB_STORAGE_ENE_UB6250=m
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+# CONFIG_USB_DWC3 is not set
+
+#
+# USB port drivers
+#
+CONFIG_USB_SERIAL=m
+CONFIG_USB_SERIAL_GENERIC=y
+CONFIG_USB_SERIAL_SIMPLE=m
+CONFIG_USB_SERIAL_AIRCABLE=m
+CONFIG_USB_SERIAL_ARK3116=m
+CONFIG_USB_SERIAL_BELKIN=m
+CONFIG_USB_SERIAL_CH341=m
+CONFIG_USB_SERIAL_WHITEHEAT=m
+CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
+CONFIG_USB_SERIAL_CP210X=m
+CONFIG_USB_SERIAL_CYPRESS_M8=m
+CONFIG_USB_SERIAL_EMPEG=m
+CONFIG_USB_SERIAL_FTDI_SIO=m
+CONFIG_USB_SERIAL_VISOR=m
+CONFIG_USB_SERIAL_IPAQ=m
+CONFIG_USB_SERIAL_IR=m
+CONFIG_USB_SERIAL_EDGEPORT=m
+CONFIG_USB_SERIAL_EDGEPORT_TI=m
+CONFIG_USB_SERIAL_F81232=m
+CONFIG_USB_SERIAL_GARMIN=m
+CONFIG_USB_SERIAL_IPW=m
+CONFIG_USB_SERIAL_IUU=m
+CONFIG_USB_SERIAL_KEYSPAN_PDA=m
+CONFIG_USB_SERIAL_KEYSPAN=m
+CONFIG_USB_SERIAL_KLSI=m
+CONFIG_USB_SERIAL_KOBIL_SCT=m
+CONFIG_USB_SERIAL_MCT_U232=m
+CONFIG_USB_SERIAL_METRO=m
+CONFIG_USB_SERIAL_MOS7720=m
+CONFIG_USB_SERIAL_MOS7840=m
+CONFIG_USB_SERIAL_NAVMAN=m
+CONFIG_USB_SERIAL_PL2303=m
+CONFIG_USB_SERIAL_OTI6858=m
+CONFIG_USB_SERIAL_QCAUX=m
+CONFIG_USB_SERIAL_QUALCOMM=m
+CONFIG_USB_SERIAL_SPCP8X5=m
+CONFIG_USB_SERIAL_SAFE=m
+CONFIG_USB_SERIAL_SAFE_PADDED=y
+CONFIG_USB_SERIAL_SIERRAWIRELESS=m
+CONFIG_USB_SERIAL_SYMBOL=m
+CONFIG_USB_SERIAL_TI=m
+CONFIG_USB_SERIAL_CYBERJACK=m
+CONFIG_USB_SERIAL_XIRCOM=m
+CONFIG_USB_SERIAL_WWAN=m
+CONFIG_USB_SERIAL_OPTION=m
+CONFIG_USB_SERIAL_OMNINET=m
+CONFIG_USB_SERIAL_OPTICON=m
+CONFIG_USB_SERIAL_XSENS_MT=m
+CONFIG_USB_SERIAL_WISHBONE=m
+CONFIG_USB_SERIAL_ZTE=m
+CONFIG_USB_SERIAL_SSU100=m
+CONFIG_USB_SERIAL_QT2=m
+# CONFIG_USB_SERIAL_DEBUG is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_TEST is not set
+# CONFIG_USB_EHSET_TEST_FIXTURE is not set
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_YUREX is not set
+CONFIG_USB_EZUSB_FX2=m
+# CONFIG_USB_HSIC_USB3503 is not set
+
+#
+# USB Physical Layer drivers
+#
+# CONFIG_USB_PHY is not set
+# CONFIG_NOP_USB_XCEIV is not set
+# CONFIG_AM335X_PHY_USB is not set
+# CONFIG_SAMSUNG_USB2PHY is not set
+# CONFIG_SAMSUNG_USB3PHY is not set
+# CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_USB_ISP1301 is not set
+# CONFIG_USB_RCAR_PHY is not set
+# CONFIG_USB_ULPI is not set
+# CONFIG_USB_GADGET is not set
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+# CONFIG_MMC_UNSAFE_RESUME is not set
+# CONFIG_MMC_CLKGATE is not set
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_MINORS=8
+CONFIG_MMC_BLOCK_BOUNCE=y
+# CONFIG_SDIO_UART is not set
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+CONFIG_MMC_PXA=y
+# CONFIG_MMC_SDHCI is not set
+# CONFIG_MMC_SDHCI_PXAV3 is not set
+# CONFIG_MMC_SDHCI_PXAV2 is not set
+# CONFIG_MMC_DW is not set
+# CONFIG_MMC_VUB300 is not set
+# CONFIG_MMC_USHC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_EDAC is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_SYSTOHC=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_DS3232 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_ISL12022 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF2127 is not set
+# CONFIG_RTC_DRV_PCF8523 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_BQ32K is not set
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
+# CONFIG_RTC_DRV_EM3027 is not set
+# CONFIG_RTC_DRV_RV3029C2 is not set
+
+#
+# SPI RTC drivers
+#
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_MSM6242 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_RP5C01 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+# CONFIG_RTC_DRV_DS2404 is not set
+
+#
+# on-CPU RTC drivers
+#
+# CONFIG_RTC_DRV_SA1100 is not set
+# CONFIG_RTC_DRV_PXA is not set
+# CONFIG_RTC_DRV_MOXART is not set
+
+#
+# HID Sensor RTC drivers
+#
+# CONFIG_RTC_DRV_HID_SENSOR_TIME is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_UIO is not set
+# CONFIG_VIRT_DRIVERS is not set
+
+#
+# Virtio drivers
+#
+# CONFIG_VIRTIO_MMIO is not set
+
+#
+# Microsoft Hyper-V guest support
+#
+# CONFIG_STAGING is not set
+CONFIG_CLKDEV_LOOKUP=y
+
+#
+# Hardware Spinlock drivers
+#
+CONFIG_CLKSRC_MMIO=y
+# CONFIG_ARM_ARCH_TIMER_EVTSTREAM is not set
+# CONFIG_MAILBOX is not set
+# CONFIG_IOMMU_SUPPORT is not set
+
+#
+# Remoteproc drivers
+#
+# CONFIG_STE_MODEM_RPROC is not set
+
+#
+# Rpmsg drivers
+#
+# CONFIG_PM_DEVFREQ is not set
+# CONFIG_EXTCON is not set
+# CONFIG_MEMORY is not set
+# CONFIG_IIO is not set
+# CONFIG_PWM is not set
+# CONFIG_IPACK_BUS is not set
+# CONFIG_RESET_CONTROLLER is not set
+# CONFIG_FMC is not set
+
+#
+# PHY Subsystem
+#
+# CONFIG_GENERIC_PHY is not set
+# CONFIG_PHY_EXYNOS_MIPI_VIDEO is not set
+# CONFIG_POWERCAP is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=m
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+CONFIG_EXT2_FS_XIP=y
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_DEFAULTS_TO_ORDERED=y
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_EXT4_FS=y
+CONFIG_EXT4_FS_POSIX_ACL=y
+CONFIG_EXT4_FS_SECURITY=y
+# CONFIG_EXT4_DEBUG is not set
+CONFIG_FS_XIP=y
+CONFIG_JBD=y
+CONFIG_JBD2=y
+# CONFIG_JBD2_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+CONFIG_REISERFS_PROC_INFO=y
+CONFIG_REISERFS_FS_XATTR=y
+CONFIG_REISERFS_FS_POSIX_ACL=y
+CONFIG_REISERFS_FS_SECURITY=y
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_BTRFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+CONFIG_FS_POSIX_ACL=y
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_FANOTIFY is not set
+# CONFIG_QUOTA is not set
+# CONFIG_QUOTACTL is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+CONFIG_NTFS_FS=m
+# CONFIG_NTFS_DEBUG is not set
+CONFIG_NTFS_RW=y
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_ECRYPT_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_JFFS2_ZLIB=y
+# CONFIG_JFFS2_LZO is not set
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_JFFS2_CMODE_NONE is not set
+CONFIG_JFFS2_CMODE_PRIORITY=y
+# CONFIG_JFFS2_CMODE_SIZE is not set
+# CONFIG_JFFS2_CMODE_FAVOURLZO is not set
+# CONFIG_LOGFS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX6FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_PSTORE is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_F2FS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=m
+CONFIG_NFS_V2=m
+CONFIG_NFS_V3=m
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=m
+# CONFIG_NFS_SWAP is not set
+CONFIG_NFS_V4_1=y
+CONFIG_NFS_V4_2=y
+CONFIG_PNFS_FILE_LAYOUT=m
+CONFIG_NFS_V4_1_IMPLEMENTATION_ID_DOMAIN="kernel.org"
+# CONFIG_NFS_V4_1_MIGRATION is not set
+# CONFIG_NFS_USE_LEGACY_DNS is not set
+CONFIG_NFS_USE_KERNEL_DNS=y
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_ACL_SUPPORT=m
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=m
+CONFIG_SUNRPC_GSS=m
+CONFIG_SUNRPC_BACKCHANNEL=y
+CONFIG_RPCSEC_GSS_KRB5=m
+# CONFIG_SUNRPC_DEBUG is not set
+# CONFIG_CEPH_FS is not set
+CONFIG_CIFS=m
+CONFIG_CIFS_STATS=y
+# CONFIG_CIFS_STATS2 is not set
+# CONFIG_CIFS_WEAK_PW_HASH is not set
+# CONFIG_CIFS_UPCALL is not set
+# CONFIG_CIFS_XATTR is not set
+CONFIG_CIFS_DEBUG=y
+# CONFIG_CIFS_DEBUG2 is not set
+# CONFIG_CIFS_DFS_UPCALL is not set
+# CONFIG_CIFS_SMB2 is not set
+# CONFIG_NCP_FS is not set
+CONFIG_CODA_FS=m
+# CONFIG_AFS_FS is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="cp1251"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+CONFIG_NLS_CODEPAGE_850=y
+CONFIG_NLS_CODEPAGE_852=y
+CONFIG_NLS_CODEPAGE_855=y
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+CONFIG_NLS_CODEPAGE_863=y
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+CONFIG_NLS_CODEPAGE_866=y
+# CONFIG_NLS_CODEPAGE_869 is not set
+CONFIG_NLS_CODEPAGE_936=y
+CONFIG_NLS_CODEPAGE_950=y
+CONFIG_NLS_CODEPAGE_932=y
+CONFIG_NLS_CODEPAGE_949=y
+CONFIG_NLS_CODEPAGE_874=y
+CONFIG_NLS_ISO8859_8=y
+# CONFIG_NLS_CODEPAGE_1250 is not set
+CONFIG_NLS_CODEPAGE_1251=y
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+CONFIG_NLS_ISO8859_15=y
+CONFIG_NLS_KOI8_R=y
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_MAC_ROMAN is not set
+# CONFIG_NLS_MAC_CELTIC is not set
+# CONFIG_NLS_MAC_CENTEURO is not set
+# CONFIG_NLS_MAC_CROATIAN is not set
+# CONFIG_NLS_MAC_CYRILLIC is not set
+# CONFIG_NLS_MAC_GAELIC is not set
+# CONFIG_NLS_MAC_GREEK is not set
+# CONFIG_NLS_MAC_ICELAND is not set
+# CONFIG_NLS_MAC_INUIT is not set
+# CONFIG_NLS_MAC_ROMANIAN is not set
+# CONFIG_NLS_MAC_TURKISH is not set
+CONFIG_NLS_UTF8=y
+
+#
+# Kernel hacking
+#
+
+#
+# printk and dmesg options
+#
+CONFIG_PRINTK_TIME=y
+CONFIG_DEFAULT_MESSAGE_LOGLEVEL=4
+# CONFIG_BOOT_PRINTK_DELAY is not set
+
+#
+# Compile-time checks and compiler options
+#
+# CONFIG_DEBUG_INFO is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+# CONFIG_STRIP_ASM_SYMS is not set
+# CONFIG_READABLE_ASM is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_SECTION_MISMATCH is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set
+# CONFIG_MAGIC_SYSRQ is not set
+CONFIG_DEBUG_KERNEL=y
+
+#
+# Memory Debugging
+#
+# CONFIG_DEBUG_PAGEALLOC is not set
+# CONFIG_DEBUG_OBJECTS is not set
+CONFIG_HAVE_DEBUG_KMEMLEAK=y
+# CONFIG_DEBUG_KMEMLEAK is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_DEBUG_SHIRQ is not set
+
+#
+# Debug Lockups and Hangs
+#
+# CONFIG_LOCKUP_DETECTOR is not set
+# CONFIG_DETECT_HUNG_TASK is not set
+# CONFIG_PANIC_ON_OOPS is not set
+CONFIG_PANIC_ON_OOPS_VALUE=0
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_PREEMPT is not set
+
+#
+# Lock Debugging (spinlocks, mutexes, etc...)
+#
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_ATOMIC_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+# CONFIG_DEBUG_CREDENTIALS is not set
+
+#
+# RCU Debugging
+#
+# CONFIG_PROVE_RCU_DELAY is not set
+# CONFIG_SPARSE_RCU_POINTER is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+CONFIG_RCU_CPU_STALL_TIMEOUT=21
+CONFIG_RCU_CPU_STALL_VERBOSE=y
+# CONFIG_RCU_CPU_STALL_INFO is not set
+# CONFIG_RCU_TRACE is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_NOTIFIER_ERROR_INJECTION is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
+CONFIG_HAVE_C_RECORDMCOUNT=y
+CONFIG_TRACING_SUPPORT=y
+# CONFIG_FTRACE is not set
+
+#
+# Runtime Testing
+#
+# CONFIG_TEST_LIST_SORT is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_RBTREE_TEST is not set
+# CONFIG_INTERVAL_TREE_TEST is not set
+# CONFIG_PERCPU_TEST is not set
+# CONFIG_ATOMIC64_SELFTEST is not set
+# CONFIG_TEST_STRING_HELPERS is not set
+# CONFIG_TEST_KSTRTOX is not set
+# CONFIG_DMA_API_DEBUG is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+# CONFIG_STRICT_DEVMEM is not set
+# CONFIG_ARM_UNWIND is not set
+# CONFIG_DEBUG_USER is not set
+# CONFIG_DEBUG_LL is not set
+CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S"
+# CONFIG_DEBUG_UART_PL01X is not set
+# CONFIG_DEBUG_UART_8250 is not set
+CONFIG_UNCOMPRESS_INCLUDE="mach/uncompress.h"
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+# CONFIG_PERSISTENT_KEYRINGS is not set
+# CONFIG_ENCRYPTED_KEYS is not set
+# CONFIG_KEYS_DEBUG_PROC_KEYS is not set
+# CONFIG_SECURITY_DMESG_RESTRICT is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+CONFIG_DEFAULT_SECURITY_DAC=y
+CONFIG_DEFAULT_SECURITY=""
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD=m
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG=m
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_PCOMP2=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+# CONFIG_CRYPTO_USER is not set
+CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y
+CONFIG_CRYPTO_GF128MUL=m
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_WORKQUEUE=y
+# CONFIG_CRYPTO_CRYPTD is not set
+CONFIG_CRYPTO_AUTHENC=m
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+CONFIG_CRYPTO_CCM=m
+CONFIG_CRYPTO_GCM=m
+CONFIG_CRYPTO_SEQIV=m
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_CTR=m
+CONFIG_CRYPTO_CTS=m
+CONFIG_CRYPTO_ECB=y
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+CONFIG_CRYPTO_CMAC=y
+CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_VMAC is not set
+
+#
+# Digest
+#
+CONFIG_CRYPTO_CRC32C=y
+# CONFIG_CRYPTO_CRC32 is not set
+# CONFIG_CRYPTO_CRCT10DIF is not set
+CONFIG_CRYPTO_GHASH=m
+CONFIG_CRYPTO_MD4=y
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA1_ARM=y
+CONFIG_CRYPTO_SHA256=y
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=y
+CONFIG_CRYPTO_AES_ARM=y
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_ARC4=y
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+CONFIG_CRYPTO_DEFLATE=m
+# CONFIG_CRYPTO_ZLIB is not set
+# CONFIG_CRYPTO_LZO is not set
+# CONFIG_CRYPTO_LZ4 is not set
+# CONFIG_CRYPTO_LZ4HC is not set
+
+#
+# Random Number Generation
+#
+CONFIG_CRYPTO_ANSI_CPRNG=m
+# CONFIG_CRYPTO_USER_API_HASH is not set
+# CONFIG_CRYPTO_USER_API_SKCIPHER is not set
+CONFIG_CRYPTO_HW=y
+# CONFIG_ASYMMETRIC_KEY_TYPE is not set
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_STRNCPY_FROM_USER=y
+CONFIG_GENERIC_STRNLEN_USER=y
+CONFIG_GENERIC_NET_UTILS=y
+CONFIG_GENERIC_PCI_IOMAP=y
+CONFIG_GENERIC_IO=y
+CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y
+CONFIG_CRC_CCITT=y
+CONFIG_CRC16=y
+# CONFIG_CRC_T10DIF is not set
+CONFIG_CRC_ITU_T=y
+CONFIG_CRC32=y
+# CONFIG_CRC32_SELFTEST is not set
+CONFIG_CRC32_SLICEBY8=y
+# CONFIG_CRC32_SLICEBY4 is not set
+# CONFIG_CRC32_SARWATE is not set
+# CONFIG_CRC32_BIT is not set
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+# CONFIG_CRC8 is not set
+# CONFIG_RANDOM32_SELFTEST is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+# CONFIG_XZ_DEC is not set
+# CONFIG_XZ_DEC_BCJ is not set
+CONFIG_TEXTSEARCH=y
+CONFIG_TEXTSEARCH_KMP=y
+CONFIG_TEXTSEARCH_BM=y
+CONFIG_TEXTSEARCH_FSM=y
+CONFIG_ASSOCIATIVE_ARRAY=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_DQL=y
+CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
+CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y
+# CONFIG_AVERAGE is not set
+# CONFIG_CORDIC is not set
+# CONFIG_DDR is not set
+CONFIG_OID_REGISTRY=m
+CONFIG_FONT_SUPPORT=m
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+# CONFIG_VIRTUALIZATION is not set
diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig
index 96100db..efaf2d0 100644
--- a/arch/arm/mach-pxa/Kconfig
+++ b/arch/arm/mach-pxa/Kconfig
@@ -273,6 +273,22 @@ config MACH_VPAC270
 
 comment "End-user Products (sorted by vendor name)"
 
+config MACH_LP8X4X
+	bool "ICP DAS LP-8X4X"
+	select IWMMXT
+	select PXA27x
+	help
+	  Say Y here if you intend to run this kernel on an ICP DAS
+	  LP-8x4x programmable automation controller.
+
+	  LP-8x4x is ARM-based and built around PXA270 SoC. The device
+	  has 128 MiB SDRAM, 48 or 96 MiB NOR flash, VGA port with
+	  800x600 resolution, MMC card slot, 2 Ethernet ports, 1 USB
+	  port, 5 serial ports (1 on them is wired internally to
+	  expansion slots). The device has a range of digital and
+	  analog expansion IO modules which can be installed in 1, 4 or
+	  8 slots depending on the model.
+
 config MACH_H4700
 	bool "HP iPAQ hx4700"
 	select HAVE_PWM
diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile
index 648867a..b264325 100644
--- a/arch/arm/mach-pxa/Makefile
+++ b/arch/arm/mach-pxa/Makefile
@@ -63,6 +63,7 @@ obj-$(CONFIG_MACH_COLIBRI320)	+= colibri-pxa3xx.o colibri-pxa320.o
 obj-$(CONFIG_MACH_VPAC270)	+= vpac270.o
 
 # End-user Products
+obj-$(CONFIG_MACH_LP8X4X)	+= lp8x4x.o
 obj-$(CONFIG_MACH_H4700)	+= hx4700.o
 obj-$(CONFIG_MACH_H5000)	+= h5000.o
 obj-$(CONFIG_MACH_HIMALAYA)	+= himalaya.o
diff --git a/arch/arm/mach-pxa/include/mach/lp8x4x.h b/arch/arm/mach-pxa/include/mach/lp8x4x.h
new file mode 100644
index 0000000..8c501fd
--- /dev/null
+++ b/arch/arm/mach-pxa/include/mach/lp8x4x.h
@@ -0,0 +1,74 @@
+/*
+ *  arch/arm/mach-pxa/include/mach/lp8x4x.h
+ *
+ *  Support for ICP DAS LP-8x4x programmable automation controller
+ *  Copyright (C) 2013 Sergei Ianovich <ynvich@gmail.com>
+ *
+ *  borrowed heavily from
+ *  Support for the Intel HCDDBBVA0 Development Platform.
+ *
+ *  Author:	Nicolas Pitre
+ *  Created:	Nov 14, 2002
+ *  Copyright:	MontaVista Software Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef ASM_ARCH_LP8X4X_H
+#define ASM_ARCH_LP8X4X_H
+
+#include <asm/io.h>
+#include <mach/irqs.h>
+
+#define LP8X4X_ETH0_BASE        0x0c000000
+#define LP8X4X_ETH0_IO          0x0c004000
+#define LP8X4X_ETH0_IRQ         PXA_GPIO_TO_IRQ(9)
+
+#define LP8X4X_ETH1_BASE        0x0d000000
+#define LP8X4X_ETH1_IO          0x0d004000
+#define LP8X4X_ETH1_IRQ         PXA_GPIO_TO_IRQ(82)
+
+#define LP8X4X_FPGA_PHYS	0x17000000
+#define LP8X4X_FPGA_VIRT	0xf1000000
+#define LP8X4X_P2V(x)		IOMEM((x) - LP8X4X_FPGA_PHYS + LP8X4X_FPGA_VIRT)
+#define LP8X4X_V2P(x)		((x) - LP8X4X_FPGA_VIRT + LP8X4X_FPGA_PHYS)
+
+/* board level registers in the FPGA */
+
+#define LP8X4X_EOI		LP8X4X_P2V(0x17009006)
+#define LP8X4X_INSINT		LP8X4X_P2V(0x17009008)
+#define LP8X4X_ENSYSINT		LP8X4X_P2V(0x1700900A)
+#define LP8X4X_PRIMINT		LP8X4X_P2V(0x1700900C)
+#define LP8X4X_SECOINT		LP8X4X_P2V(0x1700900E)
+#define LP8X4X_ENRISEINT	LP8X4X_P2V(0x17009010)
+#define LP8X4X_CLRRISEINT	LP8X4X_P2V(0x17009012)
+#define LP8X4X_ENHILVINT	LP8X4X_P2V(0x17009014)
+#define LP8X4X_CLRHILVINT	LP8X4X_P2V(0x17009016)
+#define LP8X4X_ENFALLINT	LP8X4X_P2V(0x17009018)
+#define LP8X4X_CLRFALLINT	LP8X4X_P2V(0x1700901a)
+
+/* board specific IRQs */
+
+#define LP8X4X_IRQ(x)		(IRQ_BOARD_START + (x))
+#define LP8X4X_SLOT1_IRQ	LP8X4X_IRQ(0)
+#define LP8X4X_SLOT2_IRQ	LP8X4X_IRQ(1)
+#define LP8X4X_SLOT3_IRQ	LP8X4X_IRQ(2)
+#define LP8X4X_SLOT4_IRQ	LP8X4X_IRQ(3)
+#define LP8X4X_SLOT5_IRQ	LP8X4X_IRQ(4)
+#define LP8X4X_SLOT6_IRQ	LP8X4X_IRQ(5)
+#define LP8X4X_SLOT7_IRQ	LP8X4X_IRQ(6)
+#define LP8X4X_SLOT8_IRQ	LP8X4X_IRQ(7)
+#define LP8X4X_TIMER1_IRQ	LP8X4X_IRQ(8)
+#define LP8X4X_TIMER2_IRQ	LP8X4X_IRQ(9)
+#define LP8X4X_TIMEROUT_IRQ	LP8X4X_IRQ(10)
+#define LP8X4X_HOTPLUG_IRQ	LP8X4X_IRQ(11)
+#define LP8X4X_BATLOW_IRQ	LP8X4X_IRQ(12)
+#define LP8X4X_TTYS0_IRQ	LP8X4X_IRQ(13)
+#define LP8X4X_TTYS1_IRQ	LP8X4X_IRQ(14)
+#define LP8X4X_TTYS2_IRQ	LP8X4X_IRQ(15)
+
+#define LP8X4X_NR_IRQS		(IRQ_BOARD_START + 16)
+
+#endif
diff --git a/arch/arm/mach-pxa/lp8x4x.c b/arch/arm/mach-pxa/lp8x4x.c
new file mode 100644
index 0000000..0b77e7a
--- /dev/null
+++ b/arch/arm/mach-pxa/lp8x4x.c
@@ -0,0 +1,460 @@
+/*
+ *  linux/arch/arm/mach-pxa/lp8x4x.c
+ *
+ *  Support for ICP DAS LP-8x4x programmable automation controller
+ *  Copyright (C) 2013 Sergei Ianovich <ynvich@gmail.com>
+ *
+ *  borrowed heavily from
+ *  Support for the Intel HCDDBBVA0 Development Platform.
+ *
+ *  Author:	Nicolas Pitre
+ *  Created:	Nov 05, 2002
+ *  Copyright:	MontaVista Software Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation or any later version.
+ */
+#include <linux/gpio.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/syscore_ops.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/bitops.h>
+#include <linux/fb.h>
+#include <linux/ioport.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/input.h>
+#include <linux/dm9000.h>
+#include <linux/slab.h>
+#include <linux/leds.h>
+#include <linux/ktime.h>
+#include <linux/irqchip/chained_irq.h>
+
+#include <asm/types.h>
+#include <asm/setup.h>
+#include <asm/memory.h>
+#include <asm/mach-types.h>
+#include <mach/hardware.h>
+#include <asm/irq.h>
+#include <asm/sizes.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+#include <asm/mach/flash.h>
+
+#include <mach/pxa27x.h>
+#include <mach/lp8x4x.h>
+#include <linux/platform_data/video-pxafb.h>
+#include <linux/platform_data/mmc-pxamci.h>
+#include <linux/platform_data/usb-ohci-pxa27x.h>
+#include <mach/smemc.h>
+
+#include "generic.h"
+#include "devices.h"
+
+static unsigned char lp8x4x_irq_sys_enabled;
+static unsigned char lp8x4x_irq_high_enabled;
+
+static void lp8x4x_ack_irq(struct irq_data *d)
+{
+	unsigned mask;
+	int irq = d->irq - IRQ_BOARD_START;
+
+	if (irq < 0 || irq > 15) {
+		pr_err("lp8x4x: wrong irq handler for irq %i\n", d->irq);
+		return;
+	}
+
+	if (irq < 8) {
+		mask = ioread8(LP8X4X_CLRHILVINT);
+		mask |= 1 << irq;
+		iowrite8(mask, LP8X4X_CLRHILVINT);
+	} else if (irq < 13) {
+		irq -= 8;
+		mask = ioread8(LP8X4X_SECOINT);
+		mask |= 1 << irq;
+		iowrite8(mask, LP8X4X_SECOINT);
+	} else {
+		irq -= 8;
+		mask = ioread8(LP8X4X_PRIMINT);
+		mask |= 1 << irq;
+		iowrite8(mask, LP8X4X_PRIMINT);
+	}
+}
+
+static void lp8x4x_mask_irq(struct irq_data *d)
+{
+	int irq = d->irq - IRQ_BOARD_START;
+
+	if (irq < 0 || irq > 15) {
+		pr_err("lp8x4x: wrong irq handler for irq %i\n", d->irq);
+		return;
+	}
+
+	if (irq < 8) {
+		lp8x4x_irq_high_enabled &= ~(1 << irq);
+		iowrite8(lp8x4x_irq_high_enabled, LP8X4X_ENHILVINT);
+	} else {
+		irq -= 8;
+		lp8x4x_irq_sys_enabled &= ~(1 << irq);
+		iowrite8(lp8x4x_irq_sys_enabled, LP8X4X_ENSYSINT);
+	}
+}
+
+static void lp8x4x_unmask_irq(struct irq_data *d)
+{
+	unsigned mask;
+	int irq = d->irq - IRQ_BOARD_START;
+
+	if (irq < 0 || irq > 15) {
+		pr_err("wrong irq handler for irq %i\n", d->irq);
+		return;
+	}
+
+	if (irq < 8) {
+		lp8x4x_irq_high_enabled |= 1 << irq;
+		mask = ioread8(LP8X4X_CLRHILVINT);
+		mask |= 1 << irq;
+		iowrite8(mask, LP8X4X_CLRHILVINT);
+		iowrite8(lp8x4x_irq_high_enabled, LP8X4X_ENHILVINT);
+	} else if (irq < 13) {
+		irq -= 8;
+		lp8x4x_irq_sys_enabled |= 1 << irq;
+		mask = ioread8(LP8X4X_SECOINT);
+		mask |= 1 << irq;
+		iowrite8(mask, LP8X4X_SECOINT);
+		iowrite8(lp8x4x_irq_sys_enabled, LP8X4X_ENSYSINT);
+	} else {
+		irq -= 8;
+		lp8x4x_irq_sys_enabled |= 1 << irq;
+		mask = ioread8(LP8X4X_PRIMINT);
+		mask |= 1 << irq;
+		iowrite8(mask, LP8X4X_PRIMINT);
+		iowrite8(lp8x4x_irq_sys_enabled, LP8X4X_ENSYSINT);
+	}
+}
+
+static struct irq_chip lp8x4x_irq_chip = {
+	.name			= "FPGA",
+	.irq_ack		= lp8x4x_ack_irq,
+	.irq_mask		= lp8x4x_mask_irq,
+	.irq_unmask		= lp8x4x_unmask_irq,
+};
+
+static spinlock_t fpga_irq_lock;
+
+static void lp8x4x_irq_handler(unsigned int irq, struct irq_desc *desc)
+{
+	int loop, n;
+	unsigned long mask;
+	unsigned long flags;
+	struct irq_chip *chip = irq_desc_get_chip(desc);
+
+	spin_lock_irqsave(&fpga_irq_lock, flags);
+	chained_irq_enter(chip, desc);
+
+	do {
+		loop = 0;
+		mask = ioread8(LP8X4X_CLRHILVINT) & 0xff;
+		mask |= (ioread8(LP8X4X_SECOINT) & 0x1f) << 8;
+		mask |= (ioread8(LP8X4X_PRIMINT) & 0xe0) << 8;
+		mask &= (lp8x4x_irq_high_enabled
+				| (lp8x4x_irq_sys_enabled << 8));
+		for_each_set_bit(n, &mask, BITS_PER_LONG) {
+			loop = 1;
+
+			generic_handle_irq(IRQ_BOARD_START + n);
+		}
+	} while (loop);
+
+	chained_irq_exit(chip, desc);
+	iowrite8(0, LP8X4X_EOI);
+	spin_unlock_irqrestore(&fpga_irq_lock, flags);
+}
+
+static void __init lp8x4x_init_irq(void)
+{
+	int irq;
+	int err;
+
+	err = irq_set_irq_type(PXA_GPIO_TO_IRQ(3), IRQ_TYPE_EDGE_RISING);
+	if (err < 0) {
+		pr_err("lp8x4x: irq init failed\n");
+		return;
+	}
+
+	spin_lock_init(&fpga_irq_lock);
+	irq_set_chained_handler(PXA_GPIO_TO_IRQ(3), lp8x4x_irq_handler);
+
+	for (irq = IRQ_BOARD_START; irq < LP8X4X_NR_IRQS; irq++) {
+		irq_set_chip_and_handler(irq, &lp8x4x_irq_chip,
+					 handle_level_irq);
+		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+	}
+
+	iowrite8(0, LP8X4X_CLRRISEINT);
+	iowrite8(0, LP8X4X_ENRISEINT);
+	iowrite8(0, LP8X4X_CLRFALLINT);
+	iowrite8(0, LP8X4X_ENFALLINT);
+	iowrite8(0, LP8X4X_CLRHILVINT);
+	iowrite8(0, LP8X4X_ENHILVINT);
+	iowrite8(0, LP8X4X_ENSYSINT);
+	iowrite8(0, LP8X4X_PRIMINT);
+	iowrite8(0, LP8X4X_SECOINT);
+
+	return;
+}
+
+static unsigned long lp8x4x_pin_config[] = {
+	/* MMC */
+	GPIO32_MMC_CLK,
+	GPIO112_MMC_CMD,
+	GPIO92_MMC_DAT_0,
+	GPIO109_MMC_DAT_1,
+	GPIO110_MMC_DAT_2,
+	GPIO111_MMC_DAT_3,
+
+	/* USB Host Port 1 */
+	GPIO88_USBH1_PWR,
+	GPIO89_USBH1_PEN,
+};
+
+static struct resource lp8x4x_flash_resources[] = {
+	[0] = {
+		.start	= PXA_CS0_PHYS,
+		.end	= PXA_CS0_PHYS + SZ_64M - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= PXA_CS1_PHYS,
+		.end	= PXA_CS1_PHYS + SZ_32M - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct mtd_partition lp8x4x_flash0_partitions[] = {
+	{
+		.name =		"Bootloader",
+		.size =		0x00040000,
+		.offset =	0,
+	}, {
+		.name =		"Settings",
+		.size =		0x00040000,
+		.offset =	0x00040000,
+	}, {
+		.name =		"Kernel",
+		.size =		0x00280000,
+		.offset =	0x00080000,
+	}, {
+		.name =		"Filesystem",
+		.size =		MTDPART_SIZ_FULL,
+		.offset =	0x00300000
+	}
+};
+
+static struct flash_platform_data lp8x4x_flash_data[] = {
+	{
+		.map_name	= "cfi_probe",
+		.parts		= lp8x4x_flash0_partitions,
+		.nr_parts	= ARRAY_SIZE(lp8x4x_flash0_partitions),
+		.width		= 4,
+	}, {
+		.map_name	= "cfi_probe",
+		.parts		= NULL,
+		.nr_parts	= 0,
+		.width		= 2,
+	}
+};
+
+static struct platform_device lp8x4x_flash_device[] = {
+	{
+		.name		= "pxa2xx-flash",
+		.id		= 0,
+		.dev = {
+			.platform_data = &lp8x4x_flash_data[0],
+		},
+		.resource = &lp8x4x_flash_resources[0],
+		.num_resources = 1,
+	},
+	{
+		.name		= "pxa2xx-flash",
+		.id		= 1,
+		.dev = {
+			.platform_data = &lp8x4x_flash_data[1],
+		},
+		.resource = &lp8x4x_flash_resources[1],
+		.num_resources = 1,
+	},
+};
+
+static struct pxafb_mode_info lp8x4x_vga_60_mode = {
+	.pixclock       = 38461,
+	.xres           = 640,
+	.yres           = 480,
+	.bpp            = 16,
+	.hsync_len      = 64,
+	.left_margin    = 78,
+	.right_margin   = 46,
+	.vsync_len      = 12,
+	.upper_margin   = 22,
+	.lower_margin   = 10,
+	.sync           = 0,
+};
+
+static struct pxafb_mach_info lp8x4x_pxafb_info = {
+	.num_modes		= 1,
+	.lccr0			= LCCR0_Act,
+	.lccr3			= LCCR3_PCP,
+};
+
+static int lp8x4x_mci_init(struct device *dev,
+		irq_handler_t mstone_detect_int, void *data)
+{
+	return 0;
+}
+
+static int lp8x4x_mci_setpower(struct device *dev, unsigned int vdd)
+{
+	return 0;
+}
+
+static void lp8x4x_mci_exit(struct device *dev, void *data)
+{
+}
+
+static struct pxamci_platform_data lp8x4x_mci_platform_data = {
+	.ocr_mask		= MMC_VDD_32_33|MMC_VDD_33_34,
+	.init			= lp8x4x_mci_init,
+	.setpower               = lp8x4x_mci_setpower,
+	.exit			= lp8x4x_mci_exit,
+	.gpio_card_detect	= -1,
+	.gpio_card_ro		= -1,
+	.gpio_power		= -1,
+};
+
+static struct resource lp8x4x_dm9000_resources[] = {
+	[0] = {
+		.start  = LP8X4X_ETH0_BASE,
+		.end    = LP8X4X_ETH0_BASE + 2 - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start  = LP8X4X_ETH0_IO,
+		.end    = LP8X4X_ETH0_IO + 2 - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	[2] = {
+		.start  = LP8X4X_ETH0_IRQ,
+		.end    = LP8X4X_ETH0_IRQ,
+		.flags	= IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE,
+	},
+	[3] = {
+		.start  = LP8X4X_ETH1_BASE,
+		.end    = LP8X4X_ETH1_BASE + 2 - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	[4] = {
+		.start  = LP8X4X_ETH1_IO,
+		.end    = LP8X4X_ETH1_IO + 2 - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	[5] = {
+		.start  = LP8X4X_ETH1_IRQ,
+		.end    = LP8X4X_ETH1_IRQ,
+		.flags	= IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE,
+	},
+};
+
+static struct platform_device lp8x4x_dm9000_device[2] = {
+	{
+		.name           = "dm9000",
+		.id             = 0,
+		.dev = {},
+		.resource = &lp8x4x_dm9000_resources[0],
+		.num_resources = 3,
+	},
+	{
+		.name           = "dm9000",
+		.id             = 1,
+		.dev = {},
+		.resource = &lp8x4x_dm9000_resources[3],
+		.num_resources = 3,
+	},
+};
+
+static struct platform_device *lp8x4x_devices[] __initdata = {
+	&lp8x4x_flash_device[0],
+	&lp8x4x_flash_device[1],
+	&lp8x4x_dm9000_device[0],
+	&lp8x4x_dm9000_device[1],
+};
+
+static struct pxaohci_platform_data lp8x4x_ohci_platform_data = {
+	.port_mode	= PMM_PERPORT_MODE,
+	.flags		= ENABLE_PORT1 | OC_MODE_PERPORT,
+};
+
+static void lp8x4x_restart(enum reboot_mode mode, const char *cmd)
+{
+	/* Switch off fast-bus and turbo mode */
+	asm volatile("mcr       p14, 0, %0, c6, c0, 0" : :
+			"r"(2));
+	/* SDRAM hangs on watchdog reset on Marvell PXA270 (erratum 71) */
+	pxa_restart(REBOOT_SOFT, cmd);
+}
+
+static void __init lp8x4x_init(void)
+{
+	pxa2xx_mfp_config(ARRAY_AND_SIZE(lp8x4x_pin_config));
+
+	pxa_set_ffuart_info(NULL);
+	pxa_set_btuart_info(NULL);
+	pxa_set_stuart_info(NULL);
+
+	/* system bus arbiter setting
+	 * - Core_Park
+	 * - LCD_wt:DMA_wt:CORE_Wt = 2:3:4
+	 */
+	ARB_CNTRL = ARB_CORE_PARK | 0x234;
+
+	pxa_set_mci_info(&lp8x4x_mci_platform_data);
+	pxa_set_ohci_info(&lp8x4x_ohci_platform_data);
+
+	platform_add_devices(ARRAY_AND_SIZE(lp8x4x_devices));
+
+	lp8x4x_pxafb_info.modes = &lp8x4x_vga_60_mode;
+	pxa_set_fb_info(NULL, &lp8x4x_pxafb_info);
+
+	/* Could not do this in MACHINE since GPIO is not ready then */
+	lp8x4x_init_irq();
+}
+
+static struct map_desc lp8x4x_io_desc[] __initdata = {
+	{	/* CPLD */
+		.virtual	=  LP8X4X_FPGA_VIRT,
+		.pfn		= __phys_to_pfn(LP8X4X_FPGA_PHYS),
+		.length		= 0x00100000,
+		.type		= MT_DEVICE
+	}
+};
+
+static void __init lp8x4x_map_io(void)
+{
+	pxa27x_map_io();
+	iotable_init(lp8x4x_io_desc, ARRAY_SIZE(lp8x4x_io_desc));
+}
+
+MACHINE_START(LP8X4X, "ICP DAS LP-8x4x programmable automation controller")
+	.atag_offset	= 0x100,
+	.map_io		= lp8x4x_map_io,
+	.nr_irqs	= LP8X4X_NR_IRQS,
+	.init_irq	= pxa27x_init_irq,
+	.handle_irq	= pxa27x_handle_irq,
+	.init_time	= pxa_timer_init,
+	.init_machine	= lp8x4x_init,
+	.restart	= lp8x4x_restart,
+MACHINE_END
-- 
1.8.4.2

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

* [PATCH 03/11] rtc: support DS1302 RTC on ICP DAS LP-8x4x
  2013-12-01  6:26 ` Sergei Ianovich
@ 2013-12-01  6:26   ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-01  6:26 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Russell King, Eric Miao, Haojian Zhuang,
	Alessandro Zummo

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
 arch/arm/configs/lp8x4x_defconfig       |  1 +
 arch/arm/mach-pxa/include/mach/lp8x4x.h |  1 +
 arch/arm/mach-pxa/lp8x4x.c              |  8 ++++
 drivers/rtc/Kconfig                     |  2 +-
 drivers/rtc/rtc-ds1302.c                | 85 +++++++++++++++++++++++++++++++++
 5 files changed, 96 insertions(+), 1 deletion(-)

diff --git a/arch/arm/configs/lp8x4x_defconfig b/arch/arm/configs/lp8x4x_defconfig
index 5cd6d38..27831e4 100644
--- a/arch/arm/configs/lp8x4x_defconfig
+++ b/arch/arm/configs/lp8x4x_defconfig
@@ -1745,6 +1745,7 @@ CONFIG_RTC_INTF_DEV=y
 #
 # CONFIG_RTC_DRV_CMOS is not set
 # CONFIG_RTC_DRV_DS1286 is not set
+CONFIG_RTC_DRV_DS1302=y
 # CONFIG_RTC_DRV_DS1511 is not set
 # CONFIG_RTC_DRV_DS1553 is not set
 # CONFIG_RTC_DRV_DS1742 is not set
diff --git a/arch/arm/mach-pxa/include/mach/lp8x4x.h b/arch/arm/mach-pxa/include/mach/lp8x4x.h
index 8c501fd..d8a1376 100644
--- a/arch/arm/mach-pxa/include/mach/lp8x4x.h
+++ b/arch/arm/mach-pxa/include/mach/lp8x4x.h
@@ -48,6 +48,7 @@
 #define LP8X4X_CLRHILVINT	LP8X4X_P2V(0x17009016)
 #define LP8X4X_ENFALLINT	LP8X4X_P2V(0x17009018)
 #define LP8X4X_CLRFALLINT	LP8X4X_P2V(0x1700901a)
+#define LP8X4X_RWRTC		LP8X4X_P2V(0x1700901c)
 
 /* board specific IRQs */
 
diff --git a/arch/arm/mach-pxa/lp8x4x.c b/arch/arm/mach-pxa/lp8x4x.c
index 0b77e7a..a31b556 100644
--- a/arch/arm/mach-pxa/lp8x4x.c
+++ b/arch/arm/mach-pxa/lp8x4x.c
@@ -386,11 +386,19 @@ static struct platform_device lp8x4x_dm9000_device[2] = {
 	},
 };
 
+static struct platform_device lp8x4x_ds1302_device[] = {
+	{
+		.name           = "rtc-ds1302",
+		.id             = 0,
+	},
+};
+
 static struct platform_device *lp8x4x_devices[] __initdata = {
 	&lp8x4x_flash_device[0],
 	&lp8x4x_flash_device[1],
 	&lp8x4x_dm9000_device[0],
 	&lp8x4x_dm9000_device[1],
+	&lp8x4x_ds1302_device[0],
 };
 
 static struct pxaohci_platform_data lp8x4x_ohci_platform_data = {
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 0077302..59213c0 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -676,7 +676,7 @@ config RTC_DRV_DS1286
 
 config RTC_DRV_DS1302
 	tristate "Dallas DS1302"
-	depends on SH_SECUREEDGE5410
+	depends on SH_SECUREEDGE5410 || MACH_LP8X4X
 	help
 	  If you say yes here you get support for the Dallas DS1302 RTC chips.
 
diff --git a/drivers/rtc/rtc-ds1302.c b/drivers/rtc/rtc-ds1302.c
index 07e8d79..770587b 100644
--- a/drivers/rtc/rtc-ds1302.c
+++ b/drivers/rtc/rtc-ds1302.c
@@ -86,6 +86,91 @@ static inline int ds1302_rxbit(void)
 	return !!(get_dp() & RTC_IODATA);
 }
 
+#elif defined(CONFIG_MACH_LP8X4X)
+
+#include <linux/sched.h>
+#include <linux/hrtimer.h>
+#include <mach/lp8x4x.h>
+
+#define	RTC_CE		0x01
+#define	RTC_CLK		0x02
+#define	RTC_nWE		0x04
+#define	RTC_IODATA	0x08
+
+static unsigned long ds1302_state;
+
+void nsleep(unsigned long nanosec)
+{
+	ktime_t t = ns_to_ktime(nanosec);
+	long state = current->state;
+
+	__set_current_state(TASK_UNINTERRUPTIBLE);
+	schedule_hrtimeout(&t, HRTIMER_MODE_REL);
+	__set_current_state(state);
+}
+
+static inline int ds1302_hw_init(void)
+{
+	return 0;
+}
+
+static inline void ds1302_reset(void)
+{
+	ds1302_state = 0;
+	iowrite8(ds1302_state, LP8X4X_RWRTC);
+	nsleep(4000);
+}
+
+static inline void ds1302_clock(void)
+{
+	nsleep(1000);
+	ds1302_state |= RTC_CLK;
+	iowrite8(ds1302_state, LP8X4X_RWRTC);
+	nsleep(1000);
+	ds1302_state &= ~RTC_CLK;
+	iowrite8(ds1302_state, LP8X4X_RWRTC);
+}
+
+static inline void ds1302_start(void)
+{
+	ds1302_state &= ~RTC_CLK;
+	ds1302_state |= RTC_CE;
+	iowrite8(ds1302_state, LP8X4X_RWRTC);
+	nsleep(3000);
+}
+
+static inline void ds1302_stop(void)
+{
+	ds1302_state &= ~RTC_CE;
+	iowrite8(ds1302_state, LP8X4X_RWRTC);
+}
+
+static inline void ds1302_set_tx(void)
+{
+	ds1302_state &= ~RTC_nWE;
+	iowrite8(ds1302_state, LP8X4X_RWRTC);
+}
+
+static inline void ds1302_set_rx(void)
+{
+	ds1302_state |= RTC_nWE;
+	iowrite8(ds1302_state, LP8X4X_RWRTC);
+}
+
+static inline void ds1302_txbit(int bit)
+{
+	if (bit)
+		ds1302_state |= RTC_IODATA;
+	else
+		ds1302_state &= ~RTC_IODATA;
+	iowrite8(ds1302_state, LP8X4X_RWRTC);
+}
+
+static inline int ds1302_rxbit(void)
+{
+	return ioread8(LP8X4X_RWRTC) & 0x1;
+}
+
 #else
 #error "Add support for your platform"
 #endif
-- 
1.8.4.2


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

* [PATCH 03/11] rtc: support DS1302 RTC on ICP DAS LP-8x4x
@ 2013-12-01  6:26   ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-01  6:26 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
 arch/arm/configs/lp8x4x_defconfig       |  1 +
 arch/arm/mach-pxa/include/mach/lp8x4x.h |  1 +
 arch/arm/mach-pxa/lp8x4x.c              |  8 ++++
 drivers/rtc/Kconfig                     |  2 +-
 drivers/rtc/rtc-ds1302.c                | 85 +++++++++++++++++++++++++++++++++
 5 files changed, 96 insertions(+), 1 deletion(-)

diff --git a/arch/arm/configs/lp8x4x_defconfig b/arch/arm/configs/lp8x4x_defconfig
index 5cd6d38..27831e4 100644
--- a/arch/arm/configs/lp8x4x_defconfig
+++ b/arch/arm/configs/lp8x4x_defconfig
@@ -1745,6 +1745,7 @@ CONFIG_RTC_INTF_DEV=y
 #
 # CONFIG_RTC_DRV_CMOS is not set
 # CONFIG_RTC_DRV_DS1286 is not set
+CONFIG_RTC_DRV_DS1302=y
 # CONFIG_RTC_DRV_DS1511 is not set
 # CONFIG_RTC_DRV_DS1553 is not set
 # CONFIG_RTC_DRV_DS1742 is not set
diff --git a/arch/arm/mach-pxa/include/mach/lp8x4x.h b/arch/arm/mach-pxa/include/mach/lp8x4x.h
index 8c501fd..d8a1376 100644
--- a/arch/arm/mach-pxa/include/mach/lp8x4x.h
+++ b/arch/arm/mach-pxa/include/mach/lp8x4x.h
@@ -48,6 +48,7 @@
 #define LP8X4X_CLRHILVINT	LP8X4X_P2V(0x17009016)
 #define LP8X4X_ENFALLINT	LP8X4X_P2V(0x17009018)
 #define LP8X4X_CLRFALLINT	LP8X4X_P2V(0x1700901a)
+#define LP8X4X_RWRTC		LP8X4X_P2V(0x1700901c)
 
 /* board specific IRQs */
 
diff --git a/arch/arm/mach-pxa/lp8x4x.c b/arch/arm/mach-pxa/lp8x4x.c
index 0b77e7a..a31b556 100644
--- a/arch/arm/mach-pxa/lp8x4x.c
+++ b/arch/arm/mach-pxa/lp8x4x.c
@@ -386,11 +386,19 @@ static struct platform_device lp8x4x_dm9000_device[2] = {
 	},
 };
 
+static struct platform_device lp8x4x_ds1302_device[] = {
+	{
+		.name           = "rtc-ds1302",
+		.id             = 0,
+	},
+};
+
 static struct platform_device *lp8x4x_devices[] __initdata = {
 	&lp8x4x_flash_device[0],
 	&lp8x4x_flash_device[1],
 	&lp8x4x_dm9000_device[0],
 	&lp8x4x_dm9000_device[1],
+	&lp8x4x_ds1302_device[0],
 };
 
 static struct pxaohci_platform_data lp8x4x_ohci_platform_data = {
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 0077302..59213c0 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -676,7 +676,7 @@ config RTC_DRV_DS1286
 
 config RTC_DRV_DS1302
 	tristate "Dallas DS1302"
-	depends on SH_SECUREEDGE5410
+	depends on SH_SECUREEDGE5410 || MACH_LP8X4X
 	help
 	  If you say yes here you get support for the Dallas DS1302 RTC chips.
 
diff --git a/drivers/rtc/rtc-ds1302.c b/drivers/rtc/rtc-ds1302.c
index 07e8d79..770587b 100644
--- a/drivers/rtc/rtc-ds1302.c
+++ b/drivers/rtc/rtc-ds1302.c
@@ -86,6 +86,91 @@ static inline int ds1302_rxbit(void)
 	return !!(get_dp() & RTC_IODATA);
 }
 
+#elif defined(CONFIG_MACH_LP8X4X)
+
+#include <linux/sched.h>
+#include <linux/hrtimer.h>
+#include <mach/lp8x4x.h>
+
+#define	RTC_CE		0x01
+#define	RTC_CLK		0x02
+#define	RTC_nWE		0x04
+#define	RTC_IODATA	0x08
+
+static unsigned long ds1302_state;
+
+void nsleep(unsigned long nanosec)
+{
+	ktime_t t = ns_to_ktime(nanosec);
+	long state = current->state;
+
+	__set_current_state(TASK_UNINTERRUPTIBLE);
+	schedule_hrtimeout(&t, HRTIMER_MODE_REL);
+	__set_current_state(state);
+}
+
+static inline int ds1302_hw_init(void)
+{
+	return 0;
+}
+
+static inline void ds1302_reset(void)
+{
+	ds1302_state = 0;
+	iowrite8(ds1302_state, LP8X4X_RWRTC);
+	nsleep(4000);
+}
+
+static inline void ds1302_clock(void)
+{
+	nsleep(1000);
+	ds1302_state |= RTC_CLK;
+	iowrite8(ds1302_state, LP8X4X_RWRTC);
+	nsleep(1000);
+	ds1302_state &= ~RTC_CLK;
+	iowrite8(ds1302_state, LP8X4X_RWRTC);
+}
+
+static inline void ds1302_start(void)
+{
+	ds1302_state &= ~RTC_CLK;
+	ds1302_state |= RTC_CE;
+	iowrite8(ds1302_state, LP8X4X_RWRTC);
+	nsleep(3000);
+}
+
+static inline void ds1302_stop(void)
+{
+	ds1302_state &= ~RTC_CE;
+	iowrite8(ds1302_state, LP8X4X_RWRTC);
+}
+
+static inline void ds1302_set_tx(void)
+{
+	ds1302_state &= ~RTC_nWE;
+	iowrite8(ds1302_state, LP8X4X_RWRTC);
+}
+
+static inline void ds1302_set_rx(void)
+{
+	ds1302_state |= RTC_nWE;
+	iowrite8(ds1302_state, LP8X4X_RWRTC);
+}
+
+static inline void ds1302_txbit(int bit)
+{
+	if (bit)
+		ds1302_state |= RTC_IODATA;
+	else
+		ds1302_state &= ~RTC_IODATA;
+	iowrite8(ds1302_state, LP8X4X_RWRTC);
+}
+
+static inline int ds1302_rxbit(void)
+{
+	return ioread8(LP8X4X_RWRTC) & 0x1;
+}
+
 #else
 #error "Add support for your platform"
 #endif
-- 
1.8.4.2

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

* [PATCH 04/11] mtd: support BB SRAM on ICP DAS LP-8x4x
  2013-12-01  6:26 ` Sergei Ianovich
  (?)
@ 2013-12-01  6:26   ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-01  6:26 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Russell King, Eric Miao, Haojian Zhuang,
	David Woodhouse, Artem Bityutskiy, Robert Jarzmik, Kees Cook,
	Randy Dunlap, Philip Avinash, open list:MEMORY TECHNOLOGY...

This provides an MTD device driver for 512kB of battery backed up SRAM
on ICPDAS LP-8X4X programmable automation controllers.

SRAM chip is connected via FPGA and is not accessible without a driver,
unlike flash memory which is wired to CPU MMU.

This SRAM becomes an excellent persisent storage of volatile process
data like counter values and sensor statuses. Storing those data in
flash or mmc card is not a viable solution.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
 arch/arm/configs/lp8x4x_defconfig       |   1 +
 arch/arm/mach-pxa/include/mach/lp8x4x.h |   2 +
 arch/arm/mach-pxa/lp8x4x.c              |  26 ++++
 drivers/mtd/devices/Kconfig             |  13 ++
 drivers/mtd/devices/Makefile            |   1 +
 drivers/mtd/devices/lp8x4x_sram.c       | 229 ++++++++++++++++++++++++++++++++
 6 files changed, 272 insertions(+)
 create mode 100644 drivers/mtd/devices/lp8x4x_sram.c

diff --git a/arch/arm/configs/lp8x4x_defconfig b/arch/arm/configs/lp8x4x_defconfig
index 27831e4..03c85bc 100644
--- a/arch/arm/configs/lp8x4x_defconfig
+++ b/arch/arm/configs/lp8x4x_defconfig
@@ -874,6 +874,7 @@ CONFIG_MTD_PXA2XX=y
 # Disk-On-Chip Device Drivers
 #
 # CONFIG_MTD_DOCG3 is not set
+CONFIG_MTD_LP8X4X_SRAM=y
 # CONFIG_MTD_NAND is not set
 # CONFIG_MTD_ONENAND is not set
 
diff --git a/arch/arm/mach-pxa/include/mach/lp8x4x.h b/arch/arm/mach-pxa/include/mach/lp8x4x.h
index d8a1376..a49df22 100644
--- a/arch/arm/mach-pxa/include/mach/lp8x4x.h
+++ b/arch/arm/mach-pxa/include/mach/lp8x4x.h
@@ -49,6 +49,8 @@
 #define LP8X4X_ENFALLINT	LP8X4X_P2V(0x17009018)
 #define LP8X4X_CLRFALLINT	LP8X4X_P2V(0x1700901a)
 #define LP8X4X_RWRTC		LP8X4X_P2V(0x1700901c)
+#define LP8X4X_SRAMBANK		0x1700901e
+#define LP8X4X_SRAM		0x1700a000
 
 /* board specific IRQs */
 
diff --git a/arch/arm/mach-pxa/lp8x4x.c b/arch/arm/mach-pxa/lp8x4x.c
index a31b556..47a8776 100644
--- a/arch/arm/mach-pxa/lp8x4x.c
+++ b/arch/arm/mach-pxa/lp8x4x.c
@@ -234,6 +234,17 @@ static struct resource lp8x4x_flash_resources[] = {
 		.end	= PXA_CS1_PHYS + SZ_32M - 1,
 		.flags	= IORESOURCE_MEM,
 	},
+	[2] = {
+		.start  = LP8X4X_SRAMBANK,
+		.end    = LP8X4X_SRAMBANK + 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	[3] = {
+		.start  = LP8X4X_SRAM,
+		.end    = LP8X4X_SRAM + SZ_4K - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+
 };
 
 static struct mtd_partition lp8x4x_flash0_partitions[] = {
@@ -267,6 +278,10 @@ static struct flash_platform_data lp8x4x_flash_data[] = {
 		.parts		= NULL,
 		.nr_parts	= 0,
 		.width		= 2,
+	}, {
+		.parts          = NULL,
+		.nr_parts       = 0,
+		.width          = 1,
 	}
 };
 
@@ -289,6 +304,16 @@ static struct platform_device lp8x4x_flash_device[] = {
 		.resource = &lp8x4x_flash_resources[1],
 		.num_resources = 1,
 	},
+	{
+		.name           = "lp8x4x-sram",
+		.id             = 0,
+		.dev = {
+			.platform_data = &lp8x4x_flash_data[2],
+		},
+		.resource = &lp8x4x_flash_resources[2],
+		.num_resources = 2,
+	},
+
 };
 
 static struct pxafb_mode_info lp8x4x_vga_60_mode = {
@@ -396,6 +421,7 @@ static struct platform_device lp8x4x_ds1302_device[] = {
 static struct platform_device *lp8x4x_devices[] __initdata = {
 	&lp8x4x_flash_device[0],
 	&lp8x4x_flash_device[1],
+	&lp8x4x_flash_device[2],
 	&lp8x4x_dm9000_device[0],
 	&lp8x4x_dm9000_device[1],
 	&lp8x4x_ds1302_device[0],
diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig
index 0128138..7da0c21 100644
--- a/drivers/mtd/devices/Kconfig
+++ b/drivers/mtd/devices/Kconfig
@@ -217,4 +217,17 @@ config BCH_CONST_T
 	default 4
 endif
 
+config MTD_LP8X4X_SRAM
+       tristate "SRAM on ICPDAS LP-8X4X"
+       ---help---
+	 This provides an MTD device driver for 512kB of battery backed up SRAM
+	 on ICPDAS LP-8X4X programmable automation controllers.
+
+	 SRAM chip is connected via FPGA and is not accessible without a driver,
+	 unlike flash memory which is wired to CPU MMU.
+
+	 Say N, unless you plan to run this kernel on LP-8X4X.
+
+	 If you say M, the module will be called lp8x4x_sram.
+
 endmenu
diff --git a/drivers/mtd/devices/Makefile b/drivers/mtd/devices/Makefile
index d83bd73..8c5d9b0 100644
--- a/drivers/mtd/devices/Makefile
+++ b/drivers/mtd/devices/Makefile
@@ -16,6 +16,7 @@ obj-$(CONFIG_MTD_NAND_OMAP_BCH)	+= elm.o
 obj-$(CONFIG_MTD_SPEAR_SMI)	+= spear_smi.o
 obj-$(CONFIG_MTD_SST25L)	+= sst25l.o
 obj-$(CONFIG_MTD_BCM47XXSFLASH)	+= bcm47xxsflash.o
+obj-$(CONFIG_MTD_LP8X4X_SRAM)	+= lp8x4x_sram.o
 
 
 CFLAGS_docg3.o			+= -I$(src)
diff --git a/drivers/mtd/devices/lp8x4x_sram.c b/drivers/mtd/devices/lp8x4x_sram.c
new file mode 100644
index 0000000..8fe625d
--- /dev/null
+++ b/drivers/mtd/devices/lp8x4x_sram.c
@@ -0,0 +1,229 @@
+/*
+ *  linux/drivers/mtd/devices/lp8x4x_sram.c
+ *
+ *  MTD Driver for SRAM on ICPDAS LP-8x4x
+ *  Copyright (C) 2013 Sergei Ianovich <ynvich@gmail.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation or any later version.
+ */
+
+#include <linux/string_helpers.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/map.h>
+#include <linux/mtd/partitions.h>
+
+#include <linux/io.h>
+#include <mach/hardware.h>
+
+#include <asm/mach/flash.h>
+
+struct lp8x4x_sram_info {
+	void __iomem	*bank;
+	void __iomem	*virt;
+	struct mutex	lock;
+	unsigned	active_bank;
+	struct mtd_info	mtd;
+};
+
+static int
+lp8x4x_sram_erase(struct mtd_info *mtd, struct erase_info *instr)
+{
+	struct lp8x4x_sram_info *info = mtd->priv;
+	unsigned bank = instr->addr >> 11;
+	unsigned offset = (instr->addr & 0x7ff) << 1;
+	loff_t i;
+
+	mutex_lock(&info->lock);
+	if (unlikely(bank != info->active_bank)) {
+		info->active_bank = bank;
+		iowrite8(bank, info->bank);
+	}
+	for (i = 0; i < instr->len; i++) {
+		iowrite8(0xff, info->virt + offset);
+		offset += 2;
+		if (unlikely(offset == 0)) {
+			info->active_bank++;
+			iowrite8(info->active_bank, info->bank);
+		}
+	}
+	mutex_unlock(&info->lock);
+	instr->state = MTD_ERASE_DONE;
+	mtd_erase_callback(instr);
+
+	return 0;
+}
+
+static int
+lp8x4x_sram_write(struct mtd_info *mtd, loff_t to, size_t len,
+		size_t *retlen, const u_char *b)
+{
+	struct lp8x4x_sram_info *info = mtd->priv;
+	unsigned bank = to >> 11;
+	unsigned offset = (to & 0x7ff) << 1;
+	loff_t i;
+
+	mutex_lock(&info->lock);
+	if (unlikely(bank != info->active_bank)) {
+		info->active_bank = bank;
+		iowrite8(bank, info->bank);
+	}
+	for (i = 0; i < len; i++) {
+		iowrite8(b[i], info->virt + offset);
+		offset += 2;
+		if (unlikely(offset == 0)) {
+			info->active_bank++;
+			iowrite8(info->active_bank, info->bank);
+		}
+	}
+	mutex_unlock(&info->lock);
+	*retlen = len;
+	return 0;
+}
+
+static int
+lp8x4x_sram_read(struct mtd_info *mtd, loff_t from, size_t len,
+		size_t *retlen, u_char *b)
+{
+	struct lp8x4x_sram_info *info = mtd->priv;
+	unsigned bank = from >> 11;
+	unsigned offset = (from & 0x7ff) << 1;
+	loff_t i;
+
+	mutex_lock(&info->lock);
+	if (unlikely(bank != info->active_bank)) {
+		info->active_bank = bank;
+		iowrite8(bank, info->bank);
+	}
+	for (i = 0; i < len; i++) {
+		b[i] = ioread8(info->virt + offset);
+		offset += 2;
+		if (unlikely(offset == 0)) {
+			info->active_bank++;
+			iowrite8(info->active_bank, info->bank);
+		}
+	}
+	mutex_unlock(&info->lock);
+	*retlen = len;
+	return 0;
+}
+
+static void
+lp8x4x_sram_sync(struct mtd_info *mtd)
+{
+}
+
+static const char const *probes[] = { "RedBoot", "cmdlinepart", NULL };
+
+static int
+lp8x4x_sram_probe(struct platform_device *pdev)
+{
+	struct flash_platform_data *flash = pdev->dev.platform_data;
+	struct lp8x4x_sram_info *info;
+	struct resource *res;
+	char sz_str[16];
+	int err = 0;
+
+	info = kzalloc(sizeof(*info), GFP_KERNEL);
+	if (!info)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		err = -ENODEV;
+		goto err1;
+	}
+
+	info->bank = ioremap(res->start, resource_size(res));
+	if (!info->bank) {
+		dev_err(&pdev->dev, "Failed to ioremap %p\n",
+		       info->bank);
+		err = -EFAULT;
+		goto err1;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	if (!res) {
+		err = -ENODEV;
+		goto err2;
+	}
+
+	info->virt = ioremap(res->start, resource_size(res));
+	if (!info->virt) {
+		dev_err(&pdev->dev, "Failed to ioremap %p\n",
+		       info->virt);
+		err = -EFAULT;
+		goto err2;
+	}
+
+	info->mtd.priv = info;
+	info->mtd.name = "SRAM";
+	info->mtd.type = MTD_RAM;
+	info->mtd.flags = MTD_CAP_RAM;
+	info->mtd.size = resource_size(res) << 7;
+	info->mtd.erasesize = 512;
+	info->mtd.writesize = 4;
+	info->mtd._erase = lp8x4x_sram_erase;
+	info->mtd._write = lp8x4x_sram_write;
+	info->mtd._read = lp8x4x_sram_read;
+	info->mtd._sync = lp8x4x_sram_sync;
+	info->mtd.owner = THIS_MODULE;
+
+	err = mtd_device_parse_register(&info->mtd, probes, NULL, flash->parts,
+			flash->nr_parts);
+	if (err < 0) {
+		dev_err(&pdev->dev, "Failed to register device\n");
+		goto err3;
+	}
+
+	mutex_init(&info->lock);
+	iowrite8(info->active_bank, info->bank);
+	platform_set_drvdata(pdev, info);
+	string_get_size(info->mtd.size, STRING_UNITS_2, sz_str,
+			sizeof(sz_str));
+	dev_info(&pdev->dev, "using %s SRAM on LP-8X4X as %s\n", sz_str,
+			dev_name(&info->mtd.dev));
+	return 0;
+err3:
+	iounmap(info->virt);
+err2:
+	iounmap(info->bank);
+err1:
+	kfree(info);
+	return err;
+}
+
+static int
+lp8x4x_sram_remove(struct platform_device *dev)
+{
+	struct lp8x4x_sram_info *info = platform_get_drvdata(dev);
+
+	platform_set_drvdata(dev, NULL);
+	mtd_device_unregister(&info->mtd);
+	iounmap(info->virt);
+	iounmap(info->bank);
+	kfree(info);
+	return 0;
+}
+
+static struct platform_driver lp8x4x_sram_driver = {
+	.driver = {
+		.name		= "lp8x4x-sram",
+		.owner		= THIS_MODULE,
+	},
+	.probe		= lp8x4x_sram_probe,
+	.remove		= lp8x4x_sram_remove,
+};
+
+module_platform_driver(lp8x4x_sram_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Sergei Ianovich <ynvich@gmail.com>");
+MODULE_DESCRIPTION("MTD driver for SRAM on ICPDAS LP-8x4x");
-- 
1.8.4.2


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

* [PATCH 04/11] mtd: support BB SRAM on ICP DAS LP-8x4x
@ 2013-12-01  6:26   ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-01  6:26 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Eric Miao, Kees Cook, Artem Bityutskiy, Robert Jarzmik,
	Randy Dunlap, Haojian Zhuang, Sergei Ianovich, Philip Avinash,
	open list:MEMORY TECHNOLOGY...,
	Russell King, David Woodhouse

This provides an MTD device driver for 512kB of battery backed up SRAM
on ICPDAS LP-8X4X programmable automation controllers.

SRAM chip is connected via FPGA and is not accessible without a driver,
unlike flash memory which is wired to CPU MMU.

This SRAM becomes an excellent persisent storage of volatile process
data like counter values and sensor statuses. Storing those data in
flash or mmc card is not a viable solution.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
 arch/arm/configs/lp8x4x_defconfig       |   1 +
 arch/arm/mach-pxa/include/mach/lp8x4x.h |   2 +
 arch/arm/mach-pxa/lp8x4x.c              |  26 ++++
 drivers/mtd/devices/Kconfig             |  13 ++
 drivers/mtd/devices/Makefile            |   1 +
 drivers/mtd/devices/lp8x4x_sram.c       | 229 ++++++++++++++++++++++++++++++++
 6 files changed, 272 insertions(+)
 create mode 100644 drivers/mtd/devices/lp8x4x_sram.c

diff --git a/arch/arm/configs/lp8x4x_defconfig b/arch/arm/configs/lp8x4x_defconfig
index 27831e4..03c85bc 100644
--- a/arch/arm/configs/lp8x4x_defconfig
+++ b/arch/arm/configs/lp8x4x_defconfig
@@ -874,6 +874,7 @@ CONFIG_MTD_PXA2XX=y
 # Disk-On-Chip Device Drivers
 #
 # CONFIG_MTD_DOCG3 is not set
+CONFIG_MTD_LP8X4X_SRAM=y
 # CONFIG_MTD_NAND is not set
 # CONFIG_MTD_ONENAND is not set
 
diff --git a/arch/arm/mach-pxa/include/mach/lp8x4x.h b/arch/arm/mach-pxa/include/mach/lp8x4x.h
index d8a1376..a49df22 100644
--- a/arch/arm/mach-pxa/include/mach/lp8x4x.h
+++ b/arch/arm/mach-pxa/include/mach/lp8x4x.h
@@ -49,6 +49,8 @@
 #define LP8X4X_ENFALLINT	LP8X4X_P2V(0x17009018)
 #define LP8X4X_CLRFALLINT	LP8X4X_P2V(0x1700901a)
 #define LP8X4X_RWRTC		LP8X4X_P2V(0x1700901c)
+#define LP8X4X_SRAMBANK		0x1700901e
+#define LP8X4X_SRAM		0x1700a000
 
 /* board specific IRQs */
 
diff --git a/arch/arm/mach-pxa/lp8x4x.c b/arch/arm/mach-pxa/lp8x4x.c
index a31b556..47a8776 100644
--- a/arch/arm/mach-pxa/lp8x4x.c
+++ b/arch/arm/mach-pxa/lp8x4x.c
@@ -234,6 +234,17 @@ static struct resource lp8x4x_flash_resources[] = {
 		.end	= PXA_CS1_PHYS + SZ_32M - 1,
 		.flags	= IORESOURCE_MEM,
 	},
+	[2] = {
+		.start  = LP8X4X_SRAMBANK,
+		.end    = LP8X4X_SRAMBANK + 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	[3] = {
+		.start  = LP8X4X_SRAM,
+		.end    = LP8X4X_SRAM + SZ_4K - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+
 };
 
 static struct mtd_partition lp8x4x_flash0_partitions[] = {
@@ -267,6 +278,10 @@ static struct flash_platform_data lp8x4x_flash_data[] = {
 		.parts		= NULL,
 		.nr_parts	= 0,
 		.width		= 2,
+	}, {
+		.parts          = NULL,
+		.nr_parts       = 0,
+		.width          = 1,
 	}
 };
 
@@ -289,6 +304,16 @@ static struct platform_device lp8x4x_flash_device[] = {
 		.resource = &lp8x4x_flash_resources[1],
 		.num_resources = 1,
 	},
+	{
+		.name           = "lp8x4x-sram",
+		.id             = 0,
+		.dev = {
+			.platform_data = &lp8x4x_flash_data[2],
+		},
+		.resource = &lp8x4x_flash_resources[2],
+		.num_resources = 2,
+	},
+
 };
 
 static struct pxafb_mode_info lp8x4x_vga_60_mode = {
@@ -396,6 +421,7 @@ static struct platform_device lp8x4x_ds1302_device[] = {
 static struct platform_device *lp8x4x_devices[] __initdata = {
 	&lp8x4x_flash_device[0],
 	&lp8x4x_flash_device[1],
+	&lp8x4x_flash_device[2],
 	&lp8x4x_dm9000_device[0],
 	&lp8x4x_dm9000_device[1],
 	&lp8x4x_ds1302_device[0],
diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig
index 0128138..7da0c21 100644
--- a/drivers/mtd/devices/Kconfig
+++ b/drivers/mtd/devices/Kconfig
@@ -217,4 +217,17 @@ config BCH_CONST_T
 	default 4
 endif
 
+config MTD_LP8X4X_SRAM
+       tristate "SRAM on ICPDAS LP-8X4X"
+       ---help---
+	 This provides an MTD device driver for 512kB of battery backed up SRAM
+	 on ICPDAS LP-8X4X programmable automation controllers.
+
+	 SRAM chip is connected via FPGA and is not accessible without a driver,
+	 unlike flash memory which is wired to CPU MMU.
+
+	 Say N, unless you plan to run this kernel on LP-8X4X.
+
+	 If you say M, the module will be called lp8x4x_sram.
+
 endmenu
diff --git a/drivers/mtd/devices/Makefile b/drivers/mtd/devices/Makefile
index d83bd73..8c5d9b0 100644
--- a/drivers/mtd/devices/Makefile
+++ b/drivers/mtd/devices/Makefile
@@ -16,6 +16,7 @@ obj-$(CONFIG_MTD_NAND_OMAP_BCH)	+= elm.o
 obj-$(CONFIG_MTD_SPEAR_SMI)	+= spear_smi.o
 obj-$(CONFIG_MTD_SST25L)	+= sst25l.o
 obj-$(CONFIG_MTD_BCM47XXSFLASH)	+= bcm47xxsflash.o
+obj-$(CONFIG_MTD_LP8X4X_SRAM)	+= lp8x4x_sram.o
 
 
 CFLAGS_docg3.o			+= -I$(src)
diff --git a/drivers/mtd/devices/lp8x4x_sram.c b/drivers/mtd/devices/lp8x4x_sram.c
new file mode 100644
index 0000000..8fe625d
--- /dev/null
+++ b/drivers/mtd/devices/lp8x4x_sram.c
@@ -0,0 +1,229 @@
+/*
+ *  linux/drivers/mtd/devices/lp8x4x_sram.c
+ *
+ *  MTD Driver for SRAM on ICPDAS LP-8x4x
+ *  Copyright (C) 2013 Sergei Ianovich <ynvich@gmail.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation or any later version.
+ */
+
+#include <linux/string_helpers.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/map.h>
+#include <linux/mtd/partitions.h>
+
+#include <linux/io.h>
+#include <mach/hardware.h>
+
+#include <asm/mach/flash.h>
+
+struct lp8x4x_sram_info {
+	void __iomem	*bank;
+	void __iomem	*virt;
+	struct mutex	lock;
+	unsigned	active_bank;
+	struct mtd_info	mtd;
+};
+
+static int
+lp8x4x_sram_erase(struct mtd_info *mtd, struct erase_info *instr)
+{
+	struct lp8x4x_sram_info *info = mtd->priv;
+	unsigned bank = instr->addr >> 11;
+	unsigned offset = (instr->addr & 0x7ff) << 1;
+	loff_t i;
+
+	mutex_lock(&info->lock);
+	if (unlikely(bank != info->active_bank)) {
+		info->active_bank = bank;
+		iowrite8(bank, info->bank);
+	}
+	for (i = 0; i < instr->len; i++) {
+		iowrite8(0xff, info->virt + offset);
+		offset += 2;
+		if (unlikely(offset == 0)) {
+			info->active_bank++;
+			iowrite8(info->active_bank, info->bank);
+		}
+	}
+	mutex_unlock(&info->lock);
+	instr->state = MTD_ERASE_DONE;
+	mtd_erase_callback(instr);
+
+	return 0;
+}
+
+static int
+lp8x4x_sram_write(struct mtd_info *mtd, loff_t to, size_t len,
+		size_t *retlen, const u_char *b)
+{
+	struct lp8x4x_sram_info *info = mtd->priv;
+	unsigned bank = to >> 11;
+	unsigned offset = (to & 0x7ff) << 1;
+	loff_t i;
+
+	mutex_lock(&info->lock);
+	if (unlikely(bank != info->active_bank)) {
+		info->active_bank = bank;
+		iowrite8(bank, info->bank);
+	}
+	for (i = 0; i < len; i++) {
+		iowrite8(b[i], info->virt + offset);
+		offset += 2;
+		if (unlikely(offset == 0)) {
+			info->active_bank++;
+			iowrite8(info->active_bank, info->bank);
+		}
+	}
+	mutex_unlock(&info->lock);
+	*retlen = len;
+	return 0;
+}
+
+static int
+lp8x4x_sram_read(struct mtd_info *mtd, loff_t from, size_t len,
+		size_t *retlen, u_char *b)
+{
+	struct lp8x4x_sram_info *info = mtd->priv;
+	unsigned bank = from >> 11;
+	unsigned offset = (from & 0x7ff) << 1;
+	loff_t i;
+
+	mutex_lock(&info->lock);
+	if (unlikely(bank != info->active_bank)) {
+		info->active_bank = bank;
+		iowrite8(bank, info->bank);
+	}
+	for (i = 0; i < len; i++) {
+		b[i] = ioread8(info->virt + offset);
+		offset += 2;
+		if (unlikely(offset == 0)) {
+			info->active_bank++;
+			iowrite8(info->active_bank, info->bank);
+		}
+	}
+	mutex_unlock(&info->lock);
+	*retlen = len;
+	return 0;
+}
+
+static void
+lp8x4x_sram_sync(struct mtd_info *mtd)
+{
+}
+
+static const char const *probes[] = { "RedBoot", "cmdlinepart", NULL };
+
+static int
+lp8x4x_sram_probe(struct platform_device *pdev)
+{
+	struct flash_platform_data *flash = pdev->dev.platform_data;
+	struct lp8x4x_sram_info *info;
+	struct resource *res;
+	char sz_str[16];
+	int err = 0;
+
+	info = kzalloc(sizeof(*info), GFP_KERNEL);
+	if (!info)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		err = -ENODEV;
+		goto err1;
+	}
+
+	info->bank = ioremap(res->start, resource_size(res));
+	if (!info->bank) {
+		dev_err(&pdev->dev, "Failed to ioremap %p\n",
+		       info->bank);
+		err = -EFAULT;
+		goto err1;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	if (!res) {
+		err = -ENODEV;
+		goto err2;
+	}
+
+	info->virt = ioremap(res->start, resource_size(res));
+	if (!info->virt) {
+		dev_err(&pdev->dev, "Failed to ioremap %p\n",
+		       info->virt);
+		err = -EFAULT;
+		goto err2;
+	}
+
+	info->mtd.priv = info;
+	info->mtd.name = "SRAM";
+	info->mtd.type = MTD_RAM;
+	info->mtd.flags = MTD_CAP_RAM;
+	info->mtd.size = resource_size(res) << 7;
+	info->mtd.erasesize = 512;
+	info->mtd.writesize = 4;
+	info->mtd._erase = lp8x4x_sram_erase;
+	info->mtd._write = lp8x4x_sram_write;
+	info->mtd._read = lp8x4x_sram_read;
+	info->mtd._sync = lp8x4x_sram_sync;
+	info->mtd.owner = THIS_MODULE;
+
+	err = mtd_device_parse_register(&info->mtd, probes, NULL, flash->parts,
+			flash->nr_parts);
+	if (err < 0) {
+		dev_err(&pdev->dev, "Failed to register device\n");
+		goto err3;
+	}
+
+	mutex_init(&info->lock);
+	iowrite8(info->active_bank, info->bank);
+	platform_set_drvdata(pdev, info);
+	string_get_size(info->mtd.size, STRING_UNITS_2, sz_str,
+			sizeof(sz_str));
+	dev_info(&pdev->dev, "using %s SRAM on LP-8X4X as %s\n", sz_str,
+			dev_name(&info->mtd.dev));
+	return 0;
+err3:
+	iounmap(info->virt);
+err2:
+	iounmap(info->bank);
+err1:
+	kfree(info);
+	return err;
+}
+
+static int
+lp8x4x_sram_remove(struct platform_device *dev)
+{
+	struct lp8x4x_sram_info *info = platform_get_drvdata(dev);
+
+	platform_set_drvdata(dev, NULL);
+	mtd_device_unregister(&info->mtd);
+	iounmap(info->virt);
+	iounmap(info->bank);
+	kfree(info);
+	return 0;
+}
+
+static struct platform_driver lp8x4x_sram_driver = {
+	.driver = {
+		.name		= "lp8x4x-sram",
+		.owner		= THIS_MODULE,
+	},
+	.probe		= lp8x4x_sram_probe,
+	.remove		= lp8x4x_sram_remove,
+};
+
+module_platform_driver(lp8x4x_sram_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Sergei Ianovich <ynvich@gmail.com>");
+MODULE_DESCRIPTION("MTD driver for SRAM on ICPDAS LP-8x4x");
-- 
1.8.4.2

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

* [PATCH 04/11] mtd: support BB SRAM on ICP DAS LP-8x4x
@ 2013-12-01  6:26   ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-01  6:26 UTC (permalink / raw)
  To: linux-arm-kernel

This provides an MTD device driver for 512kB of battery backed up SRAM
on ICPDAS LP-8X4X programmable automation controllers.

SRAM chip is connected via FPGA and is not accessible without a driver,
unlike flash memory which is wired to CPU MMU.

This SRAM becomes an excellent persisent storage of volatile process
data like counter values and sensor statuses. Storing those data in
flash or mmc card is not a viable solution.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
 arch/arm/configs/lp8x4x_defconfig       |   1 +
 arch/arm/mach-pxa/include/mach/lp8x4x.h |   2 +
 arch/arm/mach-pxa/lp8x4x.c              |  26 ++++
 drivers/mtd/devices/Kconfig             |  13 ++
 drivers/mtd/devices/Makefile            |   1 +
 drivers/mtd/devices/lp8x4x_sram.c       | 229 ++++++++++++++++++++++++++++++++
 6 files changed, 272 insertions(+)
 create mode 100644 drivers/mtd/devices/lp8x4x_sram.c

diff --git a/arch/arm/configs/lp8x4x_defconfig b/arch/arm/configs/lp8x4x_defconfig
index 27831e4..03c85bc 100644
--- a/arch/arm/configs/lp8x4x_defconfig
+++ b/arch/arm/configs/lp8x4x_defconfig
@@ -874,6 +874,7 @@ CONFIG_MTD_PXA2XX=y
 # Disk-On-Chip Device Drivers
 #
 # CONFIG_MTD_DOCG3 is not set
+CONFIG_MTD_LP8X4X_SRAM=y
 # CONFIG_MTD_NAND is not set
 # CONFIG_MTD_ONENAND is not set
 
diff --git a/arch/arm/mach-pxa/include/mach/lp8x4x.h b/arch/arm/mach-pxa/include/mach/lp8x4x.h
index d8a1376..a49df22 100644
--- a/arch/arm/mach-pxa/include/mach/lp8x4x.h
+++ b/arch/arm/mach-pxa/include/mach/lp8x4x.h
@@ -49,6 +49,8 @@
 #define LP8X4X_ENFALLINT	LP8X4X_P2V(0x17009018)
 #define LP8X4X_CLRFALLINT	LP8X4X_P2V(0x1700901a)
 #define LP8X4X_RWRTC		LP8X4X_P2V(0x1700901c)
+#define LP8X4X_SRAMBANK		0x1700901e
+#define LP8X4X_SRAM		0x1700a000
 
 /* board specific IRQs */
 
diff --git a/arch/arm/mach-pxa/lp8x4x.c b/arch/arm/mach-pxa/lp8x4x.c
index a31b556..47a8776 100644
--- a/arch/arm/mach-pxa/lp8x4x.c
+++ b/arch/arm/mach-pxa/lp8x4x.c
@@ -234,6 +234,17 @@ static struct resource lp8x4x_flash_resources[] = {
 		.end	= PXA_CS1_PHYS + SZ_32M - 1,
 		.flags	= IORESOURCE_MEM,
 	},
+	[2] = {
+		.start  = LP8X4X_SRAMBANK,
+		.end    = LP8X4X_SRAMBANK + 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	[3] = {
+		.start  = LP8X4X_SRAM,
+		.end    = LP8X4X_SRAM + SZ_4K - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+
 };
 
 static struct mtd_partition lp8x4x_flash0_partitions[] = {
@@ -267,6 +278,10 @@ static struct flash_platform_data lp8x4x_flash_data[] = {
 		.parts		= NULL,
 		.nr_parts	= 0,
 		.width		= 2,
+	}, {
+		.parts          = NULL,
+		.nr_parts       = 0,
+		.width          = 1,
 	}
 };
 
@@ -289,6 +304,16 @@ static struct platform_device lp8x4x_flash_device[] = {
 		.resource = &lp8x4x_flash_resources[1],
 		.num_resources = 1,
 	},
+	{
+		.name           = "lp8x4x-sram",
+		.id             = 0,
+		.dev = {
+			.platform_data = &lp8x4x_flash_data[2],
+		},
+		.resource = &lp8x4x_flash_resources[2],
+		.num_resources = 2,
+	},
+
 };
 
 static struct pxafb_mode_info lp8x4x_vga_60_mode = {
@@ -396,6 +421,7 @@ static struct platform_device lp8x4x_ds1302_device[] = {
 static struct platform_device *lp8x4x_devices[] __initdata = {
 	&lp8x4x_flash_device[0],
 	&lp8x4x_flash_device[1],
+	&lp8x4x_flash_device[2],
 	&lp8x4x_dm9000_device[0],
 	&lp8x4x_dm9000_device[1],
 	&lp8x4x_ds1302_device[0],
diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig
index 0128138..7da0c21 100644
--- a/drivers/mtd/devices/Kconfig
+++ b/drivers/mtd/devices/Kconfig
@@ -217,4 +217,17 @@ config BCH_CONST_T
 	default 4
 endif
 
+config MTD_LP8X4X_SRAM
+       tristate "SRAM on ICPDAS LP-8X4X"
+       ---help---
+	 This provides an MTD device driver for 512kB of battery backed up SRAM
+	 on ICPDAS LP-8X4X programmable automation controllers.
+
+	 SRAM chip is connected via FPGA and is not accessible without a driver,
+	 unlike flash memory which is wired to CPU MMU.
+
+	 Say N, unless you plan to run this kernel on LP-8X4X.
+
+	 If you say M, the module will be called lp8x4x_sram.
+
 endmenu
diff --git a/drivers/mtd/devices/Makefile b/drivers/mtd/devices/Makefile
index d83bd73..8c5d9b0 100644
--- a/drivers/mtd/devices/Makefile
+++ b/drivers/mtd/devices/Makefile
@@ -16,6 +16,7 @@ obj-$(CONFIG_MTD_NAND_OMAP_BCH)	+= elm.o
 obj-$(CONFIG_MTD_SPEAR_SMI)	+= spear_smi.o
 obj-$(CONFIG_MTD_SST25L)	+= sst25l.o
 obj-$(CONFIG_MTD_BCM47XXSFLASH)	+= bcm47xxsflash.o
+obj-$(CONFIG_MTD_LP8X4X_SRAM)	+= lp8x4x_sram.o
 
 
 CFLAGS_docg3.o			+= -I$(src)
diff --git a/drivers/mtd/devices/lp8x4x_sram.c b/drivers/mtd/devices/lp8x4x_sram.c
new file mode 100644
index 0000000..8fe625d
--- /dev/null
+++ b/drivers/mtd/devices/lp8x4x_sram.c
@@ -0,0 +1,229 @@
+/*
+ *  linux/drivers/mtd/devices/lp8x4x_sram.c
+ *
+ *  MTD Driver for SRAM on ICPDAS LP-8x4x
+ *  Copyright (C) 2013 Sergei Ianovich <ynvich@gmail.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation or any later version.
+ */
+
+#include <linux/string_helpers.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/map.h>
+#include <linux/mtd/partitions.h>
+
+#include <linux/io.h>
+#include <mach/hardware.h>
+
+#include <asm/mach/flash.h>
+
+struct lp8x4x_sram_info {
+	void __iomem	*bank;
+	void __iomem	*virt;
+	struct mutex	lock;
+	unsigned	active_bank;
+	struct mtd_info	mtd;
+};
+
+static int
+lp8x4x_sram_erase(struct mtd_info *mtd, struct erase_info *instr)
+{
+	struct lp8x4x_sram_info *info = mtd->priv;
+	unsigned bank = instr->addr >> 11;
+	unsigned offset = (instr->addr & 0x7ff) << 1;
+	loff_t i;
+
+	mutex_lock(&info->lock);
+	if (unlikely(bank != info->active_bank)) {
+		info->active_bank = bank;
+		iowrite8(bank, info->bank);
+	}
+	for (i = 0; i < instr->len; i++) {
+		iowrite8(0xff, info->virt + offset);
+		offset += 2;
+		if (unlikely(offset == 0)) {
+			info->active_bank++;
+			iowrite8(info->active_bank, info->bank);
+		}
+	}
+	mutex_unlock(&info->lock);
+	instr->state = MTD_ERASE_DONE;
+	mtd_erase_callback(instr);
+
+	return 0;
+}
+
+static int
+lp8x4x_sram_write(struct mtd_info *mtd, loff_t to, size_t len,
+		size_t *retlen, const u_char *b)
+{
+	struct lp8x4x_sram_info *info = mtd->priv;
+	unsigned bank = to >> 11;
+	unsigned offset = (to & 0x7ff) << 1;
+	loff_t i;
+
+	mutex_lock(&info->lock);
+	if (unlikely(bank != info->active_bank)) {
+		info->active_bank = bank;
+		iowrite8(bank, info->bank);
+	}
+	for (i = 0; i < len; i++) {
+		iowrite8(b[i], info->virt + offset);
+		offset += 2;
+		if (unlikely(offset == 0)) {
+			info->active_bank++;
+			iowrite8(info->active_bank, info->bank);
+		}
+	}
+	mutex_unlock(&info->lock);
+	*retlen = len;
+	return 0;
+}
+
+static int
+lp8x4x_sram_read(struct mtd_info *mtd, loff_t from, size_t len,
+		size_t *retlen, u_char *b)
+{
+	struct lp8x4x_sram_info *info = mtd->priv;
+	unsigned bank = from >> 11;
+	unsigned offset = (from & 0x7ff) << 1;
+	loff_t i;
+
+	mutex_lock(&info->lock);
+	if (unlikely(bank != info->active_bank)) {
+		info->active_bank = bank;
+		iowrite8(bank, info->bank);
+	}
+	for (i = 0; i < len; i++) {
+		b[i] = ioread8(info->virt + offset);
+		offset += 2;
+		if (unlikely(offset == 0)) {
+			info->active_bank++;
+			iowrite8(info->active_bank, info->bank);
+		}
+	}
+	mutex_unlock(&info->lock);
+	*retlen = len;
+	return 0;
+}
+
+static void
+lp8x4x_sram_sync(struct mtd_info *mtd)
+{
+}
+
+static const char const *probes[] = { "RedBoot", "cmdlinepart", NULL };
+
+static int
+lp8x4x_sram_probe(struct platform_device *pdev)
+{
+	struct flash_platform_data *flash = pdev->dev.platform_data;
+	struct lp8x4x_sram_info *info;
+	struct resource *res;
+	char sz_str[16];
+	int err = 0;
+
+	info = kzalloc(sizeof(*info), GFP_KERNEL);
+	if (!info)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		err = -ENODEV;
+		goto err1;
+	}
+
+	info->bank = ioremap(res->start, resource_size(res));
+	if (!info->bank) {
+		dev_err(&pdev->dev, "Failed to ioremap %p\n",
+		       info->bank);
+		err = -EFAULT;
+		goto err1;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	if (!res) {
+		err = -ENODEV;
+		goto err2;
+	}
+
+	info->virt = ioremap(res->start, resource_size(res));
+	if (!info->virt) {
+		dev_err(&pdev->dev, "Failed to ioremap %p\n",
+		       info->virt);
+		err = -EFAULT;
+		goto err2;
+	}
+
+	info->mtd.priv = info;
+	info->mtd.name = "SRAM";
+	info->mtd.type = MTD_RAM;
+	info->mtd.flags = MTD_CAP_RAM;
+	info->mtd.size = resource_size(res) << 7;
+	info->mtd.erasesize = 512;
+	info->mtd.writesize = 4;
+	info->mtd._erase = lp8x4x_sram_erase;
+	info->mtd._write = lp8x4x_sram_write;
+	info->mtd._read = lp8x4x_sram_read;
+	info->mtd._sync = lp8x4x_sram_sync;
+	info->mtd.owner = THIS_MODULE;
+
+	err = mtd_device_parse_register(&info->mtd, probes, NULL, flash->parts,
+			flash->nr_parts);
+	if (err < 0) {
+		dev_err(&pdev->dev, "Failed to register device\n");
+		goto err3;
+	}
+
+	mutex_init(&info->lock);
+	iowrite8(info->active_bank, info->bank);
+	platform_set_drvdata(pdev, info);
+	string_get_size(info->mtd.size, STRING_UNITS_2, sz_str,
+			sizeof(sz_str));
+	dev_info(&pdev->dev, "using %s SRAM on LP-8X4X as %s\n", sz_str,
+			dev_name(&info->mtd.dev));
+	return 0;
+err3:
+	iounmap(info->virt);
+err2:
+	iounmap(info->bank);
+err1:
+	kfree(info);
+	return err;
+}
+
+static int
+lp8x4x_sram_remove(struct platform_device *dev)
+{
+	struct lp8x4x_sram_info *info = platform_get_drvdata(dev);
+
+	platform_set_drvdata(dev, NULL);
+	mtd_device_unregister(&info->mtd);
+	iounmap(info->virt);
+	iounmap(info->bank);
+	kfree(info);
+	return 0;
+}
+
+static struct platform_driver lp8x4x_sram_driver = {
+	.driver = {
+		.name		= "lp8x4x-sram",
+		.owner		= THIS_MODULE,
+	},
+	.probe		= lp8x4x_sram_probe,
+	.remove		= lp8x4x_sram_remove,
+};
+
+module_platform_driver(lp8x4x_sram_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Sergei Ianovich <ynvich@gmail.com>");
+MODULE_DESCRIPTION("MTD driver for SRAM on ICPDAS LP-8x4x");
-- 
1.8.4.2

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

* [PATCH 05/11] serial: support for 16550 serial ports on LP-8x4x
  2013-12-01  6:26 ` Sergei Ianovich
  (?)
@ 2013-12-01  6:26   ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-01  6:26 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Russell King, Eric Miao, Haojian Zhuang,
	Greg Kroah-Hartman, Jiri Slaby, Heikki Krogerus, Arnd Bergmann,
	open list:SERIAL DRIVERS

The patch adds support for 3 additional LP-8x4x built-in serial
ports.

The device can also host up to 8 extension cards with 4 serial ports
on each card for a total of 35 ports. However, I don't have
the hardware to test extension cards, so they are not supported, yet.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
 arch/arm/configs/lp8x4x_defconfig       |   1 +
 arch/arm/mach-pxa/include/mach/lp8x4x.h |   6 ++
 drivers/tty/serial/8250/8250_lp8x4x.c   | 181 ++++++++++++++++++++++++++++++++
 drivers/tty/serial/8250/Kconfig         |  11 ++
 drivers/tty/serial/8250/Makefile        |   1 +
 5 files changed, 200 insertions(+)
 create mode 100644 drivers/tty/serial/8250/8250_lp8x4x.c

diff --git a/arch/arm/configs/lp8x4x_defconfig b/arch/arm/configs/lp8x4x_defconfig
index 03c85bc..d297a67 100644
--- a/arch/arm/configs/lp8x4x_defconfig
+++ b/arch/arm/configs/lp8x4x_defconfig
@@ -1141,6 +1141,7 @@ CONFIG_SERIAL_8250_NR_UARTS=36
 CONFIG_SERIAL_8250_RUNTIME_UARTS=36
 CONFIG_SERIAL_8250_EXTENDED=y
 CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_LP8X4X=m
 CONFIG_SERIAL_8250_SHARE_IRQ=y
 # CONFIG_SERIAL_8250_DETECT_IRQ is not set
 # CONFIG_SERIAL_8250_RSA is not set
diff --git a/arch/arm/mach-pxa/include/mach/lp8x4x.h b/arch/arm/mach-pxa/include/mach/lp8x4x.h
index a49df22..4d5474e 100644
--- a/arch/arm/mach-pxa/include/mach/lp8x4x.h
+++ b/arch/arm/mach-pxa/include/mach/lp8x4x.h
@@ -50,6 +50,12 @@
 #define LP8X4X_CLRFALLINT	LP8X4X_P2V(0x1700901a)
 #define LP8X4X_RWRTC		LP8X4X_P2V(0x1700901c)
 #define LP8X4X_SRAMBANK		0x1700901e
+#define LP8X4X_TTYS0_QUIRK	0x17009030
+#define LP8X4X_TTYS1_QUIRK	0x17009032
+#define LP8X4X_TTYS2_QUIRK	0x17009034
+#define LP8X4X_TTYS0_IOMEM	0x17009050
+#define LP8X4X_TTYS1_IOMEM	0x17009060
+#define LP8X4X_TTYS2_IOMEM	0x17009070
 #define LP8X4X_SRAM		0x1700a000
 
 /* board specific IRQs */
diff --git a/drivers/tty/serial/8250/8250_lp8x4x.c b/drivers/tty/serial/8250/8250_lp8x4x.c
new file mode 100644
index 0000000..27b01f0b
--- /dev/null
+++ b/drivers/tty/serial/8250/8250_lp8x4x.c
@@ -0,0 +1,181 @@
+/*  linux/drivers/tty/serial/8250/8250_lp8x4x.c
+ *
+ *  Support for 16550 serial ports on ICP DAS LP-8x4x
+ *
+ *  Copyright (C) 2013 Sergei Ianovich <ynvich@gmail.com>
+ *  Framework taken from linux/drivers/tty/serial/8250/8250_accent.c
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/delay.h>
+#include <linux/serial_8250.h>
+#include <mach/lp8x4x.h>
+#include <linux/io.h>
+
+#define QUIRK_PORT(_base, _irq)					\
+	{							\
+		.iobase		= _base,			\
+		.membase	= (void *) _base,		\
+		.mapbase	= _base,			\
+		.irq		= _irq,				\
+		.uartclk	= 14745600,			\
+		.regshift	= 1,				\
+		.iotype		= UPIO_MEM,			\
+		.flags		= UPF_IOREMAP,			\
+		.set_termios	= lp8x4x_set_termios,		\
+		.serial_in	= lp8x4x_serial_in,		\
+		.serial_out	= lp8x4x_serial_out,		\
+	}
+
+static void lp8x4x_set_termios(struct uart_port *port,
+		struct ktermios *termios, struct ktermios *old)
+{
+	unsigned int len;
+	unsigned int baud;
+
+	switch (termios->c_cflag & CSIZE) {
+	case CS5:
+		len = 7;
+		break;
+	case CS6:
+		len = 8;
+		break;
+	case CS7:
+		len = 9;
+		break;
+	default:
+	case CS8:
+		len = 10;
+		break;
+	}
+
+	if (termios->c_cflag & CSTOPB)
+		len++;
+	if (termios->c_cflag & PARENB)
+		len++;
+	if (!(termios->c_cflag & PARODD))
+		len++;
+#ifdef CMSPAR
+	if (termios->c_cflag & CMSPAR)
+		len++;
+#endif
+
+	len -= 9;
+	len &= 3;
+	len <<= 3;
+	/*
+	 * Ask the core to calculate the divisor for us.
+	 */
+	baud = uart_get_baud_rate(port, termios, old,
+				  port->uartclk / 16 / 0xffff,
+				  port->uartclk / 16);
+	switch (baud) {
+	case 2400:
+		len |= 1;
+	case 4800:
+		len |= 2;
+	case 19200:
+		len |= 4;
+	case 38400:
+		len |= 5;
+	case 57600:
+		len |= 6;
+	case 115200:
+		len |= 7;
+	case 9600:
+	default:
+		len |= 3;
+	};
+	iowrite8(len, port->private_data);
+
+	serial8250_do_set_termios(port, termios, old);
+}
+
+static unsigned int lp8x4x_serial_in(struct uart_port *p, int offset)
+{
+	unsigned int b;
+	udelay(30);
+	offset = offset << p->regshift;
+	b = readb(p->membase + offset);
+	return b;
+}
+
+static void lp8x4x_serial_out(struct uart_port *p, int offset, int value)
+{
+	offset = offset << p->regshift;
+	writeb(value, p->membase + offset);
+}
+
+static struct plat_serial8250_port lp8x4x_data[] = {
+	QUIRK_PORT(LP8X4X_TTYS0_IOMEM, LP8X4X_TTYS0_IRQ),
+	QUIRK_PORT(LP8X4X_TTYS1_IOMEM, LP8X4X_TTYS1_IRQ),
+	QUIRK_PORT(LP8X4X_TTYS2_IOMEM, LP8X4X_TTYS2_IRQ),
+	{ },
+};
+
+/* Total number of ports can be 35. The first 3 ports are on
+ * the device, the rest are on extension slots. Only the first 3
+ * require termios quirk */
+#define LP8X4X_QUIRK_PORTS	3
+
+static unsigned int extra_mem[LP8X4X_QUIRK_PORTS] = {
+	LP8X4X_TTYS0_QUIRK,
+	LP8X4X_TTYS1_QUIRK,
+	LP8X4X_TTYS2_QUIRK
+};
+
+static int request_and_remap(int i)
+{
+	if (!request_mem_region(extra_mem[i], 1, "serial"))
+		return -EBUSY;
+
+	lp8x4x_data[i].private_data = ioremap(extra_mem[i], 1);
+	if (lp8x4x_data[i].private_data)
+		return 0;
+
+	release_mem_region(extra_mem[i], 1);
+	return -ENODEV;
+}
+
+static void release_and_unmap(int i)
+{
+	iounmap((void *) lp8x4x_data[i].private_data);
+	release_mem_region(extra_mem[i], 1);
+}
+
+static struct platform_device lp8x4x_device = {
+	.name			= "serial8250",
+	.id			= PLAT8250_DEV_ACCENT,
+	.dev			= {
+		.platform_data	= lp8x4x_data,
+	},
+};
+
+static int __init lp8x4x_init(void)
+{
+	int i = 0;
+	int err = 0;
+
+	for (i = 0; i < LP8X4X_QUIRK_PORTS; i++) {
+		err = request_and_remap(i);
+		if (err == 0)
+			continue;
+
+		for (; i >= 0; i--)
+			release_and_unmap(i);
+		lp8x4x_device.dev.platform_data = NULL;
+		return err;
+	}
+	return platform_device_register(&lp8x4x_device);
+}
+
+module_init(lp8x4x_init);
+
+MODULE_AUTHOR("Sergei Ianovich");
+MODULE_DESCRIPTION("8250 serial port module for LP-8x4x");
+MODULE_LICENSE("GPL");
diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
index f3b306e..30b9af4 100644
--- a/drivers/tty/serial/8250/Kconfig
+++ b/drivers/tty/serial/8250/Kconfig
@@ -237,6 +237,17 @@ config SERIAL_8250_HUB6
 	  To compile this driver as a module, choose M here: the module
 	  will be called 8250_hub6.
 
+config SERIAL_8250_LP8X4X
+	tristate "Support 8250 ports on ICP DAS LP-8x4x"
+	depends on SERIAL_8250 != n && SERIAL_8250_MANY_PORTS && MACH_LP8X4X
+	help
+	  In addition on serial ports on PXA270 SoC, LP-8x4x has 1 dual
+	  RS232/RS485 port, 1 RS485 port and 1 RS232 port serial ports.
+
+	  Say N here, unless you plan to run this kernel on a LP-8x4x system.
+
+	  If you choose M, the module will be called 8250_lp8x4x.
+
 #
 # Misc. options/drivers.
 #
diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile
index 36d68d0..451c558 100644
--- a/drivers/tty/serial/8250/Makefile
+++ b/drivers/tty/serial/8250/Makefile
@@ -17,6 +17,7 @@ obj-$(CONFIG_SERIAL_8250_ACCENT)	+= 8250_accent.o
 obj-$(CONFIG_SERIAL_8250_BOCA)		+= 8250_boca.o
 obj-$(CONFIG_SERIAL_8250_EXAR_ST16C554)	+= 8250_exar_st16c554.o
 obj-$(CONFIG_SERIAL_8250_HUB6)		+= 8250_hub6.o
+obj-$(CONFIG_SERIAL_8250_LP8X4X)	+= 8250_lp8x4x.o
 obj-$(CONFIG_SERIAL_8250_FSL)		+= 8250_fsl.o
 obj-$(CONFIG_SERIAL_8250_DW)		+= 8250_dw.o
 obj-$(CONFIG_SERIAL_8250_EM)		+= 8250_em.o
-- 
1.8.4.2


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

* [PATCH 05/11] serial: support for 16550 serial ports on LP-8x4x
@ 2013-12-01  6:26   ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-01  6:26 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Russell King, Eric Miao, Haojian Zhuang,
	Greg Kroah-Hartman, Jiri Slaby, Heikki Krogerus, Arnd Bergmann,
	open list:SERIAL DRIVERS

The patch adds support for 3 additional LP-8x4x built-in serial
ports.

The device can also host up to 8 extension cards with 4 serial ports
on each card for a total of 35 ports. However, I don't have
the hardware to test extension cards, so they are not supported, yet.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
 arch/arm/configs/lp8x4x_defconfig       |   1 +
 arch/arm/mach-pxa/include/mach/lp8x4x.h |   6 ++
 drivers/tty/serial/8250/8250_lp8x4x.c   | 181 ++++++++++++++++++++++++++++++++
 drivers/tty/serial/8250/Kconfig         |  11 ++
 drivers/tty/serial/8250/Makefile        |   1 +
 5 files changed, 200 insertions(+)
 create mode 100644 drivers/tty/serial/8250/8250_lp8x4x.c

diff --git a/arch/arm/configs/lp8x4x_defconfig b/arch/arm/configs/lp8x4x_defconfig
index 03c85bc..d297a67 100644
--- a/arch/arm/configs/lp8x4x_defconfig
+++ b/arch/arm/configs/lp8x4x_defconfig
@@ -1141,6 +1141,7 @@ CONFIG_SERIAL_8250_NR_UARTS=36
 CONFIG_SERIAL_8250_RUNTIME_UARTS=36
 CONFIG_SERIAL_8250_EXTENDED=y
 CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_LP8X4X=m
 CONFIG_SERIAL_8250_SHARE_IRQ=y
 # CONFIG_SERIAL_8250_DETECT_IRQ is not set
 # CONFIG_SERIAL_8250_RSA is not set
diff --git a/arch/arm/mach-pxa/include/mach/lp8x4x.h b/arch/arm/mach-pxa/include/mach/lp8x4x.h
index a49df22..4d5474e 100644
--- a/arch/arm/mach-pxa/include/mach/lp8x4x.h
+++ b/arch/arm/mach-pxa/include/mach/lp8x4x.h
@@ -50,6 +50,12 @@
 #define LP8X4X_CLRFALLINT	LP8X4X_P2V(0x1700901a)
 #define LP8X4X_RWRTC		LP8X4X_P2V(0x1700901c)
 #define LP8X4X_SRAMBANK		0x1700901e
+#define LP8X4X_TTYS0_QUIRK	0x17009030
+#define LP8X4X_TTYS1_QUIRK	0x17009032
+#define LP8X4X_TTYS2_QUIRK	0x17009034
+#define LP8X4X_TTYS0_IOMEM	0x17009050
+#define LP8X4X_TTYS1_IOMEM	0x17009060
+#define LP8X4X_TTYS2_IOMEM	0x17009070
 #define LP8X4X_SRAM		0x1700a000
 
 /* board specific IRQs */
diff --git a/drivers/tty/serial/8250/8250_lp8x4x.c b/drivers/tty/serial/8250/8250_lp8x4x.c
new file mode 100644
index 0000000..27b01f0b
--- /dev/null
+++ b/drivers/tty/serial/8250/8250_lp8x4x.c
@@ -0,0 +1,181 @@
+/*  linux/drivers/tty/serial/8250/8250_lp8x4x.c
+ *
+ *  Support for 16550 serial ports on ICP DAS LP-8x4x
+ *
+ *  Copyright (C) 2013 Sergei Ianovich <ynvich@gmail.com>
+ *  Framework taken from linux/drivers/tty/serial/8250/8250_accent.c
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/delay.h>
+#include <linux/serial_8250.h>
+#include <mach/lp8x4x.h>
+#include <linux/io.h>
+
+#define QUIRK_PORT(_base, _irq)					\
+	{							\
+		.iobase		= _base,			\
+		.membase	= (void *) _base,		\
+		.mapbase	= _base,			\
+		.irq		= _irq,				\
+		.uartclk	= 14745600,			\
+		.regshift	= 1,				\
+		.iotype		= UPIO_MEM,			\
+		.flags		= UPF_IOREMAP,			\
+		.set_termios	= lp8x4x_set_termios,		\
+		.serial_in	= lp8x4x_serial_in,		\
+		.serial_out	= lp8x4x_serial_out,		\
+	}
+
+static void lp8x4x_set_termios(struct uart_port *port,
+		struct ktermios *termios, struct ktermios *old)
+{
+	unsigned int len;
+	unsigned int baud;
+
+	switch (termios->c_cflag & CSIZE) {
+	case CS5:
+		len = 7;
+		break;
+	case CS6:
+		len = 8;
+		break;
+	case CS7:
+		len = 9;
+		break;
+	default:
+	case CS8:
+		len = 10;
+		break;
+	}
+
+	if (termios->c_cflag & CSTOPB)
+		len++;
+	if (termios->c_cflag & PARENB)
+		len++;
+	if (!(termios->c_cflag & PARODD))
+		len++;
+#ifdef CMSPAR
+	if (termios->c_cflag & CMSPAR)
+		len++;
+#endif
+
+	len -= 9;
+	len &= 3;
+	len <<= 3;
+	/*
+	 * Ask the core to calculate the divisor for us.
+	 */
+	baud = uart_get_baud_rate(port, termios, old,
+				  port->uartclk / 16 / 0xffff,
+				  port->uartclk / 16);
+	switch (baud) {
+	case 2400:
+		len |= 1;
+	case 4800:
+		len |= 2;
+	case 19200:
+		len |= 4;
+	case 38400:
+		len |= 5;
+	case 57600:
+		len |= 6;
+	case 115200:
+		len |= 7;
+	case 9600:
+	default:
+		len |= 3;
+	};
+	iowrite8(len, port->private_data);
+
+	serial8250_do_set_termios(port, termios, old);
+}
+
+static unsigned int lp8x4x_serial_in(struct uart_port *p, int offset)
+{
+	unsigned int b;
+	udelay(30);
+	offset = offset << p->regshift;
+	b = readb(p->membase + offset);
+	return b;
+}
+
+static void lp8x4x_serial_out(struct uart_port *p, int offset, int value)
+{
+	offset = offset << p->regshift;
+	writeb(value, p->membase + offset);
+}
+
+static struct plat_serial8250_port lp8x4x_data[] = {
+	QUIRK_PORT(LP8X4X_TTYS0_IOMEM, LP8X4X_TTYS0_IRQ),
+	QUIRK_PORT(LP8X4X_TTYS1_IOMEM, LP8X4X_TTYS1_IRQ),
+	QUIRK_PORT(LP8X4X_TTYS2_IOMEM, LP8X4X_TTYS2_IRQ),
+	{ },
+};
+
+/* Total number of ports can be 35. The first 3 ports are on
+ * the device, the rest are on extension slots. Only the first 3
+ * require termios quirk */
+#define LP8X4X_QUIRK_PORTS	3
+
+static unsigned int extra_mem[LP8X4X_QUIRK_PORTS] = {
+	LP8X4X_TTYS0_QUIRK,
+	LP8X4X_TTYS1_QUIRK,
+	LP8X4X_TTYS2_QUIRK
+};
+
+static int request_and_remap(int i)
+{
+	if (!request_mem_region(extra_mem[i], 1, "serial"))
+		return -EBUSY;
+
+	lp8x4x_data[i].private_data = ioremap(extra_mem[i], 1);
+	if (lp8x4x_data[i].private_data)
+		return 0;
+
+	release_mem_region(extra_mem[i], 1);
+	return -ENODEV;
+}
+
+static void release_and_unmap(int i)
+{
+	iounmap((void *) lp8x4x_data[i].private_data);
+	release_mem_region(extra_mem[i], 1);
+}
+
+static struct platform_device lp8x4x_device = {
+	.name			= "serial8250",
+	.id			= PLAT8250_DEV_ACCENT,
+	.dev			= {
+		.platform_data	= lp8x4x_data,
+	},
+};
+
+static int __init lp8x4x_init(void)
+{
+	int i = 0;
+	int err = 0;
+
+	for (i = 0; i < LP8X4X_QUIRK_PORTS; i++) {
+		err = request_and_remap(i);
+		if (err == 0)
+			continue;
+
+		for (; i >= 0; i--)
+			release_and_unmap(i);
+		lp8x4x_device.dev.platform_data = NULL;
+		return err;
+	}
+	return platform_device_register(&lp8x4x_device);
+}
+
+module_init(lp8x4x_init);
+
+MODULE_AUTHOR("Sergei Ianovich");
+MODULE_DESCRIPTION("8250 serial port module for LP-8x4x");
+MODULE_LICENSE("GPL");
diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
index f3b306e..30b9af4 100644
--- a/drivers/tty/serial/8250/Kconfig
+++ b/drivers/tty/serial/8250/Kconfig
@@ -237,6 +237,17 @@ config SERIAL_8250_HUB6
 	  To compile this driver as a module, choose M here: the module
 	  will be called 8250_hub6.
 
+config SERIAL_8250_LP8X4X
+	tristate "Support 8250 ports on ICP DAS LP-8x4x"
+	depends on SERIAL_8250 != n && SERIAL_8250_MANY_PORTS && MACH_LP8X4X
+	help
+	  In addition on serial ports on PXA270 SoC, LP-8x4x has 1 dual
+	  RS232/RS485 port, 1 RS485 port and 1 RS232 port serial ports.
+
+	  Say N here, unless you plan to run this kernel on a LP-8x4x system.
+
+	  If you choose M, the module will be called 8250_lp8x4x.
+
 #
 # Misc. options/drivers.
 #
diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile
index 36d68d0..451c558 100644
--- a/drivers/tty/serial/8250/Makefile
+++ b/drivers/tty/serial/8250/Makefile
@@ -17,6 +17,7 @@ obj-$(CONFIG_SERIAL_8250_ACCENT)	+= 8250_accent.o
 obj-$(CONFIG_SERIAL_8250_BOCA)		+= 8250_boca.o
 obj-$(CONFIG_SERIAL_8250_EXAR_ST16C554)	+= 8250_exar_st16c554.o
 obj-$(CONFIG_SERIAL_8250_HUB6)		+= 8250_hub6.o
+obj-$(CONFIG_SERIAL_8250_LP8X4X)	+= 8250_lp8x4x.o
 obj-$(CONFIG_SERIAL_8250_FSL)		+= 8250_fsl.o
 obj-$(CONFIG_SERIAL_8250_DW)		+= 8250_dw.o
 obj-$(CONFIG_SERIAL_8250_EM)		+= 8250_em.o
-- 
1.8.4.2


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

* [PATCH 05/11] serial: support for 16550 serial ports on LP-8x4x
@ 2013-12-01  6:26   ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-01  6:26 UTC (permalink / raw)
  To: linux-arm-kernel

The patch adds support for 3 additional LP-8x4x built-in serial
ports.

The device can also host up to 8 extension cards with 4 serial ports
on each card for a total of 35 ports. However, I don't have
the hardware to test extension cards, so they are not supported, yet.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
 arch/arm/configs/lp8x4x_defconfig       |   1 +
 arch/arm/mach-pxa/include/mach/lp8x4x.h |   6 ++
 drivers/tty/serial/8250/8250_lp8x4x.c   | 181 ++++++++++++++++++++++++++++++++
 drivers/tty/serial/8250/Kconfig         |  11 ++
 drivers/tty/serial/8250/Makefile        |   1 +
 5 files changed, 200 insertions(+)
 create mode 100644 drivers/tty/serial/8250/8250_lp8x4x.c

diff --git a/arch/arm/configs/lp8x4x_defconfig b/arch/arm/configs/lp8x4x_defconfig
index 03c85bc..d297a67 100644
--- a/arch/arm/configs/lp8x4x_defconfig
+++ b/arch/arm/configs/lp8x4x_defconfig
@@ -1141,6 +1141,7 @@ CONFIG_SERIAL_8250_NR_UARTS=36
 CONFIG_SERIAL_8250_RUNTIME_UARTS=36
 CONFIG_SERIAL_8250_EXTENDED=y
 CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_LP8X4X=m
 CONFIG_SERIAL_8250_SHARE_IRQ=y
 # CONFIG_SERIAL_8250_DETECT_IRQ is not set
 # CONFIG_SERIAL_8250_RSA is not set
diff --git a/arch/arm/mach-pxa/include/mach/lp8x4x.h b/arch/arm/mach-pxa/include/mach/lp8x4x.h
index a49df22..4d5474e 100644
--- a/arch/arm/mach-pxa/include/mach/lp8x4x.h
+++ b/arch/arm/mach-pxa/include/mach/lp8x4x.h
@@ -50,6 +50,12 @@
 #define LP8X4X_CLRFALLINT	LP8X4X_P2V(0x1700901a)
 #define LP8X4X_RWRTC		LP8X4X_P2V(0x1700901c)
 #define LP8X4X_SRAMBANK		0x1700901e
+#define LP8X4X_TTYS0_QUIRK	0x17009030
+#define LP8X4X_TTYS1_QUIRK	0x17009032
+#define LP8X4X_TTYS2_QUIRK	0x17009034
+#define LP8X4X_TTYS0_IOMEM	0x17009050
+#define LP8X4X_TTYS1_IOMEM	0x17009060
+#define LP8X4X_TTYS2_IOMEM	0x17009070
 #define LP8X4X_SRAM		0x1700a000
 
 /* board specific IRQs */
diff --git a/drivers/tty/serial/8250/8250_lp8x4x.c b/drivers/tty/serial/8250/8250_lp8x4x.c
new file mode 100644
index 0000000..27b01f0b
--- /dev/null
+++ b/drivers/tty/serial/8250/8250_lp8x4x.c
@@ -0,0 +1,181 @@
+/*  linux/drivers/tty/serial/8250/8250_lp8x4x.c
+ *
+ *  Support for 16550 serial ports on ICP DAS LP-8x4x
+ *
+ *  Copyright (C) 2013 Sergei Ianovich <ynvich@gmail.com>
+ *  Framework taken from linux/drivers/tty/serial/8250/8250_accent.c
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/delay.h>
+#include <linux/serial_8250.h>
+#include <mach/lp8x4x.h>
+#include <linux/io.h>
+
+#define QUIRK_PORT(_base, _irq)					\
+	{							\
+		.iobase		= _base,			\
+		.membase	= (void *) _base,		\
+		.mapbase	= _base,			\
+		.irq		= _irq,				\
+		.uartclk	= 14745600,			\
+		.regshift	= 1,				\
+		.iotype		= UPIO_MEM,			\
+		.flags		= UPF_IOREMAP,			\
+		.set_termios	= lp8x4x_set_termios,		\
+		.serial_in	= lp8x4x_serial_in,		\
+		.serial_out	= lp8x4x_serial_out,		\
+	}
+
+static void lp8x4x_set_termios(struct uart_port *port,
+		struct ktermios *termios, struct ktermios *old)
+{
+	unsigned int len;
+	unsigned int baud;
+
+	switch (termios->c_cflag & CSIZE) {
+	case CS5:
+		len = 7;
+		break;
+	case CS6:
+		len = 8;
+		break;
+	case CS7:
+		len = 9;
+		break;
+	default:
+	case CS8:
+		len = 10;
+		break;
+	}
+
+	if (termios->c_cflag & CSTOPB)
+		len++;
+	if (termios->c_cflag & PARENB)
+		len++;
+	if (!(termios->c_cflag & PARODD))
+		len++;
+#ifdef CMSPAR
+	if (termios->c_cflag & CMSPAR)
+		len++;
+#endif
+
+	len -= 9;
+	len &= 3;
+	len <<= 3;
+	/*
+	 * Ask the core to calculate the divisor for us.
+	 */
+	baud = uart_get_baud_rate(port, termios, old,
+				  port->uartclk / 16 / 0xffff,
+				  port->uartclk / 16);
+	switch (baud) {
+	case 2400:
+		len |= 1;
+	case 4800:
+		len |= 2;
+	case 19200:
+		len |= 4;
+	case 38400:
+		len |= 5;
+	case 57600:
+		len |= 6;
+	case 115200:
+		len |= 7;
+	case 9600:
+	default:
+		len |= 3;
+	};
+	iowrite8(len, port->private_data);
+
+	serial8250_do_set_termios(port, termios, old);
+}
+
+static unsigned int lp8x4x_serial_in(struct uart_port *p, int offset)
+{
+	unsigned int b;
+	udelay(30);
+	offset = offset << p->regshift;
+	b = readb(p->membase + offset);
+	return b;
+}
+
+static void lp8x4x_serial_out(struct uart_port *p, int offset, int value)
+{
+	offset = offset << p->regshift;
+	writeb(value, p->membase + offset);
+}
+
+static struct plat_serial8250_port lp8x4x_data[] = {
+	QUIRK_PORT(LP8X4X_TTYS0_IOMEM, LP8X4X_TTYS0_IRQ),
+	QUIRK_PORT(LP8X4X_TTYS1_IOMEM, LP8X4X_TTYS1_IRQ),
+	QUIRK_PORT(LP8X4X_TTYS2_IOMEM, LP8X4X_TTYS2_IRQ),
+	{ },
+};
+
+/* Total number of ports can be 35. The first 3 ports are on
+ * the device, the rest are on extension slots. Only the first 3
+ * require termios quirk */
+#define LP8X4X_QUIRK_PORTS	3
+
+static unsigned int extra_mem[LP8X4X_QUIRK_PORTS] = {
+	LP8X4X_TTYS0_QUIRK,
+	LP8X4X_TTYS1_QUIRK,
+	LP8X4X_TTYS2_QUIRK
+};
+
+static int request_and_remap(int i)
+{
+	if (!request_mem_region(extra_mem[i], 1, "serial"))
+		return -EBUSY;
+
+	lp8x4x_data[i].private_data = ioremap(extra_mem[i], 1);
+	if (lp8x4x_data[i].private_data)
+		return 0;
+
+	release_mem_region(extra_mem[i], 1);
+	return -ENODEV;
+}
+
+static void release_and_unmap(int i)
+{
+	iounmap((void *) lp8x4x_data[i].private_data);
+	release_mem_region(extra_mem[i], 1);
+}
+
+static struct platform_device lp8x4x_device = {
+	.name			= "serial8250",
+	.id			= PLAT8250_DEV_ACCENT,
+	.dev			= {
+		.platform_data	= lp8x4x_data,
+	},
+};
+
+static int __init lp8x4x_init(void)
+{
+	int i = 0;
+	int err = 0;
+
+	for (i = 0; i < LP8X4X_QUIRK_PORTS; i++) {
+		err = request_and_remap(i);
+		if (err == 0)
+			continue;
+
+		for (; i >= 0; i--)
+			release_and_unmap(i);
+		lp8x4x_device.dev.platform_data = NULL;
+		return err;
+	}
+	return platform_device_register(&lp8x4x_device);
+}
+
+module_init(lp8x4x_init);
+
+MODULE_AUTHOR("Sergei Ianovich");
+MODULE_DESCRIPTION("8250 serial port module for LP-8x4x");
+MODULE_LICENSE("GPL");
diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
index f3b306e..30b9af4 100644
--- a/drivers/tty/serial/8250/Kconfig
+++ b/drivers/tty/serial/8250/Kconfig
@@ -237,6 +237,17 @@ config SERIAL_8250_HUB6
 	  To compile this driver as a module, choose M here: the module
 	  will be called 8250_hub6.
 
+config SERIAL_8250_LP8X4X
+	tristate "Support 8250 ports on ICP DAS LP-8x4x"
+	depends on SERIAL_8250 != n && SERIAL_8250_MANY_PORTS && MACH_LP8X4X
+	help
+	  In addition on serial ports on PXA270 SoC, LP-8x4x has 1 dual
+	  RS232/RS485 port, 1 RS485 port and 1 RS232 port serial ports.
+
+	  Say N here, unless you plan to run this kernel on a LP-8x4x system.
+
+	  If you choose M, the module will be called 8250_lp8x4x.
+
 #
 # Misc. options/drivers.
 #
diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile
index 36d68d0..451c558 100644
--- a/drivers/tty/serial/8250/Makefile
+++ b/drivers/tty/serial/8250/Makefile
@@ -17,6 +17,7 @@ obj-$(CONFIG_SERIAL_8250_ACCENT)	+= 8250_accent.o
 obj-$(CONFIG_SERIAL_8250_BOCA)		+= 8250_boca.o
 obj-$(CONFIG_SERIAL_8250_EXAR_ST16C554)	+= 8250_exar_st16c554.o
 obj-$(CONFIG_SERIAL_8250_HUB6)		+= 8250_hub6.o
+obj-$(CONFIG_SERIAL_8250_LP8X4X)	+= 8250_lp8x4x.o
 obj-$(CONFIG_SERIAL_8250_FSL)		+= 8250_fsl.o
 obj-$(CONFIG_SERIAL_8250_DW)		+= 8250_dw.o
 obj-$(CONFIG_SERIAL_8250_EM)		+= 8250_em.o
-- 
1.8.4.2

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

* [PATCH 06/11] misc: support for LP-8x4x custom parallel bus
  2013-12-01  6:26 ` Sergei Ianovich
@ 2013-12-01  6:26   ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-01  6:26 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Rob Landley, Russell King, Eric Miao,
	Haojian Zhuang, Arnd Bergmann, Greg Kroah-Hartman,
	open list:DOCUMENTATION

This patch implements probing for the bus and reporting the number
of available expansion slots.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
 Documentation/misc-devices/lp8x4x_bus.txt |  30 ++++++
 arch/arm/configs/lp8x4x_defconfig         |   1 +
 arch/arm/mach-pxa/include/mach/lp8x4x.h   |   1 +
 arch/arm/mach-pxa/lp8x4x.c                |  18 ++++
 drivers/misc/Kconfig                      |  12 +++
 drivers/misc/Makefile                     |   1 +
 drivers/misc/lp8x4x_bus.c                 | 165 ++++++++++++++++++++++++++++++
 7 files changed, 228 insertions(+)
 create mode 100644 Documentation/misc-devices/lp8x4x_bus.txt
 create mode 100644 drivers/misc/lp8x4x_bus.c

diff --git a/Documentation/misc-devices/lp8x4x_bus.txt b/Documentation/misc-devices/lp8x4x_bus.txt
new file mode 100644
index 0000000..f5392b3
--- /dev/null
+++ b/Documentation/misc-devices/lp8x4x_bus.txt
@@ -0,0 +1,30 @@
+Kernel driver lpx8x4x_bus
+======================
+
+Supported hardare:
+Custom parallel bus on ICP DAS LP-8x4x industrial computers
+
+Data sheet:
+Not freely available
+
+Author:
+Sergei Ianovich <ynvich@gmail.com>
+
+Description
+-----------
+
+http://www.icpdas.com/root/product/solutions/pac/linpac/lp-8x4x_hardware.html
+
+LP-8x4x is an ARM-based industrial computer with a custom parallel bus to
+connect expansion modules with digital input/output, analog input/output,
+serial, CAN and other types of ports.
+
+The bus is implemented by a FPGA.
+
+SYSFS
+-----
+
+/sys/bus/icpdas/devices/backplane:
+
+slot_count
+	RO - shows total number of expansion slots on the device
diff --git a/arch/arm/configs/lp8x4x_defconfig b/arch/arm/configs/lp8x4x_defconfig
index d297a67..5f2b842 100644
--- a/arch/arm/configs/lp8x4x_defconfig
+++ b/arch/arm/configs/lp8x4x_defconfig
@@ -921,6 +921,7 @@ CONFIG_BLK_DEV_LOOP_MIN_COUNT=2
 # CONFIG_BMP085_I2C is not set
 # CONFIG_USB_SWITCH_FSA9480 is not set
 # CONFIG_SRAM is not set
+CONFIG_LP8X4X_BUS=m
 # CONFIG_C2PORT is not set
 
 #
diff --git a/arch/arm/mach-pxa/include/mach/lp8x4x.h b/arch/arm/mach-pxa/include/mach/lp8x4x.h
index 4d5474e..5d289bf 100644
--- a/arch/arm/mach-pxa/include/mach/lp8x4x.h
+++ b/arch/arm/mach-pxa/include/mach/lp8x4x.h
@@ -53,6 +53,7 @@
 #define LP8X4X_TTYS0_QUIRK	0x17009030
 #define LP8X4X_TTYS1_QUIRK	0x17009032
 #define LP8X4X_TTYS2_QUIRK	0x17009034
+#define LP8X4X_MOD_NUM		0x17009046
 #define LP8X4X_TTYS0_IOMEM	0x17009050
 #define LP8X4X_TTYS1_IOMEM	0x17009060
 #define LP8X4X_TTYS2_IOMEM	0x17009070
diff --git a/arch/arm/mach-pxa/lp8x4x.c b/arch/arm/mach-pxa/lp8x4x.c
index 47a8776..38482d3 100644
--- a/arch/arm/mach-pxa/lp8x4x.c
+++ b/arch/arm/mach-pxa/lp8x4x.c
@@ -418,6 +418,23 @@ static struct platform_device lp8x4x_ds1302_device[] = {
 	},
 };
 
+static struct resource lp8x4x_bus_resources[] = {
+	[0] = {
+		.start  = LP8X4X_MOD_NUM,
+		.end    = LP8X4X_MOD_NUM,
+		.flags  = IORESOURCE_MEM,
+	},
+};
+
+static struct platform_device lp8x4x_bus_device[] = {
+	{
+		.name           = "lp8x4x-bus",
+		.id             = 0,
+		.resource = &lp8x4x_bus_resources[0],
+		.num_resources = 1,
+	},
+};
+
 static struct platform_device *lp8x4x_devices[] __initdata = {
 	&lp8x4x_flash_device[0],
 	&lp8x4x_flash_device[1],
@@ -425,6 +442,7 @@ static struct platform_device *lp8x4x_devices[] __initdata = {
 	&lp8x4x_dm9000_device[0],
 	&lp8x4x_dm9000_device[1],
 	&lp8x4x_ds1302_device[0],
+	&lp8x4x_bus_device[0],
 };
 
 static struct pxaohci_platform_data lp8x4x_ohci_platform_data = {
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index a3e291d..85676c4 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -515,6 +515,18 @@ config SRAM
 	  the genalloc API. It is supposed to be used for small on-chip SRAM
 	  areas found on many SoCs.
 
+config LP8X4X_BUS
+	tristate "ICP DAS LP-8x4x industrial IO bus"
+	depends on MACH_LP8X4X && SYSFS
+	---help---
+	  This is a driver for ICP DAS LP-8x4x programmable automation
+	  controller. It exposes a custom parallel bus. The bus services
+	  data acquisition and control modules.
+
+	  Say N, unless you plan to run this kernel on a LP-8x4x system.
+
+	  If you say M here, the module will be called lp8x4x_bus.
+
 source "drivers/misc/c2port/Kconfig"
 source "drivers/misc/eeprom/Kconfig"
 source "drivers/misc/cb710/Kconfig"
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index f45473e..7578cff 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -53,3 +53,4 @@ obj-$(CONFIG_VMWARE_VMCI)	+= vmw_vmci/
 obj-$(CONFIG_LATTICE_ECP3_CONFIG)	+= lattice-ecp3-config.o
 obj-$(CONFIG_SRAM)		+= sram.o
 obj-y				+= mic/
+obj-$(CONFIG_LP8X4X_BUS)	+= lp8x4x_bus.o
diff --git a/drivers/misc/lp8x4x_bus.c b/drivers/misc/lp8x4x_bus.c
new file mode 100644
index 0000000..9cd840e
--- /dev/null
+++ b/drivers/misc/lp8x4x_bus.c
@@ -0,0 +1,165 @@
+/*
+ *  linux/misc/lp8x4x_bus.c
+ *
+ *  Support for ICP DAS LP-8x4x programmable automation controller bus
+ *  Copyright (C) 2013 Sergei Ianovich <ynvich@gmail.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation or any later version.
+ */
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <linux/gpio.h>
+
+#include <mach/mfp-pxa27x.h>
+#include <mach/lp8x4x.h>
+#include <asm/system_info.h>
+
+#define MODULE_NAME	"lp8x4x-bus"
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Sergei Ianovich <ynvich@gmail.com>");
+MODULE_DESCRIPTION("ICP DAS LP-8x4x parallel bus driver");
+
+struct lp8x4x_master {
+	unsigned int		slot_count;
+	void			*count_addr;
+	struct device		dev;
+};
+
+static int lp8x4x_match(struct device *dev, struct device_driver *drv)
+{
+	return 1;
+}
+
+static struct bus_type lp8x4x_bus_type = {
+	.name		= "icpdas",
+	.match		= lp8x4x_match,
+};
+
+static void lp8x4x_master_release(struct device *dev)
+{
+	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
+	BUG_ON(!dev);
+
+	kfree(m);
+}
+
+static ssize_t slot_count_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
+
+	return sprintf(buf, "%u\n", m->slot_count);
+}
+
+static DEVICE_ATTR_RO(slot_count);
+
+static struct attribute *master_dev_attrs[] = {
+	&dev_attr_slot_count.attr,
+	NULL,
+};
+ATTRIBUTE_GROUPS(master_dev);
+
+
+static void devm_lp8x4x_bus_release(struct device *dev, void *res)
+{
+	struct lp8x4x_master *m = *(struct lp8x4x_master **)res;
+	void *mem = m->count_addr;
+
+	dev_info(dev, "releasing devices\n");
+	device_unregister(&m->dev);
+	bus_unregister(&lp8x4x_bus_type);
+	iounmap(mem);
+}
+
+static int __init lp8x4x_bus_probe(struct platform_device *pdev)
+{
+	struct lp8x4x_master *m, **p;
+	struct resource *res;
+	int err = 0;
+
+	m = kzalloc(sizeof(*m), GFP_KERNEL);
+	if (!m)
+		return -ENOMEM;
+
+	p = devres_alloc(devm_lp8x4x_bus_release, sizeof(*p), GFP_KERNEL);
+	if (!m) {
+		err = -ENOMEM;
+		goto err1;
+	}
+	*p = m;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		err = -ENODEV;
+		goto err2;
+	}
+
+	m->count_addr = ioremap(res->start, resource_size(res));
+	if (!m->count_addr) {
+		dev_err(&pdev->dev, "Failed to ioremap %p\n",
+		       m->count_addr);
+		err = -EFAULT;
+		goto err2;
+	}
+
+	m->slot_count = ioread8(m->count_addr);
+	switch (m->slot_count) {
+	case 1:
+	case 4:
+		break;
+	case 7:
+		m->slot_count = 8;
+		break;
+	default:
+		dev_info(&pdev->dev, "unexpected slot number(%u)",
+				m->slot_count);
+		goto err3;
+	};
+
+	dev_info(&pdev->dev, "found bus with up to %u slots\n", m->slot_count);
+
+	err = bus_register(&lp8x4x_bus_type);
+	if (err < 0) {
+		dev_err(&pdev->dev, "failed to register bus type\n");
+		goto err3;
+	}
+
+	m->dev.bus = &lp8x4x_bus_type;
+	dev_set_name(&m->dev, "backplane");
+	m->dev.parent = &pdev->dev;
+	m->dev.release = lp8x4x_master_release;
+	m->dev.groups = master_dev_groups;
+
+	err = device_register(&m->dev);
+	if (err < 0) {
+		dev_err(&pdev->dev, "failed to register backplane device\n");
+		goto err4;
+	}
+
+	devres_add(&pdev->dev, p);
+	return 0;
+
+err4:
+	bus_unregister(&lp8x4x_bus_type);
+err3:
+	iounmap(m->count_addr);
+err2:
+	devres_free(p);
+err1:
+	kfree(m);
+	return err;
+}
+
+static struct platform_driver lp8x4x_bus_driver = {
+	.driver		= {
+		.name	= MODULE_NAME,
+		.owner	= THIS_MODULE,
+	},
+};
+
+module_platform_driver_probe(lp8x4x_bus_driver, lp8x4x_bus_probe);
-- 
1.8.4.2


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

* [PATCH 06/11] misc: support for LP-8x4x custom parallel bus
@ 2013-12-01  6:26   ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-01  6:26 UTC (permalink / raw)
  To: linux-arm-kernel

This patch implements probing for the bus and reporting the number
of available expansion slots.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
 Documentation/misc-devices/lp8x4x_bus.txt |  30 ++++++
 arch/arm/configs/lp8x4x_defconfig         |   1 +
 arch/arm/mach-pxa/include/mach/lp8x4x.h   |   1 +
 arch/arm/mach-pxa/lp8x4x.c                |  18 ++++
 drivers/misc/Kconfig                      |  12 +++
 drivers/misc/Makefile                     |   1 +
 drivers/misc/lp8x4x_bus.c                 | 165 ++++++++++++++++++++++++++++++
 7 files changed, 228 insertions(+)
 create mode 100644 Documentation/misc-devices/lp8x4x_bus.txt
 create mode 100644 drivers/misc/lp8x4x_bus.c

diff --git a/Documentation/misc-devices/lp8x4x_bus.txt b/Documentation/misc-devices/lp8x4x_bus.txt
new file mode 100644
index 0000000..f5392b3
--- /dev/null
+++ b/Documentation/misc-devices/lp8x4x_bus.txt
@@ -0,0 +1,30 @@
+Kernel driver lpx8x4x_bus
+======================
+
+Supported hardare:
+Custom parallel bus on ICP DAS LP-8x4x industrial computers
+
+Data sheet:
+Not freely available
+
+Author:
+Sergei Ianovich <ynvich@gmail.com>
+
+Description
+-----------
+
+http://www.icpdas.com/root/product/solutions/pac/linpac/lp-8x4x_hardware.html
+
+LP-8x4x is an ARM-based industrial computer with a custom parallel bus to
+connect expansion modules with digital input/output, analog input/output,
+serial, CAN and other types of ports.
+
+The bus is implemented by a FPGA.
+
+SYSFS
+-----
+
+/sys/bus/icpdas/devices/backplane:
+
+slot_count
+	RO - shows total number of expansion slots on the device
diff --git a/arch/arm/configs/lp8x4x_defconfig b/arch/arm/configs/lp8x4x_defconfig
index d297a67..5f2b842 100644
--- a/arch/arm/configs/lp8x4x_defconfig
+++ b/arch/arm/configs/lp8x4x_defconfig
@@ -921,6 +921,7 @@ CONFIG_BLK_DEV_LOOP_MIN_COUNT=2
 # CONFIG_BMP085_I2C is not set
 # CONFIG_USB_SWITCH_FSA9480 is not set
 # CONFIG_SRAM is not set
+CONFIG_LP8X4X_BUS=m
 # CONFIG_C2PORT is not set
 
 #
diff --git a/arch/arm/mach-pxa/include/mach/lp8x4x.h b/arch/arm/mach-pxa/include/mach/lp8x4x.h
index 4d5474e..5d289bf 100644
--- a/arch/arm/mach-pxa/include/mach/lp8x4x.h
+++ b/arch/arm/mach-pxa/include/mach/lp8x4x.h
@@ -53,6 +53,7 @@
 #define LP8X4X_TTYS0_QUIRK	0x17009030
 #define LP8X4X_TTYS1_QUIRK	0x17009032
 #define LP8X4X_TTYS2_QUIRK	0x17009034
+#define LP8X4X_MOD_NUM		0x17009046
 #define LP8X4X_TTYS0_IOMEM	0x17009050
 #define LP8X4X_TTYS1_IOMEM	0x17009060
 #define LP8X4X_TTYS2_IOMEM	0x17009070
diff --git a/arch/arm/mach-pxa/lp8x4x.c b/arch/arm/mach-pxa/lp8x4x.c
index 47a8776..38482d3 100644
--- a/arch/arm/mach-pxa/lp8x4x.c
+++ b/arch/arm/mach-pxa/lp8x4x.c
@@ -418,6 +418,23 @@ static struct platform_device lp8x4x_ds1302_device[] = {
 	},
 };
 
+static struct resource lp8x4x_bus_resources[] = {
+	[0] = {
+		.start  = LP8X4X_MOD_NUM,
+		.end    = LP8X4X_MOD_NUM,
+		.flags  = IORESOURCE_MEM,
+	},
+};
+
+static struct platform_device lp8x4x_bus_device[] = {
+	{
+		.name           = "lp8x4x-bus",
+		.id             = 0,
+		.resource = &lp8x4x_bus_resources[0],
+		.num_resources = 1,
+	},
+};
+
 static struct platform_device *lp8x4x_devices[] __initdata = {
 	&lp8x4x_flash_device[0],
 	&lp8x4x_flash_device[1],
@@ -425,6 +442,7 @@ static struct platform_device *lp8x4x_devices[] __initdata = {
 	&lp8x4x_dm9000_device[0],
 	&lp8x4x_dm9000_device[1],
 	&lp8x4x_ds1302_device[0],
+	&lp8x4x_bus_device[0],
 };
 
 static struct pxaohci_platform_data lp8x4x_ohci_platform_data = {
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index a3e291d..85676c4 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -515,6 +515,18 @@ config SRAM
 	  the genalloc API. It is supposed to be used for small on-chip SRAM
 	  areas found on many SoCs.
 
+config LP8X4X_BUS
+	tristate "ICP DAS LP-8x4x industrial IO bus"
+	depends on MACH_LP8X4X && SYSFS
+	---help---
+	  This is a driver for ICP DAS LP-8x4x programmable automation
+	  controller. It exposes a custom parallel bus. The bus services
+	  data acquisition and control modules.
+
+	  Say N, unless you plan to run this kernel on a LP-8x4x system.
+
+	  If you say M here, the module will be called lp8x4x_bus.
+
 source "drivers/misc/c2port/Kconfig"
 source "drivers/misc/eeprom/Kconfig"
 source "drivers/misc/cb710/Kconfig"
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index f45473e..7578cff 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -53,3 +53,4 @@ obj-$(CONFIG_VMWARE_VMCI)	+= vmw_vmci/
 obj-$(CONFIG_LATTICE_ECP3_CONFIG)	+= lattice-ecp3-config.o
 obj-$(CONFIG_SRAM)		+= sram.o
 obj-y				+= mic/
+obj-$(CONFIG_LP8X4X_BUS)	+= lp8x4x_bus.o
diff --git a/drivers/misc/lp8x4x_bus.c b/drivers/misc/lp8x4x_bus.c
new file mode 100644
index 0000000..9cd840e
--- /dev/null
+++ b/drivers/misc/lp8x4x_bus.c
@@ -0,0 +1,165 @@
+/*
+ *  linux/misc/lp8x4x_bus.c
+ *
+ *  Support for ICP DAS LP-8x4x programmable automation controller bus
+ *  Copyright (C) 2013 Sergei Ianovich <ynvich@gmail.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation or any later version.
+ */
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <linux/gpio.h>
+
+#include <mach/mfp-pxa27x.h>
+#include <mach/lp8x4x.h>
+#include <asm/system_info.h>
+
+#define MODULE_NAME	"lp8x4x-bus"
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Sergei Ianovich <ynvich@gmail.com>");
+MODULE_DESCRIPTION("ICP DAS LP-8x4x parallel bus driver");
+
+struct lp8x4x_master {
+	unsigned int		slot_count;
+	void			*count_addr;
+	struct device		dev;
+};
+
+static int lp8x4x_match(struct device *dev, struct device_driver *drv)
+{
+	return 1;
+}
+
+static struct bus_type lp8x4x_bus_type = {
+	.name		= "icpdas",
+	.match		= lp8x4x_match,
+};
+
+static void lp8x4x_master_release(struct device *dev)
+{
+	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
+	BUG_ON(!dev);
+
+	kfree(m);
+}
+
+static ssize_t slot_count_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
+
+	return sprintf(buf, "%u\n", m->slot_count);
+}
+
+static DEVICE_ATTR_RO(slot_count);
+
+static struct attribute *master_dev_attrs[] = {
+	&dev_attr_slot_count.attr,
+	NULL,
+};
+ATTRIBUTE_GROUPS(master_dev);
+
+
+static void devm_lp8x4x_bus_release(struct device *dev, void *res)
+{
+	struct lp8x4x_master *m = *(struct lp8x4x_master **)res;
+	void *mem = m->count_addr;
+
+	dev_info(dev, "releasing devices\n");
+	device_unregister(&m->dev);
+	bus_unregister(&lp8x4x_bus_type);
+	iounmap(mem);
+}
+
+static int __init lp8x4x_bus_probe(struct platform_device *pdev)
+{
+	struct lp8x4x_master *m, **p;
+	struct resource *res;
+	int err = 0;
+
+	m = kzalloc(sizeof(*m), GFP_KERNEL);
+	if (!m)
+		return -ENOMEM;
+
+	p = devres_alloc(devm_lp8x4x_bus_release, sizeof(*p), GFP_KERNEL);
+	if (!m) {
+		err = -ENOMEM;
+		goto err1;
+	}
+	*p = m;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		err = -ENODEV;
+		goto err2;
+	}
+
+	m->count_addr = ioremap(res->start, resource_size(res));
+	if (!m->count_addr) {
+		dev_err(&pdev->dev, "Failed to ioremap %p\n",
+		       m->count_addr);
+		err = -EFAULT;
+		goto err2;
+	}
+
+	m->slot_count = ioread8(m->count_addr);
+	switch (m->slot_count) {
+	case 1:
+	case 4:
+		break;
+	case 7:
+		m->slot_count = 8;
+		break;
+	default:
+		dev_info(&pdev->dev, "unexpected slot number(%u)",
+				m->slot_count);
+		goto err3;
+	};
+
+	dev_info(&pdev->dev, "found bus with up to %u slots\n", m->slot_count);
+
+	err = bus_register(&lp8x4x_bus_type);
+	if (err < 0) {
+		dev_err(&pdev->dev, "failed to register bus type\n");
+		goto err3;
+	}
+
+	m->dev.bus = &lp8x4x_bus_type;
+	dev_set_name(&m->dev, "backplane");
+	m->dev.parent = &pdev->dev;
+	m->dev.release = lp8x4x_master_release;
+	m->dev.groups = master_dev_groups;
+
+	err = device_register(&m->dev);
+	if (err < 0) {
+		dev_err(&pdev->dev, "failed to register backplane device\n");
+		goto err4;
+	}
+
+	devres_add(&pdev->dev, p);
+	return 0;
+
+err4:
+	bus_unregister(&lp8x4x_bus_type);
+err3:
+	iounmap(m->count_addr);
+err2:
+	devres_free(p);
+err1:
+	kfree(m);
+	return err;
+}
+
+static struct platform_driver lp8x4x_bus_driver = {
+	.driver		= {
+		.name	= MODULE_NAME,
+		.owner	= THIS_MODULE,
+	},
+};
+
+module_platform_driver_probe(lp8x4x_bus_driver, lp8x4x_bus_probe);
-- 
1.8.4.2

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

* [PATCH 07/11] misc: support for serial slots in LP-8x4x
  2013-12-01  6:26 ` Sergei Ianovich
@ 2013-12-01  6:26   ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-01  6:26 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Rob Landley, Eric Miao, Russell King,
	Haojian Zhuang, Arnd Bergmann, Greg Kroah-Hartman,
	open list:DOCUMENTATION

Serial modules (I-870xxW series) implement DCON protocol which
allows one-master-many-slaves configuration over RS-485. When
these modules are installed into the device, they could be
accessed using the 2nd PXA built-in UART port (/dev/ttySA1).
However, it seems that addresses are not processed by the modules.
So the parallel bus needs to select which slot is connected.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
 Documentation/misc-devices/lp8x4x_bus.txt | 15 ++++++-
 arch/arm/mach-pxa/include/mach/lp8x4x.h   |  1 +
 arch/arm/mach-pxa/lp8x4x.c                |  7 ++-
 drivers/misc/lp8x4x_bus.c                 | 73 +++++++++++++++++++++++++++++--
 4 files changed, 90 insertions(+), 6 deletions(-)

diff --git a/Documentation/misc-devices/lp8x4x_bus.txt b/Documentation/misc-devices/lp8x4x_bus.txt
index f5392b3..d9a069d 100644
--- a/Documentation/misc-devices/lp8x4x_bus.txt
+++ b/Documentation/misc-devices/lp8x4x_bus.txt
@@ -19,7 +19,14 @@ LP-8x4x is an ARM-based industrial computer with a custom parallel bus to
 connect expansion modules with digital input/output, analog input/output,
 serial, CAN and other types of ports.
 
-The bus is implemented by a FPGA.
+The bus is implemented by a FPGA. There are two major groups of expansion
+modules: serial and parallel.
+
+Serial modules (I-870xxW series) implement DCON protocol which allows one-
+master-many-slaves configuration over RS-485. When these modules are installed
+into the device, they could be accessed using the 2nd PXA built-in UART port
+(/dev/ttySA1). However, it seems that addresses are not processed by
+the modules. So the parallel bus needs to select which slot is connected.
 
 SYSFS
 -----
@@ -28,3 +35,9 @@ SYSFS
 
 slot_count
 	RO - shows total number of expansion slots on the device
+
+active_slot
+	RW - connects the select slot for serial communications. If there
+	     is a parallel module in the selected slot, it simply ignores
+	     incoming packets. So it is safe to activate any available
+	     slot.
diff --git a/arch/arm/mach-pxa/include/mach/lp8x4x.h b/arch/arm/mach-pxa/include/mach/lp8x4x.h
index 5d289bf..9addfa8 100644
--- a/arch/arm/mach-pxa/include/mach/lp8x4x.h
+++ b/arch/arm/mach-pxa/include/mach/lp8x4x.h
@@ -37,6 +37,7 @@
 
 /* board level registers in the FPGA */
 
+#define LP8X4X_SLOT_SWITCH	0x17009004
 #define LP8X4X_EOI		LP8X4X_P2V(0x17009006)
 #define LP8X4X_INSINT		LP8X4X_P2V(0x17009008)
 #define LP8X4X_ENSYSINT		LP8X4X_P2V(0x1700900A)
diff --git a/arch/arm/mach-pxa/lp8x4x.c b/arch/arm/mach-pxa/lp8x4x.c
index 38482d3..b30343d 100644
--- a/arch/arm/mach-pxa/lp8x4x.c
+++ b/arch/arm/mach-pxa/lp8x4x.c
@@ -424,6 +424,11 @@ static struct resource lp8x4x_bus_resources[] = {
 		.end    = LP8X4X_MOD_NUM,
 		.flags  = IORESOURCE_MEM,
 	},
+	[1] = {
+		.start  = LP8X4X_SLOT_SWITCH,
+		.end    = LP8X4X_SLOT_SWITCH,
+		.flags  = IORESOURCE_MEM,
+	},
 };
 
 static struct platform_device lp8x4x_bus_device[] = {
@@ -431,7 +436,7 @@ static struct platform_device lp8x4x_bus_device[] = {
 		.name           = "lp8x4x-bus",
 		.id             = 0,
 		.resource = &lp8x4x_bus_resources[0],
-		.num_resources = 1,
+		.num_resources = 2,
 	},
 };
 
diff --git a/drivers/misc/lp8x4x_bus.c b/drivers/misc/lp8x4x_bus.c
index 9cd840e..647fde7 100644
--- a/drivers/misc/lp8x4x_bus.c
+++ b/drivers/misc/lp8x4x_bus.c
@@ -27,6 +27,8 @@ MODULE_DESCRIPTION("ICP DAS LP-8x4x parallel bus driver");
 struct lp8x4x_master {
 	unsigned int		slot_count;
 	void			*count_addr;
+	unsigned int		active_slot;
+	void			*switch_addr;
 	struct device		dev;
 };
 
@@ -58,8 +60,45 @@ static ssize_t slot_count_show(struct device *dev,
 
 static DEVICE_ATTR_RO(slot_count);
 
+static ssize_t active_slot_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
+
+	return sprintf(buf, "%u\n", m->active_slot);
+}
+
+static ssize_t active_slot_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
+	unsigned int active_slot = 0;
+	int err;
+
+	if (!buf)
+		return count;
+	if (0 == count)
+		return count;
+
+	err = kstrtouint(buf, 10, &active_slot);
+	if (err != 0 || !active_slot || active_slot > m->slot_count) {
+		dev_err(dev, "slot number is out of range 1..%u\n",
+				m->slot_count);
+		return count;
+	}
+
+	m->active_slot = active_slot;
+
+	iowrite8((1 << (m->active_slot - 1)) ^ 0xff, m->switch_addr);
+
+	return count;
+}
+
+static DEVICE_ATTR_RW(active_slot);
+
 static struct attribute *master_dev_attrs[] = {
 	&dev_attr_slot_count.attr,
+	&dev_attr_active_slot.attr,
 	NULL,
 };
 ATTRIBUTE_GROUPS(master_dev);
@@ -69,10 +108,15 @@ static void devm_lp8x4x_bus_release(struct device *dev, void *res)
 {
 	struct lp8x4x_master *m = *(struct lp8x4x_master **)res;
 	void *mem = m->count_addr;
+	void *mem2 = m->switch_addr;
 
 	dev_info(dev, "releasing devices\n");
 	device_unregister(&m->dev);
 	bus_unregister(&lp8x4x_bus_type);
+
+	/* Disable serial communications */
+	iowrite8(0xff, mem2);
+	iounmap(mem2);
 	iounmap(mem);
 }
 
@@ -95,6 +139,7 @@ static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!res) {
+		dev_err(&pdev->dev, "Failed to get slot number address\n");
 		err = -ENODEV;
 		goto err2;
 	}
@@ -107,6 +152,21 @@ static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 		goto err2;
 	}
 
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	if (!res) {
+		dev_err(&pdev->dev, "Failed to get slot switch address\n");
+		err = -ENODEV;
+		goto err3;
+	}
+
+	m->switch_addr = ioremap(res->start, resource_size(res));
+	if (!m->switch_addr) {
+		dev_err(&pdev->dev, "Failed to ioremap %p\n",
+		       m->switch_addr);
+		err = -EFAULT;
+		goto err3;
+	}
+
 	m->slot_count = ioread8(m->count_addr);
 	switch (m->slot_count) {
 	case 1:
@@ -118,15 +178,18 @@ static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 	default:
 		dev_info(&pdev->dev, "unexpected slot number(%u)",
 				m->slot_count);
-		goto err3;
+		goto err_bus;
 	};
 
 	dev_info(&pdev->dev, "found bus with up to %u slots\n", m->slot_count);
 
+	/* Disable serial communications until explicitly enabled */
+	iowrite8(0xff, m->switch_addr);
+
 	err = bus_register(&lp8x4x_bus_type);
 	if (err < 0) {
 		dev_err(&pdev->dev, "failed to register bus type\n");
-		goto err3;
+		goto err_bus;
 	}
 
 	m->dev.bus = &lp8x4x_bus_type;
@@ -138,14 +201,16 @@ static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 	err = device_register(&m->dev);
 	if (err < 0) {
 		dev_err(&pdev->dev, "failed to register backplane device\n");
-		goto err4;
+		goto err_dev;
 	}
 
 	devres_add(&pdev->dev, p);
 	return 0;
 
-err4:
+err_dev:
 	bus_unregister(&lp8x4x_bus_type);
+err_bus:
+	iounmap(m->switch_addr);
 err3:
 	iounmap(m->count_addr);
 err2:
-- 
1.8.4.2


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

* [PATCH 07/11] misc: support for serial slots in LP-8x4x
@ 2013-12-01  6:26   ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-01  6:26 UTC (permalink / raw)
  To: linux-arm-kernel

Serial modules (I-870xxW series) implement DCON protocol which
allows one-master-many-slaves configuration over RS-485. When
these modules are installed into the device, they could be
accessed using the 2nd PXA built-in UART port (/dev/ttySA1).
However, it seems that addresses are not processed by the modules.
So the parallel bus needs to select which slot is connected.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
 Documentation/misc-devices/lp8x4x_bus.txt | 15 ++++++-
 arch/arm/mach-pxa/include/mach/lp8x4x.h   |  1 +
 arch/arm/mach-pxa/lp8x4x.c                |  7 ++-
 drivers/misc/lp8x4x_bus.c                 | 73 +++++++++++++++++++++++++++++--
 4 files changed, 90 insertions(+), 6 deletions(-)

diff --git a/Documentation/misc-devices/lp8x4x_bus.txt b/Documentation/misc-devices/lp8x4x_bus.txt
index f5392b3..d9a069d 100644
--- a/Documentation/misc-devices/lp8x4x_bus.txt
+++ b/Documentation/misc-devices/lp8x4x_bus.txt
@@ -19,7 +19,14 @@ LP-8x4x is an ARM-based industrial computer with a custom parallel bus to
 connect expansion modules with digital input/output, analog input/output,
 serial, CAN and other types of ports.
 
-The bus is implemented by a FPGA.
+The bus is implemented by a FPGA. There are two major groups of expansion
+modules: serial and parallel.
+
+Serial modules (I-870xxW series) implement DCON protocol which allows one-
+master-many-slaves configuration over RS-485. When these modules are installed
+into the device, they could be accessed using the 2nd PXA built-in UART port
+(/dev/ttySA1). However, it seems that addresses are not processed by
+the modules. So the parallel bus needs to select which slot is connected.
 
 SYSFS
 -----
@@ -28,3 +35,9 @@ SYSFS
 
 slot_count
 	RO - shows total number of expansion slots on the device
+
+active_slot
+	RW - connects the select slot for serial communications. If there
+	     is a parallel module in the selected slot, it simply ignores
+	     incoming packets. So it is safe to activate any available
+	     slot.
diff --git a/arch/arm/mach-pxa/include/mach/lp8x4x.h b/arch/arm/mach-pxa/include/mach/lp8x4x.h
index 5d289bf..9addfa8 100644
--- a/arch/arm/mach-pxa/include/mach/lp8x4x.h
+++ b/arch/arm/mach-pxa/include/mach/lp8x4x.h
@@ -37,6 +37,7 @@
 
 /* board level registers in the FPGA */
 
+#define LP8X4X_SLOT_SWITCH	0x17009004
 #define LP8X4X_EOI		LP8X4X_P2V(0x17009006)
 #define LP8X4X_INSINT		LP8X4X_P2V(0x17009008)
 #define LP8X4X_ENSYSINT		LP8X4X_P2V(0x1700900A)
diff --git a/arch/arm/mach-pxa/lp8x4x.c b/arch/arm/mach-pxa/lp8x4x.c
index 38482d3..b30343d 100644
--- a/arch/arm/mach-pxa/lp8x4x.c
+++ b/arch/arm/mach-pxa/lp8x4x.c
@@ -424,6 +424,11 @@ static struct resource lp8x4x_bus_resources[] = {
 		.end    = LP8X4X_MOD_NUM,
 		.flags  = IORESOURCE_MEM,
 	},
+	[1] = {
+		.start  = LP8X4X_SLOT_SWITCH,
+		.end    = LP8X4X_SLOT_SWITCH,
+		.flags  = IORESOURCE_MEM,
+	},
 };
 
 static struct platform_device lp8x4x_bus_device[] = {
@@ -431,7 +436,7 @@ static struct platform_device lp8x4x_bus_device[] = {
 		.name           = "lp8x4x-bus",
 		.id             = 0,
 		.resource = &lp8x4x_bus_resources[0],
-		.num_resources = 1,
+		.num_resources = 2,
 	},
 };
 
diff --git a/drivers/misc/lp8x4x_bus.c b/drivers/misc/lp8x4x_bus.c
index 9cd840e..647fde7 100644
--- a/drivers/misc/lp8x4x_bus.c
+++ b/drivers/misc/lp8x4x_bus.c
@@ -27,6 +27,8 @@ MODULE_DESCRIPTION("ICP DAS LP-8x4x parallel bus driver");
 struct lp8x4x_master {
 	unsigned int		slot_count;
 	void			*count_addr;
+	unsigned int		active_slot;
+	void			*switch_addr;
 	struct device		dev;
 };
 
@@ -58,8 +60,45 @@ static ssize_t slot_count_show(struct device *dev,
 
 static DEVICE_ATTR_RO(slot_count);
 
+static ssize_t active_slot_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
+
+	return sprintf(buf, "%u\n", m->active_slot);
+}
+
+static ssize_t active_slot_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
+	unsigned int active_slot = 0;
+	int err;
+
+	if (!buf)
+		return count;
+	if (0 == count)
+		return count;
+
+	err = kstrtouint(buf, 10, &active_slot);
+	if (err != 0 || !active_slot || active_slot > m->slot_count) {
+		dev_err(dev, "slot number is out of range 1..%u\n",
+				m->slot_count);
+		return count;
+	}
+
+	m->active_slot = active_slot;
+
+	iowrite8((1 << (m->active_slot - 1)) ^ 0xff, m->switch_addr);
+
+	return count;
+}
+
+static DEVICE_ATTR_RW(active_slot);
+
 static struct attribute *master_dev_attrs[] = {
 	&dev_attr_slot_count.attr,
+	&dev_attr_active_slot.attr,
 	NULL,
 };
 ATTRIBUTE_GROUPS(master_dev);
@@ -69,10 +108,15 @@ static void devm_lp8x4x_bus_release(struct device *dev, void *res)
 {
 	struct lp8x4x_master *m = *(struct lp8x4x_master **)res;
 	void *mem = m->count_addr;
+	void *mem2 = m->switch_addr;
 
 	dev_info(dev, "releasing devices\n");
 	device_unregister(&m->dev);
 	bus_unregister(&lp8x4x_bus_type);
+
+	/* Disable serial communications */
+	iowrite8(0xff, mem2);
+	iounmap(mem2);
 	iounmap(mem);
 }
 
@@ -95,6 +139,7 @@ static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!res) {
+		dev_err(&pdev->dev, "Failed to get slot number address\n");
 		err = -ENODEV;
 		goto err2;
 	}
@@ -107,6 +152,21 @@ static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 		goto err2;
 	}
 
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	if (!res) {
+		dev_err(&pdev->dev, "Failed to get slot switch address\n");
+		err = -ENODEV;
+		goto err3;
+	}
+
+	m->switch_addr = ioremap(res->start, resource_size(res));
+	if (!m->switch_addr) {
+		dev_err(&pdev->dev, "Failed to ioremap %p\n",
+		       m->switch_addr);
+		err = -EFAULT;
+		goto err3;
+	}
+
 	m->slot_count = ioread8(m->count_addr);
 	switch (m->slot_count) {
 	case 1:
@@ -118,15 +178,18 @@ static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 	default:
 		dev_info(&pdev->dev, "unexpected slot number(%u)",
 				m->slot_count);
-		goto err3;
+		goto err_bus;
 	};
 
 	dev_info(&pdev->dev, "found bus with up to %u slots\n", m->slot_count);
 
+	/* Disable serial communications until explicitly enabled */
+	iowrite8(0xff, m->switch_addr);
+
 	err = bus_register(&lp8x4x_bus_type);
 	if (err < 0) {
 		dev_err(&pdev->dev, "failed to register bus type\n");
-		goto err3;
+		goto err_bus;
 	}
 
 	m->dev.bus = &lp8x4x_bus_type;
@@ -138,14 +201,16 @@ static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 	err = device_register(&m->dev);
 	if (err < 0) {
 		dev_err(&pdev->dev, "failed to register backplane device\n");
-		goto err4;
+		goto err_dev;
 	}
 
 	devres_add(&pdev->dev, p);
 	return 0;
 
-err4:
+err_dev:
 	bus_unregister(&lp8x4x_bus_type);
+err_bus:
+	iounmap(m->switch_addr);
 err3:
 	iounmap(m->count_addr);
 err2:
-- 
1.8.4.2

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

* [PATCH 08/11] misc: support for parallel slots in LP-8x4x
  2013-12-01  6:26 ` Sergei Ianovich
@ 2013-12-01  6:26   ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-01  6:26 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Rob Landley, Eric Miao, Russell King,
	Haojian Zhuang, Arnd Bergmann, Greg Kroah-Hartman,
	open list:DOCUMENTATION

This patch enumerates parallel modules in expansion slots and exposes
model numbers via sysfs.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
 Documentation/misc-devices/lp8x4x_bus.txt |   8 ++
 arch/arm/mach-pxa/include/mach/lp8x4x.h   |   8 ++
 arch/arm/mach-pxa/lp8x4x.c                |  42 +++++++++-
 drivers/misc/lp8x4x_bus.c                 | 127 ++++++++++++++++++++++++++++++
 4 files changed, 184 insertions(+), 1 deletion(-)

diff --git a/Documentation/misc-devices/lp8x4x_bus.txt b/Documentation/misc-devices/lp8x4x_bus.txt
index d9a069d..9285fdc 100644
--- a/Documentation/misc-devices/lp8x4x_bus.txt
+++ b/Documentation/misc-devices/lp8x4x_bus.txt
@@ -28,6 +28,9 @@ into the device, they could be accessed using the 2nd PXA built-in UART port
 (/dev/ttySA1). However, it seems that addresses are not processed by
 the modules. So the parallel bus needs to select which slot is connected.
 
+Parallel modules allow much faster communication. There are accessed using
+IO memory through the FPGA. Their ports are exposed via sysfs.
+
 SYSFS
 -----
 
@@ -41,3 +44,8 @@ active_slot
 	     is a parallel module in the selected slot, it simply ignores
 	     incoming packets. So it is safe to activate any available
 	     slot.
+
+/sys/bus/icpdas/devices/slot%02i:
+
+model
+	RO - shows expansion module model number
diff --git a/arch/arm/mach-pxa/include/mach/lp8x4x.h b/arch/arm/mach-pxa/include/mach/lp8x4x.h
index 9addfa8..e1005c5 100644
--- a/arch/arm/mach-pxa/include/mach/lp8x4x.h
+++ b/arch/arm/mach-pxa/include/mach/lp8x4x.h
@@ -37,6 +37,14 @@
 
 /* board level registers in the FPGA */
 
+#define LP8X4X_SLOT1_IO		0x17001000
+#define LP8X4X_SLOT2_IO		0x17002000
+#define LP8X4X_SLOT3_IO		0x17003000
+#define LP8X4X_SLOT4_IO		0x17004000
+#define LP8X4X_SLOT5_IO		0x17005000
+#define LP8X4X_SLOT6_IO		0x17006000
+#define LP8X4X_SLOT7_IO		0x17007000
+#define LP8X4X_SLOT8_IO		0x17008000
 #define LP8X4X_SLOT_SWITCH	0x17009004
 #define LP8X4X_EOI		LP8X4X_P2V(0x17009006)
 #define LP8X4X_INSINT		LP8X4X_P2V(0x17009008)
diff --git a/arch/arm/mach-pxa/lp8x4x.c b/arch/arm/mach-pxa/lp8x4x.c
index b30343d..ae84d36 100644
--- a/arch/arm/mach-pxa/lp8x4x.c
+++ b/arch/arm/mach-pxa/lp8x4x.c
@@ -429,6 +429,46 @@ static struct resource lp8x4x_bus_resources[] = {
 		.end    = LP8X4X_SLOT_SWITCH,
 		.flags  = IORESOURCE_MEM,
 	},
+	[2] = {
+		.start  = LP8X4X_SLOT1_IO,
+		.end    = LP8X4X_SLOT1_IO + 15,
+		.flags  = IORESOURCE_MEM,
+	},
+	[3] = {
+		.start  = LP8X4X_SLOT2_IO,
+		.end    = LP8X4X_SLOT2_IO + 15,
+		.flags  = IORESOURCE_MEM,
+	},
+	[4] = {
+		.start  = LP8X4X_SLOT3_IO,
+		.end    = LP8X4X_SLOT3_IO + 15,
+		.flags  = IORESOURCE_MEM,
+	},
+	[5] = {
+		.start  = LP8X4X_SLOT4_IO,
+		.end    = LP8X4X_SLOT4_IO + 15,
+		.flags  = IORESOURCE_MEM,
+	},
+	[6] = {
+		.start  = LP8X4X_SLOT5_IO,
+		.end    = LP8X4X_SLOT5_IO + 15,
+		.flags  = IORESOURCE_MEM,
+	},
+	[7] = {
+		.start  = LP8X4X_SLOT6_IO,
+		.end    = LP8X4X_SLOT6_IO + 15,
+		.flags  = IORESOURCE_MEM,
+	},
+	[8] = {
+		.start  = LP8X4X_SLOT7_IO,
+		.end    = LP8X4X_SLOT7_IO + 15,
+		.flags  = IORESOURCE_MEM,
+	},
+	[9] = {
+		.start  = LP8X4X_SLOT8_IO,
+		.end    = LP8X4X_SLOT8_IO + 15,
+		.flags  = IORESOURCE_MEM,
+	},
 };
 
 static struct platform_device lp8x4x_bus_device[] = {
@@ -436,7 +476,7 @@ static struct platform_device lp8x4x_bus_device[] = {
 		.name           = "lp8x4x-bus",
 		.id             = 0,
 		.resource = &lp8x4x_bus_resources[0],
-		.num_resources = 2,
+		.num_resources = 10,
 	},
 };
 
diff --git a/drivers/misc/lp8x4x_bus.c b/drivers/misc/lp8x4x_bus.c
index 647fde7..b2d4a04 100644
--- a/drivers/misc/lp8x4x_bus.c
+++ b/drivers/misc/lp8x4x_bus.c
@@ -24,14 +24,57 @@ MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Sergei Ianovich <ynvich@gmail.com>");
 MODULE_DESCRIPTION("ICP DAS LP-8x4x parallel bus driver");
 
+struct lp8x4x_slot {
+	void			*data_addr;
+	unsigned int		model;
+	struct device		dev;
+};
+
+#define LP8X4X_MAX_SLOT_COUNT	8
 struct lp8x4x_master {
 	unsigned int		slot_count;
 	void			*count_addr;
 	unsigned int		active_slot;
 	void			*switch_addr;
+	struct lp8x4x_slot	slot[LP8X4X_MAX_SLOT_COUNT];
 	struct device		dev;
 };
 
+static unsigned char lp8x4x_model[256] = {
+	   0,    0,    0, 0x11,    0, 0x18, 0x13, 0x11,
+	0x0e, 0x11,    0,    0,    0, 0x5a, 0x5b, 0x5c,
+	0x3c, 0x44, 0x34, 0x3a, 0x39, 0x36, 0x37, 0x33,
+	0x35, 0x40, 0x41, 0x42, 0x38, 0x3f, 0x32, 0x45,
+	0xac, 0x70, 0x8e, 0x8e, 0x1e, 0x72, 0x90, 0x29,
+	0x4a, 0x22, 0xd3, 0xd2, 0x28, 0x25, 0x2a, 0x29,
+	0x48, 0x49, 0x5d, 0x1f, 0x20, 0x23, 0x24, 0x4d,
+	0x3d, 0x3e,    0,    0,    0,    0,    0,    0,
+	   0, 0x78, 0x72, 0x2b, 0x5e, 0x5e, 0x36, 0xae,
+	0x30,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0, 0x5c, 0x5e,    0, 0x5e,    0,    0,
+	   0, 0x3b,    0,    0,    0,    0,    0,    0,
+	   0, 0x50, 0x2e,    0, 0x58,    0,    0, 0x43,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0, 0x54,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0
+};
+
 static int lp8x4x_match(struct device *dev, struct device_driver *drv)
 {
 	return 1;
@@ -42,6 +85,26 @@ static struct bus_type lp8x4x_bus_type = {
 	.match		= lp8x4x_match,
 };
 
+static void lp8x4x_slot_release(struct device *dev)
+{
+}
+
+static ssize_t model_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct lp8x4x_slot *s = container_of(dev, struct lp8x4x_slot, dev);
+
+	return sprintf(buf, "%u\n", s->model + 8000);
+}
+
+static DEVICE_ATTR_RO(model);
+
+static struct attribute *slot_dev_attrs[] = {
+	&dev_attr_model.attr,
+	NULL,
+};
+ATTRIBUTE_GROUPS(slot_dev);
+
 static void lp8x4x_master_release(struct device *dev)
 {
 	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
@@ -107,10 +170,18 @@ ATTRIBUTE_GROUPS(master_dev);
 static void devm_lp8x4x_bus_release(struct device *dev, void *res)
 {
 	struct lp8x4x_master *m = *(struct lp8x4x_master **)res;
+	struct lp8x4x_slot *s;
 	void *mem = m->count_addr;
 	void *mem2 = m->switch_addr;
+	int i;
 
 	dev_info(dev, "releasing devices\n");
+	for (i = 0; i < LP8X4X_MAX_SLOT_COUNT; i++) {
+		s = &m->slot[i];
+		if (s->model)
+			device_unregister(&s->dev);
+		iounmap(s->data_addr);
+	}
 	device_unregister(&m->dev);
 	bus_unregister(&lp8x4x_bus_type);
 
@@ -120,11 +191,36 @@ static void devm_lp8x4x_bus_release(struct device *dev, void *res)
 	iounmap(mem);
 }
 
+static void __init lp8x4x_bus_probe_slot(struct lp8x4x_master *m, int i,
+		unsigned char model)
+{
+	struct lp8x4x_slot *s = &m->slot[i];
+	int err;
+
+	dev_info(&m->dev, "found %u in slot %i\n", 8000 + model, i + 1);
+
+	s->dev.bus = &lp8x4x_bus_type;
+	dev_set_name(&s->dev, "slot%02i", i + 1);
+	s->dev.parent = &m->dev;
+	s->dev.release = lp8x4x_slot_release;
+	s->dev.groups = slot_dev_groups;
+	s->model = model;
+
+	err = device_register(&s->dev);
+	if (err < 0) {
+		dev_err(&s->dev, "failed to register device\n");
+		s->model = 0;
+		return;
+	}
+}
+
 static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 {
 	struct lp8x4x_master *m, **p;
 	struct resource *res;
+	int i;
 	int err = 0;
+	unsigned int model;
 
 	m = kzalloc(sizeof(*m), GFP_KERNEL);
 	if (!m)
@@ -167,6 +263,30 @@ static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 		goto err3;
 	}
 
+	for (i = 0; i < LP8X4X_MAX_SLOT_COUNT; i++) {
+		res = platform_get_resource(pdev, IORESOURCE_MEM, i + 2);
+		if (!res) {
+			dev_err(&pdev->dev, "Failed to get slot %i address\n",
+					i);
+			err = -ENODEV;
+			goto err4;
+		}
+
+		m->slot[i].data_addr = ioremap(res->start, resource_size(res));
+		if (!m->slot[i].data_addr) {
+			dev_err(&pdev->dev, "Failed to ioremap %p\n",
+					m->slot[i].data_addr);
+			err = -EFAULT;
+			goto err4;
+		}
+		continue;
+err4:
+		for (i--; i >= 0; i--)
+			iounmap(m->slot[i].data_addr);
+
+		goto err3;
+	}
+
 	m->slot_count = ioread8(m->count_addr);
 	switch (m->slot_count) {
 	case 1:
@@ -205,6 +325,13 @@ static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 	}
 
 	devres_add(&pdev->dev, p);
+	for (i = 0; i < LP8X4X_MAX_SLOT_COUNT; i++) {
+		model = lp8x4x_model[ioread8(m->slot[i].data_addr)];
+		if (!model)
+			continue;
+
+		lp8x4x_bus_probe_slot(m, i, model);
+	}
 	return 0;
 
 err_dev:
-- 
1.8.4.2


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

* [PATCH 08/11] misc: support for parallel slots in LP-8x4x
@ 2013-12-01  6:26   ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-01  6:26 UTC (permalink / raw)
  To: linux-arm-kernel

This patch enumerates parallel modules in expansion slots and exposes
model numbers via sysfs.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
 Documentation/misc-devices/lp8x4x_bus.txt |   8 ++
 arch/arm/mach-pxa/include/mach/lp8x4x.h   |   8 ++
 arch/arm/mach-pxa/lp8x4x.c                |  42 +++++++++-
 drivers/misc/lp8x4x_bus.c                 | 127 ++++++++++++++++++++++++++++++
 4 files changed, 184 insertions(+), 1 deletion(-)

diff --git a/Documentation/misc-devices/lp8x4x_bus.txt b/Documentation/misc-devices/lp8x4x_bus.txt
index d9a069d..9285fdc 100644
--- a/Documentation/misc-devices/lp8x4x_bus.txt
+++ b/Documentation/misc-devices/lp8x4x_bus.txt
@@ -28,6 +28,9 @@ into the device, they could be accessed using the 2nd PXA built-in UART port
 (/dev/ttySA1). However, it seems that addresses are not processed by
 the modules. So the parallel bus needs to select which slot is connected.
 
+Parallel modules allow much faster communication. There are accessed using
+IO memory through the FPGA. Their ports are exposed via sysfs.
+
 SYSFS
 -----
 
@@ -41,3 +44,8 @@ active_slot
 	     is a parallel module in the selected slot, it simply ignores
 	     incoming packets. So it is safe to activate any available
 	     slot.
+
+/sys/bus/icpdas/devices/slot%02i:
+
+model
+	RO - shows expansion module model number
diff --git a/arch/arm/mach-pxa/include/mach/lp8x4x.h b/arch/arm/mach-pxa/include/mach/lp8x4x.h
index 9addfa8..e1005c5 100644
--- a/arch/arm/mach-pxa/include/mach/lp8x4x.h
+++ b/arch/arm/mach-pxa/include/mach/lp8x4x.h
@@ -37,6 +37,14 @@
 
 /* board level registers in the FPGA */
 
+#define LP8X4X_SLOT1_IO		0x17001000
+#define LP8X4X_SLOT2_IO		0x17002000
+#define LP8X4X_SLOT3_IO		0x17003000
+#define LP8X4X_SLOT4_IO		0x17004000
+#define LP8X4X_SLOT5_IO		0x17005000
+#define LP8X4X_SLOT6_IO		0x17006000
+#define LP8X4X_SLOT7_IO		0x17007000
+#define LP8X4X_SLOT8_IO		0x17008000
 #define LP8X4X_SLOT_SWITCH	0x17009004
 #define LP8X4X_EOI		LP8X4X_P2V(0x17009006)
 #define LP8X4X_INSINT		LP8X4X_P2V(0x17009008)
diff --git a/arch/arm/mach-pxa/lp8x4x.c b/arch/arm/mach-pxa/lp8x4x.c
index b30343d..ae84d36 100644
--- a/arch/arm/mach-pxa/lp8x4x.c
+++ b/arch/arm/mach-pxa/lp8x4x.c
@@ -429,6 +429,46 @@ static struct resource lp8x4x_bus_resources[] = {
 		.end    = LP8X4X_SLOT_SWITCH,
 		.flags  = IORESOURCE_MEM,
 	},
+	[2] = {
+		.start  = LP8X4X_SLOT1_IO,
+		.end    = LP8X4X_SLOT1_IO + 15,
+		.flags  = IORESOURCE_MEM,
+	},
+	[3] = {
+		.start  = LP8X4X_SLOT2_IO,
+		.end    = LP8X4X_SLOT2_IO + 15,
+		.flags  = IORESOURCE_MEM,
+	},
+	[4] = {
+		.start  = LP8X4X_SLOT3_IO,
+		.end    = LP8X4X_SLOT3_IO + 15,
+		.flags  = IORESOURCE_MEM,
+	},
+	[5] = {
+		.start  = LP8X4X_SLOT4_IO,
+		.end    = LP8X4X_SLOT4_IO + 15,
+		.flags  = IORESOURCE_MEM,
+	},
+	[6] = {
+		.start  = LP8X4X_SLOT5_IO,
+		.end    = LP8X4X_SLOT5_IO + 15,
+		.flags  = IORESOURCE_MEM,
+	},
+	[7] = {
+		.start  = LP8X4X_SLOT6_IO,
+		.end    = LP8X4X_SLOT6_IO + 15,
+		.flags  = IORESOURCE_MEM,
+	},
+	[8] = {
+		.start  = LP8X4X_SLOT7_IO,
+		.end    = LP8X4X_SLOT7_IO + 15,
+		.flags  = IORESOURCE_MEM,
+	},
+	[9] = {
+		.start  = LP8X4X_SLOT8_IO,
+		.end    = LP8X4X_SLOT8_IO + 15,
+		.flags  = IORESOURCE_MEM,
+	},
 };
 
 static struct platform_device lp8x4x_bus_device[] = {
@@ -436,7 +476,7 @@ static struct platform_device lp8x4x_bus_device[] = {
 		.name           = "lp8x4x-bus",
 		.id             = 0,
 		.resource = &lp8x4x_bus_resources[0],
-		.num_resources = 2,
+		.num_resources = 10,
 	},
 };
 
diff --git a/drivers/misc/lp8x4x_bus.c b/drivers/misc/lp8x4x_bus.c
index 647fde7..b2d4a04 100644
--- a/drivers/misc/lp8x4x_bus.c
+++ b/drivers/misc/lp8x4x_bus.c
@@ -24,14 +24,57 @@ MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Sergei Ianovich <ynvich@gmail.com>");
 MODULE_DESCRIPTION("ICP DAS LP-8x4x parallel bus driver");
 
+struct lp8x4x_slot {
+	void			*data_addr;
+	unsigned int		model;
+	struct device		dev;
+};
+
+#define LP8X4X_MAX_SLOT_COUNT	8
 struct lp8x4x_master {
 	unsigned int		slot_count;
 	void			*count_addr;
 	unsigned int		active_slot;
 	void			*switch_addr;
+	struct lp8x4x_slot	slot[LP8X4X_MAX_SLOT_COUNT];
 	struct device		dev;
 };
 
+static unsigned char lp8x4x_model[256] = {
+	   0,    0,    0, 0x11,    0, 0x18, 0x13, 0x11,
+	0x0e, 0x11,    0,    0,    0, 0x5a, 0x5b, 0x5c,
+	0x3c, 0x44, 0x34, 0x3a, 0x39, 0x36, 0x37, 0x33,
+	0x35, 0x40, 0x41, 0x42, 0x38, 0x3f, 0x32, 0x45,
+	0xac, 0x70, 0x8e, 0x8e, 0x1e, 0x72, 0x90, 0x29,
+	0x4a, 0x22, 0xd3, 0xd2, 0x28, 0x25, 0x2a, 0x29,
+	0x48, 0x49, 0x5d, 0x1f, 0x20, 0x23, 0x24, 0x4d,
+	0x3d, 0x3e,    0,    0,    0,    0,    0,    0,
+	   0, 0x78, 0x72, 0x2b, 0x5e, 0x5e, 0x36, 0xae,
+	0x30,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0, 0x5c, 0x5e,    0, 0x5e,    0,    0,
+	   0, 0x3b,    0,    0,    0,    0,    0,    0,
+	   0, 0x50, 0x2e,    0, 0x58,    0,    0, 0x43,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0, 0x54,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0
+};
+
 static int lp8x4x_match(struct device *dev, struct device_driver *drv)
 {
 	return 1;
@@ -42,6 +85,26 @@ static struct bus_type lp8x4x_bus_type = {
 	.match		= lp8x4x_match,
 };
 
+static void lp8x4x_slot_release(struct device *dev)
+{
+}
+
+static ssize_t model_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct lp8x4x_slot *s = container_of(dev, struct lp8x4x_slot, dev);
+
+	return sprintf(buf, "%u\n", s->model + 8000);
+}
+
+static DEVICE_ATTR_RO(model);
+
+static struct attribute *slot_dev_attrs[] = {
+	&dev_attr_model.attr,
+	NULL,
+};
+ATTRIBUTE_GROUPS(slot_dev);
+
 static void lp8x4x_master_release(struct device *dev)
 {
 	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
@@ -107,10 +170,18 @@ ATTRIBUTE_GROUPS(master_dev);
 static void devm_lp8x4x_bus_release(struct device *dev, void *res)
 {
 	struct lp8x4x_master *m = *(struct lp8x4x_master **)res;
+	struct lp8x4x_slot *s;
 	void *mem = m->count_addr;
 	void *mem2 = m->switch_addr;
+	int i;
 
 	dev_info(dev, "releasing devices\n");
+	for (i = 0; i < LP8X4X_MAX_SLOT_COUNT; i++) {
+		s = &m->slot[i];
+		if (s->model)
+			device_unregister(&s->dev);
+		iounmap(s->data_addr);
+	}
 	device_unregister(&m->dev);
 	bus_unregister(&lp8x4x_bus_type);
 
@@ -120,11 +191,36 @@ static void devm_lp8x4x_bus_release(struct device *dev, void *res)
 	iounmap(mem);
 }
 
+static void __init lp8x4x_bus_probe_slot(struct lp8x4x_master *m, int i,
+		unsigned char model)
+{
+	struct lp8x4x_slot *s = &m->slot[i];
+	int err;
+
+	dev_info(&m->dev, "found %u in slot %i\n", 8000 + model, i + 1);
+
+	s->dev.bus = &lp8x4x_bus_type;
+	dev_set_name(&s->dev, "slot%02i", i + 1);
+	s->dev.parent = &m->dev;
+	s->dev.release = lp8x4x_slot_release;
+	s->dev.groups = slot_dev_groups;
+	s->model = model;
+
+	err = device_register(&s->dev);
+	if (err < 0) {
+		dev_err(&s->dev, "failed to register device\n");
+		s->model = 0;
+		return;
+	}
+}
+
 static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 {
 	struct lp8x4x_master *m, **p;
 	struct resource *res;
+	int i;
 	int err = 0;
+	unsigned int model;
 
 	m = kzalloc(sizeof(*m), GFP_KERNEL);
 	if (!m)
@@ -167,6 +263,30 @@ static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 		goto err3;
 	}
 
+	for (i = 0; i < LP8X4X_MAX_SLOT_COUNT; i++) {
+		res = platform_get_resource(pdev, IORESOURCE_MEM, i + 2);
+		if (!res) {
+			dev_err(&pdev->dev, "Failed to get slot %i address\n",
+					i);
+			err = -ENODEV;
+			goto err4;
+		}
+
+		m->slot[i].data_addr = ioremap(res->start, resource_size(res));
+		if (!m->slot[i].data_addr) {
+			dev_err(&pdev->dev, "Failed to ioremap %p\n",
+					m->slot[i].data_addr);
+			err = -EFAULT;
+			goto err4;
+		}
+		continue;
+err4:
+		for (i--; i >= 0; i--)
+			iounmap(m->slot[i].data_addr);
+
+		goto err3;
+	}
+
 	m->slot_count = ioread8(m->count_addr);
 	switch (m->slot_count) {
 	case 1:
@@ -205,6 +325,13 @@ static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 	}
 
 	devres_add(&pdev->dev, p);
+	for (i = 0; i < LP8X4X_MAX_SLOT_COUNT; i++) {
+		model = lp8x4x_model[ioread8(m->slot[i].data_addr)];
+		if (!model)
+			continue;
+
+		lp8x4x_bus_probe_slot(m, i, model);
+	}
 	return 0;
 
 err_dev:
-- 
1.8.4.2

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

* [PATCH 09/11] misc: support for I-8041 in LP-8x4x
  2013-12-01  6:26 ` Sergei Ianovich
@ 2013-12-01  6:26   ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-01  6:26 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Rob Landley, Arnd Bergmann, Greg Kroah-Hartman,
	open list:DOCUMENTATION

Status of I-8041 32 digital output channels can be managed via
sysfs now.

http://www.icpdas.com/products/Remote_IO/i-8ke/i-8041w.htm

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
 Documentation/misc-devices/lp8x4x_bus.txt |  4 ++
 drivers/misc/lp8x4x_bus.c                 | 67 ++++++++++++++++++++++++++++++-
 2 files changed, 69 insertions(+), 2 deletions(-)

diff --git a/Documentation/misc-devices/lp8x4x_bus.txt b/Documentation/misc-devices/lp8x4x_bus.txt
index 9285fdc..74df10b 100644
--- a/Documentation/misc-devices/lp8x4x_bus.txt
+++ b/Documentation/misc-devices/lp8x4x_bus.txt
@@ -49,3 +49,7 @@ active_slot
 
 model
 	RO - shows expansion module model number
+
+output_status
+	RW - set status of digital output channels on the module in
+	     the expansion slot. Value can be read back.
diff --git a/drivers/misc/lp8x4x_bus.c b/drivers/misc/lp8x4x_bus.c
index b2d4a04..d177735 100644
--- a/drivers/misc/lp8x4x_bus.c
+++ b/drivers/misc/lp8x4x_bus.c
@@ -27,6 +27,9 @@ MODULE_DESCRIPTION("ICP DAS LP-8x4x parallel bus driver");
 struct lp8x4x_slot {
 	void			*data_addr;
 	unsigned int		model;
+	struct mutex		lock;
+	unsigned int		DO_len;
+	u32			DO;
 	struct device		dev;
 };
 
@@ -89,6 +92,45 @@ static void lp8x4x_slot_release(struct device *dev)
 {
 }
 
+static void lp8x4x_slot_set_DO(struct lp8x4x_slot *s)
+{
+	int i;
+	mutex_lock(&s->lock);
+	for (i = 0; i < s->DO_len; i++)
+		iowrite8((s->DO >> (i * 8)) & 0xff, s->data_addr + 2 * i);
+	mutex_unlock(&s->lock);
+}
+
+static ssize_t output_status_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct lp8x4x_slot *s = container_of(dev, struct lp8x4x_slot, dev);
+
+	return sprintf(buf, "0x%08x\n", s->DO);
+}
+
+static ssize_t output_status_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct lp8x4x_slot *s = container_of(dev, struct lp8x4x_slot, dev);
+
+	if (!buf)
+		return count;
+	if (0 == count)
+		return count;
+
+	if (kstrtouint(buf, 16, &s->DO) != 0) {
+		dev_err(dev, "bad input\n");
+		return count;
+	}
+
+	lp8x4x_slot_set_DO(s);
+
+	return count;
+}
+
+static DEVICE_ATTR_RW(output_status);
+
 static ssize_t model_show(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
@@ -105,6 +147,13 @@ static struct attribute *slot_dev_attrs[] = {
 };
 ATTRIBUTE_GROUPS(slot_dev);
 
+static struct attribute *do_slot_dev_attrs[] = {
+	&dev_attr_model.attr,
+	&dev_attr_output_status.attr,
+	NULL,
+};
+ATTRIBUTE_GROUPS(do_slot_dev);
+
 static void lp8x4x_master_release(struct device *dev)
 {
 	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
@@ -178,8 +227,10 @@ static void devm_lp8x4x_bus_release(struct device *dev, void *res)
 	dev_info(dev, "releasing devices\n");
 	for (i = 0; i < LP8X4X_MAX_SLOT_COUNT; i++) {
 		s = &m->slot[i];
-		if (s->model)
+		if (s->model) {
 			device_unregister(&s->dev);
+			mutex_destroy(&s->lock);
+		}
 		iounmap(s->data_addr);
 	}
 	device_unregister(&m->dev);
@@ -203,13 +254,25 @@ static void __init lp8x4x_bus_probe_slot(struct lp8x4x_master *m, int i,
 	dev_set_name(&s->dev, "slot%02i", i + 1);
 	s->dev.parent = &m->dev;
 	s->dev.release = lp8x4x_slot_release;
-	s->dev.groups = slot_dev_groups;
 	s->model = model;
+	mutex_init(&s->lock);
+
+	switch (model) {
+	case 41:
+		s->DO_len = 4;
+		lp8x4x_slot_set_DO(s);
+		s->dev.groups = do_slot_dev_groups;
+		break;
+	default:
+		s->dev.groups = slot_dev_groups;
+		break;
+	};
 
 	err = device_register(&s->dev);
 	if (err < 0) {
 		dev_err(&s->dev, "failed to register device\n");
 		s->model = 0;
+		mutex_destroy(&s->lock);
 		return;
 	}
 }
-- 
1.8.4.2


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

* [PATCH 09/11] misc: support for I-8041 in LP-8x4x
@ 2013-12-01  6:26   ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-01  6:26 UTC (permalink / raw)
  To: linux-arm-kernel

Status of I-8041 32 digital output channels can be managed via
sysfs now.

http://www.icpdas.com/products/Remote_IO/i-8ke/i-8041w.htm

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
 Documentation/misc-devices/lp8x4x_bus.txt |  4 ++
 drivers/misc/lp8x4x_bus.c                 | 67 ++++++++++++++++++++++++++++++-
 2 files changed, 69 insertions(+), 2 deletions(-)

diff --git a/Documentation/misc-devices/lp8x4x_bus.txt b/Documentation/misc-devices/lp8x4x_bus.txt
index 9285fdc..74df10b 100644
--- a/Documentation/misc-devices/lp8x4x_bus.txt
+++ b/Documentation/misc-devices/lp8x4x_bus.txt
@@ -49,3 +49,7 @@ active_slot
 
 model
 	RO - shows expansion module model number
+
+output_status
+	RW - set status of digital output channels on the module in
+	     the expansion slot. Value can be read back.
diff --git a/drivers/misc/lp8x4x_bus.c b/drivers/misc/lp8x4x_bus.c
index b2d4a04..d177735 100644
--- a/drivers/misc/lp8x4x_bus.c
+++ b/drivers/misc/lp8x4x_bus.c
@@ -27,6 +27,9 @@ MODULE_DESCRIPTION("ICP DAS LP-8x4x parallel bus driver");
 struct lp8x4x_slot {
 	void			*data_addr;
 	unsigned int		model;
+	struct mutex		lock;
+	unsigned int		DO_len;
+	u32			DO;
 	struct device		dev;
 };
 
@@ -89,6 +92,45 @@ static void lp8x4x_slot_release(struct device *dev)
 {
 }
 
+static void lp8x4x_slot_set_DO(struct lp8x4x_slot *s)
+{
+	int i;
+	mutex_lock(&s->lock);
+	for (i = 0; i < s->DO_len; i++)
+		iowrite8((s->DO >> (i * 8)) & 0xff, s->data_addr + 2 * i);
+	mutex_unlock(&s->lock);
+}
+
+static ssize_t output_status_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct lp8x4x_slot *s = container_of(dev, struct lp8x4x_slot, dev);
+
+	return sprintf(buf, "0x%08x\n", s->DO);
+}
+
+static ssize_t output_status_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct lp8x4x_slot *s = container_of(dev, struct lp8x4x_slot, dev);
+
+	if (!buf)
+		return count;
+	if (0 == count)
+		return count;
+
+	if (kstrtouint(buf, 16, &s->DO) != 0) {
+		dev_err(dev, "bad input\n");
+		return count;
+	}
+
+	lp8x4x_slot_set_DO(s);
+
+	return count;
+}
+
+static DEVICE_ATTR_RW(output_status);
+
 static ssize_t model_show(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
@@ -105,6 +147,13 @@ static struct attribute *slot_dev_attrs[] = {
 };
 ATTRIBUTE_GROUPS(slot_dev);
 
+static struct attribute *do_slot_dev_attrs[] = {
+	&dev_attr_model.attr,
+	&dev_attr_output_status.attr,
+	NULL,
+};
+ATTRIBUTE_GROUPS(do_slot_dev);
+
 static void lp8x4x_master_release(struct device *dev)
 {
 	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
@@ -178,8 +227,10 @@ static void devm_lp8x4x_bus_release(struct device *dev, void *res)
 	dev_info(dev, "releasing devices\n");
 	for (i = 0; i < LP8X4X_MAX_SLOT_COUNT; i++) {
 		s = &m->slot[i];
-		if (s->model)
+		if (s->model) {
 			device_unregister(&s->dev);
+			mutex_destroy(&s->lock);
+		}
 		iounmap(s->data_addr);
 	}
 	device_unregister(&m->dev);
@@ -203,13 +254,25 @@ static void __init lp8x4x_bus_probe_slot(struct lp8x4x_master *m, int i,
 	dev_set_name(&s->dev, "slot%02i", i + 1);
 	s->dev.parent = &m->dev;
 	s->dev.release = lp8x4x_slot_release;
-	s->dev.groups = slot_dev_groups;
 	s->model = model;
+	mutex_init(&s->lock);
+
+	switch (model) {
+	case 41:
+		s->DO_len = 4;
+		lp8x4x_slot_set_DO(s);
+		s->dev.groups = do_slot_dev_groups;
+		break;
+	default:
+		s->dev.groups = slot_dev_groups;
+		break;
+	};
 
 	err = device_register(&s->dev);
 	if (err < 0) {
 		dev_err(&s->dev, "failed to register device\n");
 		s->model = 0;
+		mutex_destroy(&s->lock);
 		return;
 	}
 }
-- 
1.8.4.2

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

* [PATCH 10/11] misc: support for I-8042 in LP-8x4x
  2013-12-01  6:26 ` Sergei Ianovich
@ 2013-12-01  6:26   ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-01  6:26 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Rob Landley, Arnd Bergmann, Greg Kroah-Hartman,
	open list:DOCUMENTATION

Status of I-8042 16 digital output channels can be managed via
sysfs.

Status of I-8042 16 digital input channels can be read via sysfs.

http://www.icpdas.com/products/Remote_IO/i-8ke/i-8042w.htm

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
 Documentation/misc-devices/lp8x4x_bus.txt |  4 ++
 drivers/misc/lp8x4x_bus.c                 | 76 ++++++++++++++++++++++++++++++-
 2 files changed, 78 insertions(+), 2 deletions(-)

diff --git a/Documentation/misc-devices/lp8x4x_bus.txt b/Documentation/misc-devices/lp8x4x_bus.txt
index 74df10b..e3a8bcf 100644
--- a/Documentation/misc-devices/lp8x4x_bus.txt
+++ b/Documentation/misc-devices/lp8x4x_bus.txt
@@ -50,6 +50,10 @@ active_slot
 model
 	RO - shows expansion module model number
 
+input_status
+	RO - get status of digital input channels on the module in
+	     the expansion slot.
+
 output_status
 	RW - set status of digital output channels on the module in
 	     the expansion slot. Value can be read back.
diff --git a/drivers/misc/lp8x4x_bus.c b/drivers/misc/lp8x4x_bus.c
index d177735..fce11c4 100644
--- a/drivers/misc/lp8x4x_bus.c
+++ b/drivers/misc/lp8x4x_bus.c
@@ -30,6 +30,8 @@ struct lp8x4x_slot {
 	struct mutex		lock;
 	unsigned int		DO_len;
 	u32			DO;
+	unsigned int		DI_len;
+	u32			DI;
 	struct device		dev;
 };
 
@@ -92,6 +94,21 @@ static void lp8x4x_slot_release(struct device *dev)
 {
 }
 
+static void lp8x4x_slot_get_DI(struct lp8x4x_slot *s)
+{
+	int i;
+	u32 b;
+
+	mutex_lock(&s->lock);
+	s->DI = 0;
+	for (i = 0; i < s->DI_len; i++) {
+		b = ioread8(s->data_addr + 2 * (i + 1));
+		b ^= 0xff;
+		s->DI += b << (i * 8);
+	}
+	mutex_unlock(&s->lock);
+}
+
 static void lp8x4x_slot_set_DO(struct lp8x4x_slot *s)
 {
 	int i;
@@ -101,29 +118,70 @@ static void lp8x4x_slot_set_DO(struct lp8x4x_slot *s)
 	mutex_unlock(&s->lock);
 }
 
+static ssize_t input_status_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct lp8x4x_slot *s = container_of(dev, struct lp8x4x_slot, dev);
+
+	lp8x4x_slot_get_DI(s);
+	switch (s->DI_len) {
+	case 4:
+		return sprintf(buf, "0x%08x\n", s->DI);
+	case 2:
+		return sprintf(buf, "0x%04x\n", s->DI);
+	case 1:
+		return sprintf(buf, "0x%02x\n", s->DI);
+	default:
+		break;
+	}
+	return sprintf(buf, "0x%x\n", s->DI);
+}
+
+static DEVICE_ATTR_RO(input_status);
+
 static ssize_t output_status_show(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
 	struct lp8x4x_slot *s = container_of(dev, struct lp8x4x_slot, dev);
 
-	return sprintf(buf, "0x%08x\n", s->DO);
+	switch (s->DO_len) {
+	case 4:
+		return sprintf(buf, "0x%08x\n", s->DO);
+	case 2:
+		return sprintf(buf, "0x%04x\n", s->DO);
+	case 1:
+		return sprintf(buf, "0x%02x\n", s->DO);
+	default:
+		break;
+	}
+	return sprintf(buf, "0x%x\n", s->DO);
 }
 
 static ssize_t output_status_store(struct device *dev,
 		struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct lp8x4x_slot *s = container_of(dev, struct lp8x4x_slot, dev);
+	u32 DO;
+	u8 *b = (void *) &DO;
+	int i;
 
 	if (!buf)
 		return count;
 	if (0 == count)
 		return count;
 
-	if (kstrtouint(buf, 16, &s->DO) != 0) {
+	if (kstrtouint(buf, 16, &DO) != 0) {
 		dev_err(dev, "bad input\n");
 		return count;
 	}
 
+	for (i = 4; i > s->DO_len; i--)
+		if (b[i - 1] != 0) {
+			dev_err(dev, "bad input\n");
+			return count;
+		}
+
+	s->DO = DO;
 	lp8x4x_slot_set_DO(s);
 
 	return count;
@@ -154,6 +212,14 @@ static struct attribute *do_slot_dev_attrs[] = {
 };
 ATTRIBUTE_GROUPS(do_slot_dev);
 
+static struct attribute *dio_slot_dev_attrs[] = {
+	&dev_attr_model.attr,
+	&dev_attr_output_status.attr,
+	&dev_attr_input_status.attr,
+	NULL,
+};
+ATTRIBUTE_GROUPS(dio_slot_dev);
+
 static void lp8x4x_master_release(struct device *dev)
 {
 	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
@@ -263,6 +329,12 @@ static void __init lp8x4x_bus_probe_slot(struct lp8x4x_master *m, int i,
 		lp8x4x_slot_set_DO(s);
 		s->dev.groups = do_slot_dev_groups;
 		break;
+	case 42:
+		s->DI_len = 2;
+		s->DO_len = 2;
+		lp8x4x_slot_set_DO(s);
+		s->dev.groups = dio_slot_dev_groups;
+		break;
 	default:
 		s->dev.groups = slot_dev_groups;
 		break;
-- 
1.8.4.2


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

* [PATCH 10/11] misc: support for I-8042 in LP-8x4x
@ 2013-12-01  6:26   ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-01  6:26 UTC (permalink / raw)
  To: linux-arm-kernel

Status of I-8042 16 digital output channels can be managed via
sysfs.

Status of I-8042 16 digital input channels can be read via sysfs.

http://www.icpdas.com/products/Remote_IO/i-8ke/i-8042w.htm

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
 Documentation/misc-devices/lp8x4x_bus.txt |  4 ++
 drivers/misc/lp8x4x_bus.c                 | 76 ++++++++++++++++++++++++++++++-
 2 files changed, 78 insertions(+), 2 deletions(-)

diff --git a/Documentation/misc-devices/lp8x4x_bus.txt b/Documentation/misc-devices/lp8x4x_bus.txt
index 74df10b..e3a8bcf 100644
--- a/Documentation/misc-devices/lp8x4x_bus.txt
+++ b/Documentation/misc-devices/lp8x4x_bus.txt
@@ -50,6 +50,10 @@ active_slot
 model
 	RO - shows expansion module model number
 
+input_status
+	RO - get status of digital input channels on the module in
+	     the expansion slot.
+
 output_status
 	RW - set status of digital output channels on the module in
 	     the expansion slot. Value can be read back.
diff --git a/drivers/misc/lp8x4x_bus.c b/drivers/misc/lp8x4x_bus.c
index d177735..fce11c4 100644
--- a/drivers/misc/lp8x4x_bus.c
+++ b/drivers/misc/lp8x4x_bus.c
@@ -30,6 +30,8 @@ struct lp8x4x_slot {
 	struct mutex		lock;
 	unsigned int		DO_len;
 	u32			DO;
+	unsigned int		DI_len;
+	u32			DI;
 	struct device		dev;
 };
 
@@ -92,6 +94,21 @@ static void lp8x4x_slot_release(struct device *dev)
 {
 }
 
+static void lp8x4x_slot_get_DI(struct lp8x4x_slot *s)
+{
+	int i;
+	u32 b;
+
+	mutex_lock(&s->lock);
+	s->DI = 0;
+	for (i = 0; i < s->DI_len; i++) {
+		b = ioread8(s->data_addr + 2 * (i + 1));
+		b ^= 0xff;
+		s->DI += b << (i * 8);
+	}
+	mutex_unlock(&s->lock);
+}
+
 static void lp8x4x_slot_set_DO(struct lp8x4x_slot *s)
 {
 	int i;
@@ -101,29 +118,70 @@ static void lp8x4x_slot_set_DO(struct lp8x4x_slot *s)
 	mutex_unlock(&s->lock);
 }
 
+static ssize_t input_status_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct lp8x4x_slot *s = container_of(dev, struct lp8x4x_slot, dev);
+
+	lp8x4x_slot_get_DI(s);
+	switch (s->DI_len) {
+	case 4:
+		return sprintf(buf, "0x%08x\n", s->DI);
+	case 2:
+		return sprintf(buf, "0x%04x\n", s->DI);
+	case 1:
+		return sprintf(buf, "0x%02x\n", s->DI);
+	default:
+		break;
+	}
+	return sprintf(buf, "0x%x\n", s->DI);
+}
+
+static DEVICE_ATTR_RO(input_status);
+
 static ssize_t output_status_show(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
 	struct lp8x4x_slot *s = container_of(dev, struct lp8x4x_slot, dev);
 
-	return sprintf(buf, "0x%08x\n", s->DO);
+	switch (s->DO_len) {
+	case 4:
+		return sprintf(buf, "0x%08x\n", s->DO);
+	case 2:
+		return sprintf(buf, "0x%04x\n", s->DO);
+	case 1:
+		return sprintf(buf, "0x%02x\n", s->DO);
+	default:
+		break;
+	}
+	return sprintf(buf, "0x%x\n", s->DO);
 }
 
 static ssize_t output_status_store(struct device *dev,
 		struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct lp8x4x_slot *s = container_of(dev, struct lp8x4x_slot, dev);
+	u32 DO;
+	u8 *b = (void *) &DO;
+	int i;
 
 	if (!buf)
 		return count;
 	if (0 == count)
 		return count;
 
-	if (kstrtouint(buf, 16, &s->DO) != 0) {
+	if (kstrtouint(buf, 16, &DO) != 0) {
 		dev_err(dev, "bad input\n");
 		return count;
 	}
 
+	for (i = 4; i > s->DO_len; i--)
+		if (b[i - 1] != 0) {
+			dev_err(dev, "bad input\n");
+			return count;
+		}
+
+	s->DO = DO;
 	lp8x4x_slot_set_DO(s);
 
 	return count;
@@ -154,6 +212,14 @@ static struct attribute *do_slot_dev_attrs[] = {
 };
 ATTRIBUTE_GROUPS(do_slot_dev);
 
+static struct attribute *dio_slot_dev_attrs[] = {
+	&dev_attr_model.attr,
+	&dev_attr_output_status.attr,
+	&dev_attr_input_status.attr,
+	NULL,
+};
+ATTRIBUTE_GROUPS(dio_slot_dev);
+
 static void lp8x4x_master_release(struct device *dev)
 {
 	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
@@ -263,6 +329,12 @@ static void __init lp8x4x_bus_probe_slot(struct lp8x4x_master *m, int i,
 		lp8x4x_slot_set_DO(s);
 		s->dev.groups = do_slot_dev_groups;
 		break;
+	case 42:
+		s->DI_len = 2;
+		s->DO_len = 2;
+		lp8x4x_slot_set_DO(s);
+		s->dev.groups = dio_slot_dev_groups;
+		break;
 	default:
 		s->dev.groups = slot_dev_groups;
 		break;
-- 
1.8.4.2

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

* [PATCH 11/11] misc: support for I-8024 in LP-8x4x
  2013-12-01  6:26 ` Sergei Ianovich
@ 2013-12-01  6:26   ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-01  6:26 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Rob Landley, Arnd Bergmann, Greg Kroah-Hartman,
	open list:DOCUMENTATION

Status of I-8042 4 analog output channels can be managed via
sysfs.

http://www.icpdas.com/root/product/solutions/remote_io/rs-485/i-8k_i-87k/i-8024w.html

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
 Documentation/misc-devices/lp8x4x_bus.txt | 15 ++++++
 drivers/misc/lp8x4x_bus.c                 | 89 +++++++++++++++++++++++++++++++
 2 files changed, 104 insertions(+)

diff --git a/Documentation/misc-devices/lp8x4x_bus.txt b/Documentation/misc-devices/lp8x4x_bus.txt
index e3a8bcf..08419d1 100644
--- a/Documentation/misc-devices/lp8x4x_bus.txt
+++ b/Documentation/misc-devices/lp8x4x_bus.txt
@@ -57,3 +57,18 @@ input_status
 output_status
 	RW - set status of digital output channels on the module in
 	     the expansion slot. Value can be read back.
+
+analog_output
+	RW - set status of analog output channels on the module in
+	     the expansion slot. Tested with voltage output. Bits 0-13:
+	     0x00c0 is -10.0V
+	     0x2000 is   0.0V
+	     0x3f40 is +10.0V
+
+	     So 1 unit of output is 1.25 mV.
+
+	     Bits 15 and 14 determine which channel to apply the value:
+	     0x0000 is channel 1
+	     0x4000 is channel 2
+	     0x8000 is channel 3
+	     0xc000 is channel 4
diff --git a/drivers/misc/lp8x4x_bus.c b/drivers/misc/lp8x4x_bus.c
index fce11c4..0fa13a3 100644
--- a/drivers/misc/lp8x4x_bus.c
+++ b/drivers/misc/lp8x4x_bus.c
@@ -14,6 +14,8 @@
 #include <linux/list.h>
 #include <linux/slab.h>
 #include <linux/gpio.h>
+#include <linux/sched.h>
+#include <linux/hrtimer.h>
 
 #include <mach/mfp-pxa27x.h>
 #include <mach/lp8x4x.h>
@@ -24,6 +26,7 @@ MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Sergei Ianovich <ynvich@gmail.com>");
 MODULE_DESCRIPTION("ICP DAS LP-8x4x parallel bus driver");
 
+#define LP8X4X_MAX_AO_CHANNELS	4
 struct lp8x4x_slot {
 	void			*data_addr;
 	unsigned int		model;
@@ -32,6 +35,8 @@ struct lp8x4x_slot {
 	u32			DO;
 	unsigned int		DI_len;
 	u32			DI;
+	unsigned int		AO_len;
+	u32			AO[LP8X4X_MAX_AO_CHANNELS];
 	struct device		dev;
 };
 
@@ -118,6 +123,36 @@ static void lp8x4x_slot_set_DO(struct lp8x4x_slot *s)
 	mutex_unlock(&s->lock);
 }
 
+void nsleep(unsigned long nanosec)
+{
+	ktime_t t = ns_to_ktime(nanosec);
+	long state = current->state;
+
+	__set_current_state(TASK_UNINTERRUPTIBLE);
+	schedule_hrtimeout(&t, HRTIMER_MODE_REL);
+	__set_current_state(state);
+}
+
+static void lp8x4x_slot_reset_AO(struct lp8x4x_slot *s)
+{
+	int i;
+	mutex_lock(&s->lock);
+	for (i = 0; i < s->AO_len; i++)
+		s->AO[i] = 0x2000;
+	iowrite8(0x00, s->data_addr);
+	nsleep(450);
+	iowrite8(0xff, s->data_addr);
+	mutex_unlock(&s->lock);
+}
+
+static void lp8x4x_slot_set_AO(struct lp8x4x_slot *s, u32 val)
+{
+	mutex_lock(&s->lock);
+	iowrite8(val & 0xff, s->data_addr + 2);
+	iowrite8((val >> 8) & 0xff, s->data_addr + 4);
+	mutex_unlock(&s->lock);
+}
+
 static ssize_t input_status_show(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
@@ -189,6 +224,48 @@ static ssize_t output_status_store(struct device *dev,
 
 static DEVICE_ATTR_RW(output_status);
 
+static ssize_t analog_output_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct lp8x4x_slot *s = container_of(dev, struct lp8x4x_slot, dev);
+	int i, c = 0;
+
+	for (i = 0; i < s->AO_len; i++)
+		c += sprintf(&buf[c], "0x%04x\n", s->AO[i]);
+	return c;
+}
+
+static ssize_t analog_output_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct lp8x4x_slot *s = container_of(dev, struct lp8x4x_slot, dev);
+	u32 AO;
+	int i;
+
+	if (!buf)
+		return count;
+	if (0 == count)
+		return count;
+
+	if (kstrtouint(buf, 16, &AO) != 0) {
+		dev_err(dev, "bad input\n");
+		return count;
+	}
+
+	if (AO & 0xffff0000) {
+		dev_err(dev, "bad input\n");
+		return count;
+	}
+
+	i = AO >> 14;
+	s->AO[i] = AO & 0x3fff;
+	lp8x4x_slot_set_AO(s, AO);
+
+	return count;
+}
+
+static DEVICE_ATTR_RW(analog_output);
+
 static ssize_t model_show(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
@@ -220,6 +297,13 @@ static struct attribute *dio_slot_dev_attrs[] = {
 };
 ATTRIBUTE_GROUPS(dio_slot_dev);
 
+static struct attribute *ao_slot_dev_attrs[] = {
+	&dev_attr_model.attr,
+	&dev_attr_analog_output.attr,
+	NULL,
+};
+ATTRIBUTE_GROUPS(ao_slot_dev);
+
 static void lp8x4x_master_release(struct device *dev)
 {
 	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
@@ -324,6 +408,11 @@ static void __init lp8x4x_bus_probe_slot(struct lp8x4x_master *m, int i,
 	mutex_init(&s->lock);
 
 	switch (model) {
+	case 24:
+		s->AO_len = 4;
+		lp8x4x_slot_reset_AO(s);
+		s->dev.groups = ao_slot_dev_groups;
+		break;
 	case 41:
 		s->DO_len = 4;
 		lp8x4x_slot_set_DO(s);
-- 
1.8.4.2


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

* [PATCH 11/11] misc: support for I-8024 in LP-8x4x
@ 2013-12-01  6:26   ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-01  6:26 UTC (permalink / raw)
  To: linux-arm-kernel

Status of I-8042 4 analog output channels can be managed via
sysfs.

http://www.icpdas.com/root/product/solutions/remote_io/rs-485/i-8k_i-87k/i-8024w.html

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
 Documentation/misc-devices/lp8x4x_bus.txt | 15 ++++++
 drivers/misc/lp8x4x_bus.c                 | 89 +++++++++++++++++++++++++++++++
 2 files changed, 104 insertions(+)

diff --git a/Documentation/misc-devices/lp8x4x_bus.txt b/Documentation/misc-devices/lp8x4x_bus.txt
index e3a8bcf..08419d1 100644
--- a/Documentation/misc-devices/lp8x4x_bus.txt
+++ b/Documentation/misc-devices/lp8x4x_bus.txt
@@ -57,3 +57,18 @@ input_status
 output_status
 	RW - set status of digital output channels on the module in
 	     the expansion slot. Value can be read back.
+
+analog_output
+	RW - set status of analog output channels on the module in
+	     the expansion slot. Tested with voltage output. Bits 0-13:
+	     0x00c0 is -10.0V
+	     0x2000 is   0.0V
+	     0x3f40 is +10.0V
+
+	     So 1 unit of output is 1.25 mV.
+
+	     Bits 15 and 14 determine which channel to apply the value:
+	     0x0000 is channel 1
+	     0x4000 is channel 2
+	     0x8000 is channel 3
+	     0xc000 is channel 4
diff --git a/drivers/misc/lp8x4x_bus.c b/drivers/misc/lp8x4x_bus.c
index fce11c4..0fa13a3 100644
--- a/drivers/misc/lp8x4x_bus.c
+++ b/drivers/misc/lp8x4x_bus.c
@@ -14,6 +14,8 @@
 #include <linux/list.h>
 #include <linux/slab.h>
 #include <linux/gpio.h>
+#include <linux/sched.h>
+#include <linux/hrtimer.h>
 
 #include <mach/mfp-pxa27x.h>
 #include <mach/lp8x4x.h>
@@ -24,6 +26,7 @@ MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Sergei Ianovich <ynvich@gmail.com>");
 MODULE_DESCRIPTION("ICP DAS LP-8x4x parallel bus driver");
 
+#define LP8X4X_MAX_AO_CHANNELS	4
 struct lp8x4x_slot {
 	void			*data_addr;
 	unsigned int		model;
@@ -32,6 +35,8 @@ struct lp8x4x_slot {
 	u32			DO;
 	unsigned int		DI_len;
 	u32			DI;
+	unsigned int		AO_len;
+	u32			AO[LP8X4X_MAX_AO_CHANNELS];
 	struct device		dev;
 };
 
@@ -118,6 +123,36 @@ static void lp8x4x_slot_set_DO(struct lp8x4x_slot *s)
 	mutex_unlock(&s->lock);
 }
 
+void nsleep(unsigned long nanosec)
+{
+	ktime_t t = ns_to_ktime(nanosec);
+	long state = current->state;
+
+	__set_current_state(TASK_UNINTERRUPTIBLE);
+	schedule_hrtimeout(&t, HRTIMER_MODE_REL);
+	__set_current_state(state);
+}
+
+static void lp8x4x_slot_reset_AO(struct lp8x4x_slot *s)
+{
+	int i;
+	mutex_lock(&s->lock);
+	for (i = 0; i < s->AO_len; i++)
+		s->AO[i] = 0x2000;
+	iowrite8(0x00, s->data_addr);
+	nsleep(450);
+	iowrite8(0xff, s->data_addr);
+	mutex_unlock(&s->lock);
+}
+
+static void lp8x4x_slot_set_AO(struct lp8x4x_slot *s, u32 val)
+{
+	mutex_lock(&s->lock);
+	iowrite8(val & 0xff, s->data_addr + 2);
+	iowrite8((val >> 8) & 0xff, s->data_addr + 4);
+	mutex_unlock(&s->lock);
+}
+
 static ssize_t input_status_show(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
@@ -189,6 +224,48 @@ static ssize_t output_status_store(struct device *dev,
 
 static DEVICE_ATTR_RW(output_status);
 
+static ssize_t analog_output_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct lp8x4x_slot *s = container_of(dev, struct lp8x4x_slot, dev);
+	int i, c = 0;
+
+	for (i = 0; i < s->AO_len; i++)
+		c += sprintf(&buf[c], "0x%04x\n", s->AO[i]);
+	return c;
+}
+
+static ssize_t analog_output_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct lp8x4x_slot *s = container_of(dev, struct lp8x4x_slot, dev);
+	u32 AO;
+	int i;
+
+	if (!buf)
+		return count;
+	if (0 == count)
+		return count;
+
+	if (kstrtouint(buf, 16, &AO) != 0) {
+		dev_err(dev, "bad input\n");
+		return count;
+	}
+
+	if (AO & 0xffff0000) {
+		dev_err(dev, "bad input\n");
+		return count;
+	}
+
+	i = AO >> 14;
+	s->AO[i] = AO & 0x3fff;
+	lp8x4x_slot_set_AO(s, AO);
+
+	return count;
+}
+
+static DEVICE_ATTR_RW(analog_output);
+
 static ssize_t model_show(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
@@ -220,6 +297,13 @@ static struct attribute *dio_slot_dev_attrs[] = {
 };
 ATTRIBUTE_GROUPS(dio_slot_dev);
 
+static struct attribute *ao_slot_dev_attrs[] = {
+	&dev_attr_model.attr,
+	&dev_attr_analog_output.attr,
+	NULL,
+};
+ATTRIBUTE_GROUPS(ao_slot_dev);
+
 static void lp8x4x_master_release(struct device *dev)
 {
 	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
@@ -324,6 +408,11 @@ static void __init lp8x4x_bus_probe_slot(struct lp8x4x_master *m, int i,
 	mutex_init(&s->lock);
 
 	switch (model) {
+	case 24:
+		s->AO_len = 4;
+		lp8x4x_slot_reset_AO(s);
+		s->dev.groups = ao_slot_dev_groups;
+		break;
 	case 41:
 		s->DO_len = 4;
 		lp8x4x_slot_set_DO(s);
-- 
1.8.4.2

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

* Re: [PATCH 05/11] serial: support for 16550 serial ports on LP-8x4x
  2013-12-01  6:26   ` Sergei Ianovich
@ 2013-12-02  8:48     ` Heikki Krogerus
  -1 siblings, 0 replies; 700+ messages in thread
From: Heikki Krogerus @ 2013-12-02  8:48 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: linux-kernel, linux-arm-kernel, Russell King, Eric Miao,
	Haojian Zhuang, Greg Kroah-Hartman, Jiri Slaby, Arnd Bergmann,
	open list:SERIAL DRIVERS

Hi,

On Sun, Dec 01, 2013 at 10:26:18AM +0400, Sergei Ianovich wrote:
> The patch adds support for 3 additional LP-8x4x built-in serial
> ports.
> 
> The device can also host up to 8 extension cards with 4 serial ports
> on each card for a total of 35 ports. However, I don't have
> the hardware to test extension cards, so they are not supported, yet.
> 
> Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
> ---
>  arch/arm/configs/lp8x4x_defconfig       |   1 +
>  arch/arm/mach-pxa/include/mach/lp8x4x.h |   6 ++
>  drivers/tty/serial/8250/8250_lp8x4x.c   | 181 ++++++++++++++++++++++++++++++++
>  drivers/tty/serial/8250/Kconfig         |  11 ++
>  drivers/tty/serial/8250/Makefile        |   1 +
>  5 files changed, 200 insertions(+)
>  create mode 100644 drivers/tty/serial/8250/8250_lp8x4x.c
> 
> diff --git a/arch/arm/configs/lp8x4x_defconfig b/arch/arm/configs/lp8x4x_defconfig
> index 03c85bc..d297a67 100644
> --- a/arch/arm/configs/lp8x4x_defconfig
> +++ b/arch/arm/configs/lp8x4x_defconfig
> @@ -1141,6 +1141,7 @@ CONFIG_SERIAL_8250_NR_UARTS=36
>  CONFIG_SERIAL_8250_RUNTIME_UARTS=36
>  CONFIG_SERIAL_8250_EXTENDED=y
>  CONFIG_SERIAL_8250_MANY_PORTS=y
> +CONFIG_SERIAL_8250_LP8X4X=m
>  CONFIG_SERIAL_8250_SHARE_IRQ=y
>  # CONFIG_SERIAL_8250_DETECT_IRQ is not set
>  # CONFIG_SERIAL_8250_RSA is not set
> diff --git a/arch/arm/mach-pxa/include/mach/lp8x4x.h b/arch/arm/mach-pxa/include/mach/lp8x4x.h
> index a49df22..4d5474e 100644
> --- a/arch/arm/mach-pxa/include/mach/lp8x4x.h
> +++ b/arch/arm/mach-pxa/include/mach/lp8x4x.h
> @@ -50,6 +50,12 @@
>  #define LP8X4X_CLRFALLINT	LP8X4X_P2V(0x1700901a)
>  #define LP8X4X_RWRTC		LP8X4X_P2V(0x1700901c)
>  #define LP8X4X_SRAMBANK		0x1700901e
> +#define LP8X4X_TTYS0_QUIRK	0x17009030
> +#define LP8X4X_TTYS1_QUIRK	0x17009032
> +#define LP8X4X_TTYS2_QUIRK	0x17009034
> +#define LP8X4X_TTYS0_IOMEM	0x17009050
> +#define LP8X4X_TTYS1_IOMEM	0x17009060
> +#define LP8X4X_TTYS2_IOMEM	0x17009070
>  #define LP8X4X_SRAM		0x1700a000
>  
>  /* board specific IRQs */
> diff --git a/drivers/tty/serial/8250/8250_lp8x4x.c b/drivers/tty/serial/8250/8250_lp8x4x.c
> new file mode 100644
> index 0000000..27b01f0b
> --- /dev/null
> +++ b/drivers/tty/serial/8250/8250_lp8x4x.c
> @@ -0,0 +1,181 @@
> +/*  linux/drivers/tty/serial/8250/8250_lp8x4x.c
> + *
> + *  Support for 16550 serial ports on ICP DAS LP-8x4x
> + *
> + *  Copyright (C) 2013 Sergei Ianovich <ynvich@gmail.com>
> + *  Framework taken from linux/drivers/tty/serial/8250/8250_accent.c
> + *
> + *  This program is free software; you can redistribute it and/or modify
> + *  it under the terms of the GNU General Public License version 2 as
> + *  published by the Free Software Foundation.
> + */
> +#include <linux/module.h>
> +#include <linux/init.h>
> +#include <linux/irq.h>
> +#include <linux/delay.h>
> +#include <linux/serial_8250.h>
> +#include <mach/lp8x4x.h>
> +#include <linux/io.h>
> +
> +#define QUIRK_PORT(_base, _irq)					\
> +	{							\
> +		.iobase		= _base,			\
> +		.membase	= (void *) _base,		\
> +		.mapbase	= _base,			\
> +		.irq		= _irq,				\
> +		.uartclk	= 14745600,			\
> +		.regshift	= 1,				\
> +		.iotype		= UPIO_MEM,			\
> +		.flags		= UPF_IOREMAP,			\
> +		.set_termios	= lp8x4x_set_termios,		\
> +		.serial_in	= lp8x4x_serial_in,		\
> +		.serial_out	= lp8x4x_serial_out,		\
> +	}
> +
> +static void lp8x4x_set_termios(struct uart_port *port,
> +		struct ktermios *termios, struct ktermios *old)
> +{

<snip>

> +}
> +
> +static unsigned int lp8x4x_serial_in(struct uart_port *p, int offset)
> +{
> +	unsigned int b;
> +	udelay(30);
> +	offset = offset << p->regshift;
> +	b = readb(p->membase + offset);
> +	return b;
> +}
> +
> +static void lp8x4x_serial_out(struct uart_port *p, int offset, int value)
> +{
> +	offset = offset << p->regshift;
> +	writeb(value, p->membase + offset);
> +}
> +
> +static struct plat_serial8250_port lp8x4x_data[] = {
> +	QUIRK_PORT(LP8X4X_TTYS0_IOMEM, LP8X4X_TTYS0_IRQ),
> +	QUIRK_PORT(LP8X4X_TTYS1_IOMEM, LP8X4X_TTYS1_IRQ),
> +	QUIRK_PORT(LP8X4X_TTYS2_IOMEM, LP8X4X_TTYS2_IRQ),
> +	{ },
> +};
> +
> +/* Total number of ports can be 35. The first 3 ports are on
> + * the device, the rest are on extension slots. Only the first 3
> + * require termios quirk */
> +#define LP8X4X_QUIRK_PORTS	3
> +
> +static unsigned int extra_mem[LP8X4X_QUIRK_PORTS] = {
> +	LP8X4X_TTYS0_QUIRK,
> +	LP8X4X_TTYS1_QUIRK,
> +	LP8X4X_TTYS2_QUIRK
> +};
> +
> +static int request_and_remap(int i)
> +{
> +	if (!request_mem_region(extra_mem[i], 1, "serial"))
> +		return -EBUSY;
> +
> +	lp8x4x_data[i].private_data = ioremap(extra_mem[i], 1);
> +	if (lp8x4x_data[i].private_data)
> +		return 0;
> +
> +	release_mem_region(extra_mem[i], 1);
> +	return -ENODEV;
> +}
> +
> +static void release_and_unmap(int i)
> +{
> +	iounmap((void *) lp8x4x_data[i].private_data);
> +	release_mem_region(extra_mem[i], 1);
> +}
> +
> +static struct platform_device lp8x4x_device = {
> +	.name			= "serial8250",
> +	.id			= PLAT8250_DEV_ACCENT,
> +	.dev			= {
> +		.platform_data	= lp8x4x_data,
> +	},
> +};
> +
> +static int __init lp8x4x_init(void)
> +{
> +	int i = 0;
> +	int err = 0;
> +
> +	for (i = 0; i < LP8X4X_QUIRK_PORTS; i++) {
> +		err = request_and_remap(i);
> +		if (err == 0)
> +			continue;
> +
> +		for (; i >= 0; i--)
> +			release_and_unmap(i);
> +		lp8x4x_device.dev.platform_data = NULL;
> +		return err;
> +	}
> +	return platform_device_register(&lp8x4x_device);
> +}
> +
> +module_init(lp8x4x_init);

Instead of registering a platform device for serial8250 here, you need
to simply register a platform driver for something like lp8x4x_serial.
The platform code will to registers the platform devices for it. You
will use serial8250_register_8250_port() in your probe to register a
new port. Use 8250_em.c and 8250_dw.c under drivers/tty/serial/8250/
as an example.

You don't need to introduce plat_serial8250_port so you won't need
the QUIRK_PORT stuff. You deliver the iomem and the irq as normal
resources that the driver uses when you create the platform device.
That of course also means the driver does not need to care about the
instances. The platform code will generate a platform device for as
many ports you have and set to resources accordingly.


Thanks,

-- 
heikki

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

* [PATCH 05/11] serial: support for 16550 serial ports on LP-8x4x
@ 2013-12-02  8:48     ` Heikki Krogerus
  0 siblings, 0 replies; 700+ messages in thread
From: Heikki Krogerus @ 2013-12-02  8:48 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

On Sun, Dec 01, 2013 at 10:26:18AM +0400, Sergei Ianovich wrote:
> The patch adds support for 3 additional LP-8x4x built-in serial
> ports.
> 
> The device can also host up to 8 extension cards with 4 serial ports
> on each card for a total of 35 ports. However, I don't have
> the hardware to test extension cards, so they are not supported, yet.
> 
> Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
> ---
>  arch/arm/configs/lp8x4x_defconfig       |   1 +
>  arch/arm/mach-pxa/include/mach/lp8x4x.h |   6 ++
>  drivers/tty/serial/8250/8250_lp8x4x.c   | 181 ++++++++++++++++++++++++++++++++
>  drivers/tty/serial/8250/Kconfig         |  11 ++
>  drivers/tty/serial/8250/Makefile        |   1 +
>  5 files changed, 200 insertions(+)
>  create mode 100644 drivers/tty/serial/8250/8250_lp8x4x.c
> 
> diff --git a/arch/arm/configs/lp8x4x_defconfig b/arch/arm/configs/lp8x4x_defconfig
> index 03c85bc..d297a67 100644
> --- a/arch/arm/configs/lp8x4x_defconfig
> +++ b/arch/arm/configs/lp8x4x_defconfig
> @@ -1141,6 +1141,7 @@ CONFIG_SERIAL_8250_NR_UARTS=36
>  CONFIG_SERIAL_8250_RUNTIME_UARTS=36
>  CONFIG_SERIAL_8250_EXTENDED=y
>  CONFIG_SERIAL_8250_MANY_PORTS=y
> +CONFIG_SERIAL_8250_LP8X4X=m
>  CONFIG_SERIAL_8250_SHARE_IRQ=y
>  # CONFIG_SERIAL_8250_DETECT_IRQ is not set
>  # CONFIG_SERIAL_8250_RSA is not set
> diff --git a/arch/arm/mach-pxa/include/mach/lp8x4x.h b/arch/arm/mach-pxa/include/mach/lp8x4x.h
> index a49df22..4d5474e 100644
> --- a/arch/arm/mach-pxa/include/mach/lp8x4x.h
> +++ b/arch/arm/mach-pxa/include/mach/lp8x4x.h
> @@ -50,6 +50,12 @@
>  #define LP8X4X_CLRFALLINT	LP8X4X_P2V(0x1700901a)
>  #define LP8X4X_RWRTC		LP8X4X_P2V(0x1700901c)
>  #define LP8X4X_SRAMBANK		0x1700901e
> +#define LP8X4X_TTYS0_QUIRK	0x17009030
> +#define LP8X4X_TTYS1_QUIRK	0x17009032
> +#define LP8X4X_TTYS2_QUIRK	0x17009034
> +#define LP8X4X_TTYS0_IOMEM	0x17009050
> +#define LP8X4X_TTYS1_IOMEM	0x17009060
> +#define LP8X4X_TTYS2_IOMEM	0x17009070
>  #define LP8X4X_SRAM		0x1700a000
>  
>  /* board specific IRQs */
> diff --git a/drivers/tty/serial/8250/8250_lp8x4x.c b/drivers/tty/serial/8250/8250_lp8x4x.c
> new file mode 100644
> index 0000000..27b01f0b
> --- /dev/null
> +++ b/drivers/tty/serial/8250/8250_lp8x4x.c
> @@ -0,0 +1,181 @@
> +/*  linux/drivers/tty/serial/8250/8250_lp8x4x.c
> + *
> + *  Support for 16550 serial ports on ICP DAS LP-8x4x
> + *
> + *  Copyright (C) 2013 Sergei Ianovich <ynvich@gmail.com>
> + *  Framework taken from linux/drivers/tty/serial/8250/8250_accent.c
> + *
> + *  This program is free software; you can redistribute it and/or modify
> + *  it under the terms of the GNU General Public License version 2 as
> + *  published by the Free Software Foundation.
> + */
> +#include <linux/module.h>
> +#include <linux/init.h>
> +#include <linux/irq.h>
> +#include <linux/delay.h>
> +#include <linux/serial_8250.h>
> +#include <mach/lp8x4x.h>
> +#include <linux/io.h>
> +
> +#define QUIRK_PORT(_base, _irq)					\
> +	{							\
> +		.iobase		= _base,			\
> +		.membase	= (void *) _base,		\
> +		.mapbase	= _base,			\
> +		.irq		= _irq,				\
> +		.uartclk	= 14745600,			\
> +		.regshift	= 1,				\
> +		.iotype		= UPIO_MEM,			\
> +		.flags		= UPF_IOREMAP,			\
> +		.set_termios	= lp8x4x_set_termios,		\
> +		.serial_in	= lp8x4x_serial_in,		\
> +		.serial_out	= lp8x4x_serial_out,		\
> +	}
> +
> +static void lp8x4x_set_termios(struct uart_port *port,
> +		struct ktermios *termios, struct ktermios *old)
> +{

<snip>

> +}
> +
> +static unsigned int lp8x4x_serial_in(struct uart_port *p, int offset)
> +{
> +	unsigned int b;
> +	udelay(30);
> +	offset = offset << p->regshift;
> +	b = readb(p->membase + offset);
> +	return b;
> +}
> +
> +static void lp8x4x_serial_out(struct uart_port *p, int offset, int value)
> +{
> +	offset = offset << p->regshift;
> +	writeb(value, p->membase + offset);
> +}
> +
> +static struct plat_serial8250_port lp8x4x_data[] = {
> +	QUIRK_PORT(LP8X4X_TTYS0_IOMEM, LP8X4X_TTYS0_IRQ),
> +	QUIRK_PORT(LP8X4X_TTYS1_IOMEM, LP8X4X_TTYS1_IRQ),
> +	QUIRK_PORT(LP8X4X_TTYS2_IOMEM, LP8X4X_TTYS2_IRQ),
> +	{ },
> +};
> +
> +/* Total number of ports can be 35. The first 3 ports are on
> + * the device, the rest are on extension slots. Only the first 3
> + * require termios quirk */
> +#define LP8X4X_QUIRK_PORTS	3
> +
> +static unsigned int extra_mem[LP8X4X_QUIRK_PORTS] = {
> +	LP8X4X_TTYS0_QUIRK,
> +	LP8X4X_TTYS1_QUIRK,
> +	LP8X4X_TTYS2_QUIRK
> +};
> +
> +static int request_and_remap(int i)
> +{
> +	if (!request_mem_region(extra_mem[i], 1, "serial"))
> +		return -EBUSY;
> +
> +	lp8x4x_data[i].private_data = ioremap(extra_mem[i], 1);
> +	if (lp8x4x_data[i].private_data)
> +		return 0;
> +
> +	release_mem_region(extra_mem[i], 1);
> +	return -ENODEV;
> +}
> +
> +static void release_and_unmap(int i)
> +{
> +	iounmap((void *) lp8x4x_data[i].private_data);
> +	release_mem_region(extra_mem[i], 1);
> +}
> +
> +static struct platform_device lp8x4x_device = {
> +	.name			= "serial8250",
> +	.id			= PLAT8250_DEV_ACCENT,
> +	.dev			= {
> +		.platform_data	= lp8x4x_data,
> +	},
> +};
> +
> +static int __init lp8x4x_init(void)
> +{
> +	int i = 0;
> +	int err = 0;
> +
> +	for (i = 0; i < LP8X4X_QUIRK_PORTS; i++) {
> +		err = request_and_remap(i);
> +		if (err == 0)
> +			continue;
> +
> +		for (; i >= 0; i--)
> +			release_and_unmap(i);
> +		lp8x4x_device.dev.platform_data = NULL;
> +		return err;
> +	}
> +	return platform_device_register(&lp8x4x_device);
> +}
> +
> +module_init(lp8x4x_init);

Instead of registering a platform device for serial8250 here, you need
to simply register a platform driver for something like lp8x4x_serial.
The platform code will to registers the platform devices for it. You
will use serial8250_register_8250_port() in your probe to register a
new port. Use 8250_em.c and 8250_dw.c under drivers/tty/serial/8250/
as an example.

You don't need to introduce plat_serial8250_port so you won't need
the QUIRK_PORT stuff. You deliver the iomem and the irq as normal
resources that the driver uses when you create the platform device.
That of course also means the driver does not need to care about the
instances. The platform code will generate a platform device for as
many ports you have and set to resources accordingly.


Thanks,

-- 
heikki

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

* Re: [PATCH 01/11] resolve PXA<->8250 serial device address conflict
  2013-12-01  6:26   ` Sergei Ianovich
@ 2013-12-02  9:02     ` Heikki Krogerus
  -1 siblings, 0 replies; 700+ messages in thread
From: Heikki Krogerus @ 2013-12-02  9:02 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: linux-kernel, linux-arm-kernel, Greg Kroah-Hartman, Jiri Slaby,
	open list:SERIAL DRIVERS

Hi,

On Sun, Dec 01, 2013 at 10:26:14AM +0400, Sergei Ianovich wrote:
> PXA serial ports have "standard" UART names (ttyS[0-3]), major
> device number (4) and first minor device number (64) by default.
> 
> If the system has extra 8250 serial port hardware in addition
> to onboard PXA serial ports, default settings produce a device
> allocation conflict.
> 
> The patch provides a configuration option which can move onboard
> ports out of the way of 8250_core by assigning a different (204)
> major number and corresponding device names (ttySA[0-3]).
> 
> Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
> ---
>  drivers/tty/serial/Kconfig | 19 +++++++++++++++++++
>  drivers/tty/serial/pxa.c   | 22 ++++++++++++++++++----
>  2 files changed, 37 insertions(+), 4 deletions(-)
> diff --git a/drivers/tty/serial/pxa.c b/drivers/tty/serial/pxa.c

<snip>

> --- a/drivers/tty/serial/pxa.c
> +++ b/drivers/tty/serial/pxa.c
> @@ -593,6 +593,20 @@ serial_pxa_type(struct uart_port *port)
>  static struct uart_pxa_port *serial_pxa_ports[4];
>  static struct uart_driver serial_pxa_reg;
>  
> +#ifndef CONFIG_SERIAL_PXA_AS_TTYSA
> +
> +#define PXA_TTY_NAME	"ttyS"
> +#define PXA_TTY_MAJOR	TTY_MAJOR
> +#define PXA_TTY_MINOR	64
> +
> +#else
> +
> +#define PXA_TTY_NAME	"ttySA"
> +#define PXA_TTY_MAJOR	204
> +#define PXA_TTY_MINOR	5
> +
> +#endif
> +
>  #ifdef CONFIG_SERIAL_PXA_CONSOLE
>  
>  #define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
> @@ -751,7 +765,7 @@ serial_pxa_console_setup(struct console *co, char *options)
>  }
>  
>  static struct console serial_pxa_console = {
> -	.name		= "ttyS",
> +	.name		= PXA_TTY_NAME,
>  	.write		= serial_pxa_console_write,
>  	.device		= uart_console_device,
>  	.setup		= serial_pxa_console_setup,
> @@ -792,9 +806,9 @@ static struct uart_ops serial_pxa_pops = {
>  static struct uart_driver serial_pxa_reg = {
>  	.owner		= THIS_MODULE,
>  	.driver_name	= "PXA serial",
> -	.dev_name	= "ttyS",
> -	.major		= TTY_MAJOR,
> -	.minor		= 64,
> +	.dev_name	= PXA_TTY_NAME,
> +	.major		= PXA_TTY_MAJOR,
> +	.minor		= PXA_TTY_MINOR,
>  	.nr		= 4,
>  	.cons		= PXA_CONSOLE,
>  };

If drivers/tty/serial/pxa.c was converted to an other probe driver for
the 8250, this would not be an issue.

Br,

-- 
heikki

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

* [PATCH 01/11] resolve PXA<->8250 serial device address conflict
@ 2013-12-02  9:02     ` Heikki Krogerus
  0 siblings, 0 replies; 700+ messages in thread
From: Heikki Krogerus @ 2013-12-02  9:02 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

On Sun, Dec 01, 2013 at 10:26:14AM +0400, Sergei Ianovich wrote:
> PXA serial ports have "standard" UART names (ttyS[0-3]), major
> device number (4) and first minor device number (64) by default.
> 
> If the system has extra 8250 serial port hardware in addition
> to onboard PXA serial ports, default settings produce a device
> allocation conflict.
> 
> The patch provides a configuration option which can move onboard
> ports out of the way of 8250_core by assigning a different (204)
> major number and corresponding device names (ttySA[0-3]).
> 
> Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
> ---
>  drivers/tty/serial/Kconfig | 19 +++++++++++++++++++
>  drivers/tty/serial/pxa.c   | 22 ++++++++++++++++++----
>  2 files changed, 37 insertions(+), 4 deletions(-)
> diff --git a/drivers/tty/serial/pxa.c b/drivers/tty/serial/pxa.c

<snip>

> --- a/drivers/tty/serial/pxa.c
> +++ b/drivers/tty/serial/pxa.c
> @@ -593,6 +593,20 @@ serial_pxa_type(struct uart_port *port)
>  static struct uart_pxa_port *serial_pxa_ports[4];
>  static struct uart_driver serial_pxa_reg;
>  
> +#ifndef CONFIG_SERIAL_PXA_AS_TTYSA
> +
> +#define PXA_TTY_NAME	"ttyS"
> +#define PXA_TTY_MAJOR	TTY_MAJOR
> +#define PXA_TTY_MINOR	64
> +
> +#else
> +
> +#define PXA_TTY_NAME	"ttySA"
> +#define PXA_TTY_MAJOR	204
> +#define PXA_TTY_MINOR	5
> +
> +#endif
> +
>  #ifdef CONFIG_SERIAL_PXA_CONSOLE
>  
>  #define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
> @@ -751,7 +765,7 @@ serial_pxa_console_setup(struct console *co, char *options)
>  }
>  
>  static struct console serial_pxa_console = {
> -	.name		= "ttyS",
> +	.name		= PXA_TTY_NAME,
>  	.write		= serial_pxa_console_write,
>  	.device		= uart_console_device,
>  	.setup		= serial_pxa_console_setup,
> @@ -792,9 +806,9 @@ static struct uart_ops serial_pxa_pops = {
>  static struct uart_driver serial_pxa_reg = {
>  	.owner		= THIS_MODULE,
>  	.driver_name	= "PXA serial",
> -	.dev_name	= "ttyS",
> -	.major		= TTY_MAJOR,
> -	.minor		= 64,
> +	.dev_name	= PXA_TTY_NAME,
> +	.major		= PXA_TTY_MAJOR,
> +	.minor		= PXA_TTY_MINOR,
>  	.nr		= 4,
>  	.cons		= PXA_CONSOLE,
>  };

If drivers/tty/serial/pxa.c was converted to an other probe driver for
the 8250, this would not be an issue.

Br,

-- 
heikki

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

* Re: [PATCH 01/11] resolve PXA<->8250 serial device address conflict
  2013-12-02  9:02     ` Heikki Krogerus
@ 2013-12-02  9:23       ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-02  9:23 UTC (permalink / raw)
  To: Heikki Krogerus
  Cc: linux-kernel, linux-arm-kernel, Greg Kroah-Hartman, Jiri Slaby,
	open list:SERIAL DRIVERS

On Mon, 2013-12-02 at 11:02 +0200, Heikki Krogerus wrote:
> On Sun, Dec 01, 2013 at 10:26:14AM +0400, Sergei Ianovich wrote:
> > PXA serial ports have "standard" UART names (ttyS[0-3]), major
> > device number (4) and first minor device number (64) by default.
> > 
> > If the system has extra 8250 serial port hardware in addition
> > to onboard PXA serial ports, default settings produce a device
> > allocation conflict.
> > 
> > The patch provides a configuration option which can move onboard
> > ports out of the way of 8250_core by assigning a different (204)
> > major number and corresponding device names (ttySA[0-3]).
> > 
> <snip>
> 
> If drivers/tty/serial/pxa.c was converted to an other probe driver for
> the 8250, this would not be an issue.

It seems that my patch is not going to be accepted. However, there is a
device which has both PXA ports and a additional 8250 accent chip. As a
result, there is a device allocation conflict. For the device to be
usable the conflict needs to be resolved.

Do you mean that drivers/tty/serial/pxa.c needs to be rewritten to
support lp8x4x special case?


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

* [PATCH 01/11] resolve PXA<->8250 serial device address conflict
@ 2013-12-02  9:23       ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-02  9:23 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, 2013-12-02 at 11:02 +0200, Heikki Krogerus wrote:
> On Sun, Dec 01, 2013 at 10:26:14AM +0400, Sergei Ianovich wrote:
> > PXA serial ports have "standard" UART names (ttyS[0-3]), major
> > device number (4) and first minor device number (64) by default.
> > 
> > If the system has extra 8250 serial port hardware in addition
> > to onboard PXA serial ports, default settings produce a device
> > allocation conflict.
> > 
> > The patch provides a configuration option which can move onboard
> > ports out of the way of 8250_core by assigning a different (204)
> > major number and corresponding device names (ttySA[0-3]).
> > 
> <snip>
> 
> If drivers/tty/serial/pxa.c was converted to an other probe driver for
> the 8250, this would not be an issue.

It seems that my patch is not going to be accepted. However, there is a
device which has both PXA ports and a additional 8250 accent chip. As a
result, there is a device allocation conflict. For the device to be
usable the conflict needs to be resolved.

Do you mean that drivers/tty/serial/pxa.c needs to be rewritten to
support lp8x4x special case?

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

* Re: [PATCH 01/11] resolve PXA<->8250 serial device address conflict
  2013-12-02  9:23       ` Sergei Ianovich
@ 2013-12-02  9:49         ` Heikki Krogerus
  -1 siblings, 0 replies; 700+ messages in thread
From: Heikki Krogerus @ 2013-12-02  9:49 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: linux-kernel, linux-arm-kernel, Greg Kroah-Hartman, Jiri Slaby,
	open list:SERIAL DRIVERS

Hi,

On Mon, Dec 02, 2013 at 01:23:58PM +0400, Sergei Ianovich wrote:
> On Mon, 2013-12-02 at 11:02 +0200, Heikki Krogerus wrote:
> > On Sun, Dec 01, 2013 at 10:26:14AM +0400, Sergei Ianovich wrote:
> > > PXA serial ports have "standard" UART names (ttyS[0-3]), major
> > > device number (4) and first minor device number (64) by default.
> > > 
> > > If the system has extra 8250 serial port hardware in addition
> > > to onboard PXA serial ports, default settings produce a device
> > > allocation conflict.
> > > 
> > > The patch provides a configuration option which can move onboard
> > > ports out of the way of 8250_core by assigning a different (204)
> > > major number and corresponding device names (ttySA[0-3]).
> > > 
> > <snip>
> > 
> > If drivers/tty/serial/pxa.c was converted to an other probe driver for
> > the 8250, this would not be an issue.
> 
> It seems that my patch is not going to be accepted. However, there is a
> device which has both PXA ports and a additional 8250 accent chip. As a
> result, there is a device allocation conflict. For the device to be
> usable the conflict needs to be resolved.
> 
> Do you mean that drivers/tty/serial/pxa.c needs to be rewritten to
> support lp8x4x special case?

Sorry I was not clear. I was suggesting that drivers/tty/serial/pxa.c
would be converted to drivers/tty/serial/8250/8250_pxa.c since it
looks to me like just an other 16x50 compatible UART. That would fix
the issue with the name conflict. You would then simply register 8250
ports from two probe drivers (drivers/tty/serial/8250/8250_pxa.c and
drivers/tty/serial/8250/8250_lp8x4x.c).

Depending on the order you register your platform devices (which you
decide in your platform code), but let's say the pxa gets registered
first and let's say it only has one port. You will then have in your
system /dev/ttyS0 for the pxa port and /dev/ttyS[1-4] for the other
UART.

I hope I was able to explain what I mean this time :)

Thanks,

-- 
heikki

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

* [PATCH 01/11] resolve PXA<->8250 serial device address conflict
@ 2013-12-02  9:49         ` Heikki Krogerus
  0 siblings, 0 replies; 700+ messages in thread
From: Heikki Krogerus @ 2013-12-02  9:49 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

On Mon, Dec 02, 2013 at 01:23:58PM +0400, Sergei Ianovich wrote:
> On Mon, 2013-12-02 at 11:02 +0200, Heikki Krogerus wrote:
> > On Sun, Dec 01, 2013 at 10:26:14AM +0400, Sergei Ianovich wrote:
> > > PXA serial ports have "standard" UART names (ttyS[0-3]), major
> > > device number (4) and first minor device number (64) by default.
> > > 
> > > If the system has extra 8250 serial port hardware in addition
> > > to onboard PXA serial ports, default settings produce a device
> > > allocation conflict.
> > > 
> > > The patch provides a configuration option which can move onboard
> > > ports out of the way of 8250_core by assigning a different (204)
> > > major number and corresponding device names (ttySA[0-3]).
> > > 
> > <snip>
> > 
> > If drivers/tty/serial/pxa.c was converted to an other probe driver for
> > the 8250, this would not be an issue.
> 
> It seems that my patch is not going to be accepted. However, there is a
> device which has both PXA ports and a additional 8250 accent chip. As a
> result, there is a device allocation conflict. For the device to be
> usable the conflict needs to be resolved.
> 
> Do you mean that drivers/tty/serial/pxa.c needs to be rewritten to
> support lp8x4x special case?

Sorry I was not clear. I was suggesting that drivers/tty/serial/pxa.c
would be converted to drivers/tty/serial/8250/8250_pxa.c since it
looks to me like just an other 16x50 compatible UART. That would fix
the issue with the name conflict. You would then simply register 8250
ports from two probe drivers (drivers/tty/serial/8250/8250_pxa.c and
drivers/tty/serial/8250/8250_lp8x4x.c).

Depending on the order you register your platform devices (which you
decide in your platform code), but let's say the pxa gets registered
first and let's say it only has one port. You will then have in your
system /dev/ttyS0 for the pxa port and /dev/ttyS[1-4] for the other
UART.

I hope I was able to explain what I mean this time :)

Thanks,

-- 
heikki

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

* Re: [PATCH 01/11] resolve PXA<->8250 serial device address conflict
  2013-12-02  9:49         ` Heikki Krogerus
@ 2013-12-02 10:26           ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-02 10:26 UTC (permalink / raw)
  To: Heikki Krogerus
  Cc: linux-kernel, linux-arm-kernel, Greg Kroah-Hartman, Jiri Slaby,
	open list:SERIAL DRIVERS

On Mon, 2013-12-02 at 11:49 +0200, Heikki Krogerus wrote:
> On Mon, Dec 02, 2013 at 01:23:58PM +0400, Sergei Ianovich wrote:
> > On Mon, 2013-12-02 at 11:02 +0200, Heikki Krogerus wrote:
> > > On Sun, Dec 01, 2013 at 10:26:14AM +0400, Sergei Ianovich wrote:
> > > > PXA serial ports have "standard" UART names (ttyS[0-3]), major
> > > > device number (4) and first minor device number (64) by default.
> > > > 
> > > > If the system has extra 8250 serial port hardware in addition
> > > > to onboard PXA serial ports, default settings produce a device
> > > > allocation conflict.
> > > > 
> > > > The patch provides a configuration option which can move onboard
> > > > ports out of the way of 8250_core by assigning a different (204)
> > > > major number and corresponding device names (ttySA[0-3]).
> > > > 
> > > <snip>
> > > 
> > > If drivers/tty/serial/pxa.c was converted to an other probe driver for
> > > the 8250, this would not be an issue.
> > 
> > It seems that my patch is not going to be accepted. However, there is a
> > device which has both PXA ports and a additional 8250 accent chip. As a
> > result, there is a device allocation conflict. For the device to be
> > usable the conflict needs to be resolved.
> > 
> > Do you mean that drivers/tty/serial/pxa.c needs to be rewritten to
> > support lp8x4x special case?
> 
> Sorry I was not clear. I was suggesting that drivers/tty/serial/pxa.c
> would be converted to drivers/tty/serial/8250/8250_pxa.c since it
> looks to me like just an other 16x50 compatible UART. That would fix
> the issue with the name conflict. You would then simply register 8250
> ports from two probe drivers (drivers/tty/serial/8250/8250_pxa.c and
> drivers/tty/serial/8250/8250_lp8x4x.c).
> 
> Depending on the order you register your platform devices (which you
> decide in your platform code), but let's say the pxa gets registered
> first and let's say it only has one port. You will then have in your
> system /dev/ttyS0 for the pxa port and /dev/ttyS[1-4] for the other
> UART.
> 
> I hope I was able to explain what I mean this time :)

Sorry, I wasn't clear as well. I got it right the first time. You mean
pxa.c needs to merged into 8250. This will solve the conflict in
question, and do it the right way. However, this will be a *much* bigger
patch, and it will affect everyone on pxa.

Who makes the decision which way to go?


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

* [PATCH 01/11] resolve PXA<->8250 serial device address conflict
@ 2013-12-02 10:26           ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-02 10:26 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, 2013-12-02 at 11:49 +0200, Heikki Krogerus wrote:
> On Mon, Dec 02, 2013 at 01:23:58PM +0400, Sergei Ianovich wrote:
> > On Mon, 2013-12-02 at 11:02 +0200, Heikki Krogerus wrote:
> > > On Sun, Dec 01, 2013 at 10:26:14AM +0400, Sergei Ianovich wrote:
> > > > PXA serial ports have "standard" UART names (ttyS[0-3]), major
> > > > device number (4) and first minor device number (64) by default.
> > > > 
> > > > If the system has extra 8250 serial port hardware in addition
> > > > to onboard PXA serial ports, default settings produce a device
> > > > allocation conflict.
> > > > 
> > > > The patch provides a configuration option which can move onboard
> > > > ports out of the way of 8250_core by assigning a different (204)
> > > > major number and corresponding device names (ttySA[0-3]).
> > > > 
> > > <snip>
> > > 
> > > If drivers/tty/serial/pxa.c was converted to an other probe driver for
> > > the 8250, this would not be an issue.
> > 
> > It seems that my patch is not going to be accepted. However, there is a
> > device which has both PXA ports and a additional 8250 accent chip. As a
> > result, there is a device allocation conflict. For the device to be
> > usable the conflict needs to be resolved.
> > 
> > Do you mean that drivers/tty/serial/pxa.c needs to be rewritten to
> > support lp8x4x special case?
> 
> Sorry I was not clear. I was suggesting that drivers/tty/serial/pxa.c
> would be converted to drivers/tty/serial/8250/8250_pxa.c since it
> looks to me like just an other 16x50 compatible UART. That would fix
> the issue with the name conflict. You would then simply register 8250
> ports from two probe drivers (drivers/tty/serial/8250/8250_pxa.c and
> drivers/tty/serial/8250/8250_lp8x4x.c).
> 
> Depending on the order you register your platform devices (which you
> decide in your platform code), but let's say the pxa gets registered
> first and let's say it only has one port. You will then have in your
> system /dev/ttyS0 for the pxa port and /dev/ttyS[1-4] for the other
> UART.
> 
> I hope I was able to explain what I mean this time :)

Sorry, I wasn't clear as well. I got it right the first time. You mean
pxa.c needs to merged into 8250. This will solve the conflict in
question, and do it the right way. However, this will be a *much* bigger
patch, and it will affect everyone on pxa.

Who makes the decision which way to go?

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

* Re: [PATCH 05/11] serial: support for 16550 serial ports on LP-8x4x
  2013-12-01  6:26   ` Sergei Ianovich
@ 2013-12-02 11:30     ` Russell King - ARM Linux
  -1 siblings, 0 replies; 700+ messages in thread
From: Russell King - ARM Linux @ 2013-12-02 11:30 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: linux-kernel, linux-arm-kernel, Eric Miao, Haojian Zhuang,
	Greg Kroah-Hartman, Jiri Slaby, Heikki Krogerus, Arnd Bergmann,
	open list:SERIAL DRIVERS

On Sun, Dec 01, 2013 at 10:26:18AM +0400, Sergei Ianovich wrote:
> +static struct platform_device lp8x4x_device = {
> +	.name			= "serial8250",
> +	.id			= PLAT8250_DEV_ACCENT,

You should not re-use the enum value here.  The enum is designed as a
method to provide the platform devices with a unique id, not as a means
to identify the manufacturer or anything else like that.

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

* [PATCH 05/11] serial: support for 16550 serial ports on LP-8x4x
@ 2013-12-02 11:30     ` Russell King - ARM Linux
  0 siblings, 0 replies; 700+ messages in thread
From: Russell King - ARM Linux @ 2013-12-02 11:30 UTC (permalink / raw)
  To: linux-arm-kernel

On Sun, Dec 01, 2013 at 10:26:18AM +0400, Sergei Ianovich wrote:
> +static struct platform_device lp8x4x_device = {
> +	.name			= "serial8250",
> +	.id			= PLAT8250_DEV_ACCENT,

You should not re-use the enum value here.  The enum is designed as a
method to provide the platform devices with a unique id, not as a means
to identify the manufacturer or anything else like that.

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

* Re: [PATCH 05/11] serial: support for 16550 serial ports on LP-8x4x
  2013-12-02 11:30     ` Russell King - ARM Linux
@ 2013-12-02 11:39       ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-02 11:39 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: linux-kernel, linux-arm-kernel, Eric Miao, Haojian Zhuang,
	Greg Kroah-Hartman, Jiri Slaby, Heikki Krogerus, Arnd Bergmann,
	open list:SERIAL DRIVERS

On Mon, 2013-12-02 at 11:30 +0000, Russell King - ARM Linux wrote:
> On Sun, Dec 01, 2013 at 10:26:18AM +0400, Sergei Ianovich wrote:
> > +static struct platform_device lp8x4x_device = {
> > +	.name			= "serial8250",
> > +	.id			= PLAT8250_DEV_ACCENT,
> 
> You should not re-use the enum value here.  The enum is designed as a
> method to provide the platform devices with a unique id, not as a means
> to identify the manufacturer or anything else like that.

Should I add a new enum?

Or should I use zero?


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

* [PATCH 05/11] serial: support for 16550 serial ports on LP-8x4x
@ 2013-12-02 11:39       ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-02 11:39 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, 2013-12-02 at 11:30 +0000, Russell King - ARM Linux wrote:
> On Sun, Dec 01, 2013 at 10:26:18AM +0400, Sergei Ianovich wrote:
> > +static struct platform_device lp8x4x_device = {
> > +	.name			= "serial8250",
> > +	.id			= PLAT8250_DEV_ACCENT,
> 
> You should not re-use the enum value here.  The enum is designed as a
> method to provide the platform devices with a unique id, not as a means
> to identify the manufacturer or anything else like that.

Should I add a new enum?

Or should I use zero?

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

* Re: [PATCH 05/11] serial: support for 16550 serial ports on LP-8x4x
  2013-12-02  8:48     ` Heikki Krogerus
@ 2013-12-02 11:46       ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-02 11:46 UTC (permalink / raw)
  To: Heikki Krogerus
  Cc: linux-kernel, linux-arm-kernel, Russell King, Eric Miao,
	Haojian Zhuang, Greg Kroah-Hartman, Jiri Slaby, Arnd Bergmann,
	open list:SERIAL DRIVERS

On Mon, 2013-12-02 at 10:48 +0200, Heikki Krogerus wrote:
> On Sun, Dec 01, 2013 at 10:26:18AM +0400, Sergei Ianovich wrote:
> > The patch adds support for 3 additional LP-8x4x built-in serial
> > ports.
> > 
> > The device can also host up to 8 extension cards with 4 serial ports
> > on each card for a total of 35 ports. However, I don't have
> > the hardware to test extension cards, so they are not supported, yet.

> > --- a/arch/arm/mach-pxa/include/mach/lp8x4x.h
> > +++ b/arch/arm/mach-pxa/include/mach/lp8x4x.h
> > @@ -50,6 +50,12 @@
> >  #define LP8X4X_CLRFALLINT	LP8X4X_P2V(0x1700901a)
> >  #define LP8X4X_RWRTC		LP8X4X_P2V(0x1700901c)
> >  #define LP8X4X_SRAMBANK		0x1700901e
> > +#define LP8X4X_TTYS0_QUIRK	0x17009030
> > +#define LP8X4X_TTYS1_QUIRK	0x17009032
> > +#define LP8X4X_TTYS2_QUIRK	0x17009034
> > +#define LP8X4X_TTYS0_IOMEM	0x17009050
> > +#define LP8X4X_TTYS1_IOMEM	0x17009060
> > +#define LP8X4X_TTYS2_IOMEM	0x17009070
> > +
> > +static void lp8x4x_set_termios(struct uart_port *port,
> > +		struct ktermios *termios, struct ktermios *old)
> > +{
> 
> <snip>
> 
> > +static int request_and_remap(int i)
> > +{
> > +	if (!request_mem_region(extra_mem[i], 1, "serial"))
> > +		return -EBUSY;
> > +
> > +	lp8x4x_data[i].private_data = ioremap(extra_mem[i], 1);
> > +	if (lp8x4x_data[i].private_data)
> > +		return 0;
> > +
> > +	release_mem_region(extra_mem[i], 1);
> > +	return -ENODEV;

> Instead of registering a platform device for serial8250 here, you need
> to simply register a platform driver for something like lp8x4x_serial.
> The platform code will to registers the platform devices for it. You
> will use serial8250_register_8250_port() in your probe to register a
> new port. Use 8250_em.c and 8250_dw.c under drivers/tty/serial/8250/
> as an example.
> 
> You don't need to introduce plat_serial8250_port so you won't need
> the QUIRK_PORT stuff. You deliver the iomem and the irq as normal
> resources that the driver uses when you create the platform device.
> That of course also means the driver does not need to care about the
> instances. The platform code will generate a platform device for as
> many ports you have and set to resources accordingly.

8250_core.c doesn't use platform infrastructure to request and map IO
memory. There will be a conflict (and an error in
serial8250_request_std_resource()), if main IO memory is requested by
the platform device, won't it?


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

* [PATCH 05/11] serial: support for 16550 serial ports on LP-8x4x
@ 2013-12-02 11:46       ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-02 11:46 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, 2013-12-02 at 10:48 +0200, Heikki Krogerus wrote:
> On Sun, Dec 01, 2013 at 10:26:18AM +0400, Sergei Ianovich wrote:
> > The patch adds support for 3 additional LP-8x4x built-in serial
> > ports.
> > 
> > The device can also host up to 8 extension cards with 4 serial ports
> > on each card for a total of 35 ports. However, I don't have
> > the hardware to test extension cards, so they are not supported, yet.

> > --- a/arch/arm/mach-pxa/include/mach/lp8x4x.h
> > +++ b/arch/arm/mach-pxa/include/mach/lp8x4x.h
> > @@ -50,6 +50,12 @@
> >  #define LP8X4X_CLRFALLINT	LP8X4X_P2V(0x1700901a)
> >  #define LP8X4X_RWRTC		LP8X4X_P2V(0x1700901c)
> >  #define LP8X4X_SRAMBANK		0x1700901e
> > +#define LP8X4X_TTYS0_QUIRK	0x17009030
> > +#define LP8X4X_TTYS1_QUIRK	0x17009032
> > +#define LP8X4X_TTYS2_QUIRK	0x17009034
> > +#define LP8X4X_TTYS0_IOMEM	0x17009050
> > +#define LP8X4X_TTYS1_IOMEM	0x17009060
> > +#define LP8X4X_TTYS2_IOMEM	0x17009070
> > +
> > +static void lp8x4x_set_termios(struct uart_port *port,
> > +		struct ktermios *termios, struct ktermios *old)
> > +{
> 
> <snip>
> 
> > +static int request_and_remap(int i)
> > +{
> > +	if (!request_mem_region(extra_mem[i], 1, "serial"))
> > +		return -EBUSY;
> > +
> > +	lp8x4x_data[i].private_data = ioremap(extra_mem[i], 1);
> > +	if (lp8x4x_data[i].private_data)
> > +		return 0;
> > +
> > +	release_mem_region(extra_mem[i], 1);
> > +	return -ENODEV;

> Instead of registering a platform device for serial8250 here, you need
> to simply register a platform driver for something like lp8x4x_serial.
> The platform code will to registers the platform devices for it. You
> will use serial8250_register_8250_port() in your probe to register a
> new port. Use 8250_em.c and 8250_dw.c under drivers/tty/serial/8250/
> as an example.
> 
> You don't need to introduce plat_serial8250_port so you won't need
> the QUIRK_PORT stuff. You deliver the iomem and the irq as normal
> resources that the driver uses when you create the platform device.
> That of course also means the driver does not need to care about the
> instances. The platform code will generate a platform device for as
> many ports you have and set to resources accordingly.

8250_core.c doesn't use platform infrastructure to request and map IO
memory. There will be a conflict (and an error in
serial8250_request_std_resource()), if main IO memory is requested by
the platform device, won't it?

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

* Re: [PATCH 05/11] serial: support for 16550 serial ports on LP-8x4x
  2013-12-02 11:39       ` Sergei Ianovich
@ 2013-12-02 11:52         ` Russell King - ARM Linux
  -1 siblings, 0 replies; 700+ messages in thread
From: Russell King - ARM Linux @ 2013-12-02 11:52 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: linux-kernel, linux-arm-kernel, Eric Miao, Haojian Zhuang,
	Greg Kroah-Hartman, Jiri Slaby, Heikki Krogerus, Arnd Bergmann,
	open list:SERIAL DRIVERS

On Mon, Dec 02, 2013 at 03:39:26PM +0400, Sergei Ianovich wrote:
> On Mon, 2013-12-02 at 11:30 +0000, Russell King - ARM Linux wrote:
> > On Sun, Dec 01, 2013 at 10:26:18AM +0400, Sergei Ianovich wrote:
> > > +static struct platform_device lp8x4x_device = {
> > > +	.name			= "serial8250",
> > > +	.id			= PLAT8250_DEV_ACCENT,
> > 
> > You should not re-use the enum value here.  The enum is designed as a
> > method to provide the platform devices with a unique id, not as a means
> > to identify the manufacturer or anything else like that.
> 
> Should I add a new enum?

Add a new enum.

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

* [PATCH 05/11] serial: support for 16550 serial ports on LP-8x4x
@ 2013-12-02 11:52         ` Russell King - ARM Linux
  0 siblings, 0 replies; 700+ messages in thread
From: Russell King - ARM Linux @ 2013-12-02 11:52 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Dec 02, 2013 at 03:39:26PM +0400, Sergei Ianovich wrote:
> On Mon, 2013-12-02 at 11:30 +0000, Russell King - ARM Linux wrote:
> > On Sun, Dec 01, 2013 at 10:26:18AM +0400, Sergei Ianovich wrote:
> > > +static struct platform_device lp8x4x_device = {
> > > +	.name			= "serial8250",
> > > +	.id			= PLAT8250_DEV_ACCENT,
> > 
> > You should not re-use the enum value here.  The enum is designed as a
> > method to provide the platform devices with a unique id, not as a means
> > to identify the manufacturer or anything else like that.
> 
> Should I add a new enum?

Add a new enum.

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

* Re: [PATCH 05/11] serial: support for 16550 serial ports on LP-8x4x
  2013-12-02 11:52         ` Russell King - ARM Linux
@ 2013-12-02 12:01           ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-02 12:01 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: linux-kernel, linux-arm-kernel, Eric Miao, Haojian Zhuang,
	Greg Kroah-Hartman, Jiri Slaby, Heikki Krogerus, Arnd Bergmann,
	open list:SERIAL DRIVERS

On Mon, 2013-12-02 at 11:52 +0000, Russell King - ARM Linux wrote:
> Add a new enum.

I will. Thanks for prompt replies.

A side work process question:
Should I respin this single patch?

Or should I wait for other patch reviews and respin the whole series
when ready?




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

* [PATCH 05/11] serial: support for 16550 serial ports on LP-8x4x
@ 2013-12-02 12:01           ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-02 12:01 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, 2013-12-02 at 11:52 +0000, Russell King - ARM Linux wrote:
> Add a new enum.

I will. Thanks for prompt replies.

A side work process question:
Should I respin this single patch?

Or should I wait for other patch reviews and respin the whole series
when ready?

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

* Re: [PATCH 05/11] serial: support for 16550 serial ports on LP-8x4x
  2013-12-02 11:46       ` Sergei Ianovich
@ 2013-12-02 13:53         ` Heikki Krogerus
  -1 siblings, 0 replies; 700+ messages in thread
From: Heikki Krogerus @ 2013-12-02 13:53 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: linux-kernel, linux-arm-kernel, Russell King, Eric Miao,
	Haojian Zhuang, Greg Kroah-Hartman, Jiri Slaby, Arnd Bergmann,
	open list:SERIAL DRIVERS

Hi,

On Mon, Dec 02, 2013 at 03:46:22PM +0400, Sergei Ianovich wrote:
> On Mon, 2013-12-02 at 10:48 +0200, Heikki Krogerus wrote:
> > On Sun, Dec 01, 2013 at 10:26:18AM +0400, Sergei Ianovich wrote:
> > > +static int request_and_remap(int i)
> > > +{
> > > +	if (!request_mem_region(extra_mem[i], 1, "serial"))
> > > +		return -EBUSY;
> > > +
> > > +	lp8x4x_data[i].private_data = ioremap(extra_mem[i], 1);
> > > +	if (lp8x4x_data[i].private_data)
> > > +		return 0;
> > > +
> > > +	release_mem_region(extra_mem[i], 1);
> > > +	return -ENODEV;
> 
> > Instead of registering a platform device for serial8250 here, you need
> > to simply register a platform driver for something like lp8x4x_serial.
> > The platform code will to registers the platform devices for it. You
> > will use serial8250_register_8250_port() in your probe to register a
> > new port. Use 8250_em.c and 8250_dw.c under drivers/tty/serial/8250/
> > as an example.
> > 
> > You don't need to introduce plat_serial8250_port so you won't need
> > the QUIRK_PORT stuff. You deliver the iomem and the irq as normal
> > resources that the driver uses when you create the platform device.
> > That of course also means the driver does not need to care about the
> > instances. The platform code will generate a platform device for as
> > many ports you have and set to resources accordingly.
> 
> 8250_core.c doesn't use platform infrastructure to request and map IO
> memory. There will be a conflict (and an error in
> serial8250_request_std_resource()), if main IO memory is requested by
> the platform device, won't it?

You don't need to request the mem region in your probe driver.

You can still map it. You have the flag UPF_IOREMAP that you can use
to tell 8250_code.c to map the region. If you don't set the flag,
8250_core.c will in practice expect that port->membase is already set
by the probe driver.

Check 8250_dw.c. It does the mapping on it's own and simply doesn't
set the flag.

Br,

-- 
heikki

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

* [PATCH 05/11] serial: support for 16550 serial ports on LP-8x4x
@ 2013-12-02 13:53         ` Heikki Krogerus
  0 siblings, 0 replies; 700+ messages in thread
From: Heikki Krogerus @ 2013-12-02 13:53 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

On Mon, Dec 02, 2013 at 03:46:22PM +0400, Sergei Ianovich wrote:
> On Mon, 2013-12-02 at 10:48 +0200, Heikki Krogerus wrote:
> > On Sun, Dec 01, 2013 at 10:26:18AM +0400, Sergei Ianovich wrote:
> > > +static int request_and_remap(int i)
> > > +{
> > > +	if (!request_mem_region(extra_mem[i], 1, "serial"))
> > > +		return -EBUSY;
> > > +
> > > +	lp8x4x_data[i].private_data = ioremap(extra_mem[i], 1);
> > > +	if (lp8x4x_data[i].private_data)
> > > +		return 0;
> > > +
> > > +	release_mem_region(extra_mem[i], 1);
> > > +	return -ENODEV;
> 
> > Instead of registering a platform device for serial8250 here, you need
> > to simply register a platform driver for something like lp8x4x_serial.
> > The platform code will to registers the platform devices for it. You
> > will use serial8250_register_8250_port() in your probe to register a
> > new port. Use 8250_em.c and 8250_dw.c under drivers/tty/serial/8250/
> > as an example.
> > 
> > You don't need to introduce plat_serial8250_port so you won't need
> > the QUIRK_PORT stuff. You deliver the iomem and the irq as normal
> > resources that the driver uses when you create the platform device.
> > That of course also means the driver does not need to care about the
> > instances. The platform code will generate a platform device for as
> > many ports you have and set to resources accordingly.
> 
> 8250_core.c doesn't use platform infrastructure to request and map IO
> memory. There will be a conflict (and an error in
> serial8250_request_std_resource()), if main IO memory is requested by
> the platform device, won't it?

You don't need to request the mem region in your probe driver.

You can still map it. You have the flag UPF_IOREMAP that you can use
to tell 8250_code.c to map the region. If you don't set the flag,
8250_core.c will in practice expect that port->membase is already set
by the probe driver.

Check 8250_dw.c. It does the mapping on it's own and simply doesn't
set the flag.

Br,

-- 
heikki

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

* Re: [PATCH 01/11] resolve PXA<->8250 serial device address conflict
  2013-12-02 10:26           ` Sergei Ianovich
@ 2013-12-02 14:10             ` Heikki Krogerus
  -1 siblings, 0 replies; 700+ messages in thread
From: Heikki Krogerus @ 2013-12-02 14:10 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: linux-kernel, linux-arm-kernel, Greg Kroah-Hartman, Jiri Slaby,
	open list:SERIAL DRIVERS

Hi,

On Mon, Dec 02, 2013 at 02:26:45PM +0400, Sergei Ianovich wrote:
> On Mon, 2013-12-02 at 11:49 +0200, Heikki Krogerus wrote:
> > On Mon, Dec 02, 2013 at 01:23:58PM +0400, Sergei Ianovich wrote:
> > > On Mon, 2013-12-02 at 11:02 +0200, Heikki Krogerus wrote:
> > > > 
> > > > If drivers/tty/serial/pxa.c was converted to an other probe driver for
> > > > the 8250, this would not be an issue.
> > > 
> > > It seems that my patch is not going to be accepted. However, there is a
> > > device which has both PXA ports and a additional 8250 accent chip. As a
> > > result, there is a device allocation conflict. For the device to be
> > > usable the conflict needs to be resolved.
> > > 
> > > Do you mean that drivers/tty/serial/pxa.c needs to be rewritten to
> > > support lp8x4x special case?
> > 
> > Sorry I was not clear. I was suggesting that drivers/tty/serial/pxa.c
> > would be converted to drivers/tty/serial/8250/8250_pxa.c since it
> > looks to me like just an other 16x50 compatible UART. That would fix
> > the issue with the name conflict. You would then simply register 8250
> > ports from two probe drivers (drivers/tty/serial/8250/8250_pxa.c and
> > drivers/tty/serial/8250/8250_lp8x4x.c).
> > 
> > Depending on the order you register your platform devices (which you
> > decide in your platform code), but let's say the pxa gets registered
> > first and let's say it only has one port. You will then have in your
> > system /dev/ttyS0 for the pxa port and /dev/ttyS[1-4] for the other
> > UART.
> > 
> > I hope I was able to explain what I mean this time :)
> 
> Sorry, I wasn't clear as well. I got it right the first time. You mean
> pxa.c needs to merged into 8250. This will solve the conflict in
> question, and do it the right way. However, this will be a *much* bigger
> patch, and it will affect everyone on pxa.
> 
> Who makes the decision which way to go?

Greg and Russel make this decision. By having the pxa driver simply
register 8250 ports would probable reduce the code. Thats about the
biggest benefit from it.

It would still be something nice to have IMO. Ideally all the
8250/16x50 UARTs should register the ports with 8250_core.c, and not
create complete uart driver on their own.

Br,

-- 
heikki

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

* [PATCH 01/11] resolve PXA<->8250 serial device address conflict
@ 2013-12-02 14:10             ` Heikki Krogerus
  0 siblings, 0 replies; 700+ messages in thread
From: Heikki Krogerus @ 2013-12-02 14:10 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

On Mon, Dec 02, 2013 at 02:26:45PM +0400, Sergei Ianovich wrote:
> On Mon, 2013-12-02 at 11:49 +0200, Heikki Krogerus wrote:
> > On Mon, Dec 02, 2013 at 01:23:58PM +0400, Sergei Ianovich wrote:
> > > On Mon, 2013-12-02 at 11:02 +0200, Heikki Krogerus wrote:
> > > > 
> > > > If drivers/tty/serial/pxa.c was converted to an other probe driver for
> > > > the 8250, this would not be an issue.
> > > 
> > > It seems that my patch is not going to be accepted. However, there is a
> > > device which has both PXA ports and a additional 8250 accent chip. As a
> > > result, there is a device allocation conflict. For the device to be
> > > usable the conflict needs to be resolved.
> > > 
> > > Do you mean that drivers/tty/serial/pxa.c needs to be rewritten to
> > > support lp8x4x special case?
> > 
> > Sorry I was not clear. I was suggesting that drivers/tty/serial/pxa.c
> > would be converted to drivers/tty/serial/8250/8250_pxa.c since it
> > looks to me like just an other 16x50 compatible UART. That would fix
> > the issue with the name conflict. You would then simply register 8250
> > ports from two probe drivers (drivers/tty/serial/8250/8250_pxa.c and
> > drivers/tty/serial/8250/8250_lp8x4x.c).
> > 
> > Depending on the order you register your platform devices (which you
> > decide in your platform code), but let's say the pxa gets registered
> > first and let's say it only has one port. You will then have in your
> > system /dev/ttyS0 for the pxa port and /dev/ttyS[1-4] for the other
> > UART.
> > 
> > I hope I was able to explain what I mean this time :)
> 
> Sorry, I wasn't clear as well. I got it right the first time. You mean
> pxa.c needs to merged into 8250. This will solve the conflict in
> question, and do it the right way. However, this will be a *much* bigger
> patch, and it will affect everyone on pxa.
> 
> Who makes the decision which way to go?

Greg and Russel make this decision. By having the pxa driver simply
register 8250 ports would probable reduce the code. Thats about the
biggest benefit from it.

It would still be something nice to have IMO. Ideally all the
8250/16x50 UARTs should register the ports with 8250_core.c, and not
create complete uart driver on their own.

Br,

-- 
heikki

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

* Re: [PATCH 01/11] resolve PXA<->8250 serial device address conflict
  2013-12-02 14:10             ` Heikki Krogerus
@ 2013-12-05  4:12               ` Greg Kroah-Hartman
  -1 siblings, 0 replies; 700+ messages in thread
From: Greg Kroah-Hartman @ 2013-12-05  4:12 UTC (permalink / raw)
  To: Heikki Krogerus
  Cc: Sergei Ianovich, linux-kernel, linux-arm-kernel, Jiri Slaby,
	open list:SERIAL DRIVERS

On Mon, Dec 02, 2013 at 04:10:33PM +0200, Heikki Krogerus wrote:
> Hi,
> 
> On Mon, Dec 02, 2013 at 02:26:45PM +0400, Sergei Ianovich wrote:
> > On Mon, 2013-12-02 at 11:49 +0200, Heikki Krogerus wrote:
> > > On Mon, Dec 02, 2013 at 01:23:58PM +0400, Sergei Ianovich wrote:
> > > > On Mon, 2013-12-02 at 11:02 +0200, Heikki Krogerus wrote:
> > > > > 
> > > > > If drivers/tty/serial/pxa.c was converted to an other probe driver for
> > > > > the 8250, this would not be an issue.
> > > > 
> > > > It seems that my patch is not going to be accepted. However, there is a
> > > > device which has both PXA ports and a additional 8250 accent chip. As a
> > > > result, there is a device allocation conflict. For the device to be
> > > > usable the conflict needs to be resolved.
> > > > 
> > > > Do you mean that drivers/tty/serial/pxa.c needs to be rewritten to
> > > > support lp8x4x special case?
> > > 
> > > Sorry I was not clear. I was suggesting that drivers/tty/serial/pxa.c
> > > would be converted to drivers/tty/serial/8250/8250_pxa.c since it
> > > looks to me like just an other 16x50 compatible UART. That would fix
> > > the issue with the name conflict. You would then simply register 8250
> > > ports from two probe drivers (drivers/tty/serial/8250/8250_pxa.c and
> > > drivers/tty/serial/8250/8250_lp8x4x.c).
> > > 
> > > Depending on the order you register your platform devices (which you
> > > decide in your platform code), but let's say the pxa gets registered
> > > first and let's say it only has one port. You will then have in your
> > > system /dev/ttyS0 for the pxa port and /dev/ttyS[1-4] for the other
> > > UART.
> > > 
> > > I hope I was able to explain what I mean this time :)
> > 
> > Sorry, I wasn't clear as well. I got it right the first time. You mean
> > pxa.c needs to merged into 8250. This will solve the conflict in
> > question, and do it the right way. However, this will be a *much* bigger
> > patch, and it will affect everyone on pxa.
> > 
> > Who makes the decision which way to go?
> 
> Greg and Russel make this decision. By having the pxa driver simply
> register 8250 ports would probable reduce the code. Thats about the
> biggest benefit from it.
> 
> It would still be something nice to have IMO. Ideally all the
> 8250/16x50 UARTs should register the ports with 8250_core.c, and not
> create complete uart driver on their own.

I agree, this is the best way to resolve this, having a separate uart
driver isn't that good at all to be doing, if at all possible.

thanks,

greg k-h

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

* [PATCH 01/11] resolve PXA<->8250 serial device address conflict
@ 2013-12-05  4:12               ` Greg Kroah-Hartman
  0 siblings, 0 replies; 700+ messages in thread
From: Greg Kroah-Hartman @ 2013-12-05  4:12 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Dec 02, 2013 at 04:10:33PM +0200, Heikki Krogerus wrote:
> Hi,
> 
> On Mon, Dec 02, 2013 at 02:26:45PM +0400, Sergei Ianovich wrote:
> > On Mon, 2013-12-02 at 11:49 +0200, Heikki Krogerus wrote:
> > > On Mon, Dec 02, 2013 at 01:23:58PM +0400, Sergei Ianovich wrote:
> > > > On Mon, 2013-12-02 at 11:02 +0200, Heikki Krogerus wrote:
> > > > > 
> > > > > If drivers/tty/serial/pxa.c was converted to an other probe driver for
> > > > > the 8250, this would not be an issue.
> > > > 
> > > > It seems that my patch is not going to be accepted. However, there is a
> > > > device which has both PXA ports and a additional 8250 accent chip. As a
> > > > result, there is a device allocation conflict. For the device to be
> > > > usable the conflict needs to be resolved.
> > > > 
> > > > Do you mean that drivers/tty/serial/pxa.c needs to be rewritten to
> > > > support lp8x4x special case?
> > > 
> > > Sorry I was not clear. I was suggesting that drivers/tty/serial/pxa.c
> > > would be converted to drivers/tty/serial/8250/8250_pxa.c since it
> > > looks to me like just an other 16x50 compatible UART. That would fix
> > > the issue with the name conflict. You would then simply register 8250
> > > ports from two probe drivers (drivers/tty/serial/8250/8250_pxa.c and
> > > drivers/tty/serial/8250/8250_lp8x4x.c).
> > > 
> > > Depending on the order you register your platform devices (which you
> > > decide in your platform code), but let's say the pxa gets registered
> > > first and let's say it only has one port. You will then have in your
> > > system /dev/ttyS0 for the pxa port and /dev/ttyS[1-4] for the other
> > > UART.
> > > 
> > > I hope I was able to explain what I mean this time :)
> > 
> > Sorry, I wasn't clear as well. I got it right the first time. You mean
> > pxa.c needs to merged into 8250. This will solve the conflict in
> > question, and do it the right way. However, this will be a *much* bigger
> > patch, and it will affect everyone on pxa.
> > 
> > Who makes the decision which way to go?
> 
> Greg and Russel make this decision. By having the pxa driver simply
> register 8250 ports would probable reduce the code. Thats about the
> biggest benefit from it.
> 
> It would still be something nice to have IMO. Ideally all the
> 8250/16x50 UARTs should register the ports with 8250_core.c, and not
> create complete uart driver on their own.

I agree, this is the best way to resolve this, having a separate uart
driver isn't that good at all to be doing, if at all possible.

thanks,

greg k-h

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

* Re: [PATCH 01/11] resolve PXA<->8250 serial device address conflict
  2013-12-05  4:12               ` Greg Kroah-Hartman
@ 2013-12-05  4:31                 ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-05  4:31 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: Heikki Krogerus, linux-kernel, linux-arm-kernel, Jiri Slaby,
	open list:SERIAL DRIVERS

On Wed, 2013-12-04 at 20:12 -0800, Greg Kroah-Hartman wrote:
> On Mon, Dec 02, 2013 at 04:10:33PM +0200, Heikki Krogerus wrote:
> > On Mon, Dec 02, 2013 at 02:26:45PM +0400, Sergei Ianovich wrote:
> > > Who makes the decision which way to go?
> > 
> > Greg and Russel make this decision. By having the pxa driver simply
> > register 8250 ports would probable reduce the code. Thats about the
> > biggest benefit from it.
> > 
> > It would still be something nice to have IMO. Ideally all the
> > 8250/16x50 UARTs should register the ports with 8250_core.c, and not
> > create complete uart driver on their own.
> 
> I agree, this is the best way to resolve this, having a separate uart
> driver isn't that good at all to be doing, if at all possible.

I'm reading the last message as a confirmation that
drivers/tty/serial/pxa.c needs to be rewritten using 8250_core.c.
However, "if at all possible" confuses me, since we have pxa.c in the
tree and it works. Greg, could you please clarify?


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

* [PATCH 01/11] resolve PXA<->8250 serial device address conflict
@ 2013-12-05  4:31                 ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-05  4:31 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, 2013-12-04 at 20:12 -0800, Greg Kroah-Hartman wrote:
> On Mon, Dec 02, 2013 at 04:10:33PM +0200, Heikki Krogerus wrote:
> > On Mon, Dec 02, 2013 at 02:26:45PM +0400, Sergei Ianovich wrote:
> > > Who makes the decision which way to go?
> > 
> > Greg and Russel make this decision. By having the pxa driver simply
> > register 8250 ports would probable reduce the code. Thats about the
> > biggest benefit from it.
> > 
> > It would still be something nice to have IMO. Ideally all the
> > 8250/16x50 UARTs should register the ports with 8250_core.c, and not
> > create complete uart driver on their own.
> 
> I agree, this is the best way to resolve this, having a separate uart
> driver isn't that good at all to be doing, if at all possible.

I'm reading the last message as a confirmation that
drivers/tty/serial/pxa.c needs to be rewritten using 8250_core.c.
However, "if at all possible" confuses me, since we have pxa.c in the
tree and it works. Greg, could you please clarify?

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

* Re: [PATCH 01/11] resolve PXA<->8250 serial device address conflict
  2013-12-05  4:31                 ` Sergei Ianovich
@ 2013-12-05  4:35                   ` Greg Kroah-Hartman
  -1 siblings, 0 replies; 700+ messages in thread
From: Greg Kroah-Hartman @ 2013-12-05  4:35 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: Heikki Krogerus, linux-kernel, linux-arm-kernel, Jiri Slaby,
	open list:SERIAL DRIVERS

On Thu, Dec 05, 2013 at 08:31:36AM +0400, Sergei Ianovich wrote:
> On Wed, 2013-12-04 at 20:12 -0800, Greg Kroah-Hartman wrote:
> > On Mon, Dec 02, 2013 at 04:10:33PM +0200, Heikki Krogerus wrote:
> > > On Mon, Dec 02, 2013 at 02:26:45PM +0400, Sergei Ianovich wrote:
> > > > Who makes the decision which way to go?
> > > 
> > > Greg and Russel make this decision. By having the pxa driver simply
> > > register 8250 ports would probable reduce the code. Thats about the
> > > biggest benefit from it.
> > > 
> > > It would still be something nice to have IMO. Ideally all the
> > > 8250/16x50 UARTs should register the ports with 8250_core.c, and not
> > > create complete uart driver on their own.
> > 
> > I agree, this is the best way to resolve this, having a separate uart
> > driver isn't that good at all to be doing, if at all possible.
> 
> I'm reading the last message as a confirmation that
> drivers/tty/serial/pxa.c needs to be rewritten using 8250_core.c.

Yes, how much work is this really?

thanks,

greg k-h

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

* [PATCH 01/11] resolve PXA<->8250 serial device address conflict
@ 2013-12-05  4:35                   ` Greg Kroah-Hartman
  0 siblings, 0 replies; 700+ messages in thread
From: Greg Kroah-Hartman @ 2013-12-05  4:35 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Dec 05, 2013 at 08:31:36AM +0400, Sergei Ianovich wrote:
> On Wed, 2013-12-04 at 20:12 -0800, Greg Kroah-Hartman wrote:
> > On Mon, Dec 02, 2013 at 04:10:33PM +0200, Heikki Krogerus wrote:
> > > On Mon, Dec 02, 2013 at 02:26:45PM +0400, Sergei Ianovich wrote:
> > > > Who makes the decision which way to go?
> > > 
> > > Greg and Russel make this decision. By having the pxa driver simply
> > > register 8250 ports would probable reduce the code. Thats about the
> > > biggest benefit from it.
> > > 
> > > It would still be something nice to have IMO. Ideally all the
> > > 8250/16x50 UARTs should register the ports with 8250_core.c, and not
> > > create complete uart driver on their own.
> > 
> > I agree, this is the best way to resolve this, having a separate uart
> > driver isn't that good at all to be doing, if at all possible.
> 
> I'm reading the last message as a confirmation that
> drivers/tty/serial/pxa.c needs to be rewritten using 8250_core.c.

Yes, how much work is this really?

thanks,

greg k-h

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

* Re: [PATCH 01/11] resolve PXA<->8250 serial device address conflict
  2013-12-05  4:35                   ` Greg Kroah-Hartman
@ 2013-12-05  4:36                     ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-05  4:36 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: Heikki Krogerus, linux-kernel, linux-arm-kernel, Jiri Slaby,
	open list:SERIAL DRIVERS

On Wed, 2013-12-04 at 20:35 -0800, Greg Kroah-Hartman wrote:
> On Thu, Dec 05, 2013 at 08:31:36AM +0400, Sergei Ianovich wrote:
> > I'm reading the last message as a confirmation that
> > drivers/tty/serial/pxa.c needs to be rewritten using 8250_core.c.
> 
> Yes, how much work is this really?

Great. It seems two drivers practically match. I'll do and submit a
merge patch.


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

* [PATCH 01/11] resolve PXA<->8250 serial device address conflict
@ 2013-12-05  4:36                     ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-05  4:36 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, 2013-12-04 at 20:35 -0800, Greg Kroah-Hartman wrote:
> On Thu, Dec 05, 2013 at 08:31:36AM +0400, Sergei Ianovich wrote:
> > I'm reading the last message as a confirmation that
> > drivers/tty/serial/pxa.c needs to be rewritten using 8250_core.c.
> 
> Yes, how much work is this really?

Great. It seems two drivers practically match. I'll do and submit a
merge patch.

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

* [PATCH] serial: rewrite pxa2xx-uart to use 8250_core
@ 2013-12-05 23:28                     ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-05 23:28 UTC (permalink / raw)
  To: linux-kernel
  Cc: Sergei Ianovich, Heikki Krogerus, Greg Kroah-Hartman,
	Russell King, Jiri Slaby, Grant Likely, Rob Herring, Zhou Zhu,
	Andrew Morton, Haojian Zhuang, Ralf Baechle, John Crispin,
	moderated list:ARM PORT, open list:SERIAL DRIVERS,
	open list:OPEN FIRMWARE AND...

pxa2xx-uart was a separate uart platform driver. It was declaring
the same device names and numbers as 8250 driver. As a result,
it was impossible to use 8250 driver on PXA SoCs.

Upon closer examination pxa2xx-uart turned out to be a clone of
8250_core driver.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Heikki Krogerus <heikki.krogerus@linux.intel.com>
CC: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 arch/arm/configs/am200epdkit_defconfig    |   3 +-
 arch/arm/configs/cm_x2xx_defconfig        |   3 +-
 arch/arm/configs/cm_x300_defconfig        |   3 +-
 arch/arm/configs/colibri_pxa270_defconfig |   3 +-
 arch/arm/configs/colibri_pxa300_defconfig |   3 +-
 arch/arm/configs/corgi_defconfig          |   4 +-
 arch/arm/configs/em_x270_defconfig        |   3 +-
 arch/arm/configs/ezx_defconfig            |   3 +-
 arch/arm/configs/h5000_defconfig          |   3 +-
 arch/arm/configs/imote2_defconfig         |   3 +-
 arch/arm/configs/lpd270_defconfig         |   3 +-
 arch/arm/configs/lubbock_defconfig        |   3 +-
 arch/arm/configs/mainstone_defconfig      |   3 +-
 arch/arm/configs/mmp2_defconfig           |   3 +-
 arch/arm/configs/pcm027_defconfig         |   3 +-
 arch/arm/configs/pxa168_defconfig         |   3 +-
 arch/arm/configs/pxa255-idp_defconfig     |   3 +-
 arch/arm/configs/pxa3xx_defconfig         |   3 +-
 arch/arm/configs/pxa910_defconfig         |   3 +-
 arch/arm/configs/raumfeld_defconfig       |   3 +-
 arch/arm/configs/spitz_defconfig          |   4 +-
 arch/arm/configs/trizeps4_defconfig       |   3 +-
 arch/arm/configs/viper_defconfig          |   4 +-
 arch/arm/configs/xcep_defconfig           |   3 +-
 drivers/tty/serial/8250/8250_pxa.c        | 180 ++++++
 drivers/tty/serial/8250/Kconfig           |   9 +
 drivers/tty/serial/8250/Makefile          |   1 +
 drivers/tty/serial/Kconfig                |  23 -
 drivers/tty/serial/Makefile               |   1 -
 drivers/tty/serial/pxa.c                  | 971 ------------------------------
 30 files changed, 238 insertions(+), 1022 deletions(-)
 create mode 100644 drivers/tty/serial/8250/8250_pxa.c
 delete mode 100644 drivers/tty/serial/pxa.c

diff --git a/arch/arm/configs/am200epdkit_defconfig b/arch/arm/configs/am200epdkit_defconfig
index f0dea52..0cde234 100644
--- a/arch/arm/configs/am200epdkit_defconfig
+++ b/arch/arm/configs/am200epdkit_defconfig
@@ -60,8 +60,9 @@ CONFIG_BLK_DEV_IDECS=m
 CONFIG_NETDEVICES=y
 CONFIG_NET_ETHERNET=y
 CONFIG_SMC91X=m
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 # CONFIG_HWMON is not set
diff --git a/arch/arm/configs/cm_x2xx_defconfig b/arch/arm/configs/cm_x2xx_defconfig
index a93ff8d..b9fbe65 100644
--- a/arch/arm/configs/cm_x2xx_defconfig
+++ b/arch/arm/configs/cm_x2xx_defconfig
@@ -96,8 +96,9 @@ CONFIG_KEYBOARD_PXA27x=m
 CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_TOUCHSCREEN_UCB1400=m
 # CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_LEGACY_PTY_COUNT=16
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/cm_x300_defconfig b/arch/arm/configs/cm_x300_defconfig
index f4b7672..53a82ae 100644
--- a/arch/arm/configs/cm_x300_defconfig
+++ b/arch/arm/configs/cm_x300_defconfig
@@ -80,8 +80,9 @@ CONFIG_TOUCHSCREEN_WM97XX=m
 # CONFIG_TOUCHSCREEN_WM9713 is not set
 # CONFIG_SERIO is not set
 # CONFIG_LEGACY_PTYS is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
 CONFIG_I2C_PXA=y
diff --git a/arch/arm/configs/colibri_pxa270_defconfig b/arch/arm/configs/colibri_pxa270_defconfig
index 2ef2c5e..1ce0409 100644
--- a/arch/arm/configs/colibri_pxa270_defconfig
+++ b/arch/arm/configs/colibri_pxa270_defconfig
@@ -103,8 +103,9 @@ CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=m
 CONFIG_SERIO_LIBPS2=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_HW_RANDOM=y
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
diff --git a/arch/arm/configs/colibri_pxa300_defconfig b/arch/arm/configs/colibri_pxa300_defconfig
index b985334..f96bda0 100644
--- a/arch/arm/configs/colibri_pxa300_defconfig
+++ b/arch/arm/configs/colibri_pxa300_defconfig
@@ -31,8 +31,9 @@ CONFIG_INPUT_EVDEV=y
 # CONFIG_INPUT_MOUSE is not set
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_GPIO_ROTARY_ENCODER=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_HW_RANDOM=y
 CONFIG_DEBUG_GPIO=y
 # CONFIG_HWMON is not set
diff --git a/arch/arm/configs/corgi_defconfig b/arch/arm/configs/corgi_defconfig
index 1fd1d1d..bb4842d 100644
--- a/arch/arm/configs/corgi_defconfig
+++ b/arch/arm/configs/corgi_defconfig
@@ -131,10 +131,10 @@ CONFIG_TOUCHSCREEN_ADS7846=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=m
 # CONFIG_SERIO is not set
-CONFIG_SERIAL_8250=m
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_CS=m
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 CONFIG_I2C=y
 CONFIG_I2C_PXA=y
diff --git a/arch/arm/configs/em_x270_defconfig b/arch/arm/configs/em_x270_defconfig
index 60a21e0..ec0ec54 100644
--- a/arch/arm/configs/em_x270_defconfig
+++ b/arch/arm/configs/em_x270_defconfig
@@ -90,8 +90,9 @@ CONFIG_TOUCHSCREEN_WM97XX=m
 # CONFIG_TOUCHSCREEN_WM9705 is not set
 # CONFIG_TOUCHSCREEN_WM9713 is not set
 # CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_LEGACY_PTY_COUNT=16
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/ezx_defconfig b/arch/arm/configs/ezx_defconfig
index d95763d..631e2ec 100644
--- a/arch/arm/configs/ezx_defconfig
+++ b/arch/arm/configs/ezx_defconfig
@@ -215,8 +215,9 @@ CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=y
 CONFIG_INPUT_PCAP=y
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_LEGACY_PTY_COUNT=8
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/h5000_defconfig b/arch/arm/configs/h5000_defconfig
index 37903e3..655b735 100644
--- a/arch/arm/configs/h5000_defconfig
+++ b/arch/arm/configs/h5000_defconfig
@@ -47,8 +47,9 @@ CONFIG_MTD_PHYSMAP=y
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_LEGACY_PTY_COUNT=32
 # CONFIG_HW_RANDOM is not set
 # CONFIG_HWMON is not set
diff --git a/arch/arm/configs/imote2_defconfig b/arch/arm/configs/imote2_defconfig
index fd996bb..49d45e9 100644
--- a/arch/arm/configs/imote2_defconfig
+++ b/arch/arm/configs/imote2_defconfig
@@ -193,8 +193,9 @@ CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=y
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_LEGACY_PTY_COUNT=8
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/lpd270_defconfig b/arch/arm/configs/lpd270_defconfig
index 1c8c9ee..c3927b6 100644
--- a/arch/arm/configs/lpd270_defconfig
+++ b/arch/arm/configs/lpd270_defconfig
@@ -38,8 +38,9 @@ CONFIG_SMC91X=y
 CONFIG_INPUT_EVDEV=y
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_HW_RANDOM is not set
 CONFIG_FB=y
 CONFIG_FB_PXA=y
diff --git a/arch/arm/configs/lubbock_defconfig b/arch/arm/configs/lubbock_defconfig
index c4ba274..c8b0436 100644
--- a/arch/arm/configs/lubbock_defconfig
+++ b/arch/arm/configs/lubbock_defconfig
@@ -37,8 +37,9 @@ CONFIG_PCMCIA_PCNET=y
 CONFIG_INPUT_EVDEV=y
 # CONFIG_SERIO_SERPORT is not set
 CONFIG_SERIO_SA1111=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_USB_GADGET=y
 CONFIG_USB_G_SERIAL=m
diff --git a/arch/arm/configs/mainstone_defconfig b/arch/arm/configs/mainstone_defconfig
index 04efa1b..768892c 100644
--- a/arch/arm/configs/mainstone_defconfig
+++ b/arch/arm/configs/mainstone_defconfig
@@ -34,8 +34,9 @@ CONFIG_SMC91X=y
 CONFIG_INPUT_EVDEV=y
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_FB=y
 CONFIG_FB_PXA=y
 # CONFIG_VGA_CONSOLE is not set
diff --git a/arch/arm/configs/mmp2_defconfig b/arch/arm/configs/mmp2_defconfig
index f1cb95e..1ced9df 100644
--- a/arch/arm/configs/mmp2_defconfig
+++ b/arch/arm/configs/mmp2_defconfig
@@ -44,8 +44,9 @@ CONFIG_SMC91X=y
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/pcm027_defconfig b/arch/arm/configs/pcm027_defconfig
index 2f136c3..1280128 100644
--- a/arch/arm/configs/pcm027_defconfig
+++ b/arch/arm/configs/pcm027_defconfig
@@ -60,8 +60,9 @@ CONFIG_SMC91X=y
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/pxa168_defconfig b/arch/arm/configs/pxa168_defconfig
index 74d7e01..1668dac 100644
--- a/arch/arm/configs/pxa168_defconfig
+++ b/arch/arm/configs/pxa168_defconfig
@@ -40,8 +40,9 @@ CONFIG_SMC91X=y
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 # CONFIG_HWMON is not set
diff --git a/arch/arm/configs/pxa255-idp_defconfig b/arch/arm/configs/pxa255-idp_defconfig
index 917a070..399a706 100644
--- a/arch/arm/configs/pxa255-idp_defconfig
+++ b/arch/arm/configs/pxa255-idp_defconfig
@@ -35,8 +35,9 @@ CONFIG_SMC91X=y
 CONFIG_INPUT_EVDEV=y
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_FB=y
 CONFIG_FB_PXA=y
 # CONFIG_VGA_CONSOLE is not set
diff --git a/arch/arm/configs/pxa3xx_defconfig b/arch/arm/configs/pxa3xx_defconfig
index 60e3138..7c3e052 100644
--- a/arch/arm/configs/pxa3xx_defconfig
+++ b/arch/arm/configs/pxa3xx_defconfig
@@ -56,8 +56,9 @@ CONFIG_KEYBOARD_PXA27x=y
 CONFIG_KEYBOARD_PXA930_ROTARY=y
 CONFIG_MOUSE_PXA930_TRKBALL=y
 CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/pxa910_defconfig b/arch/arm/configs/pxa910_defconfig
index 3bb7771..cdacfcb 100644
--- a/arch/arm/configs/pxa910_defconfig
+++ b/arch/arm/configs/pxa910_defconfig
@@ -40,8 +40,9 @@ CONFIG_SMC91X=y
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_SPI=y
 CONFIG_FB=y
 CONFIG_MMP_DISP=y
diff --git a/arch/arm/configs/raumfeld_defconfig b/arch/arm/configs/raumfeld_defconfig
index f7caa90..f1e16f2 100644
--- a/arch/arm/configs/raumfeld_defconfig
+++ b/arch/arm/configs/raumfeld_defconfig
@@ -67,8 +67,9 @@ CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_TOUCHSCREEN_EETI=m
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_GPIO_ROTARY_ENCODER=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_HW_RANDOM=y
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
diff --git a/arch/arm/configs/spitz_defconfig b/arch/arm/configs/spitz_defconfig
index 2e0419d..b6efcf5 100644
--- a/arch/arm/configs/spitz_defconfig
+++ b/arch/arm/configs/spitz_defconfig
@@ -128,10 +128,10 @@ CONFIG_TOUCHSCREEN_ADS7846=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=m
 # CONFIG_SERIO is not set
-CONFIG_SERIAL_8250=m
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_CS=m
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 CONFIG_SPI=y
 CONFIG_SPI_PXA2XX=y
diff --git a/arch/arm/configs/trizeps4_defconfig b/arch/arm/configs/trizeps4_defconfig
index 3162173..453c79c 100644
--- a/arch/arm/configs/trizeps4_defconfig
+++ b/arch/arm/configs/trizeps4_defconfig
@@ -132,8 +132,9 @@ CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=m
 CONFIG_SERIO_LIBPS2=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_HW_RANDOM=y
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
diff --git a/arch/arm/configs/viper_defconfig b/arch/arm/configs/viper_defconfig
index d36e0d3..4efac06 100644
--- a/arch/arm/configs/viper_defconfig
+++ b/arch/arm/configs/viper_defconfig
@@ -101,11 +101,11 @@ CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=m
 # CONFIG_CONSOLE_TRANSLATIONS is not set
 # CONFIG_VT_CONSOLE is not set
-CONFIG_SERIAL_8250=m
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_NR_UARTS=5
 CONFIG_SERIAL_8250_RUNTIME_UARTS=5
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
diff --git a/arch/arm/configs/xcep_defconfig b/arch/arm/configs/xcep_defconfig
index 721832f..b67aeaf 100644
--- a/arch/arm/configs/xcep_defconfig
+++ b/arch/arm/configs/xcep_defconfig
@@ -60,8 +60,9 @@ CONFIG_NET_ETHERNET=y
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
 # CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=m
diff --git a/drivers/tty/serial/8250/8250_pxa.c b/drivers/tty/serial/8250/8250_pxa.c
new file mode 100644
index 0000000..5658fc9
--- /dev/null
+++ b/drivers/tty/serial/8250/8250_pxa.c
@@ -0,0 +1,180 @@
+/*
+ *  drivers/tty/serial/8250/8250_pxa.c -- driver for PXA on-board UARTS
+ *  Copyright:	(C) 2013 Sergei Ianovich <ynvich@gmail.com>
+ *
+ *  replaces drivers/serial/pxa.c by Nicolas Pitre
+ *  Created:	Feb 20, 2003
+ *  Copyright:	(C) 2003 Monta Vista Software, Inc.
+ *
+ *  Based on drivers/serial/8250.c by Russell King.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/serial_8250.h>
+#include <linux/serial_core.h>
+#include <linux/serial_reg.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
+#include <linux/pm_runtime.h>
+
+#include "8250.h"
+
+struct pxa8250_data {
+	int			line;
+	struct clk		*clk;
+};
+
+#ifdef CONFIG_PM
+static int serial_pxa_suspend(struct device *dev)
+{
+	struct pxa8250_data *data = dev_get_drvdata(dev);
+
+	serial8250_suspend_port(data->line);
+
+	return 0;
+}
+
+static int serial_pxa_resume(struct device *dev)
+{
+	struct pxa8250_data *data = dev_get_drvdata(dev);
+
+	serial8250_resume_port(data->line);
+
+	return 0;
+}
+
+static const struct dev_pm_ops serial_pxa_pm_ops = {
+	.suspend	= serial_pxa_suspend,
+	.resume		= serial_pxa_resume,
+};
+#endif
+
+static struct of_device_id serial_pxa_dt_ids[] = {
+	{ .compatible = "mrvl,pxa-uart", },
+	{ .compatible = "mrvl,mmp-uart", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, serial_pxa_dt_ids);
+
+/* Uart divisor latch write */
+static void serial_pxa_dl_write(struct uart_8250_port *up, int value)
+{
+	serial_out(up, UART_DLL, value & 0xff);
+	serial_out(up, UART_DLM, value >> 8 & 0xff);
+}
+
+
+static void serial_pxa_pm(struct uart_port *port, unsigned int state,
+	      unsigned int oldstate)
+{
+	struct pxa8250_data *data = port->private_data;
+
+	if (!state)
+		clk_prepare_enable(data->clk);
+	else
+		clk_disable_unprepare(data->clk);
+}
+
+static int serial_pxa_probe(struct platform_device *pdev)
+{
+	struct uart_8250_port uart = {};
+	struct pxa8250_data *data;
+	struct resource *mmres, *irqres;
+	int ret;
+
+	mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	irqres = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!mmres || !irqres)
+		return -ENODEV;
+
+	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(data->clk)) {
+		ret = PTR_ERR(data->clk);
+		goto err_free;
+	}
+
+	ret = clk_prepare(data->clk);
+	if (ret)
+		goto err_free_clk;
+
+	uart.port.type = PORT_XSCALE;
+	uart.port.iotype = UPIO_MEM32;
+	uart.port.mapbase = mmres->start;
+	uart.port.regshift = 2;
+	uart.port.irq = irqres->start;
+	uart.port.fifosize = 64;
+	uart.port.flags = UPF_IOREMAP | UPF_SKIP_TEST;
+	uart.port.dev = &pdev->dev;
+	uart.port.uartclk = clk_get_rate(data->clk);
+	uart.port.pm = serial_pxa_pm;
+	uart.port.private_data = data;
+	uart.dl_write = serial_pxa_dl_write;
+
+	ret = serial8250_register_8250_port(&uart);
+	if (ret < 0)
+		goto err_clk;
+
+	data->line = ret;
+
+	platform_set_drvdata(pdev, data);
+
+	return 0;
+
+ err_clk:
+	clk_unprepare(data->clk);
+ err_free_clk:
+	devm_clk_put(&pdev->dev, data->clk);
+ err_free:
+	devm_kfree(&pdev->dev, data);
+	return ret;
+}
+
+static int serial_pxa_remove(struct platform_device *pdev)
+{
+	struct pxa8250_data *data = platform_get_drvdata(pdev);
+
+	serial8250_unregister_port(data->line);
+
+	clk_unprepare(data->clk);
+	devm_clk_put(&pdev->dev, data->clk);
+	devm_kfree(&pdev->dev, data);
+
+	return 0;
+}
+
+static struct platform_driver serial_pxa_driver = {
+	.probe          = serial_pxa_probe,
+	.remove         = serial_pxa_remove,
+
+	.driver		= {
+		.name	= "pxa2xx-uart",
+		.owner	= THIS_MODULE,
+#ifdef CONFIG_PM
+		.pm	= &serial_pxa_pm_ops,
+#endif
+		.of_match_table = serial_pxa_dt_ids,
+	},
+};
+
+module_platform_driver(serial_pxa_driver);
+
+MODULE_AUTHOR("Sergei Ianovich");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:pxa2xx-uart");
diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
index 2332991..81bd7c9 100644
--- a/drivers/tty/serial/8250/Kconfig
+++ b/drivers/tty/serial/8250/Kconfig
@@ -302,3 +302,12 @@ config SERIAL_8250_RT288X
 	  If you have a Ralink RT288x/RT305x SoC based board and want to use the
 	  serial port, say Y to this option. The driver can handle up to 2 serial
 	  ports. If unsure, say N.
+
+config SERIAL_PXA
+	tristate "PXA serial port support"
+	depends on SERIAL_8250 && (ARCH_PXA || ARCH_MMP)
+	help
+	  If you have a machine based on an Intel XScale PXA2xx CPU you
+	  can enable its onboard serial ports by enabling this option.
+
+	  If you choose M here, the module name will be 8250_pxa.
diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile
index 36d68d0..b7d1b61 100644
--- a/drivers/tty/serial/8250/Makefile
+++ b/drivers/tty/serial/8250/Makefile
@@ -20,3 +20,4 @@ obj-$(CONFIG_SERIAL_8250_HUB6)		+= 8250_hub6.o
 obj-$(CONFIG_SERIAL_8250_FSL)		+= 8250_fsl.o
 obj-$(CONFIG_SERIAL_8250_DW)		+= 8250_dw.o
 obj-$(CONFIG_SERIAL_8250_EM)		+= 8250_em.o
+obj-$(CONFIG_SERIAL_PXA)		+= 8250_pxa.o
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index a3817ab..2ad7184b 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -396,29 +396,6 @@ config SERIAL_MPSC_CONSOLE
 	help
 	  Say Y here if you want to support a serial console on a Marvell MPSC.
 
-config SERIAL_PXA
-	bool "PXA serial port support"
-	depends on ARCH_PXA || ARCH_MMP
-	select SERIAL_CORE
-	help
-	  If you have a machine based on an Intel XScale PXA2xx CPU you
-	  can enable its onboard serial ports by enabling this option.
-
-config SERIAL_PXA_CONSOLE
-	bool "Console on PXA serial port"
-	depends on SERIAL_PXA
-	select SERIAL_CORE_CONSOLE
-	help
-	  If you have enabled the serial port on the Intel XScale PXA
-	  CPU you can make it the console by answering Y to this option.
-
-	  Even if you say Y here, the currently visible virtual console
-	  (/dev/tty0) will still be used as the system console by default, but
-	  you can alter that using a kernel command line option such as
-	  "console=ttySA0". (Try "man bootparam" or see the documentation of
-	  your boot loader (lilo or loadlin) about how to pass options to the
-	  kernel at boot time.)
-
 config SERIAL_SA1100
 	bool "SA1100 serial port support"
 	depends on ARCH_SA1100
diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile
index 3068c77..4ac337b 100644
--- a/drivers/tty/serial/Makefile
+++ b/drivers/tty/serial/Makefile
@@ -20,7 +20,6 @@ obj-$(CONFIG_SERIAL_8250) += 8250/
 obj-$(CONFIG_SERIAL_AMBA_PL010) += amba-pl010.o
 obj-$(CONFIG_SERIAL_AMBA_PL011) += amba-pl011.o
 obj-$(CONFIG_SERIAL_CLPS711X) += clps711x.o
-obj-$(CONFIG_SERIAL_PXA) += pxa.o
 obj-$(CONFIG_SERIAL_PNX8XXX) += pnx8xxx_uart.o
 obj-$(CONFIG_SERIAL_SA1100) += sa1100.o
 obj-$(CONFIG_SERIAL_BCM63XX) += bcm63xx_uart.o
diff --git a/drivers/tty/serial/pxa.c b/drivers/tty/serial/pxa.c
deleted file mode 100644
index f9f20f3..0000000
--- a/drivers/tty/serial/pxa.c
+++ /dev/null
@@ -1,971 +0,0 @@
-/*
- *  Based on drivers/serial/8250.c by Russell King.
- *
- *  Author:	Nicolas Pitre
- *  Created:	Feb 20, 2003
- *  Copyright:	(C) 2003 Monta Vista Software, Inc.
- *
- * 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.
- *
- * Note 1: This driver is made separate from the already too overloaded
- * 8250.c because it needs some kirks of its own and that'll make it
- * easier to add DMA support.
- *
- * Note 2: I'm too sick of device allocation policies for serial ports.
- * If someone else wants to request an "official" allocation of major/minor
- * for this driver please be my guest.  And don't forget that new hardware
- * to come from Intel might have more than 3 or 4 of those UARTs.  Let's
- * hope for a better port registration and dynamic device allocation scheme
- * with the serial core maintainer satisfaction to appear soon.
- */
-
-
-#if defined(CONFIG_SERIAL_PXA_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-#define SUPPORT_SYSRQ
-#endif
-
-#include <linux/module.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-#include <linux/console.h>
-#include <linux/sysrq.h>
-#include <linux/serial_reg.h>
-#include <linux/circ_buf.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/of.h>
-#include <linux/platform_device.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/serial_core.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-
-#define PXA_NAME_LEN		8
-
-struct uart_pxa_port {
-	struct uart_port        port;
-	unsigned char           ier;
-	unsigned char           lcr;
-	unsigned char           mcr;
-	unsigned int            lsr_break_flag;
-	struct clk		*clk;
-	char			name[PXA_NAME_LEN];
-};
-
-static inline unsigned int serial_in(struct uart_pxa_port *up, int offset)
-{
-	offset <<= 2;
-	return readl(up->port.membase + offset);
-}
-
-static inline void serial_out(struct uart_pxa_port *up, int offset, int value)
-{
-	offset <<= 2;
-	writel(value, up->port.membase + offset);
-}
-
-static void serial_pxa_enable_ms(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	up->ier |= UART_IER_MSI;
-	serial_out(up, UART_IER, up->ier);
-}
-
-static void serial_pxa_stop_tx(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	if (up->ier & UART_IER_THRI) {
-		up->ier &= ~UART_IER_THRI;
-		serial_out(up, UART_IER, up->ier);
-	}
-}
-
-static void serial_pxa_stop_rx(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	up->ier &= ~UART_IER_RLSI;
-	up->port.read_status_mask &= ~UART_LSR_DR;
-	serial_out(up, UART_IER, up->ier);
-}
-
-static inline void receive_chars(struct uart_pxa_port *up, int *status)
-{
-	unsigned int ch, flag;
-	int max_count = 256;
-
-	do {
-		/* work around Errata #20 according to
-		 * Intel(R) PXA27x Processor Family
-		 * Specification Update (May 2005)
-		 *
-		 * Step 2
-		 * Disable the Reciever Time Out Interrupt via IER[RTOEI]
-		 */
-		up->ier &= ~UART_IER_RTOIE;
-		serial_out(up, UART_IER, up->ier);
-
-		ch = serial_in(up, UART_RX);
-		flag = TTY_NORMAL;
-		up->port.icount.rx++;
-
-		if (unlikely(*status & (UART_LSR_BI | UART_LSR_PE |
-				       UART_LSR_FE | UART_LSR_OE))) {
-			/*
-			 * For statistics only
-			 */
-			if (*status & UART_LSR_BI) {
-				*status &= ~(UART_LSR_FE | UART_LSR_PE);
-				up->port.icount.brk++;
-				/*
-				 * We do the SysRQ and SAK checking
-				 * here because otherwise the break
-				 * may get masked by ignore_status_mask
-				 * or read_status_mask.
-				 */
-				if (uart_handle_break(&up->port))
-					goto ignore_char;
-			} else if (*status & UART_LSR_PE)
-				up->port.icount.parity++;
-			else if (*status & UART_LSR_FE)
-				up->port.icount.frame++;
-			if (*status & UART_LSR_OE)
-				up->port.icount.overrun++;
-
-			/*
-			 * Mask off conditions which should be ignored.
-			 */
-			*status &= up->port.read_status_mask;
-
-#ifdef CONFIG_SERIAL_PXA_CONSOLE
-			if (up->port.line == up->port.cons->index) {
-				/* Recover the break flag from console xmit */
-				*status |= up->lsr_break_flag;
-				up->lsr_break_flag = 0;
-			}
-#endif
-			if (*status & UART_LSR_BI) {
-				flag = TTY_BREAK;
-			} else if (*status & UART_LSR_PE)
-				flag = TTY_PARITY;
-			else if (*status & UART_LSR_FE)
-				flag = TTY_FRAME;
-		}
-
-		if (uart_handle_sysrq_char(&up->port, ch))
-			goto ignore_char;
-
-		uart_insert_char(&up->port, *status, UART_LSR_OE, ch, flag);
-
-	ignore_char:
-		*status = serial_in(up, UART_LSR);
-	} while ((*status & UART_LSR_DR) && (max_count-- > 0));
-	tty_flip_buffer_push(&up->port.state->port);
-
-	/* work around Errata #20 according to
-	 * Intel(R) PXA27x Processor Family
-	 * Specification Update (May 2005)
-	 *
-	 * Step 6:
-	 * No more data in FIFO: Re-enable RTO interrupt via IER[RTOIE]
-	 */
-	up->ier |= UART_IER_RTOIE;
-	serial_out(up, UART_IER, up->ier);
-}
-
-static void transmit_chars(struct uart_pxa_port *up)
-{
-	struct circ_buf *xmit = &up->port.state->xmit;
-	int count;
-
-	if (up->port.x_char) {
-		serial_out(up, UART_TX, up->port.x_char);
-		up->port.icount.tx++;
-		up->port.x_char = 0;
-		return;
-	}
-	if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) {
-		serial_pxa_stop_tx(&up->port);
-		return;
-	}
-
-	count = up->port.fifosize / 2;
-	do {
-		serial_out(up, UART_TX, xmit->buf[xmit->tail]);
-		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
-		up->port.icount.tx++;
-		if (uart_circ_empty(xmit))
-			break;
-	} while (--count > 0);
-
-	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
-		uart_write_wakeup(&up->port);
-
-
-	if (uart_circ_empty(xmit))
-		serial_pxa_stop_tx(&up->port);
-}
-
-static void serial_pxa_start_tx(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	if (!(up->ier & UART_IER_THRI)) {
-		up->ier |= UART_IER_THRI;
-		serial_out(up, UART_IER, up->ier);
-	}
-}
-
-static inline void check_modem_status(struct uart_pxa_port *up)
-{
-	int status;
-
-	status = serial_in(up, UART_MSR);
-
-	if ((status & UART_MSR_ANY_DELTA) == 0)
-		return;
-
-	if (status & UART_MSR_TERI)
-		up->port.icount.rng++;
-	if (status & UART_MSR_DDSR)
-		up->port.icount.dsr++;
-	if (status & UART_MSR_DDCD)
-		uart_handle_dcd_change(&up->port, status & UART_MSR_DCD);
-	if (status & UART_MSR_DCTS)
-		uart_handle_cts_change(&up->port, status & UART_MSR_CTS);
-
-	wake_up_interruptible(&up->port.state->port.delta_msr_wait);
-}
-
-/*
- * This handles the interrupt from one port.
- */
-static inline irqreturn_t serial_pxa_irq(int irq, void *dev_id)
-{
-	struct uart_pxa_port *up = dev_id;
-	unsigned int iir, lsr;
-
-	iir = serial_in(up, UART_IIR);
-	if (iir & UART_IIR_NO_INT)
-		return IRQ_NONE;
-	lsr = serial_in(up, UART_LSR);
-	if (lsr & UART_LSR_DR)
-		receive_chars(up, &lsr);
-	check_modem_status(up);
-	if (lsr & UART_LSR_THRE)
-		transmit_chars(up);
-	return IRQ_HANDLED;
-}
-
-static unsigned int serial_pxa_tx_empty(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned long flags;
-	unsigned int ret;
-
-	spin_lock_irqsave(&up->port.lock, flags);
-	ret = serial_in(up, UART_LSR) & UART_LSR_TEMT ? TIOCSER_TEMT : 0;
-	spin_unlock_irqrestore(&up->port.lock, flags);
-
-	return ret;
-}
-
-static unsigned int serial_pxa_get_mctrl(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned char status;
-	unsigned int ret;
-
-	status = serial_in(up, UART_MSR);
-
-	ret = 0;
-	if (status & UART_MSR_DCD)
-		ret |= TIOCM_CAR;
-	if (status & UART_MSR_RI)
-		ret |= TIOCM_RNG;
-	if (status & UART_MSR_DSR)
-		ret |= TIOCM_DSR;
-	if (status & UART_MSR_CTS)
-		ret |= TIOCM_CTS;
-	return ret;
-}
-
-static void serial_pxa_set_mctrl(struct uart_port *port, unsigned int mctrl)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned char mcr = 0;
-
-	if (mctrl & TIOCM_RTS)
-		mcr |= UART_MCR_RTS;
-	if (mctrl & TIOCM_DTR)
-		mcr |= UART_MCR_DTR;
-	if (mctrl & TIOCM_OUT1)
-		mcr |= UART_MCR_OUT1;
-	if (mctrl & TIOCM_OUT2)
-		mcr |= UART_MCR_OUT2;
-	if (mctrl & TIOCM_LOOP)
-		mcr |= UART_MCR_LOOP;
-
-	mcr |= up->mcr;
-
-	serial_out(up, UART_MCR, mcr);
-}
-
-static void serial_pxa_break_ctl(struct uart_port *port, int break_state)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned long flags;
-
-	spin_lock_irqsave(&up->port.lock, flags);
-	if (break_state == -1)
-		up->lcr |= UART_LCR_SBC;
-	else
-		up->lcr &= ~UART_LCR_SBC;
-	serial_out(up, UART_LCR, up->lcr);
-	spin_unlock_irqrestore(&up->port.lock, flags);
-}
-
-static int serial_pxa_startup(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned long flags;
-	int retval;
-
-	if (port->line == 3) /* HWUART */
-		up->mcr |= UART_MCR_AFE;
-	else
-		up->mcr = 0;
-
-	up->port.uartclk = clk_get_rate(up->clk);
-
-	/*
-	 * Allocate the IRQ
-	 */
-	retval = request_irq(up->port.irq, serial_pxa_irq, 0, up->name, up);
-	if (retval)
-		return retval;
-
-	/*
-	 * Clear the FIFO buffers and disable them.
-	 * (they will be reenabled in set_termios())
-	 */
-	serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO);
-	serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO |
-			UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
-	serial_out(up, UART_FCR, 0);
-
-	/*
-	 * Clear the interrupt registers.
-	 */
-	(void) serial_in(up, UART_LSR);
-	(void) serial_in(up, UART_RX);
-	(void) serial_in(up, UART_IIR);
-	(void) serial_in(up, UART_MSR);
-
-	/*
-	 * Now, initialize the UART
-	 */
-	serial_out(up, UART_LCR, UART_LCR_WLEN8);
-
-	spin_lock_irqsave(&up->port.lock, flags);
-	up->port.mctrl |= TIOCM_OUT2;
-	serial_pxa_set_mctrl(&up->port, up->port.mctrl);
-	spin_unlock_irqrestore(&up->port.lock, flags);
-
-	/*
-	 * Finally, enable interrupts.  Note: Modem status interrupts
-	 * are set via set_termios(), which will be occurring imminently
-	 * anyway, so we don't enable them here.
-	 */
-	up->ier = UART_IER_RLSI | UART_IER_RDI | UART_IER_RTOIE | UART_IER_UUE;
-	serial_out(up, UART_IER, up->ier);
-
-	/*
-	 * And clear the interrupt registers again for luck.
-	 */
-	(void) serial_in(up, UART_LSR);
-	(void) serial_in(up, UART_RX);
-	(void) serial_in(up, UART_IIR);
-	(void) serial_in(up, UART_MSR);
-
-	return 0;
-}
-
-static void serial_pxa_shutdown(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned long flags;
-
-	free_irq(up->port.irq, up);
-
-	/*
-	 * Disable interrupts from this port
-	 */
-	up->ier = 0;
-	serial_out(up, UART_IER, 0);
-
-	spin_lock_irqsave(&up->port.lock, flags);
-	up->port.mctrl &= ~TIOCM_OUT2;
-	serial_pxa_set_mctrl(&up->port, up->port.mctrl);
-	spin_unlock_irqrestore(&up->port.lock, flags);
-
-	/*
-	 * Disable break condition and FIFOs
-	 */
-	serial_out(up, UART_LCR, serial_in(up, UART_LCR) & ~UART_LCR_SBC);
-	serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO |
-				  UART_FCR_CLEAR_RCVR |
-				  UART_FCR_CLEAR_XMIT);
-	serial_out(up, UART_FCR, 0);
-}
-
-static void
-serial_pxa_set_termios(struct uart_port *port, struct ktermios *termios,
-		       struct ktermios *old)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned char cval, fcr = 0;
-	unsigned long flags;
-	unsigned int baud, quot;
-	unsigned int dll;
-
-	switch (termios->c_cflag & CSIZE) {
-	case CS5:
-		cval = UART_LCR_WLEN5;
-		break;
-	case CS6:
-		cval = UART_LCR_WLEN6;
-		break;
-	case CS7:
-		cval = UART_LCR_WLEN7;
-		break;
-	default:
-	case CS8:
-		cval = UART_LCR_WLEN8;
-		break;
-	}
-
-	if (termios->c_cflag & CSTOPB)
-		cval |= UART_LCR_STOP;
-	if (termios->c_cflag & PARENB)
-		cval |= UART_LCR_PARITY;
-	if (!(termios->c_cflag & PARODD))
-		cval |= UART_LCR_EPAR;
-
-	/*
-	 * Ask the core to calculate the divisor for us.
-	 */
-	baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
-	quot = uart_get_divisor(port, baud);
-
-	if ((up->port.uartclk / quot) < (2400 * 16))
-		fcr = UART_FCR_ENABLE_FIFO | UART_FCR_PXAR1;
-	else if ((up->port.uartclk / quot) < (230400 * 16))
-		fcr = UART_FCR_ENABLE_FIFO | UART_FCR_PXAR8;
-	else
-		fcr = UART_FCR_ENABLE_FIFO | UART_FCR_PXAR32;
-
-	/*
-	 * Ok, we're now changing the port state.  Do it with
-	 * interrupts disabled.
-	 */
-	spin_lock_irqsave(&up->port.lock, flags);
-
-	/*
-	 * Ensure the port will be enabled.
-	 * This is required especially for serial console.
-	 */
-	up->ier |= UART_IER_UUE;
-
-	/*
-	 * Update the per-port timeout.
-	 */
-	uart_update_timeout(port, termios->c_cflag, baud);
-
-	up->port.read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;
-	if (termios->c_iflag & INPCK)
-		up->port.read_status_mask |= UART_LSR_FE | UART_LSR_PE;
-	if (termios->c_iflag & (BRKINT | PARMRK))
-		up->port.read_status_mask |= UART_LSR_BI;
-
-	/*
-	 * Characters to ignore
-	 */
-	up->port.ignore_status_mask = 0;
-	if (termios->c_iflag & IGNPAR)
-		up->port.ignore_status_mask |= UART_LSR_PE | UART_LSR_FE;
-	if (termios->c_iflag & IGNBRK) {
-		up->port.ignore_status_mask |= UART_LSR_BI;
-		/*
-		 * If we're ignoring parity and break indicators,
-		 * ignore overruns too (for real raw support).
-		 */
-		if (termios->c_iflag & IGNPAR)
-			up->port.ignore_status_mask |= UART_LSR_OE;
-	}
-
-	/*
-	 * ignore all characters if CREAD is not set
-	 */
-	if ((termios->c_cflag & CREAD) == 0)
-		up->port.ignore_status_mask |= UART_LSR_DR;
-
-	/*
-	 * CTS flow control flag and modem status interrupts
-	 */
-	up->ier &= ~UART_IER_MSI;
-	if (UART_ENABLE_MS(&up->port, termios->c_cflag))
-		up->ier |= UART_IER_MSI;
-
-	serial_out(up, UART_IER, up->ier);
-
-	if (termios->c_cflag & CRTSCTS)
-		up->mcr |= UART_MCR_AFE;
-	else
-		up->mcr &= ~UART_MCR_AFE;
-
-	serial_out(up, UART_LCR, cval | UART_LCR_DLAB);	/* set DLAB */
-	serial_out(up, UART_DLL, quot & 0xff);		/* LS of divisor */
-
-	/*
-	 * work around Errata #75 according to Intel(R) PXA27x Processor Family
-	 * Specification Update (Nov 2005)
-	 */
-	dll = serial_in(up, UART_DLL);
-	WARN_ON(dll != (quot & 0xff));
-
-	serial_out(up, UART_DLM, quot >> 8);		/* MS of divisor */
-	serial_out(up, UART_LCR, cval);			/* reset DLAB */
-	up->lcr = cval;					/* Save LCR */
-	serial_pxa_set_mctrl(&up->port, up->port.mctrl);
-	serial_out(up, UART_FCR, fcr);
-	spin_unlock_irqrestore(&up->port.lock, flags);
-}
-
-static void
-serial_pxa_pm(struct uart_port *port, unsigned int state,
-	      unsigned int oldstate)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	if (!state)
-		clk_prepare_enable(up->clk);
-	else
-		clk_disable_unprepare(up->clk);
-}
-
-static void serial_pxa_release_port(struct uart_port *port)
-{
-}
-
-static int serial_pxa_request_port(struct uart_port *port)
-{
-	return 0;
-}
-
-static void serial_pxa_config_port(struct uart_port *port, int flags)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	up->port.type = PORT_PXA;
-}
-
-static int
-serial_pxa_verify_port(struct uart_port *port, struct serial_struct *ser)
-{
-	/* we don't want the core code to modify any port params */
-	return -EINVAL;
-}
-
-static const char *
-serial_pxa_type(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	return up->name;
-}
-
-static struct uart_pxa_port *serial_pxa_ports[4];
-static struct uart_driver serial_pxa_reg;
-
-#ifdef CONFIG_SERIAL_PXA_CONSOLE
-
-#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
-
-/*
- *	Wait for transmitter & holding register to empty
- */
-static inline void wait_for_xmitr(struct uart_pxa_port *up)
-{
-	unsigned int status, tmout = 10000;
-
-	/* Wait up to 10ms for the character(s) to be sent. */
-	do {
-		status = serial_in(up, UART_LSR);
-
-		if (status & UART_LSR_BI)
-			up->lsr_break_flag = UART_LSR_BI;
-
-		if (--tmout == 0)
-			break;
-		udelay(1);
-	} while ((status & BOTH_EMPTY) != BOTH_EMPTY);
-
-	/* Wait up to 1s for flow control if necessary */
-	if (up->port.flags & UPF_CONS_FLOW) {
-		tmout = 1000000;
-		while (--tmout &&
-		       ((serial_in(up, UART_MSR) & UART_MSR_CTS) == 0))
-			udelay(1);
-	}
-}
-
-static void serial_pxa_console_putchar(struct uart_port *port, int ch)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	wait_for_xmitr(up);
-	serial_out(up, UART_TX, ch);
-}
-
-/*
- * Print a string to the serial port trying not to disturb
- * any possible real use of the port...
- *
- *	The console_lock must be held when we get here.
- */
-static void
-serial_pxa_console_write(struct console *co, const char *s, unsigned int count)
-{
-	struct uart_pxa_port *up = serial_pxa_ports[co->index];
-	unsigned int ier;
-	unsigned long flags;
-	int locked = 1;
-
-	clk_enable(up->clk);
-	local_irq_save(flags);
-	if (up->port.sysrq)
-		locked = 0;
-	else if (oops_in_progress)
-		locked = spin_trylock(&up->port.lock);
-	else
-		spin_lock(&up->port.lock);
-
-	/*
-	 *	First save the IER then disable the interrupts
-	 */
-	ier = serial_in(up, UART_IER);
-	serial_out(up, UART_IER, UART_IER_UUE);
-
-	uart_console_write(&up->port, s, count, serial_pxa_console_putchar);
-
-	/*
-	 *	Finally, wait for transmitter to become empty
-	 *	and restore the IER
-	 */
-	wait_for_xmitr(up);
-	serial_out(up, UART_IER, ier);
-
-	if (locked)
-		spin_unlock(&up->port.lock);
-	local_irq_restore(flags);
-	clk_disable(up->clk);
-
-}
-
-#ifdef CONFIG_CONSOLE_POLL
-/*
- * Console polling routines for writing and reading from the uart while
- * in an interrupt or debug context.
- */
-
-static int serial_pxa_get_poll_char(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned char lsr = serial_in(up, UART_LSR);
-
-	while (!(lsr & UART_LSR_DR))
-		lsr = serial_in(up, UART_LSR);
-
-	return serial_in(up, UART_RX);
-}
-
-
-static void serial_pxa_put_poll_char(struct uart_port *port,
-			 unsigned char c)
-{
-	unsigned int ier;
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	/*
-	 *	First save the IER then disable the interrupts
-	 */
-	ier = serial_in(up, UART_IER);
-	serial_out(up, UART_IER, UART_IER_UUE);
-
-	wait_for_xmitr(up);
-	/*
-	 *	Send the character out.
-	 *	If a LF, also do CR...
-	 */
-	serial_out(up, UART_TX, c);
-	if (c == 10) {
-		wait_for_xmitr(up);
-		serial_out(up, UART_TX, 13);
-	}
-
-	/*
-	 *	Finally, wait for transmitter to become empty
-	 *	and restore the IER
-	 */
-	wait_for_xmitr(up);
-	serial_out(up, UART_IER, ier);
-}
-
-#endif /* CONFIG_CONSOLE_POLL */
-
-static int __init
-serial_pxa_console_setup(struct console *co, char *options)
-{
-	struct uart_pxa_port *up;
-	int baud = 9600;
-	int bits = 8;
-	int parity = 'n';
-	int flow = 'n';
-
-	if (co->index == -1 || co->index >= serial_pxa_reg.nr)
-		co->index = 0;
-	up = serial_pxa_ports[co->index];
-	if (!up)
-		return -ENODEV;
-
-	if (options)
-		uart_parse_options(options, &baud, &parity, &bits, &flow);
-
-	return uart_set_options(&up->port, co, baud, parity, bits, flow);
-}
-
-static struct console serial_pxa_console = {
-	.name		= "ttyS",
-	.write		= serial_pxa_console_write,
-	.device		= uart_console_device,
-	.setup		= serial_pxa_console_setup,
-	.flags		= CON_PRINTBUFFER,
-	.index		= -1,
-	.data		= &serial_pxa_reg,
-};
-
-#define PXA_CONSOLE	&serial_pxa_console
-#else
-#define PXA_CONSOLE	NULL
-#endif
-
-static struct uart_ops serial_pxa_pops = {
-	.tx_empty	= serial_pxa_tx_empty,
-	.set_mctrl	= serial_pxa_set_mctrl,
-	.get_mctrl	= serial_pxa_get_mctrl,
-	.stop_tx	= serial_pxa_stop_tx,
-	.start_tx	= serial_pxa_start_tx,
-	.stop_rx	= serial_pxa_stop_rx,
-	.enable_ms	= serial_pxa_enable_ms,
-	.break_ctl	= serial_pxa_break_ctl,
-	.startup	= serial_pxa_startup,
-	.shutdown	= serial_pxa_shutdown,
-	.set_termios	= serial_pxa_set_termios,
-	.pm		= serial_pxa_pm,
-	.type		= serial_pxa_type,
-	.release_port	= serial_pxa_release_port,
-	.request_port	= serial_pxa_request_port,
-	.config_port	= serial_pxa_config_port,
-	.verify_port	= serial_pxa_verify_port,
-#ifdef CONFIG_CONSOLE_POLL
-	.poll_get_char = serial_pxa_get_poll_char,
-	.poll_put_char = serial_pxa_put_poll_char,
-#endif
-};
-
-static struct uart_driver serial_pxa_reg = {
-	.owner		= THIS_MODULE,
-	.driver_name	= "PXA serial",
-	.dev_name	= "ttyS",
-	.major		= TTY_MAJOR,
-	.minor		= 64,
-	.nr		= 4,
-	.cons		= PXA_CONSOLE,
-};
-
-#ifdef CONFIG_PM
-static int serial_pxa_suspend(struct device *dev)
-{
-        struct uart_pxa_port *sport = dev_get_drvdata(dev);
-
-        if (sport)
-                uart_suspend_port(&serial_pxa_reg, &sport->port);
-
-        return 0;
-}
-
-static int serial_pxa_resume(struct device *dev)
-{
-        struct uart_pxa_port *sport = dev_get_drvdata(dev);
-
-        if (sport)
-                uart_resume_port(&serial_pxa_reg, &sport->port);
-
-        return 0;
-}
-
-static const struct dev_pm_ops serial_pxa_pm_ops = {
-	.suspend	= serial_pxa_suspend,
-	.resume		= serial_pxa_resume,
-};
-#endif
-
-static struct of_device_id serial_pxa_dt_ids[] = {
-	{ .compatible = "mrvl,pxa-uart", },
-	{ .compatible = "mrvl,mmp-uart", },
-	{}
-};
-MODULE_DEVICE_TABLE(of, serial_pxa_dt_ids);
-
-static int serial_pxa_probe_dt(struct platform_device *pdev,
-			       struct uart_pxa_port *sport)
-{
-	struct device_node *np = pdev->dev.of_node;
-	int ret;
-
-	if (!np)
-		return 1;
-
-	ret = of_alias_get_id(np, "serial");
-	if (ret < 0) {
-		dev_err(&pdev->dev, "failed to get alias id, errno %d\n", ret);
-		return ret;
-	}
-	sport->port.line = ret;
-	return 0;
-}
-
-static int serial_pxa_probe(struct platform_device *dev)
-{
-	struct uart_pxa_port *sport;
-	struct resource *mmres, *irqres;
-	int ret;
-
-	mmres = platform_get_resource(dev, IORESOURCE_MEM, 0);
-	irqres = platform_get_resource(dev, IORESOURCE_IRQ, 0);
-	if (!mmres || !irqres)
-		return -ENODEV;
-
-	sport = kzalloc(sizeof(struct uart_pxa_port), GFP_KERNEL);
-	if (!sport)
-		return -ENOMEM;
-
-	sport->clk = clk_get(&dev->dev, NULL);
-	if (IS_ERR(sport->clk)) {
-		ret = PTR_ERR(sport->clk);
-		goto err_free;
-	}
-
-	ret = clk_prepare(sport->clk);
-	if (ret) {
-		clk_put(sport->clk);
-		goto err_free;
-	}
-
-	sport->port.type = PORT_PXA;
-	sport->port.iotype = UPIO_MEM;
-	sport->port.mapbase = mmres->start;
-	sport->port.irq = irqres->start;
-	sport->port.fifosize = 64;
-	sport->port.ops = &serial_pxa_pops;
-	sport->port.dev = &dev->dev;
-	sport->port.flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF;
-	sport->port.uartclk = clk_get_rate(sport->clk);
-
-	ret = serial_pxa_probe_dt(dev, sport);
-	if (ret > 0)
-		sport->port.line = dev->id;
-	else if (ret < 0)
-		goto err_clk;
-	snprintf(sport->name, PXA_NAME_LEN - 1, "UART%d", sport->port.line + 1);
-
-	sport->port.membase = ioremap(mmres->start, resource_size(mmres));
-	if (!sport->port.membase) {
-		ret = -ENOMEM;
-		goto err_clk;
-	}
-
-	serial_pxa_ports[sport->port.line] = sport;
-
-	uart_add_one_port(&serial_pxa_reg, &sport->port);
-	platform_set_drvdata(dev, sport);
-
-	return 0;
-
- err_clk:
-	clk_unprepare(sport->clk);
-	clk_put(sport->clk);
- err_free:
-	kfree(sport);
-	return ret;
-}
-
-static int serial_pxa_remove(struct platform_device *dev)
-{
-	struct uart_pxa_port *sport = platform_get_drvdata(dev);
-
-	uart_remove_one_port(&serial_pxa_reg, &sport->port);
-
-	clk_unprepare(sport->clk);
-	clk_put(sport->clk);
-	kfree(sport);
-
-	return 0;
-}
-
-static struct platform_driver serial_pxa_driver = {
-        .probe          = serial_pxa_probe,
-        .remove         = serial_pxa_remove,
-
-	.driver		= {
-	        .name	= "pxa2xx-uart",
-		.owner	= THIS_MODULE,
-#ifdef CONFIG_PM
-		.pm	= &serial_pxa_pm_ops,
-#endif
-		.of_match_table = serial_pxa_dt_ids,
-	},
-};
-
-static int __init serial_pxa_init(void)
-{
-	int ret;
-
-	ret = uart_register_driver(&serial_pxa_reg);
-	if (ret != 0)
-		return ret;
-
-	ret = platform_driver_register(&serial_pxa_driver);
-	if (ret != 0)
-		uart_unregister_driver(&serial_pxa_reg);
-
-	return ret;
-}
-
-static void __exit serial_pxa_exit(void)
-{
-	platform_driver_unregister(&serial_pxa_driver);
-	uart_unregister_driver(&serial_pxa_reg);
-}
-
-module_init(serial_pxa_init);
-module_exit(serial_pxa_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:pxa2xx-uart");
-- 
1.8.4.3


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

* [PATCH] serial: rewrite pxa2xx-uart to use 8250_core
@ 2013-12-05 23:28                     ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-05 23:28 UTC (permalink / raw)
  To: linux-kernel-u79uwXL29TY76Z2rM5mHXA
  Cc: Sergei Ianovich, Heikki Krogerus, Greg Kroah-Hartman,
	Russell King, Jiri Slaby, Grant Likely, Rob Herring, Zhou Zhu,
	Andrew Morton, Haojian Zhuang, Ralf Baechle, John Crispin,
	moderated list:ARM PORT, open list:SERIAL DRIVERS,
	open list:OPEN FIRMWARE AND...

pxa2xx-uart was a separate uart platform driver. It was declaring
the same device names and numbers as 8250 driver. As a result,
it was impossible to use 8250 driver on PXA SoCs.

Upon closer examination pxa2xx-uart turned out to be a clone of
8250_core driver.

Signed-off-by: Sergei Ianovich <ynvich-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
CC: Heikki Krogerus <heikki.krogerus-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
CC: Greg Kroah-Hartman <gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r@public.gmane.org>
---
 arch/arm/configs/am200epdkit_defconfig    |   3 +-
 arch/arm/configs/cm_x2xx_defconfig        |   3 +-
 arch/arm/configs/cm_x300_defconfig        |   3 +-
 arch/arm/configs/colibri_pxa270_defconfig |   3 +-
 arch/arm/configs/colibri_pxa300_defconfig |   3 +-
 arch/arm/configs/corgi_defconfig          |   4 +-
 arch/arm/configs/em_x270_defconfig        |   3 +-
 arch/arm/configs/ezx_defconfig            |   3 +-
 arch/arm/configs/h5000_defconfig          |   3 +-
 arch/arm/configs/imote2_defconfig         |   3 +-
 arch/arm/configs/lpd270_defconfig         |   3 +-
 arch/arm/configs/lubbock_defconfig        |   3 +-
 arch/arm/configs/mainstone_defconfig      |   3 +-
 arch/arm/configs/mmp2_defconfig           |   3 +-
 arch/arm/configs/pcm027_defconfig         |   3 +-
 arch/arm/configs/pxa168_defconfig         |   3 +-
 arch/arm/configs/pxa255-idp_defconfig     |   3 +-
 arch/arm/configs/pxa3xx_defconfig         |   3 +-
 arch/arm/configs/pxa910_defconfig         |   3 +-
 arch/arm/configs/raumfeld_defconfig       |   3 +-
 arch/arm/configs/spitz_defconfig          |   4 +-
 arch/arm/configs/trizeps4_defconfig       |   3 +-
 arch/arm/configs/viper_defconfig          |   4 +-
 arch/arm/configs/xcep_defconfig           |   3 +-
 drivers/tty/serial/8250/8250_pxa.c        | 180 ++++++
 drivers/tty/serial/8250/Kconfig           |   9 +
 drivers/tty/serial/8250/Makefile          |   1 +
 drivers/tty/serial/Kconfig                |  23 -
 drivers/tty/serial/Makefile               |   1 -
 drivers/tty/serial/pxa.c                  | 971 ------------------------------
 30 files changed, 238 insertions(+), 1022 deletions(-)
 create mode 100644 drivers/tty/serial/8250/8250_pxa.c
 delete mode 100644 drivers/tty/serial/pxa.c

diff --git a/arch/arm/configs/am200epdkit_defconfig b/arch/arm/configs/am200epdkit_defconfig
index f0dea52..0cde234 100644
--- a/arch/arm/configs/am200epdkit_defconfig
+++ b/arch/arm/configs/am200epdkit_defconfig
@@ -60,8 +60,9 @@ CONFIG_BLK_DEV_IDECS=m
 CONFIG_NETDEVICES=y
 CONFIG_NET_ETHERNET=y
 CONFIG_SMC91X=m
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 # CONFIG_HWMON is not set
diff --git a/arch/arm/configs/cm_x2xx_defconfig b/arch/arm/configs/cm_x2xx_defconfig
index a93ff8d..b9fbe65 100644
--- a/arch/arm/configs/cm_x2xx_defconfig
+++ b/arch/arm/configs/cm_x2xx_defconfig
@@ -96,8 +96,9 @@ CONFIG_KEYBOARD_PXA27x=m
 CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_TOUCHSCREEN_UCB1400=m
 # CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_LEGACY_PTY_COUNT=16
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/cm_x300_defconfig b/arch/arm/configs/cm_x300_defconfig
index f4b7672..53a82ae 100644
--- a/arch/arm/configs/cm_x300_defconfig
+++ b/arch/arm/configs/cm_x300_defconfig
@@ -80,8 +80,9 @@ CONFIG_TOUCHSCREEN_WM97XX=m
 # CONFIG_TOUCHSCREEN_WM9713 is not set
 # CONFIG_SERIO is not set
 # CONFIG_LEGACY_PTYS is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
 CONFIG_I2C_PXA=y
diff --git a/arch/arm/configs/colibri_pxa270_defconfig b/arch/arm/configs/colibri_pxa270_defconfig
index 2ef2c5e..1ce0409 100644
--- a/arch/arm/configs/colibri_pxa270_defconfig
+++ b/arch/arm/configs/colibri_pxa270_defconfig
@@ -103,8 +103,9 @@ CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=m
 CONFIG_SERIO_LIBPS2=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_HW_RANDOM=y
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
diff --git a/arch/arm/configs/colibri_pxa300_defconfig b/arch/arm/configs/colibri_pxa300_defconfig
index b985334..f96bda0 100644
--- a/arch/arm/configs/colibri_pxa300_defconfig
+++ b/arch/arm/configs/colibri_pxa300_defconfig
@@ -31,8 +31,9 @@ CONFIG_INPUT_EVDEV=y
 # CONFIG_INPUT_MOUSE is not set
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_GPIO_ROTARY_ENCODER=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_HW_RANDOM=y
 CONFIG_DEBUG_GPIO=y
 # CONFIG_HWMON is not set
diff --git a/arch/arm/configs/corgi_defconfig b/arch/arm/configs/corgi_defconfig
index 1fd1d1d..bb4842d 100644
--- a/arch/arm/configs/corgi_defconfig
+++ b/arch/arm/configs/corgi_defconfig
@@ -131,10 +131,10 @@ CONFIG_TOUCHSCREEN_ADS7846=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=m
 # CONFIG_SERIO is not set
-CONFIG_SERIAL_8250=m
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_CS=m
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 CONFIG_I2C=y
 CONFIG_I2C_PXA=y
diff --git a/arch/arm/configs/em_x270_defconfig b/arch/arm/configs/em_x270_defconfig
index 60a21e0..ec0ec54 100644
--- a/arch/arm/configs/em_x270_defconfig
+++ b/arch/arm/configs/em_x270_defconfig
@@ -90,8 +90,9 @@ CONFIG_TOUCHSCREEN_WM97XX=m
 # CONFIG_TOUCHSCREEN_WM9705 is not set
 # CONFIG_TOUCHSCREEN_WM9713 is not set
 # CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_LEGACY_PTY_COUNT=16
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/ezx_defconfig b/arch/arm/configs/ezx_defconfig
index d95763d..631e2ec 100644
--- a/arch/arm/configs/ezx_defconfig
+++ b/arch/arm/configs/ezx_defconfig
@@ -215,8 +215,9 @@ CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=y
 CONFIG_INPUT_PCAP=y
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_LEGACY_PTY_COUNT=8
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/h5000_defconfig b/arch/arm/configs/h5000_defconfig
index 37903e3..655b735 100644
--- a/arch/arm/configs/h5000_defconfig
+++ b/arch/arm/configs/h5000_defconfig
@@ -47,8 +47,9 @@ CONFIG_MTD_PHYSMAP=y
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_LEGACY_PTY_COUNT=32
 # CONFIG_HW_RANDOM is not set
 # CONFIG_HWMON is not set
diff --git a/arch/arm/configs/imote2_defconfig b/arch/arm/configs/imote2_defconfig
index fd996bb..49d45e9 100644
--- a/arch/arm/configs/imote2_defconfig
+++ b/arch/arm/configs/imote2_defconfig
@@ -193,8 +193,9 @@ CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=y
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_LEGACY_PTY_COUNT=8
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/lpd270_defconfig b/arch/arm/configs/lpd270_defconfig
index 1c8c9ee..c3927b6 100644
--- a/arch/arm/configs/lpd270_defconfig
+++ b/arch/arm/configs/lpd270_defconfig
@@ -38,8 +38,9 @@ CONFIG_SMC91X=y
 CONFIG_INPUT_EVDEV=y
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_HW_RANDOM is not set
 CONFIG_FB=y
 CONFIG_FB_PXA=y
diff --git a/arch/arm/configs/lubbock_defconfig b/arch/arm/configs/lubbock_defconfig
index c4ba274..c8b0436 100644
--- a/arch/arm/configs/lubbock_defconfig
+++ b/arch/arm/configs/lubbock_defconfig
@@ -37,8 +37,9 @@ CONFIG_PCMCIA_PCNET=y
 CONFIG_INPUT_EVDEV=y
 # CONFIG_SERIO_SERPORT is not set
 CONFIG_SERIO_SA1111=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_USB_GADGET=y
 CONFIG_USB_G_SERIAL=m
diff --git a/arch/arm/configs/mainstone_defconfig b/arch/arm/configs/mainstone_defconfig
index 04efa1b..768892c 100644
--- a/arch/arm/configs/mainstone_defconfig
+++ b/arch/arm/configs/mainstone_defconfig
@@ -34,8 +34,9 @@ CONFIG_SMC91X=y
 CONFIG_INPUT_EVDEV=y
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_FB=y
 CONFIG_FB_PXA=y
 # CONFIG_VGA_CONSOLE is not set
diff --git a/arch/arm/configs/mmp2_defconfig b/arch/arm/configs/mmp2_defconfig
index f1cb95e..1ced9df 100644
--- a/arch/arm/configs/mmp2_defconfig
+++ b/arch/arm/configs/mmp2_defconfig
@@ -44,8 +44,9 @@ CONFIG_SMC91X=y
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/pcm027_defconfig b/arch/arm/configs/pcm027_defconfig
index 2f136c3..1280128 100644
--- a/arch/arm/configs/pcm027_defconfig
+++ b/arch/arm/configs/pcm027_defconfig
@@ -60,8 +60,9 @@ CONFIG_SMC91X=y
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/pxa168_defconfig b/arch/arm/configs/pxa168_defconfig
index 74d7e01..1668dac 100644
--- a/arch/arm/configs/pxa168_defconfig
+++ b/arch/arm/configs/pxa168_defconfig
@@ -40,8 +40,9 @@ CONFIG_SMC91X=y
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 # CONFIG_HWMON is not set
diff --git a/arch/arm/configs/pxa255-idp_defconfig b/arch/arm/configs/pxa255-idp_defconfig
index 917a070..399a706 100644
--- a/arch/arm/configs/pxa255-idp_defconfig
+++ b/arch/arm/configs/pxa255-idp_defconfig
@@ -35,8 +35,9 @@ CONFIG_SMC91X=y
 CONFIG_INPUT_EVDEV=y
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_FB=y
 CONFIG_FB_PXA=y
 # CONFIG_VGA_CONSOLE is not set
diff --git a/arch/arm/configs/pxa3xx_defconfig b/arch/arm/configs/pxa3xx_defconfig
index 60e3138..7c3e052 100644
--- a/arch/arm/configs/pxa3xx_defconfig
+++ b/arch/arm/configs/pxa3xx_defconfig
@@ -56,8 +56,9 @@ CONFIG_KEYBOARD_PXA27x=y
 CONFIG_KEYBOARD_PXA930_ROTARY=y
 CONFIG_MOUSE_PXA930_TRKBALL=y
 CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/pxa910_defconfig b/arch/arm/configs/pxa910_defconfig
index 3bb7771..cdacfcb 100644
--- a/arch/arm/configs/pxa910_defconfig
+++ b/arch/arm/configs/pxa910_defconfig
@@ -40,8 +40,9 @@ CONFIG_SMC91X=y
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_SPI=y
 CONFIG_FB=y
 CONFIG_MMP_DISP=y
diff --git a/arch/arm/configs/raumfeld_defconfig b/arch/arm/configs/raumfeld_defconfig
index f7caa90..f1e16f2 100644
--- a/arch/arm/configs/raumfeld_defconfig
+++ b/arch/arm/configs/raumfeld_defconfig
@@ -67,8 +67,9 @@ CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_TOUCHSCREEN_EETI=m
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_GPIO_ROTARY_ENCODER=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_HW_RANDOM=y
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
diff --git a/arch/arm/configs/spitz_defconfig b/arch/arm/configs/spitz_defconfig
index 2e0419d..b6efcf5 100644
--- a/arch/arm/configs/spitz_defconfig
+++ b/arch/arm/configs/spitz_defconfig
@@ -128,10 +128,10 @@ CONFIG_TOUCHSCREEN_ADS7846=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=m
 # CONFIG_SERIO is not set
-CONFIG_SERIAL_8250=m
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_CS=m
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 CONFIG_SPI=y
 CONFIG_SPI_PXA2XX=y
diff --git a/arch/arm/configs/trizeps4_defconfig b/arch/arm/configs/trizeps4_defconfig
index 3162173..453c79c 100644
--- a/arch/arm/configs/trizeps4_defconfig
+++ b/arch/arm/configs/trizeps4_defconfig
@@ -132,8 +132,9 @@ CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=m
 CONFIG_SERIO_LIBPS2=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_HW_RANDOM=y
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
diff --git a/arch/arm/configs/viper_defconfig b/arch/arm/configs/viper_defconfig
index d36e0d3..4efac06 100644
--- a/arch/arm/configs/viper_defconfig
+++ b/arch/arm/configs/viper_defconfig
@@ -101,11 +101,11 @@ CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=m
 # CONFIG_CONSOLE_TRANSLATIONS is not set
 # CONFIG_VT_CONSOLE is not set
-CONFIG_SERIAL_8250=m
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_NR_UARTS=5
 CONFIG_SERIAL_8250_RUNTIME_UARTS=5
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
diff --git a/arch/arm/configs/xcep_defconfig b/arch/arm/configs/xcep_defconfig
index 721832f..b67aeaf 100644
--- a/arch/arm/configs/xcep_defconfig
+++ b/arch/arm/configs/xcep_defconfig
@@ -60,8 +60,9 @@ CONFIG_NET_ETHERNET=y
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
 # CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=m
diff --git a/drivers/tty/serial/8250/8250_pxa.c b/drivers/tty/serial/8250/8250_pxa.c
new file mode 100644
index 0000000..5658fc9
--- /dev/null
+++ b/drivers/tty/serial/8250/8250_pxa.c
@@ -0,0 +1,180 @@
+/*
+ *  drivers/tty/serial/8250/8250_pxa.c -- driver for PXA on-board UARTS
+ *  Copyright:	(C) 2013 Sergei Ianovich <ynvich-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
+ *
+ *  replaces drivers/serial/pxa.c by Nicolas Pitre
+ *  Created:	Feb 20, 2003
+ *  Copyright:	(C) 2003 Monta Vista Software, Inc.
+ *
+ *  Based on drivers/serial/8250.c by Russell King.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/serial_8250.h>
+#include <linux/serial_core.h>
+#include <linux/serial_reg.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
+#include <linux/pm_runtime.h>
+
+#include "8250.h"
+
+struct pxa8250_data {
+	int			line;
+	struct clk		*clk;
+};
+
+#ifdef CONFIG_PM
+static int serial_pxa_suspend(struct device *dev)
+{
+	struct pxa8250_data *data = dev_get_drvdata(dev);
+
+	serial8250_suspend_port(data->line);
+
+	return 0;
+}
+
+static int serial_pxa_resume(struct device *dev)
+{
+	struct pxa8250_data *data = dev_get_drvdata(dev);
+
+	serial8250_resume_port(data->line);
+
+	return 0;
+}
+
+static const struct dev_pm_ops serial_pxa_pm_ops = {
+	.suspend	= serial_pxa_suspend,
+	.resume		= serial_pxa_resume,
+};
+#endif
+
+static struct of_device_id serial_pxa_dt_ids[] = {
+	{ .compatible = "mrvl,pxa-uart", },
+	{ .compatible = "mrvl,mmp-uart", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, serial_pxa_dt_ids);
+
+/* Uart divisor latch write */
+static void serial_pxa_dl_write(struct uart_8250_port *up, int value)
+{
+	serial_out(up, UART_DLL, value & 0xff);
+	serial_out(up, UART_DLM, value >> 8 & 0xff);
+}
+
+
+static void serial_pxa_pm(struct uart_port *port, unsigned int state,
+	      unsigned int oldstate)
+{
+	struct pxa8250_data *data = port->private_data;
+
+	if (!state)
+		clk_prepare_enable(data->clk);
+	else
+		clk_disable_unprepare(data->clk);
+}
+
+static int serial_pxa_probe(struct platform_device *pdev)
+{
+	struct uart_8250_port uart = {};
+	struct pxa8250_data *data;
+	struct resource *mmres, *irqres;
+	int ret;
+
+	mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	irqres = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!mmres || !irqres)
+		return -ENODEV;
+
+	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(data->clk)) {
+		ret = PTR_ERR(data->clk);
+		goto err_free;
+	}
+
+	ret = clk_prepare(data->clk);
+	if (ret)
+		goto err_free_clk;
+
+	uart.port.type = PORT_XSCALE;
+	uart.port.iotype = UPIO_MEM32;
+	uart.port.mapbase = mmres->start;
+	uart.port.regshift = 2;
+	uart.port.irq = irqres->start;
+	uart.port.fifosize = 64;
+	uart.port.flags = UPF_IOREMAP | UPF_SKIP_TEST;
+	uart.port.dev = &pdev->dev;
+	uart.port.uartclk = clk_get_rate(data->clk);
+	uart.port.pm = serial_pxa_pm;
+	uart.port.private_data = data;
+	uart.dl_write = serial_pxa_dl_write;
+
+	ret = serial8250_register_8250_port(&uart);
+	if (ret < 0)
+		goto err_clk;
+
+	data->line = ret;
+
+	platform_set_drvdata(pdev, data);
+
+	return 0;
+
+ err_clk:
+	clk_unprepare(data->clk);
+ err_free_clk:
+	devm_clk_put(&pdev->dev, data->clk);
+ err_free:
+	devm_kfree(&pdev->dev, data);
+	return ret;
+}
+
+static int serial_pxa_remove(struct platform_device *pdev)
+{
+	struct pxa8250_data *data = platform_get_drvdata(pdev);
+
+	serial8250_unregister_port(data->line);
+
+	clk_unprepare(data->clk);
+	devm_clk_put(&pdev->dev, data->clk);
+	devm_kfree(&pdev->dev, data);
+
+	return 0;
+}
+
+static struct platform_driver serial_pxa_driver = {
+	.probe          = serial_pxa_probe,
+	.remove         = serial_pxa_remove,
+
+	.driver		= {
+		.name	= "pxa2xx-uart",
+		.owner	= THIS_MODULE,
+#ifdef CONFIG_PM
+		.pm	= &serial_pxa_pm_ops,
+#endif
+		.of_match_table = serial_pxa_dt_ids,
+	},
+};
+
+module_platform_driver(serial_pxa_driver);
+
+MODULE_AUTHOR("Sergei Ianovich");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:pxa2xx-uart");
diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
index 2332991..81bd7c9 100644
--- a/drivers/tty/serial/8250/Kconfig
+++ b/drivers/tty/serial/8250/Kconfig
@@ -302,3 +302,12 @@ config SERIAL_8250_RT288X
 	  If you have a Ralink RT288x/RT305x SoC based board and want to use the
 	  serial port, say Y to this option. The driver can handle up to 2 serial
 	  ports. If unsure, say N.
+
+config SERIAL_PXA
+	tristate "PXA serial port support"
+	depends on SERIAL_8250 && (ARCH_PXA || ARCH_MMP)
+	help
+	  If you have a machine based on an Intel XScale PXA2xx CPU you
+	  can enable its onboard serial ports by enabling this option.
+
+	  If you choose M here, the module name will be 8250_pxa.
diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile
index 36d68d0..b7d1b61 100644
--- a/drivers/tty/serial/8250/Makefile
+++ b/drivers/tty/serial/8250/Makefile
@@ -20,3 +20,4 @@ obj-$(CONFIG_SERIAL_8250_HUB6)		+= 8250_hub6.o
 obj-$(CONFIG_SERIAL_8250_FSL)		+= 8250_fsl.o
 obj-$(CONFIG_SERIAL_8250_DW)		+= 8250_dw.o
 obj-$(CONFIG_SERIAL_8250_EM)		+= 8250_em.o
+obj-$(CONFIG_SERIAL_PXA)		+= 8250_pxa.o
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index a3817ab..2ad7184b 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -396,29 +396,6 @@ config SERIAL_MPSC_CONSOLE
 	help
 	  Say Y here if you want to support a serial console on a Marvell MPSC.
 
-config SERIAL_PXA
-	bool "PXA serial port support"
-	depends on ARCH_PXA || ARCH_MMP
-	select SERIAL_CORE
-	help
-	  If you have a machine based on an Intel XScale PXA2xx CPU you
-	  can enable its onboard serial ports by enabling this option.
-
-config SERIAL_PXA_CONSOLE
-	bool "Console on PXA serial port"
-	depends on SERIAL_PXA
-	select SERIAL_CORE_CONSOLE
-	help
-	  If you have enabled the serial port on the Intel XScale PXA
-	  CPU you can make it the console by answering Y to this option.
-
-	  Even if you say Y here, the currently visible virtual console
-	  (/dev/tty0) will still be used as the system console by default, but
-	  you can alter that using a kernel command line option such as
-	  "console=ttySA0". (Try "man bootparam" or see the documentation of
-	  your boot loader (lilo or loadlin) about how to pass options to the
-	  kernel at boot time.)
-
 config SERIAL_SA1100
 	bool "SA1100 serial port support"
 	depends on ARCH_SA1100
diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile
index 3068c77..4ac337b 100644
--- a/drivers/tty/serial/Makefile
+++ b/drivers/tty/serial/Makefile
@@ -20,7 +20,6 @@ obj-$(CONFIG_SERIAL_8250) += 8250/
 obj-$(CONFIG_SERIAL_AMBA_PL010) += amba-pl010.o
 obj-$(CONFIG_SERIAL_AMBA_PL011) += amba-pl011.o
 obj-$(CONFIG_SERIAL_CLPS711X) += clps711x.o
-obj-$(CONFIG_SERIAL_PXA) += pxa.o
 obj-$(CONFIG_SERIAL_PNX8XXX) += pnx8xxx_uart.o
 obj-$(CONFIG_SERIAL_SA1100) += sa1100.o
 obj-$(CONFIG_SERIAL_BCM63XX) += bcm63xx_uart.o
diff --git a/drivers/tty/serial/pxa.c b/drivers/tty/serial/pxa.c
deleted file mode 100644
index f9f20f3..0000000
--- a/drivers/tty/serial/pxa.c
+++ /dev/null
@@ -1,971 +0,0 @@
-/*
- *  Based on drivers/serial/8250.c by Russell King.
- *
- *  Author:	Nicolas Pitre
- *  Created:	Feb 20, 2003
- *  Copyright:	(C) 2003 Monta Vista Software, Inc.
- *
- * 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.
- *
- * Note 1: This driver is made separate from the already too overloaded
- * 8250.c because it needs some kirks of its own and that'll make it
- * easier to add DMA support.
- *
- * Note 2: I'm too sick of device allocation policies for serial ports.
- * If someone else wants to request an "official" allocation of major/minor
- * for this driver please be my guest.  And don't forget that new hardware
- * to come from Intel might have more than 3 or 4 of those UARTs.  Let's
- * hope for a better port registration and dynamic device allocation scheme
- * with the serial core maintainer satisfaction to appear soon.
- */
-
-
-#if defined(CONFIG_SERIAL_PXA_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-#define SUPPORT_SYSRQ
-#endif
-
-#include <linux/module.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-#include <linux/console.h>
-#include <linux/sysrq.h>
-#include <linux/serial_reg.h>
-#include <linux/circ_buf.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/of.h>
-#include <linux/platform_device.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/serial_core.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-
-#define PXA_NAME_LEN		8
-
-struct uart_pxa_port {
-	struct uart_port        port;
-	unsigned char           ier;
-	unsigned char           lcr;
-	unsigned char           mcr;
-	unsigned int            lsr_break_flag;
-	struct clk		*clk;
-	char			name[PXA_NAME_LEN];
-};
-
-static inline unsigned int serial_in(struct uart_pxa_port *up, int offset)
-{
-	offset <<= 2;
-	return readl(up->port.membase + offset);
-}
-
-static inline void serial_out(struct uart_pxa_port *up, int offset, int value)
-{
-	offset <<= 2;
-	writel(value, up->port.membase + offset);
-}
-
-static void serial_pxa_enable_ms(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	up->ier |= UART_IER_MSI;
-	serial_out(up, UART_IER, up->ier);
-}
-
-static void serial_pxa_stop_tx(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	if (up->ier & UART_IER_THRI) {
-		up->ier &= ~UART_IER_THRI;
-		serial_out(up, UART_IER, up->ier);
-	}
-}
-
-static void serial_pxa_stop_rx(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	up->ier &= ~UART_IER_RLSI;
-	up->port.read_status_mask &= ~UART_LSR_DR;
-	serial_out(up, UART_IER, up->ier);
-}
-
-static inline void receive_chars(struct uart_pxa_port *up, int *status)
-{
-	unsigned int ch, flag;
-	int max_count = 256;
-
-	do {
-		/* work around Errata #20 according to
-		 * Intel(R) PXA27x Processor Family
-		 * Specification Update (May 2005)
-		 *
-		 * Step 2
-		 * Disable the Reciever Time Out Interrupt via IER[RTOEI]
-		 */
-		up->ier &= ~UART_IER_RTOIE;
-		serial_out(up, UART_IER, up->ier);
-
-		ch = serial_in(up, UART_RX);
-		flag = TTY_NORMAL;
-		up->port.icount.rx++;
-
-		if (unlikely(*status & (UART_LSR_BI | UART_LSR_PE |
-				       UART_LSR_FE | UART_LSR_OE))) {
-			/*
-			 * For statistics only
-			 */
-			if (*status & UART_LSR_BI) {
-				*status &= ~(UART_LSR_FE | UART_LSR_PE);
-				up->port.icount.brk++;
-				/*
-				 * We do the SysRQ and SAK checking
-				 * here because otherwise the break
-				 * may get masked by ignore_status_mask
-				 * or read_status_mask.
-				 */
-				if (uart_handle_break(&up->port))
-					goto ignore_char;
-			} else if (*status & UART_LSR_PE)
-				up->port.icount.parity++;
-			else if (*status & UART_LSR_FE)
-				up->port.icount.frame++;
-			if (*status & UART_LSR_OE)
-				up->port.icount.overrun++;
-
-			/*
-			 * Mask off conditions which should be ignored.
-			 */
-			*status &= up->port.read_status_mask;
-
-#ifdef CONFIG_SERIAL_PXA_CONSOLE
-			if (up->port.line == up->port.cons->index) {
-				/* Recover the break flag from console xmit */
-				*status |= up->lsr_break_flag;
-				up->lsr_break_flag = 0;
-			}
-#endif
-			if (*status & UART_LSR_BI) {
-				flag = TTY_BREAK;
-			} else if (*status & UART_LSR_PE)
-				flag = TTY_PARITY;
-			else if (*status & UART_LSR_FE)
-				flag = TTY_FRAME;
-		}
-
-		if (uart_handle_sysrq_char(&up->port, ch))
-			goto ignore_char;
-
-		uart_insert_char(&up->port, *status, UART_LSR_OE, ch, flag);
-
-	ignore_char:
-		*status = serial_in(up, UART_LSR);
-	} while ((*status & UART_LSR_DR) && (max_count-- > 0));
-	tty_flip_buffer_push(&up->port.state->port);
-
-	/* work around Errata #20 according to
-	 * Intel(R) PXA27x Processor Family
-	 * Specification Update (May 2005)
-	 *
-	 * Step 6:
-	 * No more data in FIFO: Re-enable RTO interrupt via IER[RTOIE]
-	 */
-	up->ier |= UART_IER_RTOIE;
-	serial_out(up, UART_IER, up->ier);
-}
-
-static void transmit_chars(struct uart_pxa_port *up)
-{
-	struct circ_buf *xmit = &up->port.state->xmit;
-	int count;
-
-	if (up->port.x_char) {
-		serial_out(up, UART_TX, up->port.x_char);
-		up->port.icount.tx++;
-		up->port.x_char = 0;
-		return;
-	}
-	if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) {
-		serial_pxa_stop_tx(&up->port);
-		return;
-	}
-
-	count = up->port.fifosize / 2;
-	do {
-		serial_out(up, UART_TX, xmit->buf[xmit->tail]);
-		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
-		up->port.icount.tx++;
-		if (uart_circ_empty(xmit))
-			break;
-	} while (--count > 0);
-
-	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
-		uart_write_wakeup(&up->port);
-
-
-	if (uart_circ_empty(xmit))
-		serial_pxa_stop_tx(&up->port);
-}
-
-static void serial_pxa_start_tx(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	if (!(up->ier & UART_IER_THRI)) {
-		up->ier |= UART_IER_THRI;
-		serial_out(up, UART_IER, up->ier);
-	}
-}
-
-static inline void check_modem_status(struct uart_pxa_port *up)
-{
-	int status;
-
-	status = serial_in(up, UART_MSR);
-
-	if ((status & UART_MSR_ANY_DELTA) == 0)
-		return;
-
-	if (status & UART_MSR_TERI)
-		up->port.icount.rng++;
-	if (status & UART_MSR_DDSR)
-		up->port.icount.dsr++;
-	if (status & UART_MSR_DDCD)
-		uart_handle_dcd_change(&up->port, status & UART_MSR_DCD);
-	if (status & UART_MSR_DCTS)
-		uart_handle_cts_change(&up->port, status & UART_MSR_CTS);
-
-	wake_up_interruptible(&up->port.state->port.delta_msr_wait);
-}
-
-/*
- * This handles the interrupt from one port.
- */
-static inline irqreturn_t serial_pxa_irq(int irq, void *dev_id)
-{
-	struct uart_pxa_port *up = dev_id;
-	unsigned int iir, lsr;
-
-	iir = serial_in(up, UART_IIR);
-	if (iir & UART_IIR_NO_INT)
-		return IRQ_NONE;
-	lsr = serial_in(up, UART_LSR);
-	if (lsr & UART_LSR_DR)
-		receive_chars(up, &lsr);
-	check_modem_status(up);
-	if (lsr & UART_LSR_THRE)
-		transmit_chars(up);
-	return IRQ_HANDLED;
-}
-
-static unsigned int serial_pxa_tx_empty(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned long flags;
-	unsigned int ret;
-
-	spin_lock_irqsave(&up->port.lock, flags);
-	ret = serial_in(up, UART_LSR) & UART_LSR_TEMT ? TIOCSER_TEMT : 0;
-	spin_unlock_irqrestore(&up->port.lock, flags);
-
-	return ret;
-}
-
-static unsigned int serial_pxa_get_mctrl(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned char status;
-	unsigned int ret;
-
-	status = serial_in(up, UART_MSR);
-
-	ret = 0;
-	if (status & UART_MSR_DCD)
-		ret |= TIOCM_CAR;
-	if (status & UART_MSR_RI)
-		ret |= TIOCM_RNG;
-	if (status & UART_MSR_DSR)
-		ret |= TIOCM_DSR;
-	if (status & UART_MSR_CTS)
-		ret |= TIOCM_CTS;
-	return ret;
-}
-
-static void serial_pxa_set_mctrl(struct uart_port *port, unsigned int mctrl)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned char mcr = 0;
-
-	if (mctrl & TIOCM_RTS)
-		mcr |= UART_MCR_RTS;
-	if (mctrl & TIOCM_DTR)
-		mcr |= UART_MCR_DTR;
-	if (mctrl & TIOCM_OUT1)
-		mcr |= UART_MCR_OUT1;
-	if (mctrl & TIOCM_OUT2)
-		mcr |= UART_MCR_OUT2;
-	if (mctrl & TIOCM_LOOP)
-		mcr |= UART_MCR_LOOP;
-
-	mcr |= up->mcr;
-
-	serial_out(up, UART_MCR, mcr);
-}
-
-static void serial_pxa_break_ctl(struct uart_port *port, int break_state)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned long flags;
-
-	spin_lock_irqsave(&up->port.lock, flags);
-	if (break_state == -1)
-		up->lcr |= UART_LCR_SBC;
-	else
-		up->lcr &= ~UART_LCR_SBC;
-	serial_out(up, UART_LCR, up->lcr);
-	spin_unlock_irqrestore(&up->port.lock, flags);
-}
-
-static int serial_pxa_startup(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned long flags;
-	int retval;
-
-	if (port->line == 3) /* HWUART */
-		up->mcr |= UART_MCR_AFE;
-	else
-		up->mcr = 0;
-
-	up->port.uartclk = clk_get_rate(up->clk);
-
-	/*
-	 * Allocate the IRQ
-	 */
-	retval = request_irq(up->port.irq, serial_pxa_irq, 0, up->name, up);
-	if (retval)
-		return retval;
-
-	/*
-	 * Clear the FIFO buffers and disable them.
-	 * (they will be reenabled in set_termios())
-	 */
-	serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO);
-	serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO |
-			UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
-	serial_out(up, UART_FCR, 0);
-
-	/*
-	 * Clear the interrupt registers.
-	 */
-	(void) serial_in(up, UART_LSR);
-	(void) serial_in(up, UART_RX);
-	(void) serial_in(up, UART_IIR);
-	(void) serial_in(up, UART_MSR);
-
-	/*
-	 * Now, initialize the UART
-	 */
-	serial_out(up, UART_LCR, UART_LCR_WLEN8);
-
-	spin_lock_irqsave(&up->port.lock, flags);
-	up->port.mctrl |= TIOCM_OUT2;
-	serial_pxa_set_mctrl(&up->port, up->port.mctrl);
-	spin_unlock_irqrestore(&up->port.lock, flags);
-
-	/*
-	 * Finally, enable interrupts.  Note: Modem status interrupts
-	 * are set via set_termios(), which will be occurring imminently
-	 * anyway, so we don't enable them here.
-	 */
-	up->ier = UART_IER_RLSI | UART_IER_RDI | UART_IER_RTOIE | UART_IER_UUE;
-	serial_out(up, UART_IER, up->ier);
-
-	/*
-	 * And clear the interrupt registers again for luck.
-	 */
-	(void) serial_in(up, UART_LSR);
-	(void) serial_in(up, UART_RX);
-	(void) serial_in(up, UART_IIR);
-	(void) serial_in(up, UART_MSR);
-
-	return 0;
-}
-
-static void serial_pxa_shutdown(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned long flags;
-
-	free_irq(up->port.irq, up);
-
-	/*
-	 * Disable interrupts from this port
-	 */
-	up->ier = 0;
-	serial_out(up, UART_IER, 0);
-
-	spin_lock_irqsave(&up->port.lock, flags);
-	up->port.mctrl &= ~TIOCM_OUT2;
-	serial_pxa_set_mctrl(&up->port, up->port.mctrl);
-	spin_unlock_irqrestore(&up->port.lock, flags);
-
-	/*
-	 * Disable break condition and FIFOs
-	 */
-	serial_out(up, UART_LCR, serial_in(up, UART_LCR) & ~UART_LCR_SBC);
-	serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO |
-				  UART_FCR_CLEAR_RCVR |
-				  UART_FCR_CLEAR_XMIT);
-	serial_out(up, UART_FCR, 0);
-}
-
-static void
-serial_pxa_set_termios(struct uart_port *port, struct ktermios *termios,
-		       struct ktermios *old)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned char cval, fcr = 0;
-	unsigned long flags;
-	unsigned int baud, quot;
-	unsigned int dll;
-
-	switch (termios->c_cflag & CSIZE) {
-	case CS5:
-		cval = UART_LCR_WLEN5;
-		break;
-	case CS6:
-		cval = UART_LCR_WLEN6;
-		break;
-	case CS7:
-		cval = UART_LCR_WLEN7;
-		break;
-	default:
-	case CS8:
-		cval = UART_LCR_WLEN8;
-		break;
-	}
-
-	if (termios->c_cflag & CSTOPB)
-		cval |= UART_LCR_STOP;
-	if (termios->c_cflag & PARENB)
-		cval |= UART_LCR_PARITY;
-	if (!(termios->c_cflag & PARODD))
-		cval |= UART_LCR_EPAR;
-
-	/*
-	 * Ask the core to calculate the divisor for us.
-	 */
-	baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
-	quot = uart_get_divisor(port, baud);
-
-	if ((up->port.uartclk / quot) < (2400 * 16))
-		fcr = UART_FCR_ENABLE_FIFO | UART_FCR_PXAR1;
-	else if ((up->port.uartclk / quot) < (230400 * 16))
-		fcr = UART_FCR_ENABLE_FIFO | UART_FCR_PXAR8;
-	else
-		fcr = UART_FCR_ENABLE_FIFO | UART_FCR_PXAR32;
-
-	/*
-	 * Ok, we're now changing the port state.  Do it with
-	 * interrupts disabled.
-	 */
-	spin_lock_irqsave(&up->port.lock, flags);
-
-	/*
-	 * Ensure the port will be enabled.
-	 * This is required especially for serial console.
-	 */
-	up->ier |= UART_IER_UUE;
-
-	/*
-	 * Update the per-port timeout.
-	 */
-	uart_update_timeout(port, termios->c_cflag, baud);
-
-	up->port.read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;
-	if (termios->c_iflag & INPCK)
-		up->port.read_status_mask |= UART_LSR_FE | UART_LSR_PE;
-	if (termios->c_iflag & (BRKINT | PARMRK))
-		up->port.read_status_mask |= UART_LSR_BI;
-
-	/*
-	 * Characters to ignore
-	 */
-	up->port.ignore_status_mask = 0;
-	if (termios->c_iflag & IGNPAR)
-		up->port.ignore_status_mask |= UART_LSR_PE | UART_LSR_FE;
-	if (termios->c_iflag & IGNBRK) {
-		up->port.ignore_status_mask |= UART_LSR_BI;
-		/*
-		 * If we're ignoring parity and break indicators,
-		 * ignore overruns too (for real raw support).
-		 */
-		if (termios->c_iflag & IGNPAR)
-			up->port.ignore_status_mask |= UART_LSR_OE;
-	}
-
-	/*
-	 * ignore all characters if CREAD is not set
-	 */
-	if ((termios->c_cflag & CREAD) == 0)
-		up->port.ignore_status_mask |= UART_LSR_DR;
-
-	/*
-	 * CTS flow control flag and modem status interrupts
-	 */
-	up->ier &= ~UART_IER_MSI;
-	if (UART_ENABLE_MS(&up->port, termios->c_cflag))
-		up->ier |= UART_IER_MSI;
-
-	serial_out(up, UART_IER, up->ier);
-
-	if (termios->c_cflag & CRTSCTS)
-		up->mcr |= UART_MCR_AFE;
-	else
-		up->mcr &= ~UART_MCR_AFE;
-
-	serial_out(up, UART_LCR, cval | UART_LCR_DLAB);	/* set DLAB */
-	serial_out(up, UART_DLL, quot & 0xff);		/* LS of divisor */
-
-	/*
-	 * work around Errata #75 according to Intel(R) PXA27x Processor Family
-	 * Specification Update (Nov 2005)
-	 */
-	dll = serial_in(up, UART_DLL);
-	WARN_ON(dll != (quot & 0xff));
-
-	serial_out(up, UART_DLM, quot >> 8);		/* MS of divisor */
-	serial_out(up, UART_LCR, cval);			/* reset DLAB */
-	up->lcr = cval;					/* Save LCR */
-	serial_pxa_set_mctrl(&up->port, up->port.mctrl);
-	serial_out(up, UART_FCR, fcr);
-	spin_unlock_irqrestore(&up->port.lock, flags);
-}
-
-static void
-serial_pxa_pm(struct uart_port *port, unsigned int state,
-	      unsigned int oldstate)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	if (!state)
-		clk_prepare_enable(up->clk);
-	else
-		clk_disable_unprepare(up->clk);
-}
-
-static void serial_pxa_release_port(struct uart_port *port)
-{
-}
-
-static int serial_pxa_request_port(struct uart_port *port)
-{
-	return 0;
-}
-
-static void serial_pxa_config_port(struct uart_port *port, int flags)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	up->port.type = PORT_PXA;
-}
-
-static int
-serial_pxa_verify_port(struct uart_port *port, struct serial_struct *ser)
-{
-	/* we don't want the core code to modify any port params */
-	return -EINVAL;
-}
-
-static const char *
-serial_pxa_type(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	return up->name;
-}
-
-static struct uart_pxa_port *serial_pxa_ports[4];
-static struct uart_driver serial_pxa_reg;
-
-#ifdef CONFIG_SERIAL_PXA_CONSOLE
-
-#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
-
-/*
- *	Wait for transmitter & holding register to empty
- */
-static inline void wait_for_xmitr(struct uart_pxa_port *up)
-{
-	unsigned int status, tmout = 10000;
-
-	/* Wait up to 10ms for the character(s) to be sent. */
-	do {
-		status = serial_in(up, UART_LSR);
-
-		if (status & UART_LSR_BI)
-			up->lsr_break_flag = UART_LSR_BI;
-
-		if (--tmout == 0)
-			break;
-		udelay(1);
-	} while ((status & BOTH_EMPTY) != BOTH_EMPTY);
-
-	/* Wait up to 1s for flow control if necessary */
-	if (up->port.flags & UPF_CONS_FLOW) {
-		tmout = 1000000;
-		while (--tmout &&
-		       ((serial_in(up, UART_MSR) & UART_MSR_CTS) == 0))
-			udelay(1);
-	}
-}
-
-static void serial_pxa_console_putchar(struct uart_port *port, int ch)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	wait_for_xmitr(up);
-	serial_out(up, UART_TX, ch);
-}
-
-/*
- * Print a string to the serial port trying not to disturb
- * any possible real use of the port...
- *
- *	The console_lock must be held when we get here.
- */
-static void
-serial_pxa_console_write(struct console *co, const char *s, unsigned int count)
-{
-	struct uart_pxa_port *up = serial_pxa_ports[co->index];
-	unsigned int ier;
-	unsigned long flags;
-	int locked = 1;
-
-	clk_enable(up->clk);
-	local_irq_save(flags);
-	if (up->port.sysrq)
-		locked = 0;
-	else if (oops_in_progress)
-		locked = spin_trylock(&up->port.lock);
-	else
-		spin_lock(&up->port.lock);
-
-	/*
-	 *	First save the IER then disable the interrupts
-	 */
-	ier = serial_in(up, UART_IER);
-	serial_out(up, UART_IER, UART_IER_UUE);
-
-	uart_console_write(&up->port, s, count, serial_pxa_console_putchar);
-
-	/*
-	 *	Finally, wait for transmitter to become empty
-	 *	and restore the IER
-	 */
-	wait_for_xmitr(up);
-	serial_out(up, UART_IER, ier);
-
-	if (locked)
-		spin_unlock(&up->port.lock);
-	local_irq_restore(flags);
-	clk_disable(up->clk);
-
-}
-
-#ifdef CONFIG_CONSOLE_POLL
-/*
- * Console polling routines for writing and reading from the uart while
- * in an interrupt or debug context.
- */
-
-static int serial_pxa_get_poll_char(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned char lsr = serial_in(up, UART_LSR);
-
-	while (!(lsr & UART_LSR_DR))
-		lsr = serial_in(up, UART_LSR);
-
-	return serial_in(up, UART_RX);
-}
-
-
-static void serial_pxa_put_poll_char(struct uart_port *port,
-			 unsigned char c)
-{
-	unsigned int ier;
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	/*
-	 *	First save the IER then disable the interrupts
-	 */
-	ier = serial_in(up, UART_IER);
-	serial_out(up, UART_IER, UART_IER_UUE);
-
-	wait_for_xmitr(up);
-	/*
-	 *	Send the character out.
-	 *	If a LF, also do CR...
-	 */
-	serial_out(up, UART_TX, c);
-	if (c == 10) {
-		wait_for_xmitr(up);
-		serial_out(up, UART_TX, 13);
-	}
-
-	/*
-	 *	Finally, wait for transmitter to become empty
-	 *	and restore the IER
-	 */
-	wait_for_xmitr(up);
-	serial_out(up, UART_IER, ier);
-}
-
-#endif /* CONFIG_CONSOLE_POLL */
-
-static int __init
-serial_pxa_console_setup(struct console *co, char *options)
-{
-	struct uart_pxa_port *up;
-	int baud = 9600;
-	int bits = 8;
-	int parity = 'n';
-	int flow = 'n';
-
-	if (co->index == -1 || co->index >= serial_pxa_reg.nr)
-		co->index = 0;
-	up = serial_pxa_ports[co->index];
-	if (!up)
-		return -ENODEV;
-
-	if (options)
-		uart_parse_options(options, &baud, &parity, &bits, &flow);
-
-	return uart_set_options(&up->port, co, baud, parity, bits, flow);
-}
-
-static struct console serial_pxa_console = {
-	.name		= "ttyS",
-	.write		= serial_pxa_console_write,
-	.device		= uart_console_device,
-	.setup		= serial_pxa_console_setup,
-	.flags		= CON_PRINTBUFFER,
-	.index		= -1,
-	.data		= &serial_pxa_reg,
-};
-
-#define PXA_CONSOLE	&serial_pxa_console
-#else
-#define PXA_CONSOLE	NULL
-#endif
-
-static struct uart_ops serial_pxa_pops = {
-	.tx_empty	= serial_pxa_tx_empty,
-	.set_mctrl	= serial_pxa_set_mctrl,
-	.get_mctrl	= serial_pxa_get_mctrl,
-	.stop_tx	= serial_pxa_stop_tx,
-	.start_tx	= serial_pxa_start_tx,
-	.stop_rx	= serial_pxa_stop_rx,
-	.enable_ms	= serial_pxa_enable_ms,
-	.break_ctl	= serial_pxa_break_ctl,
-	.startup	= serial_pxa_startup,
-	.shutdown	= serial_pxa_shutdown,
-	.set_termios	= serial_pxa_set_termios,
-	.pm		= serial_pxa_pm,
-	.type		= serial_pxa_type,
-	.release_port	= serial_pxa_release_port,
-	.request_port	= serial_pxa_request_port,
-	.config_port	= serial_pxa_config_port,
-	.verify_port	= serial_pxa_verify_port,
-#ifdef CONFIG_CONSOLE_POLL
-	.poll_get_char = serial_pxa_get_poll_char,
-	.poll_put_char = serial_pxa_put_poll_char,
-#endif
-};
-
-static struct uart_driver serial_pxa_reg = {
-	.owner		= THIS_MODULE,
-	.driver_name	= "PXA serial",
-	.dev_name	= "ttyS",
-	.major		= TTY_MAJOR,
-	.minor		= 64,
-	.nr		= 4,
-	.cons		= PXA_CONSOLE,
-};
-
-#ifdef CONFIG_PM
-static int serial_pxa_suspend(struct device *dev)
-{
-        struct uart_pxa_port *sport = dev_get_drvdata(dev);
-
-        if (sport)
-                uart_suspend_port(&serial_pxa_reg, &sport->port);
-
-        return 0;
-}
-
-static int serial_pxa_resume(struct device *dev)
-{
-        struct uart_pxa_port *sport = dev_get_drvdata(dev);
-
-        if (sport)
-                uart_resume_port(&serial_pxa_reg, &sport->port);
-
-        return 0;
-}
-
-static const struct dev_pm_ops serial_pxa_pm_ops = {
-	.suspend	= serial_pxa_suspend,
-	.resume		= serial_pxa_resume,
-};
-#endif
-
-static struct of_device_id serial_pxa_dt_ids[] = {
-	{ .compatible = "mrvl,pxa-uart", },
-	{ .compatible = "mrvl,mmp-uart", },
-	{}
-};
-MODULE_DEVICE_TABLE(of, serial_pxa_dt_ids);
-
-static int serial_pxa_probe_dt(struct platform_device *pdev,
-			       struct uart_pxa_port *sport)
-{
-	struct device_node *np = pdev->dev.of_node;
-	int ret;
-
-	if (!np)
-		return 1;
-
-	ret = of_alias_get_id(np, "serial");
-	if (ret < 0) {
-		dev_err(&pdev->dev, "failed to get alias id, errno %d\n", ret);
-		return ret;
-	}
-	sport->port.line = ret;
-	return 0;
-}
-
-static int serial_pxa_probe(struct platform_device *dev)
-{
-	struct uart_pxa_port *sport;
-	struct resource *mmres, *irqres;
-	int ret;
-
-	mmres = platform_get_resource(dev, IORESOURCE_MEM, 0);
-	irqres = platform_get_resource(dev, IORESOURCE_IRQ, 0);
-	if (!mmres || !irqres)
-		return -ENODEV;
-
-	sport = kzalloc(sizeof(struct uart_pxa_port), GFP_KERNEL);
-	if (!sport)
-		return -ENOMEM;
-
-	sport->clk = clk_get(&dev->dev, NULL);
-	if (IS_ERR(sport->clk)) {
-		ret = PTR_ERR(sport->clk);
-		goto err_free;
-	}
-
-	ret = clk_prepare(sport->clk);
-	if (ret) {
-		clk_put(sport->clk);
-		goto err_free;
-	}
-
-	sport->port.type = PORT_PXA;
-	sport->port.iotype = UPIO_MEM;
-	sport->port.mapbase = mmres->start;
-	sport->port.irq = irqres->start;
-	sport->port.fifosize = 64;
-	sport->port.ops = &serial_pxa_pops;
-	sport->port.dev = &dev->dev;
-	sport->port.flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF;
-	sport->port.uartclk = clk_get_rate(sport->clk);
-
-	ret = serial_pxa_probe_dt(dev, sport);
-	if (ret > 0)
-		sport->port.line = dev->id;
-	else if (ret < 0)
-		goto err_clk;
-	snprintf(sport->name, PXA_NAME_LEN - 1, "UART%d", sport->port.line + 1);
-
-	sport->port.membase = ioremap(mmres->start, resource_size(mmres));
-	if (!sport->port.membase) {
-		ret = -ENOMEM;
-		goto err_clk;
-	}
-
-	serial_pxa_ports[sport->port.line] = sport;
-
-	uart_add_one_port(&serial_pxa_reg, &sport->port);
-	platform_set_drvdata(dev, sport);
-
-	return 0;
-
- err_clk:
-	clk_unprepare(sport->clk);
-	clk_put(sport->clk);
- err_free:
-	kfree(sport);
-	return ret;
-}
-
-static int serial_pxa_remove(struct platform_device *dev)
-{
-	struct uart_pxa_port *sport = platform_get_drvdata(dev);
-
-	uart_remove_one_port(&serial_pxa_reg, &sport->port);
-
-	clk_unprepare(sport->clk);
-	clk_put(sport->clk);
-	kfree(sport);
-
-	return 0;
-}
-
-static struct platform_driver serial_pxa_driver = {
-        .probe          = serial_pxa_probe,
-        .remove         = serial_pxa_remove,
-
-	.driver		= {
-	        .name	= "pxa2xx-uart",
-		.owner	= THIS_MODULE,
-#ifdef CONFIG_PM
-		.pm	= &serial_pxa_pm_ops,
-#endif
-		.of_match_table = serial_pxa_dt_ids,
-	},
-};
-
-static int __init serial_pxa_init(void)
-{
-	int ret;
-
-	ret = uart_register_driver(&serial_pxa_reg);
-	if (ret != 0)
-		return ret;
-
-	ret = platform_driver_register(&serial_pxa_driver);
-	if (ret != 0)
-		uart_unregister_driver(&serial_pxa_reg);
-
-	return ret;
-}
-
-static void __exit serial_pxa_exit(void)
-{
-	platform_driver_unregister(&serial_pxa_driver);
-	uart_unregister_driver(&serial_pxa_reg);
-}
-
-module_init(serial_pxa_init);
-module_exit(serial_pxa_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:pxa2xx-uart");
-- 
1.8.4.3

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH] serial: rewrite pxa2xx-uart to use 8250_core
@ 2013-12-05 23:28                     ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-05 23:28 UTC (permalink / raw)
  To: linux-arm-kernel

pxa2xx-uart was a separate uart platform driver. It was declaring
the same device names and numbers as 8250 driver. As a result,
it was impossible to use 8250 driver on PXA SoCs.

Upon closer examination pxa2xx-uart turned out to be a clone of
8250_core driver.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Heikki Krogerus <heikki.krogerus@linux.intel.com>
CC: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 arch/arm/configs/am200epdkit_defconfig    |   3 +-
 arch/arm/configs/cm_x2xx_defconfig        |   3 +-
 arch/arm/configs/cm_x300_defconfig        |   3 +-
 arch/arm/configs/colibri_pxa270_defconfig |   3 +-
 arch/arm/configs/colibri_pxa300_defconfig |   3 +-
 arch/arm/configs/corgi_defconfig          |   4 +-
 arch/arm/configs/em_x270_defconfig        |   3 +-
 arch/arm/configs/ezx_defconfig            |   3 +-
 arch/arm/configs/h5000_defconfig          |   3 +-
 arch/arm/configs/imote2_defconfig         |   3 +-
 arch/arm/configs/lpd270_defconfig         |   3 +-
 arch/arm/configs/lubbock_defconfig        |   3 +-
 arch/arm/configs/mainstone_defconfig      |   3 +-
 arch/arm/configs/mmp2_defconfig           |   3 +-
 arch/arm/configs/pcm027_defconfig         |   3 +-
 arch/arm/configs/pxa168_defconfig         |   3 +-
 arch/arm/configs/pxa255-idp_defconfig     |   3 +-
 arch/arm/configs/pxa3xx_defconfig         |   3 +-
 arch/arm/configs/pxa910_defconfig         |   3 +-
 arch/arm/configs/raumfeld_defconfig       |   3 +-
 arch/arm/configs/spitz_defconfig          |   4 +-
 arch/arm/configs/trizeps4_defconfig       |   3 +-
 arch/arm/configs/viper_defconfig          |   4 +-
 arch/arm/configs/xcep_defconfig           |   3 +-
 drivers/tty/serial/8250/8250_pxa.c        | 180 ++++++
 drivers/tty/serial/8250/Kconfig           |   9 +
 drivers/tty/serial/8250/Makefile          |   1 +
 drivers/tty/serial/Kconfig                |  23 -
 drivers/tty/serial/Makefile               |   1 -
 drivers/tty/serial/pxa.c                  | 971 ------------------------------
 30 files changed, 238 insertions(+), 1022 deletions(-)
 create mode 100644 drivers/tty/serial/8250/8250_pxa.c
 delete mode 100644 drivers/tty/serial/pxa.c

diff --git a/arch/arm/configs/am200epdkit_defconfig b/arch/arm/configs/am200epdkit_defconfig
index f0dea52..0cde234 100644
--- a/arch/arm/configs/am200epdkit_defconfig
+++ b/arch/arm/configs/am200epdkit_defconfig
@@ -60,8 +60,9 @@ CONFIG_BLK_DEV_IDECS=m
 CONFIG_NETDEVICES=y
 CONFIG_NET_ETHERNET=y
 CONFIG_SMC91X=m
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 # CONFIG_HWMON is not set
diff --git a/arch/arm/configs/cm_x2xx_defconfig b/arch/arm/configs/cm_x2xx_defconfig
index a93ff8d..b9fbe65 100644
--- a/arch/arm/configs/cm_x2xx_defconfig
+++ b/arch/arm/configs/cm_x2xx_defconfig
@@ -96,8 +96,9 @@ CONFIG_KEYBOARD_PXA27x=m
 CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_TOUCHSCREEN_UCB1400=m
 # CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_LEGACY_PTY_COUNT=16
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/cm_x300_defconfig b/arch/arm/configs/cm_x300_defconfig
index f4b7672..53a82ae 100644
--- a/arch/arm/configs/cm_x300_defconfig
+++ b/arch/arm/configs/cm_x300_defconfig
@@ -80,8 +80,9 @@ CONFIG_TOUCHSCREEN_WM97XX=m
 # CONFIG_TOUCHSCREEN_WM9713 is not set
 # CONFIG_SERIO is not set
 # CONFIG_LEGACY_PTYS is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
 CONFIG_I2C_PXA=y
diff --git a/arch/arm/configs/colibri_pxa270_defconfig b/arch/arm/configs/colibri_pxa270_defconfig
index 2ef2c5e..1ce0409 100644
--- a/arch/arm/configs/colibri_pxa270_defconfig
+++ b/arch/arm/configs/colibri_pxa270_defconfig
@@ -103,8 +103,9 @@ CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=m
 CONFIG_SERIO_LIBPS2=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_HW_RANDOM=y
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
diff --git a/arch/arm/configs/colibri_pxa300_defconfig b/arch/arm/configs/colibri_pxa300_defconfig
index b985334..f96bda0 100644
--- a/arch/arm/configs/colibri_pxa300_defconfig
+++ b/arch/arm/configs/colibri_pxa300_defconfig
@@ -31,8 +31,9 @@ CONFIG_INPUT_EVDEV=y
 # CONFIG_INPUT_MOUSE is not set
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_GPIO_ROTARY_ENCODER=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_HW_RANDOM=y
 CONFIG_DEBUG_GPIO=y
 # CONFIG_HWMON is not set
diff --git a/arch/arm/configs/corgi_defconfig b/arch/arm/configs/corgi_defconfig
index 1fd1d1d..bb4842d 100644
--- a/arch/arm/configs/corgi_defconfig
+++ b/arch/arm/configs/corgi_defconfig
@@ -131,10 +131,10 @@ CONFIG_TOUCHSCREEN_ADS7846=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=m
 # CONFIG_SERIO is not set
-CONFIG_SERIAL_8250=m
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_CS=m
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 CONFIG_I2C=y
 CONFIG_I2C_PXA=y
diff --git a/arch/arm/configs/em_x270_defconfig b/arch/arm/configs/em_x270_defconfig
index 60a21e0..ec0ec54 100644
--- a/arch/arm/configs/em_x270_defconfig
+++ b/arch/arm/configs/em_x270_defconfig
@@ -90,8 +90,9 @@ CONFIG_TOUCHSCREEN_WM97XX=m
 # CONFIG_TOUCHSCREEN_WM9705 is not set
 # CONFIG_TOUCHSCREEN_WM9713 is not set
 # CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_LEGACY_PTY_COUNT=16
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/ezx_defconfig b/arch/arm/configs/ezx_defconfig
index d95763d..631e2ec 100644
--- a/arch/arm/configs/ezx_defconfig
+++ b/arch/arm/configs/ezx_defconfig
@@ -215,8 +215,9 @@ CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=y
 CONFIG_INPUT_PCAP=y
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_LEGACY_PTY_COUNT=8
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/h5000_defconfig b/arch/arm/configs/h5000_defconfig
index 37903e3..655b735 100644
--- a/arch/arm/configs/h5000_defconfig
+++ b/arch/arm/configs/h5000_defconfig
@@ -47,8 +47,9 @@ CONFIG_MTD_PHYSMAP=y
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_LEGACY_PTY_COUNT=32
 # CONFIG_HW_RANDOM is not set
 # CONFIG_HWMON is not set
diff --git a/arch/arm/configs/imote2_defconfig b/arch/arm/configs/imote2_defconfig
index fd996bb..49d45e9 100644
--- a/arch/arm/configs/imote2_defconfig
+++ b/arch/arm/configs/imote2_defconfig
@@ -193,8 +193,9 @@ CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=y
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_LEGACY_PTY_COUNT=8
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/lpd270_defconfig b/arch/arm/configs/lpd270_defconfig
index 1c8c9ee..c3927b6 100644
--- a/arch/arm/configs/lpd270_defconfig
+++ b/arch/arm/configs/lpd270_defconfig
@@ -38,8 +38,9 @@ CONFIG_SMC91X=y
 CONFIG_INPUT_EVDEV=y
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_HW_RANDOM is not set
 CONFIG_FB=y
 CONFIG_FB_PXA=y
diff --git a/arch/arm/configs/lubbock_defconfig b/arch/arm/configs/lubbock_defconfig
index c4ba274..c8b0436 100644
--- a/arch/arm/configs/lubbock_defconfig
+++ b/arch/arm/configs/lubbock_defconfig
@@ -37,8 +37,9 @@ CONFIG_PCMCIA_PCNET=y
 CONFIG_INPUT_EVDEV=y
 # CONFIG_SERIO_SERPORT is not set
 CONFIG_SERIO_SA1111=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_USB_GADGET=y
 CONFIG_USB_G_SERIAL=m
diff --git a/arch/arm/configs/mainstone_defconfig b/arch/arm/configs/mainstone_defconfig
index 04efa1b..768892c 100644
--- a/arch/arm/configs/mainstone_defconfig
+++ b/arch/arm/configs/mainstone_defconfig
@@ -34,8 +34,9 @@ CONFIG_SMC91X=y
 CONFIG_INPUT_EVDEV=y
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_FB=y
 CONFIG_FB_PXA=y
 # CONFIG_VGA_CONSOLE is not set
diff --git a/arch/arm/configs/mmp2_defconfig b/arch/arm/configs/mmp2_defconfig
index f1cb95e..1ced9df 100644
--- a/arch/arm/configs/mmp2_defconfig
+++ b/arch/arm/configs/mmp2_defconfig
@@ -44,8 +44,9 @@ CONFIG_SMC91X=y
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/pcm027_defconfig b/arch/arm/configs/pcm027_defconfig
index 2f136c3..1280128 100644
--- a/arch/arm/configs/pcm027_defconfig
+++ b/arch/arm/configs/pcm027_defconfig
@@ -60,8 +60,9 @@ CONFIG_SMC91X=y
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/pxa168_defconfig b/arch/arm/configs/pxa168_defconfig
index 74d7e01..1668dac 100644
--- a/arch/arm/configs/pxa168_defconfig
+++ b/arch/arm/configs/pxa168_defconfig
@@ -40,8 +40,9 @@ CONFIG_SMC91X=y
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 # CONFIG_HWMON is not set
diff --git a/arch/arm/configs/pxa255-idp_defconfig b/arch/arm/configs/pxa255-idp_defconfig
index 917a070..399a706 100644
--- a/arch/arm/configs/pxa255-idp_defconfig
+++ b/arch/arm/configs/pxa255-idp_defconfig
@@ -35,8 +35,9 @@ CONFIG_SMC91X=y
 CONFIG_INPUT_EVDEV=y
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_FB=y
 CONFIG_FB_PXA=y
 # CONFIG_VGA_CONSOLE is not set
diff --git a/arch/arm/configs/pxa3xx_defconfig b/arch/arm/configs/pxa3xx_defconfig
index 60e3138..7c3e052 100644
--- a/arch/arm/configs/pxa3xx_defconfig
+++ b/arch/arm/configs/pxa3xx_defconfig
@@ -56,8 +56,9 @@ CONFIG_KEYBOARD_PXA27x=y
 CONFIG_KEYBOARD_PXA930_ROTARY=y
 CONFIG_MOUSE_PXA930_TRKBALL=y
 CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/pxa910_defconfig b/arch/arm/configs/pxa910_defconfig
index 3bb7771..cdacfcb 100644
--- a/arch/arm/configs/pxa910_defconfig
+++ b/arch/arm/configs/pxa910_defconfig
@@ -40,8 +40,9 @@ CONFIG_SMC91X=y
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_SPI=y
 CONFIG_FB=y
 CONFIG_MMP_DISP=y
diff --git a/arch/arm/configs/raumfeld_defconfig b/arch/arm/configs/raumfeld_defconfig
index f7caa90..f1e16f2 100644
--- a/arch/arm/configs/raumfeld_defconfig
+++ b/arch/arm/configs/raumfeld_defconfig
@@ -67,8 +67,9 @@ CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_TOUCHSCREEN_EETI=m
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_GPIO_ROTARY_ENCODER=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_HW_RANDOM=y
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
diff --git a/arch/arm/configs/spitz_defconfig b/arch/arm/configs/spitz_defconfig
index 2e0419d..b6efcf5 100644
--- a/arch/arm/configs/spitz_defconfig
+++ b/arch/arm/configs/spitz_defconfig
@@ -128,10 +128,10 @@ CONFIG_TOUCHSCREEN_ADS7846=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=m
 # CONFIG_SERIO is not set
-CONFIG_SERIAL_8250=m
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_CS=m
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 CONFIG_SPI=y
 CONFIG_SPI_PXA2XX=y
diff --git a/arch/arm/configs/trizeps4_defconfig b/arch/arm/configs/trizeps4_defconfig
index 3162173..453c79c 100644
--- a/arch/arm/configs/trizeps4_defconfig
+++ b/arch/arm/configs/trizeps4_defconfig
@@ -132,8 +132,9 @@ CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=m
 CONFIG_SERIO_LIBPS2=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_HW_RANDOM=y
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
diff --git a/arch/arm/configs/viper_defconfig b/arch/arm/configs/viper_defconfig
index d36e0d3..4efac06 100644
--- a/arch/arm/configs/viper_defconfig
+++ b/arch/arm/configs/viper_defconfig
@@ -101,11 +101,11 @@ CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=m
 # CONFIG_CONSOLE_TRANSLATIONS is not set
 # CONFIG_VT_CONSOLE is not set
-CONFIG_SERIAL_8250=m
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_NR_UARTS=5
 CONFIG_SERIAL_8250_RUNTIME_UARTS=5
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
diff --git a/arch/arm/configs/xcep_defconfig b/arch/arm/configs/xcep_defconfig
index 721832f..b67aeaf 100644
--- a/arch/arm/configs/xcep_defconfig
+++ b/arch/arm/configs/xcep_defconfig
@@ -60,8 +60,9 @@ CONFIG_NET_ETHERNET=y
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
 # CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=m
diff --git a/drivers/tty/serial/8250/8250_pxa.c b/drivers/tty/serial/8250/8250_pxa.c
new file mode 100644
index 0000000..5658fc9
--- /dev/null
+++ b/drivers/tty/serial/8250/8250_pxa.c
@@ -0,0 +1,180 @@
+/*
+ *  drivers/tty/serial/8250/8250_pxa.c -- driver for PXA on-board UARTS
+ *  Copyright:	(C) 2013 Sergei Ianovich <ynvich@gmail.com>
+ *
+ *  replaces drivers/serial/pxa.c by Nicolas Pitre
+ *  Created:	Feb 20, 2003
+ *  Copyright:	(C) 2003 Monta Vista Software, Inc.
+ *
+ *  Based on drivers/serial/8250.c by Russell King.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/serial_8250.h>
+#include <linux/serial_core.h>
+#include <linux/serial_reg.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
+#include <linux/pm_runtime.h>
+
+#include "8250.h"
+
+struct pxa8250_data {
+	int			line;
+	struct clk		*clk;
+};
+
+#ifdef CONFIG_PM
+static int serial_pxa_suspend(struct device *dev)
+{
+	struct pxa8250_data *data = dev_get_drvdata(dev);
+
+	serial8250_suspend_port(data->line);
+
+	return 0;
+}
+
+static int serial_pxa_resume(struct device *dev)
+{
+	struct pxa8250_data *data = dev_get_drvdata(dev);
+
+	serial8250_resume_port(data->line);
+
+	return 0;
+}
+
+static const struct dev_pm_ops serial_pxa_pm_ops = {
+	.suspend	= serial_pxa_suspend,
+	.resume		= serial_pxa_resume,
+};
+#endif
+
+static struct of_device_id serial_pxa_dt_ids[] = {
+	{ .compatible = "mrvl,pxa-uart", },
+	{ .compatible = "mrvl,mmp-uart", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, serial_pxa_dt_ids);
+
+/* Uart divisor latch write */
+static void serial_pxa_dl_write(struct uart_8250_port *up, int value)
+{
+	serial_out(up, UART_DLL, value & 0xff);
+	serial_out(up, UART_DLM, value >> 8 & 0xff);
+}
+
+
+static void serial_pxa_pm(struct uart_port *port, unsigned int state,
+	      unsigned int oldstate)
+{
+	struct pxa8250_data *data = port->private_data;
+
+	if (!state)
+		clk_prepare_enable(data->clk);
+	else
+		clk_disable_unprepare(data->clk);
+}
+
+static int serial_pxa_probe(struct platform_device *pdev)
+{
+	struct uart_8250_port uart = {};
+	struct pxa8250_data *data;
+	struct resource *mmres, *irqres;
+	int ret;
+
+	mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	irqres = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!mmres || !irqres)
+		return -ENODEV;
+
+	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(data->clk)) {
+		ret = PTR_ERR(data->clk);
+		goto err_free;
+	}
+
+	ret = clk_prepare(data->clk);
+	if (ret)
+		goto err_free_clk;
+
+	uart.port.type = PORT_XSCALE;
+	uart.port.iotype = UPIO_MEM32;
+	uart.port.mapbase = mmres->start;
+	uart.port.regshift = 2;
+	uart.port.irq = irqres->start;
+	uart.port.fifosize = 64;
+	uart.port.flags = UPF_IOREMAP | UPF_SKIP_TEST;
+	uart.port.dev = &pdev->dev;
+	uart.port.uartclk = clk_get_rate(data->clk);
+	uart.port.pm = serial_pxa_pm;
+	uart.port.private_data = data;
+	uart.dl_write = serial_pxa_dl_write;
+
+	ret = serial8250_register_8250_port(&uart);
+	if (ret < 0)
+		goto err_clk;
+
+	data->line = ret;
+
+	platform_set_drvdata(pdev, data);
+
+	return 0;
+
+ err_clk:
+	clk_unprepare(data->clk);
+ err_free_clk:
+	devm_clk_put(&pdev->dev, data->clk);
+ err_free:
+	devm_kfree(&pdev->dev, data);
+	return ret;
+}
+
+static int serial_pxa_remove(struct platform_device *pdev)
+{
+	struct pxa8250_data *data = platform_get_drvdata(pdev);
+
+	serial8250_unregister_port(data->line);
+
+	clk_unprepare(data->clk);
+	devm_clk_put(&pdev->dev, data->clk);
+	devm_kfree(&pdev->dev, data);
+
+	return 0;
+}
+
+static struct platform_driver serial_pxa_driver = {
+	.probe          = serial_pxa_probe,
+	.remove         = serial_pxa_remove,
+
+	.driver		= {
+		.name	= "pxa2xx-uart",
+		.owner	= THIS_MODULE,
+#ifdef CONFIG_PM
+		.pm	= &serial_pxa_pm_ops,
+#endif
+		.of_match_table = serial_pxa_dt_ids,
+	},
+};
+
+module_platform_driver(serial_pxa_driver);
+
+MODULE_AUTHOR("Sergei Ianovich");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:pxa2xx-uart");
diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
index 2332991..81bd7c9 100644
--- a/drivers/tty/serial/8250/Kconfig
+++ b/drivers/tty/serial/8250/Kconfig
@@ -302,3 +302,12 @@ config SERIAL_8250_RT288X
 	  If you have a Ralink RT288x/RT305x SoC based board and want to use the
 	  serial port, say Y to this option. The driver can handle up to 2 serial
 	  ports. If unsure, say N.
+
+config SERIAL_PXA
+	tristate "PXA serial port support"
+	depends on SERIAL_8250 && (ARCH_PXA || ARCH_MMP)
+	help
+	  If you have a machine based on an Intel XScale PXA2xx CPU you
+	  can enable its onboard serial ports by enabling this option.
+
+	  If you choose M here, the module name will be 8250_pxa.
diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile
index 36d68d0..b7d1b61 100644
--- a/drivers/tty/serial/8250/Makefile
+++ b/drivers/tty/serial/8250/Makefile
@@ -20,3 +20,4 @@ obj-$(CONFIG_SERIAL_8250_HUB6)		+= 8250_hub6.o
 obj-$(CONFIG_SERIAL_8250_FSL)		+= 8250_fsl.o
 obj-$(CONFIG_SERIAL_8250_DW)		+= 8250_dw.o
 obj-$(CONFIG_SERIAL_8250_EM)		+= 8250_em.o
+obj-$(CONFIG_SERIAL_PXA)		+= 8250_pxa.o
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index a3817ab..2ad7184b 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -396,29 +396,6 @@ config SERIAL_MPSC_CONSOLE
 	help
 	  Say Y here if you want to support a serial console on a Marvell MPSC.
 
-config SERIAL_PXA
-	bool "PXA serial port support"
-	depends on ARCH_PXA || ARCH_MMP
-	select SERIAL_CORE
-	help
-	  If you have a machine based on an Intel XScale PXA2xx CPU you
-	  can enable its onboard serial ports by enabling this option.
-
-config SERIAL_PXA_CONSOLE
-	bool "Console on PXA serial port"
-	depends on SERIAL_PXA
-	select SERIAL_CORE_CONSOLE
-	help
-	  If you have enabled the serial port on the Intel XScale PXA
-	  CPU you can make it the console by answering Y to this option.
-
-	  Even if you say Y here, the currently visible virtual console
-	  (/dev/tty0) will still be used as the system console by default, but
-	  you can alter that using a kernel command line option such as
-	  "console=ttySA0". (Try "man bootparam" or see the documentation of
-	  your boot loader (lilo or loadlin) about how to pass options to the
-	  kernel at boot time.)
-
 config SERIAL_SA1100
 	bool "SA1100 serial port support"
 	depends on ARCH_SA1100
diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile
index 3068c77..4ac337b 100644
--- a/drivers/tty/serial/Makefile
+++ b/drivers/tty/serial/Makefile
@@ -20,7 +20,6 @@ obj-$(CONFIG_SERIAL_8250) += 8250/
 obj-$(CONFIG_SERIAL_AMBA_PL010) += amba-pl010.o
 obj-$(CONFIG_SERIAL_AMBA_PL011) += amba-pl011.o
 obj-$(CONFIG_SERIAL_CLPS711X) += clps711x.o
-obj-$(CONFIG_SERIAL_PXA) += pxa.o
 obj-$(CONFIG_SERIAL_PNX8XXX) += pnx8xxx_uart.o
 obj-$(CONFIG_SERIAL_SA1100) += sa1100.o
 obj-$(CONFIG_SERIAL_BCM63XX) += bcm63xx_uart.o
diff --git a/drivers/tty/serial/pxa.c b/drivers/tty/serial/pxa.c
deleted file mode 100644
index f9f20f3..0000000
--- a/drivers/tty/serial/pxa.c
+++ /dev/null
@@ -1,971 +0,0 @@
-/*
- *  Based on drivers/serial/8250.c by Russell King.
- *
- *  Author:	Nicolas Pitre
- *  Created:	Feb 20, 2003
- *  Copyright:	(C) 2003 Monta Vista Software, Inc.
- *
- * 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.
- *
- * Note 1: This driver is made separate from the already too overloaded
- * 8250.c because it needs some kirks of its own and that'll make it
- * easier to add DMA support.
- *
- * Note 2: I'm too sick of device allocation policies for serial ports.
- * If someone else wants to request an "official" allocation of major/minor
- * for this driver please be my guest.  And don't forget that new hardware
- * to come from Intel might have more than 3 or 4 of those UARTs.  Let's
- * hope for a better port registration and dynamic device allocation scheme
- * with the serial core maintainer satisfaction to appear soon.
- */
-
-
-#if defined(CONFIG_SERIAL_PXA_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-#define SUPPORT_SYSRQ
-#endif
-
-#include <linux/module.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-#include <linux/console.h>
-#include <linux/sysrq.h>
-#include <linux/serial_reg.h>
-#include <linux/circ_buf.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/of.h>
-#include <linux/platform_device.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/serial_core.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-
-#define PXA_NAME_LEN		8
-
-struct uart_pxa_port {
-	struct uart_port        port;
-	unsigned char           ier;
-	unsigned char           lcr;
-	unsigned char           mcr;
-	unsigned int            lsr_break_flag;
-	struct clk		*clk;
-	char			name[PXA_NAME_LEN];
-};
-
-static inline unsigned int serial_in(struct uart_pxa_port *up, int offset)
-{
-	offset <<= 2;
-	return readl(up->port.membase + offset);
-}
-
-static inline void serial_out(struct uart_pxa_port *up, int offset, int value)
-{
-	offset <<= 2;
-	writel(value, up->port.membase + offset);
-}
-
-static void serial_pxa_enable_ms(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	up->ier |= UART_IER_MSI;
-	serial_out(up, UART_IER, up->ier);
-}
-
-static void serial_pxa_stop_tx(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	if (up->ier & UART_IER_THRI) {
-		up->ier &= ~UART_IER_THRI;
-		serial_out(up, UART_IER, up->ier);
-	}
-}
-
-static void serial_pxa_stop_rx(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	up->ier &= ~UART_IER_RLSI;
-	up->port.read_status_mask &= ~UART_LSR_DR;
-	serial_out(up, UART_IER, up->ier);
-}
-
-static inline void receive_chars(struct uart_pxa_port *up, int *status)
-{
-	unsigned int ch, flag;
-	int max_count = 256;
-
-	do {
-		/* work around Errata #20 according to
-		 * Intel(R) PXA27x Processor Family
-		 * Specification Update (May 2005)
-		 *
-		 * Step 2
-		 * Disable the Reciever Time Out Interrupt via IER[RTOEI]
-		 */
-		up->ier &= ~UART_IER_RTOIE;
-		serial_out(up, UART_IER, up->ier);
-
-		ch = serial_in(up, UART_RX);
-		flag = TTY_NORMAL;
-		up->port.icount.rx++;
-
-		if (unlikely(*status & (UART_LSR_BI | UART_LSR_PE |
-				       UART_LSR_FE | UART_LSR_OE))) {
-			/*
-			 * For statistics only
-			 */
-			if (*status & UART_LSR_BI) {
-				*status &= ~(UART_LSR_FE | UART_LSR_PE);
-				up->port.icount.brk++;
-				/*
-				 * We do the SysRQ and SAK checking
-				 * here because otherwise the break
-				 * may get masked by ignore_status_mask
-				 * or read_status_mask.
-				 */
-				if (uart_handle_break(&up->port))
-					goto ignore_char;
-			} else if (*status & UART_LSR_PE)
-				up->port.icount.parity++;
-			else if (*status & UART_LSR_FE)
-				up->port.icount.frame++;
-			if (*status & UART_LSR_OE)
-				up->port.icount.overrun++;
-
-			/*
-			 * Mask off conditions which should be ignored.
-			 */
-			*status &= up->port.read_status_mask;
-
-#ifdef CONFIG_SERIAL_PXA_CONSOLE
-			if (up->port.line == up->port.cons->index) {
-				/* Recover the break flag from console xmit */
-				*status |= up->lsr_break_flag;
-				up->lsr_break_flag = 0;
-			}
-#endif
-			if (*status & UART_LSR_BI) {
-				flag = TTY_BREAK;
-			} else if (*status & UART_LSR_PE)
-				flag = TTY_PARITY;
-			else if (*status & UART_LSR_FE)
-				flag = TTY_FRAME;
-		}
-
-		if (uart_handle_sysrq_char(&up->port, ch))
-			goto ignore_char;
-
-		uart_insert_char(&up->port, *status, UART_LSR_OE, ch, flag);
-
-	ignore_char:
-		*status = serial_in(up, UART_LSR);
-	} while ((*status & UART_LSR_DR) && (max_count-- > 0));
-	tty_flip_buffer_push(&up->port.state->port);
-
-	/* work around Errata #20 according to
-	 * Intel(R) PXA27x Processor Family
-	 * Specification Update (May 2005)
-	 *
-	 * Step 6:
-	 * No more data in FIFO: Re-enable RTO interrupt via IER[RTOIE]
-	 */
-	up->ier |= UART_IER_RTOIE;
-	serial_out(up, UART_IER, up->ier);
-}
-
-static void transmit_chars(struct uart_pxa_port *up)
-{
-	struct circ_buf *xmit = &up->port.state->xmit;
-	int count;
-
-	if (up->port.x_char) {
-		serial_out(up, UART_TX, up->port.x_char);
-		up->port.icount.tx++;
-		up->port.x_char = 0;
-		return;
-	}
-	if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) {
-		serial_pxa_stop_tx(&up->port);
-		return;
-	}
-
-	count = up->port.fifosize / 2;
-	do {
-		serial_out(up, UART_TX, xmit->buf[xmit->tail]);
-		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
-		up->port.icount.tx++;
-		if (uart_circ_empty(xmit))
-			break;
-	} while (--count > 0);
-
-	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
-		uart_write_wakeup(&up->port);
-
-
-	if (uart_circ_empty(xmit))
-		serial_pxa_stop_tx(&up->port);
-}
-
-static void serial_pxa_start_tx(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	if (!(up->ier & UART_IER_THRI)) {
-		up->ier |= UART_IER_THRI;
-		serial_out(up, UART_IER, up->ier);
-	}
-}
-
-static inline void check_modem_status(struct uart_pxa_port *up)
-{
-	int status;
-
-	status = serial_in(up, UART_MSR);
-
-	if ((status & UART_MSR_ANY_DELTA) == 0)
-		return;
-
-	if (status & UART_MSR_TERI)
-		up->port.icount.rng++;
-	if (status & UART_MSR_DDSR)
-		up->port.icount.dsr++;
-	if (status & UART_MSR_DDCD)
-		uart_handle_dcd_change(&up->port, status & UART_MSR_DCD);
-	if (status & UART_MSR_DCTS)
-		uart_handle_cts_change(&up->port, status & UART_MSR_CTS);
-
-	wake_up_interruptible(&up->port.state->port.delta_msr_wait);
-}
-
-/*
- * This handles the interrupt from one port.
- */
-static inline irqreturn_t serial_pxa_irq(int irq, void *dev_id)
-{
-	struct uart_pxa_port *up = dev_id;
-	unsigned int iir, lsr;
-
-	iir = serial_in(up, UART_IIR);
-	if (iir & UART_IIR_NO_INT)
-		return IRQ_NONE;
-	lsr = serial_in(up, UART_LSR);
-	if (lsr & UART_LSR_DR)
-		receive_chars(up, &lsr);
-	check_modem_status(up);
-	if (lsr & UART_LSR_THRE)
-		transmit_chars(up);
-	return IRQ_HANDLED;
-}
-
-static unsigned int serial_pxa_tx_empty(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned long flags;
-	unsigned int ret;
-
-	spin_lock_irqsave(&up->port.lock, flags);
-	ret = serial_in(up, UART_LSR) & UART_LSR_TEMT ? TIOCSER_TEMT : 0;
-	spin_unlock_irqrestore(&up->port.lock, flags);
-
-	return ret;
-}
-
-static unsigned int serial_pxa_get_mctrl(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned char status;
-	unsigned int ret;
-
-	status = serial_in(up, UART_MSR);
-
-	ret = 0;
-	if (status & UART_MSR_DCD)
-		ret |= TIOCM_CAR;
-	if (status & UART_MSR_RI)
-		ret |= TIOCM_RNG;
-	if (status & UART_MSR_DSR)
-		ret |= TIOCM_DSR;
-	if (status & UART_MSR_CTS)
-		ret |= TIOCM_CTS;
-	return ret;
-}
-
-static void serial_pxa_set_mctrl(struct uart_port *port, unsigned int mctrl)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned char mcr = 0;
-
-	if (mctrl & TIOCM_RTS)
-		mcr |= UART_MCR_RTS;
-	if (mctrl & TIOCM_DTR)
-		mcr |= UART_MCR_DTR;
-	if (mctrl & TIOCM_OUT1)
-		mcr |= UART_MCR_OUT1;
-	if (mctrl & TIOCM_OUT2)
-		mcr |= UART_MCR_OUT2;
-	if (mctrl & TIOCM_LOOP)
-		mcr |= UART_MCR_LOOP;
-
-	mcr |= up->mcr;
-
-	serial_out(up, UART_MCR, mcr);
-}
-
-static void serial_pxa_break_ctl(struct uart_port *port, int break_state)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned long flags;
-
-	spin_lock_irqsave(&up->port.lock, flags);
-	if (break_state == -1)
-		up->lcr |= UART_LCR_SBC;
-	else
-		up->lcr &= ~UART_LCR_SBC;
-	serial_out(up, UART_LCR, up->lcr);
-	spin_unlock_irqrestore(&up->port.lock, flags);
-}
-
-static int serial_pxa_startup(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned long flags;
-	int retval;
-
-	if (port->line == 3) /* HWUART */
-		up->mcr |= UART_MCR_AFE;
-	else
-		up->mcr = 0;
-
-	up->port.uartclk = clk_get_rate(up->clk);
-
-	/*
-	 * Allocate the IRQ
-	 */
-	retval = request_irq(up->port.irq, serial_pxa_irq, 0, up->name, up);
-	if (retval)
-		return retval;
-
-	/*
-	 * Clear the FIFO buffers and disable them.
-	 * (they will be reenabled in set_termios())
-	 */
-	serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO);
-	serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO |
-			UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
-	serial_out(up, UART_FCR, 0);
-
-	/*
-	 * Clear the interrupt registers.
-	 */
-	(void) serial_in(up, UART_LSR);
-	(void) serial_in(up, UART_RX);
-	(void) serial_in(up, UART_IIR);
-	(void) serial_in(up, UART_MSR);
-
-	/*
-	 * Now, initialize the UART
-	 */
-	serial_out(up, UART_LCR, UART_LCR_WLEN8);
-
-	spin_lock_irqsave(&up->port.lock, flags);
-	up->port.mctrl |= TIOCM_OUT2;
-	serial_pxa_set_mctrl(&up->port, up->port.mctrl);
-	spin_unlock_irqrestore(&up->port.lock, flags);
-
-	/*
-	 * Finally, enable interrupts.  Note: Modem status interrupts
-	 * are set via set_termios(), which will be occurring imminently
-	 * anyway, so we don't enable them here.
-	 */
-	up->ier = UART_IER_RLSI | UART_IER_RDI | UART_IER_RTOIE | UART_IER_UUE;
-	serial_out(up, UART_IER, up->ier);
-
-	/*
-	 * And clear the interrupt registers again for luck.
-	 */
-	(void) serial_in(up, UART_LSR);
-	(void) serial_in(up, UART_RX);
-	(void) serial_in(up, UART_IIR);
-	(void) serial_in(up, UART_MSR);
-
-	return 0;
-}
-
-static void serial_pxa_shutdown(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned long flags;
-
-	free_irq(up->port.irq, up);
-
-	/*
-	 * Disable interrupts from this port
-	 */
-	up->ier = 0;
-	serial_out(up, UART_IER, 0);
-
-	spin_lock_irqsave(&up->port.lock, flags);
-	up->port.mctrl &= ~TIOCM_OUT2;
-	serial_pxa_set_mctrl(&up->port, up->port.mctrl);
-	spin_unlock_irqrestore(&up->port.lock, flags);
-
-	/*
-	 * Disable break condition and FIFOs
-	 */
-	serial_out(up, UART_LCR, serial_in(up, UART_LCR) & ~UART_LCR_SBC);
-	serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO |
-				  UART_FCR_CLEAR_RCVR |
-				  UART_FCR_CLEAR_XMIT);
-	serial_out(up, UART_FCR, 0);
-}
-
-static void
-serial_pxa_set_termios(struct uart_port *port, struct ktermios *termios,
-		       struct ktermios *old)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned char cval, fcr = 0;
-	unsigned long flags;
-	unsigned int baud, quot;
-	unsigned int dll;
-
-	switch (termios->c_cflag & CSIZE) {
-	case CS5:
-		cval = UART_LCR_WLEN5;
-		break;
-	case CS6:
-		cval = UART_LCR_WLEN6;
-		break;
-	case CS7:
-		cval = UART_LCR_WLEN7;
-		break;
-	default:
-	case CS8:
-		cval = UART_LCR_WLEN8;
-		break;
-	}
-
-	if (termios->c_cflag & CSTOPB)
-		cval |= UART_LCR_STOP;
-	if (termios->c_cflag & PARENB)
-		cval |= UART_LCR_PARITY;
-	if (!(termios->c_cflag & PARODD))
-		cval |= UART_LCR_EPAR;
-
-	/*
-	 * Ask the core to calculate the divisor for us.
-	 */
-	baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
-	quot = uart_get_divisor(port, baud);
-
-	if ((up->port.uartclk / quot) < (2400 * 16))
-		fcr = UART_FCR_ENABLE_FIFO | UART_FCR_PXAR1;
-	else if ((up->port.uartclk / quot) < (230400 * 16))
-		fcr = UART_FCR_ENABLE_FIFO | UART_FCR_PXAR8;
-	else
-		fcr = UART_FCR_ENABLE_FIFO | UART_FCR_PXAR32;
-
-	/*
-	 * Ok, we're now changing the port state.  Do it with
-	 * interrupts disabled.
-	 */
-	spin_lock_irqsave(&up->port.lock, flags);
-
-	/*
-	 * Ensure the port will be enabled.
-	 * This is required especially for serial console.
-	 */
-	up->ier |= UART_IER_UUE;
-
-	/*
-	 * Update the per-port timeout.
-	 */
-	uart_update_timeout(port, termios->c_cflag, baud);
-
-	up->port.read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;
-	if (termios->c_iflag & INPCK)
-		up->port.read_status_mask |= UART_LSR_FE | UART_LSR_PE;
-	if (termios->c_iflag & (BRKINT | PARMRK))
-		up->port.read_status_mask |= UART_LSR_BI;
-
-	/*
-	 * Characters to ignore
-	 */
-	up->port.ignore_status_mask = 0;
-	if (termios->c_iflag & IGNPAR)
-		up->port.ignore_status_mask |= UART_LSR_PE | UART_LSR_FE;
-	if (termios->c_iflag & IGNBRK) {
-		up->port.ignore_status_mask |= UART_LSR_BI;
-		/*
-		 * If we're ignoring parity and break indicators,
-		 * ignore overruns too (for real raw support).
-		 */
-		if (termios->c_iflag & IGNPAR)
-			up->port.ignore_status_mask |= UART_LSR_OE;
-	}
-
-	/*
-	 * ignore all characters if CREAD is not set
-	 */
-	if ((termios->c_cflag & CREAD) == 0)
-		up->port.ignore_status_mask |= UART_LSR_DR;
-
-	/*
-	 * CTS flow control flag and modem status interrupts
-	 */
-	up->ier &= ~UART_IER_MSI;
-	if (UART_ENABLE_MS(&up->port, termios->c_cflag))
-		up->ier |= UART_IER_MSI;
-
-	serial_out(up, UART_IER, up->ier);
-
-	if (termios->c_cflag & CRTSCTS)
-		up->mcr |= UART_MCR_AFE;
-	else
-		up->mcr &= ~UART_MCR_AFE;
-
-	serial_out(up, UART_LCR, cval | UART_LCR_DLAB);	/* set DLAB */
-	serial_out(up, UART_DLL, quot & 0xff);		/* LS of divisor */
-
-	/*
-	 * work around Errata #75 according to Intel(R) PXA27x Processor Family
-	 * Specification Update (Nov 2005)
-	 */
-	dll = serial_in(up, UART_DLL);
-	WARN_ON(dll != (quot & 0xff));
-
-	serial_out(up, UART_DLM, quot >> 8);		/* MS of divisor */
-	serial_out(up, UART_LCR, cval);			/* reset DLAB */
-	up->lcr = cval;					/* Save LCR */
-	serial_pxa_set_mctrl(&up->port, up->port.mctrl);
-	serial_out(up, UART_FCR, fcr);
-	spin_unlock_irqrestore(&up->port.lock, flags);
-}
-
-static void
-serial_pxa_pm(struct uart_port *port, unsigned int state,
-	      unsigned int oldstate)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	if (!state)
-		clk_prepare_enable(up->clk);
-	else
-		clk_disable_unprepare(up->clk);
-}
-
-static void serial_pxa_release_port(struct uart_port *port)
-{
-}
-
-static int serial_pxa_request_port(struct uart_port *port)
-{
-	return 0;
-}
-
-static void serial_pxa_config_port(struct uart_port *port, int flags)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	up->port.type = PORT_PXA;
-}
-
-static int
-serial_pxa_verify_port(struct uart_port *port, struct serial_struct *ser)
-{
-	/* we don't want the core code to modify any port params */
-	return -EINVAL;
-}
-
-static const char *
-serial_pxa_type(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	return up->name;
-}
-
-static struct uart_pxa_port *serial_pxa_ports[4];
-static struct uart_driver serial_pxa_reg;
-
-#ifdef CONFIG_SERIAL_PXA_CONSOLE
-
-#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
-
-/*
- *	Wait for transmitter & holding register to empty
- */
-static inline void wait_for_xmitr(struct uart_pxa_port *up)
-{
-	unsigned int status, tmout = 10000;
-
-	/* Wait up to 10ms for the character(s) to be sent. */
-	do {
-		status = serial_in(up, UART_LSR);
-
-		if (status & UART_LSR_BI)
-			up->lsr_break_flag = UART_LSR_BI;
-
-		if (--tmout == 0)
-			break;
-		udelay(1);
-	} while ((status & BOTH_EMPTY) != BOTH_EMPTY);
-
-	/* Wait up to 1s for flow control if necessary */
-	if (up->port.flags & UPF_CONS_FLOW) {
-		tmout = 1000000;
-		while (--tmout &&
-		       ((serial_in(up, UART_MSR) & UART_MSR_CTS) == 0))
-			udelay(1);
-	}
-}
-
-static void serial_pxa_console_putchar(struct uart_port *port, int ch)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	wait_for_xmitr(up);
-	serial_out(up, UART_TX, ch);
-}
-
-/*
- * Print a string to the serial port trying not to disturb
- * any possible real use of the port...
- *
- *	The console_lock must be held when we get here.
- */
-static void
-serial_pxa_console_write(struct console *co, const char *s, unsigned int count)
-{
-	struct uart_pxa_port *up = serial_pxa_ports[co->index];
-	unsigned int ier;
-	unsigned long flags;
-	int locked = 1;
-
-	clk_enable(up->clk);
-	local_irq_save(flags);
-	if (up->port.sysrq)
-		locked = 0;
-	else if (oops_in_progress)
-		locked = spin_trylock(&up->port.lock);
-	else
-		spin_lock(&up->port.lock);
-
-	/*
-	 *	First save the IER then disable the interrupts
-	 */
-	ier = serial_in(up, UART_IER);
-	serial_out(up, UART_IER, UART_IER_UUE);
-
-	uart_console_write(&up->port, s, count, serial_pxa_console_putchar);
-
-	/*
-	 *	Finally, wait for transmitter to become empty
-	 *	and restore the IER
-	 */
-	wait_for_xmitr(up);
-	serial_out(up, UART_IER, ier);
-
-	if (locked)
-		spin_unlock(&up->port.lock);
-	local_irq_restore(flags);
-	clk_disable(up->clk);
-
-}
-
-#ifdef CONFIG_CONSOLE_POLL
-/*
- * Console polling routines for writing and reading from the uart while
- * in an interrupt or debug context.
- */
-
-static int serial_pxa_get_poll_char(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned char lsr = serial_in(up, UART_LSR);
-
-	while (!(lsr & UART_LSR_DR))
-		lsr = serial_in(up, UART_LSR);
-
-	return serial_in(up, UART_RX);
-}
-
-
-static void serial_pxa_put_poll_char(struct uart_port *port,
-			 unsigned char c)
-{
-	unsigned int ier;
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	/*
-	 *	First save the IER then disable the interrupts
-	 */
-	ier = serial_in(up, UART_IER);
-	serial_out(up, UART_IER, UART_IER_UUE);
-
-	wait_for_xmitr(up);
-	/*
-	 *	Send the character out.
-	 *	If a LF, also do CR...
-	 */
-	serial_out(up, UART_TX, c);
-	if (c == 10) {
-		wait_for_xmitr(up);
-		serial_out(up, UART_TX, 13);
-	}
-
-	/*
-	 *	Finally, wait for transmitter to become empty
-	 *	and restore the IER
-	 */
-	wait_for_xmitr(up);
-	serial_out(up, UART_IER, ier);
-}
-
-#endif /* CONFIG_CONSOLE_POLL */
-
-static int __init
-serial_pxa_console_setup(struct console *co, char *options)
-{
-	struct uart_pxa_port *up;
-	int baud = 9600;
-	int bits = 8;
-	int parity = 'n';
-	int flow = 'n';
-
-	if (co->index == -1 || co->index >= serial_pxa_reg.nr)
-		co->index = 0;
-	up = serial_pxa_ports[co->index];
-	if (!up)
-		return -ENODEV;
-
-	if (options)
-		uart_parse_options(options, &baud, &parity, &bits, &flow);
-
-	return uart_set_options(&up->port, co, baud, parity, bits, flow);
-}
-
-static struct console serial_pxa_console = {
-	.name		= "ttyS",
-	.write		= serial_pxa_console_write,
-	.device		= uart_console_device,
-	.setup		= serial_pxa_console_setup,
-	.flags		= CON_PRINTBUFFER,
-	.index		= -1,
-	.data		= &serial_pxa_reg,
-};
-
-#define PXA_CONSOLE	&serial_pxa_console
-#else
-#define PXA_CONSOLE	NULL
-#endif
-
-static struct uart_ops serial_pxa_pops = {
-	.tx_empty	= serial_pxa_tx_empty,
-	.set_mctrl	= serial_pxa_set_mctrl,
-	.get_mctrl	= serial_pxa_get_mctrl,
-	.stop_tx	= serial_pxa_stop_tx,
-	.start_tx	= serial_pxa_start_tx,
-	.stop_rx	= serial_pxa_stop_rx,
-	.enable_ms	= serial_pxa_enable_ms,
-	.break_ctl	= serial_pxa_break_ctl,
-	.startup	= serial_pxa_startup,
-	.shutdown	= serial_pxa_shutdown,
-	.set_termios	= serial_pxa_set_termios,
-	.pm		= serial_pxa_pm,
-	.type		= serial_pxa_type,
-	.release_port	= serial_pxa_release_port,
-	.request_port	= serial_pxa_request_port,
-	.config_port	= serial_pxa_config_port,
-	.verify_port	= serial_pxa_verify_port,
-#ifdef CONFIG_CONSOLE_POLL
-	.poll_get_char = serial_pxa_get_poll_char,
-	.poll_put_char = serial_pxa_put_poll_char,
-#endif
-};
-
-static struct uart_driver serial_pxa_reg = {
-	.owner		= THIS_MODULE,
-	.driver_name	= "PXA serial",
-	.dev_name	= "ttyS",
-	.major		= TTY_MAJOR,
-	.minor		= 64,
-	.nr		= 4,
-	.cons		= PXA_CONSOLE,
-};
-
-#ifdef CONFIG_PM
-static int serial_pxa_suspend(struct device *dev)
-{
-        struct uart_pxa_port *sport = dev_get_drvdata(dev);
-
-        if (sport)
-                uart_suspend_port(&serial_pxa_reg, &sport->port);
-
-        return 0;
-}
-
-static int serial_pxa_resume(struct device *dev)
-{
-        struct uart_pxa_port *sport = dev_get_drvdata(dev);
-
-        if (sport)
-                uart_resume_port(&serial_pxa_reg, &sport->port);
-
-        return 0;
-}
-
-static const struct dev_pm_ops serial_pxa_pm_ops = {
-	.suspend	= serial_pxa_suspend,
-	.resume		= serial_pxa_resume,
-};
-#endif
-
-static struct of_device_id serial_pxa_dt_ids[] = {
-	{ .compatible = "mrvl,pxa-uart", },
-	{ .compatible = "mrvl,mmp-uart", },
-	{}
-};
-MODULE_DEVICE_TABLE(of, serial_pxa_dt_ids);
-
-static int serial_pxa_probe_dt(struct platform_device *pdev,
-			       struct uart_pxa_port *sport)
-{
-	struct device_node *np = pdev->dev.of_node;
-	int ret;
-
-	if (!np)
-		return 1;
-
-	ret = of_alias_get_id(np, "serial");
-	if (ret < 0) {
-		dev_err(&pdev->dev, "failed to get alias id, errno %d\n", ret);
-		return ret;
-	}
-	sport->port.line = ret;
-	return 0;
-}
-
-static int serial_pxa_probe(struct platform_device *dev)
-{
-	struct uart_pxa_port *sport;
-	struct resource *mmres, *irqres;
-	int ret;
-
-	mmres = platform_get_resource(dev, IORESOURCE_MEM, 0);
-	irqres = platform_get_resource(dev, IORESOURCE_IRQ, 0);
-	if (!mmres || !irqres)
-		return -ENODEV;
-
-	sport = kzalloc(sizeof(struct uart_pxa_port), GFP_KERNEL);
-	if (!sport)
-		return -ENOMEM;
-
-	sport->clk = clk_get(&dev->dev, NULL);
-	if (IS_ERR(sport->clk)) {
-		ret = PTR_ERR(sport->clk);
-		goto err_free;
-	}
-
-	ret = clk_prepare(sport->clk);
-	if (ret) {
-		clk_put(sport->clk);
-		goto err_free;
-	}
-
-	sport->port.type = PORT_PXA;
-	sport->port.iotype = UPIO_MEM;
-	sport->port.mapbase = mmres->start;
-	sport->port.irq = irqres->start;
-	sport->port.fifosize = 64;
-	sport->port.ops = &serial_pxa_pops;
-	sport->port.dev = &dev->dev;
-	sport->port.flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF;
-	sport->port.uartclk = clk_get_rate(sport->clk);
-
-	ret = serial_pxa_probe_dt(dev, sport);
-	if (ret > 0)
-		sport->port.line = dev->id;
-	else if (ret < 0)
-		goto err_clk;
-	snprintf(sport->name, PXA_NAME_LEN - 1, "UART%d", sport->port.line + 1);
-
-	sport->port.membase = ioremap(mmres->start, resource_size(mmres));
-	if (!sport->port.membase) {
-		ret = -ENOMEM;
-		goto err_clk;
-	}
-
-	serial_pxa_ports[sport->port.line] = sport;
-
-	uart_add_one_port(&serial_pxa_reg, &sport->port);
-	platform_set_drvdata(dev, sport);
-
-	return 0;
-
- err_clk:
-	clk_unprepare(sport->clk);
-	clk_put(sport->clk);
- err_free:
-	kfree(sport);
-	return ret;
-}
-
-static int serial_pxa_remove(struct platform_device *dev)
-{
-	struct uart_pxa_port *sport = platform_get_drvdata(dev);
-
-	uart_remove_one_port(&serial_pxa_reg, &sport->port);
-
-	clk_unprepare(sport->clk);
-	clk_put(sport->clk);
-	kfree(sport);
-
-	return 0;
-}
-
-static struct platform_driver serial_pxa_driver = {
-        .probe          = serial_pxa_probe,
-        .remove         = serial_pxa_remove,
-
-	.driver		= {
-	        .name	= "pxa2xx-uart",
-		.owner	= THIS_MODULE,
-#ifdef CONFIG_PM
-		.pm	= &serial_pxa_pm_ops,
-#endif
-		.of_match_table = serial_pxa_dt_ids,
-	},
-};
-
-static int __init serial_pxa_init(void)
-{
-	int ret;
-
-	ret = uart_register_driver(&serial_pxa_reg);
-	if (ret != 0)
-		return ret;
-
-	ret = platform_driver_register(&serial_pxa_driver);
-	if (ret != 0)
-		uart_unregister_driver(&serial_pxa_reg);
-
-	return ret;
-}
-
-static void __exit serial_pxa_exit(void)
-{
-	platform_driver_unregister(&serial_pxa_driver);
-	uart_unregister_driver(&serial_pxa_reg);
-}
-
-module_init(serial_pxa_init);
-module_exit(serial_pxa_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:pxa2xx-uart");
-- 
1.8.4.3

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

* Re: [PATCH] serial: rewrite pxa2xx-uart to use 8250_core
@ 2013-12-06  0:02                       ` Greg Kroah-Hartman
  0 siblings, 0 replies; 700+ messages in thread
From: Greg Kroah-Hartman @ 2013-12-06  0:02 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: linux-kernel, Heikki Krogerus, Russell King, Jiri Slaby,
	Grant Likely, Rob Herring, Zhou Zhu, Andrew Morton,
	Haojian Zhuang, Ralf Baechle, John Crispin,
	moderated list:ARM PORT, open list:SERIAL DRIVERS,
	open list:OPEN FIRMWARE AND...

On Fri, Dec 06, 2013 at 03:28:37AM +0400, Sergei Ianovich wrote:
> pxa2xx-uart was a separate uart platform driver. It was declaring
> the same device names and numbers as 8250 driver. As a result,
> it was impossible to use 8250 driver on PXA SoCs.
> 
> Upon closer examination pxa2xx-uart turned out to be a clone of
> 8250_core driver.
> 
> Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
> CC: Heikki Krogerus <heikki.krogerus@linux.intel.com>
> CC: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

Wonderful!

Can someone else test this to verify it works for them on their platform
as well?

thanks,

greg k-h

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

* Re: [PATCH] serial: rewrite pxa2xx-uart to use 8250_core
@ 2013-12-06  0:02                       ` Greg Kroah-Hartman
  0 siblings, 0 replies; 700+ messages in thread
From: Greg Kroah-Hartman @ 2013-12-06  0:02 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA, Heikki Krogerus,
	Russell King, Jiri Slaby, Grant Likely, Rob Herring, Zhou Zhu,
	Andrew Morton, Haojian Zhuang, Ralf Baechle, John Crispin,
	moderated list:ARM PORT, open list:SERIAL DRIVERS,
	open list:OPEN FIRMWARE AND...

On Fri, Dec 06, 2013 at 03:28:37AM +0400, Sergei Ianovich wrote:
> pxa2xx-uart was a separate uart platform driver. It was declaring
> the same device names and numbers as 8250 driver. As a result,
> it was impossible to use 8250 driver on PXA SoCs.
> 
> Upon closer examination pxa2xx-uart turned out to be a clone of
> 8250_core driver.
> 
> Signed-off-by: Sergei Ianovich <ynvich-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> CC: Heikki Krogerus <heikki.krogerus-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
> CC: Greg Kroah-Hartman <gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r@public.gmane.org>

Wonderful!

Can someone else test this to verify it works for them on their platform
as well?

thanks,

greg k-h
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH] serial: rewrite pxa2xx-uart to use 8250_core
@ 2013-12-06  0:02                       ` Greg Kroah-Hartman
  0 siblings, 0 replies; 700+ messages in thread
From: Greg Kroah-Hartman @ 2013-12-06  0:02 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Dec 06, 2013 at 03:28:37AM +0400, Sergei Ianovich wrote:
> pxa2xx-uart was a separate uart platform driver. It was declaring
> the same device names and numbers as 8250 driver. As a result,
> it was impossible to use 8250 driver on PXA SoCs.
> 
> Upon closer examination pxa2xx-uart turned out to be a clone of
> 8250_core driver.
> 
> Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
> CC: Heikki Krogerus <heikki.krogerus@linux.intel.com>
> CC: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

Wonderful!

Can someone else test this to verify it works for them on their platform
as well?

thanks,

greg k-h

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

* Re: [PATCH] serial: rewrite pxa2xx-uart to use 8250_core
@ 2013-12-06  0:17                         ` Russell King - ARM Linux
  0 siblings, 0 replies; 700+ messages in thread
From: Russell King - ARM Linux @ 2013-12-06  0:17 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: Sergei Ianovich, linux-kernel, Heikki Krogerus, Jiri Slaby,
	Grant Likely, Rob Herring, Zhou Zhu, Andrew Morton,
	Haojian Zhuang, Ralf Baechle, John Crispin,
	moderated list:ARM PORT, open list:SERIAL DRIVERS,
	open list:OPEN FIRMWARE AND...

On Thu, Dec 05, 2013 at 04:02:53PM -0800, Greg Kroah-Hartman wrote:
> On Fri, Dec 06, 2013 at 03:28:37AM +0400, Sergei Ianovich wrote:
> > pxa2xx-uart was a separate uart platform driver. It was declaring
> > the same device names and numbers as 8250 driver. As a result,
> > it was impossible to use 8250 driver on PXA SoCs.
> > 
> > Upon closer examination pxa2xx-uart turned out to be a clone of
> > 8250_core driver.
> > 
> > Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
> > CC: Heikki Krogerus <heikki.krogerus@linux.intel.com>
> > CC: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> 
> Wonderful!
> 
> Can someone else test this to verify it works for them on their platform
> as well?

I may be able to - one of the downsides though is that many of these
systems had hard-coded scripts which started a getty on the original
port - and that kind of makes it difficult to sort out.  This kind of
change becomes very much one of Linus' "flag days".

So I'd suggest that we have a period where the old driver is still
available, so at least people can choose to use the old major/minor
numbers for a while.

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

* Re: [PATCH] serial: rewrite pxa2xx-uart to use 8250_core
@ 2013-12-06  0:17                         ` Russell King - ARM Linux
  0 siblings, 0 replies; 700+ messages in thread
From: Russell King - ARM Linux @ 2013-12-06  0:17 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: Sergei Ianovich, linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	Heikki Krogerus, Jiri Slaby, Grant Likely, Rob Herring, Zhou Zhu,
	Andrew Morton, Haojian Zhuang, Ralf Baechle, John Crispin,
	moderated list:ARM PORT, open list:SERIAL DRIVERS,
	open list:OPEN FIRMWARE AND...

On Thu, Dec 05, 2013 at 04:02:53PM -0800, Greg Kroah-Hartman wrote:
> On Fri, Dec 06, 2013 at 03:28:37AM +0400, Sergei Ianovich wrote:
> > pxa2xx-uart was a separate uart platform driver. It was declaring
> > the same device names and numbers as 8250 driver. As a result,
> > it was impossible to use 8250 driver on PXA SoCs.
> > 
> > Upon closer examination pxa2xx-uart turned out to be a clone of
> > 8250_core driver.
> > 
> > Signed-off-by: Sergei Ianovich <ynvich-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> > CC: Heikki Krogerus <heikki.krogerus-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
> > CC: Greg Kroah-Hartman <gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r@public.gmane.org>
> 
> Wonderful!
> 
> Can someone else test this to verify it works for them on their platform
> as well?

I may be able to - one of the downsides though is that many of these
systems had hard-coded scripts which started a getty on the original
port - and that kind of makes it difficult to sort out.  This kind of
change becomes very much one of Linus' "flag days".

So I'd suggest that we have a period where the old driver is still
available, so at least people can choose to use the old major/minor
numbers for a while.
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH] serial: rewrite pxa2xx-uart to use 8250_core
@ 2013-12-06  0:17                         ` Russell King - ARM Linux
  0 siblings, 0 replies; 700+ messages in thread
From: Russell King - ARM Linux @ 2013-12-06  0:17 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Dec 05, 2013 at 04:02:53PM -0800, Greg Kroah-Hartman wrote:
> On Fri, Dec 06, 2013 at 03:28:37AM +0400, Sergei Ianovich wrote:
> > pxa2xx-uart was a separate uart platform driver. It was declaring
> > the same device names and numbers as 8250 driver. As a result,
> > it was impossible to use 8250 driver on PXA SoCs.
> > 
> > Upon closer examination pxa2xx-uart turned out to be a clone of
> > 8250_core driver.
> > 
> > Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
> > CC: Heikki Krogerus <heikki.krogerus@linux.intel.com>
> > CC: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> 
> Wonderful!
> 
> Can someone else test this to verify it works for them on their platform
> as well?

I may be able to - one of the downsides though is that many of these
systems had hard-coded scripts which started a getty on the original
port - and that kind of makes it difficult to sort out.  This kind of
change becomes very much one of Linus' "flag days".

So I'd suggest that we have a period where the old driver is still
available, so at least people can choose to use the old major/minor
numbers for a while.

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

* Re: [PATCH] serial: rewrite pxa2xx-uart to use 8250_core
  2013-12-05 23:28                     ` Sergei Ianovich
  (?)
@ 2013-12-06  0:38                       ` James Cameron
  -1 siblings, 0 replies; 700+ messages in thread
From: James Cameron @ 2013-12-06  0:38 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: linux-kernel, open list:OPEN FIRMWARE AND...,
	Heikki Krogerus, Russell King, Greg Kroah-Hartman, Ralf Baechle,
	Rob Herring, Haojian Zhuang, open list:SERIAL DRIVERS,
	Grant Likely, Andrew Morton, John Crispin, Jiri Slaby,
	moderated list:ARM PORT, Zhou Zhu

On Fri, Dec 06, 2013 at 03:28:37AM +0400, Sergei Ianovich wrote:
> pxa2xx-uart was a separate uart platform driver. It was declaring
> the same device names and numbers as 8250 driver. As a result,
> it was impossible to use 8250 driver on PXA SoCs.
> 
> Upon closer examination pxa2xx-uart turned out to be a clone of
> 8250_core driver.

I'm testing this backported to 3.5 on the OLPC XO-4 [1] [2].

As Russell says, the getty had to change, but after that the shell
worked fine; no more or no less responsive.

What hasn't worked yet is the console; no kernel messages appear.  I
have tried changing command line to console=ttyS0,115200.

1.  http://dev.laptop.org/~quozl/y/1VojGn.txt (diff relative to
olpc-kernel/arm-3.5)

2.  http://dev.laptop.org/~quozl/z/1VojLz.txt (dmesg)

-- 
James Cameron
http://quozl.linux.org.au/

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

* Re: [PATCH] serial: rewrite pxa2xx-uart to use 8250_core
@ 2013-12-06  0:38                       ` James Cameron
  0 siblings, 0 replies; 700+ messages in thread
From: James Cameron @ 2013-12-06  0:38 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: open list:OPEN FIRMWARE AND...,
	Heikki Krogerus, Russell King, Greg Kroah-Hartman, linux-kernel,
	Ralf Baechle, Haojian Zhuang, Rob Herring,
	open list:SERIAL DRIVERS, Grant Likely, Andrew Morton, Zhou Zhu,
	Jiri Slaby, moderated list:ARM PORT, John Crispin

On Fri, Dec 06, 2013 at 03:28:37AM +0400, Sergei Ianovich wrote:
> pxa2xx-uart was a separate uart platform driver. It was declaring
> the same device names and numbers as 8250 driver. As a result,
> it was impossible to use 8250 driver on PXA SoCs.
> 
> Upon closer examination pxa2xx-uart turned out to be a clone of
> 8250_core driver.

I'm testing this backported to 3.5 on the OLPC XO-4 [1] [2].

As Russell says, the getty had to change, but after that the shell
worked fine; no more or no less responsive.

What hasn't worked yet is the console; no kernel messages appear.  I
have tried changing command line to console=ttyS0,115200.

1.  http://dev.laptop.org/~quozl/y/1VojGn.txt (diff relative to
olpc-kernel/arm-3.5)

2.  http://dev.laptop.org/~quozl/z/1VojLz.txt (dmesg)

-- 
James Cameron
http://quozl.linux.org.au/

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

* [PATCH] serial: rewrite pxa2xx-uart to use 8250_core
@ 2013-12-06  0:38                       ` James Cameron
  0 siblings, 0 replies; 700+ messages in thread
From: James Cameron @ 2013-12-06  0:38 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Dec 06, 2013 at 03:28:37AM +0400, Sergei Ianovich wrote:
> pxa2xx-uart was a separate uart platform driver. It was declaring
> the same device names and numbers as 8250 driver. As a result,
> it was impossible to use 8250 driver on PXA SoCs.
> 
> Upon closer examination pxa2xx-uart turned out to be a clone of
> 8250_core driver.

I'm testing this backported to 3.5 on the OLPC XO-4 [1] [2].

As Russell says, the getty had to change, but after that the shell
worked fine; no more or no less responsive.

What hasn't worked yet is the console; no kernel messages appear.  I
have tried changing command line to console=ttyS0,115200.

1.  http://dev.laptop.org/~quozl/y/1VojGn.txt (diff relative to
olpc-kernel/arm-3.5)

2.  http://dev.laptop.org/~quozl/z/1VojLz.txt (dmesg)

-- 
James Cameron
http://quozl.linux.org.au/

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

* Re: [PATCH 02/11] arm: pxa27x: support ICP DAS LP-8x4x
  2013-12-01  6:26   ` Sergei Ianovich
@ 2013-12-06  0:40     ` Arnd Bergmann
  -1 siblings, 0 replies; 700+ messages in thread
From: Arnd Bergmann @ 2013-12-06  0:40 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Sergei Ianovich, linux-kernel, Eric Miao, Russell King, Haojian Zhuang

On Sunday 01 December 2013, Sergei Ianovich wrote:
> 
> diff --git a/arch/arm/configs/lp8x4x_defconfig b/arch/arm/configs/lp8x4x_defconfig
> new file mode 100644
> index 0000000..5cd6d38
> --- /dev/null
> +++ b/arch/arm/configs/lp8x4x_defconfig
> @@ -0,0 +1,2320 @@
> +#
> +# Automatically generated file; DO NOT EDIT.
> +# Linux/arm 3.13.0-rc1 Kernel Configuration
> +#

Please use 'make savedefconfig' to generate a smaller version of this file.

Ideally we want shared defconfigs where you enable multiple (or all) pxa boards
at once and end up with a kernel that works on all of them.

For most other platforms the goal is even to have a shared defconfig across
SoC families, but PXA is one of the exceptions that I would make because
it is both old and rather different from even the ARM9 or Marvell Feroceon
based SoCs.

> +#define LP8X4X_FPGA_PHYS	0x17000000
> +#define LP8X4X_FPGA_VIRT	0xf1000000
> +#define LP8X4X_P2V(x)		IOMEM((x) - LP8X4X_FPGA_PHYS + LP8X4X_FPGA_VIRT)
> +#define LP8X4X_V2P(x)		((x) - LP8X4X_FPGA_VIRT + LP8X4X_FPGA_PHYS)

I would recommend defining LP8X4X_FPGA_VIRT as "(void *)0xf1000000". Ideally
we try to avoid hardwired virtual addresses entirely and instead use platform
device resources, but I realize that there are limits to how far you get with
that. Please make an effort to convert as many parts of the FPGA into platform
devices with regular resources, but know that we would not enforce this as
strictly as we do for new platforms.

> +
> +static struct irq_chip lp8x4x_irq_chip = {
> +	.name			= "FPGA",
> +	.irq_ack		= lp8x4x_ack_irq,
> +	.irq_mask		= lp8x4x_mask_irq,
> +	.irq_unmask		= lp8x4x_unmask_irq,
> +};

Please try to move the irqchip code to drivers/irqchip/.

> +static struct platform_device lp8x4x_flash_device[] = {

static platform_device definitions are no longer the way to do this. For
modern platforms, you'd use a device tree, but here I think it is acceptable
(because of the PXA exception) to use a hardcoded board file.

The correct way to create the devices is using platform_device_register_data()
or a related function that returns a dynamically allocated platform device.

	Arnd

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

* [PATCH 02/11] arm: pxa27x: support ICP DAS LP-8x4x
@ 2013-12-06  0:40     ` Arnd Bergmann
  0 siblings, 0 replies; 700+ messages in thread
From: Arnd Bergmann @ 2013-12-06  0:40 UTC (permalink / raw)
  To: linux-arm-kernel

On Sunday 01 December 2013, Sergei Ianovich wrote:
> 
> diff --git a/arch/arm/configs/lp8x4x_defconfig b/arch/arm/configs/lp8x4x_defconfig
> new file mode 100644
> index 0000000..5cd6d38
> --- /dev/null
> +++ b/arch/arm/configs/lp8x4x_defconfig
> @@ -0,0 +1,2320 @@
> +#
> +# Automatically generated file; DO NOT EDIT.
> +# Linux/arm 3.13.0-rc1 Kernel Configuration
> +#

Please use 'make savedefconfig' to generate a smaller version of this file.

Ideally we want shared defconfigs where you enable multiple (or all) pxa boards
at once and end up with a kernel that works on all of them.

For most other platforms the goal is even to have a shared defconfig across
SoC families, but PXA is one of the exceptions that I would make because
it is both old and rather different from even the ARM9 or Marvell Feroceon
based SoCs.

> +#define LP8X4X_FPGA_PHYS	0x17000000
> +#define LP8X4X_FPGA_VIRT	0xf1000000
> +#define LP8X4X_P2V(x)		IOMEM((x) - LP8X4X_FPGA_PHYS + LP8X4X_FPGA_VIRT)
> +#define LP8X4X_V2P(x)		((x) - LP8X4X_FPGA_VIRT + LP8X4X_FPGA_PHYS)

I would recommend defining LP8X4X_FPGA_VIRT as "(void *)0xf1000000". Ideally
we try to avoid hardwired virtual addresses entirely and instead use platform
device resources, but I realize that there are limits to how far you get with
that. Please make an effort to convert as many parts of the FPGA into platform
devices with regular resources, but know that we would not enforce this as
strictly as we do for new platforms.

> +
> +static struct irq_chip lp8x4x_irq_chip = {
> +	.name			= "FPGA",
> +	.irq_ack		= lp8x4x_ack_irq,
> +	.irq_mask		= lp8x4x_mask_irq,
> +	.irq_unmask		= lp8x4x_unmask_irq,
> +};

Please try to move the irqchip code to drivers/irqchip/.

> +static struct platform_device lp8x4x_flash_device[] = {

static platform_device definitions are no longer the way to do this. For
modern platforms, you'd use a device tree, but here I think it is acceptable
(because of the PXA exception) to use a hardcoded board file.

The correct way to create the devices is using platform_device_register_data()
or a related function that returns a dynamically allocated platform device.

	Arnd

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

* Re: [PATCH] serial: rewrite pxa2xx-uart to use 8250_core
  2013-12-05 23:28                     ` Sergei Ianovich
@ 2013-12-06  2:42                       ` James Cameron
  -1 siblings, 0 replies; 700+ messages in thread
From: James Cameron @ 2013-12-06  2:42 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: linux-kernel, open list:OPEN FIRMWARE AND...,
	Heikki Krogerus, Russell King, Greg Kroah-Hartman, Ralf Baechle,
	Rob Herring, Haojian Zhuang, open list:SERIAL DRIVERS,
	Grant Likely, Andrew Morton, John Crispin, Jiri Slaby,
	moderated list:ARM PORT, Zhou Zhu

On Fri, Dec 06, 2013 at 03:28:37AM +0400, Sergei Ianovich wrote:
> pxa2xx-uart was a separate uart platform driver. It was declaring
> the same device names and numbers as 8250 driver. As a result,
> it was impossible to use 8250 driver on PXA SoCs.
> 
> Upon closer examination pxa2xx-uart turned out to be a clone of
> 8250_core driver.

[...]

> +/* Uart divisor latch write */
> +static void serial_pxa_dl_write(struct uart_8250_port *up, int value)
> +{
> +	serial_out(up, UART_DLL, value & 0xff);
> +	serial_out(up, UART_DLM, value >> 8 & 0xff);
> +}

This is a change.  drivers/tty/serial/pxa.c did read back UART_DLL as
an errata work around:

> -	/*
> -	 * work around Errata #75 according to Intel(R) PXA27x Processor Family
> -	 * Specification Update (Nov 2005)
> -	 */
> -	dll = serial_in(up, UART_DLL);
> -	WARN_ON(dll != (quot & 0xff));

If this is no longer needed, serial_pxa_dl_write can be removed
because it is same as default_serial_dl_write.

I did not check the other errata work arounds.

--
James Cameron
http://quozl.linux.org.au/

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

* [PATCH] serial: rewrite pxa2xx-uart to use 8250_core
@ 2013-12-06  2:42                       ` James Cameron
  0 siblings, 0 replies; 700+ messages in thread
From: James Cameron @ 2013-12-06  2:42 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Dec 06, 2013 at 03:28:37AM +0400, Sergei Ianovich wrote:
> pxa2xx-uart was a separate uart platform driver. It was declaring
> the same device names and numbers as 8250 driver. As a result,
> it was impossible to use 8250 driver on PXA SoCs.
> 
> Upon closer examination pxa2xx-uart turned out to be a clone of
> 8250_core driver.

[...]

> +/* Uart divisor latch write */
> +static void serial_pxa_dl_write(struct uart_8250_port *up, int value)
> +{
> +	serial_out(up, UART_DLL, value & 0xff);
> +	serial_out(up, UART_DLM, value >> 8 & 0xff);
> +}

This is a change.  drivers/tty/serial/pxa.c did read back UART_DLL as
an errata work around:

> -	/*
> -	 * work around Errata #75 according to Intel(R) PXA27x Processor Family
> -	 * Specification Update (Nov 2005)
> -	 */
> -	dll = serial_in(up, UART_DLL);
> -	WARN_ON(dll != (quot & 0xff));

If this is no longer needed, serial_pxa_dl_write can be removed
because it is same as default_serial_dl_write.

I did not check the other errata work arounds.

--
James Cameron
http://quozl.linux.org.au/

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

* Re: [PATCH] serial: rewrite pxa2xx-uart to use 8250_core
  2013-12-06  0:38                       ` James Cameron
@ 2013-12-06  2:55                         ` James Cameron
  -1 siblings, 0 replies; 700+ messages in thread
From: James Cameron @ 2013-12-06  2:55 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: linux-kernel, open list:OPEN FIRMWARE AND...,
	Heikki Krogerus, Russell King, Greg Kroah-Hartman, Ralf Baechle,
	Rob Herring, Haojian Zhuang, open list:SERIAL DRIVERS,
	Grant Likely, Andrew Morton, John Crispin, Jiri Slaby,
	moderated list:ARM PORT, Zhou Zhu

On Fri, Dec 06, 2013 at 11:38:51AM +1100, James Cameron wrote:
> On Fri, Dec 06, 2013 at 03:28:37AM +0400, Sergei Ianovich wrote:
> > pxa2xx-uart was a separate uart platform driver. It was declaring
> > the same device names and numbers as 8250 driver. As a result,
> > it was impossible to use 8250 driver on PXA SoCs.
> > 
> > Upon closer examination pxa2xx-uart turned out to be a clone of
> > 8250_core driver.
> 
> I'm testing this backported to 3.5 on the OLPC XO-4 [1] [2].
> 
> As Russell says, the getty had to change, but after that the shell
> worked fine; no more or no less responsive.
> 
> What hasn't worked yet is the console; no kernel messages appear.  I
> have tried changing command line to console=ttyS0,115200.

My error.  Our kernel had CONFIG_CMDLINE set, changing that fixed it.
Console is working fine.

-- 
James Cameron
http://quozl.linux.org.au/

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

* [PATCH] serial: rewrite pxa2xx-uart to use 8250_core
@ 2013-12-06  2:55                         ` James Cameron
  0 siblings, 0 replies; 700+ messages in thread
From: James Cameron @ 2013-12-06  2:55 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Dec 06, 2013 at 11:38:51AM +1100, James Cameron wrote:
> On Fri, Dec 06, 2013 at 03:28:37AM +0400, Sergei Ianovich wrote:
> > pxa2xx-uart was a separate uart platform driver. It was declaring
> > the same device names and numbers as 8250 driver. As a result,
> > it was impossible to use 8250 driver on PXA SoCs.
> > 
> > Upon closer examination pxa2xx-uart turned out to be a clone of
> > 8250_core driver.
> 
> I'm testing this backported to 3.5 on the OLPC XO-4 [1] [2].
> 
> As Russell says, the getty had to change, but after that the shell
> worked fine; no more or no less responsive.
> 
> What hasn't worked yet is the console; no kernel messages appear.  I
> have tried changing command line to console=ttyS0,115200.

My error.  Our kernel had CONFIG_CMDLINE set, changing that fixed it.
Console is working fine.

-- 
James Cameron
http://quozl.linux.org.au/

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

* [PATCH v2] serial: rewrite pxa2xx-uart to use 8250_core
  2013-12-05 23:28                     ` Sergei Ianovich
  (?)
@ 2013-12-06  9:09                       ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-06  9:09 UTC (permalink / raw)
  To: linux-kernel
  Cc: Sergei Ianovich, Heikki Krogerus, Greg Kroah-Hartman,
	James Cameron, Russell King, Jiri Slaby, Grant Likely,
	Rob Herring, Zhou Zhu, Andrew Morton, Haojian Zhuang,
	Stefan Seyfried, John Crispin, Paul Bolle,
	moderated list:ARM PORT, open list:SERIAL DRIVERS,
	open list:OPEN FIRMWARE AND...

pxa2xx-uart was a separate uart platform driver. It was declaring
the same device names and numbers as 8250 driver. As a result,
it was impossible to use 8250 driver on PXA SoCs.

Upon closer examination pxa2xx-uart turned out to be a clone of
8250_core driver.

Workaround for Erratum #19 according to Marvel(R) PXA270M Processor
Specification Update (April 19, 2010) is dropped. 8250_core reads
from FIFO immediately after checking DR bit in LSR.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Heikki Krogerus <heikki.krogerus@linux.intel.com>
CC: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
CC: James Cameron <quozl@laptop.org>
---
 changes v1..v2
 * actually implement workaround for E74 in dl_write as spooted
   by James Cameron
 * added comment about E19 in commit message

 arch/arm/configs/am200epdkit_defconfig    |   3 +-
 arch/arm/configs/cm_x2xx_defconfig        |   3 +-
 arch/arm/configs/cm_x300_defconfig        |   3 +-
 arch/arm/configs/colibri_pxa270_defconfig |   3 +-
 arch/arm/configs/colibri_pxa300_defconfig |   3 +-
 arch/arm/configs/corgi_defconfig          |   4 +-
 arch/arm/configs/em_x270_defconfig        |   3 +-
 arch/arm/configs/ezx_defconfig            |   3 +-
 arch/arm/configs/h5000_defconfig          |   3 +-
 arch/arm/configs/imote2_defconfig         |   3 +-
 arch/arm/configs/lpd270_defconfig         |   3 +-
 arch/arm/configs/lubbock_defconfig        |   3 +-
 arch/arm/configs/mainstone_defconfig      |   3 +-
 arch/arm/configs/mmp2_defconfig           |   3 +-
 arch/arm/configs/pcm027_defconfig         |   3 +-
 arch/arm/configs/pxa168_defconfig         |   3 +-
 arch/arm/configs/pxa255-idp_defconfig     |   3 +-
 arch/arm/configs/pxa3xx_defconfig         |   3 +-
 arch/arm/configs/pxa910_defconfig         |   3 +-
 arch/arm/configs/raumfeld_defconfig       |   3 +-
 arch/arm/configs/spitz_defconfig          |   4 +-
 arch/arm/configs/trizeps4_defconfig       |   3 +-
 arch/arm/configs/viper_defconfig          |   4 +-
 arch/arm/configs/xcep_defconfig           |   3 +-
 drivers/tty/serial/8250/8250_pxa.c        | 189 ++++++
 drivers/tty/serial/8250/Kconfig           |   9 +
 drivers/tty/serial/8250/Makefile          |   1 +
 drivers/tty/serial/Kconfig                |  23 -
 drivers/tty/serial/Makefile               |   1 -
 drivers/tty/serial/pxa.c                  | 971 ------------------------------
 30 files changed, 247 insertions(+), 1022 deletions(-)
 create mode 100644 drivers/tty/serial/8250/8250_pxa.c
 delete mode 100644 drivers/tty/serial/pxa.c

diff --git a/arch/arm/configs/am200epdkit_defconfig b/arch/arm/configs/am200epdkit_defconfig
index f0dea52..0cde234 100644
--- a/arch/arm/configs/am200epdkit_defconfig
+++ b/arch/arm/configs/am200epdkit_defconfig
@@ -60,8 +60,9 @@ CONFIG_BLK_DEV_IDECS=m
 CONFIG_NETDEVICES=y
 CONFIG_NET_ETHERNET=y
 CONFIG_SMC91X=m
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 # CONFIG_HWMON is not set
diff --git a/arch/arm/configs/cm_x2xx_defconfig b/arch/arm/configs/cm_x2xx_defconfig
index a93ff8d..b9fbe65 100644
--- a/arch/arm/configs/cm_x2xx_defconfig
+++ b/arch/arm/configs/cm_x2xx_defconfig
@@ -96,8 +96,9 @@ CONFIG_KEYBOARD_PXA27x=m
 CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_TOUCHSCREEN_UCB1400=m
 # CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_LEGACY_PTY_COUNT=16
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/cm_x300_defconfig b/arch/arm/configs/cm_x300_defconfig
index f4b7672..53a82ae 100644
--- a/arch/arm/configs/cm_x300_defconfig
+++ b/arch/arm/configs/cm_x300_defconfig
@@ -80,8 +80,9 @@ CONFIG_TOUCHSCREEN_WM97XX=m
 # CONFIG_TOUCHSCREEN_WM9713 is not set
 # CONFIG_SERIO is not set
 # CONFIG_LEGACY_PTYS is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
 CONFIG_I2C_PXA=y
diff --git a/arch/arm/configs/colibri_pxa270_defconfig b/arch/arm/configs/colibri_pxa270_defconfig
index 2ef2c5e..1ce0409 100644
--- a/arch/arm/configs/colibri_pxa270_defconfig
+++ b/arch/arm/configs/colibri_pxa270_defconfig
@@ -103,8 +103,9 @@ CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=m
 CONFIG_SERIO_LIBPS2=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_HW_RANDOM=y
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
diff --git a/arch/arm/configs/colibri_pxa300_defconfig b/arch/arm/configs/colibri_pxa300_defconfig
index b985334..f96bda0 100644
--- a/arch/arm/configs/colibri_pxa300_defconfig
+++ b/arch/arm/configs/colibri_pxa300_defconfig
@@ -31,8 +31,9 @@ CONFIG_INPUT_EVDEV=y
 # CONFIG_INPUT_MOUSE is not set
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_GPIO_ROTARY_ENCODER=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_HW_RANDOM=y
 CONFIG_DEBUG_GPIO=y
 # CONFIG_HWMON is not set
diff --git a/arch/arm/configs/corgi_defconfig b/arch/arm/configs/corgi_defconfig
index 1fd1d1d..bb4842d 100644
--- a/arch/arm/configs/corgi_defconfig
+++ b/arch/arm/configs/corgi_defconfig
@@ -131,10 +131,10 @@ CONFIG_TOUCHSCREEN_ADS7846=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=m
 # CONFIG_SERIO is not set
-CONFIG_SERIAL_8250=m
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_CS=m
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 CONFIG_I2C=y
 CONFIG_I2C_PXA=y
diff --git a/arch/arm/configs/em_x270_defconfig b/arch/arm/configs/em_x270_defconfig
index 60a21e0..ec0ec54 100644
--- a/arch/arm/configs/em_x270_defconfig
+++ b/arch/arm/configs/em_x270_defconfig
@@ -90,8 +90,9 @@ CONFIG_TOUCHSCREEN_WM97XX=m
 # CONFIG_TOUCHSCREEN_WM9705 is not set
 # CONFIG_TOUCHSCREEN_WM9713 is not set
 # CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_LEGACY_PTY_COUNT=16
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/ezx_defconfig b/arch/arm/configs/ezx_defconfig
index d95763d..631e2ec 100644
--- a/arch/arm/configs/ezx_defconfig
+++ b/arch/arm/configs/ezx_defconfig
@@ -215,8 +215,9 @@ CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=y
 CONFIG_INPUT_PCAP=y
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_LEGACY_PTY_COUNT=8
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/h5000_defconfig b/arch/arm/configs/h5000_defconfig
index 37903e3..655b735 100644
--- a/arch/arm/configs/h5000_defconfig
+++ b/arch/arm/configs/h5000_defconfig
@@ -47,8 +47,9 @@ CONFIG_MTD_PHYSMAP=y
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_LEGACY_PTY_COUNT=32
 # CONFIG_HW_RANDOM is not set
 # CONFIG_HWMON is not set
diff --git a/arch/arm/configs/imote2_defconfig b/arch/arm/configs/imote2_defconfig
index fd996bb..49d45e9 100644
--- a/arch/arm/configs/imote2_defconfig
+++ b/arch/arm/configs/imote2_defconfig
@@ -193,8 +193,9 @@ CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=y
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_LEGACY_PTY_COUNT=8
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/lpd270_defconfig b/arch/arm/configs/lpd270_defconfig
index 1c8c9ee..c3927b6 100644
--- a/arch/arm/configs/lpd270_defconfig
+++ b/arch/arm/configs/lpd270_defconfig
@@ -38,8 +38,9 @@ CONFIG_SMC91X=y
 CONFIG_INPUT_EVDEV=y
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_HW_RANDOM is not set
 CONFIG_FB=y
 CONFIG_FB_PXA=y
diff --git a/arch/arm/configs/lubbock_defconfig b/arch/arm/configs/lubbock_defconfig
index c4ba274..c8b0436 100644
--- a/arch/arm/configs/lubbock_defconfig
+++ b/arch/arm/configs/lubbock_defconfig
@@ -37,8 +37,9 @@ CONFIG_PCMCIA_PCNET=y
 CONFIG_INPUT_EVDEV=y
 # CONFIG_SERIO_SERPORT is not set
 CONFIG_SERIO_SA1111=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_USB_GADGET=y
 CONFIG_USB_G_SERIAL=m
diff --git a/arch/arm/configs/mainstone_defconfig b/arch/arm/configs/mainstone_defconfig
index 04efa1b..768892c 100644
--- a/arch/arm/configs/mainstone_defconfig
+++ b/arch/arm/configs/mainstone_defconfig
@@ -34,8 +34,9 @@ CONFIG_SMC91X=y
 CONFIG_INPUT_EVDEV=y
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_FB=y
 CONFIG_FB_PXA=y
 # CONFIG_VGA_CONSOLE is not set
diff --git a/arch/arm/configs/mmp2_defconfig b/arch/arm/configs/mmp2_defconfig
index f1cb95e..1ced9df 100644
--- a/arch/arm/configs/mmp2_defconfig
+++ b/arch/arm/configs/mmp2_defconfig
@@ -44,8 +44,9 @@ CONFIG_SMC91X=y
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/pcm027_defconfig b/arch/arm/configs/pcm027_defconfig
index 2f136c3..1280128 100644
--- a/arch/arm/configs/pcm027_defconfig
+++ b/arch/arm/configs/pcm027_defconfig
@@ -60,8 +60,9 @@ CONFIG_SMC91X=y
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/pxa168_defconfig b/arch/arm/configs/pxa168_defconfig
index 74d7e01..1668dac 100644
--- a/arch/arm/configs/pxa168_defconfig
+++ b/arch/arm/configs/pxa168_defconfig
@@ -40,8 +40,9 @@ CONFIG_SMC91X=y
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 # CONFIG_HWMON is not set
diff --git a/arch/arm/configs/pxa255-idp_defconfig b/arch/arm/configs/pxa255-idp_defconfig
index 917a070..399a706 100644
--- a/arch/arm/configs/pxa255-idp_defconfig
+++ b/arch/arm/configs/pxa255-idp_defconfig
@@ -35,8 +35,9 @@ CONFIG_SMC91X=y
 CONFIG_INPUT_EVDEV=y
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_FB=y
 CONFIG_FB_PXA=y
 # CONFIG_VGA_CONSOLE is not set
diff --git a/arch/arm/configs/pxa3xx_defconfig b/arch/arm/configs/pxa3xx_defconfig
index 60e3138..7c3e052 100644
--- a/arch/arm/configs/pxa3xx_defconfig
+++ b/arch/arm/configs/pxa3xx_defconfig
@@ -56,8 +56,9 @@ CONFIG_KEYBOARD_PXA27x=y
 CONFIG_KEYBOARD_PXA930_ROTARY=y
 CONFIG_MOUSE_PXA930_TRKBALL=y
 CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/pxa910_defconfig b/arch/arm/configs/pxa910_defconfig
index 3bb7771..cdacfcb 100644
--- a/arch/arm/configs/pxa910_defconfig
+++ b/arch/arm/configs/pxa910_defconfig
@@ -40,8 +40,9 @@ CONFIG_SMC91X=y
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_SPI=y
 CONFIG_FB=y
 CONFIG_MMP_DISP=y
diff --git a/arch/arm/configs/raumfeld_defconfig b/arch/arm/configs/raumfeld_defconfig
index f7caa90..f1e16f2 100644
--- a/arch/arm/configs/raumfeld_defconfig
+++ b/arch/arm/configs/raumfeld_defconfig
@@ -67,8 +67,9 @@ CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_TOUCHSCREEN_EETI=m
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_GPIO_ROTARY_ENCODER=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_HW_RANDOM=y
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
diff --git a/arch/arm/configs/spitz_defconfig b/arch/arm/configs/spitz_defconfig
index 2e0419d..b6efcf5 100644
--- a/arch/arm/configs/spitz_defconfig
+++ b/arch/arm/configs/spitz_defconfig
@@ -128,10 +128,10 @@ CONFIG_TOUCHSCREEN_ADS7846=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=m
 # CONFIG_SERIO is not set
-CONFIG_SERIAL_8250=m
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_CS=m
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 CONFIG_SPI=y
 CONFIG_SPI_PXA2XX=y
diff --git a/arch/arm/configs/trizeps4_defconfig b/arch/arm/configs/trizeps4_defconfig
index 3162173..453c79c 100644
--- a/arch/arm/configs/trizeps4_defconfig
+++ b/arch/arm/configs/trizeps4_defconfig
@@ -132,8 +132,9 @@ CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=m
 CONFIG_SERIO_LIBPS2=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_HW_RANDOM=y
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
diff --git a/arch/arm/configs/viper_defconfig b/arch/arm/configs/viper_defconfig
index d36e0d3..4efac06 100644
--- a/arch/arm/configs/viper_defconfig
+++ b/arch/arm/configs/viper_defconfig
@@ -101,11 +101,11 @@ CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=m
 # CONFIG_CONSOLE_TRANSLATIONS is not set
 # CONFIG_VT_CONSOLE is not set
-CONFIG_SERIAL_8250=m
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_NR_UARTS=5
 CONFIG_SERIAL_8250_RUNTIME_UARTS=5
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
diff --git a/arch/arm/configs/xcep_defconfig b/arch/arm/configs/xcep_defconfig
index 721832f..b67aeaf 100644
--- a/arch/arm/configs/xcep_defconfig
+++ b/arch/arm/configs/xcep_defconfig
@@ -60,8 +60,9 @@ CONFIG_NET_ETHERNET=y
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
 # CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=m
diff --git a/drivers/tty/serial/8250/8250_pxa.c b/drivers/tty/serial/8250/8250_pxa.c
new file mode 100644
index 0000000..88ae73c
--- /dev/null
+++ b/drivers/tty/serial/8250/8250_pxa.c
@@ -0,0 +1,189 @@
+/*
+ *  drivers/tty/serial/8250/8250_pxa.c -- driver for PXA on-board UARTS
+ *  Copyright:	(C) 2013 Sergei Ianovich <ynvich@gmail.com>
+ *
+ *  replaces drivers/serial/pxa.c by Nicolas Pitre
+ *  Created:	Feb 20, 2003
+ *  Copyright:	(C) 2003 Monta Vista Software, Inc.
+ *
+ *  Based on drivers/serial/8250.c by Russell King.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/serial_8250.h>
+#include <linux/serial_core.h>
+#include <linux/serial_reg.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
+#include <linux/pm_runtime.h>
+
+#include "8250.h"
+
+struct pxa8250_data {
+	int			line;
+	struct clk		*clk;
+};
+
+#ifdef CONFIG_PM
+static int serial_pxa_suspend(struct device *dev)
+{
+	struct pxa8250_data *data = dev_get_drvdata(dev);
+
+	serial8250_suspend_port(data->line);
+
+	return 0;
+}
+
+static int serial_pxa_resume(struct device *dev)
+{
+	struct pxa8250_data *data = dev_get_drvdata(dev);
+
+	serial8250_resume_port(data->line);
+
+	return 0;
+}
+
+static const struct dev_pm_ops serial_pxa_pm_ops = {
+	.suspend	= serial_pxa_suspend,
+	.resume		= serial_pxa_resume,
+};
+#endif
+
+static struct of_device_id serial_pxa_dt_ids[] = {
+	{ .compatible = "mrvl,pxa-uart", },
+	{ .compatible = "mrvl,mmp-uart", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, serial_pxa_dt_ids);
+
+/* Uart divisor latch write */
+static void serial_pxa_dl_write(struct uart_8250_port *up, int value)
+{
+	unsigned int dll;
+
+	serial_out(up, UART_DLL, value & 0xff);
+	/*
+	 * work around Erratum #74 according to Marvel(R) PXA270M Processor
+	 * Specification Update (April 19, 2010)
+	 */
+	dll = serial_in(up, UART_DLL);
+	WARN_ON(dll != (value & 0xff));
+
+	serial_out(up, UART_DLM, value >> 8 & 0xff);
+}
+
+
+static void serial_pxa_pm(struct uart_port *port, unsigned int state,
+	      unsigned int oldstate)
+{
+	struct pxa8250_data *data = port->private_data;
+
+	if (!state)
+		clk_prepare_enable(data->clk);
+	else
+		clk_disable_unprepare(data->clk);
+}
+
+static int serial_pxa_probe(struct platform_device *pdev)
+{
+	struct uart_8250_port uart = {};
+	struct pxa8250_data *data;
+	struct resource *mmres, *irqres;
+	int ret;
+
+	mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	irqres = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!mmres || !irqres)
+		return -ENODEV;
+
+	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(data->clk)) {
+		ret = PTR_ERR(data->clk);
+		goto err_free;
+	}
+
+	ret = clk_prepare(data->clk);
+	if (ret)
+		goto err_free_clk;
+
+	uart.port.type = PORT_XSCALE;
+	uart.port.iotype = UPIO_MEM32;
+	uart.port.mapbase = mmres->start;
+	uart.port.regshift = 2;
+	uart.port.irq = irqres->start;
+	uart.port.fifosize = 64;
+	uart.port.flags = UPF_IOREMAP | UPF_SKIP_TEST;
+	uart.port.dev = &pdev->dev;
+	uart.port.uartclk = clk_get_rate(data->clk);
+	uart.port.pm = serial_pxa_pm;
+	uart.port.private_data = data;
+	uart.dl_write = serial_pxa_dl_write;
+
+	ret = serial8250_register_8250_port(&uart);
+	if (ret < 0)
+		goto err_clk;
+
+	data->line = ret;
+
+	platform_set_drvdata(pdev, data);
+
+	return 0;
+
+ err_clk:
+	clk_unprepare(data->clk);
+ err_free_clk:
+	devm_clk_put(&pdev->dev, data->clk);
+ err_free:
+	devm_kfree(&pdev->dev, data);
+	return ret;
+}
+
+static int serial_pxa_remove(struct platform_device *pdev)
+{
+	struct pxa8250_data *data = platform_get_drvdata(pdev);
+
+	serial8250_unregister_port(data->line);
+
+	clk_unprepare(data->clk);
+	devm_clk_put(&pdev->dev, data->clk);
+	devm_kfree(&pdev->dev, data);
+
+	return 0;
+}
+
+static struct platform_driver serial_pxa_driver = {
+	.probe          = serial_pxa_probe,
+	.remove         = serial_pxa_remove,
+
+	.driver		= {
+		.name	= "pxa2xx-uart",
+		.owner	= THIS_MODULE,
+#ifdef CONFIG_PM
+		.pm	= &serial_pxa_pm_ops,
+#endif
+		.of_match_table = serial_pxa_dt_ids,
+	},
+};
+
+module_platform_driver(serial_pxa_driver);
+
+MODULE_AUTHOR("Sergei Ianovich");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:pxa2xx-uart");
diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
index 2332991..81bd7c9 100644
--- a/drivers/tty/serial/8250/Kconfig
+++ b/drivers/tty/serial/8250/Kconfig
@@ -302,3 +302,12 @@ config SERIAL_8250_RT288X
 	  If you have a Ralink RT288x/RT305x SoC based board and want to use the
 	  serial port, say Y to this option. The driver can handle up to 2 serial
 	  ports. If unsure, say N.
+
+config SERIAL_PXA
+	tristate "PXA serial port support"
+	depends on SERIAL_8250 && (ARCH_PXA || ARCH_MMP)
+	help
+	  If you have a machine based on an Intel XScale PXA2xx CPU you
+	  can enable its onboard serial ports by enabling this option.
+
+	  If you choose M here, the module name will be 8250_pxa.
diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile
index 36d68d0..b7d1b61 100644
--- a/drivers/tty/serial/8250/Makefile
+++ b/drivers/tty/serial/8250/Makefile
@@ -20,3 +20,4 @@ obj-$(CONFIG_SERIAL_8250_HUB6)		+= 8250_hub6.o
 obj-$(CONFIG_SERIAL_8250_FSL)		+= 8250_fsl.o
 obj-$(CONFIG_SERIAL_8250_DW)		+= 8250_dw.o
 obj-$(CONFIG_SERIAL_8250_EM)		+= 8250_em.o
+obj-$(CONFIG_SERIAL_PXA)		+= 8250_pxa.o
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index a3817ab..2ad7184b 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -396,29 +396,6 @@ config SERIAL_MPSC_CONSOLE
 	help
 	  Say Y here if you want to support a serial console on a Marvell MPSC.
 
-config SERIAL_PXA
-	bool "PXA serial port support"
-	depends on ARCH_PXA || ARCH_MMP
-	select SERIAL_CORE
-	help
-	  If you have a machine based on an Intel XScale PXA2xx CPU you
-	  can enable its onboard serial ports by enabling this option.
-
-config SERIAL_PXA_CONSOLE
-	bool "Console on PXA serial port"
-	depends on SERIAL_PXA
-	select SERIAL_CORE_CONSOLE
-	help
-	  If you have enabled the serial port on the Intel XScale PXA
-	  CPU you can make it the console by answering Y to this option.
-
-	  Even if you say Y here, the currently visible virtual console
-	  (/dev/tty0) will still be used as the system console by default, but
-	  you can alter that using a kernel command line option such as
-	  "console=ttySA0". (Try "man bootparam" or see the documentation of
-	  your boot loader (lilo or loadlin) about how to pass options to the
-	  kernel at boot time.)
-
 config SERIAL_SA1100
 	bool "SA1100 serial port support"
 	depends on ARCH_SA1100
diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile
index 3068c77..4ac337b 100644
--- a/drivers/tty/serial/Makefile
+++ b/drivers/tty/serial/Makefile
@@ -20,7 +20,6 @@ obj-$(CONFIG_SERIAL_8250) += 8250/
 obj-$(CONFIG_SERIAL_AMBA_PL010) += amba-pl010.o
 obj-$(CONFIG_SERIAL_AMBA_PL011) += amba-pl011.o
 obj-$(CONFIG_SERIAL_CLPS711X) += clps711x.o
-obj-$(CONFIG_SERIAL_PXA) += pxa.o
 obj-$(CONFIG_SERIAL_PNX8XXX) += pnx8xxx_uart.o
 obj-$(CONFIG_SERIAL_SA1100) += sa1100.o
 obj-$(CONFIG_SERIAL_BCM63XX) += bcm63xx_uart.o
diff --git a/drivers/tty/serial/pxa.c b/drivers/tty/serial/pxa.c
deleted file mode 100644
index f9f20f3..0000000
--- a/drivers/tty/serial/pxa.c
+++ /dev/null
@@ -1,971 +0,0 @@
-/*
- *  Based on drivers/serial/8250.c by Russell King.
- *
- *  Author:	Nicolas Pitre
- *  Created:	Feb 20, 2003
- *  Copyright:	(C) 2003 Monta Vista Software, Inc.
- *
- * 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.
- *
- * Note 1: This driver is made separate from the already too overloaded
- * 8250.c because it needs some kirks of its own and that'll make it
- * easier to add DMA support.
- *
- * Note 2: I'm too sick of device allocation policies for serial ports.
- * If someone else wants to request an "official" allocation of major/minor
- * for this driver please be my guest.  And don't forget that new hardware
- * to come from Intel might have more than 3 or 4 of those UARTs.  Let's
- * hope for a better port registration and dynamic device allocation scheme
- * with the serial core maintainer satisfaction to appear soon.
- */
-
-
-#if defined(CONFIG_SERIAL_PXA_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-#define SUPPORT_SYSRQ
-#endif
-
-#include <linux/module.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-#include <linux/console.h>
-#include <linux/sysrq.h>
-#include <linux/serial_reg.h>
-#include <linux/circ_buf.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/of.h>
-#include <linux/platform_device.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/serial_core.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-
-#define PXA_NAME_LEN		8
-
-struct uart_pxa_port {
-	struct uart_port        port;
-	unsigned char           ier;
-	unsigned char           lcr;
-	unsigned char           mcr;
-	unsigned int            lsr_break_flag;
-	struct clk		*clk;
-	char			name[PXA_NAME_LEN];
-};
-
-static inline unsigned int serial_in(struct uart_pxa_port *up, int offset)
-{
-	offset <<= 2;
-	return readl(up->port.membase + offset);
-}
-
-static inline void serial_out(struct uart_pxa_port *up, int offset, int value)
-{
-	offset <<= 2;
-	writel(value, up->port.membase + offset);
-}
-
-static void serial_pxa_enable_ms(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	up->ier |= UART_IER_MSI;
-	serial_out(up, UART_IER, up->ier);
-}
-
-static void serial_pxa_stop_tx(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	if (up->ier & UART_IER_THRI) {
-		up->ier &= ~UART_IER_THRI;
-		serial_out(up, UART_IER, up->ier);
-	}
-}
-
-static void serial_pxa_stop_rx(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	up->ier &= ~UART_IER_RLSI;
-	up->port.read_status_mask &= ~UART_LSR_DR;
-	serial_out(up, UART_IER, up->ier);
-}
-
-static inline void receive_chars(struct uart_pxa_port *up, int *status)
-{
-	unsigned int ch, flag;
-	int max_count = 256;
-
-	do {
-		/* work around Errata #20 according to
-		 * Intel(R) PXA27x Processor Family
-		 * Specification Update (May 2005)
-		 *
-		 * Step 2
-		 * Disable the Reciever Time Out Interrupt via IER[RTOEI]
-		 */
-		up->ier &= ~UART_IER_RTOIE;
-		serial_out(up, UART_IER, up->ier);
-
-		ch = serial_in(up, UART_RX);
-		flag = TTY_NORMAL;
-		up->port.icount.rx++;
-
-		if (unlikely(*status & (UART_LSR_BI | UART_LSR_PE |
-				       UART_LSR_FE | UART_LSR_OE))) {
-			/*
-			 * For statistics only
-			 */
-			if (*status & UART_LSR_BI) {
-				*status &= ~(UART_LSR_FE | UART_LSR_PE);
-				up->port.icount.brk++;
-				/*
-				 * We do the SysRQ and SAK checking
-				 * here because otherwise the break
-				 * may get masked by ignore_status_mask
-				 * or read_status_mask.
-				 */
-				if (uart_handle_break(&up->port))
-					goto ignore_char;
-			} else if (*status & UART_LSR_PE)
-				up->port.icount.parity++;
-			else if (*status & UART_LSR_FE)
-				up->port.icount.frame++;
-			if (*status & UART_LSR_OE)
-				up->port.icount.overrun++;
-
-			/*
-			 * Mask off conditions which should be ignored.
-			 */
-			*status &= up->port.read_status_mask;
-
-#ifdef CONFIG_SERIAL_PXA_CONSOLE
-			if (up->port.line == up->port.cons->index) {
-				/* Recover the break flag from console xmit */
-				*status |= up->lsr_break_flag;
-				up->lsr_break_flag = 0;
-			}
-#endif
-			if (*status & UART_LSR_BI) {
-				flag = TTY_BREAK;
-			} else if (*status & UART_LSR_PE)
-				flag = TTY_PARITY;
-			else if (*status & UART_LSR_FE)
-				flag = TTY_FRAME;
-		}
-
-		if (uart_handle_sysrq_char(&up->port, ch))
-			goto ignore_char;
-
-		uart_insert_char(&up->port, *status, UART_LSR_OE, ch, flag);
-
-	ignore_char:
-		*status = serial_in(up, UART_LSR);
-	} while ((*status & UART_LSR_DR) && (max_count-- > 0));
-	tty_flip_buffer_push(&up->port.state->port);
-
-	/* work around Errata #20 according to
-	 * Intel(R) PXA27x Processor Family
-	 * Specification Update (May 2005)
-	 *
-	 * Step 6:
-	 * No more data in FIFO: Re-enable RTO interrupt via IER[RTOIE]
-	 */
-	up->ier |= UART_IER_RTOIE;
-	serial_out(up, UART_IER, up->ier);
-}
-
-static void transmit_chars(struct uart_pxa_port *up)
-{
-	struct circ_buf *xmit = &up->port.state->xmit;
-	int count;
-
-	if (up->port.x_char) {
-		serial_out(up, UART_TX, up->port.x_char);
-		up->port.icount.tx++;
-		up->port.x_char = 0;
-		return;
-	}
-	if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) {
-		serial_pxa_stop_tx(&up->port);
-		return;
-	}
-
-	count = up->port.fifosize / 2;
-	do {
-		serial_out(up, UART_TX, xmit->buf[xmit->tail]);
-		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
-		up->port.icount.tx++;
-		if (uart_circ_empty(xmit))
-			break;
-	} while (--count > 0);
-
-	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
-		uart_write_wakeup(&up->port);
-
-
-	if (uart_circ_empty(xmit))
-		serial_pxa_stop_tx(&up->port);
-}
-
-static void serial_pxa_start_tx(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	if (!(up->ier & UART_IER_THRI)) {
-		up->ier |= UART_IER_THRI;
-		serial_out(up, UART_IER, up->ier);
-	}
-}
-
-static inline void check_modem_status(struct uart_pxa_port *up)
-{
-	int status;
-
-	status = serial_in(up, UART_MSR);
-
-	if ((status & UART_MSR_ANY_DELTA) == 0)
-		return;
-
-	if (status & UART_MSR_TERI)
-		up->port.icount.rng++;
-	if (status & UART_MSR_DDSR)
-		up->port.icount.dsr++;
-	if (status & UART_MSR_DDCD)
-		uart_handle_dcd_change(&up->port, status & UART_MSR_DCD);
-	if (status & UART_MSR_DCTS)
-		uart_handle_cts_change(&up->port, status & UART_MSR_CTS);
-
-	wake_up_interruptible(&up->port.state->port.delta_msr_wait);
-}
-
-/*
- * This handles the interrupt from one port.
- */
-static inline irqreturn_t serial_pxa_irq(int irq, void *dev_id)
-{
-	struct uart_pxa_port *up = dev_id;
-	unsigned int iir, lsr;
-
-	iir = serial_in(up, UART_IIR);
-	if (iir & UART_IIR_NO_INT)
-		return IRQ_NONE;
-	lsr = serial_in(up, UART_LSR);
-	if (lsr & UART_LSR_DR)
-		receive_chars(up, &lsr);
-	check_modem_status(up);
-	if (lsr & UART_LSR_THRE)
-		transmit_chars(up);
-	return IRQ_HANDLED;
-}
-
-static unsigned int serial_pxa_tx_empty(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned long flags;
-	unsigned int ret;
-
-	spin_lock_irqsave(&up->port.lock, flags);
-	ret = serial_in(up, UART_LSR) & UART_LSR_TEMT ? TIOCSER_TEMT : 0;
-	spin_unlock_irqrestore(&up->port.lock, flags);
-
-	return ret;
-}
-
-static unsigned int serial_pxa_get_mctrl(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned char status;
-	unsigned int ret;
-
-	status = serial_in(up, UART_MSR);
-
-	ret = 0;
-	if (status & UART_MSR_DCD)
-		ret |= TIOCM_CAR;
-	if (status & UART_MSR_RI)
-		ret |= TIOCM_RNG;
-	if (status & UART_MSR_DSR)
-		ret |= TIOCM_DSR;
-	if (status & UART_MSR_CTS)
-		ret |= TIOCM_CTS;
-	return ret;
-}
-
-static void serial_pxa_set_mctrl(struct uart_port *port, unsigned int mctrl)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned char mcr = 0;
-
-	if (mctrl & TIOCM_RTS)
-		mcr |= UART_MCR_RTS;
-	if (mctrl & TIOCM_DTR)
-		mcr |= UART_MCR_DTR;
-	if (mctrl & TIOCM_OUT1)
-		mcr |= UART_MCR_OUT1;
-	if (mctrl & TIOCM_OUT2)
-		mcr |= UART_MCR_OUT2;
-	if (mctrl & TIOCM_LOOP)
-		mcr |= UART_MCR_LOOP;
-
-	mcr |= up->mcr;
-
-	serial_out(up, UART_MCR, mcr);
-}
-
-static void serial_pxa_break_ctl(struct uart_port *port, int break_state)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned long flags;
-
-	spin_lock_irqsave(&up->port.lock, flags);
-	if (break_state == -1)
-		up->lcr |= UART_LCR_SBC;
-	else
-		up->lcr &= ~UART_LCR_SBC;
-	serial_out(up, UART_LCR, up->lcr);
-	spin_unlock_irqrestore(&up->port.lock, flags);
-}
-
-static int serial_pxa_startup(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned long flags;
-	int retval;
-
-	if (port->line == 3) /* HWUART */
-		up->mcr |= UART_MCR_AFE;
-	else
-		up->mcr = 0;
-
-	up->port.uartclk = clk_get_rate(up->clk);
-
-	/*
-	 * Allocate the IRQ
-	 */
-	retval = request_irq(up->port.irq, serial_pxa_irq, 0, up->name, up);
-	if (retval)
-		return retval;
-
-	/*
-	 * Clear the FIFO buffers and disable them.
-	 * (they will be reenabled in set_termios())
-	 */
-	serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO);
-	serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO |
-			UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
-	serial_out(up, UART_FCR, 0);
-
-	/*
-	 * Clear the interrupt registers.
-	 */
-	(void) serial_in(up, UART_LSR);
-	(void) serial_in(up, UART_RX);
-	(void) serial_in(up, UART_IIR);
-	(void) serial_in(up, UART_MSR);
-
-	/*
-	 * Now, initialize the UART
-	 */
-	serial_out(up, UART_LCR, UART_LCR_WLEN8);
-
-	spin_lock_irqsave(&up->port.lock, flags);
-	up->port.mctrl |= TIOCM_OUT2;
-	serial_pxa_set_mctrl(&up->port, up->port.mctrl);
-	spin_unlock_irqrestore(&up->port.lock, flags);
-
-	/*
-	 * Finally, enable interrupts.  Note: Modem status interrupts
-	 * are set via set_termios(), which will be occurring imminently
-	 * anyway, so we don't enable them here.
-	 */
-	up->ier = UART_IER_RLSI | UART_IER_RDI | UART_IER_RTOIE | UART_IER_UUE;
-	serial_out(up, UART_IER, up->ier);
-
-	/*
-	 * And clear the interrupt registers again for luck.
-	 */
-	(void) serial_in(up, UART_LSR);
-	(void) serial_in(up, UART_RX);
-	(void) serial_in(up, UART_IIR);
-	(void) serial_in(up, UART_MSR);
-
-	return 0;
-}
-
-static void serial_pxa_shutdown(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned long flags;
-
-	free_irq(up->port.irq, up);
-
-	/*
-	 * Disable interrupts from this port
-	 */
-	up->ier = 0;
-	serial_out(up, UART_IER, 0);
-
-	spin_lock_irqsave(&up->port.lock, flags);
-	up->port.mctrl &= ~TIOCM_OUT2;
-	serial_pxa_set_mctrl(&up->port, up->port.mctrl);
-	spin_unlock_irqrestore(&up->port.lock, flags);
-
-	/*
-	 * Disable break condition and FIFOs
-	 */
-	serial_out(up, UART_LCR, serial_in(up, UART_LCR) & ~UART_LCR_SBC);
-	serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO |
-				  UART_FCR_CLEAR_RCVR |
-				  UART_FCR_CLEAR_XMIT);
-	serial_out(up, UART_FCR, 0);
-}
-
-static void
-serial_pxa_set_termios(struct uart_port *port, struct ktermios *termios,
-		       struct ktermios *old)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned char cval, fcr = 0;
-	unsigned long flags;
-	unsigned int baud, quot;
-	unsigned int dll;
-
-	switch (termios->c_cflag & CSIZE) {
-	case CS5:
-		cval = UART_LCR_WLEN5;
-		break;
-	case CS6:
-		cval = UART_LCR_WLEN6;
-		break;
-	case CS7:
-		cval = UART_LCR_WLEN7;
-		break;
-	default:
-	case CS8:
-		cval = UART_LCR_WLEN8;
-		break;
-	}
-
-	if (termios->c_cflag & CSTOPB)
-		cval |= UART_LCR_STOP;
-	if (termios->c_cflag & PARENB)
-		cval |= UART_LCR_PARITY;
-	if (!(termios->c_cflag & PARODD))
-		cval |= UART_LCR_EPAR;
-
-	/*
-	 * Ask the core to calculate the divisor for us.
-	 */
-	baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
-	quot = uart_get_divisor(port, baud);
-
-	if ((up->port.uartclk / quot) < (2400 * 16))
-		fcr = UART_FCR_ENABLE_FIFO | UART_FCR_PXAR1;
-	else if ((up->port.uartclk / quot) < (230400 * 16))
-		fcr = UART_FCR_ENABLE_FIFO | UART_FCR_PXAR8;
-	else
-		fcr = UART_FCR_ENABLE_FIFO | UART_FCR_PXAR32;
-
-	/*
-	 * Ok, we're now changing the port state.  Do it with
-	 * interrupts disabled.
-	 */
-	spin_lock_irqsave(&up->port.lock, flags);
-
-	/*
-	 * Ensure the port will be enabled.
-	 * This is required especially for serial console.
-	 */
-	up->ier |= UART_IER_UUE;
-
-	/*
-	 * Update the per-port timeout.
-	 */
-	uart_update_timeout(port, termios->c_cflag, baud);
-
-	up->port.read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;
-	if (termios->c_iflag & INPCK)
-		up->port.read_status_mask |= UART_LSR_FE | UART_LSR_PE;
-	if (termios->c_iflag & (BRKINT | PARMRK))
-		up->port.read_status_mask |= UART_LSR_BI;
-
-	/*
-	 * Characters to ignore
-	 */
-	up->port.ignore_status_mask = 0;
-	if (termios->c_iflag & IGNPAR)
-		up->port.ignore_status_mask |= UART_LSR_PE | UART_LSR_FE;
-	if (termios->c_iflag & IGNBRK) {
-		up->port.ignore_status_mask |= UART_LSR_BI;
-		/*
-		 * If we're ignoring parity and break indicators,
-		 * ignore overruns too (for real raw support).
-		 */
-		if (termios->c_iflag & IGNPAR)
-			up->port.ignore_status_mask |= UART_LSR_OE;
-	}
-
-	/*
-	 * ignore all characters if CREAD is not set
-	 */
-	if ((termios->c_cflag & CREAD) == 0)
-		up->port.ignore_status_mask |= UART_LSR_DR;
-
-	/*
-	 * CTS flow control flag and modem status interrupts
-	 */
-	up->ier &= ~UART_IER_MSI;
-	if (UART_ENABLE_MS(&up->port, termios->c_cflag))
-		up->ier |= UART_IER_MSI;
-
-	serial_out(up, UART_IER, up->ier);
-
-	if (termios->c_cflag & CRTSCTS)
-		up->mcr |= UART_MCR_AFE;
-	else
-		up->mcr &= ~UART_MCR_AFE;
-
-	serial_out(up, UART_LCR, cval | UART_LCR_DLAB);	/* set DLAB */
-	serial_out(up, UART_DLL, quot & 0xff);		/* LS of divisor */
-
-	/*
-	 * work around Errata #75 according to Intel(R) PXA27x Processor Family
-	 * Specification Update (Nov 2005)
-	 */
-	dll = serial_in(up, UART_DLL);
-	WARN_ON(dll != (quot & 0xff));
-
-	serial_out(up, UART_DLM, quot >> 8);		/* MS of divisor */
-	serial_out(up, UART_LCR, cval);			/* reset DLAB */
-	up->lcr = cval;					/* Save LCR */
-	serial_pxa_set_mctrl(&up->port, up->port.mctrl);
-	serial_out(up, UART_FCR, fcr);
-	spin_unlock_irqrestore(&up->port.lock, flags);
-}
-
-static void
-serial_pxa_pm(struct uart_port *port, unsigned int state,
-	      unsigned int oldstate)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	if (!state)
-		clk_prepare_enable(up->clk);
-	else
-		clk_disable_unprepare(up->clk);
-}
-
-static void serial_pxa_release_port(struct uart_port *port)
-{
-}
-
-static int serial_pxa_request_port(struct uart_port *port)
-{
-	return 0;
-}
-
-static void serial_pxa_config_port(struct uart_port *port, int flags)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	up->port.type = PORT_PXA;
-}
-
-static int
-serial_pxa_verify_port(struct uart_port *port, struct serial_struct *ser)
-{
-	/* we don't want the core code to modify any port params */
-	return -EINVAL;
-}
-
-static const char *
-serial_pxa_type(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	return up->name;
-}
-
-static struct uart_pxa_port *serial_pxa_ports[4];
-static struct uart_driver serial_pxa_reg;
-
-#ifdef CONFIG_SERIAL_PXA_CONSOLE
-
-#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
-
-/*
- *	Wait for transmitter & holding register to empty
- */
-static inline void wait_for_xmitr(struct uart_pxa_port *up)
-{
-	unsigned int status, tmout = 10000;
-
-	/* Wait up to 10ms for the character(s) to be sent. */
-	do {
-		status = serial_in(up, UART_LSR);
-
-		if (status & UART_LSR_BI)
-			up->lsr_break_flag = UART_LSR_BI;
-
-		if (--tmout == 0)
-			break;
-		udelay(1);
-	} while ((status & BOTH_EMPTY) != BOTH_EMPTY);
-
-	/* Wait up to 1s for flow control if necessary */
-	if (up->port.flags & UPF_CONS_FLOW) {
-		tmout = 1000000;
-		while (--tmout &&
-		       ((serial_in(up, UART_MSR) & UART_MSR_CTS) == 0))
-			udelay(1);
-	}
-}
-
-static void serial_pxa_console_putchar(struct uart_port *port, int ch)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	wait_for_xmitr(up);
-	serial_out(up, UART_TX, ch);
-}
-
-/*
- * Print a string to the serial port trying not to disturb
- * any possible real use of the port...
- *
- *	The console_lock must be held when we get here.
- */
-static void
-serial_pxa_console_write(struct console *co, const char *s, unsigned int count)
-{
-	struct uart_pxa_port *up = serial_pxa_ports[co->index];
-	unsigned int ier;
-	unsigned long flags;
-	int locked = 1;
-
-	clk_enable(up->clk);
-	local_irq_save(flags);
-	if (up->port.sysrq)
-		locked = 0;
-	else if (oops_in_progress)
-		locked = spin_trylock(&up->port.lock);
-	else
-		spin_lock(&up->port.lock);
-
-	/*
-	 *	First save the IER then disable the interrupts
-	 */
-	ier = serial_in(up, UART_IER);
-	serial_out(up, UART_IER, UART_IER_UUE);
-
-	uart_console_write(&up->port, s, count, serial_pxa_console_putchar);
-
-	/*
-	 *	Finally, wait for transmitter to become empty
-	 *	and restore the IER
-	 */
-	wait_for_xmitr(up);
-	serial_out(up, UART_IER, ier);
-
-	if (locked)
-		spin_unlock(&up->port.lock);
-	local_irq_restore(flags);
-	clk_disable(up->clk);
-
-}
-
-#ifdef CONFIG_CONSOLE_POLL
-/*
- * Console polling routines for writing and reading from the uart while
- * in an interrupt or debug context.
- */
-
-static int serial_pxa_get_poll_char(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned char lsr = serial_in(up, UART_LSR);
-
-	while (!(lsr & UART_LSR_DR))
-		lsr = serial_in(up, UART_LSR);
-
-	return serial_in(up, UART_RX);
-}
-
-
-static void serial_pxa_put_poll_char(struct uart_port *port,
-			 unsigned char c)
-{
-	unsigned int ier;
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	/*
-	 *	First save the IER then disable the interrupts
-	 */
-	ier = serial_in(up, UART_IER);
-	serial_out(up, UART_IER, UART_IER_UUE);
-
-	wait_for_xmitr(up);
-	/*
-	 *	Send the character out.
-	 *	If a LF, also do CR...
-	 */
-	serial_out(up, UART_TX, c);
-	if (c == 10) {
-		wait_for_xmitr(up);
-		serial_out(up, UART_TX, 13);
-	}
-
-	/*
-	 *	Finally, wait for transmitter to become empty
-	 *	and restore the IER
-	 */
-	wait_for_xmitr(up);
-	serial_out(up, UART_IER, ier);
-}
-
-#endif /* CONFIG_CONSOLE_POLL */
-
-static int __init
-serial_pxa_console_setup(struct console *co, char *options)
-{
-	struct uart_pxa_port *up;
-	int baud = 9600;
-	int bits = 8;
-	int parity = 'n';
-	int flow = 'n';
-
-	if (co->index == -1 || co->index >= serial_pxa_reg.nr)
-		co->index = 0;
-	up = serial_pxa_ports[co->index];
-	if (!up)
-		return -ENODEV;
-
-	if (options)
-		uart_parse_options(options, &baud, &parity, &bits, &flow);
-
-	return uart_set_options(&up->port, co, baud, parity, bits, flow);
-}
-
-static struct console serial_pxa_console = {
-	.name		= "ttyS",
-	.write		= serial_pxa_console_write,
-	.device		= uart_console_device,
-	.setup		= serial_pxa_console_setup,
-	.flags		= CON_PRINTBUFFER,
-	.index		= -1,
-	.data		= &serial_pxa_reg,
-};
-
-#define PXA_CONSOLE	&serial_pxa_console
-#else
-#define PXA_CONSOLE	NULL
-#endif
-
-static struct uart_ops serial_pxa_pops = {
-	.tx_empty	= serial_pxa_tx_empty,
-	.set_mctrl	= serial_pxa_set_mctrl,
-	.get_mctrl	= serial_pxa_get_mctrl,
-	.stop_tx	= serial_pxa_stop_tx,
-	.start_tx	= serial_pxa_start_tx,
-	.stop_rx	= serial_pxa_stop_rx,
-	.enable_ms	= serial_pxa_enable_ms,
-	.break_ctl	= serial_pxa_break_ctl,
-	.startup	= serial_pxa_startup,
-	.shutdown	= serial_pxa_shutdown,
-	.set_termios	= serial_pxa_set_termios,
-	.pm		= serial_pxa_pm,
-	.type		= serial_pxa_type,
-	.release_port	= serial_pxa_release_port,
-	.request_port	= serial_pxa_request_port,
-	.config_port	= serial_pxa_config_port,
-	.verify_port	= serial_pxa_verify_port,
-#ifdef CONFIG_CONSOLE_POLL
-	.poll_get_char = serial_pxa_get_poll_char,
-	.poll_put_char = serial_pxa_put_poll_char,
-#endif
-};
-
-static struct uart_driver serial_pxa_reg = {
-	.owner		= THIS_MODULE,
-	.driver_name	= "PXA serial",
-	.dev_name	= "ttyS",
-	.major		= TTY_MAJOR,
-	.minor		= 64,
-	.nr		= 4,
-	.cons		= PXA_CONSOLE,
-};
-
-#ifdef CONFIG_PM
-static int serial_pxa_suspend(struct device *dev)
-{
-        struct uart_pxa_port *sport = dev_get_drvdata(dev);
-
-        if (sport)
-                uart_suspend_port(&serial_pxa_reg, &sport->port);
-
-        return 0;
-}
-
-static int serial_pxa_resume(struct device *dev)
-{
-        struct uart_pxa_port *sport = dev_get_drvdata(dev);
-
-        if (sport)
-                uart_resume_port(&serial_pxa_reg, &sport->port);
-
-        return 0;
-}
-
-static const struct dev_pm_ops serial_pxa_pm_ops = {
-	.suspend	= serial_pxa_suspend,
-	.resume		= serial_pxa_resume,
-};
-#endif
-
-static struct of_device_id serial_pxa_dt_ids[] = {
-	{ .compatible = "mrvl,pxa-uart", },
-	{ .compatible = "mrvl,mmp-uart", },
-	{}
-};
-MODULE_DEVICE_TABLE(of, serial_pxa_dt_ids);
-
-static int serial_pxa_probe_dt(struct platform_device *pdev,
-			       struct uart_pxa_port *sport)
-{
-	struct device_node *np = pdev->dev.of_node;
-	int ret;
-
-	if (!np)
-		return 1;
-
-	ret = of_alias_get_id(np, "serial");
-	if (ret < 0) {
-		dev_err(&pdev->dev, "failed to get alias id, errno %d\n", ret);
-		return ret;
-	}
-	sport->port.line = ret;
-	return 0;
-}
-
-static int serial_pxa_probe(struct platform_device *dev)
-{
-	struct uart_pxa_port *sport;
-	struct resource *mmres, *irqres;
-	int ret;
-
-	mmres = platform_get_resource(dev, IORESOURCE_MEM, 0);
-	irqres = platform_get_resource(dev, IORESOURCE_IRQ, 0);
-	if (!mmres || !irqres)
-		return -ENODEV;
-
-	sport = kzalloc(sizeof(struct uart_pxa_port), GFP_KERNEL);
-	if (!sport)
-		return -ENOMEM;
-
-	sport->clk = clk_get(&dev->dev, NULL);
-	if (IS_ERR(sport->clk)) {
-		ret = PTR_ERR(sport->clk);
-		goto err_free;
-	}
-
-	ret = clk_prepare(sport->clk);
-	if (ret) {
-		clk_put(sport->clk);
-		goto err_free;
-	}
-
-	sport->port.type = PORT_PXA;
-	sport->port.iotype = UPIO_MEM;
-	sport->port.mapbase = mmres->start;
-	sport->port.irq = irqres->start;
-	sport->port.fifosize = 64;
-	sport->port.ops = &serial_pxa_pops;
-	sport->port.dev = &dev->dev;
-	sport->port.flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF;
-	sport->port.uartclk = clk_get_rate(sport->clk);
-
-	ret = serial_pxa_probe_dt(dev, sport);
-	if (ret > 0)
-		sport->port.line = dev->id;
-	else if (ret < 0)
-		goto err_clk;
-	snprintf(sport->name, PXA_NAME_LEN - 1, "UART%d", sport->port.line + 1);
-
-	sport->port.membase = ioremap(mmres->start, resource_size(mmres));
-	if (!sport->port.membase) {
-		ret = -ENOMEM;
-		goto err_clk;
-	}
-
-	serial_pxa_ports[sport->port.line] = sport;
-
-	uart_add_one_port(&serial_pxa_reg, &sport->port);
-	platform_set_drvdata(dev, sport);
-
-	return 0;
-
- err_clk:
-	clk_unprepare(sport->clk);
-	clk_put(sport->clk);
- err_free:
-	kfree(sport);
-	return ret;
-}
-
-static int serial_pxa_remove(struct platform_device *dev)
-{
-	struct uart_pxa_port *sport = platform_get_drvdata(dev);
-
-	uart_remove_one_port(&serial_pxa_reg, &sport->port);
-
-	clk_unprepare(sport->clk);
-	clk_put(sport->clk);
-	kfree(sport);
-
-	return 0;
-}
-
-static struct platform_driver serial_pxa_driver = {
-        .probe          = serial_pxa_probe,
-        .remove         = serial_pxa_remove,
-
-	.driver		= {
-	        .name	= "pxa2xx-uart",
-		.owner	= THIS_MODULE,
-#ifdef CONFIG_PM
-		.pm	= &serial_pxa_pm_ops,
-#endif
-		.of_match_table = serial_pxa_dt_ids,
-	},
-};
-
-static int __init serial_pxa_init(void)
-{
-	int ret;
-
-	ret = uart_register_driver(&serial_pxa_reg);
-	if (ret != 0)
-		return ret;
-
-	ret = platform_driver_register(&serial_pxa_driver);
-	if (ret != 0)
-		uart_unregister_driver(&serial_pxa_reg);
-
-	return ret;
-}
-
-static void __exit serial_pxa_exit(void)
-{
-	platform_driver_unregister(&serial_pxa_driver);
-	uart_unregister_driver(&serial_pxa_reg);
-}
-
-module_init(serial_pxa_init);
-module_exit(serial_pxa_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:pxa2xx-uart");
-- 
1.8.4.2


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

* [PATCH v2] serial: rewrite pxa2xx-uart to use 8250_core
@ 2013-12-06  9:09                       ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-06  9:09 UTC (permalink / raw)
  To: linux-kernel
  Cc: Sergei Ianovich, Heikki Krogerus, Greg Kroah-Hartman,
	James Cameron, Russell King, Jiri Slaby, Grant Likely,
	Rob Herring, Zhou Zhu, Andrew Morton, Haojian Zhuang,
	Stefan Seyfried, John Crispin, Paul Bolle,
	moderated list:ARM PORT, open list:SERIAL DRIVERS,
	open list:OPEN FIRMWARE AND...

pxa2xx-uart was a separate uart platform driver. It was declaring
the same device names and numbers as 8250 driver. As a result,
it was impossible to use 8250 driver on PXA SoCs.

Upon closer examination pxa2xx-uart turned out to be a clone of
8250_core driver.

Workaround for Erratum #19 according to Marvel(R) PXA270M Processor
Specification Update (April 19, 2010) is dropped. 8250_core reads
from FIFO immediately after checking DR bit in LSR.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Heikki Krogerus <heikki.krogerus@linux.intel.com>
CC: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
CC: James Cameron <quozl@laptop.org>
---
 changes v1..v2
 * actually implement workaround for E74 in dl_write as spooted
   by James Cameron
 * added comment about E19 in commit message

 arch/arm/configs/am200epdkit_defconfig    |   3 +-
 arch/arm/configs/cm_x2xx_defconfig        |   3 +-
 arch/arm/configs/cm_x300_defconfig        |   3 +-
 arch/arm/configs/colibri_pxa270_defconfig |   3 +-
 arch/arm/configs/colibri_pxa300_defconfig |   3 +-
 arch/arm/configs/corgi_defconfig          |   4 +-
 arch/arm/configs/em_x270_defconfig        |   3 +-
 arch/arm/configs/ezx_defconfig            |   3 +-
 arch/arm/configs/h5000_defconfig          |   3 +-
 arch/arm/configs/imote2_defconfig         |   3 +-
 arch/arm/configs/lpd270_defconfig         |   3 +-
 arch/arm/configs/lubbock_defconfig        |   3 +-
 arch/arm/configs/mainstone_defconfig      |   3 +-
 arch/arm/configs/mmp2_defconfig           |   3 +-
 arch/arm/configs/pcm027_defconfig         |   3 +-
 arch/arm/configs/pxa168_defconfig         |   3 +-
 arch/arm/configs/pxa255-idp_defconfig     |   3 +-
 arch/arm/configs/pxa3xx_defconfig         |   3 +-
 arch/arm/configs/pxa910_defconfig         |   3 +-
 arch/arm/configs/raumfeld_defconfig       |   3 +-
 arch/arm/configs/spitz_defconfig          |   4 +-
 arch/arm/configs/trizeps4_defconfig       |   3 +-
 arch/arm/configs/viper_defconfig          |   4 +-
 arch/arm/configs/xcep_defconfig           |   3 +-
 drivers/tty/serial/8250/8250_pxa.c        | 189 ++++++
 drivers/tty/serial/8250/Kconfig           |   9 +
 drivers/tty/serial/8250/Makefile          |   1 +
 drivers/tty/serial/Kconfig                |  23 -
 drivers/tty/serial/Makefile               |   1 -
 drivers/tty/serial/pxa.c                  | 971 ------------------------------
 30 files changed, 247 insertions(+), 1022 deletions(-)
 create mode 100644 drivers/tty/serial/8250/8250_pxa.c
 delete mode 100644 drivers/tty/serial/pxa.c

diff --git a/arch/arm/configs/am200epdkit_defconfig b/arch/arm/configs/am200epdkit_defconfig
index f0dea52..0cde234 100644
--- a/arch/arm/configs/am200epdkit_defconfig
+++ b/arch/arm/configs/am200epdkit_defconfig
@@ -60,8 +60,9 @@ CONFIG_BLK_DEV_IDECS=m
 CONFIG_NETDEVICES=y
 CONFIG_NET_ETHERNET=y
 CONFIG_SMC91X=m
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 # CONFIG_HWMON is not set
diff --git a/arch/arm/configs/cm_x2xx_defconfig b/arch/arm/configs/cm_x2xx_defconfig
index a93ff8d..b9fbe65 100644
--- a/arch/arm/configs/cm_x2xx_defconfig
+++ b/arch/arm/configs/cm_x2xx_defconfig
@@ -96,8 +96,9 @@ CONFIG_KEYBOARD_PXA27x=m
 CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_TOUCHSCREEN_UCB1400=m
 # CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_LEGACY_PTY_COUNT=16
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/cm_x300_defconfig b/arch/arm/configs/cm_x300_defconfig
index f4b7672..53a82ae 100644
--- a/arch/arm/configs/cm_x300_defconfig
+++ b/arch/arm/configs/cm_x300_defconfig
@@ -80,8 +80,9 @@ CONFIG_TOUCHSCREEN_WM97XX=m
 # CONFIG_TOUCHSCREEN_WM9713 is not set
 # CONFIG_SERIO is not set
 # CONFIG_LEGACY_PTYS is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
 CONFIG_I2C_PXA=y
diff --git a/arch/arm/configs/colibri_pxa270_defconfig b/arch/arm/configs/colibri_pxa270_defconfig
index 2ef2c5e..1ce0409 100644
--- a/arch/arm/configs/colibri_pxa270_defconfig
+++ b/arch/arm/configs/colibri_pxa270_defconfig
@@ -103,8 +103,9 @@ CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=m
 CONFIG_SERIO_LIBPS2=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_HW_RANDOM=y
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
diff --git a/arch/arm/configs/colibri_pxa300_defconfig b/arch/arm/configs/colibri_pxa300_defconfig
index b985334..f96bda0 100644
--- a/arch/arm/configs/colibri_pxa300_defconfig
+++ b/arch/arm/configs/colibri_pxa300_defconfig
@@ -31,8 +31,9 @@ CONFIG_INPUT_EVDEV=y
 # CONFIG_INPUT_MOUSE is not set
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_GPIO_ROTARY_ENCODER=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_HW_RANDOM=y
 CONFIG_DEBUG_GPIO=y
 # CONFIG_HWMON is not set
diff --git a/arch/arm/configs/corgi_defconfig b/arch/arm/configs/corgi_defconfig
index 1fd1d1d..bb4842d 100644
--- a/arch/arm/configs/corgi_defconfig
+++ b/arch/arm/configs/corgi_defconfig
@@ -131,10 +131,10 @@ CONFIG_TOUCHSCREEN_ADS7846=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=m
 # CONFIG_SERIO is not set
-CONFIG_SERIAL_8250=m
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_CS=m
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 CONFIG_I2C=y
 CONFIG_I2C_PXA=y
diff --git a/arch/arm/configs/em_x270_defconfig b/arch/arm/configs/em_x270_defconfig
index 60a21e0..ec0ec54 100644
--- a/arch/arm/configs/em_x270_defconfig
+++ b/arch/arm/configs/em_x270_defconfig
@@ -90,8 +90,9 @@ CONFIG_TOUCHSCREEN_WM97XX=m
 # CONFIG_TOUCHSCREEN_WM9705 is not set
 # CONFIG_TOUCHSCREEN_WM9713 is not set
 # CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_LEGACY_PTY_COUNT=16
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/ezx_defconfig b/arch/arm/configs/ezx_defconfig
index d95763d..631e2ec 100644
--- a/arch/arm/configs/ezx_defconfig
+++ b/arch/arm/configs/ezx_defconfig
@@ -215,8 +215,9 @@ CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=y
 CONFIG_INPUT_PCAP=y
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_LEGACY_PTY_COUNT=8
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/h5000_defconfig b/arch/arm/configs/h5000_defconfig
index 37903e3..655b735 100644
--- a/arch/arm/configs/h5000_defconfig
+++ b/arch/arm/configs/h5000_defconfig
@@ -47,8 +47,9 @@ CONFIG_MTD_PHYSMAP=y
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_LEGACY_PTY_COUNT=32
 # CONFIG_HW_RANDOM is not set
 # CONFIG_HWMON is not set
diff --git a/arch/arm/configs/imote2_defconfig b/arch/arm/configs/imote2_defconfig
index fd996bb..49d45e9 100644
--- a/arch/arm/configs/imote2_defconfig
+++ b/arch/arm/configs/imote2_defconfig
@@ -193,8 +193,9 @@ CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=y
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_LEGACY_PTY_COUNT=8
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/lpd270_defconfig b/arch/arm/configs/lpd270_defconfig
index 1c8c9ee..c3927b6 100644
--- a/arch/arm/configs/lpd270_defconfig
+++ b/arch/arm/configs/lpd270_defconfig
@@ -38,8 +38,9 @@ CONFIG_SMC91X=y
 CONFIG_INPUT_EVDEV=y
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_HW_RANDOM is not set
 CONFIG_FB=y
 CONFIG_FB_PXA=y
diff --git a/arch/arm/configs/lubbock_defconfig b/arch/arm/configs/lubbock_defconfig
index c4ba274..c8b0436 100644
--- a/arch/arm/configs/lubbock_defconfig
+++ b/arch/arm/configs/lubbock_defconfig
@@ -37,8 +37,9 @@ CONFIG_PCMCIA_PCNET=y
 CONFIG_INPUT_EVDEV=y
 # CONFIG_SERIO_SERPORT is not set
 CONFIG_SERIO_SA1111=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_USB_GADGET=y
 CONFIG_USB_G_SERIAL=m
diff --git a/arch/arm/configs/mainstone_defconfig b/arch/arm/configs/mainstone_defconfig
index 04efa1b..768892c 100644
--- a/arch/arm/configs/mainstone_defconfig
+++ b/arch/arm/configs/mainstone_defconfig
@@ -34,8 +34,9 @@ CONFIG_SMC91X=y
 CONFIG_INPUT_EVDEV=y
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_FB=y
 CONFIG_FB_PXA=y
 # CONFIG_VGA_CONSOLE is not set
diff --git a/arch/arm/configs/mmp2_defconfig b/arch/arm/configs/mmp2_defconfig
index f1cb95e..1ced9df 100644
--- a/arch/arm/configs/mmp2_defconfig
+++ b/arch/arm/configs/mmp2_defconfig
@@ -44,8 +44,9 @@ CONFIG_SMC91X=y
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/pcm027_defconfig b/arch/arm/configs/pcm027_defconfig
index 2f136c3..1280128 100644
--- a/arch/arm/configs/pcm027_defconfig
+++ b/arch/arm/configs/pcm027_defconfig
@@ -60,8 +60,9 @@ CONFIG_SMC91X=y
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/pxa168_defconfig b/arch/arm/configs/pxa168_defconfig
index 74d7e01..1668dac 100644
--- a/arch/arm/configs/pxa168_defconfig
+++ b/arch/arm/configs/pxa168_defconfig
@@ -40,8 +40,9 @@ CONFIG_SMC91X=y
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 # CONFIG_HWMON is not set
diff --git a/arch/arm/configs/pxa255-idp_defconfig b/arch/arm/configs/pxa255-idp_defconfig
index 917a070..399a706 100644
--- a/arch/arm/configs/pxa255-idp_defconfig
+++ b/arch/arm/configs/pxa255-idp_defconfig
@@ -35,8 +35,9 @@ CONFIG_SMC91X=y
 CONFIG_INPUT_EVDEV=y
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_FB=y
 CONFIG_FB_PXA=y
 # CONFIG_VGA_CONSOLE is not set
diff --git a/arch/arm/configs/pxa3xx_defconfig b/arch/arm/configs/pxa3xx_defconfig
index 60e3138..7c3e052 100644
--- a/arch/arm/configs/pxa3xx_defconfig
+++ b/arch/arm/configs/pxa3xx_defconfig
@@ -56,8 +56,9 @@ CONFIG_KEYBOARD_PXA27x=y
 CONFIG_KEYBOARD_PXA930_ROTARY=y
 CONFIG_MOUSE_PXA930_TRKBALL=y
 CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/pxa910_defconfig b/arch/arm/configs/pxa910_defconfig
index 3bb7771..cdacfcb 100644
--- a/arch/arm/configs/pxa910_defconfig
+++ b/arch/arm/configs/pxa910_defconfig
@@ -40,8 +40,9 @@ CONFIG_SMC91X=y
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_SPI=y
 CONFIG_FB=y
 CONFIG_MMP_DISP=y
diff --git a/arch/arm/configs/raumfeld_defconfig b/arch/arm/configs/raumfeld_defconfig
index f7caa90..f1e16f2 100644
--- a/arch/arm/configs/raumfeld_defconfig
+++ b/arch/arm/configs/raumfeld_defconfig
@@ -67,8 +67,9 @@ CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_TOUCHSCREEN_EETI=m
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_GPIO_ROTARY_ENCODER=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_HW_RANDOM=y
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
diff --git a/arch/arm/configs/spitz_defconfig b/arch/arm/configs/spitz_defconfig
index 2e0419d..b6efcf5 100644
--- a/arch/arm/configs/spitz_defconfig
+++ b/arch/arm/configs/spitz_defconfig
@@ -128,10 +128,10 @@ CONFIG_TOUCHSCREEN_ADS7846=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=m
 # CONFIG_SERIO is not set
-CONFIG_SERIAL_8250=m
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_CS=m
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 CONFIG_SPI=y
 CONFIG_SPI_PXA2XX=y
diff --git a/arch/arm/configs/trizeps4_defconfig b/arch/arm/configs/trizeps4_defconfig
index 3162173..453c79c 100644
--- a/arch/arm/configs/trizeps4_defconfig
+++ b/arch/arm/configs/trizeps4_defconfig
@@ -132,8 +132,9 @@ CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=m
 CONFIG_SERIO_LIBPS2=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_HW_RANDOM=y
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
diff --git a/arch/arm/configs/viper_defconfig b/arch/arm/configs/viper_defconfig
index d36e0d3..4efac06 100644
--- a/arch/arm/configs/viper_defconfig
+++ b/arch/arm/configs/viper_defconfig
@@ -101,11 +101,11 @@ CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=m
 # CONFIG_CONSOLE_TRANSLATIONS is not set
 # CONFIG_VT_CONSOLE is not set
-CONFIG_SERIAL_8250=m
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_NR_UARTS=5
 CONFIG_SERIAL_8250_RUNTIME_UARTS=5
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
diff --git a/arch/arm/configs/xcep_defconfig b/arch/arm/configs/xcep_defconfig
index 721832f..b67aeaf 100644
--- a/arch/arm/configs/xcep_defconfig
+++ b/arch/arm/configs/xcep_defconfig
@@ -60,8 +60,9 @@ CONFIG_NET_ETHERNET=y
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
 # CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=m
diff --git a/drivers/tty/serial/8250/8250_pxa.c b/drivers/tty/serial/8250/8250_pxa.c
new file mode 100644
index 0000000..88ae73c
--- /dev/null
+++ b/drivers/tty/serial/8250/8250_pxa.c
@@ -0,0 +1,189 @@
+/*
+ *  drivers/tty/serial/8250/8250_pxa.c -- driver for PXA on-board UARTS
+ *  Copyright:	(C) 2013 Sergei Ianovich <ynvich@gmail.com>
+ *
+ *  replaces drivers/serial/pxa.c by Nicolas Pitre
+ *  Created:	Feb 20, 2003
+ *  Copyright:	(C) 2003 Monta Vista Software, Inc.
+ *
+ *  Based on drivers/serial/8250.c by Russell King.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/serial_8250.h>
+#include <linux/serial_core.h>
+#include <linux/serial_reg.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
+#include <linux/pm_runtime.h>
+
+#include "8250.h"
+
+struct pxa8250_data {
+	int			line;
+	struct clk		*clk;
+};
+
+#ifdef CONFIG_PM
+static int serial_pxa_suspend(struct device *dev)
+{
+	struct pxa8250_data *data = dev_get_drvdata(dev);
+
+	serial8250_suspend_port(data->line);
+
+	return 0;
+}
+
+static int serial_pxa_resume(struct device *dev)
+{
+	struct pxa8250_data *data = dev_get_drvdata(dev);
+
+	serial8250_resume_port(data->line);
+
+	return 0;
+}
+
+static const struct dev_pm_ops serial_pxa_pm_ops = {
+	.suspend	= serial_pxa_suspend,
+	.resume		= serial_pxa_resume,
+};
+#endif
+
+static struct of_device_id serial_pxa_dt_ids[] = {
+	{ .compatible = "mrvl,pxa-uart", },
+	{ .compatible = "mrvl,mmp-uart", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, serial_pxa_dt_ids);
+
+/* Uart divisor latch write */
+static void serial_pxa_dl_write(struct uart_8250_port *up, int value)
+{
+	unsigned int dll;
+
+	serial_out(up, UART_DLL, value & 0xff);
+	/*
+	 * work around Erratum #74 according to Marvel(R) PXA270M Processor
+	 * Specification Update (April 19, 2010)
+	 */
+	dll = serial_in(up, UART_DLL);
+	WARN_ON(dll != (value & 0xff));
+
+	serial_out(up, UART_DLM, value >> 8 & 0xff);
+}
+
+
+static void serial_pxa_pm(struct uart_port *port, unsigned int state,
+	      unsigned int oldstate)
+{
+	struct pxa8250_data *data = port->private_data;
+
+	if (!state)
+		clk_prepare_enable(data->clk);
+	else
+		clk_disable_unprepare(data->clk);
+}
+
+static int serial_pxa_probe(struct platform_device *pdev)
+{
+	struct uart_8250_port uart = {};
+	struct pxa8250_data *data;
+	struct resource *mmres, *irqres;
+	int ret;
+
+	mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	irqres = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!mmres || !irqres)
+		return -ENODEV;
+
+	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(data->clk)) {
+		ret = PTR_ERR(data->clk);
+		goto err_free;
+	}
+
+	ret = clk_prepare(data->clk);
+	if (ret)
+		goto err_free_clk;
+
+	uart.port.type = PORT_XSCALE;
+	uart.port.iotype = UPIO_MEM32;
+	uart.port.mapbase = mmres->start;
+	uart.port.regshift = 2;
+	uart.port.irq = irqres->start;
+	uart.port.fifosize = 64;
+	uart.port.flags = UPF_IOREMAP | UPF_SKIP_TEST;
+	uart.port.dev = &pdev->dev;
+	uart.port.uartclk = clk_get_rate(data->clk);
+	uart.port.pm = serial_pxa_pm;
+	uart.port.private_data = data;
+	uart.dl_write = serial_pxa_dl_write;
+
+	ret = serial8250_register_8250_port(&uart);
+	if (ret < 0)
+		goto err_clk;
+
+	data->line = ret;
+
+	platform_set_drvdata(pdev, data);
+
+	return 0;
+
+ err_clk:
+	clk_unprepare(data->clk);
+ err_free_clk:
+	devm_clk_put(&pdev->dev, data->clk);
+ err_free:
+	devm_kfree(&pdev->dev, data);
+	return ret;
+}
+
+static int serial_pxa_remove(struct platform_device *pdev)
+{
+	struct pxa8250_data *data = platform_get_drvdata(pdev);
+
+	serial8250_unregister_port(data->line);
+
+	clk_unprepare(data->clk);
+	devm_clk_put(&pdev->dev, data->clk);
+	devm_kfree(&pdev->dev, data);
+
+	return 0;
+}
+
+static struct platform_driver serial_pxa_driver = {
+	.probe          = serial_pxa_probe,
+	.remove         = serial_pxa_remove,
+
+	.driver		= {
+		.name	= "pxa2xx-uart",
+		.owner	= THIS_MODULE,
+#ifdef CONFIG_PM
+		.pm	= &serial_pxa_pm_ops,
+#endif
+		.of_match_table = serial_pxa_dt_ids,
+	},
+};
+
+module_platform_driver(serial_pxa_driver);
+
+MODULE_AUTHOR("Sergei Ianovich");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:pxa2xx-uart");
diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
index 2332991..81bd7c9 100644
--- a/drivers/tty/serial/8250/Kconfig
+++ b/drivers/tty/serial/8250/Kconfig
@@ -302,3 +302,12 @@ config SERIAL_8250_RT288X
 	  If you have a Ralink RT288x/RT305x SoC based board and want to use the
 	  serial port, say Y to this option. The driver can handle up to 2 serial
 	  ports. If unsure, say N.
+
+config SERIAL_PXA
+	tristate "PXA serial port support"
+	depends on SERIAL_8250 && (ARCH_PXA || ARCH_MMP)
+	help
+	  If you have a machine based on an Intel XScale PXA2xx CPU you
+	  can enable its onboard serial ports by enabling this option.
+
+	  If you choose M here, the module name will be 8250_pxa.
diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile
index 36d68d0..b7d1b61 100644
--- a/drivers/tty/serial/8250/Makefile
+++ b/drivers/tty/serial/8250/Makefile
@@ -20,3 +20,4 @@ obj-$(CONFIG_SERIAL_8250_HUB6)		+= 8250_hub6.o
 obj-$(CONFIG_SERIAL_8250_FSL)		+= 8250_fsl.o
 obj-$(CONFIG_SERIAL_8250_DW)		+= 8250_dw.o
 obj-$(CONFIG_SERIAL_8250_EM)		+= 8250_em.o
+obj-$(CONFIG_SERIAL_PXA)		+= 8250_pxa.o
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index a3817ab..2ad7184b 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -396,29 +396,6 @@ config SERIAL_MPSC_CONSOLE
 	help
 	  Say Y here if you want to support a serial console on a Marvell MPSC.
 
-config SERIAL_PXA
-	bool "PXA serial port support"
-	depends on ARCH_PXA || ARCH_MMP
-	select SERIAL_CORE
-	help
-	  If you have a machine based on an Intel XScale PXA2xx CPU you
-	  can enable its onboard serial ports by enabling this option.
-
-config SERIAL_PXA_CONSOLE
-	bool "Console on PXA serial port"
-	depends on SERIAL_PXA
-	select SERIAL_CORE_CONSOLE
-	help
-	  If you have enabled the serial port on the Intel XScale PXA
-	  CPU you can make it the console by answering Y to this option.
-
-	  Even if you say Y here, the currently visible virtual console
-	  (/dev/tty0) will still be used as the system console by default, but
-	  you can alter that using a kernel command line option such as
-	  "console=ttySA0". (Try "man bootparam" or see the documentation of
-	  your boot loader (lilo or loadlin) about how to pass options to the
-	  kernel at boot time.)
-
 config SERIAL_SA1100
 	bool "SA1100 serial port support"
 	depends on ARCH_SA1100
diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile
index 3068c77..4ac337b 100644
--- a/drivers/tty/serial/Makefile
+++ b/drivers/tty/serial/Makefile
@@ -20,7 +20,6 @@ obj-$(CONFIG_SERIAL_8250) += 8250/
 obj-$(CONFIG_SERIAL_AMBA_PL010) += amba-pl010.o
 obj-$(CONFIG_SERIAL_AMBA_PL011) += amba-pl011.o
 obj-$(CONFIG_SERIAL_CLPS711X) += clps711x.o
-obj-$(CONFIG_SERIAL_PXA) += pxa.o
 obj-$(CONFIG_SERIAL_PNX8XXX) += pnx8xxx_uart.o
 obj-$(CONFIG_SERIAL_SA1100) += sa1100.o
 obj-$(CONFIG_SERIAL_BCM63XX) += bcm63xx_uart.o
diff --git a/drivers/tty/serial/pxa.c b/drivers/tty/serial/pxa.c
deleted file mode 100644
index f9f20f3..0000000
--- a/drivers/tty/serial/pxa.c
+++ /dev/null
@@ -1,971 +0,0 @@
-/*
- *  Based on drivers/serial/8250.c by Russell King.
- *
- *  Author:	Nicolas Pitre
- *  Created:	Feb 20, 2003
- *  Copyright:	(C) 2003 Monta Vista Software, Inc.
- *
- * 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.
- *
- * Note 1: This driver is made separate from the already too overloaded
- * 8250.c because it needs some kirks of its own and that'll make it
- * easier to add DMA support.
- *
- * Note 2: I'm too sick of device allocation policies for serial ports.
- * If someone else wants to request an "official" allocation of major/minor
- * for this driver please be my guest.  And don't forget that new hardware
- * to come from Intel might have more than 3 or 4 of those UARTs.  Let's
- * hope for a better port registration and dynamic device allocation scheme
- * with the serial core maintainer satisfaction to appear soon.
- */
-
-
-#if defined(CONFIG_SERIAL_PXA_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-#define SUPPORT_SYSRQ
-#endif
-
-#include <linux/module.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-#include <linux/console.h>
-#include <linux/sysrq.h>
-#include <linux/serial_reg.h>
-#include <linux/circ_buf.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/of.h>
-#include <linux/platform_device.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/serial_core.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-
-#define PXA_NAME_LEN		8
-
-struct uart_pxa_port {
-	struct uart_port        port;
-	unsigned char           ier;
-	unsigned char           lcr;
-	unsigned char           mcr;
-	unsigned int            lsr_break_flag;
-	struct clk		*clk;
-	char			name[PXA_NAME_LEN];
-};
-
-static inline unsigned int serial_in(struct uart_pxa_port *up, int offset)
-{
-	offset <<= 2;
-	return readl(up->port.membase + offset);
-}
-
-static inline void serial_out(struct uart_pxa_port *up, int offset, int value)
-{
-	offset <<= 2;
-	writel(value, up->port.membase + offset);
-}
-
-static void serial_pxa_enable_ms(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	up->ier |= UART_IER_MSI;
-	serial_out(up, UART_IER, up->ier);
-}
-
-static void serial_pxa_stop_tx(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	if (up->ier & UART_IER_THRI) {
-		up->ier &= ~UART_IER_THRI;
-		serial_out(up, UART_IER, up->ier);
-	}
-}
-
-static void serial_pxa_stop_rx(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	up->ier &= ~UART_IER_RLSI;
-	up->port.read_status_mask &= ~UART_LSR_DR;
-	serial_out(up, UART_IER, up->ier);
-}
-
-static inline void receive_chars(struct uart_pxa_port *up, int *status)
-{
-	unsigned int ch, flag;
-	int max_count = 256;
-
-	do {
-		/* work around Errata #20 according to
-		 * Intel(R) PXA27x Processor Family
-		 * Specification Update (May 2005)
-		 *
-		 * Step 2
-		 * Disable the Reciever Time Out Interrupt via IER[RTOEI]
-		 */
-		up->ier &= ~UART_IER_RTOIE;
-		serial_out(up, UART_IER, up->ier);
-
-		ch = serial_in(up, UART_RX);
-		flag = TTY_NORMAL;
-		up->port.icount.rx++;
-
-		if (unlikely(*status & (UART_LSR_BI | UART_LSR_PE |
-				       UART_LSR_FE | UART_LSR_OE))) {
-			/*
-			 * For statistics only
-			 */
-			if (*status & UART_LSR_BI) {
-				*status &= ~(UART_LSR_FE | UART_LSR_PE);
-				up->port.icount.brk++;
-				/*
-				 * We do the SysRQ and SAK checking
-				 * here because otherwise the break
-				 * may get masked by ignore_status_mask
-				 * or read_status_mask.
-				 */
-				if (uart_handle_break(&up->port))
-					goto ignore_char;
-			} else if (*status & UART_LSR_PE)
-				up->port.icount.parity++;
-			else if (*status & UART_LSR_FE)
-				up->port.icount.frame++;
-			if (*status & UART_LSR_OE)
-				up->port.icount.overrun++;
-
-			/*
-			 * Mask off conditions which should be ignored.
-			 */
-			*status &= up->port.read_status_mask;
-
-#ifdef CONFIG_SERIAL_PXA_CONSOLE
-			if (up->port.line == up->port.cons->index) {
-				/* Recover the break flag from console xmit */
-				*status |= up->lsr_break_flag;
-				up->lsr_break_flag = 0;
-			}
-#endif
-			if (*status & UART_LSR_BI) {
-				flag = TTY_BREAK;
-			} else if (*status & UART_LSR_PE)
-				flag = TTY_PARITY;
-			else if (*status & UART_LSR_FE)
-				flag = TTY_FRAME;
-		}
-
-		if (uart_handle_sysrq_char(&up->port, ch))
-			goto ignore_char;
-
-		uart_insert_char(&up->port, *status, UART_LSR_OE, ch, flag);
-
-	ignore_char:
-		*status = serial_in(up, UART_LSR);
-	} while ((*status & UART_LSR_DR) && (max_count-- > 0));
-	tty_flip_buffer_push(&up->port.state->port);
-
-	/* work around Errata #20 according to
-	 * Intel(R) PXA27x Processor Family
-	 * Specification Update (May 2005)
-	 *
-	 * Step 6:
-	 * No more data in FIFO: Re-enable RTO interrupt via IER[RTOIE]
-	 */
-	up->ier |= UART_IER_RTOIE;
-	serial_out(up, UART_IER, up->ier);
-}
-
-static void transmit_chars(struct uart_pxa_port *up)
-{
-	struct circ_buf *xmit = &up->port.state->xmit;
-	int count;
-
-	if (up->port.x_char) {
-		serial_out(up, UART_TX, up->port.x_char);
-		up->port.icount.tx++;
-		up->port.x_char = 0;
-		return;
-	}
-	if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) {
-		serial_pxa_stop_tx(&up->port);
-		return;
-	}
-
-	count = up->port.fifosize / 2;
-	do {
-		serial_out(up, UART_TX, xmit->buf[xmit->tail]);
-		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
-		up->port.icount.tx++;
-		if (uart_circ_empty(xmit))
-			break;
-	} while (--count > 0);
-
-	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
-		uart_write_wakeup(&up->port);
-
-
-	if (uart_circ_empty(xmit))
-		serial_pxa_stop_tx(&up->port);
-}
-
-static void serial_pxa_start_tx(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	if (!(up->ier & UART_IER_THRI)) {
-		up->ier |= UART_IER_THRI;
-		serial_out(up, UART_IER, up->ier);
-	}
-}
-
-static inline void check_modem_status(struct uart_pxa_port *up)
-{
-	int status;
-
-	status = serial_in(up, UART_MSR);
-
-	if ((status & UART_MSR_ANY_DELTA) == 0)
-		return;
-
-	if (status & UART_MSR_TERI)
-		up->port.icount.rng++;
-	if (status & UART_MSR_DDSR)
-		up->port.icount.dsr++;
-	if (status & UART_MSR_DDCD)
-		uart_handle_dcd_change(&up->port, status & UART_MSR_DCD);
-	if (status & UART_MSR_DCTS)
-		uart_handle_cts_change(&up->port, status & UART_MSR_CTS);
-
-	wake_up_interruptible(&up->port.state->port.delta_msr_wait);
-}
-
-/*
- * This handles the interrupt from one port.
- */
-static inline irqreturn_t serial_pxa_irq(int irq, void *dev_id)
-{
-	struct uart_pxa_port *up = dev_id;
-	unsigned int iir, lsr;
-
-	iir = serial_in(up, UART_IIR);
-	if (iir & UART_IIR_NO_INT)
-		return IRQ_NONE;
-	lsr = serial_in(up, UART_LSR);
-	if (lsr & UART_LSR_DR)
-		receive_chars(up, &lsr);
-	check_modem_status(up);
-	if (lsr & UART_LSR_THRE)
-		transmit_chars(up);
-	return IRQ_HANDLED;
-}
-
-static unsigned int serial_pxa_tx_empty(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned long flags;
-	unsigned int ret;
-
-	spin_lock_irqsave(&up->port.lock, flags);
-	ret = serial_in(up, UART_LSR) & UART_LSR_TEMT ? TIOCSER_TEMT : 0;
-	spin_unlock_irqrestore(&up->port.lock, flags);
-
-	return ret;
-}
-
-static unsigned int serial_pxa_get_mctrl(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned char status;
-	unsigned int ret;
-
-	status = serial_in(up, UART_MSR);
-
-	ret = 0;
-	if (status & UART_MSR_DCD)
-		ret |= TIOCM_CAR;
-	if (status & UART_MSR_RI)
-		ret |= TIOCM_RNG;
-	if (status & UART_MSR_DSR)
-		ret |= TIOCM_DSR;
-	if (status & UART_MSR_CTS)
-		ret |= TIOCM_CTS;
-	return ret;
-}
-
-static void serial_pxa_set_mctrl(struct uart_port *port, unsigned int mctrl)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned char mcr = 0;
-
-	if (mctrl & TIOCM_RTS)
-		mcr |= UART_MCR_RTS;
-	if (mctrl & TIOCM_DTR)
-		mcr |= UART_MCR_DTR;
-	if (mctrl & TIOCM_OUT1)
-		mcr |= UART_MCR_OUT1;
-	if (mctrl & TIOCM_OUT2)
-		mcr |= UART_MCR_OUT2;
-	if (mctrl & TIOCM_LOOP)
-		mcr |= UART_MCR_LOOP;
-
-	mcr |= up->mcr;
-
-	serial_out(up, UART_MCR, mcr);
-}
-
-static void serial_pxa_break_ctl(struct uart_port *port, int break_state)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned long flags;
-
-	spin_lock_irqsave(&up->port.lock, flags);
-	if (break_state == -1)
-		up->lcr |= UART_LCR_SBC;
-	else
-		up->lcr &= ~UART_LCR_SBC;
-	serial_out(up, UART_LCR, up->lcr);
-	spin_unlock_irqrestore(&up->port.lock, flags);
-}
-
-static int serial_pxa_startup(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned long flags;
-	int retval;
-
-	if (port->line == 3) /* HWUART */
-		up->mcr |= UART_MCR_AFE;
-	else
-		up->mcr = 0;
-
-	up->port.uartclk = clk_get_rate(up->clk);
-
-	/*
-	 * Allocate the IRQ
-	 */
-	retval = request_irq(up->port.irq, serial_pxa_irq, 0, up->name, up);
-	if (retval)
-		return retval;
-
-	/*
-	 * Clear the FIFO buffers and disable them.
-	 * (they will be reenabled in set_termios())
-	 */
-	serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO);
-	serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO |
-			UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
-	serial_out(up, UART_FCR, 0);
-
-	/*
-	 * Clear the interrupt registers.
-	 */
-	(void) serial_in(up, UART_LSR);
-	(void) serial_in(up, UART_RX);
-	(void) serial_in(up, UART_IIR);
-	(void) serial_in(up, UART_MSR);
-
-	/*
-	 * Now, initialize the UART
-	 */
-	serial_out(up, UART_LCR, UART_LCR_WLEN8);
-
-	spin_lock_irqsave(&up->port.lock, flags);
-	up->port.mctrl |= TIOCM_OUT2;
-	serial_pxa_set_mctrl(&up->port, up->port.mctrl);
-	spin_unlock_irqrestore(&up->port.lock, flags);
-
-	/*
-	 * Finally, enable interrupts.  Note: Modem status interrupts
-	 * are set via set_termios(), which will be occurring imminently
-	 * anyway, so we don't enable them here.
-	 */
-	up->ier = UART_IER_RLSI | UART_IER_RDI | UART_IER_RTOIE | UART_IER_UUE;
-	serial_out(up, UART_IER, up->ier);
-
-	/*
-	 * And clear the interrupt registers again for luck.
-	 */
-	(void) serial_in(up, UART_LSR);
-	(void) serial_in(up, UART_RX);
-	(void) serial_in(up, UART_IIR);
-	(void) serial_in(up, UART_MSR);
-
-	return 0;
-}
-
-static void serial_pxa_shutdown(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned long flags;
-
-	free_irq(up->port.irq, up);
-
-	/*
-	 * Disable interrupts from this port
-	 */
-	up->ier = 0;
-	serial_out(up, UART_IER, 0);
-
-	spin_lock_irqsave(&up->port.lock, flags);
-	up->port.mctrl &= ~TIOCM_OUT2;
-	serial_pxa_set_mctrl(&up->port, up->port.mctrl);
-	spin_unlock_irqrestore(&up->port.lock, flags);
-
-	/*
-	 * Disable break condition and FIFOs
-	 */
-	serial_out(up, UART_LCR, serial_in(up, UART_LCR) & ~UART_LCR_SBC);
-	serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO |
-				  UART_FCR_CLEAR_RCVR |
-				  UART_FCR_CLEAR_XMIT);
-	serial_out(up, UART_FCR, 0);
-}
-
-static void
-serial_pxa_set_termios(struct uart_port *port, struct ktermios *termios,
-		       struct ktermios *old)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned char cval, fcr = 0;
-	unsigned long flags;
-	unsigned int baud, quot;
-	unsigned int dll;
-
-	switch (termios->c_cflag & CSIZE) {
-	case CS5:
-		cval = UART_LCR_WLEN5;
-		break;
-	case CS6:
-		cval = UART_LCR_WLEN6;
-		break;
-	case CS7:
-		cval = UART_LCR_WLEN7;
-		break;
-	default:
-	case CS8:
-		cval = UART_LCR_WLEN8;
-		break;
-	}
-
-	if (termios->c_cflag & CSTOPB)
-		cval |= UART_LCR_STOP;
-	if (termios->c_cflag & PARENB)
-		cval |= UART_LCR_PARITY;
-	if (!(termios->c_cflag & PARODD))
-		cval |= UART_LCR_EPAR;
-
-	/*
-	 * Ask the core to calculate the divisor for us.
-	 */
-	baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
-	quot = uart_get_divisor(port, baud);
-
-	if ((up->port.uartclk / quot) < (2400 * 16))
-		fcr = UART_FCR_ENABLE_FIFO | UART_FCR_PXAR1;
-	else if ((up->port.uartclk / quot) < (230400 * 16))
-		fcr = UART_FCR_ENABLE_FIFO | UART_FCR_PXAR8;
-	else
-		fcr = UART_FCR_ENABLE_FIFO | UART_FCR_PXAR32;
-
-	/*
-	 * Ok, we're now changing the port state.  Do it with
-	 * interrupts disabled.
-	 */
-	spin_lock_irqsave(&up->port.lock, flags);
-
-	/*
-	 * Ensure the port will be enabled.
-	 * This is required especially for serial console.
-	 */
-	up->ier |= UART_IER_UUE;
-
-	/*
-	 * Update the per-port timeout.
-	 */
-	uart_update_timeout(port, termios->c_cflag, baud);
-
-	up->port.read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;
-	if (termios->c_iflag & INPCK)
-		up->port.read_status_mask |= UART_LSR_FE | UART_LSR_PE;
-	if (termios->c_iflag & (BRKINT | PARMRK))
-		up->port.read_status_mask |= UART_LSR_BI;
-
-	/*
-	 * Characters to ignore
-	 */
-	up->port.ignore_status_mask = 0;
-	if (termios->c_iflag & IGNPAR)
-		up->port.ignore_status_mask |= UART_LSR_PE | UART_LSR_FE;
-	if (termios->c_iflag & IGNBRK) {
-		up->port.ignore_status_mask |= UART_LSR_BI;
-		/*
-		 * If we're ignoring parity and break indicators,
-		 * ignore overruns too (for real raw support).
-		 */
-		if (termios->c_iflag & IGNPAR)
-			up->port.ignore_status_mask |= UART_LSR_OE;
-	}
-
-	/*
-	 * ignore all characters if CREAD is not set
-	 */
-	if ((termios->c_cflag & CREAD) == 0)
-		up->port.ignore_status_mask |= UART_LSR_DR;
-
-	/*
-	 * CTS flow control flag and modem status interrupts
-	 */
-	up->ier &= ~UART_IER_MSI;
-	if (UART_ENABLE_MS(&up->port, termios->c_cflag))
-		up->ier |= UART_IER_MSI;
-
-	serial_out(up, UART_IER, up->ier);
-
-	if (termios->c_cflag & CRTSCTS)
-		up->mcr |= UART_MCR_AFE;
-	else
-		up->mcr &= ~UART_MCR_AFE;
-
-	serial_out(up, UART_LCR, cval | UART_LCR_DLAB);	/* set DLAB */
-	serial_out(up, UART_DLL, quot & 0xff);		/* LS of divisor */
-
-	/*
-	 * work around Errata #75 according to Intel(R) PXA27x Processor Family
-	 * Specification Update (Nov 2005)
-	 */
-	dll = serial_in(up, UART_DLL);
-	WARN_ON(dll != (quot & 0xff));
-
-	serial_out(up, UART_DLM, quot >> 8);		/* MS of divisor */
-	serial_out(up, UART_LCR, cval);			/* reset DLAB */
-	up->lcr = cval;					/* Save LCR */
-	serial_pxa_set_mctrl(&up->port, up->port.mctrl);
-	serial_out(up, UART_FCR, fcr);
-	spin_unlock_irqrestore(&up->port.lock, flags);
-}
-
-static void
-serial_pxa_pm(struct uart_port *port, unsigned int state,
-	      unsigned int oldstate)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	if (!state)
-		clk_prepare_enable(up->clk);
-	else
-		clk_disable_unprepare(up->clk);
-}
-
-static void serial_pxa_release_port(struct uart_port *port)
-{
-}
-
-static int serial_pxa_request_port(struct uart_port *port)
-{
-	return 0;
-}
-
-static void serial_pxa_config_port(struct uart_port *port, int flags)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	up->port.type = PORT_PXA;
-}
-
-static int
-serial_pxa_verify_port(struct uart_port *port, struct serial_struct *ser)
-{
-	/* we don't want the core code to modify any port params */
-	return -EINVAL;
-}
-
-static const char *
-serial_pxa_type(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	return up->name;
-}
-
-static struct uart_pxa_port *serial_pxa_ports[4];
-static struct uart_driver serial_pxa_reg;
-
-#ifdef CONFIG_SERIAL_PXA_CONSOLE
-
-#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
-
-/*
- *	Wait for transmitter & holding register to empty
- */
-static inline void wait_for_xmitr(struct uart_pxa_port *up)
-{
-	unsigned int status, tmout = 10000;
-
-	/* Wait up to 10ms for the character(s) to be sent. */
-	do {
-		status = serial_in(up, UART_LSR);
-
-		if (status & UART_LSR_BI)
-			up->lsr_break_flag = UART_LSR_BI;
-
-		if (--tmout == 0)
-			break;
-		udelay(1);
-	} while ((status & BOTH_EMPTY) != BOTH_EMPTY);
-
-	/* Wait up to 1s for flow control if necessary */
-	if (up->port.flags & UPF_CONS_FLOW) {
-		tmout = 1000000;
-		while (--tmout &&
-		       ((serial_in(up, UART_MSR) & UART_MSR_CTS) == 0))
-			udelay(1);
-	}
-}
-
-static void serial_pxa_console_putchar(struct uart_port *port, int ch)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	wait_for_xmitr(up);
-	serial_out(up, UART_TX, ch);
-}
-
-/*
- * Print a string to the serial port trying not to disturb
- * any possible real use of the port...
- *
- *	The console_lock must be held when we get here.
- */
-static void
-serial_pxa_console_write(struct console *co, const char *s, unsigned int count)
-{
-	struct uart_pxa_port *up = serial_pxa_ports[co->index];
-	unsigned int ier;
-	unsigned long flags;
-	int locked = 1;
-
-	clk_enable(up->clk);
-	local_irq_save(flags);
-	if (up->port.sysrq)
-		locked = 0;
-	else if (oops_in_progress)
-		locked = spin_trylock(&up->port.lock);
-	else
-		spin_lock(&up->port.lock);
-
-	/*
-	 *	First save the IER then disable the interrupts
-	 */
-	ier = serial_in(up, UART_IER);
-	serial_out(up, UART_IER, UART_IER_UUE);
-
-	uart_console_write(&up->port, s, count, serial_pxa_console_putchar);
-
-	/*
-	 *	Finally, wait for transmitter to become empty
-	 *	and restore the IER
-	 */
-	wait_for_xmitr(up);
-	serial_out(up, UART_IER, ier);
-
-	if (locked)
-		spin_unlock(&up->port.lock);
-	local_irq_restore(flags);
-	clk_disable(up->clk);
-
-}
-
-#ifdef CONFIG_CONSOLE_POLL
-/*
- * Console polling routines for writing and reading from the uart while
- * in an interrupt or debug context.
- */
-
-static int serial_pxa_get_poll_char(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned char lsr = serial_in(up, UART_LSR);
-
-	while (!(lsr & UART_LSR_DR))
-		lsr = serial_in(up, UART_LSR);
-
-	return serial_in(up, UART_RX);
-}
-
-
-static void serial_pxa_put_poll_char(struct uart_port *port,
-			 unsigned char c)
-{
-	unsigned int ier;
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	/*
-	 *	First save the IER then disable the interrupts
-	 */
-	ier = serial_in(up, UART_IER);
-	serial_out(up, UART_IER, UART_IER_UUE);
-
-	wait_for_xmitr(up);
-	/*
-	 *	Send the character out.
-	 *	If a LF, also do CR...
-	 */
-	serial_out(up, UART_TX, c);
-	if (c == 10) {
-		wait_for_xmitr(up);
-		serial_out(up, UART_TX, 13);
-	}
-
-	/*
-	 *	Finally, wait for transmitter to become empty
-	 *	and restore the IER
-	 */
-	wait_for_xmitr(up);
-	serial_out(up, UART_IER, ier);
-}
-
-#endif /* CONFIG_CONSOLE_POLL */
-
-static int __init
-serial_pxa_console_setup(struct console *co, char *options)
-{
-	struct uart_pxa_port *up;
-	int baud = 9600;
-	int bits = 8;
-	int parity = 'n';
-	int flow = 'n';
-
-	if (co->index == -1 || co->index >= serial_pxa_reg.nr)
-		co->index = 0;
-	up = serial_pxa_ports[co->index];
-	if (!up)
-		return -ENODEV;
-
-	if (options)
-		uart_parse_options(options, &baud, &parity, &bits, &flow);
-
-	return uart_set_options(&up->port, co, baud, parity, bits, flow);
-}
-
-static struct console serial_pxa_console = {
-	.name		= "ttyS",
-	.write		= serial_pxa_console_write,
-	.device		= uart_console_device,
-	.setup		= serial_pxa_console_setup,
-	.flags		= CON_PRINTBUFFER,
-	.index		= -1,
-	.data		= &serial_pxa_reg,
-};
-
-#define PXA_CONSOLE	&serial_pxa_console
-#else
-#define PXA_CONSOLE	NULL
-#endif
-
-static struct uart_ops serial_pxa_pops = {
-	.tx_empty	= serial_pxa_tx_empty,
-	.set_mctrl	= serial_pxa_set_mctrl,
-	.get_mctrl	= serial_pxa_get_mctrl,
-	.stop_tx	= serial_pxa_stop_tx,
-	.start_tx	= serial_pxa_start_tx,
-	.stop_rx	= serial_pxa_stop_rx,
-	.enable_ms	= serial_pxa_enable_ms,
-	.break_ctl	= serial_pxa_break_ctl,
-	.startup	= serial_pxa_startup,
-	.shutdown	= serial_pxa_shutdown,
-	.set_termios	= serial_pxa_set_termios,
-	.pm		= serial_pxa_pm,
-	.type		= serial_pxa_type,
-	.release_port	= serial_pxa_release_port,
-	.request_port	= serial_pxa_request_port,
-	.config_port	= serial_pxa_config_port,
-	.verify_port	= serial_pxa_verify_port,
-#ifdef CONFIG_CONSOLE_POLL
-	.poll_get_char = serial_pxa_get_poll_char,
-	.poll_put_char = serial_pxa_put_poll_char,
-#endif
-};
-
-static struct uart_driver serial_pxa_reg = {
-	.owner		= THIS_MODULE,
-	.driver_name	= "PXA serial",
-	.dev_name	= "ttyS",
-	.major		= TTY_MAJOR,
-	.minor		= 64,
-	.nr		= 4,
-	.cons		= PXA_CONSOLE,
-};
-
-#ifdef CONFIG_PM
-static int serial_pxa_suspend(struct device *dev)
-{
-        struct uart_pxa_port *sport = dev_get_drvdata(dev);
-
-        if (sport)
-                uart_suspend_port(&serial_pxa_reg, &sport->port);
-
-        return 0;
-}
-
-static int serial_pxa_resume(struct device *dev)
-{
-        struct uart_pxa_port *sport = dev_get_drvdata(dev);
-
-        if (sport)
-                uart_resume_port(&serial_pxa_reg, &sport->port);
-
-        return 0;
-}
-
-static const struct dev_pm_ops serial_pxa_pm_ops = {
-	.suspend	= serial_pxa_suspend,
-	.resume		= serial_pxa_resume,
-};
-#endif
-
-static struct of_device_id serial_pxa_dt_ids[] = {
-	{ .compatible = "mrvl,pxa-uart", },
-	{ .compatible = "mrvl,mmp-uart", },
-	{}
-};
-MODULE_DEVICE_TABLE(of, serial_pxa_dt_ids);
-
-static int serial_pxa_probe_dt(struct platform_device *pdev,
-			       struct uart_pxa_port *sport)
-{
-	struct device_node *np = pdev->dev.of_node;
-	int ret;
-
-	if (!np)
-		return 1;
-
-	ret = of_alias_get_id(np, "serial");
-	if (ret < 0) {
-		dev_err(&pdev->dev, "failed to get alias id, errno %d\n", ret);
-		return ret;
-	}
-	sport->port.line = ret;
-	return 0;
-}
-
-static int serial_pxa_probe(struct platform_device *dev)
-{
-	struct uart_pxa_port *sport;
-	struct resource *mmres, *irqres;
-	int ret;
-
-	mmres = platform_get_resource(dev, IORESOURCE_MEM, 0);
-	irqres = platform_get_resource(dev, IORESOURCE_IRQ, 0);
-	if (!mmres || !irqres)
-		return -ENODEV;
-
-	sport = kzalloc(sizeof(struct uart_pxa_port), GFP_KERNEL);
-	if (!sport)
-		return -ENOMEM;
-
-	sport->clk = clk_get(&dev->dev, NULL);
-	if (IS_ERR(sport->clk)) {
-		ret = PTR_ERR(sport->clk);
-		goto err_free;
-	}
-
-	ret = clk_prepare(sport->clk);
-	if (ret) {
-		clk_put(sport->clk);
-		goto err_free;
-	}
-
-	sport->port.type = PORT_PXA;
-	sport->port.iotype = UPIO_MEM;
-	sport->port.mapbase = mmres->start;
-	sport->port.irq = irqres->start;
-	sport->port.fifosize = 64;
-	sport->port.ops = &serial_pxa_pops;
-	sport->port.dev = &dev->dev;
-	sport->port.flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF;
-	sport->port.uartclk = clk_get_rate(sport->clk);
-
-	ret = serial_pxa_probe_dt(dev, sport);
-	if (ret > 0)
-		sport->port.line = dev->id;
-	else if (ret < 0)
-		goto err_clk;
-	snprintf(sport->name, PXA_NAME_LEN - 1, "UART%d", sport->port.line + 1);
-
-	sport->port.membase = ioremap(mmres->start, resource_size(mmres));
-	if (!sport->port.membase) {
-		ret = -ENOMEM;
-		goto err_clk;
-	}
-
-	serial_pxa_ports[sport->port.line] = sport;
-
-	uart_add_one_port(&serial_pxa_reg, &sport->port);
-	platform_set_drvdata(dev, sport);
-
-	return 0;
-
- err_clk:
-	clk_unprepare(sport->clk);
-	clk_put(sport->clk);
- err_free:
-	kfree(sport);
-	return ret;
-}
-
-static int serial_pxa_remove(struct platform_device *dev)
-{
-	struct uart_pxa_port *sport = platform_get_drvdata(dev);
-
-	uart_remove_one_port(&serial_pxa_reg, &sport->port);
-
-	clk_unprepare(sport->clk);
-	clk_put(sport->clk);
-	kfree(sport);
-
-	return 0;
-}
-
-static struct platform_driver serial_pxa_driver = {
-        .probe          = serial_pxa_probe,
-        .remove         = serial_pxa_remove,
-
-	.driver		= {
-	        .name	= "pxa2xx-uart",
-		.owner	= THIS_MODULE,
-#ifdef CONFIG_PM
-		.pm	= &serial_pxa_pm_ops,
-#endif
-		.of_match_table = serial_pxa_dt_ids,
-	},
-};
-
-static int __init serial_pxa_init(void)
-{
-	int ret;
-
-	ret = uart_register_driver(&serial_pxa_reg);
-	if (ret != 0)
-		return ret;
-
-	ret = platform_driver_register(&serial_pxa_driver);
-	if (ret != 0)
-		uart_unregister_driver(&serial_pxa_reg);
-
-	return ret;
-}
-
-static void __exit serial_pxa_exit(void)
-{
-	platform_driver_unregister(&serial_pxa_driver);
-	uart_unregister_driver(&serial_pxa_reg);
-}
-
-module_init(serial_pxa_init);
-module_exit(serial_pxa_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:pxa2xx-uart");
-- 
1.8.4.2

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

* [PATCH v2] serial: rewrite pxa2xx-uart to use 8250_core
@ 2013-12-06  9:09                       ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-06  9:09 UTC (permalink / raw)
  To: linux-arm-kernel

pxa2xx-uart was a separate uart platform driver. It was declaring
the same device names and numbers as 8250 driver. As a result,
it was impossible to use 8250 driver on PXA SoCs.

Upon closer examination pxa2xx-uart turned out to be a clone of
8250_core driver.

Workaround for Erratum #19 according to Marvel(R) PXA270M Processor
Specification Update (April 19, 2010) is dropped. 8250_core reads
from FIFO immediately after checking DR bit in LSR.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Heikki Krogerus <heikki.krogerus@linux.intel.com>
CC: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
CC: James Cameron <quozl@laptop.org>
---
 changes v1..v2
 * actually implement workaround for E74 in dl_write as spooted
   by James Cameron
 * added comment about E19 in commit message

 arch/arm/configs/am200epdkit_defconfig    |   3 +-
 arch/arm/configs/cm_x2xx_defconfig        |   3 +-
 arch/arm/configs/cm_x300_defconfig        |   3 +-
 arch/arm/configs/colibri_pxa270_defconfig |   3 +-
 arch/arm/configs/colibri_pxa300_defconfig |   3 +-
 arch/arm/configs/corgi_defconfig          |   4 +-
 arch/arm/configs/em_x270_defconfig        |   3 +-
 arch/arm/configs/ezx_defconfig            |   3 +-
 arch/arm/configs/h5000_defconfig          |   3 +-
 arch/arm/configs/imote2_defconfig         |   3 +-
 arch/arm/configs/lpd270_defconfig         |   3 +-
 arch/arm/configs/lubbock_defconfig        |   3 +-
 arch/arm/configs/mainstone_defconfig      |   3 +-
 arch/arm/configs/mmp2_defconfig           |   3 +-
 arch/arm/configs/pcm027_defconfig         |   3 +-
 arch/arm/configs/pxa168_defconfig         |   3 +-
 arch/arm/configs/pxa255-idp_defconfig     |   3 +-
 arch/arm/configs/pxa3xx_defconfig         |   3 +-
 arch/arm/configs/pxa910_defconfig         |   3 +-
 arch/arm/configs/raumfeld_defconfig       |   3 +-
 arch/arm/configs/spitz_defconfig          |   4 +-
 arch/arm/configs/trizeps4_defconfig       |   3 +-
 arch/arm/configs/viper_defconfig          |   4 +-
 arch/arm/configs/xcep_defconfig           |   3 +-
 drivers/tty/serial/8250/8250_pxa.c        | 189 ++++++
 drivers/tty/serial/8250/Kconfig           |   9 +
 drivers/tty/serial/8250/Makefile          |   1 +
 drivers/tty/serial/Kconfig                |  23 -
 drivers/tty/serial/Makefile               |   1 -
 drivers/tty/serial/pxa.c                  | 971 ------------------------------
 30 files changed, 247 insertions(+), 1022 deletions(-)
 create mode 100644 drivers/tty/serial/8250/8250_pxa.c
 delete mode 100644 drivers/tty/serial/pxa.c

diff --git a/arch/arm/configs/am200epdkit_defconfig b/arch/arm/configs/am200epdkit_defconfig
index f0dea52..0cde234 100644
--- a/arch/arm/configs/am200epdkit_defconfig
+++ b/arch/arm/configs/am200epdkit_defconfig
@@ -60,8 +60,9 @@ CONFIG_BLK_DEV_IDECS=m
 CONFIG_NETDEVICES=y
 CONFIG_NET_ETHERNET=y
 CONFIG_SMC91X=m
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 # CONFIG_HWMON is not set
diff --git a/arch/arm/configs/cm_x2xx_defconfig b/arch/arm/configs/cm_x2xx_defconfig
index a93ff8d..b9fbe65 100644
--- a/arch/arm/configs/cm_x2xx_defconfig
+++ b/arch/arm/configs/cm_x2xx_defconfig
@@ -96,8 +96,9 @@ CONFIG_KEYBOARD_PXA27x=m
 CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_TOUCHSCREEN_UCB1400=m
 # CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_LEGACY_PTY_COUNT=16
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/cm_x300_defconfig b/arch/arm/configs/cm_x300_defconfig
index f4b7672..53a82ae 100644
--- a/arch/arm/configs/cm_x300_defconfig
+++ b/arch/arm/configs/cm_x300_defconfig
@@ -80,8 +80,9 @@ CONFIG_TOUCHSCREEN_WM97XX=m
 # CONFIG_TOUCHSCREEN_WM9713 is not set
 # CONFIG_SERIO is not set
 # CONFIG_LEGACY_PTYS is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
 CONFIG_I2C_PXA=y
diff --git a/arch/arm/configs/colibri_pxa270_defconfig b/arch/arm/configs/colibri_pxa270_defconfig
index 2ef2c5e..1ce0409 100644
--- a/arch/arm/configs/colibri_pxa270_defconfig
+++ b/arch/arm/configs/colibri_pxa270_defconfig
@@ -103,8 +103,9 @@ CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=m
 CONFIG_SERIO_LIBPS2=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_HW_RANDOM=y
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
diff --git a/arch/arm/configs/colibri_pxa300_defconfig b/arch/arm/configs/colibri_pxa300_defconfig
index b985334..f96bda0 100644
--- a/arch/arm/configs/colibri_pxa300_defconfig
+++ b/arch/arm/configs/colibri_pxa300_defconfig
@@ -31,8 +31,9 @@ CONFIG_INPUT_EVDEV=y
 # CONFIG_INPUT_MOUSE is not set
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_GPIO_ROTARY_ENCODER=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_HW_RANDOM=y
 CONFIG_DEBUG_GPIO=y
 # CONFIG_HWMON is not set
diff --git a/arch/arm/configs/corgi_defconfig b/arch/arm/configs/corgi_defconfig
index 1fd1d1d..bb4842d 100644
--- a/arch/arm/configs/corgi_defconfig
+++ b/arch/arm/configs/corgi_defconfig
@@ -131,10 +131,10 @@ CONFIG_TOUCHSCREEN_ADS7846=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=m
 # CONFIG_SERIO is not set
-CONFIG_SERIAL_8250=m
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_CS=m
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 CONFIG_I2C=y
 CONFIG_I2C_PXA=y
diff --git a/arch/arm/configs/em_x270_defconfig b/arch/arm/configs/em_x270_defconfig
index 60a21e0..ec0ec54 100644
--- a/arch/arm/configs/em_x270_defconfig
+++ b/arch/arm/configs/em_x270_defconfig
@@ -90,8 +90,9 @@ CONFIG_TOUCHSCREEN_WM97XX=m
 # CONFIG_TOUCHSCREEN_WM9705 is not set
 # CONFIG_TOUCHSCREEN_WM9713 is not set
 # CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_LEGACY_PTY_COUNT=16
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/ezx_defconfig b/arch/arm/configs/ezx_defconfig
index d95763d..631e2ec 100644
--- a/arch/arm/configs/ezx_defconfig
+++ b/arch/arm/configs/ezx_defconfig
@@ -215,8 +215,9 @@ CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=y
 CONFIG_INPUT_PCAP=y
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_LEGACY_PTY_COUNT=8
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/h5000_defconfig b/arch/arm/configs/h5000_defconfig
index 37903e3..655b735 100644
--- a/arch/arm/configs/h5000_defconfig
+++ b/arch/arm/configs/h5000_defconfig
@@ -47,8 +47,9 @@ CONFIG_MTD_PHYSMAP=y
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_LEGACY_PTY_COUNT=32
 # CONFIG_HW_RANDOM is not set
 # CONFIG_HWMON is not set
diff --git a/arch/arm/configs/imote2_defconfig b/arch/arm/configs/imote2_defconfig
index fd996bb..49d45e9 100644
--- a/arch/arm/configs/imote2_defconfig
+++ b/arch/arm/configs/imote2_defconfig
@@ -193,8 +193,9 @@ CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=y
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_LEGACY_PTY_COUNT=8
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/lpd270_defconfig b/arch/arm/configs/lpd270_defconfig
index 1c8c9ee..c3927b6 100644
--- a/arch/arm/configs/lpd270_defconfig
+++ b/arch/arm/configs/lpd270_defconfig
@@ -38,8 +38,9 @@ CONFIG_SMC91X=y
 CONFIG_INPUT_EVDEV=y
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_HW_RANDOM is not set
 CONFIG_FB=y
 CONFIG_FB_PXA=y
diff --git a/arch/arm/configs/lubbock_defconfig b/arch/arm/configs/lubbock_defconfig
index c4ba274..c8b0436 100644
--- a/arch/arm/configs/lubbock_defconfig
+++ b/arch/arm/configs/lubbock_defconfig
@@ -37,8 +37,9 @@ CONFIG_PCMCIA_PCNET=y
 CONFIG_INPUT_EVDEV=y
 # CONFIG_SERIO_SERPORT is not set
 CONFIG_SERIO_SA1111=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_USB_GADGET=y
 CONFIG_USB_G_SERIAL=m
diff --git a/arch/arm/configs/mainstone_defconfig b/arch/arm/configs/mainstone_defconfig
index 04efa1b..768892c 100644
--- a/arch/arm/configs/mainstone_defconfig
+++ b/arch/arm/configs/mainstone_defconfig
@@ -34,8 +34,9 @@ CONFIG_SMC91X=y
 CONFIG_INPUT_EVDEV=y
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_FB=y
 CONFIG_FB_PXA=y
 # CONFIG_VGA_CONSOLE is not set
diff --git a/arch/arm/configs/mmp2_defconfig b/arch/arm/configs/mmp2_defconfig
index f1cb95e..1ced9df 100644
--- a/arch/arm/configs/mmp2_defconfig
+++ b/arch/arm/configs/mmp2_defconfig
@@ -44,8 +44,9 @@ CONFIG_SMC91X=y
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/pcm027_defconfig b/arch/arm/configs/pcm027_defconfig
index 2f136c3..1280128 100644
--- a/arch/arm/configs/pcm027_defconfig
+++ b/arch/arm/configs/pcm027_defconfig
@@ -60,8 +60,9 @@ CONFIG_SMC91X=y
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/pxa168_defconfig b/arch/arm/configs/pxa168_defconfig
index 74d7e01..1668dac 100644
--- a/arch/arm/configs/pxa168_defconfig
+++ b/arch/arm/configs/pxa168_defconfig
@@ -40,8 +40,9 @@ CONFIG_SMC91X=y
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 # CONFIG_HWMON is not set
diff --git a/arch/arm/configs/pxa255-idp_defconfig b/arch/arm/configs/pxa255-idp_defconfig
index 917a070..399a706 100644
--- a/arch/arm/configs/pxa255-idp_defconfig
+++ b/arch/arm/configs/pxa255-idp_defconfig
@@ -35,8 +35,9 @@ CONFIG_SMC91X=y
 CONFIG_INPUT_EVDEV=y
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_FB=y
 CONFIG_FB_PXA=y
 # CONFIG_VGA_CONSOLE is not set
diff --git a/arch/arm/configs/pxa3xx_defconfig b/arch/arm/configs/pxa3xx_defconfig
index 60e3138..7c3e052 100644
--- a/arch/arm/configs/pxa3xx_defconfig
+++ b/arch/arm/configs/pxa3xx_defconfig
@@ -56,8 +56,9 @@ CONFIG_KEYBOARD_PXA27x=y
 CONFIG_KEYBOARD_PXA930_ROTARY=y
 CONFIG_MOUSE_PXA930_TRKBALL=y
 CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/pxa910_defconfig b/arch/arm/configs/pxa910_defconfig
index 3bb7771..cdacfcb 100644
--- a/arch/arm/configs/pxa910_defconfig
+++ b/arch/arm/configs/pxa910_defconfig
@@ -40,8 +40,9 @@ CONFIG_SMC91X=y
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_SPI=y
 CONFIG_FB=y
 CONFIG_MMP_DISP=y
diff --git a/arch/arm/configs/raumfeld_defconfig b/arch/arm/configs/raumfeld_defconfig
index f7caa90..f1e16f2 100644
--- a/arch/arm/configs/raumfeld_defconfig
+++ b/arch/arm/configs/raumfeld_defconfig
@@ -67,8 +67,9 @@ CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_TOUCHSCREEN_EETI=m
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_GPIO_ROTARY_ENCODER=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_HW_RANDOM=y
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
diff --git a/arch/arm/configs/spitz_defconfig b/arch/arm/configs/spitz_defconfig
index 2e0419d..b6efcf5 100644
--- a/arch/arm/configs/spitz_defconfig
+++ b/arch/arm/configs/spitz_defconfig
@@ -128,10 +128,10 @@ CONFIG_TOUCHSCREEN_ADS7846=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=m
 # CONFIG_SERIO is not set
-CONFIG_SERIAL_8250=m
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_CS=m
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 CONFIG_SPI=y
 CONFIG_SPI_PXA2XX=y
diff --git a/arch/arm/configs/trizeps4_defconfig b/arch/arm/configs/trizeps4_defconfig
index 3162173..453c79c 100644
--- a/arch/arm/configs/trizeps4_defconfig
+++ b/arch/arm/configs/trizeps4_defconfig
@@ -132,8 +132,9 @@ CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=m
 CONFIG_SERIO_LIBPS2=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_HW_RANDOM=y
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
diff --git a/arch/arm/configs/viper_defconfig b/arch/arm/configs/viper_defconfig
index d36e0d3..4efac06 100644
--- a/arch/arm/configs/viper_defconfig
+++ b/arch/arm/configs/viper_defconfig
@@ -101,11 +101,11 @@ CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=m
 # CONFIG_CONSOLE_TRANSLATIONS is not set
 # CONFIG_VT_CONSOLE is not set
-CONFIG_SERIAL_8250=m
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_NR_UARTS=5
 CONFIG_SERIAL_8250_RUNTIME_UARTS=5
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
diff --git a/arch/arm/configs/xcep_defconfig b/arch/arm/configs/xcep_defconfig
index 721832f..b67aeaf 100644
--- a/arch/arm/configs/xcep_defconfig
+++ b/arch/arm/configs/xcep_defconfig
@@ -60,8 +60,9 @@ CONFIG_NET_ETHERNET=y
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
 # CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=m
diff --git a/drivers/tty/serial/8250/8250_pxa.c b/drivers/tty/serial/8250/8250_pxa.c
new file mode 100644
index 0000000..88ae73c
--- /dev/null
+++ b/drivers/tty/serial/8250/8250_pxa.c
@@ -0,0 +1,189 @@
+/*
+ *  drivers/tty/serial/8250/8250_pxa.c -- driver for PXA on-board UARTS
+ *  Copyright:	(C) 2013 Sergei Ianovich <ynvich@gmail.com>
+ *
+ *  replaces drivers/serial/pxa.c by Nicolas Pitre
+ *  Created:	Feb 20, 2003
+ *  Copyright:	(C) 2003 Monta Vista Software, Inc.
+ *
+ *  Based on drivers/serial/8250.c by Russell King.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/serial_8250.h>
+#include <linux/serial_core.h>
+#include <linux/serial_reg.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
+#include <linux/pm_runtime.h>
+
+#include "8250.h"
+
+struct pxa8250_data {
+	int			line;
+	struct clk		*clk;
+};
+
+#ifdef CONFIG_PM
+static int serial_pxa_suspend(struct device *dev)
+{
+	struct pxa8250_data *data = dev_get_drvdata(dev);
+
+	serial8250_suspend_port(data->line);
+
+	return 0;
+}
+
+static int serial_pxa_resume(struct device *dev)
+{
+	struct pxa8250_data *data = dev_get_drvdata(dev);
+
+	serial8250_resume_port(data->line);
+
+	return 0;
+}
+
+static const struct dev_pm_ops serial_pxa_pm_ops = {
+	.suspend	= serial_pxa_suspend,
+	.resume		= serial_pxa_resume,
+};
+#endif
+
+static struct of_device_id serial_pxa_dt_ids[] = {
+	{ .compatible = "mrvl,pxa-uart", },
+	{ .compatible = "mrvl,mmp-uart", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, serial_pxa_dt_ids);
+
+/* Uart divisor latch write */
+static void serial_pxa_dl_write(struct uart_8250_port *up, int value)
+{
+	unsigned int dll;
+
+	serial_out(up, UART_DLL, value & 0xff);
+	/*
+	 * work around Erratum #74 according to Marvel(R) PXA270M Processor
+	 * Specification Update (April 19, 2010)
+	 */
+	dll = serial_in(up, UART_DLL);
+	WARN_ON(dll != (value & 0xff));
+
+	serial_out(up, UART_DLM, value >> 8 & 0xff);
+}
+
+
+static void serial_pxa_pm(struct uart_port *port, unsigned int state,
+	      unsigned int oldstate)
+{
+	struct pxa8250_data *data = port->private_data;
+
+	if (!state)
+		clk_prepare_enable(data->clk);
+	else
+		clk_disable_unprepare(data->clk);
+}
+
+static int serial_pxa_probe(struct platform_device *pdev)
+{
+	struct uart_8250_port uart = {};
+	struct pxa8250_data *data;
+	struct resource *mmres, *irqres;
+	int ret;
+
+	mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	irqres = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!mmres || !irqres)
+		return -ENODEV;
+
+	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(data->clk)) {
+		ret = PTR_ERR(data->clk);
+		goto err_free;
+	}
+
+	ret = clk_prepare(data->clk);
+	if (ret)
+		goto err_free_clk;
+
+	uart.port.type = PORT_XSCALE;
+	uart.port.iotype = UPIO_MEM32;
+	uart.port.mapbase = mmres->start;
+	uart.port.regshift = 2;
+	uart.port.irq = irqres->start;
+	uart.port.fifosize = 64;
+	uart.port.flags = UPF_IOREMAP | UPF_SKIP_TEST;
+	uart.port.dev = &pdev->dev;
+	uart.port.uartclk = clk_get_rate(data->clk);
+	uart.port.pm = serial_pxa_pm;
+	uart.port.private_data = data;
+	uart.dl_write = serial_pxa_dl_write;
+
+	ret = serial8250_register_8250_port(&uart);
+	if (ret < 0)
+		goto err_clk;
+
+	data->line = ret;
+
+	platform_set_drvdata(pdev, data);
+
+	return 0;
+
+ err_clk:
+	clk_unprepare(data->clk);
+ err_free_clk:
+	devm_clk_put(&pdev->dev, data->clk);
+ err_free:
+	devm_kfree(&pdev->dev, data);
+	return ret;
+}
+
+static int serial_pxa_remove(struct platform_device *pdev)
+{
+	struct pxa8250_data *data = platform_get_drvdata(pdev);
+
+	serial8250_unregister_port(data->line);
+
+	clk_unprepare(data->clk);
+	devm_clk_put(&pdev->dev, data->clk);
+	devm_kfree(&pdev->dev, data);
+
+	return 0;
+}
+
+static struct platform_driver serial_pxa_driver = {
+	.probe          = serial_pxa_probe,
+	.remove         = serial_pxa_remove,
+
+	.driver		= {
+		.name	= "pxa2xx-uart",
+		.owner	= THIS_MODULE,
+#ifdef CONFIG_PM
+		.pm	= &serial_pxa_pm_ops,
+#endif
+		.of_match_table = serial_pxa_dt_ids,
+	},
+};
+
+module_platform_driver(serial_pxa_driver);
+
+MODULE_AUTHOR("Sergei Ianovich");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:pxa2xx-uart");
diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
index 2332991..81bd7c9 100644
--- a/drivers/tty/serial/8250/Kconfig
+++ b/drivers/tty/serial/8250/Kconfig
@@ -302,3 +302,12 @@ config SERIAL_8250_RT288X
 	  If you have a Ralink RT288x/RT305x SoC based board and want to use the
 	  serial port, say Y to this option. The driver can handle up to 2 serial
 	  ports. If unsure, say N.
+
+config SERIAL_PXA
+	tristate "PXA serial port support"
+	depends on SERIAL_8250 && (ARCH_PXA || ARCH_MMP)
+	help
+	  If you have a machine based on an Intel XScale PXA2xx CPU you
+	  can enable its onboard serial ports by enabling this option.
+
+	  If you choose M here, the module name will be 8250_pxa.
diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile
index 36d68d0..b7d1b61 100644
--- a/drivers/tty/serial/8250/Makefile
+++ b/drivers/tty/serial/8250/Makefile
@@ -20,3 +20,4 @@ obj-$(CONFIG_SERIAL_8250_HUB6)		+= 8250_hub6.o
 obj-$(CONFIG_SERIAL_8250_FSL)		+= 8250_fsl.o
 obj-$(CONFIG_SERIAL_8250_DW)		+= 8250_dw.o
 obj-$(CONFIG_SERIAL_8250_EM)		+= 8250_em.o
+obj-$(CONFIG_SERIAL_PXA)		+= 8250_pxa.o
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index a3817ab..2ad7184b 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -396,29 +396,6 @@ config SERIAL_MPSC_CONSOLE
 	help
 	  Say Y here if you want to support a serial console on a Marvell MPSC.
 
-config SERIAL_PXA
-	bool "PXA serial port support"
-	depends on ARCH_PXA || ARCH_MMP
-	select SERIAL_CORE
-	help
-	  If you have a machine based on an Intel XScale PXA2xx CPU you
-	  can enable its onboard serial ports by enabling this option.
-
-config SERIAL_PXA_CONSOLE
-	bool "Console on PXA serial port"
-	depends on SERIAL_PXA
-	select SERIAL_CORE_CONSOLE
-	help
-	  If you have enabled the serial port on the Intel XScale PXA
-	  CPU you can make it the console by answering Y to this option.
-
-	  Even if you say Y here, the currently visible virtual console
-	  (/dev/tty0) will still be used as the system console by default, but
-	  you can alter that using a kernel command line option such as
-	  "console=ttySA0". (Try "man bootparam" or see the documentation of
-	  your boot loader (lilo or loadlin) about how to pass options to the
-	  kernel at boot time.)
-
 config SERIAL_SA1100
 	bool "SA1100 serial port support"
 	depends on ARCH_SA1100
diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile
index 3068c77..4ac337b 100644
--- a/drivers/tty/serial/Makefile
+++ b/drivers/tty/serial/Makefile
@@ -20,7 +20,6 @@ obj-$(CONFIG_SERIAL_8250) += 8250/
 obj-$(CONFIG_SERIAL_AMBA_PL010) += amba-pl010.o
 obj-$(CONFIG_SERIAL_AMBA_PL011) += amba-pl011.o
 obj-$(CONFIG_SERIAL_CLPS711X) += clps711x.o
-obj-$(CONFIG_SERIAL_PXA) += pxa.o
 obj-$(CONFIG_SERIAL_PNX8XXX) += pnx8xxx_uart.o
 obj-$(CONFIG_SERIAL_SA1100) += sa1100.o
 obj-$(CONFIG_SERIAL_BCM63XX) += bcm63xx_uart.o
diff --git a/drivers/tty/serial/pxa.c b/drivers/tty/serial/pxa.c
deleted file mode 100644
index f9f20f3..0000000
--- a/drivers/tty/serial/pxa.c
+++ /dev/null
@@ -1,971 +0,0 @@
-/*
- *  Based on drivers/serial/8250.c by Russell King.
- *
- *  Author:	Nicolas Pitre
- *  Created:	Feb 20, 2003
- *  Copyright:	(C) 2003 Monta Vista Software, Inc.
- *
- * 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.
- *
- * Note 1: This driver is made separate from the already too overloaded
- * 8250.c because it needs some kirks of its own and that'll make it
- * easier to add DMA support.
- *
- * Note 2: I'm too sick of device allocation policies for serial ports.
- * If someone else wants to request an "official" allocation of major/minor
- * for this driver please be my guest.  And don't forget that new hardware
- * to come from Intel might have more than 3 or 4 of those UARTs.  Let's
- * hope for a better port registration and dynamic device allocation scheme
- * with the serial core maintainer satisfaction to appear soon.
- */
-
-
-#if defined(CONFIG_SERIAL_PXA_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-#define SUPPORT_SYSRQ
-#endif
-
-#include <linux/module.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-#include <linux/console.h>
-#include <linux/sysrq.h>
-#include <linux/serial_reg.h>
-#include <linux/circ_buf.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/of.h>
-#include <linux/platform_device.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/serial_core.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-
-#define PXA_NAME_LEN		8
-
-struct uart_pxa_port {
-	struct uart_port        port;
-	unsigned char           ier;
-	unsigned char           lcr;
-	unsigned char           mcr;
-	unsigned int            lsr_break_flag;
-	struct clk		*clk;
-	char			name[PXA_NAME_LEN];
-};
-
-static inline unsigned int serial_in(struct uart_pxa_port *up, int offset)
-{
-	offset <<= 2;
-	return readl(up->port.membase + offset);
-}
-
-static inline void serial_out(struct uart_pxa_port *up, int offset, int value)
-{
-	offset <<= 2;
-	writel(value, up->port.membase + offset);
-}
-
-static void serial_pxa_enable_ms(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	up->ier |= UART_IER_MSI;
-	serial_out(up, UART_IER, up->ier);
-}
-
-static void serial_pxa_stop_tx(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	if (up->ier & UART_IER_THRI) {
-		up->ier &= ~UART_IER_THRI;
-		serial_out(up, UART_IER, up->ier);
-	}
-}
-
-static void serial_pxa_stop_rx(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	up->ier &= ~UART_IER_RLSI;
-	up->port.read_status_mask &= ~UART_LSR_DR;
-	serial_out(up, UART_IER, up->ier);
-}
-
-static inline void receive_chars(struct uart_pxa_port *up, int *status)
-{
-	unsigned int ch, flag;
-	int max_count = 256;
-
-	do {
-		/* work around Errata #20 according to
-		 * Intel(R) PXA27x Processor Family
-		 * Specification Update (May 2005)
-		 *
-		 * Step 2
-		 * Disable the Reciever Time Out Interrupt via IER[RTOEI]
-		 */
-		up->ier &= ~UART_IER_RTOIE;
-		serial_out(up, UART_IER, up->ier);
-
-		ch = serial_in(up, UART_RX);
-		flag = TTY_NORMAL;
-		up->port.icount.rx++;
-
-		if (unlikely(*status & (UART_LSR_BI | UART_LSR_PE |
-				       UART_LSR_FE | UART_LSR_OE))) {
-			/*
-			 * For statistics only
-			 */
-			if (*status & UART_LSR_BI) {
-				*status &= ~(UART_LSR_FE | UART_LSR_PE);
-				up->port.icount.brk++;
-				/*
-				 * We do the SysRQ and SAK checking
-				 * here because otherwise the break
-				 * may get masked by ignore_status_mask
-				 * or read_status_mask.
-				 */
-				if (uart_handle_break(&up->port))
-					goto ignore_char;
-			} else if (*status & UART_LSR_PE)
-				up->port.icount.parity++;
-			else if (*status & UART_LSR_FE)
-				up->port.icount.frame++;
-			if (*status & UART_LSR_OE)
-				up->port.icount.overrun++;
-
-			/*
-			 * Mask off conditions which should be ignored.
-			 */
-			*status &= up->port.read_status_mask;
-
-#ifdef CONFIG_SERIAL_PXA_CONSOLE
-			if (up->port.line == up->port.cons->index) {
-				/* Recover the break flag from console xmit */
-				*status |= up->lsr_break_flag;
-				up->lsr_break_flag = 0;
-			}
-#endif
-			if (*status & UART_LSR_BI) {
-				flag = TTY_BREAK;
-			} else if (*status & UART_LSR_PE)
-				flag = TTY_PARITY;
-			else if (*status & UART_LSR_FE)
-				flag = TTY_FRAME;
-		}
-
-		if (uart_handle_sysrq_char(&up->port, ch))
-			goto ignore_char;
-
-		uart_insert_char(&up->port, *status, UART_LSR_OE, ch, flag);
-
-	ignore_char:
-		*status = serial_in(up, UART_LSR);
-	} while ((*status & UART_LSR_DR) && (max_count-- > 0));
-	tty_flip_buffer_push(&up->port.state->port);
-
-	/* work around Errata #20 according to
-	 * Intel(R) PXA27x Processor Family
-	 * Specification Update (May 2005)
-	 *
-	 * Step 6:
-	 * No more data in FIFO: Re-enable RTO interrupt via IER[RTOIE]
-	 */
-	up->ier |= UART_IER_RTOIE;
-	serial_out(up, UART_IER, up->ier);
-}
-
-static void transmit_chars(struct uart_pxa_port *up)
-{
-	struct circ_buf *xmit = &up->port.state->xmit;
-	int count;
-
-	if (up->port.x_char) {
-		serial_out(up, UART_TX, up->port.x_char);
-		up->port.icount.tx++;
-		up->port.x_char = 0;
-		return;
-	}
-	if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) {
-		serial_pxa_stop_tx(&up->port);
-		return;
-	}
-
-	count = up->port.fifosize / 2;
-	do {
-		serial_out(up, UART_TX, xmit->buf[xmit->tail]);
-		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
-		up->port.icount.tx++;
-		if (uart_circ_empty(xmit))
-			break;
-	} while (--count > 0);
-
-	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
-		uart_write_wakeup(&up->port);
-
-
-	if (uart_circ_empty(xmit))
-		serial_pxa_stop_tx(&up->port);
-}
-
-static void serial_pxa_start_tx(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	if (!(up->ier & UART_IER_THRI)) {
-		up->ier |= UART_IER_THRI;
-		serial_out(up, UART_IER, up->ier);
-	}
-}
-
-static inline void check_modem_status(struct uart_pxa_port *up)
-{
-	int status;
-
-	status = serial_in(up, UART_MSR);
-
-	if ((status & UART_MSR_ANY_DELTA) == 0)
-		return;
-
-	if (status & UART_MSR_TERI)
-		up->port.icount.rng++;
-	if (status & UART_MSR_DDSR)
-		up->port.icount.dsr++;
-	if (status & UART_MSR_DDCD)
-		uart_handle_dcd_change(&up->port, status & UART_MSR_DCD);
-	if (status & UART_MSR_DCTS)
-		uart_handle_cts_change(&up->port, status & UART_MSR_CTS);
-
-	wake_up_interruptible(&up->port.state->port.delta_msr_wait);
-}
-
-/*
- * This handles the interrupt from one port.
- */
-static inline irqreturn_t serial_pxa_irq(int irq, void *dev_id)
-{
-	struct uart_pxa_port *up = dev_id;
-	unsigned int iir, lsr;
-
-	iir = serial_in(up, UART_IIR);
-	if (iir & UART_IIR_NO_INT)
-		return IRQ_NONE;
-	lsr = serial_in(up, UART_LSR);
-	if (lsr & UART_LSR_DR)
-		receive_chars(up, &lsr);
-	check_modem_status(up);
-	if (lsr & UART_LSR_THRE)
-		transmit_chars(up);
-	return IRQ_HANDLED;
-}
-
-static unsigned int serial_pxa_tx_empty(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned long flags;
-	unsigned int ret;
-
-	spin_lock_irqsave(&up->port.lock, flags);
-	ret = serial_in(up, UART_LSR) & UART_LSR_TEMT ? TIOCSER_TEMT : 0;
-	spin_unlock_irqrestore(&up->port.lock, flags);
-
-	return ret;
-}
-
-static unsigned int serial_pxa_get_mctrl(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned char status;
-	unsigned int ret;
-
-	status = serial_in(up, UART_MSR);
-
-	ret = 0;
-	if (status & UART_MSR_DCD)
-		ret |= TIOCM_CAR;
-	if (status & UART_MSR_RI)
-		ret |= TIOCM_RNG;
-	if (status & UART_MSR_DSR)
-		ret |= TIOCM_DSR;
-	if (status & UART_MSR_CTS)
-		ret |= TIOCM_CTS;
-	return ret;
-}
-
-static void serial_pxa_set_mctrl(struct uart_port *port, unsigned int mctrl)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned char mcr = 0;
-
-	if (mctrl & TIOCM_RTS)
-		mcr |= UART_MCR_RTS;
-	if (mctrl & TIOCM_DTR)
-		mcr |= UART_MCR_DTR;
-	if (mctrl & TIOCM_OUT1)
-		mcr |= UART_MCR_OUT1;
-	if (mctrl & TIOCM_OUT2)
-		mcr |= UART_MCR_OUT2;
-	if (mctrl & TIOCM_LOOP)
-		mcr |= UART_MCR_LOOP;
-
-	mcr |= up->mcr;
-
-	serial_out(up, UART_MCR, mcr);
-}
-
-static void serial_pxa_break_ctl(struct uart_port *port, int break_state)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned long flags;
-
-	spin_lock_irqsave(&up->port.lock, flags);
-	if (break_state == -1)
-		up->lcr |= UART_LCR_SBC;
-	else
-		up->lcr &= ~UART_LCR_SBC;
-	serial_out(up, UART_LCR, up->lcr);
-	spin_unlock_irqrestore(&up->port.lock, flags);
-}
-
-static int serial_pxa_startup(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned long flags;
-	int retval;
-
-	if (port->line == 3) /* HWUART */
-		up->mcr |= UART_MCR_AFE;
-	else
-		up->mcr = 0;
-
-	up->port.uartclk = clk_get_rate(up->clk);
-
-	/*
-	 * Allocate the IRQ
-	 */
-	retval = request_irq(up->port.irq, serial_pxa_irq, 0, up->name, up);
-	if (retval)
-		return retval;
-
-	/*
-	 * Clear the FIFO buffers and disable them.
-	 * (they will be reenabled in set_termios())
-	 */
-	serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO);
-	serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO |
-			UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
-	serial_out(up, UART_FCR, 0);
-
-	/*
-	 * Clear the interrupt registers.
-	 */
-	(void) serial_in(up, UART_LSR);
-	(void) serial_in(up, UART_RX);
-	(void) serial_in(up, UART_IIR);
-	(void) serial_in(up, UART_MSR);
-
-	/*
-	 * Now, initialize the UART
-	 */
-	serial_out(up, UART_LCR, UART_LCR_WLEN8);
-
-	spin_lock_irqsave(&up->port.lock, flags);
-	up->port.mctrl |= TIOCM_OUT2;
-	serial_pxa_set_mctrl(&up->port, up->port.mctrl);
-	spin_unlock_irqrestore(&up->port.lock, flags);
-
-	/*
-	 * Finally, enable interrupts.  Note: Modem status interrupts
-	 * are set via set_termios(), which will be occurring imminently
-	 * anyway, so we don't enable them here.
-	 */
-	up->ier = UART_IER_RLSI | UART_IER_RDI | UART_IER_RTOIE | UART_IER_UUE;
-	serial_out(up, UART_IER, up->ier);
-
-	/*
-	 * And clear the interrupt registers again for luck.
-	 */
-	(void) serial_in(up, UART_LSR);
-	(void) serial_in(up, UART_RX);
-	(void) serial_in(up, UART_IIR);
-	(void) serial_in(up, UART_MSR);
-
-	return 0;
-}
-
-static void serial_pxa_shutdown(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned long flags;
-
-	free_irq(up->port.irq, up);
-
-	/*
-	 * Disable interrupts from this port
-	 */
-	up->ier = 0;
-	serial_out(up, UART_IER, 0);
-
-	spin_lock_irqsave(&up->port.lock, flags);
-	up->port.mctrl &= ~TIOCM_OUT2;
-	serial_pxa_set_mctrl(&up->port, up->port.mctrl);
-	spin_unlock_irqrestore(&up->port.lock, flags);
-
-	/*
-	 * Disable break condition and FIFOs
-	 */
-	serial_out(up, UART_LCR, serial_in(up, UART_LCR) & ~UART_LCR_SBC);
-	serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO |
-				  UART_FCR_CLEAR_RCVR |
-				  UART_FCR_CLEAR_XMIT);
-	serial_out(up, UART_FCR, 0);
-}
-
-static void
-serial_pxa_set_termios(struct uart_port *port, struct ktermios *termios,
-		       struct ktermios *old)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned char cval, fcr = 0;
-	unsigned long flags;
-	unsigned int baud, quot;
-	unsigned int dll;
-
-	switch (termios->c_cflag & CSIZE) {
-	case CS5:
-		cval = UART_LCR_WLEN5;
-		break;
-	case CS6:
-		cval = UART_LCR_WLEN6;
-		break;
-	case CS7:
-		cval = UART_LCR_WLEN7;
-		break;
-	default:
-	case CS8:
-		cval = UART_LCR_WLEN8;
-		break;
-	}
-
-	if (termios->c_cflag & CSTOPB)
-		cval |= UART_LCR_STOP;
-	if (termios->c_cflag & PARENB)
-		cval |= UART_LCR_PARITY;
-	if (!(termios->c_cflag & PARODD))
-		cval |= UART_LCR_EPAR;
-
-	/*
-	 * Ask the core to calculate the divisor for us.
-	 */
-	baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
-	quot = uart_get_divisor(port, baud);
-
-	if ((up->port.uartclk / quot) < (2400 * 16))
-		fcr = UART_FCR_ENABLE_FIFO | UART_FCR_PXAR1;
-	else if ((up->port.uartclk / quot) < (230400 * 16))
-		fcr = UART_FCR_ENABLE_FIFO | UART_FCR_PXAR8;
-	else
-		fcr = UART_FCR_ENABLE_FIFO | UART_FCR_PXAR32;
-
-	/*
-	 * Ok, we're now changing the port state.  Do it with
-	 * interrupts disabled.
-	 */
-	spin_lock_irqsave(&up->port.lock, flags);
-
-	/*
-	 * Ensure the port will be enabled.
-	 * This is required especially for serial console.
-	 */
-	up->ier |= UART_IER_UUE;
-
-	/*
-	 * Update the per-port timeout.
-	 */
-	uart_update_timeout(port, termios->c_cflag, baud);
-
-	up->port.read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;
-	if (termios->c_iflag & INPCK)
-		up->port.read_status_mask |= UART_LSR_FE | UART_LSR_PE;
-	if (termios->c_iflag & (BRKINT | PARMRK))
-		up->port.read_status_mask |= UART_LSR_BI;
-
-	/*
-	 * Characters to ignore
-	 */
-	up->port.ignore_status_mask = 0;
-	if (termios->c_iflag & IGNPAR)
-		up->port.ignore_status_mask |= UART_LSR_PE | UART_LSR_FE;
-	if (termios->c_iflag & IGNBRK) {
-		up->port.ignore_status_mask |= UART_LSR_BI;
-		/*
-		 * If we're ignoring parity and break indicators,
-		 * ignore overruns too (for real raw support).
-		 */
-		if (termios->c_iflag & IGNPAR)
-			up->port.ignore_status_mask |= UART_LSR_OE;
-	}
-
-	/*
-	 * ignore all characters if CREAD is not set
-	 */
-	if ((termios->c_cflag & CREAD) == 0)
-		up->port.ignore_status_mask |= UART_LSR_DR;
-
-	/*
-	 * CTS flow control flag and modem status interrupts
-	 */
-	up->ier &= ~UART_IER_MSI;
-	if (UART_ENABLE_MS(&up->port, termios->c_cflag))
-		up->ier |= UART_IER_MSI;
-
-	serial_out(up, UART_IER, up->ier);
-
-	if (termios->c_cflag & CRTSCTS)
-		up->mcr |= UART_MCR_AFE;
-	else
-		up->mcr &= ~UART_MCR_AFE;
-
-	serial_out(up, UART_LCR, cval | UART_LCR_DLAB);	/* set DLAB */
-	serial_out(up, UART_DLL, quot & 0xff);		/* LS of divisor */
-
-	/*
-	 * work around Errata #75 according to Intel(R) PXA27x Processor Family
-	 * Specification Update (Nov 2005)
-	 */
-	dll = serial_in(up, UART_DLL);
-	WARN_ON(dll != (quot & 0xff));
-
-	serial_out(up, UART_DLM, quot >> 8);		/* MS of divisor */
-	serial_out(up, UART_LCR, cval);			/* reset DLAB */
-	up->lcr = cval;					/* Save LCR */
-	serial_pxa_set_mctrl(&up->port, up->port.mctrl);
-	serial_out(up, UART_FCR, fcr);
-	spin_unlock_irqrestore(&up->port.lock, flags);
-}
-
-static void
-serial_pxa_pm(struct uart_port *port, unsigned int state,
-	      unsigned int oldstate)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	if (!state)
-		clk_prepare_enable(up->clk);
-	else
-		clk_disable_unprepare(up->clk);
-}
-
-static void serial_pxa_release_port(struct uart_port *port)
-{
-}
-
-static int serial_pxa_request_port(struct uart_port *port)
-{
-	return 0;
-}
-
-static void serial_pxa_config_port(struct uart_port *port, int flags)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	up->port.type = PORT_PXA;
-}
-
-static int
-serial_pxa_verify_port(struct uart_port *port, struct serial_struct *ser)
-{
-	/* we don't want the core code to modify any port params */
-	return -EINVAL;
-}
-
-static const char *
-serial_pxa_type(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	return up->name;
-}
-
-static struct uart_pxa_port *serial_pxa_ports[4];
-static struct uart_driver serial_pxa_reg;
-
-#ifdef CONFIG_SERIAL_PXA_CONSOLE
-
-#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
-
-/*
- *	Wait for transmitter & holding register to empty
- */
-static inline void wait_for_xmitr(struct uart_pxa_port *up)
-{
-	unsigned int status, tmout = 10000;
-
-	/* Wait up to 10ms for the character(s) to be sent. */
-	do {
-		status = serial_in(up, UART_LSR);
-
-		if (status & UART_LSR_BI)
-			up->lsr_break_flag = UART_LSR_BI;
-
-		if (--tmout == 0)
-			break;
-		udelay(1);
-	} while ((status & BOTH_EMPTY) != BOTH_EMPTY);
-
-	/* Wait up to 1s for flow control if necessary */
-	if (up->port.flags & UPF_CONS_FLOW) {
-		tmout = 1000000;
-		while (--tmout &&
-		       ((serial_in(up, UART_MSR) & UART_MSR_CTS) == 0))
-			udelay(1);
-	}
-}
-
-static void serial_pxa_console_putchar(struct uart_port *port, int ch)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	wait_for_xmitr(up);
-	serial_out(up, UART_TX, ch);
-}
-
-/*
- * Print a string to the serial port trying not to disturb
- * any possible real use of the port...
- *
- *	The console_lock must be held when we get here.
- */
-static void
-serial_pxa_console_write(struct console *co, const char *s, unsigned int count)
-{
-	struct uart_pxa_port *up = serial_pxa_ports[co->index];
-	unsigned int ier;
-	unsigned long flags;
-	int locked = 1;
-
-	clk_enable(up->clk);
-	local_irq_save(flags);
-	if (up->port.sysrq)
-		locked = 0;
-	else if (oops_in_progress)
-		locked = spin_trylock(&up->port.lock);
-	else
-		spin_lock(&up->port.lock);
-
-	/*
-	 *	First save the IER then disable the interrupts
-	 */
-	ier = serial_in(up, UART_IER);
-	serial_out(up, UART_IER, UART_IER_UUE);
-
-	uart_console_write(&up->port, s, count, serial_pxa_console_putchar);
-
-	/*
-	 *	Finally, wait for transmitter to become empty
-	 *	and restore the IER
-	 */
-	wait_for_xmitr(up);
-	serial_out(up, UART_IER, ier);
-
-	if (locked)
-		spin_unlock(&up->port.lock);
-	local_irq_restore(flags);
-	clk_disable(up->clk);
-
-}
-
-#ifdef CONFIG_CONSOLE_POLL
-/*
- * Console polling routines for writing and reading from the uart while
- * in an interrupt or debug context.
- */
-
-static int serial_pxa_get_poll_char(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned char lsr = serial_in(up, UART_LSR);
-
-	while (!(lsr & UART_LSR_DR))
-		lsr = serial_in(up, UART_LSR);
-
-	return serial_in(up, UART_RX);
-}
-
-
-static void serial_pxa_put_poll_char(struct uart_port *port,
-			 unsigned char c)
-{
-	unsigned int ier;
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	/*
-	 *	First save the IER then disable the interrupts
-	 */
-	ier = serial_in(up, UART_IER);
-	serial_out(up, UART_IER, UART_IER_UUE);
-
-	wait_for_xmitr(up);
-	/*
-	 *	Send the character out.
-	 *	If a LF, also do CR...
-	 */
-	serial_out(up, UART_TX, c);
-	if (c == 10) {
-		wait_for_xmitr(up);
-		serial_out(up, UART_TX, 13);
-	}
-
-	/*
-	 *	Finally, wait for transmitter to become empty
-	 *	and restore the IER
-	 */
-	wait_for_xmitr(up);
-	serial_out(up, UART_IER, ier);
-}
-
-#endif /* CONFIG_CONSOLE_POLL */
-
-static int __init
-serial_pxa_console_setup(struct console *co, char *options)
-{
-	struct uart_pxa_port *up;
-	int baud = 9600;
-	int bits = 8;
-	int parity = 'n';
-	int flow = 'n';
-
-	if (co->index == -1 || co->index >= serial_pxa_reg.nr)
-		co->index = 0;
-	up = serial_pxa_ports[co->index];
-	if (!up)
-		return -ENODEV;
-
-	if (options)
-		uart_parse_options(options, &baud, &parity, &bits, &flow);
-
-	return uart_set_options(&up->port, co, baud, parity, bits, flow);
-}
-
-static struct console serial_pxa_console = {
-	.name		= "ttyS",
-	.write		= serial_pxa_console_write,
-	.device		= uart_console_device,
-	.setup		= serial_pxa_console_setup,
-	.flags		= CON_PRINTBUFFER,
-	.index		= -1,
-	.data		= &serial_pxa_reg,
-};
-
-#define PXA_CONSOLE	&serial_pxa_console
-#else
-#define PXA_CONSOLE	NULL
-#endif
-
-static struct uart_ops serial_pxa_pops = {
-	.tx_empty	= serial_pxa_tx_empty,
-	.set_mctrl	= serial_pxa_set_mctrl,
-	.get_mctrl	= serial_pxa_get_mctrl,
-	.stop_tx	= serial_pxa_stop_tx,
-	.start_tx	= serial_pxa_start_tx,
-	.stop_rx	= serial_pxa_stop_rx,
-	.enable_ms	= serial_pxa_enable_ms,
-	.break_ctl	= serial_pxa_break_ctl,
-	.startup	= serial_pxa_startup,
-	.shutdown	= serial_pxa_shutdown,
-	.set_termios	= serial_pxa_set_termios,
-	.pm		= serial_pxa_pm,
-	.type		= serial_pxa_type,
-	.release_port	= serial_pxa_release_port,
-	.request_port	= serial_pxa_request_port,
-	.config_port	= serial_pxa_config_port,
-	.verify_port	= serial_pxa_verify_port,
-#ifdef CONFIG_CONSOLE_POLL
-	.poll_get_char = serial_pxa_get_poll_char,
-	.poll_put_char = serial_pxa_put_poll_char,
-#endif
-};
-
-static struct uart_driver serial_pxa_reg = {
-	.owner		= THIS_MODULE,
-	.driver_name	= "PXA serial",
-	.dev_name	= "ttyS",
-	.major		= TTY_MAJOR,
-	.minor		= 64,
-	.nr		= 4,
-	.cons		= PXA_CONSOLE,
-};
-
-#ifdef CONFIG_PM
-static int serial_pxa_suspend(struct device *dev)
-{
-        struct uart_pxa_port *sport = dev_get_drvdata(dev);
-
-        if (sport)
-                uart_suspend_port(&serial_pxa_reg, &sport->port);
-
-        return 0;
-}
-
-static int serial_pxa_resume(struct device *dev)
-{
-        struct uart_pxa_port *sport = dev_get_drvdata(dev);
-
-        if (sport)
-                uart_resume_port(&serial_pxa_reg, &sport->port);
-
-        return 0;
-}
-
-static const struct dev_pm_ops serial_pxa_pm_ops = {
-	.suspend	= serial_pxa_suspend,
-	.resume		= serial_pxa_resume,
-};
-#endif
-
-static struct of_device_id serial_pxa_dt_ids[] = {
-	{ .compatible = "mrvl,pxa-uart", },
-	{ .compatible = "mrvl,mmp-uart", },
-	{}
-};
-MODULE_DEVICE_TABLE(of, serial_pxa_dt_ids);
-
-static int serial_pxa_probe_dt(struct platform_device *pdev,
-			       struct uart_pxa_port *sport)
-{
-	struct device_node *np = pdev->dev.of_node;
-	int ret;
-
-	if (!np)
-		return 1;
-
-	ret = of_alias_get_id(np, "serial");
-	if (ret < 0) {
-		dev_err(&pdev->dev, "failed to get alias id, errno %d\n", ret);
-		return ret;
-	}
-	sport->port.line = ret;
-	return 0;
-}
-
-static int serial_pxa_probe(struct platform_device *dev)
-{
-	struct uart_pxa_port *sport;
-	struct resource *mmres, *irqres;
-	int ret;
-
-	mmres = platform_get_resource(dev, IORESOURCE_MEM, 0);
-	irqres = platform_get_resource(dev, IORESOURCE_IRQ, 0);
-	if (!mmres || !irqres)
-		return -ENODEV;
-
-	sport = kzalloc(sizeof(struct uart_pxa_port), GFP_KERNEL);
-	if (!sport)
-		return -ENOMEM;
-
-	sport->clk = clk_get(&dev->dev, NULL);
-	if (IS_ERR(sport->clk)) {
-		ret = PTR_ERR(sport->clk);
-		goto err_free;
-	}
-
-	ret = clk_prepare(sport->clk);
-	if (ret) {
-		clk_put(sport->clk);
-		goto err_free;
-	}
-
-	sport->port.type = PORT_PXA;
-	sport->port.iotype = UPIO_MEM;
-	sport->port.mapbase = mmres->start;
-	sport->port.irq = irqres->start;
-	sport->port.fifosize = 64;
-	sport->port.ops = &serial_pxa_pops;
-	sport->port.dev = &dev->dev;
-	sport->port.flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF;
-	sport->port.uartclk = clk_get_rate(sport->clk);
-
-	ret = serial_pxa_probe_dt(dev, sport);
-	if (ret > 0)
-		sport->port.line = dev->id;
-	else if (ret < 0)
-		goto err_clk;
-	snprintf(sport->name, PXA_NAME_LEN - 1, "UART%d", sport->port.line + 1);
-
-	sport->port.membase = ioremap(mmres->start, resource_size(mmres));
-	if (!sport->port.membase) {
-		ret = -ENOMEM;
-		goto err_clk;
-	}
-
-	serial_pxa_ports[sport->port.line] = sport;
-
-	uart_add_one_port(&serial_pxa_reg, &sport->port);
-	platform_set_drvdata(dev, sport);
-
-	return 0;
-
- err_clk:
-	clk_unprepare(sport->clk);
-	clk_put(sport->clk);
- err_free:
-	kfree(sport);
-	return ret;
-}
-
-static int serial_pxa_remove(struct platform_device *dev)
-{
-	struct uart_pxa_port *sport = platform_get_drvdata(dev);
-
-	uart_remove_one_port(&serial_pxa_reg, &sport->port);
-
-	clk_unprepare(sport->clk);
-	clk_put(sport->clk);
-	kfree(sport);
-
-	return 0;
-}
-
-static struct platform_driver serial_pxa_driver = {
-        .probe          = serial_pxa_probe,
-        .remove         = serial_pxa_remove,
-
-	.driver		= {
-	        .name	= "pxa2xx-uart",
-		.owner	= THIS_MODULE,
-#ifdef CONFIG_PM
-		.pm	= &serial_pxa_pm_ops,
-#endif
-		.of_match_table = serial_pxa_dt_ids,
-	},
-};
-
-static int __init serial_pxa_init(void)
-{
-	int ret;
-
-	ret = uart_register_driver(&serial_pxa_reg);
-	if (ret != 0)
-		return ret;
-
-	ret = platform_driver_register(&serial_pxa_driver);
-	if (ret != 0)
-		uart_unregister_driver(&serial_pxa_reg);
-
-	return ret;
-}
-
-static void __exit serial_pxa_exit(void)
-{
-	platform_driver_unregister(&serial_pxa_driver);
-	uart_unregister_driver(&serial_pxa_reg);
-}
-
-module_init(serial_pxa_init);
-module_exit(serial_pxa_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:pxa2xx-uart");
-- 
1.8.4.2

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

* Re: [PATCH] serial: rewrite pxa2xx-uart to use 8250_core
  2013-12-06  2:42                       ` James Cameron
@ 2013-12-06  9:16                         ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-06  9:16 UTC (permalink / raw)
  To: James Cameron
  Cc: linux-kernel, open list:OPEN FIRMWARE AND...,
	Heikki Krogerus, Russell King, Greg Kroah-Hartman, Ralf Baechle,
	Rob Herring, Haojian Zhuang, open list:SERIAL DRIVERS,
	Grant Likely, Andrew Morton, John Crispin, Jiri Slaby,
	moderated list:ARM PORT, Zhou Zhu

On Fri, 2013-12-06 at 13:42 +1100, James Cameron wrote:
> On Fri, Dec 06, 2013 at 03:28:37AM +0400, Sergei Ianovich wrote:
> > +/* Uart divisor latch write */
> > +static void serial_pxa_dl_write(struct uart_8250_port *up, int value)
> > +{
> > +	serial_out(up, UART_DLL, value & 0xff);
> > +	serial_out(up, UART_DLM, value >> 8 & 0xff);
> > +}
> 
> This is a change.  drivers/tty/serial/pxa.c did read back UART_DLL as
> an errata work around:
> 
> > -	/*
> > -	 * work around Errata #75 according to Intel(R) PXA27x Processor Family
> > -	 * Specification Update (Nov 2005)
> > -	 */
> > -	dll = serial_in(up, UART_DLL);
> > -	WARN_ON(dll != (quot & 0xff));
> 
> If this is no longer needed, serial_pxa_dl_write can be removed
> because it is same as default_serial_dl_write.

Thanks for spotting this. I prepared infrastructure, but the tests never
failed so I never returned here. I've filed v2 with correct dl_write.

> I did not check the other errata work arounds.

I've intentionally dropped workaround for E20 from old pxa.c
receive_chars(). 8250_core reads FIFO immediately after it checks DR bit
in LSR, so that issue never happens. New version states this in commit
message.


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

* [PATCH] serial: rewrite pxa2xx-uart to use 8250_core
@ 2013-12-06  9:16                         ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-06  9:16 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, 2013-12-06 at 13:42 +1100, James Cameron wrote:
> On Fri, Dec 06, 2013 at 03:28:37AM +0400, Sergei Ianovich wrote:
> > +/* Uart divisor latch write */
> > +static void serial_pxa_dl_write(struct uart_8250_port *up, int value)
> > +{
> > +	serial_out(up, UART_DLL, value & 0xff);
> > +	serial_out(up, UART_DLM, value >> 8 & 0xff);
> > +}
> 
> This is a change.  drivers/tty/serial/pxa.c did read back UART_DLL as
> an errata work around:
> 
> > -	/*
> > -	 * work around Errata #75 according to Intel(R) PXA27x Processor Family
> > -	 * Specification Update (Nov 2005)
> > -	 */
> > -	dll = serial_in(up, UART_DLL);
> > -	WARN_ON(dll != (quot & 0xff));
> 
> If this is no longer needed, serial_pxa_dl_write can be removed
> because it is same as default_serial_dl_write.

Thanks for spotting this. I prepared infrastructure, but the tests never
failed so I never returned here. I've filed v2 with correct dl_write.

> I did not check the other errata work arounds.

I've intentionally dropped workaround for E20 from old pxa.c
receive_chars(). 8250_core reads FIFO immediately after it checks DR bit
in LSR, so that issue never happens. New version states this in commit
message.

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

* Re: [PATCH v2] serial: rewrite pxa2xx-uart to use 8250_core
  2013-12-06  9:09                       ` Sergei Ianovich
@ 2013-12-06  9:28                         ` James Cameron
  -1 siblings, 0 replies; 700+ messages in thread
From: James Cameron @ 2013-12-06  9:28 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: linux-kernel, Heikki Krogerus, Greg Kroah-Hartman, Russell King,
	Jiri Slaby, Grant Likely, Rob Herring, Zhou Zhu, Andrew Morton,
	Haojian Zhuang, Stefan Seyfried, John Crispin, Paul Bolle,
	moderated list:ARM PORT, open list:SERIAL DRIVERS,
	open list:OPEN FIRMWARE AND...

On Fri, Dec 06, 2013 at 01:09:31PM +0400, Sergei Ianovich wrote:
> pxa2xx-uart was a separate uart platform driver. It was declaring
> the same device names and numbers as 8250 driver. As a result,
> it was impossible to use 8250 driver on PXA SoCs.
> 
> Upon closer examination pxa2xx-uart turned out to be a clone of
> 8250_core driver.
> 
> Workaround for Erratum #19 according to Marvel(R) PXA270M Processor
> Specification Update (April 19, 2010) is dropped. 8250_core reads
> from FIFO immediately after checking DR bit in LSR.

Reviewed-by: James Cameron <quozl@laptop.org>

Thanks.

(for my notes ... V1 has passed 4.5 hours in OLPC's RUNIN test.)

-- 
James Cameron
http://quozl.linux.org.au/

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

* [PATCH v2] serial: rewrite pxa2xx-uart to use 8250_core
@ 2013-12-06  9:28                         ` James Cameron
  0 siblings, 0 replies; 700+ messages in thread
From: James Cameron @ 2013-12-06  9:28 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Dec 06, 2013 at 01:09:31PM +0400, Sergei Ianovich wrote:
> pxa2xx-uart was a separate uart platform driver. It was declaring
> the same device names and numbers as 8250 driver. As a result,
> it was impossible to use 8250 driver on PXA SoCs.
> 
> Upon closer examination pxa2xx-uart turned out to be a clone of
> 8250_core driver.
> 
> Workaround for Erratum #19 according to Marvel(R) PXA270M Processor
> Specification Update (April 19, 2010) is dropped. 8250_core reads
> from FIFO immediately after checking DR bit in LSR.

Reviewed-by: James Cameron <quozl@laptop.org>

Thanks.

(for my notes ... V1 has passed 4.5 hours in OLPC's RUNIN test.)

-- 
James Cameron
http://quozl.linux.org.au/

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

* Re: [PATCH] serial: rewrite pxa2xx-uart to use 8250_core
  2013-12-06  0:17                         ` Russell King - ARM Linux
@ 2013-12-06  9:28                           ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-06  9:28 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: Greg Kroah-Hartman, linux-kernel, Heikki Krogerus, Jiri Slaby,
	Grant Likely, Rob Herring, Zhou Zhu, Andrew Morton,
	Haojian Zhuang, Ralf Baechle, John Crispin,
	moderated list:ARM PORT, open list:SERIAL DRIVERS,
	open list:OPEN FIRMWARE AND...

On Fri, 2013-12-06 at 00:17 +0000, Russell King - ARM Linux wrote:

> I may be able to - one of the downsides though is that many of these
> systems had hard-coded scripts which started a getty on the original
> port - and that kind of makes it difficult to sort out.  This kind of
> change becomes very much one of Linus' "flag days".

> So I'd suggest that we have a period where the old driver is still
> available, so at least people can choose to use the old major/minor
> numbers for a while.

The patch doesn't change how the driver looks from the outside. The old
driver was using 8250 name (ttyS), major (4) and first minor (64). So we
only resolve an internal conflict.

Kernel configuration is the place where issues may appear, since the
patch removes CONFIG_SERIAL_PXA_CONSOLE option. I've updated all
in-kernel users. However, out-of-kernel configs will no longer provide
serial console, unless manually reconfigured. Is this the case we should
worry about?


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

* [PATCH] serial: rewrite pxa2xx-uart to use 8250_core
@ 2013-12-06  9:28                           ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-06  9:28 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, 2013-12-06 at 00:17 +0000, Russell King - ARM Linux wrote:

> I may be able to - one of the downsides though is that many of these
> systems had hard-coded scripts which started a getty on the original
> port - and that kind of makes it difficult to sort out.  This kind of
> change becomes very much one of Linus' "flag days".

> So I'd suggest that we have a period where the old driver is still
> available, so at least people can choose to use the old major/minor
> numbers for a while.

The patch doesn't change how the driver looks from the outside. The old
driver was using 8250 name (ttyS), major (4) and first minor (64). So we
only resolve an internal conflict.

Kernel configuration is the place where issues may appear, since the
patch removes CONFIG_SERIAL_PXA_CONSOLE option. I've updated all
in-kernel users. However, out-of-kernel configs will no longer provide
serial console, unless manually reconfigured. Is this the case we should
worry about?

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

* Re: [PATCH] serial: rewrite pxa2xx-uart to use 8250_core
  2013-12-06  9:28                           ` Sergei Ianovich
@ 2013-12-06  9:53                             ` James Cameron
  -1 siblings, 0 replies; 700+ messages in thread
From: James Cameron @ 2013-12-06  9:53 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: Russell King - ARM Linux, open list:OPEN FIRMWARE AND...,
	Heikki Krogerus, Greg Kroah-Hartman, Ralf Baechle, linux-kernel,
	Rob Herring, Haojian Zhuang, open list:SERIAL DRIVERS,
	Grant Likely, Andrew Morton, John Crispin, Jiri Slaby,
	moderated list:ARM PORT, Zhou Zhu

On Fri, Dec 06, 2013 at 01:28:51PM +0400, Sergei Ianovich wrote:
> On Fri, 2013-12-06 at 00:17 +0000, Russell King - ARM Linux wrote:
> 
> > I may be able to - one of the downsides though is that many of these
> > systems had hard-coded scripts which started a getty on the original
> > port - and that kind of makes it difficult to sort out.  This kind of
> > change becomes very much one of Linus' "flag days".
> 
> > So I'd suggest that we have a period where the old driver is still
> > available, so at least people can choose to use the old major/minor
> > numbers for a while.
> 
> The patch doesn't change how the driver looks from the outside. The old
> driver was using 8250 name (ttyS), major (4) and first minor (64). So we
> only resolve an internal conflict.

I don't understand why /dev/ttyS2 (4,66) changed to /dev/ttyS0 (4,64)
after the patch was applied to olpc-kernel/arm-3.5 but, as you say it
doesn't change, perhaps there is something between 3.5 and now for me
to watch out for.  My problem.

> Kernel configuration is the place where issues may appear, since the
> patch removes CONFIG_SERIAL_PXA_CONSOLE option. I've updated all
> in-kernel users. However, out-of-kernel configs will no longer provide
> serial console, unless manually reconfigured. Is this the case we should
> worry about?

OLPC holds an out-of-kernel config (xo_4_defconfig); but no, I don't
think we'd have trouble with this.  Go for it.

-- 
James Cameron
http://quozl.linux.org.au/

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

* [PATCH] serial: rewrite pxa2xx-uart to use 8250_core
@ 2013-12-06  9:53                             ` James Cameron
  0 siblings, 0 replies; 700+ messages in thread
From: James Cameron @ 2013-12-06  9:53 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Dec 06, 2013 at 01:28:51PM +0400, Sergei Ianovich wrote:
> On Fri, 2013-12-06 at 00:17 +0000, Russell King - ARM Linux wrote:
> 
> > I may be able to - one of the downsides though is that many of these
> > systems had hard-coded scripts which started a getty on the original
> > port - and that kind of makes it difficult to sort out.  This kind of
> > change becomes very much one of Linus' "flag days".
> 
> > So I'd suggest that we have a period where the old driver is still
> > available, so at least people can choose to use the old major/minor
> > numbers for a while.
> 
> The patch doesn't change how the driver looks from the outside. The old
> driver was using 8250 name (ttyS), major (4) and first minor (64). So we
> only resolve an internal conflict.

I don't understand why /dev/ttyS2 (4,66) changed to /dev/ttyS0 (4,64)
after the patch was applied to olpc-kernel/arm-3.5 but, as you say it
doesn't change, perhaps there is something between 3.5 and now for me
to watch out for.  My problem.

> Kernel configuration is the place where issues may appear, since the
> patch removes CONFIG_SERIAL_PXA_CONSOLE option. I've updated all
> in-kernel users. However, out-of-kernel configs will no longer provide
> serial console, unless manually reconfigured. Is this the case we should
> worry about?

OLPC holds an out-of-kernel config (xo_4_defconfig); but no, I don't
think we'd have trouble with this.  Go for it.

-- 
James Cameron
http://quozl.linux.org.au/

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

* Re: [PATCH] serial: rewrite pxa2xx-uart to use 8250_core
  2013-12-06  9:53                             ` James Cameron
@ 2013-12-06 10:34                               ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-06 10:34 UTC (permalink / raw)
  To: James Cameron
  Cc: Russell King - ARM Linux, open list:OPEN FIRMWARE AND...,
	Heikki Krogerus, Greg Kroah-Hartman, Ralf Baechle, linux-kernel,
	Rob Herring, Haojian Zhuang, open list:SERIAL DRIVERS,
	Grant Likely, Andrew Morton, John Crispin, Jiri Slaby,
	moderated list:ARM PORT, Zhou Zhu

On Fri, 2013-12-06 at 20:53 +1100, James Cameron wrote:
> I don't understand why /dev/ttyS2 (4,66) changed to /dev/ttyS0 (4,64)
> after the patch was applied to olpc-kernel/arm-3.5 but, as you say it
> doesn't change, perhaps there is something between 3.5 and now for me
> to watch out for.  My problem.

The old pxa.c set device ids explicitly:
-static int serial_pxa_probe_dt(struct platform_device *pdev,
-                              struct uart_pxa_port *sport)
-{
-       struct device_node *np = pdev->dev.of_node;
-       int ret;
-
-       if (!np)
-               return 1;
-
-       ret = of_alias_get_id(np, "serial");
-       if (ret < 0) {
-               dev_err(&pdev->dev, "failed to get alias id, errno %d
\n", ret);
-               return ret;
-       }
-       sport->port.line = ret;
-       return 0;
-}

and

-       ret = serial_pxa_probe_dt(dev, sport);
-       if (ret > 0)
-               sport->port.line = dev->id;


However, this is not possible with 8250_core. The latter assigns device
ids strictly in the call order of serial8250_register_8250_port().

Hope it helps.


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

* [PATCH] serial: rewrite pxa2xx-uart to use 8250_core
@ 2013-12-06 10:34                               ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-06 10:34 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, 2013-12-06 at 20:53 +1100, James Cameron wrote:
> I don't understand why /dev/ttyS2 (4,66) changed to /dev/ttyS0 (4,64)
> after the patch was applied to olpc-kernel/arm-3.5 but, as you say it
> doesn't change, perhaps there is something between 3.5 and now for me
> to watch out for.  My problem.

The old pxa.c set device ids explicitly:
-static int serial_pxa_probe_dt(struct platform_device *pdev,
-                              struct uart_pxa_port *sport)
-{
-       struct device_node *np = pdev->dev.of_node;
-       int ret;
-
-       if (!np)
-               return 1;
-
-       ret = of_alias_get_id(np, "serial");
-       if (ret < 0) {
-               dev_err(&pdev->dev, "failed to get alias id, errno %d
\n", ret);
-               return ret;
-       }
-       sport->port.line = ret;
-       return 0;
-}

and

-       ret = serial_pxa_probe_dt(dev, sport);
-       if (ret > 0)
-               sport->port.line = dev->id;


However, this is not possible with 8250_core. The latter assigns device
ids strictly in the call order of serial8250_register_8250_port().

Hope it helps.

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

* Re: [PATCH] serial: rewrite pxa2xx-uart to use 8250_core
  2013-12-06 10:34                               ` Sergei Ianovich
@ 2013-12-06 11:05                                 ` James Cameron
  -1 siblings, 0 replies; 700+ messages in thread
From: James Cameron @ 2013-12-06 11:05 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: Russell King - ARM Linux, open list:OPEN FIRMWARE AND...,
	Heikki Krogerus, Greg Kroah-Hartman, Ralf Baechle, linux-kernel,
	Rob Herring, Haojian Zhuang, open list:SERIAL DRIVERS,
	Grant Likely, Andrew Morton, John Crispin, Jiri Slaby,
	moderated list:ARM PORT, Zhou Zhu

On Fri, Dec 06, 2013 at 02:34:17PM +0400, Sergei Ianovich wrote:
> On Fri, 2013-12-06 at 20:53 +1100, James Cameron wrote:
> > I don't understand why /dev/ttyS2 (4,66) changed to /dev/ttyS0 (4,64)
> > after the patch was applied to olpc-kernel/arm-3.5 but, as you say it
> > doesn't change, perhaps there is something between 3.5 and now for me
> > to watch out for.  My problem.
> 
> The old pxa.c set device ids explicitly:
> -static int serial_pxa_probe_dt(struct platform_device *pdev,
> -                              struct uart_pxa_port *sport)
> -{
> -       struct device_node *np = pdev->dev.of_node;
> -       int ret;
> -
> -       if (!np)
> -               return 1;
> -
> -       ret = of_alias_get_id(np, "serial");
> -       if (ret < 0) {
> -               dev_err(&pdev->dev, "failed to get alias id, errno %d
> \n", ret);
> -               return ret;
> -       }
> -       sport->port.line = ret;
> -       return 0;
> -}
> 
> and
> 
> -       ret = serial_pxa_probe_dt(dev, sport);
> -       if (ret > 0)
> -               sport->port.line = dev->id;
> 
> 
> However, this is not possible with 8250_core. The latter assigns device
> ids strictly in the call order of serial8250_register_8250_port().
> 
> Hope it helps.

Yes, thanks, that explains it.

Your patch deprecates the use of property "linux,unit#" in the device
tree for serial ports, or the numbering according to the ordering of
the device tree.

(On OLPC XO-4, we set the numbering according to the ordering, we don't
use "linux,unit#".)

It is sad to see device tree sawdust.  ;-)

-- 
James Cameron
http://quozl.linux.org.au/

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

* [PATCH] serial: rewrite pxa2xx-uart to use 8250_core
@ 2013-12-06 11:05                                 ` James Cameron
  0 siblings, 0 replies; 700+ messages in thread
From: James Cameron @ 2013-12-06 11:05 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Dec 06, 2013 at 02:34:17PM +0400, Sergei Ianovich wrote:
> On Fri, 2013-12-06 at 20:53 +1100, James Cameron wrote:
> > I don't understand why /dev/ttyS2 (4,66) changed to /dev/ttyS0 (4,64)
> > after the patch was applied to olpc-kernel/arm-3.5 but, as you say it
> > doesn't change, perhaps there is something between 3.5 and now for me
> > to watch out for.  My problem.
> 
> The old pxa.c set device ids explicitly:
> -static int serial_pxa_probe_dt(struct platform_device *pdev,
> -                              struct uart_pxa_port *sport)
> -{
> -       struct device_node *np = pdev->dev.of_node;
> -       int ret;
> -
> -       if (!np)
> -               return 1;
> -
> -       ret = of_alias_get_id(np, "serial");
> -       if (ret < 0) {
> -               dev_err(&pdev->dev, "failed to get alias id, errno %d
> \n", ret);
> -               return ret;
> -       }
> -       sport->port.line = ret;
> -       return 0;
> -}
> 
> and
> 
> -       ret = serial_pxa_probe_dt(dev, sport);
> -       if (ret > 0)
> -               sport->port.line = dev->id;
> 
> 
> However, this is not possible with 8250_core. The latter assigns device
> ids strictly in the call order of serial8250_register_8250_port().
> 
> Hope it helps.

Yes, thanks, that explains it.

Your patch deprecates the use of property "linux,unit#" in the device
tree for serial ports, or the numbering according to the ordering of
the device tree.

(On OLPC XO-4, we set the numbering according to the ordering, we don't
use "linux,unit#".)

It is sad to see device tree sawdust.  ;-)

-- 
James Cameron
http://quozl.linux.org.au/

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

* Re: [PATCH 02/11] arm: pxa27x: support ICP DAS LP-8x4x
  2013-12-06  0:40     ` Arnd Bergmann
@ 2013-12-06 16:38       ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-06 16:38 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: linux-arm-kernel, linux-kernel, Eric Miao, Russell King, Haojian Zhuang

On Fri, 2013-12-06 at 01:40 +0100, Arnd Bergmann wrote:
> On Sunday 01 December 2013, Sergei Ianovich wrote:
> > 
> > diff --git a/arch/arm/configs/lp8x4x_defconfig b/arch/arm/configs/lp8x4x_defconfig
> > new file mode 100644
> > index 0000000..5cd6d38
> > --- /dev/null
> > +++ b/arch/arm/configs/lp8x4x_defconfig
> > @@ -0,0 +1,2320 @@
> > +#
> > +# Automatically generated file; DO NOT EDIT.
> > +# Linux/arm 3.13.0-rc1 Kernel Configuration
> > +#
> 
> Please use 'make savedefconfig' to generate a smaller version of this file.

Done. Updated in v2.

> Ideally we want shared defconfigs where you enable multiple (or all) pxa boards
> at once and end up with a kernel that works on all of them.
> 
> For most other platforms the goal is even to have a shared defconfig across
> SoC families, but PXA is one of the exceptions that I would make because
> it is both old and rather different from even the ARM9 or Marvell Feroceon
> based SoCs.

There is probably no in point sharing this config with most other
devices on PXA2xx SoC. This device is an industrial PC. Its config needs
to be optimized for low latency even by the cost of greater power
consumption. It is not supposed to run on batteries or enter any low
power mode anyway.

> > +#define LP8X4X_FPGA_PHYS     0x17000000
> > +#define LP8X4X_FPGA_VIRT     0xf1000000
> > +#define LP8X4X_P2V(x)                IOMEM((x) - LP8X4X_FPGA_PHYS + LP8X4X_FPGA_VIRT)
> > +#define LP8X4X_V2P(x)                ((x) - LP8X4X_FPGA_VIRT + LP8X4X_FPGA_PHYS)
> 
> I would recommend defining LP8X4X_FPGA_VIRT as "(void *)0xf1000000". Ideally

Done in v2. 

> we try to avoid hardwired virtual addresses entirely and instead use platform
> device resources, but I realize that there are limits to how far you get with
> that. Please make an effort to convert as many parts of the FPGA into platform
> devices with regular resources, but know that we would not enforce this as
> strictly as we do for new platforms.
> 
> > +
> > +static struct irq_chip lp8x4x_irq_chip = {
> > +     .name                   = "FPGA",
> > +     .irq_ack                = lp8x4x_ack_irq,
> > +     .irq_mask               = lp8x4x_mask_irq,
> > +     .irq_unmask             = lp8x4x_unmask_irq,
> > +};
> 
> Please try to move the irqchip code to drivers/irqchip/.

CONFIG_IRQCHIP depends on CONFIG_OF_IRQ which in turn depends on Open
Firmware.

The device is shipped with such a flash device partition table, which
makes migration to device tree rather difficult. The partition for
U-Boot is just 256kiB. This is a high aim already. U-Boot needs to be
compiled without command line help and USB support to fit into this
size. Otherwise the main flash needs to be repartitioned.

Could it be acceptable to accept the device without device tree support?

If so, FPGA irqchip could remain in the machine source file. It is
highly unlikely, it will ever be reused. In this case all fixed virtual
address definitions could be moved to the machine source file. The file
will be the only place where LP8X4X_FPGA_VIRT is used directly.

> > +static struct platform_device lp8x4x_flash_device[] = {
> 
> static platform_device definitions are no longer the way to do this. For
> modern platforms, you'd use a device tree, but here I think it is acceptable
> (because of the PXA exception) to use a hardcoded board file.
> 
> The correct way to create the devices is using platform_device_register_data()
> or a related function that returns a dynamically allocated platform device.

Done in v2. Allocation migrated to use
platform_device_register_resndata() and
platform_device_register_simple().



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

* [PATCH 02/11] arm: pxa27x: support ICP DAS LP-8x4x
@ 2013-12-06 16:38       ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-06 16:38 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, 2013-12-06 at 01:40 +0100, Arnd Bergmann wrote:
> On Sunday 01 December 2013, Sergei Ianovich wrote:
> > 
> > diff --git a/arch/arm/configs/lp8x4x_defconfig b/arch/arm/configs/lp8x4x_defconfig
> > new file mode 100644
> > index 0000000..5cd6d38
> > --- /dev/null
> > +++ b/arch/arm/configs/lp8x4x_defconfig
> > @@ -0,0 +1,2320 @@
> > +#
> > +# Automatically generated file; DO NOT EDIT.
> > +# Linux/arm 3.13.0-rc1 Kernel Configuration
> > +#
> 
> Please use 'make savedefconfig' to generate a smaller version of this file.

Done. Updated in v2.

> Ideally we want shared defconfigs where you enable multiple (or all) pxa boards
> at once and end up with a kernel that works on all of them.
> 
> For most other platforms the goal is even to have a shared defconfig across
> SoC families, but PXA is one of the exceptions that I would make because
> it is both old and rather different from even the ARM9 or Marvell Feroceon
> based SoCs.

There is probably no in point sharing this config with most other
devices on PXA2xx SoC. This device is an industrial PC. Its config needs
to be optimized for low latency even by the cost of greater power
consumption. It is not supposed to run on batteries or enter any low
power mode anyway.

> > +#define LP8X4X_FPGA_PHYS     0x17000000
> > +#define LP8X4X_FPGA_VIRT     0xf1000000
> > +#define LP8X4X_P2V(x)                IOMEM((x) - LP8X4X_FPGA_PHYS + LP8X4X_FPGA_VIRT)
> > +#define LP8X4X_V2P(x)                ((x) - LP8X4X_FPGA_VIRT + LP8X4X_FPGA_PHYS)
> 
> I would recommend defining LP8X4X_FPGA_VIRT as "(void *)0xf1000000". Ideally

Done in v2. 

> we try to avoid hardwired virtual addresses entirely and instead use platform
> device resources, but I realize that there are limits to how far you get with
> that. Please make an effort to convert as many parts of the FPGA into platform
> devices with regular resources, but know that we would not enforce this as
> strictly as we do for new platforms.
> 
> > +
> > +static struct irq_chip lp8x4x_irq_chip = {
> > +     .name                   = "FPGA",
> > +     .irq_ack                = lp8x4x_ack_irq,
> > +     .irq_mask               = lp8x4x_mask_irq,
> > +     .irq_unmask             = lp8x4x_unmask_irq,
> > +};
> 
> Please try to move the irqchip code to drivers/irqchip/.

CONFIG_IRQCHIP depends on CONFIG_OF_IRQ which in turn depends on Open
Firmware.

The device is shipped with such a flash device partition table, which
makes migration to device tree rather difficult. The partition for
U-Boot is just 256kiB. This is a high aim already. U-Boot needs to be
compiled without command line help and USB support to fit into this
size. Otherwise the main flash needs to be repartitioned.

Could it be acceptable to accept the device without device tree support?

If so, FPGA irqchip could remain in the machine source file. It is
highly unlikely, it will ever be reused. In this case all fixed virtual
address definitions could be moved to the machine source file. The file
will be the only place where LP8X4X_FPGA_VIRT is used directly.

> > +static struct platform_device lp8x4x_flash_device[] = {
> 
> static platform_device definitions are no longer the way to do this. For
> modern platforms, you'd use a device tree, but here I think it is acceptable
> (because of the PXA exception) to use a hardcoded board file.
> 
> The correct way to create the devices is using platform_device_register_data()
> or a related function that returns a dynamically allocated platform device.

Done in v2. Allocation migrated to use
platform_device_register_resndata() and
platform_device_register_simple().

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

* [PATCH v2 02/11] arm: pxa27x: support ICP DAS LP-8x4x
  2013-12-01  6:26   ` Sergei Ianovich
@ 2013-12-06 16:48     ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-06 16:48 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Arnd Bergmann, Russell King, Eric Miao, Haojian Zhuang

ICP DAS calls LP-8x4x 'programmable automation controller'. It is
an industrial computer based on PXA270 SoC. They ship it with a 2.6.19
kernel and proprietary kernel module and userspace library to access
its industrial IO.

This patch allows to boot the device with a modern kernel. It adds
support for:
* FPGA irq chip
* MMC card interface on PXA270
* USB 1.1 port on PXA270
* 2 NOR flash devices
* VGA interface on PXA270
* 2 onboard ethernet Davicom DM9000 devices
* 3 serial UART ports on PXA270

Support for these devices will be added in separate patches, since
they are not currently supported by the kernel:
* DS1302 RTC
* 512kiB SRAM
* 3 built-in and up to 32 pluggable 8250 serial UART ports
* industrial IO parallel bus
* digital and analog industrial IO modules for parallel bus
* serial interface for digital and analog industrial IO modules on
  parallel bus

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Arnd Bergmann <arnd@arndb.de>
---
 changes v1..v2
 * clean up defconfig (reduces size by 10) as suggested 
   by Arnd Bergmann

 * fixed constant address definition to include (void *) cast
   as suggested by Arnd Bergmann

 * moved fixed virtual addresses into the machine source file.
   Header file is dropped.

 * static platform devices are replaced by dynamically allocated
   as suggested by Arnd Bergmann

 arch/arm/configs/lp8x4x_defconfig | 235 +++++++++++++++++++
 arch/arm/mach-pxa/Kconfig         |  16 ++
 arch/arm/mach-pxa/Makefile        |   1 +
 arch/arm/mach-pxa/lp8x4x.c        | 473 ++++++++++++++++++++++++++++++++++++++
 4 files changed, 725 insertions(+)
 create mode 100644 arch/arm/configs/lp8x4x_defconfig
 create mode 100644 arch/arm/mach-pxa/lp8x4x.c

diff --git a/arch/arm/configs/lp8x4x_defconfig b/arch/arm/configs/lp8x4x_defconfig
new file mode 100644
index 0000000..2612e60
--- /dev/null
+++ b/arch/arm/configs/lp8x4x_defconfig
@@ -0,0 +1,235 @@
+CONFIG_CROSS_COMPILE="arm-linux-gnueabi-"
+# CONFIG_LOCALVERSION_AUTO is not set
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_RCU_BOOST=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_NS is not set
+# CONFIG_IPC_NS is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+# CONFIG_UID16 is not set
+# CONFIG_SHMEM is not set
+CONFIG_EMBEDDED=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_SLOB=y
+CONFIG_JUMP_LABEL=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+# CONFIG_LBDAF is not set
+CONFIG_BLK_CMDLINE_PARSER=y
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_MINIX_SUBPARTITION=y
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_UNIXWARE_DISKLABEL=y
+CONFIG_LDM_PARTITION=y
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_ARCH_PXA=y
+CONFIG_MACH_LP8X4X=y
+# CONFIG_ARM_THUMB is not set
+CONFIG_PREEMPT=y
+CONFIG_AEABI=y
+# CONFIG_COMPACTION is not set
+# CONFIG_CROSS_MEMORY_ATTACH is not set
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="init=/sbin/init root=/dev/mmcblk0p1 rw rootfstype=ext4 console=ttyS0,115200 mem=128M rootwait"
+# CONFIG_SUSPEND is not set
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_BRIDGE=m
+CONFIG_BRIDGE_VLAN_FILTERING=y
+CONFIG_VLAN_8021Q=m
+CONFIG_VLAN_8021Q_GVRP=y
+CONFIG_VLAN_8021Q_MVRP=y
+# CONFIG_WIRELESS is not set
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+# CONFIG_FW_LOADER is not set
+CONFIG_MTD=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_CFI_GEOMETRY=y
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_PXA2XX=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_LOOP_MIN_COUNT=2
+CONFIG_SCSI=y
+# CONFIG_SCSI_PROC_FS is not set
+CONFIG_BLK_DEV_SD=y
+# CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_NETDEVICES=y
+CONFIG_BONDING=m
+CONFIG_MACVLAN=m
+CONFIG_MACVTAP=m
+CONFIG_TUN=m
+# CONFIG_NET_VENDOR_ARC is not set
+# CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_CIRRUS is not set
+CONFIG_DM9000=y
+CONFIG_DM9000_FORCE_SIMPLE_PHY_POLL=y
+# CONFIG_NET_VENDOR_FARADAY is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+CONFIG_PPP=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPPOE=m
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_SLIP=m
+CONFIG_SLIP_COMPRESSED=y
+# CONFIG_WLAN is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=800
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=600
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_SERIO is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_8250=y
+# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=40
+CONFIG_SERIAL_8250_RUNTIME_UARTS=40
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_PXA=y
+CONFIG_HW_RANDOM=y
+CONFIG_I2C=m
+# CONFIG_I2C_COMPAT is not set
+CONFIG_I2C_PXA=m
+CONFIG_I2C_PXA_SLAVE=y
+# CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_SA1100_WATCHDOG=m
+CONFIG_FB=y
+CONFIG_FB_PXA=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_LOGO=y
+CONFIG_HID_GENERIC=m
+CONFIG_HID_A4TECH=m
+CONFIG_HID_CYPRESS=m
+CONFIG_HID_KEYTOUCH=m
+CONFIG_HID_KENSINGTON=m
+CONFIG_HID_LOGITECH=m
+CONFIG_HID_MICROSOFT=m
+CONFIG_HID_MONTEREY=m
+CONFIG_USB_HIDDEV=y
+CONFIG_I2C_HID=m
+CONFIG_USB=m
+CONFIG_USB_OHCI_HCD=m
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+CONFIG_USB_STORAGE=m
+CONFIG_USB_STORAGE_REALTEK=m
+CONFIG_USB_STORAGE_DATAFAB=m
+CONFIG_USB_STORAGE_FREECOM=m
+CONFIG_USB_STORAGE_ISD200=m
+CONFIG_USB_STORAGE_USBAT=m
+CONFIG_USB_STORAGE_SDDR09=m
+CONFIG_USB_STORAGE_SDDR55=m
+CONFIG_USB_STORAGE_JUMPSHOT=m
+CONFIG_USB_STORAGE_ALAUDA=m
+CONFIG_USB_STORAGE_ONETOUCH=m
+CONFIG_USB_STORAGE_KARMA=m
+CONFIG_USB_STORAGE_CYPRESS_ATACB=m
+CONFIG_USB_STORAGE_ENE_UB6250=m
+CONFIG_USB_SERIAL=m
+CONFIG_USB_SERIAL_GENERIC=y
+CONFIG_USB_SERIAL_SIMPLE=m
+CONFIG_USB_SERIAL_AIRCABLE=m
+CONFIG_USB_SERIAL_ARK3116=m
+CONFIG_USB_SERIAL_BELKIN=m
+CONFIG_USB_SERIAL_CH341=m
+CONFIG_USB_SERIAL_WHITEHEAT=m
+CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
+CONFIG_USB_SERIAL_CP210X=m
+CONFIG_USB_SERIAL_CYPRESS_M8=m
+CONFIG_USB_SERIAL_EMPEG=m
+CONFIG_USB_SERIAL_FTDI_SIO=m
+CONFIG_USB_SERIAL_VISOR=m
+CONFIG_USB_SERIAL_IPAQ=m
+CONFIG_USB_SERIAL_IR=m
+CONFIG_USB_SERIAL_EDGEPORT=m
+CONFIG_USB_SERIAL_EDGEPORT_TI=m
+CONFIG_USB_SERIAL_F81232=m
+CONFIG_USB_SERIAL_GARMIN=m
+CONFIG_USB_SERIAL_IPW=m
+CONFIG_USB_SERIAL_IUU=m
+CONFIG_USB_SERIAL_KEYSPAN_PDA=m
+CONFIG_USB_SERIAL_KEYSPAN=m
+CONFIG_USB_SERIAL_KLSI=m
+CONFIG_USB_SERIAL_KOBIL_SCT=m
+CONFIG_USB_SERIAL_MCT_U232=m
+CONFIG_USB_SERIAL_METRO=m
+CONFIG_USB_SERIAL_MOS7720=m
+CONFIG_USB_SERIAL_MOS7840=m
+CONFIG_USB_SERIAL_NAVMAN=m
+CONFIG_USB_SERIAL_PL2303=m
+CONFIG_USB_SERIAL_OTI6858=m
+CONFIG_USB_SERIAL_QCAUX=m
+CONFIG_USB_SERIAL_QUALCOMM=m
+CONFIG_USB_SERIAL_SPCP8X5=m
+CONFIG_USB_SERIAL_SAFE=m
+CONFIG_USB_SERIAL_SAFE_PADDED=y
+CONFIG_USB_SERIAL_SIERRAWIRELESS=m
+CONFIG_USB_SERIAL_SYMBOL=m
+CONFIG_USB_SERIAL_TI=m
+CONFIG_USB_SERIAL_CYBERJACK=m
+CONFIG_USB_SERIAL_XIRCOM=m
+CONFIG_USB_SERIAL_OPTION=m
+CONFIG_USB_SERIAL_OMNINET=m
+CONFIG_USB_SERIAL_OPTICON=m
+CONFIG_USB_SERIAL_XSENS_MT=m
+CONFIG_USB_SERIAL_WISHBONE=m
+CONFIG_USB_SERIAL_ZTE=m
+CONFIG_USB_SERIAL_SSU100=m
+CONFIG_USB_SERIAL_QT2=m
+CONFIG_MMC=y
+CONFIG_MMC_PXA=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_PXA=m
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_EXT2_FS=m
+CONFIG_EXT3_FS=y
+CONFIG_EXT4_FS=y
+CONFIG_REISERFS_FS=m
+CONFIG_ISO9660_FS=m
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_NTFS_FS=m
+CONFIG_NTFS_RW=y
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V4=y
+CONFIG_ROOT_NFS=y
+CONFIG_CIFS=m
+CONFIG_CIFS_STATS=y
+CONFIG_CODA_FS=m
+CONFIG_NLS_DEFAULT="cp1251"
+CONFIG_NLS_CODEPAGE_1251=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_UTF8=y
+CONFIG_PRINTK_TIME=y
diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig
index 96100db..efaf2d0 100644
--- a/arch/arm/mach-pxa/Kconfig
+++ b/arch/arm/mach-pxa/Kconfig
@@ -273,6 +273,22 @@ config MACH_VPAC270
 
 comment "End-user Products (sorted by vendor name)"
 
+config MACH_LP8X4X
+	bool "ICP DAS LP-8X4X"
+	select IWMMXT
+	select PXA27x
+	help
+	  Say Y here if you intend to run this kernel on an ICP DAS
+	  LP-8x4x programmable automation controller.
+
+	  LP-8x4x is ARM-based and built around PXA270 SoC. The device
+	  has 128 MiB SDRAM, 48 or 96 MiB NOR flash, VGA port with
+	  800x600 resolution, MMC card slot, 2 Ethernet ports, 1 USB
+	  port, 5 serial ports (1 on them is wired internally to
+	  expansion slots). The device has a range of digital and
+	  analog expansion IO modules which can be installed in 1, 4 or
+	  8 slots depending on the model.
+
 config MACH_H4700
 	bool "HP iPAQ hx4700"
 	select HAVE_PWM
diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile
index 648867a..b264325 100644
--- a/arch/arm/mach-pxa/Makefile
+++ b/arch/arm/mach-pxa/Makefile
@@ -63,6 +63,7 @@ obj-$(CONFIG_MACH_COLIBRI320)	+= colibri-pxa3xx.o colibri-pxa320.o
 obj-$(CONFIG_MACH_VPAC270)	+= vpac270.o
 
 # End-user Products
+obj-$(CONFIG_MACH_LP8X4X)	+= lp8x4x.o
 obj-$(CONFIG_MACH_H4700)	+= hx4700.o
 obj-$(CONFIG_MACH_H5000)	+= h5000.o
 obj-$(CONFIG_MACH_HIMALAYA)	+= himalaya.o
diff --git a/arch/arm/mach-pxa/lp8x4x.c b/arch/arm/mach-pxa/lp8x4x.c
new file mode 100644
index 0000000..0d3d8c0
--- /dev/null
+++ b/arch/arm/mach-pxa/lp8x4x.c
@@ -0,0 +1,473 @@
+/*
+ *  linux/arch/arm/mach-pxa/lp8x4x.c
+ *
+ *  Support for ICP DAS LP-8x4x programmable automation controller
+ *  Copyright (C) 2013 Sergei Ianovich <ynvich@gmail.com>
+ *
+ *  borrowed heavily from
+ *  Support for the Intel HCDDBBVA0 Development Platform.
+ *
+ *  Author:	Nicolas Pitre
+ *  Created:	Nov 05, 2002
+ *  Copyright:	MontaVista Software Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation or any later version.
+ */
+#include <linux/gpio.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/syscore_ops.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/bitops.h>
+#include <linux/fb.h>
+#include <linux/ioport.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/input.h>
+#include <linux/dm9000.h>
+#include <linux/slab.h>
+#include <linux/leds.h>
+#include <linux/ktime.h>
+#include <linux/irqchip/chained_irq.h>
+
+#include <asm/types.h>
+#include <asm/setup.h>
+#include <asm/memory.h>
+#include <asm/mach-types.h>
+#include <mach/hardware.h>
+#include <asm/irq.h>
+#include <asm/sizes.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+#include <asm/mach/flash.h>
+
+#include <mach/irqs.h>
+#include <mach/pxa27x.h>
+#include <linux/platform_data/video-pxafb.h>
+#include <linux/platform_data/mmc-pxamci.h>
+#include <linux/platform_data/usb-ohci-pxa27x.h>
+#include <mach/smemc.h>
+
+#include "generic.h"
+#include "devices.h"
+
+#define LP8X4X_ETH0_BASE        0x0c000000
+#define LP8X4X_ETH0_IO          0x0c004000
+#define LP8X4X_ETH0_IRQ         PXA_GPIO_TO_IRQ(9)
+
+#define LP8X4X_ETH1_BASE        0x0d000000
+#define LP8X4X_ETH1_IO          0x0d004000
+#define LP8X4X_ETH1_IRQ         PXA_GPIO_TO_IRQ(82)
+
+#define LP8X4X_FPGA_PHYS	0x17000000
+#define LP8X4X_FPGA_VIRT	((void *) 0xf1000000)
+#define LP8X4X_P2V(x)		IOMEM((x) - LP8X4X_FPGA_PHYS + LP8X4X_FPGA_VIRT)
+#define LP8X4X_V2P(x)		((x) - LP8X4X_FPGA_VIRT + LP8X4X_FPGA_PHYS)
+
+/* board level registers in the FPGA */
+
+#define LP8X4X_EOI		LP8X4X_P2V(0x17009006)
+#define LP8X4X_INSINT		LP8X4X_P2V(0x17009008)
+#define LP8X4X_ENSYSINT		LP8X4X_P2V(0x1700900A)
+#define LP8X4X_PRIMINT		LP8X4X_P2V(0x1700900C)
+#define LP8X4X_SECOINT		LP8X4X_P2V(0x1700900E)
+#define LP8X4X_ENRISEINT	LP8X4X_P2V(0x17009010)
+#define LP8X4X_CLRRISEINT	LP8X4X_P2V(0x17009012)
+#define LP8X4X_ENHILVINT	LP8X4X_P2V(0x17009014)
+#define LP8X4X_CLRHILVINT	LP8X4X_P2V(0x17009016)
+#define LP8X4X_ENFALLINT	LP8X4X_P2V(0x17009018)
+#define LP8X4X_CLRFALLINT	LP8X4X_P2V(0x1700901a)
+
+/* board specific IRQs */
+
+#define LP8X4X_IRQ(x)		(IRQ_BOARD_START + (x))
+#define LP8X4X_SLOT1_IRQ	LP8X4X_IRQ(0)
+#define LP8X4X_SLOT2_IRQ	LP8X4X_IRQ(1)
+#define LP8X4X_SLOT3_IRQ	LP8X4X_IRQ(2)
+#define LP8X4X_SLOT4_IRQ	LP8X4X_IRQ(3)
+#define LP8X4X_SLOT5_IRQ	LP8X4X_IRQ(4)
+#define LP8X4X_SLOT6_IRQ	LP8X4X_IRQ(5)
+#define LP8X4X_SLOT7_IRQ	LP8X4X_IRQ(6)
+#define LP8X4X_SLOT8_IRQ	LP8X4X_IRQ(7)
+#define LP8X4X_TIMER1_IRQ	LP8X4X_IRQ(8)
+#define LP8X4X_TIMER2_IRQ	LP8X4X_IRQ(9)
+#define LP8X4X_TIMEROUT_IRQ	LP8X4X_IRQ(10)
+#define LP8X4X_HOTPLUG_IRQ	LP8X4X_IRQ(11)
+#define LP8X4X_BATLOW_IRQ	LP8X4X_IRQ(12)
+#define LP8X4X_TTYS0_IRQ	LP8X4X_IRQ(13)
+#define LP8X4X_TTYS1_IRQ	LP8X4X_IRQ(14)
+#define LP8X4X_TTYS2_IRQ	LP8X4X_IRQ(15)
+
+#define LP8X4X_NR_IRQS		(IRQ_BOARD_START + 16)
+
+static unsigned char lp8x4x_irq_sys_enabled;
+static unsigned char lp8x4x_irq_high_enabled;
+
+static void lp8x4x_ack_irq(struct irq_data *d)
+{
+	unsigned mask;
+	int irq = d->irq - IRQ_BOARD_START;
+
+	if (irq < 0 || irq > 15) {
+		pr_err("lp8x4x: wrong irq handler for irq %i\n", d->irq);
+		return;
+	}
+
+	if (irq < 8) {
+		mask = ioread8(LP8X4X_CLRHILVINT);
+		mask |= 1 << irq;
+		iowrite8(mask, LP8X4X_CLRHILVINT);
+	} else if (irq < 13) {
+		irq -= 8;
+		mask = ioread8(LP8X4X_SECOINT);
+		mask |= 1 << irq;
+		iowrite8(mask, LP8X4X_SECOINT);
+	} else {
+		irq -= 8;
+		mask = ioread8(LP8X4X_PRIMINT);
+		mask |= 1 << irq;
+		iowrite8(mask, LP8X4X_PRIMINT);
+	}
+}
+
+static void lp8x4x_mask_irq(struct irq_data *d)
+{
+	int irq = d->irq - IRQ_BOARD_START;
+
+	if (irq < 0 || irq > 15) {
+		pr_err("lp8x4x: wrong irq handler for irq %i\n", d->irq);
+		return;
+	}
+
+	if (irq < 8) {
+		lp8x4x_irq_high_enabled &= ~(1 << irq);
+		iowrite8(lp8x4x_irq_high_enabled, LP8X4X_ENHILVINT);
+	} else {
+		irq -= 8;
+		lp8x4x_irq_sys_enabled &= ~(1 << irq);
+		iowrite8(lp8x4x_irq_sys_enabled, LP8X4X_ENSYSINT);
+	}
+}
+
+static void lp8x4x_unmask_irq(struct irq_data *d)
+{
+	unsigned mask;
+	int irq = d->irq - IRQ_BOARD_START;
+
+	if (irq < 0 || irq > 15) {
+		pr_err("wrong irq handler for irq %i\n", d->irq);
+		return;
+	}
+
+	if (irq < 8) {
+		lp8x4x_irq_high_enabled |= 1 << irq;
+		mask = ioread8(LP8X4X_CLRHILVINT);
+		mask |= 1 << irq;
+		iowrite8(mask, LP8X4X_CLRHILVINT);
+		iowrite8(lp8x4x_irq_high_enabled, LP8X4X_ENHILVINT);
+	} else if (irq < 13) {
+		irq -= 8;
+		lp8x4x_irq_sys_enabled |= 1 << irq;
+		mask = ioread8(LP8X4X_SECOINT);
+		mask |= 1 << irq;
+		iowrite8(mask, LP8X4X_SECOINT);
+		iowrite8(lp8x4x_irq_sys_enabled, LP8X4X_ENSYSINT);
+	} else {
+		irq -= 8;
+		lp8x4x_irq_sys_enabled |= 1 << irq;
+		mask = ioread8(LP8X4X_PRIMINT);
+		mask |= 1 << irq;
+		iowrite8(mask, LP8X4X_PRIMINT);
+		iowrite8(lp8x4x_irq_sys_enabled, LP8X4X_ENSYSINT);
+	}
+}
+
+static struct irq_chip lp8x4x_irq_chip = {
+	.name			= "FPGA",
+	.irq_ack		= lp8x4x_ack_irq,
+	.irq_mask		= lp8x4x_mask_irq,
+	.irq_unmask		= lp8x4x_unmask_irq,
+};
+
+static spinlock_t fpga_irq_lock;
+
+static void lp8x4x_irq_handler(unsigned int irq, struct irq_desc *desc)
+{
+	int loop, n;
+	unsigned long mask;
+	unsigned long flags;
+	struct irq_chip *chip = irq_desc_get_chip(desc);
+
+	spin_lock_irqsave(&fpga_irq_lock, flags);
+	chained_irq_enter(chip, desc);
+
+	do {
+		loop = 0;
+		mask = ioread8(LP8X4X_CLRHILVINT) & 0xff;
+		mask |= (ioread8(LP8X4X_SECOINT) & 0x1f) << 8;
+		mask |= (ioread8(LP8X4X_PRIMINT) & 0xe0) << 8;
+		mask &= (lp8x4x_irq_high_enabled
+				| (lp8x4x_irq_sys_enabled << 8));
+		for_each_set_bit(n, &mask, BITS_PER_LONG) {
+			loop = 1;
+
+			generic_handle_irq(IRQ_BOARD_START + n);
+		}
+	} while (loop);
+
+	chained_irq_exit(chip, desc);
+	iowrite8(0, LP8X4X_EOI);
+	spin_unlock_irqrestore(&fpga_irq_lock, flags);
+}
+
+static void __init lp8x4x_init_irq(void)
+{
+	int irq;
+	int err;
+
+	err = irq_set_irq_type(PXA_GPIO_TO_IRQ(3), IRQ_TYPE_EDGE_RISING);
+	if (err < 0) {
+		pr_err("lp8x4x: irq init failed\n");
+		return;
+	}
+
+	spin_lock_init(&fpga_irq_lock);
+	irq_set_chained_handler(PXA_GPIO_TO_IRQ(3), lp8x4x_irq_handler);
+
+	for (irq = IRQ_BOARD_START; irq < LP8X4X_NR_IRQS; irq++) {
+		irq_set_chip_and_handler(irq, &lp8x4x_irq_chip,
+					 handle_level_irq);
+		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+	}
+
+	iowrite8(0, LP8X4X_CLRRISEINT);
+	iowrite8(0, LP8X4X_ENRISEINT);
+	iowrite8(0, LP8X4X_CLRFALLINT);
+	iowrite8(0, LP8X4X_ENFALLINT);
+	iowrite8(0, LP8X4X_CLRHILVINT);
+	iowrite8(0, LP8X4X_ENHILVINT);
+	iowrite8(0, LP8X4X_ENSYSINT);
+	iowrite8(0, LP8X4X_PRIMINT);
+	iowrite8(0, LP8X4X_SECOINT);
+
+	return;
+}
+
+static unsigned long lp8x4x_pin_config[] = {
+	/* MMC */
+	GPIO32_MMC_CLK,
+	GPIO112_MMC_CMD,
+	GPIO92_MMC_DAT_0,
+	GPIO109_MMC_DAT_1,
+	GPIO110_MMC_DAT_2,
+	GPIO111_MMC_DAT_3,
+
+	/* USB Host Port 1 */
+	GPIO88_USBH1_PWR,
+	GPIO89_USBH1_PEN,
+};
+
+static struct resource lp8x4x_flash_resources[] __initdata = {
+	[0] = {
+		.start	= PXA_CS0_PHYS,
+		.end	= PXA_CS0_PHYS + SZ_64M - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= PXA_CS1_PHYS,
+		.end	= PXA_CS1_PHYS + SZ_32M - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct mtd_partition lp8x4x_flash0_partitions[] = {
+	{
+		.name =		"Bootloader",
+		.size =		0x00040000,
+		.offset =	0,
+	}, {
+		.name =		"Settings",
+		.size =		0x00040000,
+		.offset =	0x00040000,
+	}, {
+		.name =		"Kernel",
+		.size =		0x00280000,
+		.offset =	0x00080000,
+	}, {
+		.name =		"Filesystem",
+		.size =		MTDPART_SIZ_FULL,
+		.offset =	0x00300000
+	}
+};
+
+static struct flash_platform_data lp8x4x_flash_data[] __initdata = {
+	{
+		.map_name	= "cfi_probe",
+		.parts		= lp8x4x_flash0_partitions,
+		.nr_parts	= ARRAY_SIZE(lp8x4x_flash0_partitions),
+		.width		= 4,
+	}, {
+		.map_name	= "cfi_probe",
+		.parts		= NULL,
+		.nr_parts	= 0,
+		.width		= 2,
+	}
+};
+
+static struct pxafb_mode_info lp8x4x_vga_60_mode = {
+	.pixclock       = 38461,
+	.xres           = 640,
+	.yres           = 480,
+	.bpp            = 16,
+	.hsync_len      = 64,
+	.left_margin    = 78,
+	.right_margin   = 46,
+	.vsync_len      = 12,
+	.upper_margin   = 22,
+	.lower_margin   = 10,
+	.sync           = 0,
+};
+
+static struct pxafb_mach_info lp8x4x_pxafb_info = {
+	.num_modes		= 1,
+	.lccr0			= LCCR0_Act,
+	.lccr3			= LCCR3_PCP,
+};
+
+static int lp8x4x_mci_init(struct device *dev,
+		irq_handler_t mstone_detect_int, void *data)
+{
+	return 0;
+}
+
+static int lp8x4x_mci_setpower(struct device *dev, unsigned int vdd)
+{
+	return 0;
+}
+
+static void lp8x4x_mci_exit(struct device *dev, void *data)
+{
+}
+
+static struct pxamci_platform_data lp8x4x_mci_platform_data = {
+	.ocr_mask		= MMC_VDD_32_33|MMC_VDD_33_34,
+	.init			= lp8x4x_mci_init,
+	.setpower               = lp8x4x_mci_setpower,
+	.exit			= lp8x4x_mci_exit,
+	.gpio_card_detect	= -1,
+	.gpio_card_ro		= -1,
+	.gpio_power		= -1,
+};
+
+static struct resource lp8x4x_dm9000_resources[] __initdata = {
+	[0] = {
+		.start  = LP8X4X_ETH0_BASE,
+		.end    = LP8X4X_ETH0_BASE + 2 - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start  = LP8X4X_ETH0_IO,
+		.end    = LP8X4X_ETH0_IO + 2 - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	[2] = {
+		.start  = LP8X4X_ETH0_IRQ,
+		.end    = LP8X4X_ETH0_IRQ,
+		.flags	= IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE,
+	},
+	[3] = {
+		.start  = LP8X4X_ETH1_BASE,
+		.end    = LP8X4X_ETH1_BASE + 2 - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	[4] = {
+		.start  = LP8X4X_ETH1_IO,
+		.end    = LP8X4X_ETH1_IO + 2 - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	[5] = {
+		.start  = LP8X4X_ETH1_IRQ,
+		.end    = LP8X4X_ETH1_IRQ,
+		.flags	= IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE,
+	},
+};
+
+static struct pxaohci_platform_data lp8x4x_ohci_platform_data = {
+	.port_mode	= PMM_PERPORT_MODE,
+	.flags		= ENABLE_PORT1 | OC_MODE_PERPORT,
+};
+
+static void lp8x4x_restart(enum reboot_mode mode, const char *cmd)
+{
+	/* Switch off fast-bus and turbo mode */
+	asm volatile("mcr       p14, 0, %0, c6, c0, 0" : :
+			"r"(2));
+	/* SDRAM hangs on watchdog reset on Marvell PXA270 (erratum 71) */
+	pxa_restart(REBOOT_SOFT, cmd);
+}
+
+static void __init lp8x4x_init(void)
+{
+	pxa2xx_mfp_config(ARRAY_AND_SIZE(lp8x4x_pin_config));
+
+	pxa_set_ffuart_info(NULL);
+	pxa_set_btuart_info(NULL);
+	pxa_set_stuart_info(NULL);
+
+	/* system bus arbiter setting
+	 * - Core_Park
+	 * - LCD_wt:DMA_wt:CORE_Wt = 2:3:4
+	 */
+	ARB_CNTRL = ARB_CORE_PARK | 0x234;
+
+	pxa_set_mci_info(&lp8x4x_mci_platform_data);
+	pxa_set_ohci_info(&lp8x4x_ohci_platform_data);
+
+	platform_device_register_resndata(NULL, "pxa2xx-flash", 0,
+			&lp8x4x_flash_resources[0], 1,
+			&lp8x4x_flash_data[0], sizeof(lp8x4x_flash_data[0]));
+	platform_device_register_resndata(NULL, "pxa2xx-flash", 1,
+			&lp8x4x_flash_resources[1], 1,
+			&lp8x4x_flash_data[1], sizeof(lp8x4x_flash_data[1]));
+	platform_device_register_simple("dm9000", 0,
+			&lp8x4x_dm9000_resources[0], 3);
+	platform_device_register_simple("dm9000", 1,
+			&lp8x4x_dm9000_resources[3], 3);
+
+	lp8x4x_pxafb_info.modes = &lp8x4x_vga_60_mode;
+	pxa_set_fb_info(NULL, &lp8x4x_pxafb_info);
+
+	/* Could not do this in MACHINE since GPIO is not ready then */
+	lp8x4x_init_irq();
+}
+
+static struct map_desc lp8x4x_io_desc[] __initdata = {
+	{	/* CPLD */
+		.virtual	=  (unsigned long) LP8X4X_FPGA_VIRT,
+		.pfn		= __phys_to_pfn(LP8X4X_FPGA_PHYS),
+		.length		= 0x00100000,
+		.type		= MT_DEVICE
+	}
+};
+
+static void __init lp8x4x_map_io(void)
+{
+	pxa27x_map_io();
+	iotable_init(lp8x4x_io_desc, ARRAY_SIZE(lp8x4x_io_desc));
+}
+
+MACHINE_START(LP8X4X, "ICP DAS LP-8x4x programmable automation controller")
+	.atag_offset	= 0x100,
+	.map_io		= lp8x4x_map_io,
+	.nr_irqs	= LP8X4X_NR_IRQS,
+	.init_irq	= pxa27x_init_irq,
+	.handle_irq	= pxa27x_handle_irq,
+	.init_time	= pxa_timer_init,
+	.init_machine	= lp8x4x_init,
+	.restart	= lp8x4x_restart,
+MACHINE_END
-- 
1.8.4.2


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

* [PATCH v2 02/11] arm: pxa27x: support ICP DAS LP-8x4x
@ 2013-12-06 16:48     ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-06 16:48 UTC (permalink / raw)
  To: linux-arm-kernel

ICP DAS calls LP-8x4x 'programmable automation controller'. It is
an industrial computer based on PXA270 SoC. They ship it with a 2.6.19
kernel and proprietary kernel module and userspace library to access
its industrial IO.

This patch allows to boot the device with a modern kernel. It adds
support for:
* FPGA irq chip
* MMC card interface on PXA270
* USB 1.1 port on PXA270
* 2 NOR flash devices
* VGA interface on PXA270
* 2 onboard ethernet Davicom DM9000 devices
* 3 serial UART ports on PXA270

Support for these devices will be added in separate patches, since
they are not currently supported by the kernel:
* DS1302 RTC
* 512kiB SRAM
* 3 built-in and up to 32 pluggable 8250 serial UART ports
* industrial IO parallel bus
* digital and analog industrial IO modules for parallel bus
* serial interface for digital and analog industrial IO modules on
  parallel bus

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Arnd Bergmann <arnd@arndb.de>
---
 changes v1..v2
 * clean up defconfig (reduces size by 10) as suggested 
   by Arnd Bergmann

 * fixed constant address definition to include (void *) cast
   as suggested by Arnd Bergmann

 * moved fixed virtual addresses into the machine source file.
   Header file is dropped.

 * static platform devices are replaced by dynamically allocated
   as suggested by Arnd Bergmann

 arch/arm/configs/lp8x4x_defconfig | 235 +++++++++++++++++++
 arch/arm/mach-pxa/Kconfig         |  16 ++
 arch/arm/mach-pxa/Makefile        |   1 +
 arch/arm/mach-pxa/lp8x4x.c        | 473 ++++++++++++++++++++++++++++++++++++++
 4 files changed, 725 insertions(+)
 create mode 100644 arch/arm/configs/lp8x4x_defconfig
 create mode 100644 arch/arm/mach-pxa/lp8x4x.c

diff --git a/arch/arm/configs/lp8x4x_defconfig b/arch/arm/configs/lp8x4x_defconfig
new file mode 100644
index 0000000..2612e60
--- /dev/null
+++ b/arch/arm/configs/lp8x4x_defconfig
@@ -0,0 +1,235 @@
+CONFIG_CROSS_COMPILE="arm-linux-gnueabi-"
+# CONFIG_LOCALVERSION_AUTO is not set
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_RCU_BOOST=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_NS is not set
+# CONFIG_IPC_NS is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+# CONFIG_UID16 is not set
+# CONFIG_SHMEM is not set
+CONFIG_EMBEDDED=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_SLOB=y
+CONFIG_JUMP_LABEL=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+# CONFIG_LBDAF is not set
+CONFIG_BLK_CMDLINE_PARSER=y
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_MINIX_SUBPARTITION=y
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_UNIXWARE_DISKLABEL=y
+CONFIG_LDM_PARTITION=y
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_ARCH_PXA=y
+CONFIG_MACH_LP8X4X=y
+# CONFIG_ARM_THUMB is not set
+CONFIG_PREEMPT=y
+CONFIG_AEABI=y
+# CONFIG_COMPACTION is not set
+# CONFIG_CROSS_MEMORY_ATTACH is not set
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="init=/sbin/init root=/dev/mmcblk0p1 rw rootfstype=ext4 console=ttyS0,115200 mem=128M rootwait"
+# CONFIG_SUSPEND is not set
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_BRIDGE=m
+CONFIG_BRIDGE_VLAN_FILTERING=y
+CONFIG_VLAN_8021Q=m
+CONFIG_VLAN_8021Q_GVRP=y
+CONFIG_VLAN_8021Q_MVRP=y
+# CONFIG_WIRELESS is not set
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+# CONFIG_FW_LOADER is not set
+CONFIG_MTD=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_CFI_GEOMETRY=y
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_PXA2XX=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_LOOP_MIN_COUNT=2
+CONFIG_SCSI=y
+# CONFIG_SCSI_PROC_FS is not set
+CONFIG_BLK_DEV_SD=y
+# CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_NETDEVICES=y
+CONFIG_BONDING=m
+CONFIG_MACVLAN=m
+CONFIG_MACVTAP=m
+CONFIG_TUN=m
+# CONFIG_NET_VENDOR_ARC is not set
+# CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_CIRRUS is not set
+CONFIG_DM9000=y
+CONFIG_DM9000_FORCE_SIMPLE_PHY_POLL=y
+# CONFIG_NET_VENDOR_FARADAY is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+CONFIG_PPP=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPPOE=m
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_SLIP=m
+CONFIG_SLIP_COMPRESSED=y
+# CONFIG_WLAN is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=800
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=600
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_SERIO is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_8250=y
+# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=40
+CONFIG_SERIAL_8250_RUNTIME_UARTS=40
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_PXA=y
+CONFIG_HW_RANDOM=y
+CONFIG_I2C=m
+# CONFIG_I2C_COMPAT is not set
+CONFIG_I2C_PXA=m
+CONFIG_I2C_PXA_SLAVE=y
+# CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_SA1100_WATCHDOG=m
+CONFIG_FB=y
+CONFIG_FB_PXA=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_LOGO=y
+CONFIG_HID_GENERIC=m
+CONFIG_HID_A4TECH=m
+CONFIG_HID_CYPRESS=m
+CONFIG_HID_KEYTOUCH=m
+CONFIG_HID_KENSINGTON=m
+CONFIG_HID_LOGITECH=m
+CONFIG_HID_MICROSOFT=m
+CONFIG_HID_MONTEREY=m
+CONFIG_USB_HIDDEV=y
+CONFIG_I2C_HID=m
+CONFIG_USB=m
+CONFIG_USB_OHCI_HCD=m
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+CONFIG_USB_STORAGE=m
+CONFIG_USB_STORAGE_REALTEK=m
+CONFIG_USB_STORAGE_DATAFAB=m
+CONFIG_USB_STORAGE_FREECOM=m
+CONFIG_USB_STORAGE_ISD200=m
+CONFIG_USB_STORAGE_USBAT=m
+CONFIG_USB_STORAGE_SDDR09=m
+CONFIG_USB_STORAGE_SDDR55=m
+CONFIG_USB_STORAGE_JUMPSHOT=m
+CONFIG_USB_STORAGE_ALAUDA=m
+CONFIG_USB_STORAGE_ONETOUCH=m
+CONFIG_USB_STORAGE_KARMA=m
+CONFIG_USB_STORAGE_CYPRESS_ATACB=m
+CONFIG_USB_STORAGE_ENE_UB6250=m
+CONFIG_USB_SERIAL=m
+CONFIG_USB_SERIAL_GENERIC=y
+CONFIG_USB_SERIAL_SIMPLE=m
+CONFIG_USB_SERIAL_AIRCABLE=m
+CONFIG_USB_SERIAL_ARK3116=m
+CONFIG_USB_SERIAL_BELKIN=m
+CONFIG_USB_SERIAL_CH341=m
+CONFIG_USB_SERIAL_WHITEHEAT=m
+CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
+CONFIG_USB_SERIAL_CP210X=m
+CONFIG_USB_SERIAL_CYPRESS_M8=m
+CONFIG_USB_SERIAL_EMPEG=m
+CONFIG_USB_SERIAL_FTDI_SIO=m
+CONFIG_USB_SERIAL_VISOR=m
+CONFIG_USB_SERIAL_IPAQ=m
+CONFIG_USB_SERIAL_IR=m
+CONFIG_USB_SERIAL_EDGEPORT=m
+CONFIG_USB_SERIAL_EDGEPORT_TI=m
+CONFIG_USB_SERIAL_F81232=m
+CONFIG_USB_SERIAL_GARMIN=m
+CONFIG_USB_SERIAL_IPW=m
+CONFIG_USB_SERIAL_IUU=m
+CONFIG_USB_SERIAL_KEYSPAN_PDA=m
+CONFIG_USB_SERIAL_KEYSPAN=m
+CONFIG_USB_SERIAL_KLSI=m
+CONFIG_USB_SERIAL_KOBIL_SCT=m
+CONFIG_USB_SERIAL_MCT_U232=m
+CONFIG_USB_SERIAL_METRO=m
+CONFIG_USB_SERIAL_MOS7720=m
+CONFIG_USB_SERIAL_MOS7840=m
+CONFIG_USB_SERIAL_NAVMAN=m
+CONFIG_USB_SERIAL_PL2303=m
+CONFIG_USB_SERIAL_OTI6858=m
+CONFIG_USB_SERIAL_QCAUX=m
+CONFIG_USB_SERIAL_QUALCOMM=m
+CONFIG_USB_SERIAL_SPCP8X5=m
+CONFIG_USB_SERIAL_SAFE=m
+CONFIG_USB_SERIAL_SAFE_PADDED=y
+CONFIG_USB_SERIAL_SIERRAWIRELESS=m
+CONFIG_USB_SERIAL_SYMBOL=m
+CONFIG_USB_SERIAL_TI=m
+CONFIG_USB_SERIAL_CYBERJACK=m
+CONFIG_USB_SERIAL_XIRCOM=m
+CONFIG_USB_SERIAL_OPTION=m
+CONFIG_USB_SERIAL_OMNINET=m
+CONFIG_USB_SERIAL_OPTICON=m
+CONFIG_USB_SERIAL_XSENS_MT=m
+CONFIG_USB_SERIAL_WISHBONE=m
+CONFIG_USB_SERIAL_ZTE=m
+CONFIG_USB_SERIAL_SSU100=m
+CONFIG_USB_SERIAL_QT2=m
+CONFIG_MMC=y
+CONFIG_MMC_PXA=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_PXA=m
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_EXT2_FS=m
+CONFIG_EXT3_FS=y
+CONFIG_EXT4_FS=y
+CONFIG_REISERFS_FS=m
+CONFIG_ISO9660_FS=m
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_NTFS_FS=m
+CONFIG_NTFS_RW=y
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V4=y
+CONFIG_ROOT_NFS=y
+CONFIG_CIFS=m
+CONFIG_CIFS_STATS=y
+CONFIG_CODA_FS=m
+CONFIG_NLS_DEFAULT="cp1251"
+CONFIG_NLS_CODEPAGE_1251=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_UTF8=y
+CONFIG_PRINTK_TIME=y
diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig
index 96100db..efaf2d0 100644
--- a/arch/arm/mach-pxa/Kconfig
+++ b/arch/arm/mach-pxa/Kconfig
@@ -273,6 +273,22 @@ config MACH_VPAC270
 
 comment "End-user Products (sorted by vendor name)"
 
+config MACH_LP8X4X
+	bool "ICP DAS LP-8X4X"
+	select IWMMXT
+	select PXA27x
+	help
+	  Say Y here if you intend to run this kernel on an ICP DAS
+	  LP-8x4x programmable automation controller.
+
+	  LP-8x4x is ARM-based and built around PXA270 SoC. The device
+	  has 128 MiB SDRAM, 48 or 96 MiB NOR flash, VGA port with
+	  800x600 resolution, MMC card slot, 2 Ethernet ports, 1 USB
+	  port, 5 serial ports (1 on them is wired internally to
+	  expansion slots). The device has a range of digital and
+	  analog expansion IO modules which can be installed in 1, 4 or
+	  8 slots depending on the model.
+
 config MACH_H4700
 	bool "HP iPAQ hx4700"
 	select HAVE_PWM
diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile
index 648867a..b264325 100644
--- a/arch/arm/mach-pxa/Makefile
+++ b/arch/arm/mach-pxa/Makefile
@@ -63,6 +63,7 @@ obj-$(CONFIG_MACH_COLIBRI320)	+= colibri-pxa3xx.o colibri-pxa320.o
 obj-$(CONFIG_MACH_VPAC270)	+= vpac270.o
 
 # End-user Products
+obj-$(CONFIG_MACH_LP8X4X)	+= lp8x4x.o
 obj-$(CONFIG_MACH_H4700)	+= hx4700.o
 obj-$(CONFIG_MACH_H5000)	+= h5000.o
 obj-$(CONFIG_MACH_HIMALAYA)	+= himalaya.o
diff --git a/arch/arm/mach-pxa/lp8x4x.c b/arch/arm/mach-pxa/lp8x4x.c
new file mode 100644
index 0000000..0d3d8c0
--- /dev/null
+++ b/arch/arm/mach-pxa/lp8x4x.c
@@ -0,0 +1,473 @@
+/*
+ *  linux/arch/arm/mach-pxa/lp8x4x.c
+ *
+ *  Support for ICP DAS LP-8x4x programmable automation controller
+ *  Copyright (C) 2013 Sergei Ianovich <ynvich@gmail.com>
+ *
+ *  borrowed heavily from
+ *  Support for the Intel HCDDBBVA0 Development Platform.
+ *
+ *  Author:	Nicolas Pitre
+ *  Created:	Nov 05, 2002
+ *  Copyright:	MontaVista Software Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation or any later version.
+ */
+#include <linux/gpio.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/syscore_ops.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/bitops.h>
+#include <linux/fb.h>
+#include <linux/ioport.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/input.h>
+#include <linux/dm9000.h>
+#include <linux/slab.h>
+#include <linux/leds.h>
+#include <linux/ktime.h>
+#include <linux/irqchip/chained_irq.h>
+
+#include <asm/types.h>
+#include <asm/setup.h>
+#include <asm/memory.h>
+#include <asm/mach-types.h>
+#include <mach/hardware.h>
+#include <asm/irq.h>
+#include <asm/sizes.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+#include <asm/mach/flash.h>
+
+#include <mach/irqs.h>
+#include <mach/pxa27x.h>
+#include <linux/platform_data/video-pxafb.h>
+#include <linux/platform_data/mmc-pxamci.h>
+#include <linux/platform_data/usb-ohci-pxa27x.h>
+#include <mach/smemc.h>
+
+#include "generic.h"
+#include "devices.h"
+
+#define LP8X4X_ETH0_BASE        0x0c000000
+#define LP8X4X_ETH0_IO          0x0c004000
+#define LP8X4X_ETH0_IRQ         PXA_GPIO_TO_IRQ(9)
+
+#define LP8X4X_ETH1_BASE        0x0d000000
+#define LP8X4X_ETH1_IO          0x0d004000
+#define LP8X4X_ETH1_IRQ         PXA_GPIO_TO_IRQ(82)
+
+#define LP8X4X_FPGA_PHYS	0x17000000
+#define LP8X4X_FPGA_VIRT	((void *) 0xf1000000)
+#define LP8X4X_P2V(x)		IOMEM((x) - LP8X4X_FPGA_PHYS + LP8X4X_FPGA_VIRT)
+#define LP8X4X_V2P(x)		((x) - LP8X4X_FPGA_VIRT + LP8X4X_FPGA_PHYS)
+
+/* board level registers in the FPGA */
+
+#define LP8X4X_EOI		LP8X4X_P2V(0x17009006)
+#define LP8X4X_INSINT		LP8X4X_P2V(0x17009008)
+#define LP8X4X_ENSYSINT		LP8X4X_P2V(0x1700900A)
+#define LP8X4X_PRIMINT		LP8X4X_P2V(0x1700900C)
+#define LP8X4X_SECOINT		LP8X4X_P2V(0x1700900E)
+#define LP8X4X_ENRISEINT	LP8X4X_P2V(0x17009010)
+#define LP8X4X_CLRRISEINT	LP8X4X_P2V(0x17009012)
+#define LP8X4X_ENHILVINT	LP8X4X_P2V(0x17009014)
+#define LP8X4X_CLRHILVINT	LP8X4X_P2V(0x17009016)
+#define LP8X4X_ENFALLINT	LP8X4X_P2V(0x17009018)
+#define LP8X4X_CLRFALLINT	LP8X4X_P2V(0x1700901a)
+
+/* board specific IRQs */
+
+#define LP8X4X_IRQ(x)		(IRQ_BOARD_START + (x))
+#define LP8X4X_SLOT1_IRQ	LP8X4X_IRQ(0)
+#define LP8X4X_SLOT2_IRQ	LP8X4X_IRQ(1)
+#define LP8X4X_SLOT3_IRQ	LP8X4X_IRQ(2)
+#define LP8X4X_SLOT4_IRQ	LP8X4X_IRQ(3)
+#define LP8X4X_SLOT5_IRQ	LP8X4X_IRQ(4)
+#define LP8X4X_SLOT6_IRQ	LP8X4X_IRQ(5)
+#define LP8X4X_SLOT7_IRQ	LP8X4X_IRQ(6)
+#define LP8X4X_SLOT8_IRQ	LP8X4X_IRQ(7)
+#define LP8X4X_TIMER1_IRQ	LP8X4X_IRQ(8)
+#define LP8X4X_TIMER2_IRQ	LP8X4X_IRQ(9)
+#define LP8X4X_TIMEROUT_IRQ	LP8X4X_IRQ(10)
+#define LP8X4X_HOTPLUG_IRQ	LP8X4X_IRQ(11)
+#define LP8X4X_BATLOW_IRQ	LP8X4X_IRQ(12)
+#define LP8X4X_TTYS0_IRQ	LP8X4X_IRQ(13)
+#define LP8X4X_TTYS1_IRQ	LP8X4X_IRQ(14)
+#define LP8X4X_TTYS2_IRQ	LP8X4X_IRQ(15)
+
+#define LP8X4X_NR_IRQS		(IRQ_BOARD_START + 16)
+
+static unsigned char lp8x4x_irq_sys_enabled;
+static unsigned char lp8x4x_irq_high_enabled;
+
+static void lp8x4x_ack_irq(struct irq_data *d)
+{
+	unsigned mask;
+	int irq = d->irq - IRQ_BOARD_START;
+
+	if (irq < 0 || irq > 15) {
+		pr_err("lp8x4x: wrong irq handler for irq %i\n", d->irq);
+		return;
+	}
+
+	if (irq < 8) {
+		mask = ioread8(LP8X4X_CLRHILVINT);
+		mask |= 1 << irq;
+		iowrite8(mask, LP8X4X_CLRHILVINT);
+	} else if (irq < 13) {
+		irq -= 8;
+		mask = ioread8(LP8X4X_SECOINT);
+		mask |= 1 << irq;
+		iowrite8(mask, LP8X4X_SECOINT);
+	} else {
+		irq -= 8;
+		mask = ioread8(LP8X4X_PRIMINT);
+		mask |= 1 << irq;
+		iowrite8(mask, LP8X4X_PRIMINT);
+	}
+}
+
+static void lp8x4x_mask_irq(struct irq_data *d)
+{
+	int irq = d->irq - IRQ_BOARD_START;
+
+	if (irq < 0 || irq > 15) {
+		pr_err("lp8x4x: wrong irq handler for irq %i\n", d->irq);
+		return;
+	}
+
+	if (irq < 8) {
+		lp8x4x_irq_high_enabled &= ~(1 << irq);
+		iowrite8(lp8x4x_irq_high_enabled, LP8X4X_ENHILVINT);
+	} else {
+		irq -= 8;
+		lp8x4x_irq_sys_enabled &= ~(1 << irq);
+		iowrite8(lp8x4x_irq_sys_enabled, LP8X4X_ENSYSINT);
+	}
+}
+
+static void lp8x4x_unmask_irq(struct irq_data *d)
+{
+	unsigned mask;
+	int irq = d->irq - IRQ_BOARD_START;
+
+	if (irq < 0 || irq > 15) {
+		pr_err("wrong irq handler for irq %i\n", d->irq);
+		return;
+	}
+
+	if (irq < 8) {
+		lp8x4x_irq_high_enabled |= 1 << irq;
+		mask = ioread8(LP8X4X_CLRHILVINT);
+		mask |= 1 << irq;
+		iowrite8(mask, LP8X4X_CLRHILVINT);
+		iowrite8(lp8x4x_irq_high_enabled, LP8X4X_ENHILVINT);
+	} else if (irq < 13) {
+		irq -= 8;
+		lp8x4x_irq_sys_enabled |= 1 << irq;
+		mask = ioread8(LP8X4X_SECOINT);
+		mask |= 1 << irq;
+		iowrite8(mask, LP8X4X_SECOINT);
+		iowrite8(lp8x4x_irq_sys_enabled, LP8X4X_ENSYSINT);
+	} else {
+		irq -= 8;
+		lp8x4x_irq_sys_enabled |= 1 << irq;
+		mask = ioread8(LP8X4X_PRIMINT);
+		mask |= 1 << irq;
+		iowrite8(mask, LP8X4X_PRIMINT);
+		iowrite8(lp8x4x_irq_sys_enabled, LP8X4X_ENSYSINT);
+	}
+}
+
+static struct irq_chip lp8x4x_irq_chip = {
+	.name			= "FPGA",
+	.irq_ack		= lp8x4x_ack_irq,
+	.irq_mask		= lp8x4x_mask_irq,
+	.irq_unmask		= lp8x4x_unmask_irq,
+};
+
+static spinlock_t fpga_irq_lock;
+
+static void lp8x4x_irq_handler(unsigned int irq, struct irq_desc *desc)
+{
+	int loop, n;
+	unsigned long mask;
+	unsigned long flags;
+	struct irq_chip *chip = irq_desc_get_chip(desc);
+
+	spin_lock_irqsave(&fpga_irq_lock, flags);
+	chained_irq_enter(chip, desc);
+
+	do {
+		loop = 0;
+		mask = ioread8(LP8X4X_CLRHILVINT) & 0xff;
+		mask |= (ioread8(LP8X4X_SECOINT) & 0x1f) << 8;
+		mask |= (ioread8(LP8X4X_PRIMINT) & 0xe0) << 8;
+		mask &= (lp8x4x_irq_high_enabled
+				| (lp8x4x_irq_sys_enabled << 8));
+		for_each_set_bit(n, &mask, BITS_PER_LONG) {
+			loop = 1;
+
+			generic_handle_irq(IRQ_BOARD_START + n);
+		}
+	} while (loop);
+
+	chained_irq_exit(chip, desc);
+	iowrite8(0, LP8X4X_EOI);
+	spin_unlock_irqrestore(&fpga_irq_lock, flags);
+}
+
+static void __init lp8x4x_init_irq(void)
+{
+	int irq;
+	int err;
+
+	err = irq_set_irq_type(PXA_GPIO_TO_IRQ(3), IRQ_TYPE_EDGE_RISING);
+	if (err < 0) {
+		pr_err("lp8x4x: irq init failed\n");
+		return;
+	}
+
+	spin_lock_init(&fpga_irq_lock);
+	irq_set_chained_handler(PXA_GPIO_TO_IRQ(3), lp8x4x_irq_handler);
+
+	for (irq = IRQ_BOARD_START; irq < LP8X4X_NR_IRQS; irq++) {
+		irq_set_chip_and_handler(irq, &lp8x4x_irq_chip,
+					 handle_level_irq);
+		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+	}
+
+	iowrite8(0, LP8X4X_CLRRISEINT);
+	iowrite8(0, LP8X4X_ENRISEINT);
+	iowrite8(0, LP8X4X_CLRFALLINT);
+	iowrite8(0, LP8X4X_ENFALLINT);
+	iowrite8(0, LP8X4X_CLRHILVINT);
+	iowrite8(0, LP8X4X_ENHILVINT);
+	iowrite8(0, LP8X4X_ENSYSINT);
+	iowrite8(0, LP8X4X_PRIMINT);
+	iowrite8(0, LP8X4X_SECOINT);
+
+	return;
+}
+
+static unsigned long lp8x4x_pin_config[] = {
+	/* MMC */
+	GPIO32_MMC_CLK,
+	GPIO112_MMC_CMD,
+	GPIO92_MMC_DAT_0,
+	GPIO109_MMC_DAT_1,
+	GPIO110_MMC_DAT_2,
+	GPIO111_MMC_DAT_3,
+
+	/* USB Host Port 1 */
+	GPIO88_USBH1_PWR,
+	GPIO89_USBH1_PEN,
+};
+
+static struct resource lp8x4x_flash_resources[] __initdata = {
+	[0] = {
+		.start	= PXA_CS0_PHYS,
+		.end	= PXA_CS0_PHYS + SZ_64M - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= PXA_CS1_PHYS,
+		.end	= PXA_CS1_PHYS + SZ_32M - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct mtd_partition lp8x4x_flash0_partitions[] = {
+	{
+		.name =		"Bootloader",
+		.size =		0x00040000,
+		.offset =	0,
+	}, {
+		.name =		"Settings",
+		.size =		0x00040000,
+		.offset =	0x00040000,
+	}, {
+		.name =		"Kernel",
+		.size =		0x00280000,
+		.offset =	0x00080000,
+	}, {
+		.name =		"Filesystem",
+		.size =		MTDPART_SIZ_FULL,
+		.offset =	0x00300000
+	}
+};
+
+static struct flash_platform_data lp8x4x_flash_data[] __initdata = {
+	{
+		.map_name	= "cfi_probe",
+		.parts		= lp8x4x_flash0_partitions,
+		.nr_parts	= ARRAY_SIZE(lp8x4x_flash0_partitions),
+		.width		= 4,
+	}, {
+		.map_name	= "cfi_probe",
+		.parts		= NULL,
+		.nr_parts	= 0,
+		.width		= 2,
+	}
+};
+
+static struct pxafb_mode_info lp8x4x_vga_60_mode = {
+	.pixclock       = 38461,
+	.xres           = 640,
+	.yres           = 480,
+	.bpp            = 16,
+	.hsync_len      = 64,
+	.left_margin    = 78,
+	.right_margin   = 46,
+	.vsync_len      = 12,
+	.upper_margin   = 22,
+	.lower_margin   = 10,
+	.sync           = 0,
+};
+
+static struct pxafb_mach_info lp8x4x_pxafb_info = {
+	.num_modes		= 1,
+	.lccr0			= LCCR0_Act,
+	.lccr3			= LCCR3_PCP,
+};
+
+static int lp8x4x_mci_init(struct device *dev,
+		irq_handler_t mstone_detect_int, void *data)
+{
+	return 0;
+}
+
+static int lp8x4x_mci_setpower(struct device *dev, unsigned int vdd)
+{
+	return 0;
+}
+
+static void lp8x4x_mci_exit(struct device *dev, void *data)
+{
+}
+
+static struct pxamci_platform_data lp8x4x_mci_platform_data = {
+	.ocr_mask		= MMC_VDD_32_33|MMC_VDD_33_34,
+	.init			= lp8x4x_mci_init,
+	.setpower               = lp8x4x_mci_setpower,
+	.exit			= lp8x4x_mci_exit,
+	.gpio_card_detect	= -1,
+	.gpio_card_ro		= -1,
+	.gpio_power		= -1,
+};
+
+static struct resource lp8x4x_dm9000_resources[] __initdata = {
+	[0] = {
+		.start  = LP8X4X_ETH0_BASE,
+		.end    = LP8X4X_ETH0_BASE + 2 - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start  = LP8X4X_ETH0_IO,
+		.end    = LP8X4X_ETH0_IO + 2 - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	[2] = {
+		.start  = LP8X4X_ETH0_IRQ,
+		.end    = LP8X4X_ETH0_IRQ,
+		.flags	= IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE,
+	},
+	[3] = {
+		.start  = LP8X4X_ETH1_BASE,
+		.end    = LP8X4X_ETH1_BASE + 2 - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	[4] = {
+		.start  = LP8X4X_ETH1_IO,
+		.end    = LP8X4X_ETH1_IO + 2 - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	[5] = {
+		.start  = LP8X4X_ETH1_IRQ,
+		.end    = LP8X4X_ETH1_IRQ,
+		.flags	= IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE,
+	},
+};
+
+static struct pxaohci_platform_data lp8x4x_ohci_platform_data = {
+	.port_mode	= PMM_PERPORT_MODE,
+	.flags		= ENABLE_PORT1 | OC_MODE_PERPORT,
+};
+
+static void lp8x4x_restart(enum reboot_mode mode, const char *cmd)
+{
+	/* Switch off fast-bus and turbo mode */
+	asm volatile("mcr       p14, 0, %0, c6, c0, 0" : :
+			"r"(2));
+	/* SDRAM hangs on watchdog reset on Marvell PXA270 (erratum 71) */
+	pxa_restart(REBOOT_SOFT, cmd);
+}
+
+static void __init lp8x4x_init(void)
+{
+	pxa2xx_mfp_config(ARRAY_AND_SIZE(lp8x4x_pin_config));
+
+	pxa_set_ffuart_info(NULL);
+	pxa_set_btuart_info(NULL);
+	pxa_set_stuart_info(NULL);
+
+	/* system bus arbiter setting
+	 * - Core_Park
+	 * - LCD_wt:DMA_wt:CORE_Wt = 2:3:4
+	 */
+	ARB_CNTRL = ARB_CORE_PARK | 0x234;
+
+	pxa_set_mci_info(&lp8x4x_mci_platform_data);
+	pxa_set_ohci_info(&lp8x4x_ohci_platform_data);
+
+	platform_device_register_resndata(NULL, "pxa2xx-flash", 0,
+			&lp8x4x_flash_resources[0], 1,
+			&lp8x4x_flash_data[0], sizeof(lp8x4x_flash_data[0]));
+	platform_device_register_resndata(NULL, "pxa2xx-flash", 1,
+			&lp8x4x_flash_resources[1], 1,
+			&lp8x4x_flash_data[1], sizeof(lp8x4x_flash_data[1]));
+	platform_device_register_simple("dm9000", 0,
+			&lp8x4x_dm9000_resources[0], 3);
+	platform_device_register_simple("dm9000", 1,
+			&lp8x4x_dm9000_resources[3], 3);
+
+	lp8x4x_pxafb_info.modes = &lp8x4x_vga_60_mode;
+	pxa_set_fb_info(NULL, &lp8x4x_pxafb_info);
+
+	/* Could not do this in MACHINE since GPIO is not ready then */
+	lp8x4x_init_irq();
+}
+
+static struct map_desc lp8x4x_io_desc[] __initdata = {
+	{	/* CPLD */
+		.virtual	=  (unsigned long) LP8X4X_FPGA_VIRT,
+		.pfn		= __phys_to_pfn(LP8X4X_FPGA_PHYS),
+		.length		= 0x00100000,
+		.type		= MT_DEVICE
+	}
+};
+
+static void __init lp8x4x_map_io(void)
+{
+	pxa27x_map_io();
+	iotable_init(lp8x4x_io_desc, ARRAY_SIZE(lp8x4x_io_desc));
+}
+
+MACHINE_START(LP8X4X, "ICP DAS LP-8x4x programmable automation controller")
+	.atag_offset	= 0x100,
+	.map_io		= lp8x4x_map_io,
+	.nr_irqs	= LP8X4X_NR_IRQS,
+	.init_irq	= pxa27x_init_irq,
+	.handle_irq	= pxa27x_handle_irq,
+	.init_time	= pxa_timer_init,
+	.init_machine	= lp8x4x_init,
+	.restart	= lp8x4x_restart,
+MACHINE_END
-- 
1.8.4.2

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

* Re: [PATCH 02/11] arm: pxa27x: support ICP DAS LP-8x4x
  2013-12-06 16:38       ` Sergei Ianovich
@ 2013-12-06 17:14         ` Arnd Bergmann
  -1 siblings, 0 replies; 700+ messages in thread
From: Arnd Bergmann @ 2013-12-06 17:14 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: linux-arm-kernel, linux-kernel, Eric Miao, Russell King,
	Haojian Zhuang, Olof Johansson, Linus Walleij, Daniel Mack

On Friday 06 December 2013, Sergei Ianovich wrote:
> On Fri, 2013-12-06 at 01:40 +0100, Arnd Bergmann wrote:
> 
> > Ideally we want shared defconfigs where you enable multiple (or all) pxa boards
> > at once and end up with a kernel that works on all of them.
> > 
> > For most other platforms the goal is even to have a shared defconfig across
> > SoC families, but PXA is one of the exceptions that I would make because
> > it is both old and rather different from even the ARM9 or Marvell Feroceon
> > based SoCs.
> 
> There is probably no in point sharing this config with most other
> devices on PXA2xx SoC. This device is an industrial PC. Its config needs
> to be optimized for low latency even by the cost of greater power
> consumption. It is not supposed to run on batteries or enter any low
> power mode anyway.

Ok, I see. Note that while most of them are mobile, I believe there are
a couple of pxa boards that are in the same category as yours.

Unfortunately, PXA already has most defconfigs than any other platform (25
at the moment) and I would like to see that reduced in the future if
I can find someone to do the work.

> > we try to avoid hardwired virtual addresses entirely and instead use platform
> > device resources, but I realize that there are limits to how far you get with
> > that. Please make an effort to convert as many parts of the FPGA into platform
> > devices with regular resources, but know that we would not enforce this as
> > strictly as we do for new platforms.
> > 
> > > +
> > > +static struct irq_chip lp8x4x_irq_chip = {
> > > +     .name                   = "FPGA",
> > > +     .irq_ack                = lp8x4x_ack_irq,
> > > +     .irq_mask               = lp8x4x_mask_irq,
> > > +     .irq_unmask             = lp8x4x_unmask_irq,
> > > +};
> > 
> > Please try to move the irqchip code to drivers/irqchip/.
> 
> CONFIG_IRQCHIP depends on CONFIG_OF_IRQ which in turn depends on Open
> Firmware.

Hmm, I wonder if we should try to change Kconfig then. Let's leave it
alone for now, maybe Linus Walleij has some comments since he has
been looking into moving drivers out in the past.

> The device is shipped with such a flash device partition table, which
> makes migration to device tree rather difficult. The partition for
> U-Boot is just 256kiB. This is a high aim already. U-Boot needs to be
> compiled without command line help and USB support to fit into this
> size. Otherwise the main flash needs to be repartitioned.
> 
> Could it be acceptable to accept the device without device tree support?

>From my point of view it's ok, but I'll leave that up to Daniel Mack,
since he has been doing all the work on PXA migration to DT lately.
I believe with his work it won't actually be a problem to do DT.

> If so, FPGA irqchip could remain in the machine source file. It is
> highly unlikely, it will ever be reused. In this case all fixed virtual
> address definitions could be moved to the machine source file. The file
> will be the only place where LP8X4X_FPGA_VIRT is used directly.

That sounds reasonable to me as well.

	Arnd

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

* [PATCH 02/11] arm: pxa27x: support ICP DAS LP-8x4x
@ 2013-12-06 17:14         ` Arnd Bergmann
  0 siblings, 0 replies; 700+ messages in thread
From: Arnd Bergmann @ 2013-12-06 17:14 UTC (permalink / raw)
  To: linux-arm-kernel

On Friday 06 December 2013, Sergei Ianovich wrote:
> On Fri, 2013-12-06 at 01:40 +0100, Arnd Bergmann wrote:
> 
> > Ideally we want shared defconfigs where you enable multiple (or all) pxa boards
> > at once and end up with a kernel that works on all of them.
> > 
> > For most other platforms the goal is even to have a shared defconfig across
> > SoC families, but PXA is one of the exceptions that I would make because
> > it is both old and rather different from even the ARM9 or Marvell Feroceon
> > based SoCs.
> 
> There is probably no in point sharing this config with most other
> devices on PXA2xx SoC. This device is an industrial PC. Its config needs
> to be optimized for low latency even by the cost of greater power
> consumption. It is not supposed to run on batteries or enter any low
> power mode anyway.

Ok, I see. Note that while most of them are mobile, I believe there are
a couple of pxa boards that are in the same category as yours.

Unfortunately, PXA already has most defconfigs than any other platform (25
at the moment) and I would like to see that reduced in the future if
I can find someone to do the work.

> > we try to avoid hardwired virtual addresses entirely and instead use platform
> > device resources, but I realize that there are limits to how far you get with
> > that. Please make an effort to convert as many parts of the FPGA into platform
> > devices with regular resources, but know that we would not enforce this as
> > strictly as we do for new platforms.
> > 
> > > +
> > > +static struct irq_chip lp8x4x_irq_chip = {
> > > +     .name                   = "FPGA",
> > > +     .irq_ack                = lp8x4x_ack_irq,
> > > +     .irq_mask               = lp8x4x_mask_irq,
> > > +     .irq_unmask             = lp8x4x_unmask_irq,
> > > +};
> > 
> > Please try to move the irqchip code to drivers/irqchip/.
> 
> CONFIG_IRQCHIP depends on CONFIG_OF_IRQ which in turn depends on Open
> Firmware.

Hmm, I wonder if we should try to change Kconfig then. Let's leave it
alone for now, maybe Linus Walleij has some comments since he has
been looking into moving drivers out in the past.

> The device is shipped with such a flash device partition table, which
> makes migration to device tree rather difficult. The partition for
> U-Boot is just 256kiB. This is a high aim already. U-Boot needs to be
> compiled without command line help and USB support to fit into this
> size. Otherwise the main flash needs to be repartitioned.
> 
> Could it be acceptable to accept the device without device tree support?

>From my point of view it's ok, but I'll leave that up to Daniel Mack,
since he has been doing all the work on PXA migration to DT lately.
I believe with his work it won't actually be a problem to do DT.

> If so, FPGA irqchip could remain in the machine source file. It is
> highly unlikely, it will ever be reused. In this case all fixed virtual
> address definitions could be moved to the machine source file. The file
> will be the only place where LP8X4X_FPGA_VIRT is used directly.

That sounds reasonable to me as well.

	Arnd

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

* Re: [PATCH v2 02/11] arm: pxa27x: support ICP DAS LP-8x4x
  2013-12-06 16:48     ` Sergei Ianovich
@ 2013-12-08  2:21       ` Arnd Bergmann
  -1 siblings, 0 replies; 700+ messages in thread
From: Arnd Bergmann @ 2013-12-08  2:21 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Sergei Ianovich, linux-kernel, Eric Miao, Russell King, Haojian Zhuang

On Friday 06 December 2013, Sergei Ianovich wrote:

> new file mode 100644
> index 0000000..2612e60
> --- /dev/null
> +++ b/arch/arm/configs/lp8x4x_defconfig
> @@ -0,0 +1,235 @@
> +CONFIG_CROSS_COMPILE="arm-linux-gnueabi-"

This will break some build bots, please remove it here and add it to your
build environment instead.

> +# CONFIG_LBDAF is not set
> +CONFIG_BLK_CMDLINE_PARSER=y
> +CONFIG_PARTITION_ADVANCED=y
> +CONFIG_BSD_DISKLABEL=y
> +CONFIG_MINIX_SUBPARTITION=y
> +CONFIG_SOLARIS_X86_PARTITION=y
> +CONFIG_UNIXWARE_DISKLABEL=y
> +CONFIG_LDM_PARTITION=y

You have some rather unusual options in here. I'd suggest you go through
the reduced defconfig file and remove all options that look like they
are unnecessary for your system.

It's probably based on some distro config that enables lots of modules
you don't actually want.

> +#define LP8X4X_FPGA_PHYS	0x17000000
> +#define LP8X4X_FPGA_VIRT	((void *) 0xf1000000)
> +#define LP8X4X_P2V(x)		IOMEM((x) - LP8X4X_FPGA_PHYS + LP8X4X_FPGA_VIRT)
> +#define LP8X4X_V2P(x)		((x) - LP8X4X_FPGA_VIRT + LP8X4X_FPGA_PHYS)

I think you misunderstood my comment, the point was that you should
move the IOMEM() to the LP8X4X_FPGA_VIRT definition, like

#define LP8X4X_FPGA_VIRT	((void __iomem *) 0xf1000000)
#define LP8X4X_P2V(x)		(x) - LP8X4X_FPGA_PHYS + LP8X4X_FPGA_VIRT)

which would result in the correct type because of pointer arithmetics.

> +/* board level registers in the FPGA */
> +
> +#define LP8X4X_EOI		LP8X4X_P2V(0x17009006)
> +#define LP8X4X_INSINT		LP8X4X_P2V(0x17009008)
> +#define LP8X4X_ENSYSINT		LP8X4X_P2V(0x1700900A)
> +#define LP8X4X_PRIMINT		LP8X4X_P2V(0x1700900C)
> +#define LP8X4X_SECOINT		LP8X4X_P2V(0x1700900E)
> +#define LP8X4X_ENRISEINT	LP8X4X_P2V(0x17009010)
> +#define LP8X4X_CLRRISEINT	LP8X4X_P2V(0x17009012)
> +#define LP8X4X_ENHILVINT	LP8X4X_P2V(0x17009014)
> +#define LP8X4X_CLRHILVINT	LP8X4X_P2V(0x17009016)
> +#define LP8X4X_ENFALLINT	LP8X4X_P2V(0x17009018)
> +#define LP8X4X_CLRFALLINT	LP8X4X_P2V(0x1700901a)

Thinking about this again, it's actually better if you just get rid of
LP8X4X_P2V() entirely and redefine these to

#define LP8X4X_EOI		0x0006
#define LP8X4X_INSINT		0x0008
...

and change the users to do e.g.

	readl(LP8X4X_FPGA_VIRT + LP8X4X_INSINT);

This is closer to the normal way of adding the offset to an __iomem
pointer returned from ioremap.

> +	platform_device_register_resndata(NULL, "pxa2xx-flash", 0,
> +			&lp8x4x_flash_resources[0], 1,
> +			&lp8x4x_flash_data[0], sizeof(lp8x4x_flash_data[0]));
> +	platform_device_register_resndata(NULL, "pxa2xx-flash", 1,
> +			&lp8x4x_flash_resources[1], 1,
> +			&lp8x4x_flash_data[1], sizeof(lp8x4x_flash_data[1]));
> +	platform_device_register_simple("dm9000", 0,
> +			&lp8x4x_dm9000_resources[0], 3);
> +	platform_device_register_simple("dm9000", 1,
> +			&lp8x4x_dm9000_resources[3], 3);

This looks much better than the first version, a slight improvement IMHO would
be to split the resource arrays into one symbol per device to turn this into

platform_device_register_resndata(NULL, "pxa2xx-flash", 0,
			&lp8x4x_flash_resources0, 1,
			&lp8x4x_flash_data0, sizeof(lp8x4x_flash_data0));
platform_device_register_resndata(NULL, "pxa2xx-flash", 1,
			&lp8x4x_flash_resources1, 1,
			&lp8x4x_flash_data1, sizeof(lp8x4x_flash_data1));

It's not important though if you have a strong preference for the way you
did this, it just seems unusual.

	Arnd

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

* [PATCH v2 02/11] arm: pxa27x: support ICP DAS LP-8x4x
@ 2013-12-08  2:21       ` Arnd Bergmann
  0 siblings, 0 replies; 700+ messages in thread
From: Arnd Bergmann @ 2013-12-08  2:21 UTC (permalink / raw)
  To: linux-arm-kernel

On Friday 06 December 2013, Sergei Ianovich wrote:

> new file mode 100644
> index 0000000..2612e60
> --- /dev/null
> +++ b/arch/arm/configs/lp8x4x_defconfig
> @@ -0,0 +1,235 @@
> +CONFIG_CROSS_COMPILE="arm-linux-gnueabi-"

This will break some build bots, please remove it here and add it to your
build environment instead.

> +# CONFIG_LBDAF is not set
> +CONFIG_BLK_CMDLINE_PARSER=y
> +CONFIG_PARTITION_ADVANCED=y
> +CONFIG_BSD_DISKLABEL=y
> +CONFIG_MINIX_SUBPARTITION=y
> +CONFIG_SOLARIS_X86_PARTITION=y
> +CONFIG_UNIXWARE_DISKLABEL=y
> +CONFIG_LDM_PARTITION=y

You have some rather unusual options in here. I'd suggest you go through
the reduced defconfig file and remove all options that look like they
are unnecessary for your system.

It's probably based on some distro config that enables lots of modules
you don't actually want.

> +#define LP8X4X_FPGA_PHYS	0x17000000
> +#define LP8X4X_FPGA_VIRT	((void *) 0xf1000000)
> +#define LP8X4X_P2V(x)		IOMEM((x) - LP8X4X_FPGA_PHYS + LP8X4X_FPGA_VIRT)
> +#define LP8X4X_V2P(x)		((x) - LP8X4X_FPGA_VIRT + LP8X4X_FPGA_PHYS)

I think you misunderstood my comment, the point was that you should
move the IOMEM() to the LP8X4X_FPGA_VIRT definition, like

#define LP8X4X_FPGA_VIRT	((void __iomem *) 0xf1000000)
#define LP8X4X_P2V(x)		(x) - LP8X4X_FPGA_PHYS + LP8X4X_FPGA_VIRT)

which would result in the correct type because of pointer arithmetics.

> +/* board level registers in the FPGA */
> +
> +#define LP8X4X_EOI		LP8X4X_P2V(0x17009006)
> +#define LP8X4X_INSINT		LP8X4X_P2V(0x17009008)
> +#define LP8X4X_ENSYSINT		LP8X4X_P2V(0x1700900A)
> +#define LP8X4X_PRIMINT		LP8X4X_P2V(0x1700900C)
> +#define LP8X4X_SECOINT		LP8X4X_P2V(0x1700900E)
> +#define LP8X4X_ENRISEINT	LP8X4X_P2V(0x17009010)
> +#define LP8X4X_CLRRISEINT	LP8X4X_P2V(0x17009012)
> +#define LP8X4X_ENHILVINT	LP8X4X_P2V(0x17009014)
> +#define LP8X4X_CLRHILVINT	LP8X4X_P2V(0x17009016)
> +#define LP8X4X_ENFALLINT	LP8X4X_P2V(0x17009018)
> +#define LP8X4X_CLRFALLINT	LP8X4X_P2V(0x1700901a)

Thinking about this again, it's actually better if you just get rid of
LP8X4X_P2V() entirely and redefine these to

#define LP8X4X_EOI		0x0006
#define LP8X4X_INSINT		0x0008
...

and change the users to do e.g.

	readl(LP8X4X_FPGA_VIRT + LP8X4X_INSINT);

This is closer to the normal way of adding the offset to an __iomem
pointer returned from ioremap.

> +	platform_device_register_resndata(NULL, "pxa2xx-flash", 0,
> +			&lp8x4x_flash_resources[0], 1,
> +			&lp8x4x_flash_data[0], sizeof(lp8x4x_flash_data[0]));
> +	platform_device_register_resndata(NULL, "pxa2xx-flash", 1,
> +			&lp8x4x_flash_resources[1], 1,
> +			&lp8x4x_flash_data[1], sizeof(lp8x4x_flash_data[1]));
> +	platform_device_register_simple("dm9000", 0,
> +			&lp8x4x_dm9000_resources[0], 3);
> +	platform_device_register_simple("dm9000", 1,
> +			&lp8x4x_dm9000_resources[3], 3);

This looks much better than the first version, a slight improvement IMHO would
be to split the resource arrays into one symbol per device to turn this into

platform_device_register_resndata(NULL, "pxa2xx-flash", 0,
			&lp8x4x_flash_resources0, 1,
			&lp8x4x_flash_data0, sizeof(lp8x4x_flash_data0));
platform_device_register_resndata(NULL, "pxa2xx-flash", 1,
			&lp8x4x_flash_resources1, 1,
			&lp8x4x_flash_data1, sizeof(lp8x4x_flash_data1));

It's not important though if you have a strong preference for the way you
did this, it just seems unusual.

	Arnd

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

* Re: [PATCH v2 02/11] arm: pxa27x: support ICP DAS LP-8x4x
  2013-12-08  2:21       ` Arnd Bergmann
@ 2013-12-08  7:05         ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-08  7:05 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: linux-arm-kernel, linux-kernel, Eric Miao, Russell King, Haojian Zhuang

On Sun, 2013-12-08 at 03:21 +0100, Arnd Bergmann wrote:
> On Friday 06 December 2013, Sergei Ianovich wrote:
> You have some rather unusual options in here. I'd suggest you go through
> the reduced defconfig file and remove all options that look like they
> are unnecessary for your system.
> 
> It's probably based on some distro config that enables lots of modules
> you don't actually want.

I tried to future-proof the config, by enabling all partition tables and
USB disks and modems that could be plugged into the device.

I'll remove those. However, I would like to retain config options
related to low latency and small kernel size. Keeping them will
hopefully allow being notified about changes affecting the system.

Will this fly?

> > +#define LP8X4X_FPGA_PHYS     0x17000000
> > +#define LP8X4X_FPGA_VIRT     ((void *) 0xf1000000)
> > +#define LP8X4X_P2V(x)                IOMEM((x) - LP8X4X_FPGA_PHYS + LP8X4X_FPGA_VIRT)
> > +#define LP8X4X_V2P(x)                ((x) - LP8X4X_FPGA_VIRT + LP8X4X_FPGA_PHYS)
> 
> I think you misunderstood my comment, the point was that you should
> move the IOMEM() to the LP8X4X_FPGA_VIRT definition, like
> 
> #define LP8X4X_FPGA_VIRT        ((void __iomem *) 0xf1000000)
> #define LP8X4X_P2V(x)           (x) - LP8X4X_FPGA_PHYS + LP8X4X_FPGA_VIRT)
> 
> which would result in the correct type because of pointer arithmetics.
> 
> > +/* board level registers in the FPGA */
> > +
> > +#define LP8X4X_EOI           LP8X4X_P2V(0x17009006)
> > +#define LP8X4X_INSINT                LP8X4X_P2V(0x17009008)
> > +#define LP8X4X_ENSYSINT              LP8X4X_P2V(0x1700900A)
> > +#define LP8X4X_PRIMINT               LP8X4X_P2V(0x1700900C)
> > +#define LP8X4X_SECOINT               LP8X4X_P2V(0x1700900E)
> > +#define LP8X4X_ENRISEINT     LP8X4X_P2V(0x17009010)
> > +#define LP8X4X_CLRRISEINT    LP8X4X_P2V(0x17009012)
> > +#define LP8X4X_ENHILVINT     LP8X4X_P2V(0x17009014)
> > +#define LP8X4X_CLRHILVINT    LP8X4X_P2V(0x17009016)
> > +#define LP8X4X_ENFALLINT     LP8X4X_P2V(0x17009018)
> > +#define LP8X4X_CLRFALLINT    LP8X4X_P2V(0x1700901a)
> 
> Thinking about this again, it's actually better if you just get rid of
> LP8X4X_P2V() entirely and redefine these to
> 
> #define LP8X4X_EOI              0x0006
> #define LP8X4X_INSINT           0x0008
> ...
> 
> and change the users to do e.g.
> 
>         readl(LP8X4X_FPGA_VIRT + LP8X4X_INSINT);

I am trying to boot the system with device tree. If I manage, I'll move
this code into drivers/irqchip/ as a platform device. Otherwise, I'll
make this change.

> This is closer to the normal way of adding the offset to an __iomem
> pointer returned from ioremap.
> 
> > +     platform_device_register_resndata(NULL, "pxa2xx-flash", 0,
> > +                     &lp8x4x_flash_resources[0], 1,
> > +                     &lp8x4x_flash_data[0], sizeof(lp8x4x_flash_data[0]));
> > +     platform_device_register_resndata(NULL, "pxa2xx-flash", 1,
> > +                     &lp8x4x_flash_resources[1], 1,
> > +                     &lp8x4x_flash_data[1], sizeof(lp8x4x_flash_data[1]));
> > +     platform_device_register_simple("dm9000", 0,
> > +                     &lp8x4x_dm9000_resources[0], 3);
> > +     platform_device_register_simple("dm9000", 1,
> > +                     &lp8x4x_dm9000_resources[3], 3);
> 
> This looks much better than the first version, a slight improvement IMHO would
> be to split the resource arrays into one symbol per device to turn this into
> 
> platform_device_register_resndata(NULL, "pxa2xx-flash", 0,
>                         &lp8x4x_flash_resources0, 1,
>                         &lp8x4x_flash_data0, sizeof(lp8x4x_flash_data0));
> platform_device_register_resndata(NULL, "pxa2xx-flash", 1,
>                         &lp8x4x_flash_resources1, 1,
>                         &lp8x4x_flash_data1, sizeof(lp8x4x_flash_data1));
> 
> It's not important though if you have a strong preference for the way you
> did this, it just seems unusual.

I'll make this change, if device tree doesn't boot.

Thanks for reviewing.



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

* [PATCH v2 02/11] arm: pxa27x: support ICP DAS LP-8x4x
@ 2013-12-08  7:05         ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-08  7:05 UTC (permalink / raw)
  To: linux-arm-kernel

On Sun, 2013-12-08 at 03:21 +0100, Arnd Bergmann wrote:
> On Friday 06 December 2013, Sergei Ianovich wrote:
> You have some rather unusual options in here. I'd suggest you go through
> the reduced defconfig file and remove all options that look like they
> are unnecessary for your system.
> 
> It's probably based on some distro config that enables lots of modules
> you don't actually want.

I tried to future-proof the config, by enabling all partition tables and
USB disks and modems that could be plugged into the device.

I'll remove those. However, I would like to retain config options
related to low latency and small kernel size. Keeping them will
hopefully allow being notified about changes affecting the system.

Will this fly?

> > +#define LP8X4X_FPGA_PHYS     0x17000000
> > +#define LP8X4X_FPGA_VIRT     ((void *) 0xf1000000)
> > +#define LP8X4X_P2V(x)                IOMEM((x) - LP8X4X_FPGA_PHYS + LP8X4X_FPGA_VIRT)
> > +#define LP8X4X_V2P(x)                ((x) - LP8X4X_FPGA_VIRT + LP8X4X_FPGA_PHYS)
> 
> I think you misunderstood my comment, the point was that you should
> move the IOMEM() to the LP8X4X_FPGA_VIRT definition, like
> 
> #define LP8X4X_FPGA_VIRT        ((void __iomem *) 0xf1000000)
> #define LP8X4X_P2V(x)           (x) - LP8X4X_FPGA_PHYS + LP8X4X_FPGA_VIRT)
> 
> which would result in the correct type because of pointer arithmetics.
> 
> > +/* board level registers in the FPGA */
> > +
> > +#define LP8X4X_EOI           LP8X4X_P2V(0x17009006)
> > +#define LP8X4X_INSINT                LP8X4X_P2V(0x17009008)
> > +#define LP8X4X_ENSYSINT              LP8X4X_P2V(0x1700900A)
> > +#define LP8X4X_PRIMINT               LP8X4X_P2V(0x1700900C)
> > +#define LP8X4X_SECOINT               LP8X4X_P2V(0x1700900E)
> > +#define LP8X4X_ENRISEINT     LP8X4X_P2V(0x17009010)
> > +#define LP8X4X_CLRRISEINT    LP8X4X_P2V(0x17009012)
> > +#define LP8X4X_ENHILVINT     LP8X4X_P2V(0x17009014)
> > +#define LP8X4X_CLRHILVINT    LP8X4X_P2V(0x17009016)
> > +#define LP8X4X_ENFALLINT     LP8X4X_P2V(0x17009018)
> > +#define LP8X4X_CLRFALLINT    LP8X4X_P2V(0x1700901a)
> 
> Thinking about this again, it's actually better if you just get rid of
> LP8X4X_P2V() entirely and redefine these to
> 
> #define LP8X4X_EOI              0x0006
> #define LP8X4X_INSINT           0x0008
> ...
> 
> and change the users to do e.g.
> 
>         readl(LP8X4X_FPGA_VIRT + LP8X4X_INSINT);

I am trying to boot the system with device tree. If I manage, I'll move
this code into drivers/irqchip/ as a platform device. Otherwise, I'll
make this change.

> This is closer to the normal way of adding the offset to an __iomem
> pointer returned from ioremap.
> 
> > +     platform_device_register_resndata(NULL, "pxa2xx-flash", 0,
> > +                     &lp8x4x_flash_resources[0], 1,
> > +                     &lp8x4x_flash_data[0], sizeof(lp8x4x_flash_data[0]));
> > +     platform_device_register_resndata(NULL, "pxa2xx-flash", 1,
> > +                     &lp8x4x_flash_resources[1], 1,
> > +                     &lp8x4x_flash_data[1], sizeof(lp8x4x_flash_data[1]));
> > +     platform_device_register_simple("dm9000", 0,
> > +                     &lp8x4x_dm9000_resources[0], 3);
> > +     platform_device_register_simple("dm9000", 1,
> > +                     &lp8x4x_dm9000_resources[3], 3);
> 
> This looks much better than the first version, a slight improvement IMHO would
> be to split the resource arrays into one symbol per device to turn this into
> 
> platform_device_register_resndata(NULL, "pxa2xx-flash", 0,
>                         &lp8x4x_flash_resources0, 1,
>                         &lp8x4x_flash_data0, sizeof(lp8x4x_flash_data0));
> platform_device_register_resndata(NULL, "pxa2xx-flash", 1,
>                         &lp8x4x_flash_resources1, 1,
>                         &lp8x4x_flash_data1, sizeof(lp8x4x_flash_data1));
> 
> It's not important though if you have a strong preference for the way you
> did this, it just seems unusual.

I'll make this change, if device tree doesn't boot.

Thanks for reviewing.

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

* [PATCH 0/9] ARM: support for ICP DAS LP-8x4x (with dts)
  2013-12-06 16:48     ` Sergei Ianovich
@ 2013-12-08 22:53       ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-08 22:53 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Daniel Mack, Arnd Bergmann

Except for defconfig, this is a completely new series. The first
eight patches fix outstanding issues with device tree support
in PXA. The 9th boots ICP DAS LP-8x4x.

Daniel chose to add a lot of selects for his MACH_PXA3XX_DT config
option. I feel that it will be easier to create multi-machine kernel
configurations and support per-machine workaround, if those selects
reside in separate machine options.

If Daniel agrees with my arguments, MACH_PXA3XX_DT and MACH_PXA27X_DT
could be merged into a single MACH_PXA_DT option.

CC: Daniel Mack <zonque@gmail.com>
CC: Arnd Bergmann <arnd@arndb.de>

Sergei Ianovich (9):
  ARM: dts: pxa2xx fix compatible strings
  ARM: dts: fix pxa27x-gpio interrupts
  ARM: fix ohci-pxa27x build error with OF enabled
  ARM: pxa: remove unused variable
  ARM: dts: provide DMA config to pxamci
  ARM: dts: pxa3xx: move declaration to header
  ARM: dts: pxa27x: skip static platform devices
  ARM: dts: pxa27x: device tree irq init
  ARM: pxa27x: device tree support ICP DAS LP-8x4x

 Documentation/devicetree/bindings/mmc/pxa-mmc.txt |   2 +
 arch/arm/boot/dts/Makefile                        |   1 +
 arch/arm/boot/dts/pxa27x-lp8x4x.dts               | 111 +++++++++++++++
 arch/arm/boot/dts/pxa27x.dtsi                     |  10 ++
 arch/arm/boot/dts/pxa2xx.dtsi                     |   5 +-
 arch/arm/configs/lp8x4x_defconfig                 | 162 ++++++++++++++++++++++
 arch/arm/mach-pxa/Kconfig                         |  31 +++++
 arch/arm/mach-pxa/Makefile                        |   1 +
 arch/arm/mach-pxa/include/mach/irqs.h             |   4 +
 arch/arm/mach-pxa/include/mach/pxa27x.h           |   4 +
 arch/arm/mach-pxa/irq.c                           |   2 -
 arch/arm/mach-pxa/pxa27x-dt.c                     |  97 +++++++++++++
 arch/arm/mach-pxa/pxa27x.c                        |  17 +++
 arch/arm/mach-pxa/pxa3xx.c                        |   2 -
 drivers/mmc/host/pxamci.c                         |  50 +++++--
 drivers/usb/host/ohci-pxa27x.c                    |   1 +
 16 files changed, 482 insertions(+), 18 deletions(-)
 create mode 100644 arch/arm/boot/dts/pxa27x-lp8x4x.dts
 create mode 100644 arch/arm/configs/lp8x4x_defconfig
 create mode 100644 arch/arm/mach-pxa/pxa27x-dt.c

-- 
1.8.4.3


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

* [PATCH 0/9] ARM: support for ICP DAS LP-8x4x (with dts)
@ 2013-12-08 22:53       ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-08 22:53 UTC (permalink / raw)
  To: linux-arm-kernel

Except for defconfig, this is a completely new series. The first
eight patches fix outstanding issues with device tree support
in PXA. The 9th boots ICP DAS LP-8x4x.

Daniel chose to add a lot of selects for his MACH_PXA3XX_DT config
option. I feel that it will be easier to create multi-machine kernel
configurations and support per-machine workaround, if those selects
reside in separate machine options.

If Daniel agrees with my arguments, MACH_PXA3XX_DT and MACH_PXA27X_DT
could be merged into a single MACH_PXA_DT option.

CC: Daniel Mack <zonque@gmail.com>
CC: Arnd Bergmann <arnd@arndb.de>

Sergei Ianovich (9):
  ARM: dts: pxa2xx fix compatible strings
  ARM: dts: fix pxa27x-gpio interrupts
  ARM: fix ohci-pxa27x build error with OF enabled
  ARM: pxa: remove unused variable
  ARM: dts: provide DMA config to pxamci
  ARM: dts: pxa3xx: move declaration to header
  ARM: dts: pxa27x: skip static platform devices
  ARM: dts: pxa27x: device tree irq init
  ARM: pxa27x: device tree support ICP DAS LP-8x4x

 Documentation/devicetree/bindings/mmc/pxa-mmc.txt |   2 +
 arch/arm/boot/dts/Makefile                        |   1 +
 arch/arm/boot/dts/pxa27x-lp8x4x.dts               | 111 +++++++++++++++
 arch/arm/boot/dts/pxa27x.dtsi                     |  10 ++
 arch/arm/boot/dts/pxa2xx.dtsi                     |   5 +-
 arch/arm/configs/lp8x4x_defconfig                 | 162 ++++++++++++++++++++++
 arch/arm/mach-pxa/Kconfig                         |  31 +++++
 arch/arm/mach-pxa/Makefile                        |   1 +
 arch/arm/mach-pxa/include/mach/irqs.h             |   4 +
 arch/arm/mach-pxa/include/mach/pxa27x.h           |   4 +
 arch/arm/mach-pxa/irq.c                           |   2 -
 arch/arm/mach-pxa/pxa27x-dt.c                     |  97 +++++++++++++
 arch/arm/mach-pxa/pxa27x.c                        |  17 +++
 arch/arm/mach-pxa/pxa3xx.c                        |   2 -
 drivers/mmc/host/pxamci.c                         |  50 +++++--
 drivers/usb/host/ohci-pxa27x.c                    |   1 +
 16 files changed, 482 insertions(+), 18 deletions(-)
 create mode 100644 arch/arm/boot/dts/pxa27x-lp8x4x.dts
 create mode 100644 arch/arm/configs/lp8x4x_defconfig
 create mode 100644 arch/arm/mach-pxa/pxa27x-dt.c

-- 
1.8.4.3

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

* [PATCH 1/9] ARM: dts: pxa2xx fix compatible strings
  2013-12-08 22:53       ` Sergei Ianovich
  (?)
@ 2013-12-08 22:53         ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-08 22:53 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Daniel Mack, Arnd Bergmann, Rob Herring,
	Pawel Moll, Mark Rutland, Stephen Warren, Ian Campbell,
	Russell King, open list:OPEN FIRMWARE AND...

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Daniel Mack <zonque@gmail.com>
CC: Arnd Bergmann <arnd@arndb.de>
---
 arch/arm/boot/dts/pxa2xx.dtsi | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/arch/arm/boot/dts/pxa2xx.dtsi b/arch/arm/boot/dts/pxa2xx.dtsi
index a5e90f0..3419f87 100644
--- a/arch/arm/boot/dts/pxa2xx.dtsi
+++ b/arch/arm/boot/dts/pxa2xx.dtsi
@@ -18,7 +18,6 @@
 		serial1 = &btuart;
 		serial2 = &stuart;
 		serial3 = &hwuart;
-		i2c0 = &pwri2c;
 		i2c1 = &pxai2c1;
 	};
 
@@ -113,14 +112,14 @@
 		};
 
 		usb0: ohci@4c000000 {
-			compatible = "mrvl,pxa-ohci";
+			compatible = "marvell,pxa-ohci";
 			reg = <0x4c000000 0x10000>;
 			interrupts = <3>;
 			status = "disabled";
 		};
 
 		mmc0: mmc@41100000 {
-			compatible = "mrvl,pxa-mmc";
+			compatible = "marvell,pxa-mmc";
 			reg = <0x41100000 0x1000>;
 			interrupts = <23>;
 			status = "disabled";
-- 
1.8.4.3


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

* [PATCH 1/9] ARM: dts: pxa2xx fix compatible strings
@ 2013-12-08 22:53         ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-08 22:53 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Daniel Mack, Arnd Bergmann, Rob Herring,
	Pawel Moll, Mark Rutland, Stephen Warren, Ian Campbell,
	Russell King, open list:OPEN FIRMWARE AND...

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Daniel Mack <zonque@gmail.com>
CC: Arnd Bergmann <arnd@arndb.de>
---
 arch/arm/boot/dts/pxa2xx.dtsi | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/arch/arm/boot/dts/pxa2xx.dtsi b/arch/arm/boot/dts/pxa2xx.dtsi
index a5e90f0..3419f87 100644
--- a/arch/arm/boot/dts/pxa2xx.dtsi
+++ b/arch/arm/boot/dts/pxa2xx.dtsi
@@ -18,7 +18,6 @@
 		serial1 = &btuart;
 		serial2 = &stuart;
 		serial3 = &hwuart;
-		i2c0 = &pwri2c;
 		i2c1 = &pxai2c1;
 	};
 
@@ -113,14 +112,14 @@
 		};
 
 		usb0: ohci@4c000000 {
-			compatible = "mrvl,pxa-ohci";
+			compatible = "marvell,pxa-ohci";
 			reg = <0x4c000000 0x10000>;
 			interrupts = <3>;
 			status = "disabled";
 		};
 
 		mmc0: mmc@41100000 {
-			compatible = "mrvl,pxa-mmc";
+			compatible = "marvell,pxa-mmc";
 			reg = <0x41100000 0x1000>;
 			interrupts = <23>;
 			status = "disabled";
-- 
1.8.4.3

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

* [PATCH 1/9] ARM: dts: pxa2xx fix compatible strings
@ 2013-12-08 22:53         ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-08 22:53 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Daniel Mack <zonque@gmail.com>
CC: Arnd Bergmann <arnd@arndb.de>
---
 arch/arm/boot/dts/pxa2xx.dtsi | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/arch/arm/boot/dts/pxa2xx.dtsi b/arch/arm/boot/dts/pxa2xx.dtsi
index a5e90f0..3419f87 100644
--- a/arch/arm/boot/dts/pxa2xx.dtsi
+++ b/arch/arm/boot/dts/pxa2xx.dtsi
@@ -18,7 +18,6 @@
 		serial1 = &btuart;
 		serial2 = &stuart;
 		serial3 = &hwuart;
-		i2c0 = &pwri2c;
 		i2c1 = &pxai2c1;
 	};
 
@@ -113,14 +112,14 @@
 		};
 
 		usb0: ohci at 4c000000 {
-			compatible = "mrvl,pxa-ohci";
+			compatible = "marvell,pxa-ohci";
 			reg = <0x4c000000 0x10000>;
 			interrupts = <3>;
 			status = "disabled";
 		};
 
 		mmc0: mmc at 41100000 {
-			compatible = "mrvl,pxa-mmc";
+			compatible = "marvell,pxa-mmc";
 			reg = <0x41100000 0x1000>;
 			interrupts = <23>;
 			status = "disabled";
-- 
1.8.4.3

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

* [PATCH 2/9] ARM: dts: fix pxa27x-gpio interrupts
  2013-12-08 22:53       ` Sergei Ianovich
  (?)
@ 2013-12-08 22:53         ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-08 22:53 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Daniel Mack, Arnd Bergmann, Rob Herring,
	Pawel Moll, Mark Rutland, Stephen Warren, Ian Campbell,
	Russell King, open list:OPEN FIRMWARE AND...

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Daniel Mack <zonque@gmail.com>
CC: Arnd Bergmann <arnd@arndb.de>
---
 arch/arm/boot/dts/pxa27x.dtsi | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/arch/arm/boot/dts/pxa27x.dtsi b/arch/arm/boot/dts/pxa27x.dtsi
index d7c5d72..44df554 100644
--- a/arch/arm/boot/dts/pxa27x.dtsi
+++ b/arch/arm/boot/dts/pxa27x.dtsi
@@ -10,5 +10,11 @@
 			marvell,intc-priority;
 			marvell,intc-nr-irqs = <34>;
 		};
+
+		gpio: gpio@40e00000 {
+			compatible = "intel,pxa27x-gpio";
+			interrupts = <8>, <9>, <10>;
+			interrupt-names = "gpio0", "gpio1", "gpio_mux";
+		};
 	};
 };
-- 
1.8.4.3


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

* [PATCH 2/9] ARM: dts: fix pxa27x-gpio interrupts
@ 2013-12-08 22:53         ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-08 22:53 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Daniel Mack, Arnd Bergmann, Rob Herring,
	Pawel Moll, Mark Rutland, Stephen Warren, Ian Campbell,
	Russell King, open list:OPEN FIRMWARE AND...

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Daniel Mack <zonque@gmail.com>
CC: Arnd Bergmann <arnd@arndb.de>
---
 arch/arm/boot/dts/pxa27x.dtsi | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/arch/arm/boot/dts/pxa27x.dtsi b/arch/arm/boot/dts/pxa27x.dtsi
index d7c5d72..44df554 100644
--- a/arch/arm/boot/dts/pxa27x.dtsi
+++ b/arch/arm/boot/dts/pxa27x.dtsi
@@ -10,5 +10,11 @@
 			marvell,intc-priority;
 			marvell,intc-nr-irqs = <34>;
 		};
+
+		gpio: gpio@40e00000 {
+			compatible = "intel,pxa27x-gpio";
+			interrupts = <8>, <9>, <10>;
+			interrupt-names = "gpio0", "gpio1", "gpio_mux";
+		};
 	};
 };
-- 
1.8.4.3

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

* [PATCH 2/9] ARM: dts: fix pxa27x-gpio interrupts
@ 2013-12-08 22:53         ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-08 22:53 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Daniel Mack <zonque@gmail.com>
CC: Arnd Bergmann <arnd@arndb.de>
---
 arch/arm/boot/dts/pxa27x.dtsi | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/arch/arm/boot/dts/pxa27x.dtsi b/arch/arm/boot/dts/pxa27x.dtsi
index d7c5d72..44df554 100644
--- a/arch/arm/boot/dts/pxa27x.dtsi
+++ b/arch/arm/boot/dts/pxa27x.dtsi
@@ -10,5 +10,11 @@
 			marvell,intc-priority;
 			marvell,intc-nr-irqs = <34>;
 		};
+
+		gpio: gpio at 40e00000 {
+			compatible = "intel,pxa27x-gpio";
+			interrupts = <8>, <9>, <10>;
+			interrupt-names = "gpio0", "gpio1", "gpio_mux";
+		};
 	};
 };
-- 
1.8.4.3

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

* [PATCH 3/9] ARM: fix ohci-pxa27x build error with OF enabled
  2013-12-08 22:53       ` Sergei Ianovich
@ 2013-12-08 22:53         ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-08 22:53 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Russell King - ARM Linux, Alan Stern,
	Greg Kroah-Hartman, open list:USB OHCI DRIVER

--->8---
$ make
  CC [M]  drivers/usb/host/ohci-pxa27x.o
drivers/usb/host/ohci-pxa27x.c: In function ‘ohci_pxa_of_init’:
drivers/usb/host/ohci-pxa27x.c:310:2: error: implicit declaration of function ‘dma_coerce_mask_and_coherent’ [-Werror=implicit-function-declaration]
drivers/usb/host/ohci-pxa27x.c:310:2: error: implicit declaration of function ‘DMA_BIT_MASK’ [-Werror=implicit-function-declaration]
--->8---

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Russell King - ARM Linux <linux@arm.linux.org.uk>

 # Changes to be committed:
---
 drivers/usb/host/ohci-pxa27x.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c
index e89ac4d..97983fd 100644
--- a/drivers/usb/host/ohci-pxa27x.c
+++ b/drivers/usb/host/ohci-pxa27x.c
@@ -24,6 +24,7 @@
 #include <linux/io.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/dma-mapping.h>
 #include <linux/of_platform.h>
 #include <linux/of_gpio.h>
 #include <linux/platform_data/usb-ohci-pxa27x.h>
-- 
1.8.4.3


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

* [PATCH 3/9] ARM: fix ohci-pxa27x build error with OF enabled
@ 2013-12-08 22:53         ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-08 22:53 UTC (permalink / raw)
  To: linux-arm-kernel

--->8---
$ make
  CC [M]  drivers/usb/host/ohci-pxa27x.o
drivers/usb/host/ohci-pxa27x.c: In function ?ohci_pxa_of_init?:
drivers/usb/host/ohci-pxa27x.c:310:2: error: implicit declaration of function ?dma_coerce_mask_and_coherent? [-Werror=implicit-function-declaration]
drivers/usb/host/ohci-pxa27x.c:310:2: error: implicit declaration of function ?DMA_BIT_MASK? [-Werror=implicit-function-declaration]
--->8---

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Russell King - ARM Linux <linux@arm.linux.org.uk>

 # Changes to be committed:
---
 drivers/usb/host/ohci-pxa27x.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c
index e89ac4d..97983fd 100644
--- a/drivers/usb/host/ohci-pxa27x.c
+++ b/drivers/usb/host/ohci-pxa27x.c
@@ -24,6 +24,7 @@
 #include <linux/io.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/dma-mapping.h>
 #include <linux/of_platform.h>
 #include <linux/of_gpio.h>
 #include <linux/platform_data/usb-ohci-pxa27x.h>
-- 
1.8.4.3

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

* [PATCH 4/9] ARM: pxa: remove unused variable
  2013-12-08 22:53       ` Sergei Ianovich
@ 2013-12-08 22:53         ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-08 22:53 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Daniel Mack, Eric Miao, Russell King, Haojian Zhuang

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Daniel Mack <zonque@gmail.com>
---
 arch/arm/mach-pxa/irq.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/arch/arm/mach-pxa/irq.c b/arch/arm/mach-pxa/irq.c
index b6cc181..432842c 100644
--- a/arch/arm/mach-pxa/irq.c
+++ b/arch/arm/mach-pxa/irq.c
@@ -236,7 +236,6 @@ void __init pxa_dt_irq_init(int (*fn)(struct irq_data *, unsigned int))
 {
 	struct device_node *node;
 	const struct of_device_id *of_id;
-	struct pxa_intc_conf *conf;
 	struct resource res;
 	int n, ret;
 
@@ -246,7 +245,6 @@ void __init pxa_dt_irq_init(int (*fn)(struct irq_data *, unsigned int))
 		return;
 	}
 	of_id = of_match_node(intc_ids, node);
-	conf = of_id->data;
 
 	ret = of_property_read_u32(node, "marvell,intc-nr-irqs",
 				   &pxa_internal_irq_nr);
-- 
1.8.4.3


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

* [PATCH 4/9] ARM: pxa: remove unused variable
@ 2013-12-08 22:53         ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-08 22:53 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Daniel Mack <zonque@gmail.com>
---
 arch/arm/mach-pxa/irq.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/arch/arm/mach-pxa/irq.c b/arch/arm/mach-pxa/irq.c
index b6cc181..432842c 100644
--- a/arch/arm/mach-pxa/irq.c
+++ b/arch/arm/mach-pxa/irq.c
@@ -236,7 +236,6 @@ void __init pxa_dt_irq_init(int (*fn)(struct irq_data *, unsigned int))
 {
 	struct device_node *node;
 	const struct of_device_id *of_id;
-	struct pxa_intc_conf *conf;
 	struct resource res;
 	int n, ret;
 
@@ -246,7 +245,6 @@ void __init pxa_dt_irq_init(int (*fn)(struct irq_data *, unsigned int))
 		return;
 	}
 	of_id = of_match_node(intc_ids, node);
-	conf = of_id->data;
 
 	ret = of_property_read_u32(node, "marvell,intc-nr-irqs",
 				   &pxa_internal_irq_nr);
-- 
1.8.4.3

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

* [PATCH 5/9] ARM: dts: provide DMA config to pxamci
  2013-12-08 22:53       ` Sergei Ianovich
  (?)
@ 2013-12-08 22:53         ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-08 22:53 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Daniel Mack, Arnd Bergmann, Rob Herring,
	Pawel Moll, Mark Rutland, Stephen Warren, Ian Campbell,
	Rob Landley, Russell King, Chris Ball, Ulf Hansson,
	Jaehoon Chung, Seungwon Jeon, open list:OPEN FIRMWARE AND...,
	open list:DOCUMENTATION

Non-dts implementation supply required DMA channel numbers as
IORESOURCE_DMA. However, there is was no way to get them from
device tree.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Daniel Mack <zonque@gmail.com>
CC: Arnd Bergmann <arnd@arndb.de>
---
 Documentation/devicetree/bindings/mmc/pxa-mmc.txt |  2 +
 arch/arm/boot/dts/pxa27x.dtsi                     |  4 ++
 drivers/mmc/host/pxamci.c                         | 50 ++++++++++++++++++-----
 3 files changed, 45 insertions(+), 11 deletions(-)

diff --git a/Documentation/devicetree/bindings/mmc/pxa-mmc.txt b/Documentation/devicetree/bindings/mmc/pxa-mmc.txt
index b7025de..27447ec 100644
--- a/Documentation/devicetree/bindings/mmc/pxa-mmc.txt
+++ b/Documentation/devicetree/bindings/mmc/pxa-mmc.txt
@@ -5,6 +5,7 @@ Driver bindings for the PXA MCI (MMC/SDIO) interfaces
 Required properties:
 - compatible: Should be "marvell,pxa-mmc".
 - vmmc-supply: A regulator for VMMC
+- marvell,dma-channels: 2 PXA DMA channels [0] for RX, [1] for TX
 
 Optional properties:
 - marvell,detect-delay-ms: sets the detection delay timeout in ms.
@@ -19,6 +20,7 @@ mmc0: mmc@41100000 {
 	compatible = "marvell,pxa-mmc";
 	reg = <0x41100000 0x1000>;
 	interrupts = <23>;
+	marvell,dma-channels = <21 22>;
 	cd-gpios = <&gpio 23 0>;
 	wp-gpios = <&gpio 24 0>;
 };
diff --git a/arch/arm/boot/dts/pxa27x.dtsi b/arch/arm/boot/dts/pxa27x.dtsi
index 44df554..3f97520 100644
--- a/arch/arm/boot/dts/pxa27x.dtsi
+++ b/arch/arm/boot/dts/pxa27x.dtsi
@@ -16,5 +16,9 @@
 			interrupts = <8>, <9>, <10>;
 			interrupt-names = "gpio0", "gpio1", "gpio_mux";
 		};
+
+		mmc@41100000 {
+			marvell,dma-channels = <21 22>;
+		};
 	};
 };
diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c
index 32fe113..8c7a110 100644
--- a/drivers/mmc/host/pxamci.c
+++ b/drivers/mmc/host/pxamci.c
@@ -613,11 +613,37 @@ static int pxamci_of_init(struct platform_device *pdev)
 
         return 0;
 }
+
+static int pxamci_of_init_dma(struct platform_device *pdev,
+		struct pxamci_host *host)
+{
+        struct device_node *np = pdev->dev.of_node;
+        u32 tmp;
+	int ret;
+
+	ret = of_property_read_u32_index(np, "marvell,dma-channels", 0, &tmp);
+	if (ret < 0)
+		return ret;
+	host->dma_drcmrrx = tmp;
+
+	ret = of_property_read_u32_index(np, "marvell,dma-channels", 1, &tmp);
+	if (ret < 0)
+		return ret;
+	host->dma_drcmrtx = tmp;
+
+	return 0;
+}
 #else
 static int pxamci_of_init(struct platform_device *pdev)
 {
         return 0;
 }
+
+static int pxamci_of_init_dma(struct platform_device *pdev,
+		struct pxamci_host *host)
+{
+	return -ENODATA;
+}
 #endif
 
 static int pxamci_probe(struct platform_device *pdev)
@@ -741,19 +767,21 @@ static int pxamci_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, mmc);
 
-	dmarx = platform_get_resource(pdev, IORESOURCE_DMA, 0);
-	if (!dmarx) {
-		ret = -ENXIO;
-		goto out;
-	}
-	host->dma_drcmrrx = dmarx->start;
+	if (pxamci_of_init_dma(pdev, host) < 0) {
+		dmarx = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+		if (!dmarx) {
+			ret = -ENXIO;
+			goto out;
+		}
+		host->dma_drcmrrx = dmarx->start;
 
-	dmatx = platform_get_resource(pdev, IORESOURCE_DMA, 1);
-	if (!dmatx) {
-		ret = -ENXIO;
-		goto out;
+		dmatx = platform_get_resource(pdev, IORESOURCE_DMA, 1);
+		if (!dmatx) {
+			ret = -ENXIO;
+			goto out;
+		}
+		host->dma_drcmrtx = dmatx->start;
 	}
-	host->dma_drcmrtx = dmatx->start;
 
 	if (host->pdata) {
 		gpio_cd = host->pdata->gpio_card_detect;
-- 
1.8.4.3


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

* [PATCH 5/9] ARM: dts: provide DMA config to pxamci
@ 2013-12-08 22:53         ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-08 22:53 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Daniel Mack, Arnd Bergmann, Rob Herring,
	Pawel Moll, Mark Rutland, Stephen Warren, Ian Campbell,
	Rob Landley, Russell King, Chris Ball, Ulf Hansson,
	Jaehoon Chung, Seungwon Jeon, open list:OPEN FIRMWARE AND...,
	open list:DOCUMENTATION

Non-dts implementation supply required DMA channel numbers as
IORESOURCE_DMA. However, there is was no way to get them from
device tree.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Daniel Mack <zonque@gmail.com>
CC: Arnd Bergmann <arnd@arndb.de>
---
 Documentation/devicetree/bindings/mmc/pxa-mmc.txt |  2 +
 arch/arm/boot/dts/pxa27x.dtsi                     |  4 ++
 drivers/mmc/host/pxamci.c                         | 50 ++++++++++++++++++-----
 3 files changed, 45 insertions(+), 11 deletions(-)

diff --git a/Documentation/devicetree/bindings/mmc/pxa-mmc.txt b/Documentation/devicetree/bindings/mmc/pxa-mmc.txt
index b7025de..27447ec 100644
--- a/Documentation/devicetree/bindings/mmc/pxa-mmc.txt
+++ b/Documentation/devicetree/bindings/mmc/pxa-mmc.txt
@@ -5,6 +5,7 @@ Driver bindings for the PXA MCI (MMC/SDIO) interfaces
 Required properties:
 - compatible: Should be "marvell,pxa-mmc".
 - vmmc-supply: A regulator for VMMC
+- marvell,dma-channels: 2 PXA DMA channels [0] for RX, [1] for TX
 
 Optional properties:
 - marvell,detect-delay-ms: sets the detection delay timeout in ms.
@@ -19,6 +20,7 @@ mmc0: mmc@41100000 {
 	compatible = "marvell,pxa-mmc";
 	reg = <0x41100000 0x1000>;
 	interrupts = <23>;
+	marvell,dma-channels = <21 22>;
 	cd-gpios = <&gpio 23 0>;
 	wp-gpios = <&gpio 24 0>;
 };
diff --git a/arch/arm/boot/dts/pxa27x.dtsi b/arch/arm/boot/dts/pxa27x.dtsi
index 44df554..3f97520 100644
--- a/arch/arm/boot/dts/pxa27x.dtsi
+++ b/arch/arm/boot/dts/pxa27x.dtsi
@@ -16,5 +16,9 @@
 			interrupts = <8>, <9>, <10>;
 			interrupt-names = "gpio0", "gpio1", "gpio_mux";
 		};
+
+		mmc@41100000 {
+			marvell,dma-channels = <21 22>;
+		};
 	};
 };
diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c
index 32fe113..8c7a110 100644
--- a/drivers/mmc/host/pxamci.c
+++ b/drivers/mmc/host/pxamci.c
@@ -613,11 +613,37 @@ static int pxamci_of_init(struct platform_device *pdev)
 
         return 0;
 }
+
+static int pxamci_of_init_dma(struct platform_device *pdev,
+		struct pxamci_host *host)
+{
+        struct device_node *np = pdev->dev.of_node;
+        u32 tmp;
+	int ret;
+
+	ret = of_property_read_u32_index(np, "marvell,dma-channels", 0, &tmp);
+	if (ret < 0)
+		return ret;
+	host->dma_drcmrrx = tmp;
+
+	ret = of_property_read_u32_index(np, "marvell,dma-channels", 1, &tmp);
+	if (ret < 0)
+		return ret;
+	host->dma_drcmrtx = tmp;
+
+	return 0;
+}
 #else
 static int pxamci_of_init(struct platform_device *pdev)
 {
         return 0;
 }
+
+static int pxamci_of_init_dma(struct platform_device *pdev,
+		struct pxamci_host *host)
+{
+	return -ENODATA;
+}
 #endif
 
 static int pxamci_probe(struct platform_device *pdev)
@@ -741,19 +767,21 @@ static int pxamci_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, mmc);
 
-	dmarx = platform_get_resource(pdev, IORESOURCE_DMA, 0);
-	if (!dmarx) {
-		ret = -ENXIO;
-		goto out;
-	}
-	host->dma_drcmrrx = dmarx->start;
+	if (pxamci_of_init_dma(pdev, host) < 0) {
+		dmarx = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+		if (!dmarx) {
+			ret = -ENXIO;
+			goto out;
+		}
+		host->dma_drcmrrx = dmarx->start;
 
-	dmatx = platform_get_resource(pdev, IORESOURCE_DMA, 1);
-	if (!dmatx) {
-		ret = -ENXIO;
-		goto out;
+		dmatx = platform_get_resource(pdev, IORESOURCE_DMA, 1);
+		if (!dmatx) {
+			ret = -ENXIO;
+			goto out;
+		}
+		host->dma_drcmrtx = dmatx->start;
 	}
-	host->dma_drcmrtx = dmatx->start;
 
 	if (host->pdata) {
 		gpio_cd = host->pdata->gpio_card_detect;
-- 
1.8.4.3

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

* [PATCH 5/9] ARM: dts: provide DMA config to pxamci
@ 2013-12-08 22:53         ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-08 22:53 UTC (permalink / raw)
  To: linux-arm-kernel

Non-dts implementation supply required DMA channel numbers as
IORESOURCE_DMA. However, there is was no way to get them from
device tree.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Daniel Mack <zonque@gmail.com>
CC: Arnd Bergmann <arnd@arndb.de>
---
 Documentation/devicetree/bindings/mmc/pxa-mmc.txt |  2 +
 arch/arm/boot/dts/pxa27x.dtsi                     |  4 ++
 drivers/mmc/host/pxamci.c                         | 50 ++++++++++++++++++-----
 3 files changed, 45 insertions(+), 11 deletions(-)

diff --git a/Documentation/devicetree/bindings/mmc/pxa-mmc.txt b/Documentation/devicetree/bindings/mmc/pxa-mmc.txt
index b7025de..27447ec 100644
--- a/Documentation/devicetree/bindings/mmc/pxa-mmc.txt
+++ b/Documentation/devicetree/bindings/mmc/pxa-mmc.txt
@@ -5,6 +5,7 @@ Driver bindings for the PXA MCI (MMC/SDIO) interfaces
 Required properties:
 - compatible: Should be "marvell,pxa-mmc".
 - vmmc-supply: A regulator for VMMC
+- marvell,dma-channels: 2 PXA DMA channels [0] for RX, [1] for TX
 
 Optional properties:
 - marvell,detect-delay-ms: sets the detection delay timeout in ms.
@@ -19,6 +20,7 @@ mmc0: mmc at 41100000 {
 	compatible = "marvell,pxa-mmc";
 	reg = <0x41100000 0x1000>;
 	interrupts = <23>;
+	marvell,dma-channels = <21 22>;
 	cd-gpios = <&gpio 23 0>;
 	wp-gpios = <&gpio 24 0>;
 };
diff --git a/arch/arm/boot/dts/pxa27x.dtsi b/arch/arm/boot/dts/pxa27x.dtsi
index 44df554..3f97520 100644
--- a/arch/arm/boot/dts/pxa27x.dtsi
+++ b/arch/arm/boot/dts/pxa27x.dtsi
@@ -16,5 +16,9 @@
 			interrupts = <8>, <9>, <10>;
 			interrupt-names = "gpio0", "gpio1", "gpio_mux";
 		};
+
+		mmc at 41100000 {
+			marvell,dma-channels = <21 22>;
+		};
 	};
 };
diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c
index 32fe113..8c7a110 100644
--- a/drivers/mmc/host/pxamci.c
+++ b/drivers/mmc/host/pxamci.c
@@ -613,11 +613,37 @@ static int pxamci_of_init(struct platform_device *pdev)
 
         return 0;
 }
+
+static int pxamci_of_init_dma(struct platform_device *pdev,
+		struct pxamci_host *host)
+{
+        struct device_node *np = pdev->dev.of_node;
+        u32 tmp;
+	int ret;
+
+	ret = of_property_read_u32_index(np, "marvell,dma-channels", 0, &tmp);
+	if (ret < 0)
+		return ret;
+	host->dma_drcmrrx = tmp;
+
+	ret = of_property_read_u32_index(np, "marvell,dma-channels", 1, &tmp);
+	if (ret < 0)
+		return ret;
+	host->dma_drcmrtx = tmp;
+
+	return 0;
+}
 #else
 static int pxamci_of_init(struct platform_device *pdev)
 {
         return 0;
 }
+
+static int pxamci_of_init_dma(struct platform_device *pdev,
+		struct pxamci_host *host)
+{
+	return -ENODATA;
+}
 #endif
 
 static int pxamci_probe(struct platform_device *pdev)
@@ -741,19 +767,21 @@ static int pxamci_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, mmc);
 
-	dmarx = platform_get_resource(pdev, IORESOURCE_DMA, 0);
-	if (!dmarx) {
-		ret = -ENXIO;
-		goto out;
-	}
-	host->dma_drcmrrx = dmarx->start;
+	if (pxamci_of_init_dma(pdev, host) < 0) {
+		dmarx = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+		if (!dmarx) {
+			ret = -ENXIO;
+			goto out;
+		}
+		host->dma_drcmrrx = dmarx->start;
 
-	dmatx = platform_get_resource(pdev, IORESOURCE_DMA, 1);
-	if (!dmatx) {
-		ret = -ENXIO;
-		goto out;
+		dmatx = platform_get_resource(pdev, IORESOURCE_DMA, 1);
+		if (!dmatx) {
+			ret = -ENXIO;
+			goto out;
+		}
+		host->dma_drcmrtx = dmatx->start;
 	}
-	host->dma_drcmrtx = dmatx->start;
 
 	if (host->pdata) {
 		gpio_cd = host->pdata->gpio_card_detect;
-- 
1.8.4.3

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

* [PATCH 6/9] ARM: dts: pxa3xx: move declaration to header
  2013-12-08 22:53       ` Sergei Ianovich
@ 2013-12-08 22:53         ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-08 22:53 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Daniel Mack, Arnd Bergmann, Eric Miao,
	Russell King, Haojian Zhuang

This way it will be more difficult to change the declaration in one
place, but not the other.

In addition, the change allows to use the binding for pxa-gpio on
other PXA CPUs.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Daniel Mack <zonque@gmail.com>
CC: Arnd Bergmann <arnd@arndb.de>
---
 arch/arm/mach-pxa/include/mach/irqs.h | 4 ++++
 arch/arm/mach-pxa/pxa3xx.c            | 2 --
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-pxa/include/mach/irqs.h b/arch/arm/mach-pxa/include/mach/irqs.h
index 48c2fd8..0d71ae9 100644
--- a/arch/arm/mach-pxa/include/mach/irqs.h
+++ b/arch/arm/mach-pxa/include/mach/irqs.h
@@ -113,4 +113,8 @@ void ichp_handle_irq(struct pt_regs *);
 void pxa_init_irq(int irq_nr, int (*set_wake)(struct irq_data *, unsigned int));
 #endif
 
+#ifdef CONFIG_OF
+extern void __init pxa_dt_irq_init(int (*fn)(struct irq_data *, unsigned int));
+#endif /* CONFIG_OF */
+
 #endif /* __ASM_MACH_IRQS_H */
diff --git a/arch/arm/mach-pxa/pxa3xx.c b/arch/arm/mach-pxa/pxa3xx.c
index 87011f3..2397dec 100644
--- a/arch/arm/mach-pxa/pxa3xx.c
+++ b/arch/arm/mach-pxa/pxa3xx.c
@@ -42,8 +42,6 @@
 #define PECR_IE(n)	((1 << ((n) * 2)) << 28)
 #define PECR_IS(n)	((1 << ((n) * 2)) << 29)
 
-extern void __init pxa_dt_irq_init(int (*fn)(struct irq_data *, unsigned int));
-
 static DEFINE_PXA3_CKEN(pxa3xx_ffuart, FFUART, 14857000, 1);
 static DEFINE_PXA3_CKEN(pxa3xx_btuart, BTUART, 14857000, 1);
 static DEFINE_PXA3_CKEN(pxa3xx_stuart, STUART, 14857000, 1);
-- 
1.8.4.3


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

* [PATCH 6/9] ARM: dts: pxa3xx: move declaration to header
@ 2013-12-08 22:53         ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-08 22:53 UTC (permalink / raw)
  To: linux-arm-kernel

This way it will be more difficult to change the declaration in one
place, but not the other.

In addition, the change allows to use the binding for pxa-gpio on
other PXA CPUs.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Daniel Mack <zonque@gmail.com>
CC: Arnd Bergmann <arnd@arndb.de>
---
 arch/arm/mach-pxa/include/mach/irqs.h | 4 ++++
 arch/arm/mach-pxa/pxa3xx.c            | 2 --
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-pxa/include/mach/irqs.h b/arch/arm/mach-pxa/include/mach/irqs.h
index 48c2fd8..0d71ae9 100644
--- a/arch/arm/mach-pxa/include/mach/irqs.h
+++ b/arch/arm/mach-pxa/include/mach/irqs.h
@@ -113,4 +113,8 @@ void ichp_handle_irq(struct pt_regs *);
 void pxa_init_irq(int irq_nr, int (*set_wake)(struct irq_data *, unsigned int));
 #endif
 
+#ifdef CONFIG_OF
+extern void __init pxa_dt_irq_init(int (*fn)(struct irq_data *, unsigned int));
+#endif /* CONFIG_OF */
+
 #endif /* __ASM_MACH_IRQS_H */
diff --git a/arch/arm/mach-pxa/pxa3xx.c b/arch/arm/mach-pxa/pxa3xx.c
index 87011f3..2397dec 100644
--- a/arch/arm/mach-pxa/pxa3xx.c
+++ b/arch/arm/mach-pxa/pxa3xx.c
@@ -42,8 +42,6 @@
 #define PECR_IE(n)	((1 << ((n) * 2)) << 28)
 #define PECR_IS(n)	((1 << ((n) * 2)) << 29)
 
-extern void __init pxa_dt_irq_init(int (*fn)(struct irq_data *, unsigned int));
-
 static DEFINE_PXA3_CKEN(pxa3xx_ffuart, FFUART, 14857000, 1);
 static DEFINE_PXA3_CKEN(pxa3xx_btuart, BTUART, 14857000, 1);
 static DEFINE_PXA3_CKEN(pxa3xx_stuart, STUART, 14857000, 1);
-- 
1.8.4.3

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

* [PATCH 7/9] ARM: dts: pxa27x: skip static platform devices
  2013-12-08 22:53       ` Sergei Ianovich
@ 2013-12-08 22:53         ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-08 22:53 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Russell King - ARM Linux, Daniel Mack,
	Arnd Bergmann, Eric Miao, Haojian Zhuang

Static plaform devices are created from postcore_initcall(). The
status quo remains for non-device tree machines.

Device tree machine now have a chance to prevent spawning of static
devices by calling pxa27x_skip_init().

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Russell King - ARM Linux <linux@arm.linux.org.uk>
CC: Daniel Mack <zonque@gmail.com>
CC: Arnd Bergmann <arnd@arndb.de>
---
 arch/arm/mach-pxa/include/mach/pxa27x.h |  1 +
 arch/arm/mach-pxa/pxa27x.c              | 10 ++++++++++
 2 files changed, 11 insertions(+)

diff --git a/arch/arm/mach-pxa/include/mach/pxa27x.h b/arch/arm/mach-pxa/include/mach/pxa27x.h
index 7cff640..d62fc8f 100644
--- a/arch/arm/mach-pxa/include/mach/pxa27x.h
+++ b/arch/arm/mach-pxa/include/mach/pxa27x.h
@@ -23,6 +23,7 @@ extern void __init pxa27x_map_io(void);
 extern void __init pxa27x_init_irq(void);
 extern int __init pxa27x_set_pwrmode(unsigned int mode);
 extern void pxa27x_cpu_pm_enter(suspend_state_t state);
+extern void __init pxa27x_skip_init(void);
 
 #define pxa27x_handle_irq	ichp_handle_irq
 
diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c
index 301471a..98dea3a 100644
--- a/arch/arm/mach-pxa/pxa27x.c
+++ b/arch/arm/mach-pxa/pxa27x.c
@@ -452,6 +452,13 @@ static struct platform_device *devices[] __initdata = {
 	&pxa27x_device_pwm1,
 };
 
+static unsigned int skip_init;
+
+void __init pxa27x_skip_init(void)
+{
+	skip_init = 1;
+}
+
 static int __init pxa27x_init(void)
 {
 	int ret = 0;
@@ -471,6 +478,9 @@ static int __init pxa27x_init(void)
 		register_syscore_ops(&pxa2xx_mfp_syscore_ops);
 		register_syscore_ops(&pxa2xx_clock_syscore_ops);
 
+		if (skip_init)
+			return 0;
+
 		pxa_register_device(&pxa27x_device_gpio, &pxa27x_gpio_info);
 		ret = platform_add_devices(devices, ARRAY_SIZE(devices));
 	}
-- 
1.8.4.3


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

* [PATCH 7/9] ARM: dts: pxa27x: skip static platform devices
@ 2013-12-08 22:53         ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-08 22:53 UTC (permalink / raw)
  To: linux-arm-kernel

Static plaform devices are created from postcore_initcall(). The
status quo remains for non-device tree machines.

Device tree machine now have a chance to prevent spawning of static
devices by calling pxa27x_skip_init().

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Russell King - ARM Linux <linux@arm.linux.org.uk>
CC: Daniel Mack <zonque@gmail.com>
CC: Arnd Bergmann <arnd@arndb.de>
---
 arch/arm/mach-pxa/include/mach/pxa27x.h |  1 +
 arch/arm/mach-pxa/pxa27x.c              | 10 ++++++++++
 2 files changed, 11 insertions(+)

diff --git a/arch/arm/mach-pxa/include/mach/pxa27x.h b/arch/arm/mach-pxa/include/mach/pxa27x.h
index 7cff640..d62fc8f 100644
--- a/arch/arm/mach-pxa/include/mach/pxa27x.h
+++ b/arch/arm/mach-pxa/include/mach/pxa27x.h
@@ -23,6 +23,7 @@ extern void __init pxa27x_map_io(void);
 extern void __init pxa27x_init_irq(void);
 extern int __init pxa27x_set_pwrmode(unsigned int mode);
 extern void pxa27x_cpu_pm_enter(suspend_state_t state);
+extern void __init pxa27x_skip_init(void);
 
 #define pxa27x_handle_irq	ichp_handle_irq
 
diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c
index 301471a..98dea3a 100644
--- a/arch/arm/mach-pxa/pxa27x.c
+++ b/arch/arm/mach-pxa/pxa27x.c
@@ -452,6 +452,13 @@ static struct platform_device *devices[] __initdata = {
 	&pxa27x_device_pwm1,
 };
 
+static unsigned int skip_init;
+
+void __init pxa27x_skip_init(void)
+{
+	skip_init = 1;
+}
+
 static int __init pxa27x_init(void)
 {
 	int ret = 0;
@@ -471,6 +478,9 @@ static int __init pxa27x_init(void)
 		register_syscore_ops(&pxa2xx_mfp_syscore_ops);
 		register_syscore_ops(&pxa2xx_clock_syscore_ops);
 
+		if (skip_init)
+			return 0;
+
 		pxa_register_device(&pxa27x_device_gpio, &pxa27x_gpio_info);
 		ret = platform_add_devices(devices, ARRAY_SIZE(devices));
 	}
-- 
1.8.4.3

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

* [PATCH 8/9] ARM: dts: pxa27x: device tree irq init
  2013-12-08 22:53       ` Sergei Ianovich
@ 2013-12-08 22:53         ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-08 22:53 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Daniel Mack, Arnd Bergmann, Eric Miao,
	Russell King, Haojian Zhuang

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Daniel Mack <zonque@gmail.com>
CC: Arnd Bergmann <arnd@arndb.de>
---
 arch/arm/mach-pxa/include/mach/pxa27x.h | 3 +++
 arch/arm/mach-pxa/pxa27x.c              | 7 +++++++
 2 files changed, 10 insertions(+)

diff --git a/arch/arm/mach-pxa/include/mach/pxa27x.h b/arch/arm/mach-pxa/include/mach/pxa27x.h
index d62fc8f..64d0804 100644
--- a/arch/arm/mach-pxa/include/mach/pxa27x.h
+++ b/arch/arm/mach-pxa/include/mach/pxa27x.h
@@ -24,6 +24,9 @@ extern void __init pxa27x_init_irq(void);
 extern int __init pxa27x_set_pwrmode(unsigned int mode);
 extern void pxa27x_cpu_pm_enter(suspend_state_t state);
 extern void __init pxa27x_skip_init(void);
+#ifdef CONFIG_OF
+extern void __init pxa27x_dt_init_irq(void);
+#endif  /* CONFIG_OF */
 
 #define pxa27x_handle_irq	ichp_handle_irq
 
diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c
index 98dea3a..1235201 100644
--- a/arch/arm/mach-pxa/pxa27x.c
+++ b/arch/arm/mach-pxa/pxa27x.c
@@ -398,6 +398,13 @@ void __init pxa27x_init_irq(void)
 	pxa_init_irq(34, pxa27x_set_wake);
 }
 
+#ifdef CONFIG_OF
+void __init pxa27x_dt_init_irq(void)
+{
+	pxa_dt_irq_init(pxa27x_set_wake);
+}
+#endif  /* CONFIG_OF */
+
 static struct map_desc pxa27x_io_desc[] __initdata = {
 	{	/* Mem Ctl */
 		.virtual	= (unsigned long)SMEMC_VIRT,
-- 
1.8.4.3


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

* [PATCH 8/9] ARM: dts: pxa27x: device tree irq init
@ 2013-12-08 22:53         ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-08 22:53 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Daniel Mack <zonque@gmail.com>
CC: Arnd Bergmann <arnd@arndb.de>
---
 arch/arm/mach-pxa/include/mach/pxa27x.h | 3 +++
 arch/arm/mach-pxa/pxa27x.c              | 7 +++++++
 2 files changed, 10 insertions(+)

diff --git a/arch/arm/mach-pxa/include/mach/pxa27x.h b/arch/arm/mach-pxa/include/mach/pxa27x.h
index d62fc8f..64d0804 100644
--- a/arch/arm/mach-pxa/include/mach/pxa27x.h
+++ b/arch/arm/mach-pxa/include/mach/pxa27x.h
@@ -24,6 +24,9 @@ extern void __init pxa27x_init_irq(void);
 extern int __init pxa27x_set_pwrmode(unsigned int mode);
 extern void pxa27x_cpu_pm_enter(suspend_state_t state);
 extern void __init pxa27x_skip_init(void);
+#ifdef CONFIG_OF
+extern void __init pxa27x_dt_init_irq(void);
+#endif  /* CONFIG_OF */
 
 #define pxa27x_handle_irq	ichp_handle_irq
 
diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c
index 98dea3a..1235201 100644
--- a/arch/arm/mach-pxa/pxa27x.c
+++ b/arch/arm/mach-pxa/pxa27x.c
@@ -398,6 +398,13 @@ void __init pxa27x_init_irq(void)
 	pxa_init_irq(34, pxa27x_set_wake);
 }
 
+#ifdef CONFIG_OF
+void __init pxa27x_dt_init_irq(void)
+{
+	pxa_dt_irq_init(pxa27x_set_wake);
+}
+#endif  /* CONFIG_OF */
+
 static struct map_desc pxa27x_io_desc[] __initdata = {
 	{	/* Mem Ctl */
 		.virtual	= (unsigned long)SMEMC_VIRT,
-- 
1.8.4.3

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

* [PATCH 9/9] ARM: pxa27x: device tree support ICP DAS LP-8x4x
  2013-12-08 22:53       ` Sergei Ianovich
  (?)
@ 2013-12-08 22:53         ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-08 22:53 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Daniel Mack, Arnd Bergmann, Olof Johansson,
	Linus Walleij, Rob Herring, Pawel Moll, Mark Rutland,
	Stephen Warren, Ian Campbell, Russell King, Eric Miao,
	Haojian Zhuang, open list:OPEN FIRMWARE AND...

ICP DAS calls LP-8x4x 'programmable automation controller'. It is
an industrial computer based on PXA270 SoC. They ship it with a 2.6.19
kernel and proprietary kernel module and userspace library to access
its industrial IO.

This patch allows to boot the device with a modern kernel with device
tree. It adds support for:
* MMC card interface on PXA270
* USB 1.1 port on PXA270
* 2 NOR flash devices
* 2 onboard ethernet Davicom DM9000 devices
* 3 serial UART ports on PXA270

Support for these devices will be added in separate patches, since
they are not currently supported by the kernel:
* DS1302 RTC
* 512kiB SRAM
* FPGA irq chip
* 3 built-in and up to 32 pluggable 8250 serial UART ports
* industrial IO parallel bus
* digital and analog industrial IO modules for parallel bus
* serial interface for digital and analog industrial IO modules on
  parallel bus

Not supported for now:
* VGA interface on PXA270 for lack of dts binding

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Daniel Mack <zonque@gmail.com>
CC: Arnd Bergmann <arnd@arndb.de>
CC: Olof Johansson <olof@lixom.net>
CC: Linus Walleij <linus.walleij@linaro.org>
---
 Changes v2..v3:
 * further clean up defconfig (minus 100 lines more) as suggested 
   by Arnd Bergmann

 * rewrite machine support code to use device tree

 changes v1..v2
 * clean up defconfig (reduces size by 10) as suggested 
   by Arnd Bergmann

 * the rest is now irrelevant

 arch/arm/boot/dts/Makefile          |   1 +
 arch/arm/boot/dts/pxa27x-lp8x4x.dts | 111 ++++++++++++++++++++++++
 arch/arm/configs/lp8x4x_defconfig   | 162 ++++++++++++++++++++++++++++++++++++
 arch/arm/mach-pxa/Kconfig           |  31 +++++++
 arch/arm/mach-pxa/Makefile          |   1 +
 arch/arm/mach-pxa/pxa27x-dt.c       |  97 +++++++++++++++++++++
 6 files changed, 403 insertions(+)
 create mode 100644 arch/arm/boot/dts/pxa27x-lp8x4x.dts
 create mode 100644 arch/arm/configs/lp8x4x_defconfig
 create mode 100644 arch/arm/mach-pxa/pxa27x-dt.c

diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index d57c1a6..c4752ff 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -206,6 +206,7 @@ dtb-$(CONFIG_ARCH_OMAP2PLUS) += omap2420-h4.dtb \
 	dra7-evm.dtb
 dtb-$(CONFIG_ARCH_ORION5X) += orion5x-lacie-ethernet-disk-mini-v2.dtb
 dtb-$(CONFIG_ARCH_PRIMA2) += prima2-evb.dtb
+dtb-$(CONFIG_MACH_PXA27X_DT) += pxa27x-lp8x4x.dtb
 dtb-$(CONFIG_ARCH_U8500) += ste-snowball.dtb \
 	ste-hrefprev60-stuib.dtb \
 	ste-hrefprev60-tvk.dtb \
diff --git a/arch/arm/boot/dts/pxa27x-lp8x4x.dts b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
new file mode 100644
index 0000000..b288c98
--- /dev/null
+++ b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
@@ -0,0 +1,111 @@
+/* Device tree for ICP DAS LP-8x4x */
+/dts-v1/;
+
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include "pxa27x.dtsi"
+
+/ {
+	model = "ICP DAS LP-8x4x programmable automation controller";
+	compatible = "marvell,lp8x4x", "marvell,pxa27x";
+
+	memory {
+		reg = <0xa0000000 0x08000000>;
+	};
+
+	regulators {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		vmmc: regulator@0 {
+			compatible = "regulator-fixed";
+			reg = <0>;
+			regulator-name = "vmmc";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-always-on;
+		};
+	};
+
+	flash@00000000 {
+		compatible = "cfi-flash";
+		reg = <0x0 0x02000000>;
+		bank-width = <4>;
+		device-width = <2>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		fs@0 {
+			label = "u-boot";
+			reg = <0 0x40000>;
+		};
+		fs@40000 {
+			label = "settings";
+			reg = <0x40000 0x40000>;
+		};
+		fs@80000 {
+			label = "kernel";
+			reg = <0x80000 0x280000>;
+		};
+		fs@300000 {
+			label = "root_fs";
+			reg = <0x300000 0x1d00000>;
+		};
+	};
+
+	flash@04000000 {
+		compatible = "cfi-flash";
+		reg = <0x04000000 0x02000000>;
+		bank-width = <2>;
+		device-width = <1>;
+	};
+
+	pxabus {
+		pxairq: interrupt-controller@40d00000 {
+			marvell,intc-priority;
+			marvell,intc-nr-irqs = <34>;
+		};
+
+		uart@40100000 {
+			status = "okay";
+		};
+
+		uart@40200000 {
+			status = "okay";
+		};
+
+		uart@40700000 {
+			status = "okay";
+		};
+
+		mmc@41100000 {
+			status = "okay";
+			vmmc-supply = <&vmmc>;
+			marvell,dma-channels = <21 22>;
+		};
+
+		ohci@4c000000 {
+			status = "okay";
+			marvell,port-mode = <3>;
+			marvell,oc-mode-perport;
+			marvell,enable-port1;
+		};
+
+		eth0: eth@0c000000 {
+			compatible = "davicom,dm9000";
+			reg = <0x0c000000 0x2
+			       0x0c004000 0x2>;
+			interrupt-parent = <&gpio>;
+			interrupts = <9 IRQ_TYPE_EDGE_RISING>;
+			status = "okay";
+		};
+
+		eth1: eth@0d000000 {
+			compatible = "davicom,dm9000";
+			reg = <0x0d000000 0x2
+			       0x0d004000 0x2>;
+			interrupt-parent = <&gpio>;
+			interrupts = <82 IRQ_TYPE_EDGE_RISING>;
+			status = "okay";
+		};
+	};
+};
diff --git a/arch/arm/configs/lp8x4x_defconfig b/arch/arm/configs/lp8x4x_defconfig
new file mode 100644
index 0000000..faaa604
--- /dev/null
+++ b/arch/arm/configs/lp8x4x_defconfig
@@ -0,0 +1,162 @@
+# CONFIG_LOCALVERSION_AUTO is not set
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_RCU_BOOST=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_NS is not set
+# CONFIG_IPC_NS is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+# CONFIG_UID16 is not set
+# CONFIG_SHMEM is not set
+CONFIG_EMBEDDED=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_SLOB=y
+CONFIG_JUMP_LABEL=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+# CONFIG_LBDAF is not set
+CONFIG_BLK_CMDLINE_PARSER=y
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_ARCH_PXA=y
+CONFIG_MACH_PXA27X_DT=y
+CONFIG_MACH_LP8X4X=y
+# CONFIG_ARM_THUMB is not set
+CONFIG_PREEMPT=y
+CONFIG_AEABI=y
+# CONFIG_COMPACTION is not set
+# CONFIG_CROSS_MEMORY_ATTACH is not set
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="init=/sbin/init root=/dev/mmcblk0p1 rw rootfstype=ext4 console=ttyS0,115200 mem=128M rootwait"
+# CONFIG_SUSPEND is not set
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_BRIDGE=m
+CONFIG_BRIDGE_VLAN_FILTERING=y
+CONFIG_VLAN_8021Q=m
+CONFIG_VLAN_8021Q_GVRP=y
+CONFIG_VLAN_8021Q_MVRP=y
+# CONFIG_WIRELESS is not set
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+# CONFIG_FW_LOADER is not set
+CONFIG_MTD=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_CFI_GEOMETRY=y
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_PHYSMAP_OF=y
+CONFIG_PROC_DEVICETREE=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_LOOP_MIN_COUNT=2
+CONFIG_SCSI=y
+# CONFIG_SCSI_PROC_FS is not set
+CONFIG_BLK_DEV_SD=y
+# CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_NETDEVICES=y
+CONFIG_BONDING=m
+CONFIG_MACVLAN=m
+CONFIG_MACVTAP=m
+CONFIG_TUN=m
+# CONFIG_NET_VENDOR_ARC is not set
+# CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_CIRRUS is not set
+CONFIG_DM9000=y
+CONFIG_DM9000_FORCE_SIMPLE_PHY_POLL=y
+# CONFIG_NET_VENDOR_FARADAY is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+CONFIG_PPP=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPPOE=m
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_SLIP=m
+CONFIG_SLIP_COMPRESSED=y
+# CONFIG_WLAN is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=800
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=600
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_SERIO is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_8250=y
+# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=40
+CONFIG_SERIAL_8250_RUNTIME_UARTS=40
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_PXA=y
+CONFIG_HW_RANDOM=y
+CONFIG_I2C=m
+# CONFIG_I2C_COMPAT is not set
+CONFIG_I2C_PXA=m
+CONFIG_I2C_PXA_SLAVE=y
+# CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_SA1100_WATCHDOG=m
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_FB=y
+CONFIG_FB_PXA=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_LOGO=y
+CONFIG_USB=m
+CONFIG_USB_OHCI_HCD=m
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+CONFIG_USB_STORAGE=m
+CONFIG_USB_SERIAL=m
+CONFIG_MMC=y
+CONFIG_MMC_PXA=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_PXA=m
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_EXT2_FS=m
+CONFIG_EXT3_FS=y
+CONFIG_EXT4_FS=y
+CONFIG_REISERFS_FS=m
+CONFIG_ISO9660_FS=m
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_NTFS_FS=m
+CONFIG_NTFS_RW=y
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V4=y
+CONFIG_ROOT_NFS=y
+CONFIG_CIFS=m
+CONFIG_CIFS_STATS=y
+CONFIG_CODA_FS=m
+CONFIG_NLS_DEFAULT="cp855"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_855=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_UTF8=y
+CONFIG_PRINTK_TIME=y
+CONFIG_DEBUG_INFO=y
diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig
index 96100db..f0c8f01 100644
--- a/arch/arm/mach-pxa/Kconfig
+++ b/arch/arm/mach-pxa/Kconfig
@@ -4,6 +4,20 @@ menu "Intel PXA2xx/PXA3xx Implementations"
 
 comment "Intel/Marvell Dev Platforms (sorted by hardware release time)"
 
+config MACH_PXA27X_DT
+	bool "Support PXA27x platforms from device tree"
+	select USE_OF
+	help
+	  Include support for Marvell PXA27x based platforms using
+	  the device tree.
+
+	  While MACH_PXA27X_DT when enabled should boot any PXA27x
+	  compatible machine, it still makes sense to select specific
+	  machines. Those options will select required features and
+	  provide per-machine errata workarounds.
+
+	  If unsure, say Y.
+
 config MACH_PXA3XX_DT
 	bool "Support PXA3xx platforms from device tree"
 	select CPU_PXA300
@@ -273,6 +287,23 @@ config MACH_VPAC270
 
 comment "End-user Products (sorted by vendor name)"
 
+config MACH_LP8X4X
+	bool "ICP DAS LP-8X4X (device tree)"
+	depends on MACH_PXA27X_DT
+	select IWMMXT
+	select PXA27x
+	help
+	  Say Y here if you intend to run this kernel on an ICP DAS
+	  LP-8x4x programmable automation controller.
+
+	  LP-8x4x is ARM-based and built around PXA270 SoC. The device
+	  has 128 MiB SDRAM, 48 or 96 MiB NOR flash, VGA port with
+	  800x600 resolution, MMC card slot, 2 Ethernet ports, 1 USB
+	  port, 5 serial ports (1 on them is wired internally to
+	  expansion slots). The device has a range of digital and
+	  analog expansion IO modules which can be installed in 1, 4 or
+	  8 slots depending on the model.
+
 config MACH_H4700
 	bool "HP iPAQ hx4700"
 	select HAVE_PWM
diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile
index 648867a..adaa72a 100644
--- a/arch/arm/mach-pxa/Makefile
+++ b/arch/arm/mach-pxa/Makefile
@@ -20,6 +20,7 @@ obj-$(CONFIG_CPU_PXA930)	+= pxa930.o
 # NOTE: keep the order of boards in accordance to their order in Kconfig
 
 # Device Tree support
+obj-$(CONFIG_MACH_PXA27X_DT)	+= pxa27x-dt.o
 obj-$(CONFIG_MACH_PXA3XX_DT)	+= pxa-dt.o
 
 # Intel/Marvell Dev Platforms
diff --git a/arch/arm/mach-pxa/pxa27x-dt.c b/arch/arm/mach-pxa/pxa27x-dt.c
new file mode 100644
index 0000000..95c6ef4
--- /dev/null
+++ b/arch/arm/mach-pxa/pxa27x-dt.c
@@ -0,0 +1,97 @@
+/*
+ *  linux/arch/arm/mach-pxa/pxa27x-dt.c
+ *
+ *  Copyright (C) 2013 Sergei Ianovich
+ *
+ *  based mostly on linux/arch/arm/mach-pxa/pxa-dt.c by Daniel Mack
+ *
+ *  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
+ *  publishhed by the Free Software Foundation.
+ */
+
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <asm/io.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <mach/irqs.h>
+#include <mach/pxa27x.h>
+
+#include "generic.h"
+
+#ifdef CONFIG_PXA27x
+extern void __init pxa27x_dt_init_irq(void);
+
+static const struct of_dev_auxdata pxa27x_auxdata_lookup[] __initconst = {
+	OF_DEV_AUXDATA("mrvl,pxa-uart",		0x40100000, "pxa2xx-uart.0", NULL),
+	OF_DEV_AUXDATA("mrvl,pxa-uart",		0x40200000, "pxa2xx-uart.1", NULL),
+	OF_DEV_AUXDATA("mrvl,pxa-uart",		0x40700000, "pxa2xx-uart.2", NULL),
+	OF_DEV_AUXDATA("mrvl,pxa-uart",		0x41600000, "pxa2xx-uart.3", NULL),
+	OF_DEV_AUXDATA("marvell,pxa-mmc",	0x41100000, "pxa2xx-mci.0", NULL),
+	OF_DEV_AUXDATA("intel,pxa27x-gpio",	0x40e00000, "pxa27x-gpio", NULL),
+	OF_DEV_AUXDATA("marvell,pxa-ohci",	0x4c000000, "pxa27x-ohci", NULL),
+	OF_DEV_AUXDATA("mrvl,pxa-i2c",		0x40301680, "pxa2xx-i2c.0", NULL),
+	{}
+};
+
+static void __init pxa27x_init_early(void)
+{
+	pxa27x_skip_init();
+}
+
+static void __init pxa27x_dt_init(void)
+{
+	of_platform_populate(NULL, of_default_bus_match_table,
+			     pxa27x_auxdata_lookup, NULL);
+}
+
+static const char *pxa27x_dt_board_compat[] __initdata = {
+	"marvell,pxa27x",
+	NULL,
+};
+
+#ifdef CONFIG_MACH_LP8X4X
+static const char *lp8x4x_dt_board_compat[] __initdata = {
+	"marvell,lp8x4x",
+	NULL,
+};
+
+static void lp8x4x_restart(enum reboot_mode mode, const char *cmd)
+{
+	/* Switch off fast-bus and turbo mode */
+	asm volatile("mcr       p14, 0, %0, c6, c0, 0" : :
+			"r"(2));
+	/* SDRAM hangs on watchdog reset on Marvell PXA270 (erratum 71) */
+	pxa_restart(REBOOT_SOFT, cmd);
+}
+#endif
+#endif
+
+#ifdef CONFIG_PXA27x
+DT_MACHINE_START(PXA27X_DT, "Marvell PXA27x (Device Tree Support)")
+	.map_io		= pxa27x_map_io,
+	.init_irq	= pxa27x_dt_init_irq,
+	.handle_irq	= pxa27x_handle_irq,
+	.init_time	= pxa_timer_init,
+	.restart	= pxa_restart,
+	.init_early	= pxa27x_init_early,
+	.init_machine	= pxa27x_dt_init,
+	.dt_compat	= pxa27x_dt_board_compat,
+MACHINE_END
+
+#ifdef CONFIG_MACH_LP8X4X
+DT_MACHINE_START(LP8X4X_DT, "ICP DAS LP-8X4X (Device Tree Support)")
+	.map_io		= pxa27x_map_io,
+	.init_irq	= pxa27x_dt_init_irq,
+	.handle_irq	= pxa27x_handle_irq,
+	.init_time	= pxa_timer_init,
+	.restart	= lp8x4x_restart,
+	.init_early	= pxa27x_init_early,
+	.init_machine	= pxa27x_dt_init,
+	.dt_compat	= lp8x4x_dt_board_compat,
+MACHINE_END
+#endif
+#endif
-- 
1.8.4.3


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

* [PATCH 9/9] ARM: pxa27x: device tree support ICP DAS LP-8x4x
@ 2013-12-08 22:53         ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-08 22:53 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Daniel Mack, Arnd Bergmann, Olof Johansson,
	Linus Walleij, Rob Herring, Pawel Moll, Mark Rutland,
	Stephen Warren, Ian Campbell, Russell King, Eric Miao,
	Haojian Zhuang, open list:OPEN FIRMWARE AND...

ICP DAS calls LP-8x4x 'programmable automation controller'. It is
an industrial computer based on PXA270 SoC. They ship it with a 2.6.19
kernel and proprietary kernel module and userspace library to access
its industrial IO.

This patch allows to boot the device with a modern kernel with device
tree. It adds support for:
* MMC card interface on PXA270
* USB 1.1 port on PXA270
* 2 NOR flash devices
* 2 onboard ethernet Davicom DM9000 devices
* 3 serial UART ports on PXA270

Support for these devices will be added in separate patches, since
they are not currently supported by the kernel:
* DS1302 RTC
* 512kiB SRAM
* FPGA irq chip
* 3 built-in and up to 32 pluggable 8250 serial UART ports
* industrial IO parallel bus
* digital and analog industrial IO modules for parallel bus
* serial interface for digital and analog industrial IO modules on
  parallel bus

Not supported for now:
* VGA interface on PXA270 for lack of dts binding

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Daniel Mack <zonque@gmail.com>
CC: Arnd Bergmann <arnd@arndb.de>
CC: Olof Johansson <olof@lixom.net>
CC: Linus Walleij <linus.walleij@linaro.org>
---
 Changes v2..v3:
 * further clean up defconfig (minus 100 lines more) as suggested 
   by Arnd Bergmann

 * rewrite machine support code to use device tree

 changes v1..v2
 * clean up defconfig (reduces size by 10) as suggested 
   by Arnd Bergmann

 * the rest is now irrelevant

 arch/arm/boot/dts/Makefile          |   1 +
 arch/arm/boot/dts/pxa27x-lp8x4x.dts | 111 ++++++++++++++++++++++++
 arch/arm/configs/lp8x4x_defconfig   | 162 ++++++++++++++++++++++++++++++++++++
 arch/arm/mach-pxa/Kconfig           |  31 +++++++
 arch/arm/mach-pxa/Makefile          |   1 +
 arch/arm/mach-pxa/pxa27x-dt.c       |  97 +++++++++++++++++++++
 6 files changed, 403 insertions(+)
 create mode 100644 arch/arm/boot/dts/pxa27x-lp8x4x.dts
 create mode 100644 arch/arm/configs/lp8x4x_defconfig
 create mode 100644 arch/arm/mach-pxa/pxa27x-dt.c

diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index d57c1a6..c4752ff 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -206,6 +206,7 @@ dtb-$(CONFIG_ARCH_OMAP2PLUS) += omap2420-h4.dtb \
 	dra7-evm.dtb
 dtb-$(CONFIG_ARCH_ORION5X) += orion5x-lacie-ethernet-disk-mini-v2.dtb
 dtb-$(CONFIG_ARCH_PRIMA2) += prima2-evb.dtb
+dtb-$(CONFIG_MACH_PXA27X_DT) += pxa27x-lp8x4x.dtb
 dtb-$(CONFIG_ARCH_U8500) += ste-snowball.dtb \
 	ste-hrefprev60-stuib.dtb \
 	ste-hrefprev60-tvk.dtb \
diff --git a/arch/arm/boot/dts/pxa27x-lp8x4x.dts b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
new file mode 100644
index 0000000..b288c98
--- /dev/null
+++ b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
@@ -0,0 +1,111 @@
+/* Device tree for ICP DAS LP-8x4x */
+/dts-v1/;
+
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include "pxa27x.dtsi"
+
+/ {
+	model = "ICP DAS LP-8x4x programmable automation controller";
+	compatible = "marvell,lp8x4x", "marvell,pxa27x";
+
+	memory {
+		reg = <0xa0000000 0x08000000>;
+	};
+
+	regulators {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		vmmc: regulator@0 {
+			compatible = "regulator-fixed";
+			reg = <0>;
+			regulator-name = "vmmc";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-always-on;
+		};
+	};
+
+	flash@00000000 {
+		compatible = "cfi-flash";
+		reg = <0x0 0x02000000>;
+		bank-width = <4>;
+		device-width = <2>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		fs@0 {
+			label = "u-boot";
+			reg = <0 0x40000>;
+		};
+		fs@40000 {
+			label = "settings";
+			reg = <0x40000 0x40000>;
+		};
+		fs@80000 {
+			label = "kernel";
+			reg = <0x80000 0x280000>;
+		};
+		fs@300000 {
+			label = "root_fs";
+			reg = <0x300000 0x1d00000>;
+		};
+	};
+
+	flash@04000000 {
+		compatible = "cfi-flash";
+		reg = <0x04000000 0x02000000>;
+		bank-width = <2>;
+		device-width = <1>;
+	};
+
+	pxabus {
+		pxairq: interrupt-controller@40d00000 {
+			marvell,intc-priority;
+			marvell,intc-nr-irqs = <34>;
+		};
+
+		uart@40100000 {
+			status = "okay";
+		};
+
+		uart@40200000 {
+			status = "okay";
+		};
+
+		uart@40700000 {
+			status = "okay";
+		};
+
+		mmc@41100000 {
+			status = "okay";
+			vmmc-supply = <&vmmc>;
+			marvell,dma-channels = <21 22>;
+		};
+
+		ohci@4c000000 {
+			status = "okay";
+			marvell,port-mode = <3>;
+			marvell,oc-mode-perport;
+			marvell,enable-port1;
+		};
+
+		eth0: eth@0c000000 {
+			compatible = "davicom,dm9000";
+			reg = <0x0c000000 0x2
+			       0x0c004000 0x2>;
+			interrupt-parent = <&gpio>;
+			interrupts = <9 IRQ_TYPE_EDGE_RISING>;
+			status = "okay";
+		};
+
+		eth1: eth@0d000000 {
+			compatible = "davicom,dm9000";
+			reg = <0x0d000000 0x2
+			       0x0d004000 0x2>;
+			interrupt-parent = <&gpio>;
+			interrupts = <82 IRQ_TYPE_EDGE_RISING>;
+			status = "okay";
+		};
+	};
+};
diff --git a/arch/arm/configs/lp8x4x_defconfig b/arch/arm/configs/lp8x4x_defconfig
new file mode 100644
index 0000000..faaa604
--- /dev/null
+++ b/arch/arm/configs/lp8x4x_defconfig
@@ -0,0 +1,162 @@
+# CONFIG_LOCALVERSION_AUTO is not set
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_RCU_BOOST=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_NS is not set
+# CONFIG_IPC_NS is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+# CONFIG_UID16 is not set
+# CONFIG_SHMEM is not set
+CONFIG_EMBEDDED=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_SLOB=y
+CONFIG_JUMP_LABEL=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+# CONFIG_LBDAF is not set
+CONFIG_BLK_CMDLINE_PARSER=y
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_ARCH_PXA=y
+CONFIG_MACH_PXA27X_DT=y
+CONFIG_MACH_LP8X4X=y
+# CONFIG_ARM_THUMB is not set
+CONFIG_PREEMPT=y
+CONFIG_AEABI=y
+# CONFIG_COMPACTION is not set
+# CONFIG_CROSS_MEMORY_ATTACH is not set
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="init=/sbin/init root=/dev/mmcblk0p1 rw rootfstype=ext4 console=ttyS0,115200 mem=128M rootwait"
+# CONFIG_SUSPEND is not set
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_BRIDGE=m
+CONFIG_BRIDGE_VLAN_FILTERING=y
+CONFIG_VLAN_8021Q=m
+CONFIG_VLAN_8021Q_GVRP=y
+CONFIG_VLAN_8021Q_MVRP=y
+# CONFIG_WIRELESS is not set
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+# CONFIG_FW_LOADER is not set
+CONFIG_MTD=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_CFI_GEOMETRY=y
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_PHYSMAP_OF=y
+CONFIG_PROC_DEVICETREE=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_LOOP_MIN_COUNT=2
+CONFIG_SCSI=y
+# CONFIG_SCSI_PROC_FS is not set
+CONFIG_BLK_DEV_SD=y
+# CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_NETDEVICES=y
+CONFIG_BONDING=m
+CONFIG_MACVLAN=m
+CONFIG_MACVTAP=m
+CONFIG_TUN=m
+# CONFIG_NET_VENDOR_ARC is not set
+# CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_CIRRUS is not set
+CONFIG_DM9000=y
+CONFIG_DM9000_FORCE_SIMPLE_PHY_POLL=y
+# CONFIG_NET_VENDOR_FARADAY is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+CONFIG_PPP=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPPOE=m
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_SLIP=m
+CONFIG_SLIP_COMPRESSED=y
+# CONFIG_WLAN is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=800
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=600
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_SERIO is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_8250=y
+# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=40
+CONFIG_SERIAL_8250_RUNTIME_UARTS=40
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_PXA=y
+CONFIG_HW_RANDOM=y
+CONFIG_I2C=m
+# CONFIG_I2C_COMPAT is not set
+CONFIG_I2C_PXA=m
+CONFIG_I2C_PXA_SLAVE=y
+# CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_SA1100_WATCHDOG=m
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_FB=y
+CONFIG_FB_PXA=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_LOGO=y
+CONFIG_USB=m
+CONFIG_USB_OHCI_HCD=m
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+CONFIG_USB_STORAGE=m
+CONFIG_USB_SERIAL=m
+CONFIG_MMC=y
+CONFIG_MMC_PXA=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_PXA=m
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_EXT2_FS=m
+CONFIG_EXT3_FS=y
+CONFIG_EXT4_FS=y
+CONFIG_REISERFS_FS=m
+CONFIG_ISO9660_FS=m
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_NTFS_FS=m
+CONFIG_NTFS_RW=y
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V4=y
+CONFIG_ROOT_NFS=y
+CONFIG_CIFS=m
+CONFIG_CIFS_STATS=y
+CONFIG_CODA_FS=m
+CONFIG_NLS_DEFAULT="cp855"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_855=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_UTF8=y
+CONFIG_PRINTK_TIME=y
+CONFIG_DEBUG_INFO=y
diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig
index 96100db..f0c8f01 100644
--- a/arch/arm/mach-pxa/Kconfig
+++ b/arch/arm/mach-pxa/Kconfig
@@ -4,6 +4,20 @@ menu "Intel PXA2xx/PXA3xx Implementations"
 
 comment "Intel/Marvell Dev Platforms (sorted by hardware release time)"
 
+config MACH_PXA27X_DT
+	bool "Support PXA27x platforms from device tree"
+	select USE_OF
+	help
+	  Include support for Marvell PXA27x based platforms using
+	  the device tree.
+
+	  While MACH_PXA27X_DT when enabled should boot any PXA27x
+	  compatible machine, it still makes sense to select specific
+	  machines. Those options will select required features and
+	  provide per-machine errata workarounds.
+
+	  If unsure, say Y.
+
 config MACH_PXA3XX_DT
 	bool "Support PXA3xx platforms from device tree"
 	select CPU_PXA300
@@ -273,6 +287,23 @@ config MACH_VPAC270
 
 comment "End-user Products (sorted by vendor name)"
 
+config MACH_LP8X4X
+	bool "ICP DAS LP-8X4X (device tree)"
+	depends on MACH_PXA27X_DT
+	select IWMMXT
+	select PXA27x
+	help
+	  Say Y here if you intend to run this kernel on an ICP DAS
+	  LP-8x4x programmable automation controller.
+
+	  LP-8x4x is ARM-based and built around PXA270 SoC. The device
+	  has 128 MiB SDRAM, 48 or 96 MiB NOR flash, VGA port with
+	  800x600 resolution, MMC card slot, 2 Ethernet ports, 1 USB
+	  port, 5 serial ports (1 on them is wired internally to
+	  expansion slots). The device has a range of digital and
+	  analog expansion IO modules which can be installed in 1, 4 or
+	  8 slots depending on the model.
+
 config MACH_H4700
 	bool "HP iPAQ hx4700"
 	select HAVE_PWM
diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile
index 648867a..adaa72a 100644
--- a/arch/arm/mach-pxa/Makefile
+++ b/arch/arm/mach-pxa/Makefile
@@ -20,6 +20,7 @@ obj-$(CONFIG_CPU_PXA930)	+= pxa930.o
 # NOTE: keep the order of boards in accordance to their order in Kconfig
 
 # Device Tree support
+obj-$(CONFIG_MACH_PXA27X_DT)	+= pxa27x-dt.o
 obj-$(CONFIG_MACH_PXA3XX_DT)	+= pxa-dt.o
 
 # Intel/Marvell Dev Platforms
diff --git a/arch/arm/mach-pxa/pxa27x-dt.c b/arch/arm/mach-pxa/pxa27x-dt.c
new file mode 100644
index 0000000..95c6ef4
--- /dev/null
+++ b/arch/arm/mach-pxa/pxa27x-dt.c
@@ -0,0 +1,97 @@
+/*
+ *  linux/arch/arm/mach-pxa/pxa27x-dt.c
+ *
+ *  Copyright (C) 2013 Sergei Ianovich
+ *
+ *  based mostly on linux/arch/arm/mach-pxa/pxa-dt.c by Daniel Mack
+ *
+ *  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
+ *  publishhed by the Free Software Foundation.
+ */
+
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <asm/io.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <mach/irqs.h>
+#include <mach/pxa27x.h>
+
+#include "generic.h"
+
+#ifdef CONFIG_PXA27x
+extern void __init pxa27x_dt_init_irq(void);
+
+static const struct of_dev_auxdata pxa27x_auxdata_lookup[] __initconst = {
+	OF_DEV_AUXDATA("mrvl,pxa-uart",		0x40100000, "pxa2xx-uart.0", NULL),
+	OF_DEV_AUXDATA("mrvl,pxa-uart",		0x40200000, "pxa2xx-uart.1", NULL),
+	OF_DEV_AUXDATA("mrvl,pxa-uart",		0x40700000, "pxa2xx-uart.2", NULL),
+	OF_DEV_AUXDATA("mrvl,pxa-uart",		0x41600000, "pxa2xx-uart.3", NULL),
+	OF_DEV_AUXDATA("marvell,pxa-mmc",	0x41100000, "pxa2xx-mci.0", NULL),
+	OF_DEV_AUXDATA("intel,pxa27x-gpio",	0x40e00000, "pxa27x-gpio", NULL),
+	OF_DEV_AUXDATA("marvell,pxa-ohci",	0x4c000000, "pxa27x-ohci", NULL),
+	OF_DEV_AUXDATA("mrvl,pxa-i2c",		0x40301680, "pxa2xx-i2c.0", NULL),
+	{}
+};
+
+static void __init pxa27x_init_early(void)
+{
+	pxa27x_skip_init();
+}
+
+static void __init pxa27x_dt_init(void)
+{
+	of_platform_populate(NULL, of_default_bus_match_table,
+			     pxa27x_auxdata_lookup, NULL);
+}
+
+static const char *pxa27x_dt_board_compat[] __initdata = {
+	"marvell,pxa27x",
+	NULL,
+};
+
+#ifdef CONFIG_MACH_LP8X4X
+static const char *lp8x4x_dt_board_compat[] __initdata = {
+	"marvell,lp8x4x",
+	NULL,
+};
+
+static void lp8x4x_restart(enum reboot_mode mode, const char *cmd)
+{
+	/* Switch off fast-bus and turbo mode */
+	asm volatile("mcr       p14, 0, %0, c6, c0, 0" : :
+			"r"(2));
+	/* SDRAM hangs on watchdog reset on Marvell PXA270 (erratum 71) */
+	pxa_restart(REBOOT_SOFT, cmd);
+}
+#endif
+#endif
+
+#ifdef CONFIG_PXA27x
+DT_MACHINE_START(PXA27X_DT, "Marvell PXA27x (Device Tree Support)")
+	.map_io		= pxa27x_map_io,
+	.init_irq	= pxa27x_dt_init_irq,
+	.handle_irq	= pxa27x_handle_irq,
+	.init_time	= pxa_timer_init,
+	.restart	= pxa_restart,
+	.init_early	= pxa27x_init_early,
+	.init_machine	= pxa27x_dt_init,
+	.dt_compat	= pxa27x_dt_board_compat,
+MACHINE_END
+
+#ifdef CONFIG_MACH_LP8X4X
+DT_MACHINE_START(LP8X4X_DT, "ICP DAS LP-8X4X (Device Tree Support)")
+	.map_io		= pxa27x_map_io,
+	.init_irq	= pxa27x_dt_init_irq,
+	.handle_irq	= pxa27x_handle_irq,
+	.init_time	= pxa_timer_init,
+	.restart	= lp8x4x_restart,
+	.init_early	= pxa27x_init_early,
+	.init_machine	= pxa27x_dt_init,
+	.dt_compat	= lp8x4x_dt_board_compat,
+MACHINE_END
+#endif
+#endif
-- 
1.8.4.3

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

* [PATCH 9/9] ARM: pxa27x: device tree support ICP DAS LP-8x4x
@ 2013-12-08 22:53         ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-08 22:53 UTC (permalink / raw)
  To: linux-arm-kernel

ICP DAS calls LP-8x4x 'programmable automation controller'. It is
an industrial computer based on PXA270 SoC. They ship it with a 2.6.19
kernel and proprietary kernel module and userspace library to access
its industrial IO.

This patch allows to boot the device with a modern kernel with device
tree. It adds support for:
* MMC card interface on PXA270
* USB 1.1 port on PXA270
* 2 NOR flash devices
* 2 onboard ethernet Davicom DM9000 devices
* 3 serial UART ports on PXA270

Support for these devices will be added in separate patches, since
they are not currently supported by the kernel:
* DS1302 RTC
* 512kiB SRAM
* FPGA irq chip
* 3 built-in and up to 32 pluggable 8250 serial UART ports
* industrial IO parallel bus
* digital and analog industrial IO modules for parallel bus
* serial interface for digital and analog industrial IO modules on
  parallel bus

Not supported for now:
* VGA interface on PXA270 for lack of dts binding

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Daniel Mack <zonque@gmail.com>
CC: Arnd Bergmann <arnd@arndb.de>
CC: Olof Johansson <olof@lixom.net>
CC: Linus Walleij <linus.walleij@linaro.org>
---
 Changes v2..v3:
 * further clean up defconfig (minus 100 lines more) as suggested 
   by Arnd Bergmann

 * rewrite machine support code to use device tree

 changes v1..v2
 * clean up defconfig (reduces size by 10) as suggested 
   by Arnd Bergmann

 * the rest is now irrelevant

 arch/arm/boot/dts/Makefile          |   1 +
 arch/arm/boot/dts/pxa27x-lp8x4x.dts | 111 ++++++++++++++++++++++++
 arch/arm/configs/lp8x4x_defconfig   | 162 ++++++++++++++++++++++++++++++++++++
 arch/arm/mach-pxa/Kconfig           |  31 +++++++
 arch/arm/mach-pxa/Makefile          |   1 +
 arch/arm/mach-pxa/pxa27x-dt.c       |  97 +++++++++++++++++++++
 6 files changed, 403 insertions(+)
 create mode 100644 arch/arm/boot/dts/pxa27x-lp8x4x.dts
 create mode 100644 arch/arm/configs/lp8x4x_defconfig
 create mode 100644 arch/arm/mach-pxa/pxa27x-dt.c

diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index d57c1a6..c4752ff 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -206,6 +206,7 @@ dtb-$(CONFIG_ARCH_OMAP2PLUS) += omap2420-h4.dtb \
 	dra7-evm.dtb
 dtb-$(CONFIG_ARCH_ORION5X) += orion5x-lacie-ethernet-disk-mini-v2.dtb
 dtb-$(CONFIG_ARCH_PRIMA2) += prima2-evb.dtb
+dtb-$(CONFIG_MACH_PXA27X_DT) += pxa27x-lp8x4x.dtb
 dtb-$(CONFIG_ARCH_U8500) += ste-snowball.dtb \
 	ste-hrefprev60-stuib.dtb \
 	ste-hrefprev60-tvk.dtb \
diff --git a/arch/arm/boot/dts/pxa27x-lp8x4x.dts b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
new file mode 100644
index 0000000..b288c98
--- /dev/null
+++ b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
@@ -0,0 +1,111 @@
+/* Device tree for ICP DAS LP-8x4x */
+/dts-v1/;
+
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include "pxa27x.dtsi"
+
+/ {
+	model = "ICP DAS LP-8x4x programmable automation controller";
+	compatible = "marvell,lp8x4x", "marvell,pxa27x";
+
+	memory {
+		reg = <0xa0000000 0x08000000>;
+	};
+
+	regulators {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		vmmc: regulator at 0 {
+			compatible = "regulator-fixed";
+			reg = <0>;
+			regulator-name = "vmmc";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-always-on;
+		};
+	};
+
+	flash at 00000000 {
+		compatible = "cfi-flash";
+		reg = <0x0 0x02000000>;
+		bank-width = <4>;
+		device-width = <2>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		fs at 0 {
+			label = "u-boot";
+			reg = <0 0x40000>;
+		};
+		fs at 40000 {
+			label = "settings";
+			reg = <0x40000 0x40000>;
+		};
+		fs at 80000 {
+			label = "kernel";
+			reg = <0x80000 0x280000>;
+		};
+		fs at 300000 {
+			label = "root_fs";
+			reg = <0x300000 0x1d00000>;
+		};
+	};
+
+	flash at 04000000 {
+		compatible = "cfi-flash";
+		reg = <0x04000000 0x02000000>;
+		bank-width = <2>;
+		device-width = <1>;
+	};
+
+	pxabus {
+		pxairq: interrupt-controller at 40d00000 {
+			marvell,intc-priority;
+			marvell,intc-nr-irqs = <34>;
+		};
+
+		uart at 40100000 {
+			status = "okay";
+		};
+
+		uart at 40200000 {
+			status = "okay";
+		};
+
+		uart at 40700000 {
+			status = "okay";
+		};
+
+		mmc at 41100000 {
+			status = "okay";
+			vmmc-supply = <&vmmc>;
+			marvell,dma-channels = <21 22>;
+		};
+
+		ohci at 4c000000 {
+			status = "okay";
+			marvell,port-mode = <3>;
+			marvell,oc-mode-perport;
+			marvell,enable-port1;
+		};
+
+		eth0: eth at 0c000000 {
+			compatible = "davicom,dm9000";
+			reg = <0x0c000000 0x2
+			       0x0c004000 0x2>;
+			interrupt-parent = <&gpio>;
+			interrupts = <9 IRQ_TYPE_EDGE_RISING>;
+			status = "okay";
+		};
+
+		eth1: eth at 0d000000 {
+			compatible = "davicom,dm9000";
+			reg = <0x0d000000 0x2
+			       0x0d004000 0x2>;
+			interrupt-parent = <&gpio>;
+			interrupts = <82 IRQ_TYPE_EDGE_RISING>;
+			status = "okay";
+		};
+	};
+};
diff --git a/arch/arm/configs/lp8x4x_defconfig b/arch/arm/configs/lp8x4x_defconfig
new file mode 100644
index 0000000..faaa604
--- /dev/null
+++ b/arch/arm/configs/lp8x4x_defconfig
@@ -0,0 +1,162 @@
+# CONFIG_LOCALVERSION_AUTO is not set
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_RCU_BOOST=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_NS is not set
+# CONFIG_IPC_NS is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+# CONFIG_UID16 is not set
+# CONFIG_SHMEM is not set
+CONFIG_EMBEDDED=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_SLOB=y
+CONFIG_JUMP_LABEL=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+# CONFIG_LBDAF is not set
+CONFIG_BLK_CMDLINE_PARSER=y
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_ARCH_PXA=y
+CONFIG_MACH_PXA27X_DT=y
+CONFIG_MACH_LP8X4X=y
+# CONFIG_ARM_THUMB is not set
+CONFIG_PREEMPT=y
+CONFIG_AEABI=y
+# CONFIG_COMPACTION is not set
+# CONFIG_CROSS_MEMORY_ATTACH is not set
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="init=/sbin/init root=/dev/mmcblk0p1 rw rootfstype=ext4 console=ttyS0,115200 mem=128M rootwait"
+# CONFIG_SUSPEND is not set
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_BRIDGE=m
+CONFIG_BRIDGE_VLAN_FILTERING=y
+CONFIG_VLAN_8021Q=m
+CONFIG_VLAN_8021Q_GVRP=y
+CONFIG_VLAN_8021Q_MVRP=y
+# CONFIG_WIRELESS is not set
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+# CONFIG_FW_LOADER is not set
+CONFIG_MTD=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_CFI_GEOMETRY=y
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_PHYSMAP_OF=y
+CONFIG_PROC_DEVICETREE=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_LOOP_MIN_COUNT=2
+CONFIG_SCSI=y
+# CONFIG_SCSI_PROC_FS is not set
+CONFIG_BLK_DEV_SD=y
+# CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_NETDEVICES=y
+CONFIG_BONDING=m
+CONFIG_MACVLAN=m
+CONFIG_MACVTAP=m
+CONFIG_TUN=m
+# CONFIG_NET_VENDOR_ARC is not set
+# CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_CIRRUS is not set
+CONFIG_DM9000=y
+CONFIG_DM9000_FORCE_SIMPLE_PHY_POLL=y
+# CONFIG_NET_VENDOR_FARADAY is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+CONFIG_PPP=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPPOE=m
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_SLIP=m
+CONFIG_SLIP_COMPRESSED=y
+# CONFIG_WLAN is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=800
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=600
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_SERIO is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_8250=y
+# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=40
+CONFIG_SERIAL_8250_RUNTIME_UARTS=40
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_PXA=y
+CONFIG_HW_RANDOM=y
+CONFIG_I2C=m
+# CONFIG_I2C_COMPAT is not set
+CONFIG_I2C_PXA=m
+CONFIG_I2C_PXA_SLAVE=y
+# CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_SA1100_WATCHDOG=m
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_FB=y
+CONFIG_FB_PXA=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_LOGO=y
+CONFIG_USB=m
+CONFIG_USB_OHCI_HCD=m
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+CONFIG_USB_STORAGE=m
+CONFIG_USB_SERIAL=m
+CONFIG_MMC=y
+CONFIG_MMC_PXA=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_PXA=m
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_EXT2_FS=m
+CONFIG_EXT3_FS=y
+CONFIG_EXT4_FS=y
+CONFIG_REISERFS_FS=m
+CONFIG_ISO9660_FS=m
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_NTFS_FS=m
+CONFIG_NTFS_RW=y
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V4=y
+CONFIG_ROOT_NFS=y
+CONFIG_CIFS=m
+CONFIG_CIFS_STATS=y
+CONFIG_CODA_FS=m
+CONFIG_NLS_DEFAULT="cp855"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_855=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_UTF8=y
+CONFIG_PRINTK_TIME=y
+CONFIG_DEBUG_INFO=y
diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig
index 96100db..f0c8f01 100644
--- a/arch/arm/mach-pxa/Kconfig
+++ b/arch/arm/mach-pxa/Kconfig
@@ -4,6 +4,20 @@ menu "Intel PXA2xx/PXA3xx Implementations"
 
 comment "Intel/Marvell Dev Platforms (sorted by hardware release time)"
 
+config MACH_PXA27X_DT
+	bool "Support PXA27x platforms from device tree"
+	select USE_OF
+	help
+	  Include support for Marvell PXA27x based platforms using
+	  the device tree.
+
+	  While MACH_PXA27X_DT when enabled should boot any PXA27x
+	  compatible machine, it still makes sense to select specific
+	  machines. Those options will select required features and
+	  provide per-machine errata workarounds.
+
+	  If unsure, say Y.
+
 config MACH_PXA3XX_DT
 	bool "Support PXA3xx platforms from device tree"
 	select CPU_PXA300
@@ -273,6 +287,23 @@ config MACH_VPAC270
 
 comment "End-user Products (sorted by vendor name)"
 
+config MACH_LP8X4X
+	bool "ICP DAS LP-8X4X (device tree)"
+	depends on MACH_PXA27X_DT
+	select IWMMXT
+	select PXA27x
+	help
+	  Say Y here if you intend to run this kernel on an ICP DAS
+	  LP-8x4x programmable automation controller.
+
+	  LP-8x4x is ARM-based and built around PXA270 SoC. The device
+	  has 128 MiB SDRAM, 48 or 96 MiB NOR flash, VGA port with
+	  800x600 resolution, MMC card slot, 2 Ethernet ports, 1 USB
+	  port, 5 serial ports (1 on them is wired internally to
+	  expansion slots). The device has a range of digital and
+	  analog expansion IO modules which can be installed in 1, 4 or
+	  8 slots depending on the model.
+
 config MACH_H4700
 	bool "HP iPAQ hx4700"
 	select HAVE_PWM
diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile
index 648867a..adaa72a 100644
--- a/arch/arm/mach-pxa/Makefile
+++ b/arch/arm/mach-pxa/Makefile
@@ -20,6 +20,7 @@ obj-$(CONFIG_CPU_PXA930)	+= pxa930.o
 # NOTE: keep the order of boards in accordance to their order in Kconfig
 
 # Device Tree support
+obj-$(CONFIG_MACH_PXA27X_DT)	+= pxa27x-dt.o
 obj-$(CONFIG_MACH_PXA3XX_DT)	+= pxa-dt.o
 
 # Intel/Marvell Dev Platforms
diff --git a/arch/arm/mach-pxa/pxa27x-dt.c b/arch/arm/mach-pxa/pxa27x-dt.c
new file mode 100644
index 0000000..95c6ef4
--- /dev/null
+++ b/arch/arm/mach-pxa/pxa27x-dt.c
@@ -0,0 +1,97 @@
+/*
+ *  linux/arch/arm/mach-pxa/pxa27x-dt.c
+ *
+ *  Copyright (C) 2013 Sergei Ianovich
+ *
+ *  based mostly on linux/arch/arm/mach-pxa/pxa-dt.c by Daniel Mack
+ *
+ *  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
+ *  publishhed by the Free Software Foundation.
+ */
+
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <asm/io.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <mach/irqs.h>
+#include <mach/pxa27x.h>
+
+#include "generic.h"
+
+#ifdef CONFIG_PXA27x
+extern void __init pxa27x_dt_init_irq(void);
+
+static const struct of_dev_auxdata pxa27x_auxdata_lookup[] __initconst = {
+	OF_DEV_AUXDATA("mrvl,pxa-uart",		0x40100000, "pxa2xx-uart.0", NULL),
+	OF_DEV_AUXDATA("mrvl,pxa-uart",		0x40200000, "pxa2xx-uart.1", NULL),
+	OF_DEV_AUXDATA("mrvl,pxa-uart",		0x40700000, "pxa2xx-uart.2", NULL),
+	OF_DEV_AUXDATA("mrvl,pxa-uart",		0x41600000, "pxa2xx-uart.3", NULL),
+	OF_DEV_AUXDATA("marvell,pxa-mmc",	0x41100000, "pxa2xx-mci.0", NULL),
+	OF_DEV_AUXDATA("intel,pxa27x-gpio",	0x40e00000, "pxa27x-gpio", NULL),
+	OF_DEV_AUXDATA("marvell,pxa-ohci",	0x4c000000, "pxa27x-ohci", NULL),
+	OF_DEV_AUXDATA("mrvl,pxa-i2c",		0x40301680, "pxa2xx-i2c.0", NULL),
+	{}
+};
+
+static void __init pxa27x_init_early(void)
+{
+	pxa27x_skip_init();
+}
+
+static void __init pxa27x_dt_init(void)
+{
+	of_platform_populate(NULL, of_default_bus_match_table,
+			     pxa27x_auxdata_lookup, NULL);
+}
+
+static const char *pxa27x_dt_board_compat[] __initdata = {
+	"marvell,pxa27x",
+	NULL,
+};
+
+#ifdef CONFIG_MACH_LP8X4X
+static const char *lp8x4x_dt_board_compat[] __initdata = {
+	"marvell,lp8x4x",
+	NULL,
+};
+
+static void lp8x4x_restart(enum reboot_mode mode, const char *cmd)
+{
+	/* Switch off fast-bus and turbo mode */
+	asm volatile("mcr       p14, 0, %0, c6, c0, 0" : :
+			"r"(2));
+	/* SDRAM hangs on watchdog reset on Marvell PXA270 (erratum 71) */
+	pxa_restart(REBOOT_SOFT, cmd);
+}
+#endif
+#endif
+
+#ifdef CONFIG_PXA27x
+DT_MACHINE_START(PXA27X_DT, "Marvell PXA27x (Device Tree Support)")
+	.map_io		= pxa27x_map_io,
+	.init_irq	= pxa27x_dt_init_irq,
+	.handle_irq	= pxa27x_handle_irq,
+	.init_time	= pxa_timer_init,
+	.restart	= pxa_restart,
+	.init_early	= pxa27x_init_early,
+	.init_machine	= pxa27x_dt_init,
+	.dt_compat	= pxa27x_dt_board_compat,
+MACHINE_END
+
+#ifdef CONFIG_MACH_LP8X4X
+DT_MACHINE_START(LP8X4X_DT, "ICP DAS LP-8X4X (Device Tree Support)")
+	.map_io		= pxa27x_map_io,
+	.init_irq	= pxa27x_dt_init_irq,
+	.handle_irq	= pxa27x_handle_irq,
+	.init_time	= pxa_timer_init,
+	.restart	= lp8x4x_restart,
+	.init_early	= pxa27x_init_early,
+	.init_machine	= pxa27x_dt_init,
+	.dt_compat	= lp8x4x_dt_board_compat,
+MACHINE_END
+#endif
+#endif
-- 
1.8.4.3

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

* Re: [PATCH v2 02/11] arm: pxa27x: support ICP DAS LP-8x4x
  2013-12-08  7:05         ` Sergei Ianovich
@ 2013-12-09  0:54           ` Arnd Bergmann
  -1 siblings, 0 replies; 700+ messages in thread
From: Arnd Bergmann @ 2013-12-09  0:54 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: linux-arm-kernel, linux-kernel, Eric Miao, Russell King, Haojian Zhuang

On Sunday 08 December 2013, Sergei Ianovich wrote:
> On Sun, 2013-12-08 at 03:21 +0100, Arnd Bergmann wrote:
> > On Friday 06 December 2013, Sergei Ianovich wrote:
> > You have some rather unusual options in here. I'd suggest you go through
> > the reduced defconfig file and remove all options that look like they
> > are unnecessary for your system.
> > 
> > It's probably based on some distro config that enables lots of modules
> > you don't actually want.
> 
> I tried to future-proof the config, by enabling all partition tables and
> USB disks and modems that could be plugged into the device.
> 
> I'll remove those. However, I would like to retain config options
> related to low latency and small kernel size. Keeping them will
> hopefully allow being notified about changes affecting the system.
> 
> Will this fly?

Yes, of course, keep as many as you need. I was just trying to ensure
that you had put some thought in it, and e.g. the various USB serial
modules and some other things appeared to be fairly random, but I can
see them making sense now.

> > #define LP8X4X_EOI              0x0006
> > #define LP8X4X_INSINT           0x0008
> > ...
> > 
> > and change the users to do e.g.
> > 
> >         readl(LP8X4X_FPGA_VIRT + LP8X4X_INSINT);
> 
> I am trying to boot the system with device tree. If I manage, I'll move
> this code into drivers/irqchip/ as a platform device. Otherwise, I'll
> make this change.

Ok, cool. If you need help with the DT conversion, just ask here or on
IRC (#armlinux or #mvlinux on freenode.net, there might also be a
PXA specific channel I don't know).

	Arnd

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

* [PATCH v2 02/11] arm: pxa27x: support ICP DAS LP-8x4x
@ 2013-12-09  0:54           ` Arnd Bergmann
  0 siblings, 0 replies; 700+ messages in thread
From: Arnd Bergmann @ 2013-12-09  0:54 UTC (permalink / raw)
  To: linux-arm-kernel

On Sunday 08 December 2013, Sergei Ianovich wrote:
> On Sun, 2013-12-08 at 03:21 +0100, Arnd Bergmann wrote:
> > On Friday 06 December 2013, Sergei Ianovich wrote:
> > You have some rather unusual options in here. I'd suggest you go through
> > the reduced defconfig file and remove all options that look like they
> > are unnecessary for your system.
> > 
> > It's probably based on some distro config that enables lots of modules
> > you don't actually want.
> 
> I tried to future-proof the config, by enabling all partition tables and
> USB disks and modems that could be plugged into the device.
> 
> I'll remove those. However, I would like to retain config options
> related to low latency and small kernel size. Keeping them will
> hopefully allow being notified about changes affecting the system.
> 
> Will this fly?

Yes, of course, keep as many as you need. I was just trying to ensure
that you had put some thought in it, and e.g. the various USB serial
modules and some other things appeared to be fairly random, but I can
see them making sense now.

> > #define LP8X4X_EOI              0x0006
> > #define LP8X4X_INSINT           0x0008
> > ...
> > 
> > and change the users to do e.g.
> > 
> >         readl(LP8X4X_FPGA_VIRT + LP8X4X_INSINT);
> 
> I am trying to boot the system with device tree. If I manage, I'll move
> this code into drivers/irqchip/ as a platform device. Otherwise, I'll
> make this change.

Ok, cool. If you need help with the DT conversion, just ask here or on
IRC (#armlinux or #mvlinux on freenode.net, there might also be a
PXA specific channel I don't know).

	Arnd

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

* Re: [PATCH 6/9] ARM: dts: pxa3xx: move declaration to header
  2013-12-08 22:53         ` Sergei Ianovich
@ 2013-12-09  1:13           ` Arnd Bergmann
  -1 siblings, 0 replies; 700+ messages in thread
From: Arnd Bergmann @ 2013-12-09  1:13 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: linux-kernel, linux-arm-kernel, Daniel Mack, Eric Miao,
	Russell King, Haojian Zhuang

On Sunday 08 December 2013, Sergei Ianovich wrote:
> +#ifdef CONFIG_OF
> +extern void __init pxa_dt_irq_init(int (*fn)(struct irq_data *, unsigned int));
> +#endif /* CONFIG_OF */
> +

In general, don't put declarations like this into #ifdef, unless you need
an #else clause like

static inline void pxa_dt_irq_init(int (*fn)(struct irq_data *, unsigned int) {}

Same in patch 8.

	Arnd

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

* [PATCH 6/9] ARM: dts: pxa3xx: move declaration to header
@ 2013-12-09  1:13           ` Arnd Bergmann
  0 siblings, 0 replies; 700+ messages in thread
From: Arnd Bergmann @ 2013-12-09  1:13 UTC (permalink / raw)
  To: linux-arm-kernel

On Sunday 08 December 2013, Sergei Ianovich wrote:
> +#ifdef CONFIG_OF
> +extern void __init pxa_dt_irq_init(int (*fn)(struct irq_data *, unsigned int));
> +#endif /* CONFIG_OF */
> +

In general, don't put declarations like this into #ifdef, unless you need
an #else clause like

static inline void pxa_dt_irq_init(int (*fn)(struct irq_data *, unsigned int) {}

Same in patch 8.

	Arnd

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

* Re: [PATCH 5/9] ARM: dts: provide DMA config to pxamci
  2013-12-08 22:53         ` Sergei Ianovich
@ 2013-12-09  1:33           ` Arnd Bergmann
  -1 siblings, 0 replies; 700+ messages in thread
From: Arnd Bergmann @ 2013-12-09  1:33 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: linux-kernel, linux-arm-kernel, Daniel Mack, Rob Herring,
	Pawel Moll, Mark Rutland, Stephen Warren, Ian Campbell,
	Rob Landley, Russell King, Chris Ball, Ulf Hansson,
	Jaehoon Chung, Seungwon Jeon, open list:OPEN FIRMWARE AND...,
	open list:DOCUMENTATION

On Sunday 08 December 2013, Sergei Ianovich wrote:
> Non-dts implementation supply required DMA channel numbers as
> IORESOURCE_DMA. However, there is was no way to get them from
> device tree.

I just wrote a lengthy reply to this email to explain in what ways
you got it wrong, but then I saw that Daniel has already done all
the work in the right way in August, so nevermind that.

It hasn't made it upstream yet, but see http://list-archives.org/2013/08/07/linux-mtd-lists-infradead-org/patch-00-20-arm-pxa-move-core-and-drivers-to-dmaengine/f/3444199144
for how it's done. Maybe Daniel can comment on the status of his
patches.

	Arnd

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

* [PATCH 5/9] ARM: dts: provide DMA config to pxamci
@ 2013-12-09  1:33           ` Arnd Bergmann
  0 siblings, 0 replies; 700+ messages in thread
From: Arnd Bergmann @ 2013-12-09  1:33 UTC (permalink / raw)
  To: linux-arm-kernel

On Sunday 08 December 2013, Sergei Ianovich wrote:
> Non-dts implementation supply required DMA channel numbers as
> IORESOURCE_DMA. However, there is was no way to get them from
> device tree.

I just wrote a lengthy reply to this email to explain in what ways
you got it wrong, but then I saw that Daniel has already done all
the work in the right way in August, so nevermind that.

It hasn't made it upstream yet, but see http://list-archives.org/2013/08/07/linux-mtd-lists-infradead-org/patch-00-20-arm-pxa-move-core-and-drivers-to-dmaengine/f/3444199144
for how it's done. Maybe Daniel can comment on the status of his
patches.

	Arnd

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

* Re: [PATCH 9/9] ARM: pxa27x: device tree support ICP DAS LP-8x4x
  2013-12-08 22:53         ` Sergei Ianovich
@ 2013-12-09  1:47           ` Arnd Bergmann
  -1 siblings, 0 replies; 700+ messages in thread
From: Arnd Bergmann @ 2013-12-09  1:47 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: linux-kernel, linux-arm-kernel, Daniel Mack, Olof Johansson,
	Linus Walleij, Rob Herring, Pawel Moll, Mark Rutland,
	Stephen Warren, Ian Campbell, Russell King, Eric Miao,
	Haojian Zhuang, open list:OPEN FIRMWARE AND...

On Sunday 08 December 2013, Sergei Ianovich wrote:
> +
> +#ifdef CONFIG_PXA27x
> +extern void __init pxa27x_dt_init_irq(void);

This is not the right place to put an 'extern' declaration, it should go into
a header file if it's really needed. Ideally you would not need it at all
and just add an IRQCHIP_DECLARE() line into the driver to automatically
probe it.

> +static const struct of_dev_auxdata pxa27x_auxdata_lookup[] __initconst = {
> +	OF_DEV_AUXDATA("mrvl,pxa-uart",		0x40100000, "pxa2xx-uart.0", NULL),
> +	OF_DEV_AUXDATA("mrvl,pxa-uart",		0x40200000, "pxa2xx-uart.1", NULL),
> +	OF_DEV_AUXDATA("mrvl,pxa-uart",		0x40700000, "pxa2xx-uart.2", NULL),
> +	OF_DEV_AUXDATA("mrvl,pxa-uart",		0x41600000, "pxa2xx-uart.3", NULL),
> +	OF_DEV_AUXDATA("marvell,pxa-mmc",	0x41100000, "pxa2xx-mci.0", NULL),
> +	OF_DEV_AUXDATA("intel,pxa27x-gpio",	0x40e00000, "pxa27x-gpio", NULL),
> +	OF_DEV_AUXDATA("marvell,pxa-ohci",	0x4c000000, "pxa27x-ohci", NULL),
> +	OF_DEV_AUXDATA("mrvl,pxa-i2c",		0x40301680, "pxa2xx-i2c.0", NULL),
> +	{}
> +};

I guess these are needed only for clock management purposes at the moment?

> +static void __init pxa27x_init_early(void)
> +{
> +	pxa27x_skip_init();
> +}

I would prefer not to have an init_early function at all, and instead
check "if (of_have_populated_dt())" in pxa27x_init, or to split
that function into two.

> +static const char *pxa27x_dt_board_compat[] __initdata = {
> +	"marvell,pxa27x",
> +	NULL,
> +};
> +
> +#ifdef CONFIG_MACH_LP8X4X
> +static const char *lp8x4x_dt_board_compat[] __initdata = {
> +	"marvell,lp8x4x",
> +	NULL,
> +};

Note that you should not have wildcards in any "compatible" strings.
Just list all the combinations here (pxa270, pxa271, pxa272, and whatever
you need for lp8x4x).

> +static void lp8x4x_restart(enum reboot_mode mode, const char *cmd)
> +{
> +	/* Switch off fast-bus and turbo mode */
> +	asm volatile("mcr       p14, 0, %0, c6, c0, 0" : :
> +			"r"(2));
> +	/* SDRAM hangs on watchdog reset on Marvell PXA270 (erratum 71) */
> +	pxa_restart(REBOOT_SOFT, cmd);
> +}
> +#endif
> +#endif

Since the only difference here is the restart logic, I would prefer here to
have only a single DT_MACHINE_START() and do

static void pxa27x_restart(enum reboot_mode mode, const char *cmd)
{
	/* Switch off fast-bus and turbo mode */
	if (of_machine_is_compatible("marvell,lp8x4x"))
		asm volatile("mcr       p14, 0, %0, c6, c0, 0" : : "r"(2));

	/* SDRAM hangs on watchdog reset on Marvell PXA270 (erratum 71) */
	if (of_machine_is_compatible("marvell,pxa270"))
		pxa_restart(REBOOT_SOFT, cmd);
}

	Arnd

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

* [PATCH 9/9] ARM: pxa27x: device tree support ICP DAS LP-8x4x
@ 2013-12-09  1:47           ` Arnd Bergmann
  0 siblings, 0 replies; 700+ messages in thread
From: Arnd Bergmann @ 2013-12-09  1:47 UTC (permalink / raw)
  To: linux-arm-kernel

On Sunday 08 December 2013, Sergei Ianovich wrote:
> +
> +#ifdef CONFIG_PXA27x
> +extern void __init pxa27x_dt_init_irq(void);

This is not the right place to put an 'extern' declaration, it should go into
a header file if it's really needed. Ideally you would not need it at all
and just add an IRQCHIP_DECLARE() line into the driver to automatically
probe it.

> +static const struct of_dev_auxdata pxa27x_auxdata_lookup[] __initconst = {
> +	OF_DEV_AUXDATA("mrvl,pxa-uart",		0x40100000, "pxa2xx-uart.0", NULL),
> +	OF_DEV_AUXDATA("mrvl,pxa-uart",		0x40200000, "pxa2xx-uart.1", NULL),
> +	OF_DEV_AUXDATA("mrvl,pxa-uart",		0x40700000, "pxa2xx-uart.2", NULL),
> +	OF_DEV_AUXDATA("mrvl,pxa-uart",		0x41600000, "pxa2xx-uart.3", NULL),
> +	OF_DEV_AUXDATA("marvell,pxa-mmc",	0x41100000, "pxa2xx-mci.0", NULL),
> +	OF_DEV_AUXDATA("intel,pxa27x-gpio",	0x40e00000, "pxa27x-gpio", NULL),
> +	OF_DEV_AUXDATA("marvell,pxa-ohci",	0x4c000000, "pxa27x-ohci", NULL),
> +	OF_DEV_AUXDATA("mrvl,pxa-i2c",		0x40301680, "pxa2xx-i2c.0", NULL),
> +	{}
> +};

I guess these are needed only for clock management purposes at the moment?

> +static void __init pxa27x_init_early(void)
> +{
> +	pxa27x_skip_init();
> +}

I would prefer not to have an init_early function at all, and instead
check "if (of_have_populated_dt())" in pxa27x_init, or to split
that function into two.

> +static const char *pxa27x_dt_board_compat[] __initdata = {
> +	"marvell,pxa27x",
> +	NULL,
> +};
> +
> +#ifdef CONFIG_MACH_LP8X4X
> +static const char *lp8x4x_dt_board_compat[] __initdata = {
> +	"marvell,lp8x4x",
> +	NULL,
> +};

Note that you should not have wildcards in any "compatible" strings.
Just list all the combinations here (pxa270, pxa271, pxa272, and whatever
you need for lp8x4x).

> +static void lp8x4x_restart(enum reboot_mode mode, const char *cmd)
> +{
> +	/* Switch off fast-bus and turbo mode */
> +	asm volatile("mcr       p14, 0, %0, c6, c0, 0" : :
> +			"r"(2));
> +	/* SDRAM hangs on watchdog reset on Marvell PXA270 (erratum 71) */
> +	pxa_restart(REBOOT_SOFT, cmd);
> +}
> +#endif
> +#endif

Since the only difference here is the restart logic, I would prefer here to
have only a single DT_MACHINE_START() and do

static void pxa27x_restart(enum reboot_mode mode, const char *cmd)
{
	/* Switch off fast-bus and turbo mode */
	if (of_machine_is_compatible("marvell,lp8x4x"))
		asm volatile("mcr       p14, 0, %0, c6, c0, 0" : : "r"(2));

	/* SDRAM hangs on watchdog reset on Marvell PXA270 (erratum 71) */
	if (of_machine_is_compatible("marvell,pxa270"))
		pxa_restart(REBOOT_SOFT, cmd);
}

	Arnd

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

* Re: [PATCH 0/9] ARM: support for ICP DAS LP-8x4x (with dts)
  2013-12-08 22:53       ` Sergei Ianovich
@ 2013-12-09  1:51         ` Arnd Bergmann
  -1 siblings, 0 replies; 700+ messages in thread
From: Arnd Bergmann @ 2013-12-09  1:51 UTC (permalink / raw)
  To: Sergei Ianovich; +Cc: linux-kernel, linux-arm-kernel, Daniel Mack

On Sunday 08 December 2013, Sergei Ianovich wrote:
> 
> Except for defconfig, this is a completely new series. The first
> eight patches fix outstanding issues with device tree support
> in PXA. The 9th boots ICP DAS LP-8x4x.

Awesome! That was very quick. The main comment I have is for the
dmaengine support, you will need to rebase on Daniel's patches for
that. I also found few minor details.

	Arnd

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

* [PATCH 0/9] ARM: support for ICP DAS LP-8x4x (with dts)
@ 2013-12-09  1:51         ` Arnd Bergmann
  0 siblings, 0 replies; 700+ messages in thread
From: Arnd Bergmann @ 2013-12-09  1:51 UTC (permalink / raw)
  To: linux-arm-kernel

On Sunday 08 December 2013, Sergei Ianovich wrote:
> 
> Except for defconfig, this is a completely new series. The first
> eight patches fix outstanding issues with device tree support
> in PXA. The 9th boots ICP DAS LP-8x4x.

Awesome! That was very quick. The main comment I have is for the
dmaengine support, you will need to rebase on Daniel's patches for
that. I also found few minor details.

	Arnd

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

* Re: [PATCH v2] serial: rewrite pxa2xx-uart to use 8250_core
  2013-12-06  9:09                       ` Sergei Ianovich
@ 2013-12-09  8:38                         ` Heikki Krogerus
  -1 siblings, 0 replies; 700+ messages in thread
From: Heikki Krogerus @ 2013-12-09  8:38 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: linux-kernel, Greg Kroah-Hartman, James Cameron, Russell King,
	Jiri Slaby, Grant Likely, Rob Herring, Zhou Zhu, Andrew Morton,
	Haojian Zhuang, Stefan Seyfried, John Crispin, Paul Bolle,
	moderated list:ARM PORT, open list:SERIAL DRIVERS,
	open list:OPEN FIRMWARE AND...

Hi,

On Fri, Dec 06, 2013 at 01:09:31PM +0400, Sergei Ianovich wrote:
> pxa2xx-uart was a separate uart platform driver. It was declaring
> the same device names and numbers as 8250 driver. As a result,
> it was impossible to use 8250 driver on PXA SoCs.
> 
> Upon closer examination pxa2xx-uart turned out to be a clone of
> 8250_core driver.
> 
> Workaround for Erratum #19 according to Marvel(R) PXA270M Processor
> Specification Update (April 19, 2010) is dropped. 8250_core reads
> from FIFO immediately after checking DR bit in LSR.
> 
> Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
> CC: Heikki Krogerus <heikki.krogerus@linux.intel.com>
> CC: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> CC: James Cameron <quozl@laptop.org>
> ---
>  changes v1..v2
>  * actually implement workaround for E74 in dl_write as spooted
>    by James Cameron
>  * added comment about E19 in commit message

Nice job Sergei! I have a few minor nitpicks below, but if they are
the only comments, don't bother with v3. I'm fine with this. For what
it's worth:

Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>

>  arch/arm/configs/am200epdkit_defconfig    |   3 +-
>  arch/arm/configs/cm_x2xx_defconfig        |   3 +-
>  arch/arm/configs/cm_x300_defconfig        |   3 +-
>  arch/arm/configs/colibri_pxa270_defconfig |   3 +-
>  arch/arm/configs/colibri_pxa300_defconfig |   3 +-
>  arch/arm/configs/corgi_defconfig          |   4 +-
>  arch/arm/configs/em_x270_defconfig        |   3 +-
>  arch/arm/configs/ezx_defconfig            |   3 +-
>  arch/arm/configs/h5000_defconfig          |   3 +-
>  arch/arm/configs/imote2_defconfig         |   3 +-
>  arch/arm/configs/lpd270_defconfig         |   3 +-
>  arch/arm/configs/lubbock_defconfig        |   3 +-
>  arch/arm/configs/mainstone_defconfig      |   3 +-
>  arch/arm/configs/mmp2_defconfig           |   3 +-
>  arch/arm/configs/pcm027_defconfig         |   3 +-
>  arch/arm/configs/pxa168_defconfig         |   3 +-
>  arch/arm/configs/pxa255-idp_defconfig     |   3 +-
>  arch/arm/configs/pxa3xx_defconfig         |   3 +-
>  arch/arm/configs/pxa910_defconfig         |   3 +-
>  arch/arm/configs/raumfeld_defconfig       |   3 +-
>  arch/arm/configs/spitz_defconfig          |   4 +-
>  arch/arm/configs/trizeps4_defconfig       |   3 +-
>  arch/arm/configs/viper_defconfig          |   4 +-
>  arch/arm/configs/xcep_defconfig           |   3 +-
>  drivers/tty/serial/8250/8250_pxa.c        | 189 ++++++
>  drivers/tty/serial/8250/Kconfig           |   9 +
>  drivers/tty/serial/8250/Makefile          |   1 +
>  drivers/tty/serial/Kconfig                |  23 -
>  drivers/tty/serial/Makefile               |   1 -
>  drivers/tty/serial/pxa.c                  | 971 ------------------------------
>  30 files changed, 247 insertions(+), 1022 deletions(-)
>  create mode 100644 drivers/tty/serial/8250/8250_pxa.c
>  delete mode 100644 drivers/tty/serial/pxa.c

<snip>

> diff --git a/drivers/tty/serial/8250/8250_pxa.c b/drivers/tty/serial/8250/8250_pxa.c
> new file mode 100644
> index 0000000..88ae73c
> --- /dev/null
> +++ b/drivers/tty/serial/8250/8250_pxa.c
> @@ -0,0 +1,189 @@
> +/*
> + *  drivers/tty/serial/8250/8250_pxa.c -- driver for PXA on-board UARTS
> + *  Copyright:	(C) 2013 Sergei Ianovich <ynvich@gmail.com>
> + *
> + *  replaces drivers/serial/pxa.c by Nicolas Pitre
> + *  Created:	Feb 20, 2003
> + *  Copyright:	(C) 2003 Monta Vista Software, Inc.
> + *
> + *  Based on drivers/serial/8250.c by Russell King.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + */
> +
> +#include <linux/device.h>
> +#include <linux/init.h>
> +#include <linux/io.h>
> +#include <linux/module.h>
> +#include <linux/serial_8250.h>
> +#include <linux/serial_core.h>
> +#include <linux/serial_reg.h>
> +#include <linux/of.h>
> +#include <linux/of_irq.h>
> +#include <linux/of_platform.h>
> +#include <linux/platform_device.h>
> +#include <linux/slab.h>
> +#include <linux/clk.h>
> +#include <linux/pm_runtime.h>
> +
> +#include "8250.h"
> +
> +struct pxa8250_data {
> +	int			line;
> +	struct clk		*clk;
> +};
> +
> +#ifdef CONFIG_PM
> +static int serial_pxa_suspend(struct device *dev)
> +{
> +	struct pxa8250_data *data = dev_get_drvdata(dev);
> +
> +	serial8250_suspend_port(data->line);
> +
> +	return 0;
> +}
> +
> +static int serial_pxa_resume(struct device *dev)
> +{
> +	struct pxa8250_data *data = dev_get_drvdata(dev);
> +
> +	serial8250_resume_port(data->line);
> +
> +	return 0;
> +}
> +
> +static const struct dev_pm_ops serial_pxa_pm_ops = {
> +	.suspend	= serial_pxa_suspend,
> +	.resume		= serial_pxa_resume,
> +};

If you leave this structure outside the ifdef CONFIG_PM and use
SET_SYSTEM_SLEEP_PM_OPS() macro, you don't need the ifdef when you set
the driver pm ops below.

> +#endif
> +
> +static struct of_device_id serial_pxa_dt_ids[] = {
> +	{ .compatible = "mrvl,pxa-uart", },
> +	{ .compatible = "mrvl,mmp-uart", },
> +	{}
> +};
> +MODULE_DEVICE_TABLE(of, serial_pxa_dt_ids);
> +
> +/* Uart divisor latch write */
> +static void serial_pxa_dl_write(struct uart_8250_port *up, int value)
> +{
> +	unsigned int dll;
> +
> +	serial_out(up, UART_DLL, value & 0xff);
> +	/*
> +	 * work around Erratum #74 according to Marvel(R) PXA270M Processor
> +	 * Specification Update (April 19, 2010)
> +	 */
> +	dll = serial_in(up, UART_DLL);
> +	WARN_ON(dll != (value & 0xff));
> +
> +	serial_out(up, UART_DLM, value >> 8 & 0xff);
> +}
> +
> +
> +static void serial_pxa_pm(struct uart_port *port, unsigned int state,
> +	      unsigned int oldstate)
> +{
> +	struct pxa8250_data *data = port->private_data;
> +
> +	if (!state)
> +		clk_prepare_enable(data->clk);
> +	else
> +		clk_disable_unprepare(data->clk);
> +}
> +
> +static int serial_pxa_probe(struct platform_device *pdev)
> +{
> +	struct uart_8250_port uart = {};
> +	struct pxa8250_data *data;
> +	struct resource *mmres, *irqres;
> +	int ret;
> +
> +	mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	irqres = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
> +	if (!mmres || !irqres)
> +		return -ENODEV;
> +
> +	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
> +	if (!data)
> +		return -ENOMEM;
> +
> +	data->clk = devm_clk_get(&pdev->dev, NULL);
> +	if (IS_ERR(data->clk)) {
> +		ret = PTR_ERR(data->clk);
> +		goto err_free;

You can just return here.

> +	}
> +
> +	ret = clk_prepare(data->clk);
> +	if (ret)
> +		goto err_free_clk;

ditto

> +	uart.port.type = PORT_XSCALE;
> +	uart.port.iotype = UPIO_MEM32;
> +	uart.port.mapbase = mmres->start;
> +	uart.port.regshift = 2;
> +	uart.port.irq = irqres->start;
> +	uart.port.fifosize = 64;
> +	uart.port.flags = UPF_IOREMAP | UPF_SKIP_TEST;
> +	uart.port.dev = &pdev->dev;
> +	uart.port.uartclk = clk_get_rate(data->clk);
> +	uart.port.pm = serial_pxa_pm;
> +	uart.port.private_data = data;
> +	uart.dl_write = serial_pxa_dl_write;
> +
> +	ret = serial8250_register_8250_port(&uart);
> +	if (ret < 0)
> +		goto err_clk;
> +
> +	data->line = ret;
> +
> +	platform_set_drvdata(pdev, data);
> +
> +	return 0;
> +
> + err_clk:
> +	clk_unprepare(data->clk);
> + err_free_clk:
> +	devm_clk_put(&pdev->dev, data->clk);
> + err_free:
> +	devm_kfree(&pdev->dev, data);

And there labels could be dropped.

> +	return ret;
> +}
> +
> +static int serial_pxa_remove(struct platform_device *pdev)
> +{
> +	struct pxa8250_data *data = platform_get_drvdata(pdev);
> +
> +	serial8250_unregister_port(data->line);
> +
> +	clk_unprepare(data->clk);
> +	devm_clk_put(&pdev->dev, data->clk);
> +	devm_kfree(&pdev->dev, data);

You also don't need to call these resource freeing functions here.

> +	return 0;
> +}
> +
> +static struct platform_driver serial_pxa_driver = {
> +	.probe          = serial_pxa_probe,
> +	.remove         = serial_pxa_remove,
> +
> +	.driver		= {
> +		.name	= "pxa2xx-uart",
> +		.owner	= THIS_MODULE,
> +#ifdef CONFIG_PM
> +		.pm	= &serial_pxa_pm_ops,
> +#endif
> +		.of_match_table = serial_pxa_dt_ids,
> +	},
> +};
> +
> +module_platform_driver(serial_pxa_driver);
> +
> +MODULE_AUTHOR("Sergei Ianovich");
> +MODULE_LICENSE("GPL");
> +MODULE_ALIAS("platform:pxa2xx-uart");


Thanks,

-- 
heikki

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

* [PATCH v2] serial: rewrite pxa2xx-uart to use 8250_core
@ 2013-12-09  8:38                         ` Heikki Krogerus
  0 siblings, 0 replies; 700+ messages in thread
From: Heikki Krogerus @ 2013-12-09  8:38 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

On Fri, Dec 06, 2013 at 01:09:31PM +0400, Sergei Ianovich wrote:
> pxa2xx-uart was a separate uart platform driver. It was declaring
> the same device names and numbers as 8250 driver. As a result,
> it was impossible to use 8250 driver on PXA SoCs.
> 
> Upon closer examination pxa2xx-uart turned out to be a clone of
> 8250_core driver.
> 
> Workaround for Erratum #19 according to Marvel(R) PXA270M Processor
> Specification Update (April 19, 2010) is dropped. 8250_core reads
> from FIFO immediately after checking DR bit in LSR.
> 
> Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
> CC: Heikki Krogerus <heikki.krogerus@linux.intel.com>
> CC: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> CC: James Cameron <quozl@laptop.org>
> ---
>  changes v1..v2
>  * actually implement workaround for E74 in dl_write as spooted
>    by James Cameron
>  * added comment about E19 in commit message

Nice job Sergei! I have a few minor nitpicks below, but if they are
the only comments, don't bother with v3. I'm fine with this. For what
it's worth:

Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>

>  arch/arm/configs/am200epdkit_defconfig    |   3 +-
>  arch/arm/configs/cm_x2xx_defconfig        |   3 +-
>  arch/arm/configs/cm_x300_defconfig        |   3 +-
>  arch/arm/configs/colibri_pxa270_defconfig |   3 +-
>  arch/arm/configs/colibri_pxa300_defconfig |   3 +-
>  arch/arm/configs/corgi_defconfig          |   4 +-
>  arch/arm/configs/em_x270_defconfig        |   3 +-
>  arch/arm/configs/ezx_defconfig            |   3 +-
>  arch/arm/configs/h5000_defconfig          |   3 +-
>  arch/arm/configs/imote2_defconfig         |   3 +-
>  arch/arm/configs/lpd270_defconfig         |   3 +-
>  arch/arm/configs/lubbock_defconfig        |   3 +-
>  arch/arm/configs/mainstone_defconfig      |   3 +-
>  arch/arm/configs/mmp2_defconfig           |   3 +-
>  arch/arm/configs/pcm027_defconfig         |   3 +-
>  arch/arm/configs/pxa168_defconfig         |   3 +-
>  arch/arm/configs/pxa255-idp_defconfig     |   3 +-
>  arch/arm/configs/pxa3xx_defconfig         |   3 +-
>  arch/arm/configs/pxa910_defconfig         |   3 +-
>  arch/arm/configs/raumfeld_defconfig       |   3 +-
>  arch/arm/configs/spitz_defconfig          |   4 +-
>  arch/arm/configs/trizeps4_defconfig       |   3 +-
>  arch/arm/configs/viper_defconfig          |   4 +-
>  arch/arm/configs/xcep_defconfig           |   3 +-
>  drivers/tty/serial/8250/8250_pxa.c        | 189 ++++++
>  drivers/tty/serial/8250/Kconfig           |   9 +
>  drivers/tty/serial/8250/Makefile          |   1 +
>  drivers/tty/serial/Kconfig                |  23 -
>  drivers/tty/serial/Makefile               |   1 -
>  drivers/tty/serial/pxa.c                  | 971 ------------------------------
>  30 files changed, 247 insertions(+), 1022 deletions(-)
>  create mode 100644 drivers/tty/serial/8250/8250_pxa.c
>  delete mode 100644 drivers/tty/serial/pxa.c

<snip>

> diff --git a/drivers/tty/serial/8250/8250_pxa.c b/drivers/tty/serial/8250/8250_pxa.c
> new file mode 100644
> index 0000000..88ae73c
> --- /dev/null
> +++ b/drivers/tty/serial/8250/8250_pxa.c
> @@ -0,0 +1,189 @@
> +/*
> + *  drivers/tty/serial/8250/8250_pxa.c -- driver for PXA on-board UARTS
> + *  Copyright:	(C) 2013 Sergei Ianovich <ynvich@gmail.com>
> + *
> + *  replaces drivers/serial/pxa.c by Nicolas Pitre
> + *  Created:	Feb 20, 2003
> + *  Copyright:	(C) 2003 Monta Vista Software, Inc.
> + *
> + *  Based on drivers/serial/8250.c by Russell King.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + */
> +
> +#include <linux/device.h>
> +#include <linux/init.h>
> +#include <linux/io.h>
> +#include <linux/module.h>
> +#include <linux/serial_8250.h>
> +#include <linux/serial_core.h>
> +#include <linux/serial_reg.h>
> +#include <linux/of.h>
> +#include <linux/of_irq.h>
> +#include <linux/of_platform.h>
> +#include <linux/platform_device.h>
> +#include <linux/slab.h>
> +#include <linux/clk.h>
> +#include <linux/pm_runtime.h>
> +
> +#include "8250.h"
> +
> +struct pxa8250_data {
> +	int			line;
> +	struct clk		*clk;
> +};
> +
> +#ifdef CONFIG_PM
> +static int serial_pxa_suspend(struct device *dev)
> +{
> +	struct pxa8250_data *data = dev_get_drvdata(dev);
> +
> +	serial8250_suspend_port(data->line);
> +
> +	return 0;
> +}
> +
> +static int serial_pxa_resume(struct device *dev)
> +{
> +	struct pxa8250_data *data = dev_get_drvdata(dev);
> +
> +	serial8250_resume_port(data->line);
> +
> +	return 0;
> +}
> +
> +static const struct dev_pm_ops serial_pxa_pm_ops = {
> +	.suspend	= serial_pxa_suspend,
> +	.resume		= serial_pxa_resume,
> +};

If you leave this structure outside the ifdef CONFIG_PM and use
SET_SYSTEM_SLEEP_PM_OPS() macro, you don't need the ifdef when you set
the driver pm ops below.

> +#endif
> +
> +static struct of_device_id serial_pxa_dt_ids[] = {
> +	{ .compatible = "mrvl,pxa-uart", },
> +	{ .compatible = "mrvl,mmp-uart", },
> +	{}
> +};
> +MODULE_DEVICE_TABLE(of, serial_pxa_dt_ids);
> +
> +/* Uart divisor latch write */
> +static void serial_pxa_dl_write(struct uart_8250_port *up, int value)
> +{
> +	unsigned int dll;
> +
> +	serial_out(up, UART_DLL, value & 0xff);
> +	/*
> +	 * work around Erratum #74 according to Marvel(R) PXA270M Processor
> +	 * Specification Update (April 19, 2010)
> +	 */
> +	dll = serial_in(up, UART_DLL);
> +	WARN_ON(dll != (value & 0xff));
> +
> +	serial_out(up, UART_DLM, value >> 8 & 0xff);
> +}
> +
> +
> +static void serial_pxa_pm(struct uart_port *port, unsigned int state,
> +	      unsigned int oldstate)
> +{
> +	struct pxa8250_data *data = port->private_data;
> +
> +	if (!state)
> +		clk_prepare_enable(data->clk);
> +	else
> +		clk_disable_unprepare(data->clk);
> +}
> +
> +static int serial_pxa_probe(struct platform_device *pdev)
> +{
> +	struct uart_8250_port uart = {};
> +	struct pxa8250_data *data;
> +	struct resource *mmres, *irqres;
> +	int ret;
> +
> +	mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	irqres = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
> +	if (!mmres || !irqres)
> +		return -ENODEV;
> +
> +	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
> +	if (!data)
> +		return -ENOMEM;
> +
> +	data->clk = devm_clk_get(&pdev->dev, NULL);
> +	if (IS_ERR(data->clk)) {
> +		ret = PTR_ERR(data->clk);
> +		goto err_free;

You can just return here.

> +	}
> +
> +	ret = clk_prepare(data->clk);
> +	if (ret)
> +		goto err_free_clk;

ditto

> +	uart.port.type = PORT_XSCALE;
> +	uart.port.iotype = UPIO_MEM32;
> +	uart.port.mapbase = mmres->start;
> +	uart.port.regshift = 2;
> +	uart.port.irq = irqres->start;
> +	uart.port.fifosize = 64;
> +	uart.port.flags = UPF_IOREMAP | UPF_SKIP_TEST;
> +	uart.port.dev = &pdev->dev;
> +	uart.port.uartclk = clk_get_rate(data->clk);
> +	uart.port.pm = serial_pxa_pm;
> +	uart.port.private_data = data;
> +	uart.dl_write = serial_pxa_dl_write;
> +
> +	ret = serial8250_register_8250_port(&uart);
> +	if (ret < 0)
> +		goto err_clk;
> +
> +	data->line = ret;
> +
> +	platform_set_drvdata(pdev, data);
> +
> +	return 0;
> +
> + err_clk:
> +	clk_unprepare(data->clk);
> + err_free_clk:
> +	devm_clk_put(&pdev->dev, data->clk);
> + err_free:
> +	devm_kfree(&pdev->dev, data);

And there labels could be dropped.

> +	return ret;
> +}
> +
> +static int serial_pxa_remove(struct platform_device *pdev)
> +{
> +	struct pxa8250_data *data = platform_get_drvdata(pdev);
> +
> +	serial8250_unregister_port(data->line);
> +
> +	clk_unprepare(data->clk);
> +	devm_clk_put(&pdev->dev, data->clk);
> +	devm_kfree(&pdev->dev, data);

You also don't need to call these resource freeing functions here.

> +	return 0;
> +}
> +
> +static struct platform_driver serial_pxa_driver = {
> +	.probe          = serial_pxa_probe,
> +	.remove         = serial_pxa_remove,
> +
> +	.driver		= {
> +		.name	= "pxa2xx-uart",
> +		.owner	= THIS_MODULE,
> +#ifdef CONFIG_PM
> +		.pm	= &serial_pxa_pm_ops,
> +#endif
> +		.of_match_table = serial_pxa_dt_ids,
> +	},
> +};
> +
> +module_platform_driver(serial_pxa_driver);
> +
> +MODULE_AUTHOR("Sergei Ianovich");
> +MODULE_LICENSE("GPL");
> +MODULE_ALIAS("platform:pxa2xx-uart");


Thanks,

-- 
heikki

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

* Re: [PATCH v2] serial: rewrite pxa2xx-uart to use 8250_core
  2013-12-09  8:38                         ` Heikki Krogerus
@ 2013-12-09  8:44                           ` Sascha Hauer
  -1 siblings, 0 replies; 700+ messages in thread
From: Sascha Hauer @ 2013-12-09  8:44 UTC (permalink / raw)
  To: Heikki Krogerus
  Cc: Sergei Ianovich, linux-kernel, Greg Kroah-Hartman, James Cameron,
	Russell King, Jiri Slaby, Grant Likely, Rob Herring, Zhou Zhu,
	Andrew Morton, Haojian Zhuang, Stefan Seyfried, John Crispin,
	Paul Bolle, moderated list:ARM PORT, open list:SERIAL DRIVERS,
	open list:OPEN FIRMWARE AND...

On Mon, Dec 09, 2013 at 10:38:15AM +0200, Heikki Krogerus wrote:
> Hi,
> 
> > +	return 0;
> > +
> > + err_clk:
> > +	clk_unprepare(data->clk);
> > + err_free_clk:
> > +	devm_clk_put(&pdev->dev, data->clk);
> > + err_free:
> > +	devm_kfree(&pdev->dev, data);
> 
> And there labels could be dropped.

This should really be fixed. Explicitly releasing devm_* allocated
resources invalidates the whole idea of the devm functions. People
looking for templates shouldn't find examples for this in the kernel.

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

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

* [PATCH v2] serial: rewrite pxa2xx-uart to use 8250_core
@ 2013-12-09  8:44                           ` Sascha Hauer
  0 siblings, 0 replies; 700+ messages in thread
From: Sascha Hauer @ 2013-12-09  8:44 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Dec 09, 2013 at 10:38:15AM +0200, Heikki Krogerus wrote:
> Hi,
> 
> > +	return 0;
> > +
> > + err_clk:
> > +	clk_unprepare(data->clk);
> > + err_free_clk:
> > +	devm_clk_put(&pdev->dev, data->clk);
> > + err_free:
> > +	devm_kfree(&pdev->dev, data);
> 
> And there labels could be dropped.

This should really be fixed. Explicitly releasing devm_* allocated
resources invalidates the whole idea of the devm functions. People
looking for templates shouldn't find examples for this in the kernel.

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

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

* Re: [PATCH 4/9] ARM: pxa: remove unused variable
  2013-12-08 22:53         ` Sergei Ianovich
@ 2013-12-09  8:56           ` Daniel Mack
  -1 siblings, 0 replies; 700+ messages in thread
From: Daniel Mack @ 2013-12-09  8:56 UTC (permalink / raw)
  To: Sergei Ianovich, linux-kernel, linux-arm-kernel
  Cc: Eric Miao, Russell King, Haojian Zhuang

On 12/08/2013 11:53 PM, Sergei Ianovich wrote:
> Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
> CC: Daniel Mack <zonque@gmail.com>
> ---
>  arch/arm/mach-pxa/irq.c | 2 --
>  1 file changed, 2 deletions(-)
> 
> diff --git a/arch/arm/mach-pxa/irq.c b/arch/arm/mach-pxa/irq.c
> index b6cc181..432842c 100644
> --- a/arch/arm/mach-pxa/irq.c
> +++ b/arch/arm/mach-pxa/irq.c
> @@ -236,7 +236,6 @@ void __init pxa_dt_irq_init(int (*fn)(struct irq_data *, unsigned int))
>  {
>  	struct device_node *node;
>  	const struct of_device_id *of_id;
> -	struct pxa_intc_conf *conf;
>  	struct resource res;
>  	int n, ret;
>  
> @@ -246,7 +245,6 @@ void __init pxa_dt_irq_init(int (*fn)(struct irq_data *, unsigned int))
>  		return;
>  	}
>  	of_id = of_match_node(intc_ids, node);
> -	conf = of_id->data;

A similar patch was already merged by Haojian recently. You should
probably rebase your patch stack on top of his maintainer tree.


Daniel


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

* [PATCH 4/9] ARM: pxa: remove unused variable
@ 2013-12-09  8:56           ` Daniel Mack
  0 siblings, 0 replies; 700+ messages in thread
From: Daniel Mack @ 2013-12-09  8:56 UTC (permalink / raw)
  To: linux-arm-kernel

On 12/08/2013 11:53 PM, Sergei Ianovich wrote:
> Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
> CC: Daniel Mack <zonque@gmail.com>
> ---
>  arch/arm/mach-pxa/irq.c | 2 --
>  1 file changed, 2 deletions(-)
> 
> diff --git a/arch/arm/mach-pxa/irq.c b/arch/arm/mach-pxa/irq.c
> index b6cc181..432842c 100644
> --- a/arch/arm/mach-pxa/irq.c
> +++ b/arch/arm/mach-pxa/irq.c
> @@ -236,7 +236,6 @@ void __init pxa_dt_irq_init(int (*fn)(struct irq_data *, unsigned int))
>  {
>  	struct device_node *node;
>  	const struct of_device_id *of_id;
> -	struct pxa_intc_conf *conf;
>  	struct resource res;
>  	int n, ret;
>  
> @@ -246,7 +245,6 @@ void __init pxa_dt_irq_init(int (*fn)(struct irq_data *, unsigned int))
>  		return;
>  	}
>  	of_id = of_match_node(intc_ids, node);
> -	conf = of_id->data;

A similar patch was already merged by Haojian recently. You should
probably rebase your patch stack on top of his maintainer tree.


Daniel

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

* Re: [PATCH 5/9] ARM: dts: provide DMA config to pxamci
  2013-12-09  1:33           ` Arnd Bergmann
@ 2013-12-09  9:04             ` Daniel Mack
  -1 siblings, 0 replies; 700+ messages in thread
From: Daniel Mack @ 2013-12-09  9:04 UTC (permalink / raw)
  To: Arnd Bergmann, Sergei Ianovich
  Cc: Mark Rutland, open list:OPEN FIRMWARE AND...,
	Ulf Hansson, Russell King, Pawel Moll, Stephen Warren,
	Seungwon Jeon, Ian Campbell, DOCUMENTATION, linux-kernel,
	Rob Herring, Jaehoon Chung, Rob Landley, Chris Ball,
	Robert Jarzmik, linux-arm-kernel

On 12/09/2013 02:33 AM, Arnd Bergmann wrote:
> On Sunday 08 December 2013, Sergei Ianovich wrote:
>> Non-dts implementation supply required DMA channel numbers as
>> IORESOURCE_DMA. However, there is was no way to get them from
>> device tree.
> 
> I just wrote a lengthy reply to this email to explain in what ways
> you got it wrong, but then I saw that Daniel has already done all
> the work in the right way in August, so nevermind that.
> 
> It hasn't made it upstream yet, but see http://list-archives.org/2013/08/07/linux-mtd-lists-infradead-org/patch-00-20-arm-pxa-move-core-and-drivers-to-dmaengine/f/3444199144
> for how it's done. Maybe Daniel can comment on the status of his
> patches.

I recently rebased all my patches on top of 3.13-rc3, and will resend in
couple of days.

The real problem here is that by reworking the DMA related PXA bits, all
drivers have to be changed at once, and a gradual transition seems
impossible. For that, I was asking for help in areas where I don't have
any hardware to test my patches on, but unfortunately, nobody got back
to me yet.

In particular, the pxa camera driver is something Robert (cc) wanted to
have a look at. Robert, any updates on this?


Anyway, I'll have to clean up some details and will resend my patches
very soon.


Thanks,
Daniel

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

* [PATCH 5/9] ARM: dts: provide DMA config to pxamci
@ 2013-12-09  9:04             ` Daniel Mack
  0 siblings, 0 replies; 700+ messages in thread
From: Daniel Mack @ 2013-12-09  9:04 UTC (permalink / raw)
  To: linux-arm-kernel

On 12/09/2013 02:33 AM, Arnd Bergmann wrote:
> On Sunday 08 December 2013, Sergei Ianovich wrote:
>> Non-dts implementation supply required DMA channel numbers as
>> IORESOURCE_DMA. However, there is was no way to get them from
>> device tree.
> 
> I just wrote a lengthy reply to this email to explain in what ways
> you got it wrong, but then I saw that Daniel has already done all
> the work in the right way in August, so nevermind that.
> 
> It hasn't made it upstream yet, but see http://list-archives.org/2013/08/07/linux-mtd-lists-infradead-org/patch-00-20-arm-pxa-move-core-and-drivers-to-dmaengine/f/3444199144
> for how it's done. Maybe Daniel can comment on the status of his
> patches.

I recently rebased all my patches on top of 3.13-rc3, and will resend in
couple of days.

The real problem here is that by reworking the DMA related PXA bits, all
drivers have to be changed at once, and a gradual transition seems
impossible. For that, I was asking for help in areas where I don't have
any hardware to test my patches on, but unfortunately, nobody got back
to me yet.

In particular, the pxa camera driver is something Robert (cc) wanted to
have a look at. Robert, any updates on this?


Anyway, I'll have to clean up some details and will resend my patches
very soon.


Thanks,
Daniel

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

* Re: [PATCH 5/9] ARM: dts: provide DMA config to pxamci
  2013-12-09  9:04             ` Daniel Mack
@ 2013-12-09  9:34               ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-09  9:34 UTC (permalink / raw)
  To: Daniel Mack
  Cc: Arnd Bergmann, linux-kernel, linux-arm-kernel, Rob Herring,
	Pawel Moll, Mark Rutland, Stephen Warren, Ian Campbell,
	Rob Landley, Russell King, Chris Ball, Ulf Hansson,
	Jaehoon Chung, Seungwon Jeon, open list:OPEN FIRMWARE AND...,
	DOCUMENTATION, Robert Jarzmik

On Mon, 2013-12-09 at 10:04 +0100, Daniel Mack wrote:
> On 12/09/2013 02:33 AM, Arnd Bergmann wrote:
> > On Sunday 08 December 2013, Sergei Ianovich wrote:
> >> Non-dts implementation supply required DMA channel numbers as
> >> IORESOURCE_DMA. However, there is was no way to get them from
> >> device tree.
> > 
> > I just wrote a lengthy reply to this email to explain in what ways
> > you got it wrong, but then I saw that Daniel has already done all
> > the work in the right way in August, so nevermind that.
> > 
> > It hasn't made it upstream yet, but see http://list-archives.org/2013/08/07/linux-mtd-lists-infradead-org/patch-00-20-arm-pxa-move-core-and-drivers-to-dmaengine/f/3444199144
> > for how it's done. Maybe Daniel can comment on the status of his
> > patches.
> 
> I recently rebased all my patches on top of 3.13-rc3, and will resend in
> couple of days.
> 
> The real problem here is that by reworking the DMA related PXA bits, all
> drivers have to be changed at once, and a gradual transition seems
> impossible. For that, I was asking for help in areas where I don't have
> any hardware to test my patches on, but unfortunately, nobody got back
> to me yet.

Nice to have Daniel in this conversation. Your patch series is a big and
important work. However, I am not sure I will ever land as is exactly
for this reason.

DMA is a per-physical-device concept, not per-platform. Only the DMA
controller is per-platform. This means we need to rewrite all platform
drivers at once. This is roughly equivalent to adding a new platform
support in one patch, which is not going to work.

In patch 08/20 in the series above, you change 10% lines of the pxa mmc
driver. If we don't count boilerplate lines, this will amount to over
50%. In other word, the output is a new driver.

My proposal in to actually add new drivers for each platform device with
DMA and mark new ones EXPERIMENTAL. When they receive adequate testing
we remove the tag and mark the old one OBSOLETE. When we have a new
driver for every device presently supported, we will drop the whole old
series.

This should be very close to a gradual transition.

While we are in transition, I propose that we allow 'hackish' support
for device tree in the existing drivers. Platform devices are declared
in dtsi files, so when we move to a new driver we just change the
compatible string there. Actual devices with their one dts file won't
need any change. They will need a dtb recompile, though. This way we can
begin a migration to device tree in pxa immediately.

The patch series does just that.


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

* [PATCH 5/9] ARM: dts: provide DMA config to pxamci
@ 2013-12-09  9:34               ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-09  9:34 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, 2013-12-09 at 10:04 +0100, Daniel Mack wrote:
> On 12/09/2013 02:33 AM, Arnd Bergmann wrote:
> > On Sunday 08 December 2013, Sergei Ianovich wrote:
> >> Non-dts implementation supply required DMA channel numbers as
> >> IORESOURCE_DMA. However, there is was no way to get them from
> >> device tree.
> > 
> > I just wrote a lengthy reply to this email to explain in what ways
> > you got it wrong, but then I saw that Daniel has already done all
> > the work in the right way in August, so nevermind that.
> > 
> > It hasn't made it upstream yet, but see http://list-archives.org/2013/08/07/linux-mtd-lists-infradead-org/patch-00-20-arm-pxa-move-core-and-drivers-to-dmaengine/f/3444199144
> > for how it's done. Maybe Daniel can comment on the status of his
> > patches.
> 
> I recently rebased all my patches on top of 3.13-rc3, and will resend in
> couple of days.
> 
> The real problem here is that by reworking the DMA related PXA bits, all
> drivers have to be changed at once, and a gradual transition seems
> impossible. For that, I was asking for help in areas where I don't have
> any hardware to test my patches on, but unfortunately, nobody got back
> to me yet.

Nice to have Daniel in this conversation. Your patch series is a big and
important work. However, I am not sure I will ever land as is exactly
for this reason.

DMA is a per-physical-device concept, not per-platform. Only the DMA
controller is per-platform. This means we need to rewrite all platform
drivers at once. This is roughly equivalent to adding a new platform
support in one patch, which is not going to work.

In patch 08/20 in the series above, you change 10% lines of the pxa mmc
driver. If we don't count boilerplate lines, this will amount to over
50%. In other word, the output is a new driver.

My proposal in to actually add new drivers for each platform device with
DMA and mark new ones EXPERIMENTAL. When they receive adequate testing
we remove the tag and mark the old one OBSOLETE. When we have a new
driver for every device presently supported, we will drop the whole old
series.

This should be very close to a gradual transition.

While we are in transition, I propose that we allow 'hackish' support
for device tree in the existing drivers. Platform devices are declared
in dtsi files, so when we move to a new driver we just change the
compatible string there. Actual devices with their one dts file won't
need any change. They will need a dtb recompile, though. This way we can
begin a migration to device tree in pxa immediately.

The patch series does just that.

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

* Re: [PATCH 4/9] ARM: pxa: remove unused variable
  2013-12-09  8:56           ` Daniel Mack
@ 2013-12-09  9:42             ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-09  9:42 UTC (permalink / raw)
  To: Daniel Mack
  Cc: linux-kernel, linux-arm-kernel, Eric Miao, Russell King, Haojian Zhuang

On Mon, 2013-12-09 at 09:56 +0100, Daniel Mack wrote:
> A similar patch was already merged by Haojian recently. You should
> probably rebase your patch stack on top of his maintainer tree.

I've just come across the patch you mention in the arm mailing list.

Could you please provide a link to Haojian's official public repository?

If possible, a link link to your repository will also be very helpful.

My tree is at https://github.com/yanovich/linux


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

* [PATCH 4/9] ARM: pxa: remove unused variable
@ 2013-12-09  9:42             ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-09  9:42 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, 2013-12-09 at 09:56 +0100, Daniel Mack wrote:
> A similar patch was already merged by Haojian recently. You should
> probably rebase your patch stack on top of his maintainer tree.

I've just come across the patch you mention in the arm mailing list.

Could you please provide a link to Haojian's official public repository?

If possible, a link link to your repository will also be very helpful.

My tree is at https://github.com/yanovich/linux

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

* Re: [PATCH 4/9] ARM: pxa: remove unused variable
  2013-12-09  9:42             ` Sergei Ianovich
@ 2013-12-09  9:49               ` Daniel Mack
  -1 siblings, 0 replies; 700+ messages in thread
From: Daniel Mack @ 2013-12-09  9:49 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: linux-kernel, linux-arm-kernel, Eric Miao, Russell King, Haojian Zhuang

On 12/09/2013 10:42 AM, Sergei Ianovich wrote:
> On Mon, 2013-12-09 at 09:56 +0100, Daniel Mack wrote:
>> A similar patch was already merged by Haojian recently. You should
>> probably rebase your patch stack on top of his maintainer tree.
> 
> I've just come across the patch you mention in the arm mailing list.
> 
> Could you please provide a link to Haojian's official public repository?

According to MAINTAINERS, it's here:

  git://github.com/hzhuang1/linux.git

But it seems it hasn't seen an update recently. Haojian?

> If possible, a link link to your repository will also be very helpful.

  https://github.com/zonque/linux/tree/pxa-dma-v2


Daniel


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

* [PATCH 4/9] ARM: pxa: remove unused variable
@ 2013-12-09  9:49               ` Daniel Mack
  0 siblings, 0 replies; 700+ messages in thread
From: Daniel Mack @ 2013-12-09  9:49 UTC (permalink / raw)
  To: linux-arm-kernel

On 12/09/2013 10:42 AM, Sergei Ianovich wrote:
> On Mon, 2013-12-09 at 09:56 +0100, Daniel Mack wrote:
>> A similar patch was already merged by Haojian recently. You should
>> probably rebase your patch stack on top of his maintainer tree.
> 
> I've just come across the patch you mention in the arm mailing list.
> 
> Could you please provide a link to Haojian's official public repository?

According to MAINTAINERS, it's here:

  git://github.com/hzhuang1/linux.git

But it seems it hasn't seen an update recently. Haojian?

> If possible, a link link to your repository will also be very helpful.

  https://github.com/zonque/linux/tree/pxa-dma-v2


Daniel

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

* Re: [PATCH 5/9] ARM: dts: provide DMA config to pxamci
  2013-12-09  9:34               ` Sergei Ianovich
@ 2013-12-09  9:53                 ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-09  9:53 UTC (permalink / raw)
  To: Daniel Mack
  Cc: Arnd Bergmann, linux-kernel, linux-arm-kernel, Rob Herring,
	Pawel Moll, Mark Rutland, Stephen Warren, Ian Campbell,
	Rob Landley, Russell King, Chris Ball, Ulf Hansson,
	Jaehoon Chung, Seungwon Jeon, open list:OPEN FIRMWARE AND...,
	DOCUMENTATION, Robert Jarzmik

On Mon, 2013-12-09 at 13:34 +0400, Sergei Ianovich wrote:
> On Mon, 2013-12-09 at 10:04 +0100, Daniel Mack wrote:
> > On 12/09/2013 02:33 AM, Arnd Bergmann wrote:
> > > On Sunday 08 December 2013, Sergei Ianovich wrote:
> > >> Non-dts implementation supply required DMA channel numbers as
> > >> IORESOURCE_DMA. However, there is was no way to get them from
> > >> device tree.
> > > 
> > > I just wrote a lengthy reply to this email to explain in what ways
> > > you got it wrong, but then I saw that Daniel has already done all
> > > the work in the right way in August, so nevermind that.
> > > 
> > > It hasn't made it upstream yet, but see http://list-archives.org/2013/08/07/linux-mtd-lists-infradead-org/patch-00-20-arm-pxa-move-core-and-drivers-to-dmaengine/f/3444199144
> > > for how it's done. Maybe Daniel can comment on the status of his
> > > patches.
> > 
> > I recently rebased all my patches on top of 3.13-rc3, and will resend in
> > couple of days.
> > 
> > The real problem here is that by reworking the DMA related PXA bits, all
> > drivers have to be changed at once, and a gradual transition seems
> > impossible. For that, I was asking for help in areas where I don't have
> > any hardware to test my patches on, but unfortunately, nobody got back
> > to me yet.
> 
> Nice to have Daniel in this conversation. Your patch series is a big and
> important work. However, I am not sure I will ever land as is exactly
> for this reason.

s/I will/it will/

> DMA is a per-physical-device concept, not per-platform. Only the DMA
> controller is per-platform. This means we need to rewrite all platform
> drivers at once. This is roughly equivalent to adding a new platform
> support in one patch, which is not going to work.
> 
> In patch 08/20 in the series above, you change 10% lines of the pxa mmc
> driver. If we don't count boilerplate lines, this will amount to over
> 50%. In other word, the output is a new driver.

s/other word/other words/

> My proposal in to actually add new drivers for each platform device with
> DMA and mark new ones EXPERIMENTAL. When they receive adequate testing
> we remove the tag and mark the old one OBSOLETE. When we have a new
> driver for every device presently supported, we will drop the whole old
> series.

s/proposal in/proposal is/

> This should be very close to a gradual transition.
> 
> While we are in transition, I propose that we allow 'hackish' support
> for device tree in the existing drivers. Platform devices are declared
> in dtsi files, so when we move to a new driver we just change the
> compatible string there. Actual devices with their one dts file won't
> need any change. They will need a dtb recompile, though. This way we can
> begin a migration to device tree in pxa immediately.

s/their one/their own/

> The patch series does just that.

Sorry for noise.


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

* [PATCH 5/9] ARM: dts: provide DMA config to pxamci
@ 2013-12-09  9:53                 ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-09  9:53 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, 2013-12-09 at 13:34 +0400, Sergei Ianovich wrote:
> On Mon, 2013-12-09 at 10:04 +0100, Daniel Mack wrote:
> > On 12/09/2013 02:33 AM, Arnd Bergmann wrote:
> > > On Sunday 08 December 2013, Sergei Ianovich wrote:
> > >> Non-dts implementation supply required DMA channel numbers as
> > >> IORESOURCE_DMA. However, there is was no way to get them from
> > >> device tree.
> > > 
> > > I just wrote a lengthy reply to this email to explain in what ways
> > > you got it wrong, but then I saw that Daniel has already done all
> > > the work in the right way in August, so nevermind that.
> > > 
> > > It hasn't made it upstream yet, but see http://list-archives.org/2013/08/07/linux-mtd-lists-infradead-org/patch-00-20-arm-pxa-move-core-and-drivers-to-dmaengine/f/3444199144
> > > for how it's done. Maybe Daniel can comment on the status of his
> > > patches.
> > 
> > I recently rebased all my patches on top of 3.13-rc3, and will resend in
> > couple of days.
> > 
> > The real problem here is that by reworking the DMA related PXA bits, all
> > drivers have to be changed at once, and a gradual transition seems
> > impossible. For that, I was asking for help in areas where I don't have
> > any hardware to test my patches on, but unfortunately, nobody got back
> > to me yet.
> 
> Nice to have Daniel in this conversation. Your patch series is a big and
> important work. However, I am not sure I will ever land as is exactly
> for this reason.

s/I will/it will/

> DMA is a per-physical-device concept, not per-platform. Only the DMA
> controller is per-platform. This means we need to rewrite all platform
> drivers at once. This is roughly equivalent to adding a new platform
> support in one patch, which is not going to work.
> 
> In patch 08/20 in the series above, you change 10% lines of the pxa mmc
> driver. If we don't count boilerplate lines, this will amount to over
> 50%. In other word, the output is a new driver.

s/other word/other words/

> My proposal in to actually add new drivers for each platform device with
> DMA and mark new ones EXPERIMENTAL. When they receive adequate testing
> we remove the tag and mark the old one OBSOLETE. When we have a new
> driver for every device presently supported, we will drop the whole old
> series.

s/proposal in/proposal is/

> This should be very close to a gradual transition.
> 
> While we are in transition, I propose that we allow 'hackish' support
> for device tree in the existing drivers. Platform devices are declared
> in dtsi files, so when we move to a new driver we just change the
> compatible string there. Actual devices with their one dts file won't
> need any change. They will need a dtb recompile, though. This way we can
> begin a migration to device tree in pxa immediately.

s/their one/their own/

> The patch series does just that.

Sorry for noise.

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

* Re: [PATCH 5/9] ARM: dts: provide DMA config to pxamci
  2013-12-09  9:34               ` Sergei Ianovich
@ 2013-12-09 10:21                 ` Daniel Mack
  -1 siblings, 0 replies; 700+ messages in thread
From: Daniel Mack @ 2013-12-09 10:21 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: Arnd Bergmann, linux-kernel, linux-arm-kernel, Rob Herring,
	Pawel Moll, Mark Rutland, Stephen Warren, Ian Campbell,
	Rob Landley, Russell King, Chris Ball, Ulf Hansson,
	Jaehoon Chung, Seungwon Jeon, open list:OPEN FIRMWARE AND...,
	DOCUMENTATION, Robert Jarzmik

On 12/09/2013 10:34 AM, Sergei Ianovich wrote:
> On Mon, 2013-12-09 at 10:04 +0100, Daniel Mack wrote:
>> On 12/09/2013 02:33 AM, Arnd Bergmann wrote:
>>> On Sunday 08 December 2013, Sergei Ianovich wrote:
>>>> Non-dts implementation supply required DMA channel numbers as
>>>> IORESOURCE_DMA. However, there is was no way to get them from
>>>> device tree.
>>>
>>> I just wrote a lengthy reply to this email to explain in what ways
>>> you got it wrong, but then I saw that Daniel has already done all
>>> the work in the right way in August, so nevermind that.
>>>
>>> It hasn't made it upstream yet, but see http://list-archives.org/2013/08/07/linux-mtd-lists-infradead-org/patch-00-20-arm-pxa-move-core-and-drivers-to-dmaengine/f/3444199144
>>> for how it's done. Maybe Daniel can comment on the status of his
>>> patches.
>>
>> I recently rebased all my patches on top of 3.13-rc3, and will resend in
>> couple of days.
>>
>> The real problem here is that by reworking the DMA related PXA bits, all
>> drivers have to be changed at once, and a gradual transition seems
>> impossible. For that, I was asking for help in areas where I don't have
>> any hardware to test my patches on, but unfortunately, nobody got back
>> to me yet.
> 
> Nice to have Daniel in this conversation. Your patch series is a big and
> important work. However, I am not sure I will ever land as is exactly
> for this reason.

Well, I wouldn't be so certain about that statement. As I wrote in the
cover letter, most of the work is actually done, and I successfully
tested the new DMA support with a some of the drivers I ported. Others
were ported blindly, and in case of no reaction, I'd dare to merge them
and wait for people to report back in case of trouble.

The only real problem is the PXA camera driver, which does tricky things
like hot re-queuing of DMA descriptors. That one needs fixing before the
series can land.

> My proposal in to actually add new drivers for each platform device with
> DMA and mark new ones EXPERIMENTAL.

That would cause tree-wide cross-dependencies between drivers, because
the two DMA controllers can't be used at the same time, and the PXA
specific API will be unavailable when the mmp-dma driver is selected. My
patch series (and the DMA controller framework for that matter) aims for
the opposite - the unification of APIs and drivers.

> When they receive adequate testing
> we remove the tag and mark the old one OBSOLETE. When we have a new
> driver for every device presently supported, we will drop the whole old
> series.

Well, given the feedback I got for the series so far, I fear we'll be
off to maintain two drivers for each peripheral for a very long time.

I'd rather propose cracking the last nut that's left, and then get the
thing merged.

Arnd, Haojian? Any opinion here?



Daniel

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

* [PATCH 5/9] ARM: dts: provide DMA config to pxamci
@ 2013-12-09 10:21                 ` Daniel Mack
  0 siblings, 0 replies; 700+ messages in thread
From: Daniel Mack @ 2013-12-09 10:21 UTC (permalink / raw)
  To: linux-arm-kernel

On 12/09/2013 10:34 AM, Sergei Ianovich wrote:
> On Mon, 2013-12-09 at 10:04 +0100, Daniel Mack wrote:
>> On 12/09/2013 02:33 AM, Arnd Bergmann wrote:
>>> On Sunday 08 December 2013, Sergei Ianovich wrote:
>>>> Non-dts implementation supply required DMA channel numbers as
>>>> IORESOURCE_DMA. However, there is was no way to get them from
>>>> device tree.
>>>
>>> I just wrote a lengthy reply to this email to explain in what ways
>>> you got it wrong, but then I saw that Daniel has already done all
>>> the work in the right way in August, so nevermind that.
>>>
>>> It hasn't made it upstream yet, but see http://list-archives.org/2013/08/07/linux-mtd-lists-infradead-org/patch-00-20-arm-pxa-move-core-and-drivers-to-dmaengine/f/3444199144
>>> for how it's done. Maybe Daniel can comment on the status of his
>>> patches.
>>
>> I recently rebased all my patches on top of 3.13-rc3, and will resend in
>> couple of days.
>>
>> The real problem here is that by reworking the DMA related PXA bits, all
>> drivers have to be changed at once, and a gradual transition seems
>> impossible. For that, I was asking for help in areas where I don't have
>> any hardware to test my patches on, but unfortunately, nobody got back
>> to me yet.
> 
> Nice to have Daniel in this conversation. Your patch series is a big and
> important work. However, I am not sure I will ever land as is exactly
> for this reason.

Well, I wouldn't be so certain about that statement. As I wrote in the
cover letter, most of the work is actually done, and I successfully
tested the new DMA support with a some of the drivers I ported. Others
were ported blindly, and in case of no reaction, I'd dare to merge them
and wait for people to report back in case of trouble.

The only real problem is the PXA camera driver, which does tricky things
like hot re-queuing of DMA descriptors. That one needs fixing before the
series can land.

> My proposal in to actually add new drivers for each platform device with
> DMA and mark new ones EXPERIMENTAL.

That would cause tree-wide cross-dependencies between drivers, because
the two DMA controllers can't be used at the same time, and the PXA
specific API will be unavailable when the mmp-dma driver is selected. My
patch series (and the DMA controller framework for that matter) aims for
the opposite - the unification of APIs and drivers.

> When they receive adequate testing
> we remove the tag and mark the old one OBSOLETE. When we have a new
> driver for every device presently supported, we will drop the whole old
> series.

Well, given the feedback I got for the series so far, I fear we'll be
off to maintain two drivers for each peripheral for a very long time.

I'd rather propose cracking the last nut that's left, and then get the
thing merged.

Arnd, Haojian? Any opinion here?



Daniel

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

* [PATCH v3] serial: rewrite pxa2xx-uart to use 8250_core
  2013-12-06  9:09                       ` Sergei Ianovich
  (?)
@ 2013-12-09 11:38                         ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-09 11:38 UTC (permalink / raw)
  To: linux-kernel
  Cc: Sergei Ianovich, Greg Kroah-Hartman, Russell King, Jiri Slaby,
	Grant Likely, Rob Herring, Heikki Krogerus, James Cameron,
	Andrew Morton, Haojian Zhuang, Zhou Zhu, John Crispin,
	moderated list:ARM PORT, open list:SERIAL DRIVERS,
	open list:OPEN FIRMWARE AND...

pxa2xx-uart was a separate uart platform driver. It was declaring
the same device names and numbers as 8250 driver. As a result,
it was impossible to use 8250 driver on PXA SoCs.

Upon closer examination pxa2xx-uart turned out to be a clone of
8250_core driver.

Workaround for Erratum #19 according to Marvel(R) PXA270M Processor
Specification Update (April 19, 2010) is dropped. 8250_core reads
from FIFO immediately after checking DR bit in LSR.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Reviewed-by: James Cameron <quozl@laptop.org>
CC: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 changes v2..v3
 * remove devm_free/put as suggested by Heikki Krogerus
 * use SET_SYSTEM_SLEEP_PM_OPS macro to set pm ops as suggested
   by Heikki Krogerus

 changes v1..v2
 * actually implement workaround for E74 in dl_write as spooted
   by James Cameron
 * added comment about E19 in commit message

 arch/arm/configs/am200epdkit_defconfig    |   3 +-
 arch/arm/configs/cm_x2xx_defconfig        |   3 +-
 arch/arm/configs/cm_x300_defconfig        |   3 +-
 arch/arm/configs/colibri_pxa270_defconfig |   3 +-
 arch/arm/configs/colibri_pxa300_defconfig |   3 +-
 arch/arm/configs/corgi_defconfig          |   4 +-
 arch/arm/configs/em_x270_defconfig        |   3 +-
 arch/arm/configs/ezx_defconfig            |   3 +-
 arch/arm/configs/h5000_defconfig          |   3 +-
 arch/arm/configs/imote2_defconfig         |   3 +-
 arch/arm/configs/lpd270_defconfig         |   3 +-
 arch/arm/configs/lubbock_defconfig        |   3 +-
 arch/arm/configs/mainstone_defconfig      |   3 +-
 arch/arm/configs/mmp2_defconfig           |   3 +-
 arch/arm/configs/pcm027_defconfig         |   3 +-
 arch/arm/configs/pxa168_defconfig         |   3 +-
 arch/arm/configs/pxa255-idp_defconfig     |   3 +-
 arch/arm/configs/pxa3xx_defconfig         |   3 +-
 arch/arm/configs/pxa910_defconfig         |   3 +-
 arch/arm/configs/raumfeld_defconfig       |   3 +-
 arch/arm/configs/spitz_defconfig          |   4 +-
 arch/arm/configs/trizeps4_defconfig       |   3 +-
 arch/arm/configs/viper_defconfig          |   4 +-
 arch/arm/configs/xcep_defconfig           |   3 +-
 drivers/tty/serial/8250/8250_pxa.c        | 178 ++++++
 drivers/tty/serial/8250/Kconfig           |   9 +
 drivers/tty/serial/8250/Makefile          |   1 +
 drivers/tty/serial/Kconfig                |  23 -
 drivers/tty/serial/Makefile               |   1 -
 drivers/tty/serial/pxa.c                  | 971 ------------------------------
 30 files changed, 236 insertions(+), 1022 deletions(-)
 create mode 100644 drivers/tty/serial/8250/8250_pxa.c
 delete mode 100644 drivers/tty/serial/pxa.c

diff --git a/arch/arm/configs/am200epdkit_defconfig b/arch/arm/configs/am200epdkit_defconfig
index f0dea52..0cde234 100644
--- a/arch/arm/configs/am200epdkit_defconfig
+++ b/arch/arm/configs/am200epdkit_defconfig
@@ -60,8 +60,9 @@ CONFIG_BLK_DEV_IDECS=m
 CONFIG_NETDEVICES=y
 CONFIG_NET_ETHERNET=y
 CONFIG_SMC91X=m
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 # CONFIG_HWMON is not set
diff --git a/arch/arm/configs/cm_x2xx_defconfig b/arch/arm/configs/cm_x2xx_defconfig
index a93ff8d..b9fbe65 100644
--- a/arch/arm/configs/cm_x2xx_defconfig
+++ b/arch/arm/configs/cm_x2xx_defconfig
@@ -96,8 +96,9 @@ CONFIG_KEYBOARD_PXA27x=m
 CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_TOUCHSCREEN_UCB1400=m
 # CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_LEGACY_PTY_COUNT=16
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/cm_x300_defconfig b/arch/arm/configs/cm_x300_defconfig
index f4b7672..53a82ae 100644
--- a/arch/arm/configs/cm_x300_defconfig
+++ b/arch/arm/configs/cm_x300_defconfig
@@ -80,8 +80,9 @@ CONFIG_TOUCHSCREEN_WM97XX=m
 # CONFIG_TOUCHSCREEN_WM9713 is not set
 # CONFIG_SERIO is not set
 # CONFIG_LEGACY_PTYS is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
 CONFIG_I2C_PXA=y
diff --git a/arch/arm/configs/colibri_pxa270_defconfig b/arch/arm/configs/colibri_pxa270_defconfig
index 2ef2c5e..1ce0409 100644
--- a/arch/arm/configs/colibri_pxa270_defconfig
+++ b/arch/arm/configs/colibri_pxa270_defconfig
@@ -103,8 +103,9 @@ CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=m
 CONFIG_SERIO_LIBPS2=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_HW_RANDOM=y
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
diff --git a/arch/arm/configs/colibri_pxa300_defconfig b/arch/arm/configs/colibri_pxa300_defconfig
index b985334..f96bda0 100644
--- a/arch/arm/configs/colibri_pxa300_defconfig
+++ b/arch/arm/configs/colibri_pxa300_defconfig
@@ -31,8 +31,9 @@ CONFIG_INPUT_EVDEV=y
 # CONFIG_INPUT_MOUSE is not set
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_GPIO_ROTARY_ENCODER=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_HW_RANDOM=y
 CONFIG_DEBUG_GPIO=y
 # CONFIG_HWMON is not set
diff --git a/arch/arm/configs/corgi_defconfig b/arch/arm/configs/corgi_defconfig
index 1fd1d1d..bb4842d 100644
--- a/arch/arm/configs/corgi_defconfig
+++ b/arch/arm/configs/corgi_defconfig
@@ -131,10 +131,10 @@ CONFIG_TOUCHSCREEN_ADS7846=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=m
 # CONFIG_SERIO is not set
-CONFIG_SERIAL_8250=m
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_CS=m
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 CONFIG_I2C=y
 CONFIG_I2C_PXA=y
diff --git a/arch/arm/configs/em_x270_defconfig b/arch/arm/configs/em_x270_defconfig
index 60a21e0..ec0ec54 100644
--- a/arch/arm/configs/em_x270_defconfig
+++ b/arch/arm/configs/em_x270_defconfig
@@ -90,8 +90,9 @@ CONFIG_TOUCHSCREEN_WM97XX=m
 # CONFIG_TOUCHSCREEN_WM9705 is not set
 # CONFIG_TOUCHSCREEN_WM9713 is not set
 # CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_LEGACY_PTY_COUNT=16
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/ezx_defconfig b/arch/arm/configs/ezx_defconfig
index d95763d..631e2ec 100644
--- a/arch/arm/configs/ezx_defconfig
+++ b/arch/arm/configs/ezx_defconfig
@@ -215,8 +215,9 @@ CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=y
 CONFIG_INPUT_PCAP=y
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_LEGACY_PTY_COUNT=8
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/h5000_defconfig b/arch/arm/configs/h5000_defconfig
index 37903e3..655b735 100644
--- a/arch/arm/configs/h5000_defconfig
+++ b/arch/arm/configs/h5000_defconfig
@@ -47,8 +47,9 @@ CONFIG_MTD_PHYSMAP=y
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_LEGACY_PTY_COUNT=32
 # CONFIG_HW_RANDOM is not set
 # CONFIG_HWMON is not set
diff --git a/arch/arm/configs/imote2_defconfig b/arch/arm/configs/imote2_defconfig
index fd996bb..49d45e9 100644
--- a/arch/arm/configs/imote2_defconfig
+++ b/arch/arm/configs/imote2_defconfig
@@ -193,8 +193,9 @@ CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=y
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_LEGACY_PTY_COUNT=8
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/lpd270_defconfig b/arch/arm/configs/lpd270_defconfig
index 1c8c9ee..c3927b6 100644
--- a/arch/arm/configs/lpd270_defconfig
+++ b/arch/arm/configs/lpd270_defconfig
@@ -38,8 +38,9 @@ CONFIG_SMC91X=y
 CONFIG_INPUT_EVDEV=y
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_HW_RANDOM is not set
 CONFIG_FB=y
 CONFIG_FB_PXA=y
diff --git a/arch/arm/configs/lubbock_defconfig b/arch/arm/configs/lubbock_defconfig
index c4ba274..c8b0436 100644
--- a/arch/arm/configs/lubbock_defconfig
+++ b/arch/arm/configs/lubbock_defconfig
@@ -37,8 +37,9 @@ CONFIG_PCMCIA_PCNET=y
 CONFIG_INPUT_EVDEV=y
 # CONFIG_SERIO_SERPORT is not set
 CONFIG_SERIO_SA1111=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_USB_GADGET=y
 CONFIG_USB_G_SERIAL=m
diff --git a/arch/arm/configs/mainstone_defconfig b/arch/arm/configs/mainstone_defconfig
index 04efa1b..768892c 100644
--- a/arch/arm/configs/mainstone_defconfig
+++ b/arch/arm/configs/mainstone_defconfig
@@ -34,8 +34,9 @@ CONFIG_SMC91X=y
 CONFIG_INPUT_EVDEV=y
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_FB=y
 CONFIG_FB_PXA=y
 # CONFIG_VGA_CONSOLE is not set
diff --git a/arch/arm/configs/mmp2_defconfig b/arch/arm/configs/mmp2_defconfig
index f1cb95e..1ced9df 100644
--- a/arch/arm/configs/mmp2_defconfig
+++ b/arch/arm/configs/mmp2_defconfig
@@ -44,8 +44,9 @@ CONFIG_SMC91X=y
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/pcm027_defconfig b/arch/arm/configs/pcm027_defconfig
index 2f136c3..1280128 100644
--- a/arch/arm/configs/pcm027_defconfig
+++ b/arch/arm/configs/pcm027_defconfig
@@ -60,8 +60,9 @@ CONFIG_SMC91X=y
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/pxa168_defconfig b/arch/arm/configs/pxa168_defconfig
index 74d7e01..1668dac 100644
--- a/arch/arm/configs/pxa168_defconfig
+++ b/arch/arm/configs/pxa168_defconfig
@@ -40,8 +40,9 @@ CONFIG_SMC91X=y
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 # CONFIG_HWMON is not set
diff --git a/arch/arm/configs/pxa255-idp_defconfig b/arch/arm/configs/pxa255-idp_defconfig
index 917a070..399a706 100644
--- a/arch/arm/configs/pxa255-idp_defconfig
+++ b/arch/arm/configs/pxa255-idp_defconfig
@@ -35,8 +35,9 @@ CONFIG_SMC91X=y
 CONFIG_INPUT_EVDEV=y
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_FB=y
 CONFIG_FB_PXA=y
 # CONFIG_VGA_CONSOLE is not set
diff --git a/arch/arm/configs/pxa3xx_defconfig b/arch/arm/configs/pxa3xx_defconfig
index 60e3138..7c3e052 100644
--- a/arch/arm/configs/pxa3xx_defconfig
+++ b/arch/arm/configs/pxa3xx_defconfig
@@ -56,8 +56,9 @@ CONFIG_KEYBOARD_PXA27x=y
 CONFIG_KEYBOARD_PXA930_ROTARY=y
 CONFIG_MOUSE_PXA930_TRKBALL=y
 CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/pxa910_defconfig b/arch/arm/configs/pxa910_defconfig
index 3bb7771..cdacfcb 100644
--- a/arch/arm/configs/pxa910_defconfig
+++ b/arch/arm/configs/pxa910_defconfig
@@ -40,8 +40,9 @@ CONFIG_SMC91X=y
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_SPI=y
 CONFIG_FB=y
 CONFIG_MMP_DISP=y
diff --git a/arch/arm/configs/raumfeld_defconfig b/arch/arm/configs/raumfeld_defconfig
index f7caa90..f1e16f2 100644
--- a/arch/arm/configs/raumfeld_defconfig
+++ b/arch/arm/configs/raumfeld_defconfig
@@ -67,8 +67,9 @@ CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_TOUCHSCREEN_EETI=m
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_GPIO_ROTARY_ENCODER=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_HW_RANDOM=y
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
diff --git a/arch/arm/configs/spitz_defconfig b/arch/arm/configs/spitz_defconfig
index 2e0419d..b6efcf5 100644
--- a/arch/arm/configs/spitz_defconfig
+++ b/arch/arm/configs/spitz_defconfig
@@ -128,10 +128,10 @@ CONFIG_TOUCHSCREEN_ADS7846=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=m
 # CONFIG_SERIO is not set
-CONFIG_SERIAL_8250=m
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_CS=m
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 CONFIG_SPI=y
 CONFIG_SPI_PXA2XX=y
diff --git a/arch/arm/configs/trizeps4_defconfig b/arch/arm/configs/trizeps4_defconfig
index 3162173..453c79c 100644
--- a/arch/arm/configs/trizeps4_defconfig
+++ b/arch/arm/configs/trizeps4_defconfig
@@ -132,8 +132,9 @@ CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=m
 CONFIG_SERIO_LIBPS2=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_HW_RANDOM=y
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
diff --git a/arch/arm/configs/viper_defconfig b/arch/arm/configs/viper_defconfig
index d36e0d3..4efac06 100644
--- a/arch/arm/configs/viper_defconfig
+++ b/arch/arm/configs/viper_defconfig
@@ -101,11 +101,11 @@ CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=m
 # CONFIG_CONSOLE_TRANSLATIONS is not set
 # CONFIG_VT_CONSOLE is not set
-CONFIG_SERIAL_8250=m
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_NR_UARTS=5
 CONFIG_SERIAL_8250_RUNTIME_UARTS=5
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
diff --git a/arch/arm/configs/xcep_defconfig b/arch/arm/configs/xcep_defconfig
index 721832f..b67aeaf 100644
--- a/arch/arm/configs/xcep_defconfig
+++ b/arch/arm/configs/xcep_defconfig
@@ -60,8 +60,9 @@ CONFIG_NET_ETHERNET=y
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
 # CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=m
diff --git a/drivers/tty/serial/8250/8250_pxa.c b/drivers/tty/serial/8250/8250_pxa.c
new file mode 100644
index 0000000..0da0d40
--- /dev/null
+++ b/drivers/tty/serial/8250/8250_pxa.c
@@ -0,0 +1,178 @@
+/*
+ *  drivers/tty/serial/8250/8250_pxa.c -- driver for PXA on-board UARTS
+ *  Copyright:	(C) 2013 Sergei Ianovich <ynvich@gmail.com>
+ *
+ *  replaces drivers/serial/pxa.c by Nicolas Pitre
+ *  Created:	Feb 20, 2003
+ *  Copyright:	(C) 2003 Monta Vista Software, Inc.
+ *
+ *  Based on drivers/serial/8250.c by Russell King.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/serial_8250.h>
+#include <linux/serial_core.h>
+#include <linux/serial_reg.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
+#include <linux/pm_runtime.h>
+
+#include "8250.h"
+
+struct pxa8250_data {
+	int			line;
+	struct clk		*clk;
+};
+
+#ifdef CONFIG_PM
+static int serial_pxa_suspend(struct device *dev)
+{
+	struct pxa8250_data *data = dev_get_drvdata(dev);
+
+	serial8250_suspend_port(data->line);
+
+	return 0;
+}
+
+static int serial_pxa_resume(struct device *dev)
+{
+	struct pxa8250_data *data = dev_get_drvdata(dev);
+
+	serial8250_resume_port(data->line);
+
+	return 0;
+}
+#endif
+
+static const struct dev_pm_ops serial_pxa_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(serial_pxa_suspend, serial_pxa_resume)
+};
+
+static struct of_device_id serial_pxa_dt_ids[] = {
+	{ .compatible = "mrvl,pxa-uart", },
+	{ .compatible = "mrvl,mmp-uart", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, serial_pxa_dt_ids);
+
+/* Uart divisor latch write */
+static void serial_pxa_dl_write(struct uart_8250_port *up, int value)
+{
+	unsigned int dll;
+
+	serial_out(up, UART_DLL, value & 0xff);
+	/*
+	 * work around Erratum #74 according to Marvel(R) PXA270M Processor
+	 * Specification Update (April 19, 2010)
+	 */
+	dll = serial_in(up, UART_DLL);
+	WARN_ON(dll != (value & 0xff));
+
+	serial_out(up, UART_DLM, value >> 8 & 0xff);
+}
+
+
+static void serial_pxa_pm(struct uart_port *port, unsigned int state,
+	      unsigned int oldstate)
+{
+	struct pxa8250_data *data = port->private_data;
+
+	if (!state)
+		clk_prepare_enable(data->clk);
+	else
+		clk_disable_unprepare(data->clk);
+}
+
+static int serial_pxa_probe(struct platform_device *pdev)
+{
+	struct uart_8250_port uart = {};
+	struct pxa8250_data *data;
+	struct resource *mmres, *irqres;
+	int ret;
+
+	mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	irqres = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!mmres || !irqres)
+		return -ENODEV;
+
+	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(data->clk))
+		return PTR_ERR(data->clk);
+
+	ret = clk_prepare(data->clk);
+	if (ret)
+		return ret;
+
+	uart.port.type = PORT_XSCALE;
+	uart.port.iotype = UPIO_MEM32;
+	uart.port.mapbase = mmres->start;
+	uart.port.regshift = 2;
+	uart.port.irq = irqres->start;
+	uart.port.fifosize = 64;
+	uart.port.flags = UPF_IOREMAP | UPF_SKIP_TEST;
+	uart.port.dev = &pdev->dev;
+	uart.port.uartclk = clk_get_rate(data->clk);
+	uart.port.pm = serial_pxa_pm;
+	uart.port.private_data = data;
+	uart.dl_write = serial_pxa_dl_write;
+
+	ret = serial8250_register_8250_port(&uart);
+	if (ret < 0)
+		goto err_clk;
+
+	data->line = ret;
+
+	platform_set_drvdata(pdev, data);
+
+	return 0;
+
+ err_clk:
+	clk_unprepare(data->clk);
+	return ret;
+}
+
+static int serial_pxa_remove(struct platform_device *pdev)
+{
+	struct pxa8250_data *data = platform_get_drvdata(pdev);
+
+	serial8250_unregister_port(data->line);
+
+	clk_unprepare(data->clk);
+
+	return 0;
+}
+
+static struct platform_driver serial_pxa_driver = {
+	.probe          = serial_pxa_probe,
+	.remove         = serial_pxa_remove,
+
+	.driver		= {
+		.name	= "pxa2xx-uart",
+		.owner	= THIS_MODULE,
+		.pm	= &serial_pxa_pm_ops,
+		.of_match_table = serial_pxa_dt_ids,
+	},
+};
+
+module_platform_driver(serial_pxa_driver);
+
+MODULE_AUTHOR("Sergei Ianovich");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:pxa2xx-uart");
diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
index 2332991..81bd7c9 100644
--- a/drivers/tty/serial/8250/Kconfig
+++ b/drivers/tty/serial/8250/Kconfig
@@ -302,3 +302,12 @@ config SERIAL_8250_RT288X
 	  If you have a Ralink RT288x/RT305x SoC based board and want to use the
 	  serial port, say Y to this option. The driver can handle up to 2 serial
 	  ports. If unsure, say N.
+
+config SERIAL_PXA
+	tristate "PXA serial port support"
+	depends on SERIAL_8250 && (ARCH_PXA || ARCH_MMP)
+	help
+	  If you have a machine based on an Intel XScale PXA2xx CPU you
+	  can enable its onboard serial ports by enabling this option.
+
+	  If you choose M here, the module name will be 8250_pxa.
diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile
index 36d68d0..b7d1b61 100644
--- a/drivers/tty/serial/8250/Makefile
+++ b/drivers/tty/serial/8250/Makefile
@@ -20,3 +20,4 @@ obj-$(CONFIG_SERIAL_8250_HUB6)		+= 8250_hub6.o
 obj-$(CONFIG_SERIAL_8250_FSL)		+= 8250_fsl.o
 obj-$(CONFIG_SERIAL_8250_DW)		+= 8250_dw.o
 obj-$(CONFIG_SERIAL_8250_EM)		+= 8250_em.o
+obj-$(CONFIG_SERIAL_PXA)		+= 8250_pxa.o
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index a3817ab..2ad7184b 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -396,29 +396,6 @@ config SERIAL_MPSC_CONSOLE
 	help
 	  Say Y here if you want to support a serial console on a Marvell MPSC.
 
-config SERIAL_PXA
-	bool "PXA serial port support"
-	depends on ARCH_PXA || ARCH_MMP
-	select SERIAL_CORE
-	help
-	  If you have a machine based on an Intel XScale PXA2xx CPU you
-	  can enable its onboard serial ports by enabling this option.
-
-config SERIAL_PXA_CONSOLE
-	bool "Console on PXA serial port"
-	depends on SERIAL_PXA
-	select SERIAL_CORE_CONSOLE
-	help
-	  If you have enabled the serial port on the Intel XScale PXA
-	  CPU you can make it the console by answering Y to this option.
-
-	  Even if you say Y here, the currently visible virtual console
-	  (/dev/tty0) will still be used as the system console by default, but
-	  you can alter that using a kernel command line option such as
-	  "console=ttySA0". (Try "man bootparam" or see the documentation of
-	  your boot loader (lilo or loadlin) about how to pass options to the
-	  kernel at boot time.)
-
 config SERIAL_SA1100
 	bool "SA1100 serial port support"
 	depends on ARCH_SA1100
diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile
index 3068c77..4ac337b 100644
--- a/drivers/tty/serial/Makefile
+++ b/drivers/tty/serial/Makefile
@@ -20,7 +20,6 @@ obj-$(CONFIG_SERIAL_8250) += 8250/
 obj-$(CONFIG_SERIAL_AMBA_PL010) += amba-pl010.o
 obj-$(CONFIG_SERIAL_AMBA_PL011) += amba-pl011.o
 obj-$(CONFIG_SERIAL_CLPS711X) += clps711x.o
-obj-$(CONFIG_SERIAL_PXA) += pxa.o
 obj-$(CONFIG_SERIAL_PNX8XXX) += pnx8xxx_uart.o
 obj-$(CONFIG_SERIAL_SA1100) += sa1100.o
 obj-$(CONFIG_SERIAL_BCM63XX) += bcm63xx_uart.o
diff --git a/drivers/tty/serial/pxa.c b/drivers/tty/serial/pxa.c
deleted file mode 100644
index f9f20f3..0000000
--- a/drivers/tty/serial/pxa.c
+++ /dev/null
@@ -1,971 +0,0 @@
-/*
- *  Based on drivers/serial/8250.c by Russell King.
- *
- *  Author:	Nicolas Pitre
- *  Created:	Feb 20, 2003
- *  Copyright:	(C) 2003 Monta Vista Software, Inc.
- *
- * 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.
- *
- * Note 1: This driver is made separate from the already too overloaded
- * 8250.c because it needs some kirks of its own and that'll make it
- * easier to add DMA support.
- *
- * Note 2: I'm too sick of device allocation policies for serial ports.
- * If someone else wants to request an "official" allocation of major/minor
- * for this driver please be my guest.  And don't forget that new hardware
- * to come from Intel might have more than 3 or 4 of those UARTs.  Let's
- * hope for a better port registration and dynamic device allocation scheme
- * with the serial core maintainer satisfaction to appear soon.
- */
-
-
-#if defined(CONFIG_SERIAL_PXA_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-#define SUPPORT_SYSRQ
-#endif
-
-#include <linux/module.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-#include <linux/console.h>
-#include <linux/sysrq.h>
-#include <linux/serial_reg.h>
-#include <linux/circ_buf.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/of.h>
-#include <linux/platform_device.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/serial_core.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-
-#define PXA_NAME_LEN		8
-
-struct uart_pxa_port {
-	struct uart_port        port;
-	unsigned char           ier;
-	unsigned char           lcr;
-	unsigned char           mcr;
-	unsigned int            lsr_break_flag;
-	struct clk		*clk;
-	char			name[PXA_NAME_LEN];
-};
-
-static inline unsigned int serial_in(struct uart_pxa_port *up, int offset)
-{
-	offset <<= 2;
-	return readl(up->port.membase + offset);
-}
-
-static inline void serial_out(struct uart_pxa_port *up, int offset, int value)
-{
-	offset <<= 2;
-	writel(value, up->port.membase + offset);
-}
-
-static void serial_pxa_enable_ms(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	up->ier |= UART_IER_MSI;
-	serial_out(up, UART_IER, up->ier);
-}
-
-static void serial_pxa_stop_tx(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	if (up->ier & UART_IER_THRI) {
-		up->ier &= ~UART_IER_THRI;
-		serial_out(up, UART_IER, up->ier);
-	}
-}
-
-static void serial_pxa_stop_rx(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	up->ier &= ~UART_IER_RLSI;
-	up->port.read_status_mask &= ~UART_LSR_DR;
-	serial_out(up, UART_IER, up->ier);
-}
-
-static inline void receive_chars(struct uart_pxa_port *up, int *status)
-{
-	unsigned int ch, flag;
-	int max_count = 256;
-
-	do {
-		/* work around Errata #20 according to
-		 * Intel(R) PXA27x Processor Family
-		 * Specification Update (May 2005)
-		 *
-		 * Step 2
-		 * Disable the Reciever Time Out Interrupt via IER[RTOEI]
-		 */
-		up->ier &= ~UART_IER_RTOIE;
-		serial_out(up, UART_IER, up->ier);
-
-		ch = serial_in(up, UART_RX);
-		flag = TTY_NORMAL;
-		up->port.icount.rx++;
-
-		if (unlikely(*status & (UART_LSR_BI | UART_LSR_PE |
-				       UART_LSR_FE | UART_LSR_OE))) {
-			/*
-			 * For statistics only
-			 */
-			if (*status & UART_LSR_BI) {
-				*status &= ~(UART_LSR_FE | UART_LSR_PE);
-				up->port.icount.brk++;
-				/*
-				 * We do the SysRQ and SAK checking
-				 * here because otherwise the break
-				 * may get masked by ignore_status_mask
-				 * or read_status_mask.
-				 */
-				if (uart_handle_break(&up->port))
-					goto ignore_char;
-			} else if (*status & UART_LSR_PE)
-				up->port.icount.parity++;
-			else if (*status & UART_LSR_FE)
-				up->port.icount.frame++;
-			if (*status & UART_LSR_OE)
-				up->port.icount.overrun++;
-
-			/*
-			 * Mask off conditions which should be ignored.
-			 */
-			*status &= up->port.read_status_mask;
-
-#ifdef CONFIG_SERIAL_PXA_CONSOLE
-			if (up->port.line == up->port.cons->index) {
-				/* Recover the break flag from console xmit */
-				*status |= up->lsr_break_flag;
-				up->lsr_break_flag = 0;
-			}
-#endif
-			if (*status & UART_LSR_BI) {
-				flag = TTY_BREAK;
-			} else if (*status & UART_LSR_PE)
-				flag = TTY_PARITY;
-			else if (*status & UART_LSR_FE)
-				flag = TTY_FRAME;
-		}
-
-		if (uart_handle_sysrq_char(&up->port, ch))
-			goto ignore_char;
-
-		uart_insert_char(&up->port, *status, UART_LSR_OE, ch, flag);
-
-	ignore_char:
-		*status = serial_in(up, UART_LSR);
-	} while ((*status & UART_LSR_DR) && (max_count-- > 0));
-	tty_flip_buffer_push(&up->port.state->port);
-
-	/* work around Errata #20 according to
-	 * Intel(R) PXA27x Processor Family
-	 * Specification Update (May 2005)
-	 *
-	 * Step 6:
-	 * No more data in FIFO: Re-enable RTO interrupt via IER[RTOIE]
-	 */
-	up->ier |= UART_IER_RTOIE;
-	serial_out(up, UART_IER, up->ier);
-}
-
-static void transmit_chars(struct uart_pxa_port *up)
-{
-	struct circ_buf *xmit = &up->port.state->xmit;
-	int count;
-
-	if (up->port.x_char) {
-		serial_out(up, UART_TX, up->port.x_char);
-		up->port.icount.tx++;
-		up->port.x_char = 0;
-		return;
-	}
-	if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) {
-		serial_pxa_stop_tx(&up->port);
-		return;
-	}
-
-	count = up->port.fifosize / 2;
-	do {
-		serial_out(up, UART_TX, xmit->buf[xmit->tail]);
-		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
-		up->port.icount.tx++;
-		if (uart_circ_empty(xmit))
-			break;
-	} while (--count > 0);
-
-	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
-		uart_write_wakeup(&up->port);
-
-
-	if (uart_circ_empty(xmit))
-		serial_pxa_stop_tx(&up->port);
-}
-
-static void serial_pxa_start_tx(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	if (!(up->ier & UART_IER_THRI)) {
-		up->ier |= UART_IER_THRI;
-		serial_out(up, UART_IER, up->ier);
-	}
-}
-
-static inline void check_modem_status(struct uart_pxa_port *up)
-{
-	int status;
-
-	status = serial_in(up, UART_MSR);
-
-	if ((status & UART_MSR_ANY_DELTA) == 0)
-		return;
-
-	if (status & UART_MSR_TERI)
-		up->port.icount.rng++;
-	if (status & UART_MSR_DDSR)
-		up->port.icount.dsr++;
-	if (status & UART_MSR_DDCD)
-		uart_handle_dcd_change(&up->port, status & UART_MSR_DCD);
-	if (status & UART_MSR_DCTS)
-		uart_handle_cts_change(&up->port, status & UART_MSR_CTS);
-
-	wake_up_interruptible(&up->port.state->port.delta_msr_wait);
-}
-
-/*
- * This handles the interrupt from one port.
- */
-static inline irqreturn_t serial_pxa_irq(int irq, void *dev_id)
-{
-	struct uart_pxa_port *up = dev_id;
-	unsigned int iir, lsr;
-
-	iir = serial_in(up, UART_IIR);
-	if (iir & UART_IIR_NO_INT)
-		return IRQ_NONE;
-	lsr = serial_in(up, UART_LSR);
-	if (lsr & UART_LSR_DR)
-		receive_chars(up, &lsr);
-	check_modem_status(up);
-	if (lsr & UART_LSR_THRE)
-		transmit_chars(up);
-	return IRQ_HANDLED;
-}
-
-static unsigned int serial_pxa_tx_empty(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned long flags;
-	unsigned int ret;
-
-	spin_lock_irqsave(&up->port.lock, flags);
-	ret = serial_in(up, UART_LSR) & UART_LSR_TEMT ? TIOCSER_TEMT : 0;
-	spin_unlock_irqrestore(&up->port.lock, flags);
-
-	return ret;
-}
-
-static unsigned int serial_pxa_get_mctrl(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned char status;
-	unsigned int ret;
-
-	status = serial_in(up, UART_MSR);
-
-	ret = 0;
-	if (status & UART_MSR_DCD)
-		ret |= TIOCM_CAR;
-	if (status & UART_MSR_RI)
-		ret |= TIOCM_RNG;
-	if (status & UART_MSR_DSR)
-		ret |= TIOCM_DSR;
-	if (status & UART_MSR_CTS)
-		ret |= TIOCM_CTS;
-	return ret;
-}
-
-static void serial_pxa_set_mctrl(struct uart_port *port, unsigned int mctrl)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned char mcr = 0;
-
-	if (mctrl & TIOCM_RTS)
-		mcr |= UART_MCR_RTS;
-	if (mctrl & TIOCM_DTR)
-		mcr |= UART_MCR_DTR;
-	if (mctrl & TIOCM_OUT1)
-		mcr |= UART_MCR_OUT1;
-	if (mctrl & TIOCM_OUT2)
-		mcr |= UART_MCR_OUT2;
-	if (mctrl & TIOCM_LOOP)
-		mcr |= UART_MCR_LOOP;
-
-	mcr |= up->mcr;
-
-	serial_out(up, UART_MCR, mcr);
-}
-
-static void serial_pxa_break_ctl(struct uart_port *port, int break_state)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned long flags;
-
-	spin_lock_irqsave(&up->port.lock, flags);
-	if (break_state == -1)
-		up->lcr |= UART_LCR_SBC;
-	else
-		up->lcr &= ~UART_LCR_SBC;
-	serial_out(up, UART_LCR, up->lcr);
-	spin_unlock_irqrestore(&up->port.lock, flags);
-}
-
-static int serial_pxa_startup(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned long flags;
-	int retval;
-
-	if (port->line == 3) /* HWUART */
-		up->mcr |= UART_MCR_AFE;
-	else
-		up->mcr = 0;
-
-	up->port.uartclk = clk_get_rate(up->clk);
-
-	/*
-	 * Allocate the IRQ
-	 */
-	retval = request_irq(up->port.irq, serial_pxa_irq, 0, up->name, up);
-	if (retval)
-		return retval;
-
-	/*
-	 * Clear the FIFO buffers and disable them.
-	 * (they will be reenabled in set_termios())
-	 */
-	serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO);
-	serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO |
-			UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
-	serial_out(up, UART_FCR, 0);
-
-	/*
-	 * Clear the interrupt registers.
-	 */
-	(void) serial_in(up, UART_LSR);
-	(void) serial_in(up, UART_RX);
-	(void) serial_in(up, UART_IIR);
-	(void) serial_in(up, UART_MSR);
-
-	/*
-	 * Now, initialize the UART
-	 */
-	serial_out(up, UART_LCR, UART_LCR_WLEN8);
-
-	spin_lock_irqsave(&up->port.lock, flags);
-	up->port.mctrl |= TIOCM_OUT2;
-	serial_pxa_set_mctrl(&up->port, up->port.mctrl);
-	spin_unlock_irqrestore(&up->port.lock, flags);
-
-	/*
-	 * Finally, enable interrupts.  Note: Modem status interrupts
-	 * are set via set_termios(), which will be occurring imminently
-	 * anyway, so we don't enable them here.
-	 */
-	up->ier = UART_IER_RLSI | UART_IER_RDI | UART_IER_RTOIE | UART_IER_UUE;
-	serial_out(up, UART_IER, up->ier);
-
-	/*
-	 * And clear the interrupt registers again for luck.
-	 */
-	(void) serial_in(up, UART_LSR);
-	(void) serial_in(up, UART_RX);
-	(void) serial_in(up, UART_IIR);
-	(void) serial_in(up, UART_MSR);
-
-	return 0;
-}
-
-static void serial_pxa_shutdown(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned long flags;
-
-	free_irq(up->port.irq, up);
-
-	/*
-	 * Disable interrupts from this port
-	 */
-	up->ier = 0;
-	serial_out(up, UART_IER, 0);
-
-	spin_lock_irqsave(&up->port.lock, flags);
-	up->port.mctrl &= ~TIOCM_OUT2;
-	serial_pxa_set_mctrl(&up->port, up->port.mctrl);
-	spin_unlock_irqrestore(&up->port.lock, flags);
-
-	/*
-	 * Disable break condition and FIFOs
-	 */
-	serial_out(up, UART_LCR, serial_in(up, UART_LCR) & ~UART_LCR_SBC);
-	serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO |
-				  UART_FCR_CLEAR_RCVR |
-				  UART_FCR_CLEAR_XMIT);
-	serial_out(up, UART_FCR, 0);
-}
-
-static void
-serial_pxa_set_termios(struct uart_port *port, struct ktermios *termios,
-		       struct ktermios *old)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned char cval, fcr = 0;
-	unsigned long flags;
-	unsigned int baud, quot;
-	unsigned int dll;
-
-	switch (termios->c_cflag & CSIZE) {
-	case CS5:
-		cval = UART_LCR_WLEN5;
-		break;
-	case CS6:
-		cval = UART_LCR_WLEN6;
-		break;
-	case CS7:
-		cval = UART_LCR_WLEN7;
-		break;
-	default:
-	case CS8:
-		cval = UART_LCR_WLEN8;
-		break;
-	}
-
-	if (termios->c_cflag & CSTOPB)
-		cval |= UART_LCR_STOP;
-	if (termios->c_cflag & PARENB)
-		cval |= UART_LCR_PARITY;
-	if (!(termios->c_cflag & PARODD))
-		cval |= UART_LCR_EPAR;
-
-	/*
-	 * Ask the core to calculate the divisor for us.
-	 */
-	baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
-	quot = uart_get_divisor(port, baud);
-
-	if ((up->port.uartclk / quot) < (2400 * 16))
-		fcr = UART_FCR_ENABLE_FIFO | UART_FCR_PXAR1;
-	else if ((up->port.uartclk / quot) < (230400 * 16))
-		fcr = UART_FCR_ENABLE_FIFO | UART_FCR_PXAR8;
-	else
-		fcr = UART_FCR_ENABLE_FIFO | UART_FCR_PXAR32;
-
-	/*
-	 * Ok, we're now changing the port state.  Do it with
-	 * interrupts disabled.
-	 */
-	spin_lock_irqsave(&up->port.lock, flags);
-
-	/*
-	 * Ensure the port will be enabled.
-	 * This is required especially for serial console.
-	 */
-	up->ier |= UART_IER_UUE;
-
-	/*
-	 * Update the per-port timeout.
-	 */
-	uart_update_timeout(port, termios->c_cflag, baud);
-
-	up->port.read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;
-	if (termios->c_iflag & INPCK)
-		up->port.read_status_mask |= UART_LSR_FE | UART_LSR_PE;
-	if (termios->c_iflag & (BRKINT | PARMRK))
-		up->port.read_status_mask |= UART_LSR_BI;
-
-	/*
-	 * Characters to ignore
-	 */
-	up->port.ignore_status_mask = 0;
-	if (termios->c_iflag & IGNPAR)
-		up->port.ignore_status_mask |= UART_LSR_PE | UART_LSR_FE;
-	if (termios->c_iflag & IGNBRK) {
-		up->port.ignore_status_mask |= UART_LSR_BI;
-		/*
-		 * If we're ignoring parity and break indicators,
-		 * ignore overruns too (for real raw support).
-		 */
-		if (termios->c_iflag & IGNPAR)
-			up->port.ignore_status_mask |= UART_LSR_OE;
-	}
-
-	/*
-	 * ignore all characters if CREAD is not set
-	 */
-	if ((termios->c_cflag & CREAD) == 0)
-		up->port.ignore_status_mask |= UART_LSR_DR;
-
-	/*
-	 * CTS flow control flag and modem status interrupts
-	 */
-	up->ier &= ~UART_IER_MSI;
-	if (UART_ENABLE_MS(&up->port, termios->c_cflag))
-		up->ier |= UART_IER_MSI;
-
-	serial_out(up, UART_IER, up->ier);
-
-	if (termios->c_cflag & CRTSCTS)
-		up->mcr |= UART_MCR_AFE;
-	else
-		up->mcr &= ~UART_MCR_AFE;
-
-	serial_out(up, UART_LCR, cval | UART_LCR_DLAB);	/* set DLAB */
-	serial_out(up, UART_DLL, quot & 0xff);		/* LS of divisor */
-
-	/*
-	 * work around Errata #75 according to Intel(R) PXA27x Processor Family
-	 * Specification Update (Nov 2005)
-	 */
-	dll = serial_in(up, UART_DLL);
-	WARN_ON(dll != (quot & 0xff));
-
-	serial_out(up, UART_DLM, quot >> 8);		/* MS of divisor */
-	serial_out(up, UART_LCR, cval);			/* reset DLAB */
-	up->lcr = cval;					/* Save LCR */
-	serial_pxa_set_mctrl(&up->port, up->port.mctrl);
-	serial_out(up, UART_FCR, fcr);
-	spin_unlock_irqrestore(&up->port.lock, flags);
-}
-
-static void
-serial_pxa_pm(struct uart_port *port, unsigned int state,
-	      unsigned int oldstate)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	if (!state)
-		clk_prepare_enable(up->clk);
-	else
-		clk_disable_unprepare(up->clk);
-}
-
-static void serial_pxa_release_port(struct uart_port *port)
-{
-}
-
-static int serial_pxa_request_port(struct uart_port *port)
-{
-	return 0;
-}
-
-static void serial_pxa_config_port(struct uart_port *port, int flags)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	up->port.type = PORT_PXA;
-}
-
-static int
-serial_pxa_verify_port(struct uart_port *port, struct serial_struct *ser)
-{
-	/* we don't want the core code to modify any port params */
-	return -EINVAL;
-}
-
-static const char *
-serial_pxa_type(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	return up->name;
-}
-
-static struct uart_pxa_port *serial_pxa_ports[4];
-static struct uart_driver serial_pxa_reg;
-
-#ifdef CONFIG_SERIAL_PXA_CONSOLE
-
-#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
-
-/*
- *	Wait for transmitter & holding register to empty
- */
-static inline void wait_for_xmitr(struct uart_pxa_port *up)
-{
-	unsigned int status, tmout = 10000;
-
-	/* Wait up to 10ms for the character(s) to be sent. */
-	do {
-		status = serial_in(up, UART_LSR);
-
-		if (status & UART_LSR_BI)
-			up->lsr_break_flag = UART_LSR_BI;
-
-		if (--tmout == 0)
-			break;
-		udelay(1);
-	} while ((status & BOTH_EMPTY) != BOTH_EMPTY);
-
-	/* Wait up to 1s for flow control if necessary */
-	if (up->port.flags & UPF_CONS_FLOW) {
-		tmout = 1000000;
-		while (--tmout &&
-		       ((serial_in(up, UART_MSR) & UART_MSR_CTS) == 0))
-			udelay(1);
-	}
-}
-
-static void serial_pxa_console_putchar(struct uart_port *port, int ch)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	wait_for_xmitr(up);
-	serial_out(up, UART_TX, ch);
-}
-
-/*
- * Print a string to the serial port trying not to disturb
- * any possible real use of the port...
- *
- *	The console_lock must be held when we get here.
- */
-static void
-serial_pxa_console_write(struct console *co, const char *s, unsigned int count)
-{
-	struct uart_pxa_port *up = serial_pxa_ports[co->index];
-	unsigned int ier;
-	unsigned long flags;
-	int locked = 1;
-
-	clk_enable(up->clk);
-	local_irq_save(flags);
-	if (up->port.sysrq)
-		locked = 0;
-	else if (oops_in_progress)
-		locked = spin_trylock(&up->port.lock);
-	else
-		spin_lock(&up->port.lock);
-
-	/*
-	 *	First save the IER then disable the interrupts
-	 */
-	ier = serial_in(up, UART_IER);
-	serial_out(up, UART_IER, UART_IER_UUE);
-
-	uart_console_write(&up->port, s, count, serial_pxa_console_putchar);
-
-	/*
-	 *	Finally, wait for transmitter to become empty
-	 *	and restore the IER
-	 */
-	wait_for_xmitr(up);
-	serial_out(up, UART_IER, ier);
-
-	if (locked)
-		spin_unlock(&up->port.lock);
-	local_irq_restore(flags);
-	clk_disable(up->clk);
-
-}
-
-#ifdef CONFIG_CONSOLE_POLL
-/*
- * Console polling routines for writing and reading from the uart while
- * in an interrupt or debug context.
- */
-
-static int serial_pxa_get_poll_char(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned char lsr = serial_in(up, UART_LSR);
-
-	while (!(lsr & UART_LSR_DR))
-		lsr = serial_in(up, UART_LSR);
-
-	return serial_in(up, UART_RX);
-}
-
-
-static void serial_pxa_put_poll_char(struct uart_port *port,
-			 unsigned char c)
-{
-	unsigned int ier;
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	/*
-	 *	First save the IER then disable the interrupts
-	 */
-	ier = serial_in(up, UART_IER);
-	serial_out(up, UART_IER, UART_IER_UUE);
-
-	wait_for_xmitr(up);
-	/*
-	 *	Send the character out.
-	 *	If a LF, also do CR...
-	 */
-	serial_out(up, UART_TX, c);
-	if (c == 10) {
-		wait_for_xmitr(up);
-		serial_out(up, UART_TX, 13);
-	}
-
-	/*
-	 *	Finally, wait for transmitter to become empty
-	 *	and restore the IER
-	 */
-	wait_for_xmitr(up);
-	serial_out(up, UART_IER, ier);
-}
-
-#endif /* CONFIG_CONSOLE_POLL */
-
-static int __init
-serial_pxa_console_setup(struct console *co, char *options)
-{
-	struct uart_pxa_port *up;
-	int baud = 9600;
-	int bits = 8;
-	int parity = 'n';
-	int flow = 'n';
-
-	if (co->index == -1 || co->index >= serial_pxa_reg.nr)
-		co->index = 0;
-	up = serial_pxa_ports[co->index];
-	if (!up)
-		return -ENODEV;
-
-	if (options)
-		uart_parse_options(options, &baud, &parity, &bits, &flow);
-
-	return uart_set_options(&up->port, co, baud, parity, bits, flow);
-}
-
-static struct console serial_pxa_console = {
-	.name		= "ttyS",
-	.write		= serial_pxa_console_write,
-	.device		= uart_console_device,
-	.setup		= serial_pxa_console_setup,
-	.flags		= CON_PRINTBUFFER,
-	.index		= -1,
-	.data		= &serial_pxa_reg,
-};
-
-#define PXA_CONSOLE	&serial_pxa_console
-#else
-#define PXA_CONSOLE	NULL
-#endif
-
-static struct uart_ops serial_pxa_pops = {
-	.tx_empty	= serial_pxa_tx_empty,
-	.set_mctrl	= serial_pxa_set_mctrl,
-	.get_mctrl	= serial_pxa_get_mctrl,
-	.stop_tx	= serial_pxa_stop_tx,
-	.start_tx	= serial_pxa_start_tx,
-	.stop_rx	= serial_pxa_stop_rx,
-	.enable_ms	= serial_pxa_enable_ms,
-	.break_ctl	= serial_pxa_break_ctl,
-	.startup	= serial_pxa_startup,
-	.shutdown	= serial_pxa_shutdown,
-	.set_termios	= serial_pxa_set_termios,
-	.pm		= serial_pxa_pm,
-	.type		= serial_pxa_type,
-	.release_port	= serial_pxa_release_port,
-	.request_port	= serial_pxa_request_port,
-	.config_port	= serial_pxa_config_port,
-	.verify_port	= serial_pxa_verify_port,
-#ifdef CONFIG_CONSOLE_POLL
-	.poll_get_char = serial_pxa_get_poll_char,
-	.poll_put_char = serial_pxa_put_poll_char,
-#endif
-};
-
-static struct uart_driver serial_pxa_reg = {
-	.owner		= THIS_MODULE,
-	.driver_name	= "PXA serial",
-	.dev_name	= "ttyS",
-	.major		= TTY_MAJOR,
-	.minor		= 64,
-	.nr		= 4,
-	.cons		= PXA_CONSOLE,
-};
-
-#ifdef CONFIG_PM
-static int serial_pxa_suspend(struct device *dev)
-{
-        struct uart_pxa_port *sport = dev_get_drvdata(dev);
-
-        if (sport)
-                uart_suspend_port(&serial_pxa_reg, &sport->port);
-
-        return 0;
-}
-
-static int serial_pxa_resume(struct device *dev)
-{
-        struct uart_pxa_port *sport = dev_get_drvdata(dev);
-
-        if (sport)
-                uart_resume_port(&serial_pxa_reg, &sport->port);
-
-        return 0;
-}
-
-static const struct dev_pm_ops serial_pxa_pm_ops = {
-	.suspend	= serial_pxa_suspend,
-	.resume		= serial_pxa_resume,
-};
-#endif
-
-static struct of_device_id serial_pxa_dt_ids[] = {
-	{ .compatible = "mrvl,pxa-uart", },
-	{ .compatible = "mrvl,mmp-uart", },
-	{}
-};
-MODULE_DEVICE_TABLE(of, serial_pxa_dt_ids);
-
-static int serial_pxa_probe_dt(struct platform_device *pdev,
-			       struct uart_pxa_port *sport)
-{
-	struct device_node *np = pdev->dev.of_node;
-	int ret;
-
-	if (!np)
-		return 1;
-
-	ret = of_alias_get_id(np, "serial");
-	if (ret < 0) {
-		dev_err(&pdev->dev, "failed to get alias id, errno %d\n", ret);
-		return ret;
-	}
-	sport->port.line = ret;
-	return 0;
-}
-
-static int serial_pxa_probe(struct platform_device *dev)
-{
-	struct uart_pxa_port *sport;
-	struct resource *mmres, *irqres;
-	int ret;
-
-	mmres = platform_get_resource(dev, IORESOURCE_MEM, 0);
-	irqres = platform_get_resource(dev, IORESOURCE_IRQ, 0);
-	if (!mmres || !irqres)
-		return -ENODEV;
-
-	sport = kzalloc(sizeof(struct uart_pxa_port), GFP_KERNEL);
-	if (!sport)
-		return -ENOMEM;
-
-	sport->clk = clk_get(&dev->dev, NULL);
-	if (IS_ERR(sport->clk)) {
-		ret = PTR_ERR(sport->clk);
-		goto err_free;
-	}
-
-	ret = clk_prepare(sport->clk);
-	if (ret) {
-		clk_put(sport->clk);
-		goto err_free;
-	}
-
-	sport->port.type = PORT_PXA;
-	sport->port.iotype = UPIO_MEM;
-	sport->port.mapbase = mmres->start;
-	sport->port.irq = irqres->start;
-	sport->port.fifosize = 64;
-	sport->port.ops = &serial_pxa_pops;
-	sport->port.dev = &dev->dev;
-	sport->port.flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF;
-	sport->port.uartclk = clk_get_rate(sport->clk);
-
-	ret = serial_pxa_probe_dt(dev, sport);
-	if (ret > 0)
-		sport->port.line = dev->id;
-	else if (ret < 0)
-		goto err_clk;
-	snprintf(sport->name, PXA_NAME_LEN - 1, "UART%d", sport->port.line + 1);
-
-	sport->port.membase = ioremap(mmres->start, resource_size(mmres));
-	if (!sport->port.membase) {
-		ret = -ENOMEM;
-		goto err_clk;
-	}
-
-	serial_pxa_ports[sport->port.line] = sport;
-
-	uart_add_one_port(&serial_pxa_reg, &sport->port);
-	platform_set_drvdata(dev, sport);
-
-	return 0;
-
- err_clk:
-	clk_unprepare(sport->clk);
-	clk_put(sport->clk);
- err_free:
-	kfree(sport);
-	return ret;
-}
-
-static int serial_pxa_remove(struct platform_device *dev)
-{
-	struct uart_pxa_port *sport = platform_get_drvdata(dev);
-
-	uart_remove_one_port(&serial_pxa_reg, &sport->port);
-
-	clk_unprepare(sport->clk);
-	clk_put(sport->clk);
-	kfree(sport);
-
-	return 0;
-}
-
-static struct platform_driver serial_pxa_driver = {
-        .probe          = serial_pxa_probe,
-        .remove         = serial_pxa_remove,
-
-	.driver		= {
-	        .name	= "pxa2xx-uart",
-		.owner	= THIS_MODULE,
-#ifdef CONFIG_PM
-		.pm	= &serial_pxa_pm_ops,
-#endif
-		.of_match_table = serial_pxa_dt_ids,
-	},
-};
-
-static int __init serial_pxa_init(void)
-{
-	int ret;
-
-	ret = uart_register_driver(&serial_pxa_reg);
-	if (ret != 0)
-		return ret;
-
-	ret = platform_driver_register(&serial_pxa_driver);
-	if (ret != 0)
-		uart_unregister_driver(&serial_pxa_reg);
-
-	return ret;
-}
-
-static void __exit serial_pxa_exit(void)
-{
-	platform_driver_unregister(&serial_pxa_driver);
-	uart_unregister_driver(&serial_pxa_reg);
-}
-
-module_init(serial_pxa_init);
-module_exit(serial_pxa_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:pxa2xx-uart");
-- 
1.8.4.2


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

* [PATCH v3] serial: rewrite pxa2xx-uart to use 8250_core
@ 2013-12-09 11:38                         ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-09 11:38 UTC (permalink / raw)
  To: linux-kernel
  Cc: open list:OPEN FIRMWARE AND...,
	Heikki Krogerus, Russell King, James Cameron, Greg Kroah-Hartman,
	Rob Herring, Sergei Ianovich, Haojian Zhuang,
	open list:SERIAL DRIVERS, Grant Likely, Andrew Morton,
	John Crispin, Jiri Slaby, moderated list:ARM PORT, Zhou Zhu

pxa2xx-uart was a separate uart platform driver. It was declaring
the same device names and numbers as 8250 driver. As a result,
it was impossible to use 8250 driver on PXA SoCs.

Upon closer examination pxa2xx-uart turned out to be a clone of
8250_core driver.

Workaround for Erratum #19 according to Marvel(R) PXA270M Processor
Specification Update (April 19, 2010) is dropped. 8250_core reads
from FIFO immediately after checking DR bit in LSR.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Reviewed-by: James Cameron <quozl@laptop.org>
CC: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 changes v2..v3
 * remove devm_free/put as suggested by Heikki Krogerus
 * use SET_SYSTEM_SLEEP_PM_OPS macro to set pm ops as suggested
   by Heikki Krogerus

 changes v1..v2
 * actually implement workaround for E74 in dl_write as spooted
   by James Cameron
 * added comment about E19 in commit message

 arch/arm/configs/am200epdkit_defconfig    |   3 +-
 arch/arm/configs/cm_x2xx_defconfig        |   3 +-
 arch/arm/configs/cm_x300_defconfig        |   3 +-
 arch/arm/configs/colibri_pxa270_defconfig |   3 +-
 arch/arm/configs/colibri_pxa300_defconfig |   3 +-
 arch/arm/configs/corgi_defconfig          |   4 +-
 arch/arm/configs/em_x270_defconfig        |   3 +-
 arch/arm/configs/ezx_defconfig            |   3 +-
 arch/arm/configs/h5000_defconfig          |   3 +-
 arch/arm/configs/imote2_defconfig         |   3 +-
 arch/arm/configs/lpd270_defconfig         |   3 +-
 arch/arm/configs/lubbock_defconfig        |   3 +-
 arch/arm/configs/mainstone_defconfig      |   3 +-
 arch/arm/configs/mmp2_defconfig           |   3 +-
 arch/arm/configs/pcm027_defconfig         |   3 +-
 arch/arm/configs/pxa168_defconfig         |   3 +-
 arch/arm/configs/pxa255-idp_defconfig     |   3 +-
 arch/arm/configs/pxa3xx_defconfig         |   3 +-
 arch/arm/configs/pxa910_defconfig         |   3 +-
 arch/arm/configs/raumfeld_defconfig       |   3 +-
 arch/arm/configs/spitz_defconfig          |   4 +-
 arch/arm/configs/trizeps4_defconfig       |   3 +-
 arch/arm/configs/viper_defconfig          |   4 +-
 arch/arm/configs/xcep_defconfig           |   3 +-
 drivers/tty/serial/8250/8250_pxa.c        | 178 ++++++
 drivers/tty/serial/8250/Kconfig           |   9 +
 drivers/tty/serial/8250/Makefile          |   1 +
 drivers/tty/serial/Kconfig                |  23 -
 drivers/tty/serial/Makefile               |   1 -
 drivers/tty/serial/pxa.c                  | 971 ------------------------------
 30 files changed, 236 insertions(+), 1022 deletions(-)
 create mode 100644 drivers/tty/serial/8250/8250_pxa.c
 delete mode 100644 drivers/tty/serial/pxa.c

diff --git a/arch/arm/configs/am200epdkit_defconfig b/arch/arm/configs/am200epdkit_defconfig
index f0dea52..0cde234 100644
--- a/arch/arm/configs/am200epdkit_defconfig
+++ b/arch/arm/configs/am200epdkit_defconfig
@@ -60,8 +60,9 @@ CONFIG_BLK_DEV_IDECS=m
 CONFIG_NETDEVICES=y
 CONFIG_NET_ETHERNET=y
 CONFIG_SMC91X=m
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 # CONFIG_HWMON is not set
diff --git a/arch/arm/configs/cm_x2xx_defconfig b/arch/arm/configs/cm_x2xx_defconfig
index a93ff8d..b9fbe65 100644
--- a/arch/arm/configs/cm_x2xx_defconfig
+++ b/arch/arm/configs/cm_x2xx_defconfig
@@ -96,8 +96,9 @@ CONFIG_KEYBOARD_PXA27x=m
 CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_TOUCHSCREEN_UCB1400=m
 # CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_LEGACY_PTY_COUNT=16
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/cm_x300_defconfig b/arch/arm/configs/cm_x300_defconfig
index f4b7672..53a82ae 100644
--- a/arch/arm/configs/cm_x300_defconfig
+++ b/arch/arm/configs/cm_x300_defconfig
@@ -80,8 +80,9 @@ CONFIG_TOUCHSCREEN_WM97XX=m
 # CONFIG_TOUCHSCREEN_WM9713 is not set
 # CONFIG_SERIO is not set
 # CONFIG_LEGACY_PTYS is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
 CONFIG_I2C_PXA=y
diff --git a/arch/arm/configs/colibri_pxa270_defconfig b/arch/arm/configs/colibri_pxa270_defconfig
index 2ef2c5e..1ce0409 100644
--- a/arch/arm/configs/colibri_pxa270_defconfig
+++ b/arch/arm/configs/colibri_pxa270_defconfig
@@ -103,8 +103,9 @@ CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=m
 CONFIG_SERIO_LIBPS2=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_HW_RANDOM=y
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
diff --git a/arch/arm/configs/colibri_pxa300_defconfig b/arch/arm/configs/colibri_pxa300_defconfig
index b985334..f96bda0 100644
--- a/arch/arm/configs/colibri_pxa300_defconfig
+++ b/arch/arm/configs/colibri_pxa300_defconfig
@@ -31,8 +31,9 @@ CONFIG_INPUT_EVDEV=y
 # CONFIG_INPUT_MOUSE is not set
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_GPIO_ROTARY_ENCODER=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_HW_RANDOM=y
 CONFIG_DEBUG_GPIO=y
 # CONFIG_HWMON is not set
diff --git a/arch/arm/configs/corgi_defconfig b/arch/arm/configs/corgi_defconfig
index 1fd1d1d..bb4842d 100644
--- a/arch/arm/configs/corgi_defconfig
+++ b/arch/arm/configs/corgi_defconfig
@@ -131,10 +131,10 @@ CONFIG_TOUCHSCREEN_ADS7846=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=m
 # CONFIG_SERIO is not set
-CONFIG_SERIAL_8250=m
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_CS=m
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 CONFIG_I2C=y
 CONFIG_I2C_PXA=y
diff --git a/arch/arm/configs/em_x270_defconfig b/arch/arm/configs/em_x270_defconfig
index 60a21e0..ec0ec54 100644
--- a/arch/arm/configs/em_x270_defconfig
+++ b/arch/arm/configs/em_x270_defconfig
@@ -90,8 +90,9 @@ CONFIG_TOUCHSCREEN_WM97XX=m
 # CONFIG_TOUCHSCREEN_WM9705 is not set
 # CONFIG_TOUCHSCREEN_WM9713 is not set
 # CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_LEGACY_PTY_COUNT=16
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/ezx_defconfig b/arch/arm/configs/ezx_defconfig
index d95763d..631e2ec 100644
--- a/arch/arm/configs/ezx_defconfig
+++ b/arch/arm/configs/ezx_defconfig
@@ -215,8 +215,9 @@ CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=y
 CONFIG_INPUT_PCAP=y
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_LEGACY_PTY_COUNT=8
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/h5000_defconfig b/arch/arm/configs/h5000_defconfig
index 37903e3..655b735 100644
--- a/arch/arm/configs/h5000_defconfig
+++ b/arch/arm/configs/h5000_defconfig
@@ -47,8 +47,9 @@ CONFIG_MTD_PHYSMAP=y
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_LEGACY_PTY_COUNT=32
 # CONFIG_HW_RANDOM is not set
 # CONFIG_HWMON is not set
diff --git a/arch/arm/configs/imote2_defconfig b/arch/arm/configs/imote2_defconfig
index fd996bb..49d45e9 100644
--- a/arch/arm/configs/imote2_defconfig
+++ b/arch/arm/configs/imote2_defconfig
@@ -193,8 +193,9 @@ CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=y
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_LEGACY_PTY_COUNT=8
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/lpd270_defconfig b/arch/arm/configs/lpd270_defconfig
index 1c8c9ee..c3927b6 100644
--- a/arch/arm/configs/lpd270_defconfig
+++ b/arch/arm/configs/lpd270_defconfig
@@ -38,8 +38,9 @@ CONFIG_SMC91X=y
 CONFIG_INPUT_EVDEV=y
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_HW_RANDOM is not set
 CONFIG_FB=y
 CONFIG_FB_PXA=y
diff --git a/arch/arm/configs/lubbock_defconfig b/arch/arm/configs/lubbock_defconfig
index c4ba274..c8b0436 100644
--- a/arch/arm/configs/lubbock_defconfig
+++ b/arch/arm/configs/lubbock_defconfig
@@ -37,8 +37,9 @@ CONFIG_PCMCIA_PCNET=y
 CONFIG_INPUT_EVDEV=y
 # CONFIG_SERIO_SERPORT is not set
 CONFIG_SERIO_SA1111=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_USB_GADGET=y
 CONFIG_USB_G_SERIAL=m
diff --git a/arch/arm/configs/mainstone_defconfig b/arch/arm/configs/mainstone_defconfig
index 04efa1b..768892c 100644
--- a/arch/arm/configs/mainstone_defconfig
+++ b/arch/arm/configs/mainstone_defconfig
@@ -34,8 +34,9 @@ CONFIG_SMC91X=y
 CONFIG_INPUT_EVDEV=y
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_FB=y
 CONFIG_FB_PXA=y
 # CONFIG_VGA_CONSOLE is not set
diff --git a/arch/arm/configs/mmp2_defconfig b/arch/arm/configs/mmp2_defconfig
index f1cb95e..1ced9df 100644
--- a/arch/arm/configs/mmp2_defconfig
+++ b/arch/arm/configs/mmp2_defconfig
@@ -44,8 +44,9 @@ CONFIG_SMC91X=y
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/pcm027_defconfig b/arch/arm/configs/pcm027_defconfig
index 2f136c3..1280128 100644
--- a/arch/arm/configs/pcm027_defconfig
+++ b/arch/arm/configs/pcm027_defconfig
@@ -60,8 +60,9 @@ CONFIG_SMC91X=y
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/pxa168_defconfig b/arch/arm/configs/pxa168_defconfig
index 74d7e01..1668dac 100644
--- a/arch/arm/configs/pxa168_defconfig
+++ b/arch/arm/configs/pxa168_defconfig
@@ -40,8 +40,9 @@ CONFIG_SMC91X=y
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 # CONFIG_HWMON is not set
diff --git a/arch/arm/configs/pxa255-idp_defconfig b/arch/arm/configs/pxa255-idp_defconfig
index 917a070..399a706 100644
--- a/arch/arm/configs/pxa255-idp_defconfig
+++ b/arch/arm/configs/pxa255-idp_defconfig
@@ -35,8 +35,9 @@ CONFIG_SMC91X=y
 CONFIG_INPUT_EVDEV=y
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_FB=y
 CONFIG_FB_PXA=y
 # CONFIG_VGA_CONSOLE is not set
diff --git a/arch/arm/configs/pxa3xx_defconfig b/arch/arm/configs/pxa3xx_defconfig
index 60e3138..7c3e052 100644
--- a/arch/arm/configs/pxa3xx_defconfig
+++ b/arch/arm/configs/pxa3xx_defconfig
@@ -56,8 +56,9 @@ CONFIG_KEYBOARD_PXA27x=y
 CONFIG_KEYBOARD_PXA930_ROTARY=y
 CONFIG_MOUSE_PXA930_TRKBALL=y
 CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/pxa910_defconfig b/arch/arm/configs/pxa910_defconfig
index 3bb7771..cdacfcb 100644
--- a/arch/arm/configs/pxa910_defconfig
+++ b/arch/arm/configs/pxa910_defconfig
@@ -40,8 +40,9 @@ CONFIG_SMC91X=y
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_SPI=y
 CONFIG_FB=y
 CONFIG_MMP_DISP=y
diff --git a/arch/arm/configs/raumfeld_defconfig b/arch/arm/configs/raumfeld_defconfig
index f7caa90..f1e16f2 100644
--- a/arch/arm/configs/raumfeld_defconfig
+++ b/arch/arm/configs/raumfeld_defconfig
@@ -67,8 +67,9 @@ CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_TOUCHSCREEN_EETI=m
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_GPIO_ROTARY_ENCODER=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_HW_RANDOM=y
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
diff --git a/arch/arm/configs/spitz_defconfig b/arch/arm/configs/spitz_defconfig
index 2e0419d..b6efcf5 100644
--- a/arch/arm/configs/spitz_defconfig
+++ b/arch/arm/configs/spitz_defconfig
@@ -128,10 +128,10 @@ CONFIG_TOUCHSCREEN_ADS7846=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=m
 # CONFIG_SERIO is not set
-CONFIG_SERIAL_8250=m
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_CS=m
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 CONFIG_SPI=y
 CONFIG_SPI_PXA2XX=y
diff --git a/arch/arm/configs/trizeps4_defconfig b/arch/arm/configs/trizeps4_defconfig
index 3162173..453c79c 100644
--- a/arch/arm/configs/trizeps4_defconfig
+++ b/arch/arm/configs/trizeps4_defconfig
@@ -132,8 +132,9 @@ CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=m
 CONFIG_SERIO_LIBPS2=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_HW_RANDOM=y
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
diff --git a/arch/arm/configs/viper_defconfig b/arch/arm/configs/viper_defconfig
index d36e0d3..4efac06 100644
--- a/arch/arm/configs/viper_defconfig
+++ b/arch/arm/configs/viper_defconfig
@@ -101,11 +101,11 @@ CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=m
 # CONFIG_CONSOLE_TRANSLATIONS is not set
 # CONFIG_VT_CONSOLE is not set
-CONFIG_SERIAL_8250=m
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_NR_UARTS=5
 CONFIG_SERIAL_8250_RUNTIME_UARTS=5
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
diff --git a/arch/arm/configs/xcep_defconfig b/arch/arm/configs/xcep_defconfig
index 721832f..b67aeaf 100644
--- a/arch/arm/configs/xcep_defconfig
+++ b/arch/arm/configs/xcep_defconfig
@@ -60,8 +60,9 @@ CONFIG_NET_ETHERNET=y
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
 # CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=m
diff --git a/drivers/tty/serial/8250/8250_pxa.c b/drivers/tty/serial/8250/8250_pxa.c
new file mode 100644
index 0000000..0da0d40
--- /dev/null
+++ b/drivers/tty/serial/8250/8250_pxa.c
@@ -0,0 +1,178 @@
+/*
+ *  drivers/tty/serial/8250/8250_pxa.c -- driver for PXA on-board UARTS
+ *  Copyright:	(C) 2013 Sergei Ianovich <ynvich@gmail.com>
+ *
+ *  replaces drivers/serial/pxa.c by Nicolas Pitre
+ *  Created:	Feb 20, 2003
+ *  Copyright:	(C) 2003 Monta Vista Software, Inc.
+ *
+ *  Based on drivers/serial/8250.c by Russell King.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/serial_8250.h>
+#include <linux/serial_core.h>
+#include <linux/serial_reg.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
+#include <linux/pm_runtime.h>
+
+#include "8250.h"
+
+struct pxa8250_data {
+	int			line;
+	struct clk		*clk;
+};
+
+#ifdef CONFIG_PM
+static int serial_pxa_suspend(struct device *dev)
+{
+	struct pxa8250_data *data = dev_get_drvdata(dev);
+
+	serial8250_suspend_port(data->line);
+
+	return 0;
+}
+
+static int serial_pxa_resume(struct device *dev)
+{
+	struct pxa8250_data *data = dev_get_drvdata(dev);
+
+	serial8250_resume_port(data->line);
+
+	return 0;
+}
+#endif
+
+static const struct dev_pm_ops serial_pxa_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(serial_pxa_suspend, serial_pxa_resume)
+};
+
+static struct of_device_id serial_pxa_dt_ids[] = {
+	{ .compatible = "mrvl,pxa-uart", },
+	{ .compatible = "mrvl,mmp-uart", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, serial_pxa_dt_ids);
+
+/* Uart divisor latch write */
+static void serial_pxa_dl_write(struct uart_8250_port *up, int value)
+{
+	unsigned int dll;
+
+	serial_out(up, UART_DLL, value & 0xff);
+	/*
+	 * work around Erratum #74 according to Marvel(R) PXA270M Processor
+	 * Specification Update (April 19, 2010)
+	 */
+	dll = serial_in(up, UART_DLL);
+	WARN_ON(dll != (value & 0xff));
+
+	serial_out(up, UART_DLM, value >> 8 & 0xff);
+}
+
+
+static void serial_pxa_pm(struct uart_port *port, unsigned int state,
+	      unsigned int oldstate)
+{
+	struct pxa8250_data *data = port->private_data;
+
+	if (!state)
+		clk_prepare_enable(data->clk);
+	else
+		clk_disable_unprepare(data->clk);
+}
+
+static int serial_pxa_probe(struct platform_device *pdev)
+{
+	struct uart_8250_port uart = {};
+	struct pxa8250_data *data;
+	struct resource *mmres, *irqres;
+	int ret;
+
+	mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	irqres = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!mmres || !irqres)
+		return -ENODEV;
+
+	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(data->clk))
+		return PTR_ERR(data->clk);
+
+	ret = clk_prepare(data->clk);
+	if (ret)
+		return ret;
+
+	uart.port.type = PORT_XSCALE;
+	uart.port.iotype = UPIO_MEM32;
+	uart.port.mapbase = mmres->start;
+	uart.port.regshift = 2;
+	uart.port.irq = irqres->start;
+	uart.port.fifosize = 64;
+	uart.port.flags = UPF_IOREMAP | UPF_SKIP_TEST;
+	uart.port.dev = &pdev->dev;
+	uart.port.uartclk = clk_get_rate(data->clk);
+	uart.port.pm = serial_pxa_pm;
+	uart.port.private_data = data;
+	uart.dl_write = serial_pxa_dl_write;
+
+	ret = serial8250_register_8250_port(&uart);
+	if (ret < 0)
+		goto err_clk;
+
+	data->line = ret;
+
+	platform_set_drvdata(pdev, data);
+
+	return 0;
+
+ err_clk:
+	clk_unprepare(data->clk);
+	return ret;
+}
+
+static int serial_pxa_remove(struct platform_device *pdev)
+{
+	struct pxa8250_data *data = platform_get_drvdata(pdev);
+
+	serial8250_unregister_port(data->line);
+
+	clk_unprepare(data->clk);
+
+	return 0;
+}
+
+static struct platform_driver serial_pxa_driver = {
+	.probe          = serial_pxa_probe,
+	.remove         = serial_pxa_remove,
+
+	.driver		= {
+		.name	= "pxa2xx-uart",
+		.owner	= THIS_MODULE,
+		.pm	= &serial_pxa_pm_ops,
+		.of_match_table = serial_pxa_dt_ids,
+	},
+};
+
+module_platform_driver(serial_pxa_driver);
+
+MODULE_AUTHOR("Sergei Ianovich");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:pxa2xx-uart");
diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
index 2332991..81bd7c9 100644
--- a/drivers/tty/serial/8250/Kconfig
+++ b/drivers/tty/serial/8250/Kconfig
@@ -302,3 +302,12 @@ config SERIAL_8250_RT288X
 	  If you have a Ralink RT288x/RT305x SoC based board and want to use the
 	  serial port, say Y to this option. The driver can handle up to 2 serial
 	  ports. If unsure, say N.
+
+config SERIAL_PXA
+	tristate "PXA serial port support"
+	depends on SERIAL_8250 && (ARCH_PXA || ARCH_MMP)
+	help
+	  If you have a machine based on an Intel XScale PXA2xx CPU you
+	  can enable its onboard serial ports by enabling this option.
+
+	  If you choose M here, the module name will be 8250_pxa.
diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile
index 36d68d0..b7d1b61 100644
--- a/drivers/tty/serial/8250/Makefile
+++ b/drivers/tty/serial/8250/Makefile
@@ -20,3 +20,4 @@ obj-$(CONFIG_SERIAL_8250_HUB6)		+= 8250_hub6.o
 obj-$(CONFIG_SERIAL_8250_FSL)		+= 8250_fsl.o
 obj-$(CONFIG_SERIAL_8250_DW)		+= 8250_dw.o
 obj-$(CONFIG_SERIAL_8250_EM)		+= 8250_em.o
+obj-$(CONFIG_SERIAL_PXA)		+= 8250_pxa.o
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index a3817ab..2ad7184b 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -396,29 +396,6 @@ config SERIAL_MPSC_CONSOLE
 	help
 	  Say Y here if you want to support a serial console on a Marvell MPSC.
 
-config SERIAL_PXA
-	bool "PXA serial port support"
-	depends on ARCH_PXA || ARCH_MMP
-	select SERIAL_CORE
-	help
-	  If you have a machine based on an Intel XScale PXA2xx CPU you
-	  can enable its onboard serial ports by enabling this option.
-
-config SERIAL_PXA_CONSOLE
-	bool "Console on PXA serial port"
-	depends on SERIAL_PXA
-	select SERIAL_CORE_CONSOLE
-	help
-	  If you have enabled the serial port on the Intel XScale PXA
-	  CPU you can make it the console by answering Y to this option.
-
-	  Even if you say Y here, the currently visible virtual console
-	  (/dev/tty0) will still be used as the system console by default, but
-	  you can alter that using a kernel command line option such as
-	  "console=ttySA0". (Try "man bootparam" or see the documentation of
-	  your boot loader (lilo or loadlin) about how to pass options to the
-	  kernel at boot time.)
-
 config SERIAL_SA1100
 	bool "SA1100 serial port support"
 	depends on ARCH_SA1100
diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile
index 3068c77..4ac337b 100644
--- a/drivers/tty/serial/Makefile
+++ b/drivers/tty/serial/Makefile
@@ -20,7 +20,6 @@ obj-$(CONFIG_SERIAL_8250) += 8250/
 obj-$(CONFIG_SERIAL_AMBA_PL010) += amba-pl010.o
 obj-$(CONFIG_SERIAL_AMBA_PL011) += amba-pl011.o
 obj-$(CONFIG_SERIAL_CLPS711X) += clps711x.o
-obj-$(CONFIG_SERIAL_PXA) += pxa.o
 obj-$(CONFIG_SERIAL_PNX8XXX) += pnx8xxx_uart.o
 obj-$(CONFIG_SERIAL_SA1100) += sa1100.o
 obj-$(CONFIG_SERIAL_BCM63XX) += bcm63xx_uart.o
diff --git a/drivers/tty/serial/pxa.c b/drivers/tty/serial/pxa.c
deleted file mode 100644
index f9f20f3..0000000
--- a/drivers/tty/serial/pxa.c
+++ /dev/null
@@ -1,971 +0,0 @@
-/*
- *  Based on drivers/serial/8250.c by Russell King.
- *
- *  Author:	Nicolas Pitre
- *  Created:	Feb 20, 2003
- *  Copyright:	(C) 2003 Monta Vista Software, Inc.
- *
- * 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.
- *
- * Note 1: This driver is made separate from the already too overloaded
- * 8250.c because it needs some kirks of its own and that'll make it
- * easier to add DMA support.
- *
- * Note 2: I'm too sick of device allocation policies for serial ports.
- * If someone else wants to request an "official" allocation of major/minor
- * for this driver please be my guest.  And don't forget that new hardware
- * to come from Intel might have more than 3 or 4 of those UARTs.  Let's
- * hope for a better port registration and dynamic device allocation scheme
- * with the serial core maintainer satisfaction to appear soon.
- */
-
-
-#if defined(CONFIG_SERIAL_PXA_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-#define SUPPORT_SYSRQ
-#endif
-
-#include <linux/module.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-#include <linux/console.h>
-#include <linux/sysrq.h>
-#include <linux/serial_reg.h>
-#include <linux/circ_buf.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/of.h>
-#include <linux/platform_device.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/serial_core.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-
-#define PXA_NAME_LEN		8
-
-struct uart_pxa_port {
-	struct uart_port        port;
-	unsigned char           ier;
-	unsigned char           lcr;
-	unsigned char           mcr;
-	unsigned int            lsr_break_flag;
-	struct clk		*clk;
-	char			name[PXA_NAME_LEN];
-};
-
-static inline unsigned int serial_in(struct uart_pxa_port *up, int offset)
-{
-	offset <<= 2;
-	return readl(up->port.membase + offset);
-}
-
-static inline void serial_out(struct uart_pxa_port *up, int offset, int value)
-{
-	offset <<= 2;
-	writel(value, up->port.membase + offset);
-}
-
-static void serial_pxa_enable_ms(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	up->ier |= UART_IER_MSI;
-	serial_out(up, UART_IER, up->ier);
-}
-
-static void serial_pxa_stop_tx(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	if (up->ier & UART_IER_THRI) {
-		up->ier &= ~UART_IER_THRI;
-		serial_out(up, UART_IER, up->ier);
-	}
-}
-
-static void serial_pxa_stop_rx(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	up->ier &= ~UART_IER_RLSI;
-	up->port.read_status_mask &= ~UART_LSR_DR;
-	serial_out(up, UART_IER, up->ier);
-}
-
-static inline void receive_chars(struct uart_pxa_port *up, int *status)
-{
-	unsigned int ch, flag;
-	int max_count = 256;
-
-	do {
-		/* work around Errata #20 according to
-		 * Intel(R) PXA27x Processor Family
-		 * Specification Update (May 2005)
-		 *
-		 * Step 2
-		 * Disable the Reciever Time Out Interrupt via IER[RTOEI]
-		 */
-		up->ier &= ~UART_IER_RTOIE;
-		serial_out(up, UART_IER, up->ier);
-
-		ch = serial_in(up, UART_RX);
-		flag = TTY_NORMAL;
-		up->port.icount.rx++;
-
-		if (unlikely(*status & (UART_LSR_BI | UART_LSR_PE |
-				       UART_LSR_FE | UART_LSR_OE))) {
-			/*
-			 * For statistics only
-			 */
-			if (*status & UART_LSR_BI) {
-				*status &= ~(UART_LSR_FE | UART_LSR_PE);
-				up->port.icount.brk++;
-				/*
-				 * We do the SysRQ and SAK checking
-				 * here because otherwise the break
-				 * may get masked by ignore_status_mask
-				 * or read_status_mask.
-				 */
-				if (uart_handle_break(&up->port))
-					goto ignore_char;
-			} else if (*status & UART_LSR_PE)
-				up->port.icount.parity++;
-			else if (*status & UART_LSR_FE)
-				up->port.icount.frame++;
-			if (*status & UART_LSR_OE)
-				up->port.icount.overrun++;
-
-			/*
-			 * Mask off conditions which should be ignored.
-			 */
-			*status &= up->port.read_status_mask;
-
-#ifdef CONFIG_SERIAL_PXA_CONSOLE
-			if (up->port.line == up->port.cons->index) {
-				/* Recover the break flag from console xmit */
-				*status |= up->lsr_break_flag;
-				up->lsr_break_flag = 0;
-			}
-#endif
-			if (*status & UART_LSR_BI) {
-				flag = TTY_BREAK;
-			} else if (*status & UART_LSR_PE)
-				flag = TTY_PARITY;
-			else if (*status & UART_LSR_FE)
-				flag = TTY_FRAME;
-		}
-
-		if (uart_handle_sysrq_char(&up->port, ch))
-			goto ignore_char;
-
-		uart_insert_char(&up->port, *status, UART_LSR_OE, ch, flag);
-
-	ignore_char:
-		*status = serial_in(up, UART_LSR);
-	} while ((*status & UART_LSR_DR) && (max_count-- > 0));
-	tty_flip_buffer_push(&up->port.state->port);
-
-	/* work around Errata #20 according to
-	 * Intel(R) PXA27x Processor Family
-	 * Specification Update (May 2005)
-	 *
-	 * Step 6:
-	 * No more data in FIFO: Re-enable RTO interrupt via IER[RTOIE]
-	 */
-	up->ier |= UART_IER_RTOIE;
-	serial_out(up, UART_IER, up->ier);
-}
-
-static void transmit_chars(struct uart_pxa_port *up)
-{
-	struct circ_buf *xmit = &up->port.state->xmit;
-	int count;
-
-	if (up->port.x_char) {
-		serial_out(up, UART_TX, up->port.x_char);
-		up->port.icount.tx++;
-		up->port.x_char = 0;
-		return;
-	}
-	if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) {
-		serial_pxa_stop_tx(&up->port);
-		return;
-	}
-
-	count = up->port.fifosize / 2;
-	do {
-		serial_out(up, UART_TX, xmit->buf[xmit->tail]);
-		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
-		up->port.icount.tx++;
-		if (uart_circ_empty(xmit))
-			break;
-	} while (--count > 0);
-
-	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
-		uart_write_wakeup(&up->port);
-
-
-	if (uart_circ_empty(xmit))
-		serial_pxa_stop_tx(&up->port);
-}
-
-static void serial_pxa_start_tx(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	if (!(up->ier & UART_IER_THRI)) {
-		up->ier |= UART_IER_THRI;
-		serial_out(up, UART_IER, up->ier);
-	}
-}
-
-static inline void check_modem_status(struct uart_pxa_port *up)
-{
-	int status;
-
-	status = serial_in(up, UART_MSR);
-
-	if ((status & UART_MSR_ANY_DELTA) == 0)
-		return;
-
-	if (status & UART_MSR_TERI)
-		up->port.icount.rng++;
-	if (status & UART_MSR_DDSR)
-		up->port.icount.dsr++;
-	if (status & UART_MSR_DDCD)
-		uart_handle_dcd_change(&up->port, status & UART_MSR_DCD);
-	if (status & UART_MSR_DCTS)
-		uart_handle_cts_change(&up->port, status & UART_MSR_CTS);
-
-	wake_up_interruptible(&up->port.state->port.delta_msr_wait);
-}
-
-/*
- * This handles the interrupt from one port.
- */
-static inline irqreturn_t serial_pxa_irq(int irq, void *dev_id)
-{
-	struct uart_pxa_port *up = dev_id;
-	unsigned int iir, lsr;
-
-	iir = serial_in(up, UART_IIR);
-	if (iir & UART_IIR_NO_INT)
-		return IRQ_NONE;
-	lsr = serial_in(up, UART_LSR);
-	if (lsr & UART_LSR_DR)
-		receive_chars(up, &lsr);
-	check_modem_status(up);
-	if (lsr & UART_LSR_THRE)
-		transmit_chars(up);
-	return IRQ_HANDLED;
-}
-
-static unsigned int serial_pxa_tx_empty(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned long flags;
-	unsigned int ret;
-
-	spin_lock_irqsave(&up->port.lock, flags);
-	ret = serial_in(up, UART_LSR) & UART_LSR_TEMT ? TIOCSER_TEMT : 0;
-	spin_unlock_irqrestore(&up->port.lock, flags);
-
-	return ret;
-}
-
-static unsigned int serial_pxa_get_mctrl(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned char status;
-	unsigned int ret;
-
-	status = serial_in(up, UART_MSR);
-
-	ret = 0;
-	if (status & UART_MSR_DCD)
-		ret |= TIOCM_CAR;
-	if (status & UART_MSR_RI)
-		ret |= TIOCM_RNG;
-	if (status & UART_MSR_DSR)
-		ret |= TIOCM_DSR;
-	if (status & UART_MSR_CTS)
-		ret |= TIOCM_CTS;
-	return ret;
-}
-
-static void serial_pxa_set_mctrl(struct uart_port *port, unsigned int mctrl)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned char mcr = 0;
-
-	if (mctrl & TIOCM_RTS)
-		mcr |= UART_MCR_RTS;
-	if (mctrl & TIOCM_DTR)
-		mcr |= UART_MCR_DTR;
-	if (mctrl & TIOCM_OUT1)
-		mcr |= UART_MCR_OUT1;
-	if (mctrl & TIOCM_OUT2)
-		mcr |= UART_MCR_OUT2;
-	if (mctrl & TIOCM_LOOP)
-		mcr |= UART_MCR_LOOP;
-
-	mcr |= up->mcr;
-
-	serial_out(up, UART_MCR, mcr);
-}
-
-static void serial_pxa_break_ctl(struct uart_port *port, int break_state)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned long flags;
-
-	spin_lock_irqsave(&up->port.lock, flags);
-	if (break_state == -1)
-		up->lcr |= UART_LCR_SBC;
-	else
-		up->lcr &= ~UART_LCR_SBC;
-	serial_out(up, UART_LCR, up->lcr);
-	spin_unlock_irqrestore(&up->port.lock, flags);
-}
-
-static int serial_pxa_startup(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned long flags;
-	int retval;
-
-	if (port->line == 3) /* HWUART */
-		up->mcr |= UART_MCR_AFE;
-	else
-		up->mcr = 0;
-
-	up->port.uartclk = clk_get_rate(up->clk);
-
-	/*
-	 * Allocate the IRQ
-	 */
-	retval = request_irq(up->port.irq, serial_pxa_irq, 0, up->name, up);
-	if (retval)
-		return retval;
-
-	/*
-	 * Clear the FIFO buffers and disable them.
-	 * (they will be reenabled in set_termios())
-	 */
-	serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO);
-	serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO |
-			UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
-	serial_out(up, UART_FCR, 0);
-
-	/*
-	 * Clear the interrupt registers.
-	 */
-	(void) serial_in(up, UART_LSR);
-	(void) serial_in(up, UART_RX);
-	(void) serial_in(up, UART_IIR);
-	(void) serial_in(up, UART_MSR);
-
-	/*
-	 * Now, initialize the UART
-	 */
-	serial_out(up, UART_LCR, UART_LCR_WLEN8);
-
-	spin_lock_irqsave(&up->port.lock, flags);
-	up->port.mctrl |= TIOCM_OUT2;
-	serial_pxa_set_mctrl(&up->port, up->port.mctrl);
-	spin_unlock_irqrestore(&up->port.lock, flags);
-
-	/*
-	 * Finally, enable interrupts.  Note: Modem status interrupts
-	 * are set via set_termios(), which will be occurring imminently
-	 * anyway, so we don't enable them here.
-	 */
-	up->ier = UART_IER_RLSI | UART_IER_RDI | UART_IER_RTOIE | UART_IER_UUE;
-	serial_out(up, UART_IER, up->ier);
-
-	/*
-	 * And clear the interrupt registers again for luck.
-	 */
-	(void) serial_in(up, UART_LSR);
-	(void) serial_in(up, UART_RX);
-	(void) serial_in(up, UART_IIR);
-	(void) serial_in(up, UART_MSR);
-
-	return 0;
-}
-
-static void serial_pxa_shutdown(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned long flags;
-
-	free_irq(up->port.irq, up);
-
-	/*
-	 * Disable interrupts from this port
-	 */
-	up->ier = 0;
-	serial_out(up, UART_IER, 0);
-
-	spin_lock_irqsave(&up->port.lock, flags);
-	up->port.mctrl &= ~TIOCM_OUT2;
-	serial_pxa_set_mctrl(&up->port, up->port.mctrl);
-	spin_unlock_irqrestore(&up->port.lock, flags);
-
-	/*
-	 * Disable break condition and FIFOs
-	 */
-	serial_out(up, UART_LCR, serial_in(up, UART_LCR) & ~UART_LCR_SBC);
-	serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO |
-				  UART_FCR_CLEAR_RCVR |
-				  UART_FCR_CLEAR_XMIT);
-	serial_out(up, UART_FCR, 0);
-}
-
-static void
-serial_pxa_set_termios(struct uart_port *port, struct ktermios *termios,
-		       struct ktermios *old)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned char cval, fcr = 0;
-	unsigned long flags;
-	unsigned int baud, quot;
-	unsigned int dll;
-
-	switch (termios->c_cflag & CSIZE) {
-	case CS5:
-		cval = UART_LCR_WLEN5;
-		break;
-	case CS6:
-		cval = UART_LCR_WLEN6;
-		break;
-	case CS7:
-		cval = UART_LCR_WLEN7;
-		break;
-	default:
-	case CS8:
-		cval = UART_LCR_WLEN8;
-		break;
-	}
-
-	if (termios->c_cflag & CSTOPB)
-		cval |= UART_LCR_STOP;
-	if (termios->c_cflag & PARENB)
-		cval |= UART_LCR_PARITY;
-	if (!(termios->c_cflag & PARODD))
-		cval |= UART_LCR_EPAR;
-
-	/*
-	 * Ask the core to calculate the divisor for us.
-	 */
-	baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
-	quot = uart_get_divisor(port, baud);
-
-	if ((up->port.uartclk / quot) < (2400 * 16))
-		fcr = UART_FCR_ENABLE_FIFO | UART_FCR_PXAR1;
-	else if ((up->port.uartclk / quot) < (230400 * 16))
-		fcr = UART_FCR_ENABLE_FIFO | UART_FCR_PXAR8;
-	else
-		fcr = UART_FCR_ENABLE_FIFO | UART_FCR_PXAR32;
-
-	/*
-	 * Ok, we're now changing the port state.  Do it with
-	 * interrupts disabled.
-	 */
-	spin_lock_irqsave(&up->port.lock, flags);
-
-	/*
-	 * Ensure the port will be enabled.
-	 * This is required especially for serial console.
-	 */
-	up->ier |= UART_IER_UUE;
-
-	/*
-	 * Update the per-port timeout.
-	 */
-	uart_update_timeout(port, termios->c_cflag, baud);
-
-	up->port.read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;
-	if (termios->c_iflag & INPCK)
-		up->port.read_status_mask |= UART_LSR_FE | UART_LSR_PE;
-	if (termios->c_iflag & (BRKINT | PARMRK))
-		up->port.read_status_mask |= UART_LSR_BI;
-
-	/*
-	 * Characters to ignore
-	 */
-	up->port.ignore_status_mask = 0;
-	if (termios->c_iflag & IGNPAR)
-		up->port.ignore_status_mask |= UART_LSR_PE | UART_LSR_FE;
-	if (termios->c_iflag & IGNBRK) {
-		up->port.ignore_status_mask |= UART_LSR_BI;
-		/*
-		 * If we're ignoring parity and break indicators,
-		 * ignore overruns too (for real raw support).
-		 */
-		if (termios->c_iflag & IGNPAR)
-			up->port.ignore_status_mask |= UART_LSR_OE;
-	}
-
-	/*
-	 * ignore all characters if CREAD is not set
-	 */
-	if ((termios->c_cflag & CREAD) == 0)
-		up->port.ignore_status_mask |= UART_LSR_DR;
-
-	/*
-	 * CTS flow control flag and modem status interrupts
-	 */
-	up->ier &= ~UART_IER_MSI;
-	if (UART_ENABLE_MS(&up->port, termios->c_cflag))
-		up->ier |= UART_IER_MSI;
-
-	serial_out(up, UART_IER, up->ier);
-
-	if (termios->c_cflag & CRTSCTS)
-		up->mcr |= UART_MCR_AFE;
-	else
-		up->mcr &= ~UART_MCR_AFE;
-
-	serial_out(up, UART_LCR, cval | UART_LCR_DLAB);	/* set DLAB */
-	serial_out(up, UART_DLL, quot & 0xff);		/* LS of divisor */
-
-	/*
-	 * work around Errata #75 according to Intel(R) PXA27x Processor Family
-	 * Specification Update (Nov 2005)
-	 */
-	dll = serial_in(up, UART_DLL);
-	WARN_ON(dll != (quot & 0xff));
-
-	serial_out(up, UART_DLM, quot >> 8);		/* MS of divisor */
-	serial_out(up, UART_LCR, cval);			/* reset DLAB */
-	up->lcr = cval;					/* Save LCR */
-	serial_pxa_set_mctrl(&up->port, up->port.mctrl);
-	serial_out(up, UART_FCR, fcr);
-	spin_unlock_irqrestore(&up->port.lock, flags);
-}
-
-static void
-serial_pxa_pm(struct uart_port *port, unsigned int state,
-	      unsigned int oldstate)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	if (!state)
-		clk_prepare_enable(up->clk);
-	else
-		clk_disable_unprepare(up->clk);
-}
-
-static void serial_pxa_release_port(struct uart_port *port)
-{
-}
-
-static int serial_pxa_request_port(struct uart_port *port)
-{
-	return 0;
-}
-
-static void serial_pxa_config_port(struct uart_port *port, int flags)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	up->port.type = PORT_PXA;
-}
-
-static int
-serial_pxa_verify_port(struct uart_port *port, struct serial_struct *ser)
-{
-	/* we don't want the core code to modify any port params */
-	return -EINVAL;
-}
-
-static const char *
-serial_pxa_type(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	return up->name;
-}
-
-static struct uart_pxa_port *serial_pxa_ports[4];
-static struct uart_driver serial_pxa_reg;
-
-#ifdef CONFIG_SERIAL_PXA_CONSOLE
-
-#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
-
-/*
- *	Wait for transmitter & holding register to empty
- */
-static inline void wait_for_xmitr(struct uart_pxa_port *up)
-{
-	unsigned int status, tmout = 10000;
-
-	/* Wait up to 10ms for the character(s) to be sent. */
-	do {
-		status = serial_in(up, UART_LSR);
-
-		if (status & UART_LSR_BI)
-			up->lsr_break_flag = UART_LSR_BI;
-
-		if (--tmout == 0)
-			break;
-		udelay(1);
-	} while ((status & BOTH_EMPTY) != BOTH_EMPTY);
-
-	/* Wait up to 1s for flow control if necessary */
-	if (up->port.flags & UPF_CONS_FLOW) {
-		tmout = 1000000;
-		while (--tmout &&
-		       ((serial_in(up, UART_MSR) & UART_MSR_CTS) == 0))
-			udelay(1);
-	}
-}
-
-static void serial_pxa_console_putchar(struct uart_port *port, int ch)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	wait_for_xmitr(up);
-	serial_out(up, UART_TX, ch);
-}
-
-/*
- * Print a string to the serial port trying not to disturb
- * any possible real use of the port...
- *
- *	The console_lock must be held when we get here.
- */
-static void
-serial_pxa_console_write(struct console *co, const char *s, unsigned int count)
-{
-	struct uart_pxa_port *up = serial_pxa_ports[co->index];
-	unsigned int ier;
-	unsigned long flags;
-	int locked = 1;
-
-	clk_enable(up->clk);
-	local_irq_save(flags);
-	if (up->port.sysrq)
-		locked = 0;
-	else if (oops_in_progress)
-		locked = spin_trylock(&up->port.lock);
-	else
-		spin_lock(&up->port.lock);
-
-	/*
-	 *	First save the IER then disable the interrupts
-	 */
-	ier = serial_in(up, UART_IER);
-	serial_out(up, UART_IER, UART_IER_UUE);
-
-	uart_console_write(&up->port, s, count, serial_pxa_console_putchar);
-
-	/*
-	 *	Finally, wait for transmitter to become empty
-	 *	and restore the IER
-	 */
-	wait_for_xmitr(up);
-	serial_out(up, UART_IER, ier);
-
-	if (locked)
-		spin_unlock(&up->port.lock);
-	local_irq_restore(flags);
-	clk_disable(up->clk);
-
-}
-
-#ifdef CONFIG_CONSOLE_POLL
-/*
- * Console polling routines for writing and reading from the uart while
- * in an interrupt or debug context.
- */
-
-static int serial_pxa_get_poll_char(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned char lsr = serial_in(up, UART_LSR);
-
-	while (!(lsr & UART_LSR_DR))
-		lsr = serial_in(up, UART_LSR);
-
-	return serial_in(up, UART_RX);
-}
-
-
-static void serial_pxa_put_poll_char(struct uart_port *port,
-			 unsigned char c)
-{
-	unsigned int ier;
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	/*
-	 *	First save the IER then disable the interrupts
-	 */
-	ier = serial_in(up, UART_IER);
-	serial_out(up, UART_IER, UART_IER_UUE);
-
-	wait_for_xmitr(up);
-	/*
-	 *	Send the character out.
-	 *	If a LF, also do CR...
-	 */
-	serial_out(up, UART_TX, c);
-	if (c == 10) {
-		wait_for_xmitr(up);
-		serial_out(up, UART_TX, 13);
-	}
-
-	/*
-	 *	Finally, wait for transmitter to become empty
-	 *	and restore the IER
-	 */
-	wait_for_xmitr(up);
-	serial_out(up, UART_IER, ier);
-}
-
-#endif /* CONFIG_CONSOLE_POLL */
-
-static int __init
-serial_pxa_console_setup(struct console *co, char *options)
-{
-	struct uart_pxa_port *up;
-	int baud = 9600;
-	int bits = 8;
-	int parity = 'n';
-	int flow = 'n';
-
-	if (co->index == -1 || co->index >= serial_pxa_reg.nr)
-		co->index = 0;
-	up = serial_pxa_ports[co->index];
-	if (!up)
-		return -ENODEV;
-
-	if (options)
-		uart_parse_options(options, &baud, &parity, &bits, &flow);
-
-	return uart_set_options(&up->port, co, baud, parity, bits, flow);
-}
-
-static struct console serial_pxa_console = {
-	.name		= "ttyS",
-	.write		= serial_pxa_console_write,
-	.device		= uart_console_device,
-	.setup		= serial_pxa_console_setup,
-	.flags		= CON_PRINTBUFFER,
-	.index		= -1,
-	.data		= &serial_pxa_reg,
-};
-
-#define PXA_CONSOLE	&serial_pxa_console
-#else
-#define PXA_CONSOLE	NULL
-#endif
-
-static struct uart_ops serial_pxa_pops = {
-	.tx_empty	= serial_pxa_tx_empty,
-	.set_mctrl	= serial_pxa_set_mctrl,
-	.get_mctrl	= serial_pxa_get_mctrl,
-	.stop_tx	= serial_pxa_stop_tx,
-	.start_tx	= serial_pxa_start_tx,
-	.stop_rx	= serial_pxa_stop_rx,
-	.enable_ms	= serial_pxa_enable_ms,
-	.break_ctl	= serial_pxa_break_ctl,
-	.startup	= serial_pxa_startup,
-	.shutdown	= serial_pxa_shutdown,
-	.set_termios	= serial_pxa_set_termios,
-	.pm		= serial_pxa_pm,
-	.type		= serial_pxa_type,
-	.release_port	= serial_pxa_release_port,
-	.request_port	= serial_pxa_request_port,
-	.config_port	= serial_pxa_config_port,
-	.verify_port	= serial_pxa_verify_port,
-#ifdef CONFIG_CONSOLE_POLL
-	.poll_get_char = serial_pxa_get_poll_char,
-	.poll_put_char = serial_pxa_put_poll_char,
-#endif
-};
-
-static struct uart_driver serial_pxa_reg = {
-	.owner		= THIS_MODULE,
-	.driver_name	= "PXA serial",
-	.dev_name	= "ttyS",
-	.major		= TTY_MAJOR,
-	.minor		= 64,
-	.nr		= 4,
-	.cons		= PXA_CONSOLE,
-};
-
-#ifdef CONFIG_PM
-static int serial_pxa_suspend(struct device *dev)
-{
-        struct uart_pxa_port *sport = dev_get_drvdata(dev);
-
-        if (sport)
-                uart_suspend_port(&serial_pxa_reg, &sport->port);
-
-        return 0;
-}
-
-static int serial_pxa_resume(struct device *dev)
-{
-        struct uart_pxa_port *sport = dev_get_drvdata(dev);
-
-        if (sport)
-                uart_resume_port(&serial_pxa_reg, &sport->port);
-
-        return 0;
-}
-
-static const struct dev_pm_ops serial_pxa_pm_ops = {
-	.suspend	= serial_pxa_suspend,
-	.resume		= serial_pxa_resume,
-};
-#endif
-
-static struct of_device_id serial_pxa_dt_ids[] = {
-	{ .compatible = "mrvl,pxa-uart", },
-	{ .compatible = "mrvl,mmp-uart", },
-	{}
-};
-MODULE_DEVICE_TABLE(of, serial_pxa_dt_ids);
-
-static int serial_pxa_probe_dt(struct platform_device *pdev,
-			       struct uart_pxa_port *sport)
-{
-	struct device_node *np = pdev->dev.of_node;
-	int ret;
-
-	if (!np)
-		return 1;
-
-	ret = of_alias_get_id(np, "serial");
-	if (ret < 0) {
-		dev_err(&pdev->dev, "failed to get alias id, errno %d\n", ret);
-		return ret;
-	}
-	sport->port.line = ret;
-	return 0;
-}
-
-static int serial_pxa_probe(struct platform_device *dev)
-{
-	struct uart_pxa_port *sport;
-	struct resource *mmres, *irqres;
-	int ret;
-
-	mmres = platform_get_resource(dev, IORESOURCE_MEM, 0);
-	irqres = platform_get_resource(dev, IORESOURCE_IRQ, 0);
-	if (!mmres || !irqres)
-		return -ENODEV;
-
-	sport = kzalloc(sizeof(struct uart_pxa_port), GFP_KERNEL);
-	if (!sport)
-		return -ENOMEM;
-
-	sport->clk = clk_get(&dev->dev, NULL);
-	if (IS_ERR(sport->clk)) {
-		ret = PTR_ERR(sport->clk);
-		goto err_free;
-	}
-
-	ret = clk_prepare(sport->clk);
-	if (ret) {
-		clk_put(sport->clk);
-		goto err_free;
-	}
-
-	sport->port.type = PORT_PXA;
-	sport->port.iotype = UPIO_MEM;
-	sport->port.mapbase = mmres->start;
-	sport->port.irq = irqres->start;
-	sport->port.fifosize = 64;
-	sport->port.ops = &serial_pxa_pops;
-	sport->port.dev = &dev->dev;
-	sport->port.flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF;
-	sport->port.uartclk = clk_get_rate(sport->clk);
-
-	ret = serial_pxa_probe_dt(dev, sport);
-	if (ret > 0)
-		sport->port.line = dev->id;
-	else if (ret < 0)
-		goto err_clk;
-	snprintf(sport->name, PXA_NAME_LEN - 1, "UART%d", sport->port.line + 1);
-
-	sport->port.membase = ioremap(mmres->start, resource_size(mmres));
-	if (!sport->port.membase) {
-		ret = -ENOMEM;
-		goto err_clk;
-	}
-
-	serial_pxa_ports[sport->port.line] = sport;
-
-	uart_add_one_port(&serial_pxa_reg, &sport->port);
-	platform_set_drvdata(dev, sport);
-
-	return 0;
-
- err_clk:
-	clk_unprepare(sport->clk);
-	clk_put(sport->clk);
- err_free:
-	kfree(sport);
-	return ret;
-}
-
-static int serial_pxa_remove(struct platform_device *dev)
-{
-	struct uart_pxa_port *sport = platform_get_drvdata(dev);
-
-	uart_remove_one_port(&serial_pxa_reg, &sport->port);
-
-	clk_unprepare(sport->clk);
-	clk_put(sport->clk);
-	kfree(sport);
-
-	return 0;
-}
-
-static struct platform_driver serial_pxa_driver = {
-        .probe          = serial_pxa_probe,
-        .remove         = serial_pxa_remove,
-
-	.driver		= {
-	        .name	= "pxa2xx-uart",
-		.owner	= THIS_MODULE,
-#ifdef CONFIG_PM
-		.pm	= &serial_pxa_pm_ops,
-#endif
-		.of_match_table = serial_pxa_dt_ids,
-	},
-};
-
-static int __init serial_pxa_init(void)
-{
-	int ret;
-
-	ret = uart_register_driver(&serial_pxa_reg);
-	if (ret != 0)
-		return ret;
-
-	ret = platform_driver_register(&serial_pxa_driver);
-	if (ret != 0)
-		uart_unregister_driver(&serial_pxa_reg);
-
-	return ret;
-}
-
-static void __exit serial_pxa_exit(void)
-{
-	platform_driver_unregister(&serial_pxa_driver);
-	uart_unregister_driver(&serial_pxa_reg);
-}
-
-module_init(serial_pxa_init);
-module_exit(serial_pxa_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:pxa2xx-uart");
-- 
1.8.4.2

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

* [PATCH v3] serial: rewrite pxa2xx-uart to use 8250_core
@ 2013-12-09 11:38                         ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-09 11:38 UTC (permalink / raw)
  To: linux-arm-kernel

pxa2xx-uart was a separate uart platform driver. It was declaring
the same device names and numbers as 8250 driver. As a result,
it was impossible to use 8250 driver on PXA SoCs.

Upon closer examination pxa2xx-uart turned out to be a clone of
8250_core driver.

Workaround for Erratum #19 according to Marvel(R) PXA270M Processor
Specification Update (April 19, 2010) is dropped. 8250_core reads
from FIFO immediately after checking DR bit in LSR.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Reviewed-by: James Cameron <quozl@laptop.org>
CC: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 changes v2..v3
 * remove devm_free/put as suggested by Heikki Krogerus
 * use SET_SYSTEM_SLEEP_PM_OPS macro to set pm ops as suggested
   by Heikki Krogerus

 changes v1..v2
 * actually implement workaround for E74 in dl_write as spooted
   by James Cameron
 * added comment about E19 in commit message

 arch/arm/configs/am200epdkit_defconfig    |   3 +-
 arch/arm/configs/cm_x2xx_defconfig        |   3 +-
 arch/arm/configs/cm_x300_defconfig        |   3 +-
 arch/arm/configs/colibri_pxa270_defconfig |   3 +-
 arch/arm/configs/colibri_pxa300_defconfig |   3 +-
 arch/arm/configs/corgi_defconfig          |   4 +-
 arch/arm/configs/em_x270_defconfig        |   3 +-
 arch/arm/configs/ezx_defconfig            |   3 +-
 arch/arm/configs/h5000_defconfig          |   3 +-
 arch/arm/configs/imote2_defconfig         |   3 +-
 arch/arm/configs/lpd270_defconfig         |   3 +-
 arch/arm/configs/lubbock_defconfig        |   3 +-
 arch/arm/configs/mainstone_defconfig      |   3 +-
 arch/arm/configs/mmp2_defconfig           |   3 +-
 arch/arm/configs/pcm027_defconfig         |   3 +-
 arch/arm/configs/pxa168_defconfig         |   3 +-
 arch/arm/configs/pxa255-idp_defconfig     |   3 +-
 arch/arm/configs/pxa3xx_defconfig         |   3 +-
 arch/arm/configs/pxa910_defconfig         |   3 +-
 arch/arm/configs/raumfeld_defconfig       |   3 +-
 arch/arm/configs/spitz_defconfig          |   4 +-
 arch/arm/configs/trizeps4_defconfig       |   3 +-
 arch/arm/configs/viper_defconfig          |   4 +-
 arch/arm/configs/xcep_defconfig           |   3 +-
 drivers/tty/serial/8250/8250_pxa.c        | 178 ++++++
 drivers/tty/serial/8250/Kconfig           |   9 +
 drivers/tty/serial/8250/Makefile          |   1 +
 drivers/tty/serial/Kconfig                |  23 -
 drivers/tty/serial/Makefile               |   1 -
 drivers/tty/serial/pxa.c                  | 971 ------------------------------
 30 files changed, 236 insertions(+), 1022 deletions(-)
 create mode 100644 drivers/tty/serial/8250/8250_pxa.c
 delete mode 100644 drivers/tty/serial/pxa.c

diff --git a/arch/arm/configs/am200epdkit_defconfig b/arch/arm/configs/am200epdkit_defconfig
index f0dea52..0cde234 100644
--- a/arch/arm/configs/am200epdkit_defconfig
+++ b/arch/arm/configs/am200epdkit_defconfig
@@ -60,8 +60,9 @@ CONFIG_BLK_DEV_IDECS=m
 CONFIG_NETDEVICES=y
 CONFIG_NET_ETHERNET=y
 CONFIG_SMC91X=m
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 # CONFIG_HWMON is not set
diff --git a/arch/arm/configs/cm_x2xx_defconfig b/arch/arm/configs/cm_x2xx_defconfig
index a93ff8d..b9fbe65 100644
--- a/arch/arm/configs/cm_x2xx_defconfig
+++ b/arch/arm/configs/cm_x2xx_defconfig
@@ -96,8 +96,9 @@ CONFIG_KEYBOARD_PXA27x=m
 CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_TOUCHSCREEN_UCB1400=m
 # CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_LEGACY_PTY_COUNT=16
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/cm_x300_defconfig b/arch/arm/configs/cm_x300_defconfig
index f4b7672..53a82ae 100644
--- a/arch/arm/configs/cm_x300_defconfig
+++ b/arch/arm/configs/cm_x300_defconfig
@@ -80,8 +80,9 @@ CONFIG_TOUCHSCREEN_WM97XX=m
 # CONFIG_TOUCHSCREEN_WM9713 is not set
 # CONFIG_SERIO is not set
 # CONFIG_LEGACY_PTYS is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
 CONFIG_I2C_PXA=y
diff --git a/arch/arm/configs/colibri_pxa270_defconfig b/arch/arm/configs/colibri_pxa270_defconfig
index 2ef2c5e..1ce0409 100644
--- a/arch/arm/configs/colibri_pxa270_defconfig
+++ b/arch/arm/configs/colibri_pxa270_defconfig
@@ -103,8 +103,9 @@ CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=m
 CONFIG_SERIO_LIBPS2=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_HW_RANDOM=y
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
diff --git a/arch/arm/configs/colibri_pxa300_defconfig b/arch/arm/configs/colibri_pxa300_defconfig
index b985334..f96bda0 100644
--- a/arch/arm/configs/colibri_pxa300_defconfig
+++ b/arch/arm/configs/colibri_pxa300_defconfig
@@ -31,8 +31,9 @@ CONFIG_INPUT_EVDEV=y
 # CONFIG_INPUT_MOUSE is not set
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_GPIO_ROTARY_ENCODER=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_HW_RANDOM=y
 CONFIG_DEBUG_GPIO=y
 # CONFIG_HWMON is not set
diff --git a/arch/arm/configs/corgi_defconfig b/arch/arm/configs/corgi_defconfig
index 1fd1d1d..bb4842d 100644
--- a/arch/arm/configs/corgi_defconfig
+++ b/arch/arm/configs/corgi_defconfig
@@ -131,10 +131,10 @@ CONFIG_TOUCHSCREEN_ADS7846=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=m
 # CONFIG_SERIO is not set
-CONFIG_SERIAL_8250=m
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_CS=m
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 CONFIG_I2C=y
 CONFIG_I2C_PXA=y
diff --git a/arch/arm/configs/em_x270_defconfig b/arch/arm/configs/em_x270_defconfig
index 60a21e0..ec0ec54 100644
--- a/arch/arm/configs/em_x270_defconfig
+++ b/arch/arm/configs/em_x270_defconfig
@@ -90,8 +90,9 @@ CONFIG_TOUCHSCREEN_WM97XX=m
 # CONFIG_TOUCHSCREEN_WM9705 is not set
 # CONFIG_TOUCHSCREEN_WM9713 is not set
 # CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_LEGACY_PTY_COUNT=16
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/ezx_defconfig b/arch/arm/configs/ezx_defconfig
index d95763d..631e2ec 100644
--- a/arch/arm/configs/ezx_defconfig
+++ b/arch/arm/configs/ezx_defconfig
@@ -215,8 +215,9 @@ CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=y
 CONFIG_INPUT_PCAP=y
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_LEGACY_PTY_COUNT=8
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/h5000_defconfig b/arch/arm/configs/h5000_defconfig
index 37903e3..655b735 100644
--- a/arch/arm/configs/h5000_defconfig
+++ b/arch/arm/configs/h5000_defconfig
@@ -47,8 +47,9 @@ CONFIG_MTD_PHYSMAP=y
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_LEGACY_PTY_COUNT=32
 # CONFIG_HW_RANDOM is not set
 # CONFIG_HWMON is not set
diff --git a/arch/arm/configs/imote2_defconfig b/arch/arm/configs/imote2_defconfig
index fd996bb..49d45e9 100644
--- a/arch/arm/configs/imote2_defconfig
+++ b/arch/arm/configs/imote2_defconfig
@@ -193,8 +193,9 @@ CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=y
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_LEGACY_PTY_COUNT=8
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/lpd270_defconfig b/arch/arm/configs/lpd270_defconfig
index 1c8c9ee..c3927b6 100644
--- a/arch/arm/configs/lpd270_defconfig
+++ b/arch/arm/configs/lpd270_defconfig
@@ -38,8 +38,9 @@ CONFIG_SMC91X=y
 CONFIG_INPUT_EVDEV=y
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_HW_RANDOM is not set
 CONFIG_FB=y
 CONFIG_FB_PXA=y
diff --git a/arch/arm/configs/lubbock_defconfig b/arch/arm/configs/lubbock_defconfig
index c4ba274..c8b0436 100644
--- a/arch/arm/configs/lubbock_defconfig
+++ b/arch/arm/configs/lubbock_defconfig
@@ -37,8 +37,9 @@ CONFIG_PCMCIA_PCNET=y
 CONFIG_INPUT_EVDEV=y
 # CONFIG_SERIO_SERPORT is not set
 CONFIG_SERIO_SA1111=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_USB_GADGET=y
 CONFIG_USB_G_SERIAL=m
diff --git a/arch/arm/configs/mainstone_defconfig b/arch/arm/configs/mainstone_defconfig
index 04efa1b..768892c 100644
--- a/arch/arm/configs/mainstone_defconfig
+++ b/arch/arm/configs/mainstone_defconfig
@@ -34,8 +34,9 @@ CONFIG_SMC91X=y
 CONFIG_INPUT_EVDEV=y
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_FB=y
 CONFIG_FB_PXA=y
 # CONFIG_VGA_CONSOLE is not set
diff --git a/arch/arm/configs/mmp2_defconfig b/arch/arm/configs/mmp2_defconfig
index f1cb95e..1ced9df 100644
--- a/arch/arm/configs/mmp2_defconfig
+++ b/arch/arm/configs/mmp2_defconfig
@@ -44,8 +44,9 @@ CONFIG_SMC91X=y
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/pcm027_defconfig b/arch/arm/configs/pcm027_defconfig
index 2f136c3..1280128 100644
--- a/arch/arm/configs/pcm027_defconfig
+++ b/arch/arm/configs/pcm027_defconfig
@@ -60,8 +60,9 @@ CONFIG_SMC91X=y
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/pxa168_defconfig b/arch/arm/configs/pxa168_defconfig
index 74d7e01..1668dac 100644
--- a/arch/arm/configs/pxa168_defconfig
+++ b/arch/arm/configs/pxa168_defconfig
@@ -40,8 +40,9 @@ CONFIG_SMC91X=y
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 # CONFIG_HWMON is not set
diff --git a/arch/arm/configs/pxa255-idp_defconfig b/arch/arm/configs/pxa255-idp_defconfig
index 917a070..399a706 100644
--- a/arch/arm/configs/pxa255-idp_defconfig
+++ b/arch/arm/configs/pxa255-idp_defconfig
@@ -35,8 +35,9 @@ CONFIG_SMC91X=y
 CONFIG_INPUT_EVDEV=y
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_FB=y
 CONFIG_FB_PXA=y
 # CONFIG_VGA_CONSOLE is not set
diff --git a/arch/arm/configs/pxa3xx_defconfig b/arch/arm/configs/pxa3xx_defconfig
index 60e3138..7c3e052 100644
--- a/arch/arm/configs/pxa3xx_defconfig
+++ b/arch/arm/configs/pxa3xx_defconfig
@@ -56,8 +56,9 @@ CONFIG_KEYBOARD_PXA27x=y
 CONFIG_KEYBOARD_PXA930_ROTARY=y
 CONFIG_MOUSE_PXA930_TRKBALL=y
 CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/pxa910_defconfig b/arch/arm/configs/pxa910_defconfig
index 3bb7771..cdacfcb 100644
--- a/arch/arm/configs/pxa910_defconfig
+++ b/arch/arm/configs/pxa910_defconfig
@@ -40,8 +40,9 @@ CONFIG_SMC91X=y
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_SPI=y
 CONFIG_FB=y
 CONFIG_MMP_DISP=y
diff --git a/arch/arm/configs/raumfeld_defconfig b/arch/arm/configs/raumfeld_defconfig
index f7caa90..f1e16f2 100644
--- a/arch/arm/configs/raumfeld_defconfig
+++ b/arch/arm/configs/raumfeld_defconfig
@@ -67,8 +67,9 @@ CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_TOUCHSCREEN_EETI=m
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_GPIO_ROTARY_ENCODER=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_HW_RANDOM=y
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
diff --git a/arch/arm/configs/spitz_defconfig b/arch/arm/configs/spitz_defconfig
index 2e0419d..b6efcf5 100644
--- a/arch/arm/configs/spitz_defconfig
+++ b/arch/arm/configs/spitz_defconfig
@@ -128,10 +128,10 @@ CONFIG_TOUCHSCREEN_ADS7846=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=m
 # CONFIG_SERIO is not set
-CONFIG_SERIAL_8250=m
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_CS=m
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 CONFIG_SPI=y
 CONFIG_SPI_PXA2XX=y
diff --git a/arch/arm/configs/trizeps4_defconfig b/arch/arm/configs/trizeps4_defconfig
index 3162173..453c79c 100644
--- a/arch/arm/configs/trizeps4_defconfig
+++ b/arch/arm/configs/trizeps4_defconfig
@@ -132,8 +132,9 @@ CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=m
 CONFIG_SERIO_LIBPS2=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_HW_RANDOM=y
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
diff --git a/arch/arm/configs/viper_defconfig b/arch/arm/configs/viper_defconfig
index d36e0d3..4efac06 100644
--- a/arch/arm/configs/viper_defconfig
+++ b/arch/arm/configs/viper_defconfig
@@ -101,11 +101,11 @@ CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=m
 # CONFIG_CONSOLE_TRANSLATIONS is not set
 # CONFIG_VT_CONSOLE is not set
-CONFIG_SERIAL_8250=m
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_NR_UARTS=5
 CONFIG_SERIAL_8250_RUNTIME_UARTS=5
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
diff --git a/arch/arm/configs/xcep_defconfig b/arch/arm/configs/xcep_defconfig
index 721832f..b67aeaf 100644
--- a/arch/arm/configs/xcep_defconfig
+++ b/arch/arm/configs/xcep_defconfig
@@ -60,8 +60,9 @@ CONFIG_NET_ETHERNET=y
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
 # CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=m
diff --git a/drivers/tty/serial/8250/8250_pxa.c b/drivers/tty/serial/8250/8250_pxa.c
new file mode 100644
index 0000000..0da0d40
--- /dev/null
+++ b/drivers/tty/serial/8250/8250_pxa.c
@@ -0,0 +1,178 @@
+/*
+ *  drivers/tty/serial/8250/8250_pxa.c -- driver for PXA on-board UARTS
+ *  Copyright:	(C) 2013 Sergei Ianovich <ynvich@gmail.com>
+ *
+ *  replaces drivers/serial/pxa.c by Nicolas Pitre
+ *  Created:	Feb 20, 2003
+ *  Copyright:	(C) 2003 Monta Vista Software, Inc.
+ *
+ *  Based on drivers/serial/8250.c by Russell King.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/serial_8250.h>
+#include <linux/serial_core.h>
+#include <linux/serial_reg.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
+#include <linux/pm_runtime.h>
+
+#include "8250.h"
+
+struct pxa8250_data {
+	int			line;
+	struct clk		*clk;
+};
+
+#ifdef CONFIG_PM
+static int serial_pxa_suspend(struct device *dev)
+{
+	struct pxa8250_data *data = dev_get_drvdata(dev);
+
+	serial8250_suspend_port(data->line);
+
+	return 0;
+}
+
+static int serial_pxa_resume(struct device *dev)
+{
+	struct pxa8250_data *data = dev_get_drvdata(dev);
+
+	serial8250_resume_port(data->line);
+
+	return 0;
+}
+#endif
+
+static const struct dev_pm_ops serial_pxa_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(serial_pxa_suspend, serial_pxa_resume)
+};
+
+static struct of_device_id serial_pxa_dt_ids[] = {
+	{ .compatible = "mrvl,pxa-uart", },
+	{ .compatible = "mrvl,mmp-uart", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, serial_pxa_dt_ids);
+
+/* Uart divisor latch write */
+static void serial_pxa_dl_write(struct uart_8250_port *up, int value)
+{
+	unsigned int dll;
+
+	serial_out(up, UART_DLL, value & 0xff);
+	/*
+	 * work around Erratum #74 according to Marvel(R) PXA270M Processor
+	 * Specification Update (April 19, 2010)
+	 */
+	dll = serial_in(up, UART_DLL);
+	WARN_ON(dll != (value & 0xff));
+
+	serial_out(up, UART_DLM, value >> 8 & 0xff);
+}
+
+
+static void serial_pxa_pm(struct uart_port *port, unsigned int state,
+	      unsigned int oldstate)
+{
+	struct pxa8250_data *data = port->private_data;
+
+	if (!state)
+		clk_prepare_enable(data->clk);
+	else
+		clk_disable_unprepare(data->clk);
+}
+
+static int serial_pxa_probe(struct platform_device *pdev)
+{
+	struct uart_8250_port uart = {};
+	struct pxa8250_data *data;
+	struct resource *mmres, *irqres;
+	int ret;
+
+	mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	irqres = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!mmres || !irqres)
+		return -ENODEV;
+
+	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(data->clk))
+		return PTR_ERR(data->clk);
+
+	ret = clk_prepare(data->clk);
+	if (ret)
+		return ret;
+
+	uart.port.type = PORT_XSCALE;
+	uart.port.iotype = UPIO_MEM32;
+	uart.port.mapbase = mmres->start;
+	uart.port.regshift = 2;
+	uart.port.irq = irqres->start;
+	uart.port.fifosize = 64;
+	uart.port.flags = UPF_IOREMAP | UPF_SKIP_TEST;
+	uart.port.dev = &pdev->dev;
+	uart.port.uartclk = clk_get_rate(data->clk);
+	uart.port.pm = serial_pxa_pm;
+	uart.port.private_data = data;
+	uart.dl_write = serial_pxa_dl_write;
+
+	ret = serial8250_register_8250_port(&uart);
+	if (ret < 0)
+		goto err_clk;
+
+	data->line = ret;
+
+	platform_set_drvdata(pdev, data);
+
+	return 0;
+
+ err_clk:
+	clk_unprepare(data->clk);
+	return ret;
+}
+
+static int serial_pxa_remove(struct platform_device *pdev)
+{
+	struct pxa8250_data *data = platform_get_drvdata(pdev);
+
+	serial8250_unregister_port(data->line);
+
+	clk_unprepare(data->clk);
+
+	return 0;
+}
+
+static struct platform_driver serial_pxa_driver = {
+	.probe          = serial_pxa_probe,
+	.remove         = serial_pxa_remove,
+
+	.driver		= {
+		.name	= "pxa2xx-uart",
+		.owner	= THIS_MODULE,
+		.pm	= &serial_pxa_pm_ops,
+		.of_match_table = serial_pxa_dt_ids,
+	},
+};
+
+module_platform_driver(serial_pxa_driver);
+
+MODULE_AUTHOR("Sergei Ianovich");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:pxa2xx-uart");
diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
index 2332991..81bd7c9 100644
--- a/drivers/tty/serial/8250/Kconfig
+++ b/drivers/tty/serial/8250/Kconfig
@@ -302,3 +302,12 @@ config SERIAL_8250_RT288X
 	  If you have a Ralink RT288x/RT305x SoC based board and want to use the
 	  serial port, say Y to this option. The driver can handle up to 2 serial
 	  ports. If unsure, say N.
+
+config SERIAL_PXA
+	tristate "PXA serial port support"
+	depends on SERIAL_8250 && (ARCH_PXA || ARCH_MMP)
+	help
+	  If you have a machine based on an Intel XScale PXA2xx CPU you
+	  can enable its onboard serial ports by enabling this option.
+
+	  If you choose M here, the module name will be 8250_pxa.
diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile
index 36d68d0..b7d1b61 100644
--- a/drivers/tty/serial/8250/Makefile
+++ b/drivers/tty/serial/8250/Makefile
@@ -20,3 +20,4 @@ obj-$(CONFIG_SERIAL_8250_HUB6)		+= 8250_hub6.o
 obj-$(CONFIG_SERIAL_8250_FSL)		+= 8250_fsl.o
 obj-$(CONFIG_SERIAL_8250_DW)		+= 8250_dw.o
 obj-$(CONFIG_SERIAL_8250_EM)		+= 8250_em.o
+obj-$(CONFIG_SERIAL_PXA)		+= 8250_pxa.o
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index a3817ab..2ad7184b 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -396,29 +396,6 @@ config SERIAL_MPSC_CONSOLE
 	help
 	  Say Y here if you want to support a serial console on a Marvell MPSC.
 
-config SERIAL_PXA
-	bool "PXA serial port support"
-	depends on ARCH_PXA || ARCH_MMP
-	select SERIAL_CORE
-	help
-	  If you have a machine based on an Intel XScale PXA2xx CPU you
-	  can enable its onboard serial ports by enabling this option.
-
-config SERIAL_PXA_CONSOLE
-	bool "Console on PXA serial port"
-	depends on SERIAL_PXA
-	select SERIAL_CORE_CONSOLE
-	help
-	  If you have enabled the serial port on the Intel XScale PXA
-	  CPU you can make it the console by answering Y to this option.
-
-	  Even if you say Y here, the currently visible virtual console
-	  (/dev/tty0) will still be used as the system console by default, but
-	  you can alter that using a kernel command line option such as
-	  "console=ttySA0". (Try "man bootparam" or see the documentation of
-	  your boot loader (lilo or loadlin) about how to pass options to the
-	  kernel at boot time.)
-
 config SERIAL_SA1100
 	bool "SA1100 serial port support"
 	depends on ARCH_SA1100
diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile
index 3068c77..4ac337b 100644
--- a/drivers/tty/serial/Makefile
+++ b/drivers/tty/serial/Makefile
@@ -20,7 +20,6 @@ obj-$(CONFIG_SERIAL_8250) += 8250/
 obj-$(CONFIG_SERIAL_AMBA_PL010) += amba-pl010.o
 obj-$(CONFIG_SERIAL_AMBA_PL011) += amba-pl011.o
 obj-$(CONFIG_SERIAL_CLPS711X) += clps711x.o
-obj-$(CONFIG_SERIAL_PXA) += pxa.o
 obj-$(CONFIG_SERIAL_PNX8XXX) += pnx8xxx_uart.o
 obj-$(CONFIG_SERIAL_SA1100) += sa1100.o
 obj-$(CONFIG_SERIAL_BCM63XX) += bcm63xx_uart.o
diff --git a/drivers/tty/serial/pxa.c b/drivers/tty/serial/pxa.c
deleted file mode 100644
index f9f20f3..0000000
--- a/drivers/tty/serial/pxa.c
+++ /dev/null
@@ -1,971 +0,0 @@
-/*
- *  Based on drivers/serial/8250.c by Russell King.
- *
- *  Author:	Nicolas Pitre
- *  Created:	Feb 20, 2003
- *  Copyright:	(C) 2003 Monta Vista Software, Inc.
- *
- * 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.
- *
- * Note 1: This driver is made separate from the already too overloaded
- * 8250.c because it needs some kirks of its own and that'll make it
- * easier to add DMA support.
- *
- * Note 2: I'm too sick of device allocation policies for serial ports.
- * If someone else wants to request an "official" allocation of major/minor
- * for this driver please be my guest.  And don't forget that new hardware
- * to come from Intel might have more than 3 or 4 of those UARTs.  Let's
- * hope for a better port registration and dynamic device allocation scheme
- * with the serial core maintainer satisfaction to appear soon.
- */
-
-
-#if defined(CONFIG_SERIAL_PXA_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-#define SUPPORT_SYSRQ
-#endif
-
-#include <linux/module.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-#include <linux/console.h>
-#include <linux/sysrq.h>
-#include <linux/serial_reg.h>
-#include <linux/circ_buf.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/of.h>
-#include <linux/platform_device.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/serial_core.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-
-#define PXA_NAME_LEN		8
-
-struct uart_pxa_port {
-	struct uart_port        port;
-	unsigned char           ier;
-	unsigned char           lcr;
-	unsigned char           mcr;
-	unsigned int            lsr_break_flag;
-	struct clk		*clk;
-	char			name[PXA_NAME_LEN];
-};
-
-static inline unsigned int serial_in(struct uart_pxa_port *up, int offset)
-{
-	offset <<= 2;
-	return readl(up->port.membase + offset);
-}
-
-static inline void serial_out(struct uart_pxa_port *up, int offset, int value)
-{
-	offset <<= 2;
-	writel(value, up->port.membase + offset);
-}
-
-static void serial_pxa_enable_ms(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	up->ier |= UART_IER_MSI;
-	serial_out(up, UART_IER, up->ier);
-}
-
-static void serial_pxa_stop_tx(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	if (up->ier & UART_IER_THRI) {
-		up->ier &= ~UART_IER_THRI;
-		serial_out(up, UART_IER, up->ier);
-	}
-}
-
-static void serial_pxa_stop_rx(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	up->ier &= ~UART_IER_RLSI;
-	up->port.read_status_mask &= ~UART_LSR_DR;
-	serial_out(up, UART_IER, up->ier);
-}
-
-static inline void receive_chars(struct uart_pxa_port *up, int *status)
-{
-	unsigned int ch, flag;
-	int max_count = 256;
-
-	do {
-		/* work around Errata #20 according to
-		 * Intel(R) PXA27x Processor Family
-		 * Specification Update (May 2005)
-		 *
-		 * Step 2
-		 * Disable the Reciever Time Out Interrupt via IER[RTOEI]
-		 */
-		up->ier &= ~UART_IER_RTOIE;
-		serial_out(up, UART_IER, up->ier);
-
-		ch = serial_in(up, UART_RX);
-		flag = TTY_NORMAL;
-		up->port.icount.rx++;
-
-		if (unlikely(*status & (UART_LSR_BI | UART_LSR_PE |
-				       UART_LSR_FE | UART_LSR_OE))) {
-			/*
-			 * For statistics only
-			 */
-			if (*status & UART_LSR_BI) {
-				*status &= ~(UART_LSR_FE | UART_LSR_PE);
-				up->port.icount.brk++;
-				/*
-				 * We do the SysRQ and SAK checking
-				 * here because otherwise the break
-				 * may get masked by ignore_status_mask
-				 * or read_status_mask.
-				 */
-				if (uart_handle_break(&up->port))
-					goto ignore_char;
-			} else if (*status & UART_LSR_PE)
-				up->port.icount.parity++;
-			else if (*status & UART_LSR_FE)
-				up->port.icount.frame++;
-			if (*status & UART_LSR_OE)
-				up->port.icount.overrun++;
-
-			/*
-			 * Mask off conditions which should be ignored.
-			 */
-			*status &= up->port.read_status_mask;
-
-#ifdef CONFIG_SERIAL_PXA_CONSOLE
-			if (up->port.line == up->port.cons->index) {
-				/* Recover the break flag from console xmit */
-				*status |= up->lsr_break_flag;
-				up->lsr_break_flag = 0;
-			}
-#endif
-			if (*status & UART_LSR_BI) {
-				flag = TTY_BREAK;
-			} else if (*status & UART_LSR_PE)
-				flag = TTY_PARITY;
-			else if (*status & UART_LSR_FE)
-				flag = TTY_FRAME;
-		}
-
-		if (uart_handle_sysrq_char(&up->port, ch))
-			goto ignore_char;
-
-		uart_insert_char(&up->port, *status, UART_LSR_OE, ch, flag);
-
-	ignore_char:
-		*status = serial_in(up, UART_LSR);
-	} while ((*status & UART_LSR_DR) && (max_count-- > 0));
-	tty_flip_buffer_push(&up->port.state->port);
-
-	/* work around Errata #20 according to
-	 * Intel(R) PXA27x Processor Family
-	 * Specification Update (May 2005)
-	 *
-	 * Step 6:
-	 * No more data in FIFO: Re-enable RTO interrupt via IER[RTOIE]
-	 */
-	up->ier |= UART_IER_RTOIE;
-	serial_out(up, UART_IER, up->ier);
-}
-
-static void transmit_chars(struct uart_pxa_port *up)
-{
-	struct circ_buf *xmit = &up->port.state->xmit;
-	int count;
-
-	if (up->port.x_char) {
-		serial_out(up, UART_TX, up->port.x_char);
-		up->port.icount.tx++;
-		up->port.x_char = 0;
-		return;
-	}
-	if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) {
-		serial_pxa_stop_tx(&up->port);
-		return;
-	}
-
-	count = up->port.fifosize / 2;
-	do {
-		serial_out(up, UART_TX, xmit->buf[xmit->tail]);
-		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
-		up->port.icount.tx++;
-		if (uart_circ_empty(xmit))
-			break;
-	} while (--count > 0);
-
-	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
-		uart_write_wakeup(&up->port);
-
-
-	if (uart_circ_empty(xmit))
-		serial_pxa_stop_tx(&up->port);
-}
-
-static void serial_pxa_start_tx(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	if (!(up->ier & UART_IER_THRI)) {
-		up->ier |= UART_IER_THRI;
-		serial_out(up, UART_IER, up->ier);
-	}
-}
-
-static inline void check_modem_status(struct uart_pxa_port *up)
-{
-	int status;
-
-	status = serial_in(up, UART_MSR);
-
-	if ((status & UART_MSR_ANY_DELTA) == 0)
-		return;
-
-	if (status & UART_MSR_TERI)
-		up->port.icount.rng++;
-	if (status & UART_MSR_DDSR)
-		up->port.icount.dsr++;
-	if (status & UART_MSR_DDCD)
-		uart_handle_dcd_change(&up->port, status & UART_MSR_DCD);
-	if (status & UART_MSR_DCTS)
-		uart_handle_cts_change(&up->port, status & UART_MSR_CTS);
-
-	wake_up_interruptible(&up->port.state->port.delta_msr_wait);
-}
-
-/*
- * This handles the interrupt from one port.
- */
-static inline irqreturn_t serial_pxa_irq(int irq, void *dev_id)
-{
-	struct uart_pxa_port *up = dev_id;
-	unsigned int iir, lsr;
-
-	iir = serial_in(up, UART_IIR);
-	if (iir & UART_IIR_NO_INT)
-		return IRQ_NONE;
-	lsr = serial_in(up, UART_LSR);
-	if (lsr & UART_LSR_DR)
-		receive_chars(up, &lsr);
-	check_modem_status(up);
-	if (lsr & UART_LSR_THRE)
-		transmit_chars(up);
-	return IRQ_HANDLED;
-}
-
-static unsigned int serial_pxa_tx_empty(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned long flags;
-	unsigned int ret;
-
-	spin_lock_irqsave(&up->port.lock, flags);
-	ret = serial_in(up, UART_LSR) & UART_LSR_TEMT ? TIOCSER_TEMT : 0;
-	spin_unlock_irqrestore(&up->port.lock, flags);
-
-	return ret;
-}
-
-static unsigned int serial_pxa_get_mctrl(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned char status;
-	unsigned int ret;
-
-	status = serial_in(up, UART_MSR);
-
-	ret = 0;
-	if (status & UART_MSR_DCD)
-		ret |= TIOCM_CAR;
-	if (status & UART_MSR_RI)
-		ret |= TIOCM_RNG;
-	if (status & UART_MSR_DSR)
-		ret |= TIOCM_DSR;
-	if (status & UART_MSR_CTS)
-		ret |= TIOCM_CTS;
-	return ret;
-}
-
-static void serial_pxa_set_mctrl(struct uart_port *port, unsigned int mctrl)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned char mcr = 0;
-
-	if (mctrl & TIOCM_RTS)
-		mcr |= UART_MCR_RTS;
-	if (mctrl & TIOCM_DTR)
-		mcr |= UART_MCR_DTR;
-	if (mctrl & TIOCM_OUT1)
-		mcr |= UART_MCR_OUT1;
-	if (mctrl & TIOCM_OUT2)
-		mcr |= UART_MCR_OUT2;
-	if (mctrl & TIOCM_LOOP)
-		mcr |= UART_MCR_LOOP;
-
-	mcr |= up->mcr;
-
-	serial_out(up, UART_MCR, mcr);
-}
-
-static void serial_pxa_break_ctl(struct uart_port *port, int break_state)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned long flags;
-
-	spin_lock_irqsave(&up->port.lock, flags);
-	if (break_state == -1)
-		up->lcr |= UART_LCR_SBC;
-	else
-		up->lcr &= ~UART_LCR_SBC;
-	serial_out(up, UART_LCR, up->lcr);
-	spin_unlock_irqrestore(&up->port.lock, flags);
-}
-
-static int serial_pxa_startup(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned long flags;
-	int retval;
-
-	if (port->line == 3) /* HWUART */
-		up->mcr |= UART_MCR_AFE;
-	else
-		up->mcr = 0;
-
-	up->port.uartclk = clk_get_rate(up->clk);
-
-	/*
-	 * Allocate the IRQ
-	 */
-	retval = request_irq(up->port.irq, serial_pxa_irq, 0, up->name, up);
-	if (retval)
-		return retval;
-
-	/*
-	 * Clear the FIFO buffers and disable them.
-	 * (they will be reenabled in set_termios())
-	 */
-	serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO);
-	serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO |
-			UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
-	serial_out(up, UART_FCR, 0);
-
-	/*
-	 * Clear the interrupt registers.
-	 */
-	(void) serial_in(up, UART_LSR);
-	(void) serial_in(up, UART_RX);
-	(void) serial_in(up, UART_IIR);
-	(void) serial_in(up, UART_MSR);
-
-	/*
-	 * Now, initialize the UART
-	 */
-	serial_out(up, UART_LCR, UART_LCR_WLEN8);
-
-	spin_lock_irqsave(&up->port.lock, flags);
-	up->port.mctrl |= TIOCM_OUT2;
-	serial_pxa_set_mctrl(&up->port, up->port.mctrl);
-	spin_unlock_irqrestore(&up->port.lock, flags);
-
-	/*
-	 * Finally, enable interrupts.  Note: Modem status interrupts
-	 * are set via set_termios(), which will be occurring imminently
-	 * anyway, so we don't enable them here.
-	 */
-	up->ier = UART_IER_RLSI | UART_IER_RDI | UART_IER_RTOIE | UART_IER_UUE;
-	serial_out(up, UART_IER, up->ier);
-
-	/*
-	 * And clear the interrupt registers again for luck.
-	 */
-	(void) serial_in(up, UART_LSR);
-	(void) serial_in(up, UART_RX);
-	(void) serial_in(up, UART_IIR);
-	(void) serial_in(up, UART_MSR);
-
-	return 0;
-}
-
-static void serial_pxa_shutdown(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned long flags;
-
-	free_irq(up->port.irq, up);
-
-	/*
-	 * Disable interrupts from this port
-	 */
-	up->ier = 0;
-	serial_out(up, UART_IER, 0);
-
-	spin_lock_irqsave(&up->port.lock, flags);
-	up->port.mctrl &= ~TIOCM_OUT2;
-	serial_pxa_set_mctrl(&up->port, up->port.mctrl);
-	spin_unlock_irqrestore(&up->port.lock, flags);
-
-	/*
-	 * Disable break condition and FIFOs
-	 */
-	serial_out(up, UART_LCR, serial_in(up, UART_LCR) & ~UART_LCR_SBC);
-	serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO |
-				  UART_FCR_CLEAR_RCVR |
-				  UART_FCR_CLEAR_XMIT);
-	serial_out(up, UART_FCR, 0);
-}
-
-static void
-serial_pxa_set_termios(struct uart_port *port, struct ktermios *termios,
-		       struct ktermios *old)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned char cval, fcr = 0;
-	unsigned long flags;
-	unsigned int baud, quot;
-	unsigned int dll;
-
-	switch (termios->c_cflag & CSIZE) {
-	case CS5:
-		cval = UART_LCR_WLEN5;
-		break;
-	case CS6:
-		cval = UART_LCR_WLEN6;
-		break;
-	case CS7:
-		cval = UART_LCR_WLEN7;
-		break;
-	default:
-	case CS8:
-		cval = UART_LCR_WLEN8;
-		break;
-	}
-
-	if (termios->c_cflag & CSTOPB)
-		cval |= UART_LCR_STOP;
-	if (termios->c_cflag & PARENB)
-		cval |= UART_LCR_PARITY;
-	if (!(termios->c_cflag & PARODD))
-		cval |= UART_LCR_EPAR;
-
-	/*
-	 * Ask the core to calculate the divisor for us.
-	 */
-	baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
-	quot = uart_get_divisor(port, baud);
-
-	if ((up->port.uartclk / quot) < (2400 * 16))
-		fcr = UART_FCR_ENABLE_FIFO | UART_FCR_PXAR1;
-	else if ((up->port.uartclk / quot) < (230400 * 16))
-		fcr = UART_FCR_ENABLE_FIFO | UART_FCR_PXAR8;
-	else
-		fcr = UART_FCR_ENABLE_FIFO | UART_FCR_PXAR32;
-
-	/*
-	 * Ok, we're now changing the port state.  Do it with
-	 * interrupts disabled.
-	 */
-	spin_lock_irqsave(&up->port.lock, flags);
-
-	/*
-	 * Ensure the port will be enabled.
-	 * This is required especially for serial console.
-	 */
-	up->ier |= UART_IER_UUE;
-
-	/*
-	 * Update the per-port timeout.
-	 */
-	uart_update_timeout(port, termios->c_cflag, baud);
-
-	up->port.read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;
-	if (termios->c_iflag & INPCK)
-		up->port.read_status_mask |= UART_LSR_FE | UART_LSR_PE;
-	if (termios->c_iflag & (BRKINT | PARMRK))
-		up->port.read_status_mask |= UART_LSR_BI;
-
-	/*
-	 * Characters to ignore
-	 */
-	up->port.ignore_status_mask = 0;
-	if (termios->c_iflag & IGNPAR)
-		up->port.ignore_status_mask |= UART_LSR_PE | UART_LSR_FE;
-	if (termios->c_iflag & IGNBRK) {
-		up->port.ignore_status_mask |= UART_LSR_BI;
-		/*
-		 * If we're ignoring parity and break indicators,
-		 * ignore overruns too (for real raw support).
-		 */
-		if (termios->c_iflag & IGNPAR)
-			up->port.ignore_status_mask |= UART_LSR_OE;
-	}
-
-	/*
-	 * ignore all characters if CREAD is not set
-	 */
-	if ((termios->c_cflag & CREAD) == 0)
-		up->port.ignore_status_mask |= UART_LSR_DR;
-
-	/*
-	 * CTS flow control flag and modem status interrupts
-	 */
-	up->ier &= ~UART_IER_MSI;
-	if (UART_ENABLE_MS(&up->port, termios->c_cflag))
-		up->ier |= UART_IER_MSI;
-
-	serial_out(up, UART_IER, up->ier);
-
-	if (termios->c_cflag & CRTSCTS)
-		up->mcr |= UART_MCR_AFE;
-	else
-		up->mcr &= ~UART_MCR_AFE;
-
-	serial_out(up, UART_LCR, cval | UART_LCR_DLAB);	/* set DLAB */
-	serial_out(up, UART_DLL, quot & 0xff);		/* LS of divisor */
-
-	/*
-	 * work around Errata #75 according to Intel(R) PXA27x Processor Family
-	 * Specification Update (Nov 2005)
-	 */
-	dll = serial_in(up, UART_DLL);
-	WARN_ON(dll != (quot & 0xff));
-
-	serial_out(up, UART_DLM, quot >> 8);		/* MS of divisor */
-	serial_out(up, UART_LCR, cval);			/* reset DLAB */
-	up->lcr = cval;					/* Save LCR */
-	serial_pxa_set_mctrl(&up->port, up->port.mctrl);
-	serial_out(up, UART_FCR, fcr);
-	spin_unlock_irqrestore(&up->port.lock, flags);
-}
-
-static void
-serial_pxa_pm(struct uart_port *port, unsigned int state,
-	      unsigned int oldstate)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	if (!state)
-		clk_prepare_enable(up->clk);
-	else
-		clk_disable_unprepare(up->clk);
-}
-
-static void serial_pxa_release_port(struct uart_port *port)
-{
-}
-
-static int serial_pxa_request_port(struct uart_port *port)
-{
-	return 0;
-}
-
-static void serial_pxa_config_port(struct uart_port *port, int flags)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	up->port.type = PORT_PXA;
-}
-
-static int
-serial_pxa_verify_port(struct uart_port *port, struct serial_struct *ser)
-{
-	/* we don't want the core code to modify any port params */
-	return -EINVAL;
-}
-
-static const char *
-serial_pxa_type(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	return up->name;
-}
-
-static struct uart_pxa_port *serial_pxa_ports[4];
-static struct uart_driver serial_pxa_reg;
-
-#ifdef CONFIG_SERIAL_PXA_CONSOLE
-
-#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
-
-/*
- *	Wait for transmitter & holding register to empty
- */
-static inline void wait_for_xmitr(struct uart_pxa_port *up)
-{
-	unsigned int status, tmout = 10000;
-
-	/* Wait up to 10ms for the character(s) to be sent. */
-	do {
-		status = serial_in(up, UART_LSR);
-
-		if (status & UART_LSR_BI)
-			up->lsr_break_flag = UART_LSR_BI;
-
-		if (--tmout == 0)
-			break;
-		udelay(1);
-	} while ((status & BOTH_EMPTY) != BOTH_EMPTY);
-
-	/* Wait up to 1s for flow control if necessary */
-	if (up->port.flags & UPF_CONS_FLOW) {
-		tmout = 1000000;
-		while (--tmout &&
-		       ((serial_in(up, UART_MSR) & UART_MSR_CTS) == 0))
-			udelay(1);
-	}
-}
-
-static void serial_pxa_console_putchar(struct uart_port *port, int ch)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	wait_for_xmitr(up);
-	serial_out(up, UART_TX, ch);
-}
-
-/*
- * Print a string to the serial port trying not to disturb
- * any possible real use of the port...
- *
- *	The console_lock must be held when we get here.
- */
-static void
-serial_pxa_console_write(struct console *co, const char *s, unsigned int count)
-{
-	struct uart_pxa_port *up = serial_pxa_ports[co->index];
-	unsigned int ier;
-	unsigned long flags;
-	int locked = 1;
-
-	clk_enable(up->clk);
-	local_irq_save(flags);
-	if (up->port.sysrq)
-		locked = 0;
-	else if (oops_in_progress)
-		locked = spin_trylock(&up->port.lock);
-	else
-		spin_lock(&up->port.lock);
-
-	/*
-	 *	First save the IER then disable the interrupts
-	 */
-	ier = serial_in(up, UART_IER);
-	serial_out(up, UART_IER, UART_IER_UUE);
-
-	uart_console_write(&up->port, s, count, serial_pxa_console_putchar);
-
-	/*
-	 *	Finally, wait for transmitter to become empty
-	 *	and restore the IER
-	 */
-	wait_for_xmitr(up);
-	serial_out(up, UART_IER, ier);
-
-	if (locked)
-		spin_unlock(&up->port.lock);
-	local_irq_restore(flags);
-	clk_disable(up->clk);
-
-}
-
-#ifdef CONFIG_CONSOLE_POLL
-/*
- * Console polling routines for writing and reading from the uart while
- * in an interrupt or debug context.
- */
-
-static int serial_pxa_get_poll_char(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned char lsr = serial_in(up, UART_LSR);
-
-	while (!(lsr & UART_LSR_DR))
-		lsr = serial_in(up, UART_LSR);
-
-	return serial_in(up, UART_RX);
-}
-
-
-static void serial_pxa_put_poll_char(struct uart_port *port,
-			 unsigned char c)
-{
-	unsigned int ier;
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	/*
-	 *	First save the IER then disable the interrupts
-	 */
-	ier = serial_in(up, UART_IER);
-	serial_out(up, UART_IER, UART_IER_UUE);
-
-	wait_for_xmitr(up);
-	/*
-	 *	Send the character out.
-	 *	If a LF, also do CR...
-	 */
-	serial_out(up, UART_TX, c);
-	if (c == 10) {
-		wait_for_xmitr(up);
-		serial_out(up, UART_TX, 13);
-	}
-
-	/*
-	 *	Finally, wait for transmitter to become empty
-	 *	and restore the IER
-	 */
-	wait_for_xmitr(up);
-	serial_out(up, UART_IER, ier);
-}
-
-#endif /* CONFIG_CONSOLE_POLL */
-
-static int __init
-serial_pxa_console_setup(struct console *co, char *options)
-{
-	struct uart_pxa_port *up;
-	int baud = 9600;
-	int bits = 8;
-	int parity = 'n';
-	int flow = 'n';
-
-	if (co->index == -1 || co->index >= serial_pxa_reg.nr)
-		co->index = 0;
-	up = serial_pxa_ports[co->index];
-	if (!up)
-		return -ENODEV;
-
-	if (options)
-		uart_parse_options(options, &baud, &parity, &bits, &flow);
-
-	return uart_set_options(&up->port, co, baud, parity, bits, flow);
-}
-
-static struct console serial_pxa_console = {
-	.name		= "ttyS",
-	.write		= serial_pxa_console_write,
-	.device		= uart_console_device,
-	.setup		= serial_pxa_console_setup,
-	.flags		= CON_PRINTBUFFER,
-	.index		= -1,
-	.data		= &serial_pxa_reg,
-};
-
-#define PXA_CONSOLE	&serial_pxa_console
-#else
-#define PXA_CONSOLE	NULL
-#endif
-
-static struct uart_ops serial_pxa_pops = {
-	.tx_empty	= serial_pxa_tx_empty,
-	.set_mctrl	= serial_pxa_set_mctrl,
-	.get_mctrl	= serial_pxa_get_mctrl,
-	.stop_tx	= serial_pxa_stop_tx,
-	.start_tx	= serial_pxa_start_tx,
-	.stop_rx	= serial_pxa_stop_rx,
-	.enable_ms	= serial_pxa_enable_ms,
-	.break_ctl	= serial_pxa_break_ctl,
-	.startup	= serial_pxa_startup,
-	.shutdown	= serial_pxa_shutdown,
-	.set_termios	= serial_pxa_set_termios,
-	.pm		= serial_pxa_pm,
-	.type		= serial_pxa_type,
-	.release_port	= serial_pxa_release_port,
-	.request_port	= serial_pxa_request_port,
-	.config_port	= serial_pxa_config_port,
-	.verify_port	= serial_pxa_verify_port,
-#ifdef CONFIG_CONSOLE_POLL
-	.poll_get_char = serial_pxa_get_poll_char,
-	.poll_put_char = serial_pxa_put_poll_char,
-#endif
-};
-
-static struct uart_driver serial_pxa_reg = {
-	.owner		= THIS_MODULE,
-	.driver_name	= "PXA serial",
-	.dev_name	= "ttyS",
-	.major		= TTY_MAJOR,
-	.minor		= 64,
-	.nr		= 4,
-	.cons		= PXA_CONSOLE,
-};
-
-#ifdef CONFIG_PM
-static int serial_pxa_suspend(struct device *dev)
-{
-        struct uart_pxa_port *sport = dev_get_drvdata(dev);
-
-        if (sport)
-                uart_suspend_port(&serial_pxa_reg, &sport->port);
-
-        return 0;
-}
-
-static int serial_pxa_resume(struct device *dev)
-{
-        struct uart_pxa_port *sport = dev_get_drvdata(dev);
-
-        if (sport)
-                uart_resume_port(&serial_pxa_reg, &sport->port);
-
-        return 0;
-}
-
-static const struct dev_pm_ops serial_pxa_pm_ops = {
-	.suspend	= serial_pxa_suspend,
-	.resume		= serial_pxa_resume,
-};
-#endif
-
-static struct of_device_id serial_pxa_dt_ids[] = {
-	{ .compatible = "mrvl,pxa-uart", },
-	{ .compatible = "mrvl,mmp-uart", },
-	{}
-};
-MODULE_DEVICE_TABLE(of, serial_pxa_dt_ids);
-
-static int serial_pxa_probe_dt(struct platform_device *pdev,
-			       struct uart_pxa_port *sport)
-{
-	struct device_node *np = pdev->dev.of_node;
-	int ret;
-
-	if (!np)
-		return 1;
-
-	ret = of_alias_get_id(np, "serial");
-	if (ret < 0) {
-		dev_err(&pdev->dev, "failed to get alias id, errno %d\n", ret);
-		return ret;
-	}
-	sport->port.line = ret;
-	return 0;
-}
-
-static int serial_pxa_probe(struct platform_device *dev)
-{
-	struct uart_pxa_port *sport;
-	struct resource *mmres, *irqres;
-	int ret;
-
-	mmres = platform_get_resource(dev, IORESOURCE_MEM, 0);
-	irqres = platform_get_resource(dev, IORESOURCE_IRQ, 0);
-	if (!mmres || !irqres)
-		return -ENODEV;
-
-	sport = kzalloc(sizeof(struct uart_pxa_port), GFP_KERNEL);
-	if (!sport)
-		return -ENOMEM;
-
-	sport->clk = clk_get(&dev->dev, NULL);
-	if (IS_ERR(sport->clk)) {
-		ret = PTR_ERR(sport->clk);
-		goto err_free;
-	}
-
-	ret = clk_prepare(sport->clk);
-	if (ret) {
-		clk_put(sport->clk);
-		goto err_free;
-	}
-
-	sport->port.type = PORT_PXA;
-	sport->port.iotype = UPIO_MEM;
-	sport->port.mapbase = mmres->start;
-	sport->port.irq = irqres->start;
-	sport->port.fifosize = 64;
-	sport->port.ops = &serial_pxa_pops;
-	sport->port.dev = &dev->dev;
-	sport->port.flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF;
-	sport->port.uartclk = clk_get_rate(sport->clk);
-
-	ret = serial_pxa_probe_dt(dev, sport);
-	if (ret > 0)
-		sport->port.line = dev->id;
-	else if (ret < 0)
-		goto err_clk;
-	snprintf(sport->name, PXA_NAME_LEN - 1, "UART%d", sport->port.line + 1);
-
-	sport->port.membase = ioremap(mmres->start, resource_size(mmres));
-	if (!sport->port.membase) {
-		ret = -ENOMEM;
-		goto err_clk;
-	}
-
-	serial_pxa_ports[sport->port.line] = sport;
-
-	uart_add_one_port(&serial_pxa_reg, &sport->port);
-	platform_set_drvdata(dev, sport);
-
-	return 0;
-
- err_clk:
-	clk_unprepare(sport->clk);
-	clk_put(sport->clk);
- err_free:
-	kfree(sport);
-	return ret;
-}
-
-static int serial_pxa_remove(struct platform_device *dev)
-{
-	struct uart_pxa_port *sport = platform_get_drvdata(dev);
-
-	uart_remove_one_port(&serial_pxa_reg, &sport->port);
-
-	clk_unprepare(sport->clk);
-	clk_put(sport->clk);
-	kfree(sport);
-
-	return 0;
-}
-
-static struct platform_driver serial_pxa_driver = {
-        .probe          = serial_pxa_probe,
-        .remove         = serial_pxa_remove,
-
-	.driver		= {
-	        .name	= "pxa2xx-uart",
-		.owner	= THIS_MODULE,
-#ifdef CONFIG_PM
-		.pm	= &serial_pxa_pm_ops,
-#endif
-		.of_match_table = serial_pxa_dt_ids,
-	},
-};
-
-static int __init serial_pxa_init(void)
-{
-	int ret;
-
-	ret = uart_register_driver(&serial_pxa_reg);
-	if (ret != 0)
-		return ret;
-
-	ret = platform_driver_register(&serial_pxa_driver);
-	if (ret != 0)
-		uart_unregister_driver(&serial_pxa_reg);
-
-	return ret;
-}
-
-static void __exit serial_pxa_exit(void)
-{
-	platform_driver_unregister(&serial_pxa_driver);
-	uart_unregister_driver(&serial_pxa_reg);
-}
-
-module_init(serial_pxa_init);
-module_exit(serial_pxa_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:pxa2xx-uart");
-- 
1.8.4.2

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

* Re: [PATCH 5/9] ARM: dts: provide DMA config to pxamci
@ 2013-12-09 12:09                   ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-09 12:09 UTC (permalink / raw)
  To: Daniel Mack
  Cc: Arnd Bergmann, linux-kernel, linux-arm-kernel, Rob Herring,
	Pawel Moll, Mark Rutland, Stephen Warren, Ian Campbell,
	Rob Landley, Russell King, Chris Ball, Ulf Hansson,
	Jaehoon Chung, Seungwon Jeon, open list:OPEN FIRMWARE AND...,
	DOCUMENTATION, Robert Jarzmik

On Mon, 2013-12-09 at 11:21 +0100, Daniel Mack wrote:
> On 12/09/2013 10:34 AM, Sergei Ianovich wrote:
> > Nice to have Daniel in this conversation. Your patch series is a big and
> > important work. However, I am not sure I will ever land as is exactly
> > for this reason.
> 
> Well, I wouldn't be so certain about that statement. As I wrote in the
> cover letter, most of the work is actually done, and I successfully
> tested the new DMA support with a some of the drivers I ported. Others
> were ported blindly, and in case of no reaction, I'd dare to merge them
> and wait for people to report back in case of trouble.

If breaking things is an option, I am definitely wrong. I assumed the
opposite.

> > My proposal in to actually add new drivers for each platform device with
> > DMA and mark new ones EXPERIMENTAL.
> 
> That would cause tree-wide cross-dependencies between drivers, because
> the two DMA controllers can't be used at the same time, and the PXA
> specific API will be unavailable when the mmp-dma driver is selected. My
> patch series (and the DMA controller framework for that matter) aims for
> the opposite - the unification of APIs and drivers.

Not sure I got this point. My proposal is to keep the existing DMA
intact until we are ready to remove it. I understand this approach
requires considerably more work inside DMA to allow both driver to
coexist than wholesale replacement. I still think big change is risky.


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

* Re: [PATCH 5/9] ARM: dts: provide DMA config to pxamci
@ 2013-12-09 12:09                   ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-09 12:09 UTC (permalink / raw)
  To: Daniel Mack
  Cc: Arnd Bergmann, linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Rob Herring,
	Pawel Moll, Mark Rutland, Stephen Warren, Ian Campbell,
	Rob Landley, Russell King, Chris Ball, Ulf Hansson,
	Jaehoon Chung, Seungwon Jeon, open list:OPEN FIRMWARE AND...,
	DOCUMENTATION, Robert Jarzmik

On Mon, 2013-12-09 at 11:21 +0100, Daniel Mack wrote:
> On 12/09/2013 10:34 AM, Sergei Ianovich wrote:
> > Nice to have Daniel in this conversation. Your patch series is a big and
> > important work. However, I am not sure I will ever land as is exactly
> > for this reason.
> 
> Well, I wouldn't be so certain about that statement. As I wrote in the
> cover letter, most of the work is actually done, and I successfully
> tested the new DMA support with a some of the drivers I ported. Others
> were ported blindly, and in case of no reaction, I'd dare to merge them
> and wait for people to report back in case of trouble.

If breaking things is an option, I am definitely wrong. I assumed the
opposite.

> > My proposal in to actually add new drivers for each platform device with
> > DMA and mark new ones EXPERIMENTAL.
> 
> That would cause tree-wide cross-dependencies between drivers, because
> the two DMA controllers can't be used at the same time, and the PXA
> specific API will be unavailable when the mmp-dma driver is selected. My
> patch series (and the DMA controller framework for that matter) aims for
> the opposite - the unification of APIs and drivers.

Not sure I got this point. My proposal is to keep the existing DMA
intact until we are ready to remove it. I understand this approach
requires considerably more work inside DMA to allow both driver to
coexist than wholesale replacement. I still think big change is risky.

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH 5/9] ARM: dts: provide DMA config to pxamci
@ 2013-12-09 12:09                   ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-09 12:09 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, 2013-12-09 at 11:21 +0100, Daniel Mack wrote:
> On 12/09/2013 10:34 AM, Sergei Ianovich wrote:
> > Nice to have Daniel in this conversation. Your patch series is a big and
> > important work. However, I am not sure I will ever land as is exactly
> > for this reason.
> 
> Well, I wouldn't be so certain about that statement. As I wrote in the
> cover letter, most of the work is actually done, and I successfully
> tested the new DMA support with a some of the drivers I ported. Others
> were ported blindly, and in case of no reaction, I'd dare to merge them
> and wait for people to report back in case of trouble.

If breaking things is an option, I am definitely wrong. I assumed the
opposite.

> > My proposal in to actually add new drivers for each platform device with
> > DMA and mark new ones EXPERIMENTAL.
> 
> That would cause tree-wide cross-dependencies between drivers, because
> the two DMA controllers can't be used at the same time, and the PXA
> specific API will be unavailable when the mmp-dma driver is selected. My
> patch series (and the DMA controller framework for that matter) aims for
> the opposite - the unification of APIs and drivers.

Not sure I got this point. My proposal is to keep the existing DMA
intact until we are ready to remove it. I understand this approach
requires considerably more work inside DMA to allow both driver to
coexist than wholesale replacement. I still think big change is risky.

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

* Re: [PATCH 5/9] ARM: dts: provide DMA config to pxamci
  2013-12-09 10:21                 ` Daniel Mack
@ 2013-12-09 13:16                   ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-09 13:16 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Daniel Mack, linux-kernel, linux-arm-kernel, Rob Herring,
	Pawel Moll, Mark Rutland, Stephen Warren, Ian Campbell,
	Rob Landley, Russell King, Chris Ball, Ulf Hansson,
	Jaehoon Chung, Seungwon Jeon, open list:OPEN FIRMWARE AND...,
	DOCUMENTATION, Robert Jarzmik

On Mon, 2013-12-09 at 11:21 +0100, Daniel Mack wrote:
> On 12/09/2013 10:34 AM, Sergei Ianovich wrote:
> > On Mon, 2013-12-09 at 10:04 +0100, Daniel Mack wrote:
> >> On 12/09/2013 02:33 AM, Arnd Bergmann wrote:
> >>> It hasn't made it upstream yet, but see http://list-archives.org/2013/08/07/linux-mtd-lists-infradead-org/patch-00-20-arm-pxa-move-core-and-drivers-to-dmaengine/f/3444199144
> >>> for how it's done. Maybe Daniel can comment on the status of his
> >>> patches.
> >>
...
> The only real problem is the PXA camera driver, which does tricky things
> like hot re-queuing of DMA descriptors. That one needs fixing before the
> series can land.

My impression is that his series is hard to land. I've expressed my
concerns about big changes in a separate mail.

PXA device tree support issue is practically orthogonal. As of August
2013, Daniel's dma series doesn't add any dt support. After new DMA is
working, we will need to add dt support in the same drivers.

Basically we have three options:
A. Wait for Daniel DMA, than for PXA clock, than do dt support
 pros: 
 * correct order
 cons:
 * need to wait, possibly a long time
 * dt boot not possible, while we wait

B. Provide 'hackish' support to dt, than correct hacks when DMA is
merged.
 pros:
 * parallel development
 * healthier kernel code (current PXA usb driver won't compile with dt
enabled)
 cons:
 * wrong concept (like my patch 5/9) until DMA is working
 * need to recompile dtb files when kernel changes

C. Use 'fake' DMA provider dt binding to emulate existing DMA until new
DMA is merged, than 
 pros:
 * parallel development
 * healthier kernel code
 * correct device trees from the beginning
 cons:
 * more work
 * still need to recompile dtbs when clock support is merged

Any ideas?


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

* [PATCH 5/9] ARM: dts: provide DMA config to pxamci
@ 2013-12-09 13:16                   ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-09 13:16 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, 2013-12-09 at 11:21 +0100, Daniel Mack wrote:
> On 12/09/2013 10:34 AM, Sergei Ianovich wrote:
> > On Mon, 2013-12-09 at 10:04 +0100, Daniel Mack wrote:
> >> On 12/09/2013 02:33 AM, Arnd Bergmann wrote:
> >>> It hasn't made it upstream yet, but see http://list-archives.org/2013/08/07/linux-mtd-lists-infradead-org/patch-00-20-arm-pxa-move-core-and-drivers-to-dmaengine/f/3444199144
> >>> for how it's done. Maybe Daniel can comment on the status of his
> >>> patches.
> >>
...
> The only real problem is the PXA camera driver, which does tricky things
> like hot re-queuing of DMA descriptors. That one needs fixing before the
> series can land.

My impression is that his series is hard to land. I've expressed my
concerns about big changes in a separate mail.

PXA device tree support issue is practically orthogonal. As of August
2013, Daniel's dma series doesn't add any dt support. After new DMA is
working, we will need to add dt support in the same drivers.

Basically we have three options:
A. Wait for Daniel DMA, than for PXA clock, than do dt support
 pros: 
 * correct order
 cons:
 * need to wait, possibly a long time
 * dt boot not possible, while we wait

B. Provide 'hackish' support to dt, than correct hacks when DMA is
merged.
 pros:
 * parallel development
 * healthier kernel code (current PXA usb driver won't compile with dt
enabled)
 cons:
 * wrong concept (like my patch 5/9) until DMA is working
 * need to recompile dtb files when kernel changes

C. Use 'fake' DMA provider dt binding to emulate existing DMA until new
DMA is merged, than 
 pros:
 * parallel development
 * healthier kernel code
 * correct device trees from the beginning
 cons:
 * more work
 * still need to recompile dtbs when clock support is merged

Any ideas?

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

* Re: [PATCH 3/9] ARM: fix ohci-pxa27x build error with OF enabled
  2013-12-08 22:53         ` Sergei Ianovich
@ 2013-12-09 14:26           ` Steve Cotton
  -1 siblings, 0 replies; 700+ messages in thread
From: Steve Cotton @ 2013-12-09 14:26 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: linux-kernel, linux-arm-kernel, Russell King - ARM Linux,
	Alan Stern, Greg Kroah-Hartman, open list:USB OHCI DRIVER

On Mon, Dec 09, 2013 at 02:53 +0400, Sergei Ianovich wrote:
> --->8---
> $ make
>   CC [M]  drivers/usb/host/ohci-pxa27x.o
> drivers/usb/host/ohci-pxa27x.c: In function ‘ohci_pxa_of_init’:
> drivers/usb/host/ohci-pxa27x.c:310:2: error: implicit declaration of function ‘dma_coerce_mask_and_coherent’ [-Werror=implicit-function-declaration]
> drivers/usb/host/ohci-pxa27x.c:310:2: error: implicit declaration of function ‘DMA_BIT_MASK’ [-Werror=implicit-function-declaration]
> --->8---
> 
> Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
> CC: Russell King - ARM Linux <linux@arm.linux.org.uk>
> 
>  # Changes to be committed:
> ---
>  drivers/usb/host/ohci-pxa27x.c | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c
> index e89ac4d..97983fd 100644
> --- a/drivers/usb/host/ohci-pxa27x.c
> +++ b/drivers/usb/host/ohci-pxa27x.c
> @@ -24,6 +24,7 @@
>  #include <linux/io.h>
>  #include <linux/kernel.h>
>  #include <linux/module.h>
> +#include <linux/dma-mapping.h>
>  #include <linux/of_platform.h>
>  #include <linux/of_gpio.h>
>  #include <linux/platform_data/usb-ohci-pxa27x.h>

Hi Sergei,

There's already a different patch for this
in the linux-next/master and gregkh/usb/usb-linus trees, but
not in the linux-next/stable or gregkh/usb/usb-next trees.

It adds that include 3 lines higher up, to keep the includes in
alphabetical order.

commit 9876388edfa553960815110acae4544359b385b5
Author:     Daniel Mack <zonque@gmail.com>
AuthorDate: Fri Nov 15 14:19:02 2013 +0100
Commit:     Greg Kroah-Hartman <gregkh@linuxfoundation.org>
CommitDate: Wed Dec 4 16:57:46 2013 -0800

Cheers,
Steve

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

* [PATCH 3/9] ARM: fix ohci-pxa27x build error with OF enabled
@ 2013-12-09 14:26           ` Steve Cotton
  0 siblings, 0 replies; 700+ messages in thread
From: Steve Cotton @ 2013-12-09 14:26 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Dec 09, 2013 at 02:53 +0400, Sergei Ianovich wrote:
> --->8---
> $ make
>   CC [M]  drivers/usb/host/ohci-pxa27x.o
> drivers/usb/host/ohci-pxa27x.c: In function ?ohci_pxa_of_init?:
> drivers/usb/host/ohci-pxa27x.c:310:2: error: implicit declaration of function ?dma_coerce_mask_and_coherent? [-Werror=implicit-function-declaration]
> drivers/usb/host/ohci-pxa27x.c:310:2: error: implicit declaration of function ?DMA_BIT_MASK? [-Werror=implicit-function-declaration]
> --->8---
> 
> Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
> CC: Russell King - ARM Linux <linux@arm.linux.org.uk>
> 
>  # Changes to be committed:
> ---
>  drivers/usb/host/ohci-pxa27x.c | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c
> index e89ac4d..97983fd 100644
> --- a/drivers/usb/host/ohci-pxa27x.c
> +++ b/drivers/usb/host/ohci-pxa27x.c
> @@ -24,6 +24,7 @@
>  #include <linux/io.h>
>  #include <linux/kernel.h>
>  #include <linux/module.h>
> +#include <linux/dma-mapping.h>
>  #include <linux/of_platform.h>
>  #include <linux/of_gpio.h>
>  #include <linux/platform_data/usb-ohci-pxa27x.h>

Hi Sergei,

There's already a different patch for this
in the linux-next/master and gregkh/usb/usb-linus trees, but
not in the linux-next/stable or gregkh/usb/usb-next trees.

It adds that include 3 lines higher up, to keep the includes in
alphabetical order.

commit 9876388edfa553960815110acae4544359b385b5
Author:     Daniel Mack <zonque@gmail.com>
AuthorDate: Fri Nov 15 14:19:02 2013 +0100
Commit:     Greg Kroah-Hartman <gregkh@linuxfoundation.org>
CommitDate: Wed Dec 4 16:57:46 2013 -0800

Cheers,
Steve

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

* Re: [PATCH 3/9] ARM: fix ohci-pxa27x build error with OF enabled
  2013-12-09 14:26           ` Steve Cotton
@ 2013-12-09 14:42             ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-09 14:42 UTC (permalink / raw)
  To: Steve Cotton
  Cc: linux-kernel, linux-arm-kernel, Russell King - ARM Linux,
	Alan Stern, Greg Kroah-Hartman, open list:USB OHCI DRIVER

On Mon, 2013-12-09 at 14:26 +0000, Steve Cotton wrote:
> There's already a different patch for this
> in the linux-next/master and gregkh/usb/usb-linus trees, but
> not in the linux-next/stable or gregkh/usb/usb-next trees.
> 
> It adds that include 3 lines higher up, to keep the includes in
> alphabetical order.

Thanks.


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

* [PATCH 3/9] ARM: fix ohci-pxa27x build error with OF enabled
@ 2013-12-09 14:42             ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-09 14:42 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, 2013-12-09 at 14:26 +0000, Steve Cotton wrote:
> There's already a different patch for this
> in the linux-next/master and gregkh/usb/usb-linus trees, but
> not in the linux-next/stable or gregkh/usb/usb-next trees.
> 
> It adds that include 3 lines higher up, to keep the includes in
> alphabetical order.

Thanks.

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

* Re: [PATCH 9/9] ARM: pxa27x: device tree support ICP DAS LP-8x4x
  2013-12-09  1:47           ` Arnd Bergmann
@ 2013-12-09 15:16             ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-09 15:16 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: linux-kernel, linux-arm-kernel, Daniel Mack, Olof Johansson,
	Linus Walleij, Rob Herring, Pawel Moll, Mark Rutland,
	Stephen Warren, Ian Campbell, Russell King, Eric Miao,
	Haojian Zhuang, open list:OPEN FIRMWARE AND...

On Mon, 2013-12-09 at 02:47 +0100, Arnd Bergmann wrote:
> On Sunday 08 December 2013, Sergei Ianovich wrote:
> > +
> > +#ifdef CONFIG_PXA27x
> > +extern void __init pxa27x_dt_init_irq(void);

> This is not the right place to put an 'extern' declaration, it should go into
> a header file if it's really needed. Ideally you would not need it at all
> and just add an IRQCHIP_DECLARE() line into the driver to automatically
> probe it.

I thought I moved it to the header in patch 6/9. I'll just drop the
line.

IRQCHIP_DECLARE isn't used on pxa_internal_irq_chip in
arch/arm/mach-pxa/irq.c, probably for a reason.

> > +static const struct of_dev_auxdata pxa27x_auxdata_lookup[] __initconst = {
> > +     OF_DEV_AUXDATA("mrvl,pxa-uart",         0x40100000, "pxa2xx-uart.0", NULL),
> > +     OF_DEV_AUXDATA("mrvl,pxa-uart",         0x40200000, "pxa2xx-uart.1", NULL),
> > +     OF_DEV_AUXDATA("mrvl,pxa-uart",         0x40700000, "pxa2xx-uart.2", NULL),
> > +     OF_DEV_AUXDATA("mrvl,pxa-uart",         0x41600000, "pxa2xx-uart.3", NULL),
> > +     OF_DEV_AUXDATA("marvell,pxa-mmc",       0x41100000, "pxa2xx-mci.0", NULL),
> > +     OF_DEV_AUXDATA("intel,pxa27x-gpio",     0x40e00000, "pxa27x-gpio", NULL),
> > +     OF_DEV_AUXDATA("marvell,pxa-ohci",      0x4c000000, "pxa27x-ohci", NULL),
> > +     OF_DEV_AUXDATA("mrvl,pxa-i2c",          0x40301680, "pxa2xx-i2c.0", NULL),
> > +     {}
> > +};
> 
> I guess these are needed only for clock management purposes at the moment?

Absolutely.

> > +static void __init pxa27x_init_early(void)
> > +{
> > +     pxa27x_skip_init();
> > +}
> 
> I would prefer not to have an init_early function at all, and instead
> check "if (of_have_populated_dt())" in pxa27x_init, or to split
> that function into two.

Device tree is populated in init_machine. However, pxa27x_init is
executed before via postcore_initcall. The only chance to run before is
to use init_early. What's wrong with this function?

> > +static const char *pxa27x_dt_board_compat[] __initdata = {
> > +     "marvell,pxa27x",
> > +     NULL,
> > +};
> > +
> > +#ifdef CONFIG_MACH_LP8X4X
> > +static const char *lp8x4x_dt_board_compat[] __initdata = {
> > +     "marvell,lp8x4x",
> > +     NULL,
> > +};
> 
> Note that you should not have wildcards in any "compatible" strings.
> Just list all the combinations here (pxa270, pxa271, pxa272, and whatever
> you need for lp8x4x).

Will do.

> > +static void lp8x4x_restart(enum reboot_mode mode, const char *cmd)
> > +{
> > +     /* Switch off fast-bus and turbo mode */
> > +     asm volatile("mcr       p14, 0, %0, c6, c0, 0" : :
> > +                     "r"(2));
> > +     /* SDRAM hangs on watchdog reset on Marvell PXA270 (erratum 71) */
> > +     pxa_restart(REBOOT_SOFT, cmd);
> > +}
> > +#endif
> > +#endif
> 
> Since the only difference here is the restart logic, I would prefer here to
> have only a single DT_MACHINE_START() and do
> 
> static void pxa27x_restart(enum reboot_mode mode, const char *cmd)
> {
>         /* Switch off fast-bus and turbo mode */
>         if (of_machine_is_compatible("marvell,lp8x4x"))
>                 asm volatile("mcr       p14, 0, %0, c6, c0, 0" : : "r"(2));
> 
>         /* SDRAM hangs on watchdog reset on Marvell PXA270 (erratum 71) */
>         if (of_machine_is_compatible("marvell,pxa270"))
>                 pxa_restart(REBOOT_SOFT, cmd);
> }

Nice tip, thanks. I've spent 30 minutes to find something like that.

If the device has fast SDRAM, which can reset itself in up to 8ms, the
device is not affected by E71. So both checks are per-device.



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

* [PATCH 9/9] ARM: pxa27x: device tree support ICP DAS LP-8x4x
@ 2013-12-09 15:16             ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-09 15:16 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, 2013-12-09 at 02:47 +0100, Arnd Bergmann wrote:
> On Sunday 08 December 2013, Sergei Ianovich wrote:
> > +
> > +#ifdef CONFIG_PXA27x
> > +extern void __init pxa27x_dt_init_irq(void);

> This is not the right place to put an 'extern' declaration, it should go into
> a header file if it's really needed. Ideally you would not need it at all
> and just add an IRQCHIP_DECLARE() line into the driver to automatically
> probe it.

I thought I moved it to the header in patch 6/9. I'll just drop the
line.

IRQCHIP_DECLARE isn't used on pxa_internal_irq_chip in
arch/arm/mach-pxa/irq.c, probably for a reason.

> > +static const struct of_dev_auxdata pxa27x_auxdata_lookup[] __initconst = {
> > +     OF_DEV_AUXDATA("mrvl,pxa-uart",         0x40100000, "pxa2xx-uart.0", NULL),
> > +     OF_DEV_AUXDATA("mrvl,pxa-uart",         0x40200000, "pxa2xx-uart.1", NULL),
> > +     OF_DEV_AUXDATA("mrvl,pxa-uart",         0x40700000, "pxa2xx-uart.2", NULL),
> > +     OF_DEV_AUXDATA("mrvl,pxa-uart",         0x41600000, "pxa2xx-uart.3", NULL),
> > +     OF_DEV_AUXDATA("marvell,pxa-mmc",       0x41100000, "pxa2xx-mci.0", NULL),
> > +     OF_DEV_AUXDATA("intel,pxa27x-gpio",     0x40e00000, "pxa27x-gpio", NULL),
> > +     OF_DEV_AUXDATA("marvell,pxa-ohci",      0x4c000000, "pxa27x-ohci", NULL),
> > +     OF_DEV_AUXDATA("mrvl,pxa-i2c",          0x40301680, "pxa2xx-i2c.0", NULL),
> > +     {}
> > +};
> 
> I guess these are needed only for clock management purposes at the moment?

Absolutely.

> > +static void __init pxa27x_init_early(void)
> > +{
> > +     pxa27x_skip_init();
> > +}
> 
> I would prefer not to have an init_early function at all, and instead
> check "if (of_have_populated_dt())" in pxa27x_init, or to split
> that function into two.

Device tree is populated in init_machine. However, pxa27x_init is
executed before via postcore_initcall. The only chance to run before is
to use init_early. What's wrong with this function?

> > +static const char *pxa27x_dt_board_compat[] __initdata = {
> > +     "marvell,pxa27x",
> > +     NULL,
> > +};
> > +
> > +#ifdef CONFIG_MACH_LP8X4X
> > +static const char *lp8x4x_dt_board_compat[] __initdata = {
> > +     "marvell,lp8x4x",
> > +     NULL,
> > +};
> 
> Note that you should not have wildcards in any "compatible" strings.
> Just list all the combinations here (pxa270, pxa271, pxa272, and whatever
> you need for lp8x4x).

Will do.

> > +static void lp8x4x_restart(enum reboot_mode mode, const char *cmd)
> > +{
> > +     /* Switch off fast-bus and turbo mode */
> > +     asm volatile("mcr       p14, 0, %0, c6, c0, 0" : :
> > +                     "r"(2));
> > +     /* SDRAM hangs on watchdog reset on Marvell PXA270 (erratum 71) */
> > +     pxa_restart(REBOOT_SOFT, cmd);
> > +}
> > +#endif
> > +#endif
> 
> Since the only difference here is the restart logic, I would prefer here to
> have only a single DT_MACHINE_START() and do
> 
> static void pxa27x_restart(enum reboot_mode mode, const char *cmd)
> {
>         /* Switch off fast-bus and turbo mode */
>         if (of_machine_is_compatible("marvell,lp8x4x"))
>                 asm volatile("mcr       p14, 0, %0, c6, c0, 0" : : "r"(2));
> 
>         /* SDRAM hangs on watchdog reset on Marvell PXA270 (erratum 71) */
>         if (of_machine_is_compatible("marvell,pxa270"))
>                 pxa_restart(REBOOT_SOFT, cmd);
> }

Nice tip, thanks. I've spent 30 minutes to find something like that.

If the device has fast SDRAM, which can reset itself in up to 8ms, the
device is not affected by E71. So both checks are per-device.

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

* Re: [PATCH 7/9] ARM: dts: pxa27x: skip static platform devices
  2013-12-08 22:53         ` Sergei Ianovich
  (?)
@ 2013-12-09 15:26         ` Dmitry Eremin-Solenikov
  -1 siblings, 0 replies; 700+ messages in thread
From: Dmitry Eremin-Solenikov @ 2013-12-09 15:26 UTC (permalink / raw)
  To: linux-kernel; +Cc: linux-arm-kernel

Hello,

On Mon, 09 Dec 2013 02:53:47 +0400, Sergei Ianovich wrote:

> Static plaform devices are created from postcore_initcall(). The status
> quo remains for non-device tree machines.
> 
> Device tree machine now have a chance to prevent spawning of static
> devices by calling pxa27x_skip_init().
> 
> Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
> CC: Russell King - ARM Linux <linux@arm.linux.org.uk>
> CC: Daniel Mack <zonque@gmail.com>
> CC: Arnd Bergmann <arnd@arndb.de>
> ---
>  arch/arm/mach-pxa/include/mach/pxa27x.h |  1 +
>  arch/arm/mach-pxa/pxa27x.c              | 10 ++++++++++ 2 files
>  changed, 11 insertions(+)

I would suggest to copy the corresponding code from pxa3xx.c - use 
of_have_populated_dt() instead of adding extra static variable.

-- 
With best wishes
Dmitry



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

* Re: [PATCH 9/9] ARM: pxa27x: device tree support ICP DAS LP-8x4x
  2013-12-09 15:16             ` Sergei Ianovich
@ 2013-12-09 15:55               ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-09 15:55 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: linux-kernel, linux-arm-kernel, Daniel Mack, Olof Johansson,
	Linus Walleij, Rob Herring, Pawel Moll, Mark Rutland,
	Stephen Warren, Ian Campbell, Russell King, Eric Miao,
	Haojian Zhuang, open list:OPEN FIRMWARE AND...,
	Dmitry Eremin-Solenikov

On Mon, 2013-12-09 at 19:16 +0400, Sergei Ianovich wrote:
> On Mon, 2013-12-09 at 02:47 +0100, Arnd Bergmann wrote:
> > On Sunday 08 December 2013, Sergei Ianovich wrote:
> > > +
> > > +#ifdef CONFIG_PXA27x
> > > +extern void __init pxa27x_dt_init_irq(void);
> 
> > > +static void __init pxa27x_init_early(void)
> > > +{
> > > +     pxa27x_skip_init();
> > > +}
> > 
> > I would prefer not to have an init_early function at all, and instead
> > check "if (of_have_populated_dt())" in pxa27x_init, or to split
> > that function into two.

Although this is counterintuitive, it works. Since of_populate_dt() is
not required for of_have_populated_dt() to return true, should we rename
of_have_populated_dt() to of_have_dt()?

> Device tree is populated in init_machine. However, pxa27x_init is
> executed before via postcore_initcall. The only chance to run before is
> to use init_early. What's wrong with this function?

I was wrong.


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

* [PATCH 9/9] ARM: pxa27x: device tree support ICP DAS LP-8x4x
@ 2013-12-09 15:55               ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-09 15:55 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, 2013-12-09 at 19:16 +0400, Sergei Ianovich wrote:
> On Mon, 2013-12-09 at 02:47 +0100, Arnd Bergmann wrote:
> > On Sunday 08 December 2013, Sergei Ianovich wrote:
> > > +
> > > +#ifdef CONFIG_PXA27x
> > > +extern void __init pxa27x_dt_init_irq(void);
> 
> > > +static void __init pxa27x_init_early(void)
> > > +{
> > > +     pxa27x_skip_init();
> > > +}
> > 
> > I would prefer not to have an init_early function at all, and instead
> > check "if (of_have_populated_dt())" in pxa27x_init, or to split
> > that function into two.

Although this is counterintuitive, it works. Since of_populate_dt() is
not required for of_have_populated_dt() to return true, should we rename
of_have_populated_dt() to of_have_dt()?

> Device tree is populated in init_machine. However, pxa27x_init is
> executed before via postcore_initcall. The only chance to run before is
> to use init_early. What's wrong with this function?

I was wrong.

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

* Re: [PATCH 9/9] ARM: pxa27x: device tree support ICP DAS LP-8x4x
  2013-12-09 15:16             ` Sergei Ianovich
@ 2013-12-09 16:25               ` Arnd Bergmann
  -1 siblings, 0 replies; 700+ messages in thread
From: Arnd Bergmann @ 2013-12-09 16:25 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: linux-kernel, linux-arm-kernel, Daniel Mack, Olof Johansson,
	Linus Walleij, Rob Herring, Pawel Moll, Mark Rutland,
	Stephen Warren, Ian Campbell, Russell King, Eric Miao,
	Haojian Zhuang, open list:OPEN FIRMWARE AND...

On Monday 09 December 2013, Sergei Ianovich wrote:
> On Mon, 2013-12-09 at 02:47 +0100, Arnd Bergmann wrote:
> > On Sunday 08 December 2013, Sergei Ianovich wrote:
> > > +
> > > +#ifdef CONFIG_PXA27x
> > > +extern void __init pxa27x_dt_init_irq(void);
> 
> > This is not the right place to put an 'extern' declaration, it should go into
> > a header file if it's really needed. Ideally you would not need it at all
> > and just add an IRQCHIP_DECLARE() line into the driver to automatically
> > probe it.
> 
> I thought I moved it to the header in patch 6/9. I'll just drop the
> line.

Ok.

> IRQCHIP_DECLARE isn't used on pxa_internal_irq_chip in
> arch/arm/mach-pxa/irq.c, probably for a reason.

Yes, you can only use it from drivers in drivers/irqchip/.

> > > +static void __init pxa27x_init_early(void)
> > > +{
> > > +     pxa27x_skip_init();
> > > +}
> > 
> > I would prefer not to have an init_early function at all, and instead
> > check "if (of_have_populated_dt())" in pxa27x_init, or to split
> > that function into two.
> 
> Device tree is populated in init_machine. However, pxa27x_init is
> executed before via postcore_initcall. 

The device tree is populated in unflatten_device_tree(), which gets
called before init_early.

> The only chance to run before is
> to use init_early. What's wrong with this function?

I generally dislike adding any platform specific hooks to "early"
functions, i.e. stuff that runs before init_machine, and I'm pretty
sure it's not necessary here.

> > static void pxa27x_restart(enum reboot_mode mode, const char *cmd)
> > {
> >         /* Switch off fast-bus and turbo mode */
> >         if (of_machine_is_compatible("marvell,lp8x4x"))
> >                 asm volatile("mcr       p14, 0, %0, c6, c0, 0" : : "r"(2));
> > 
> >         /* SDRAM hangs on watchdog reset on Marvell PXA270 (erratum 71) */
> >         if (of_machine_is_compatible("marvell,pxa270"))
> >                 pxa_restart(REBOOT_SOFT, cmd);
> > }
> 
> Nice tip, thanks. I've spent 30 minutes to find something like that.
> 
> If the device has fast SDRAM, which can reset itself in up to 8ms, the
> device is not affected by E71. So both checks are per-device.

Ok.

	Arnd

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

* [PATCH 9/9] ARM: pxa27x: device tree support ICP DAS LP-8x4x
@ 2013-12-09 16:25               ` Arnd Bergmann
  0 siblings, 0 replies; 700+ messages in thread
From: Arnd Bergmann @ 2013-12-09 16:25 UTC (permalink / raw)
  To: linux-arm-kernel

On Monday 09 December 2013, Sergei Ianovich wrote:
> On Mon, 2013-12-09 at 02:47 +0100, Arnd Bergmann wrote:
> > On Sunday 08 December 2013, Sergei Ianovich wrote:
> > > +
> > > +#ifdef CONFIG_PXA27x
> > > +extern void __init pxa27x_dt_init_irq(void);
> 
> > This is not the right place to put an 'extern' declaration, it should go into
> > a header file if it's really needed. Ideally you would not need it at all
> > and just add an IRQCHIP_DECLARE() line into the driver to automatically
> > probe it.
> 
> I thought I moved it to the header in patch 6/9. I'll just drop the
> line.

Ok.

> IRQCHIP_DECLARE isn't used on pxa_internal_irq_chip in
> arch/arm/mach-pxa/irq.c, probably for a reason.

Yes, you can only use it from drivers in drivers/irqchip/.

> > > +static void __init pxa27x_init_early(void)
> > > +{
> > > +     pxa27x_skip_init();
> > > +}
> > 
> > I would prefer not to have an init_early function at all, and instead
> > check "if (of_have_populated_dt())" in pxa27x_init, or to split
> > that function into two.
> 
> Device tree is populated in init_machine. However, pxa27x_init is
> executed before via postcore_initcall. 

The device tree is populated in unflatten_device_tree(), which gets
called before init_early.

> The only chance to run before is
> to use init_early. What's wrong with this function?

I generally dislike adding any platform specific hooks to "early"
functions, i.e. stuff that runs before init_machine, and I'm pretty
sure it's not necessary here.

> > static void pxa27x_restart(enum reboot_mode mode, const char *cmd)
> > {
> >         /* Switch off fast-bus and turbo mode */
> >         if (of_machine_is_compatible("marvell,lp8x4x"))
> >                 asm volatile("mcr       p14, 0, %0, c6, c0, 0" : : "r"(2));
> > 
> >         /* SDRAM hangs on watchdog reset on Marvell PXA270 (erratum 71) */
> >         if (of_machine_is_compatible("marvell,pxa270"))
> >                 pxa_restart(REBOOT_SOFT, cmd);
> > }
> 
> Nice tip, thanks. I've spent 30 minutes to find something like that.
> 
> If the device has fast SDRAM, which can reset itself in up to 8ms, the
> device is not affected by E71. So both checks are per-device.

Ok.

	Arnd

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

* Re: [PATCH 9/9] ARM: pxa27x: device tree support ICP DAS LP-8x4x
@ 2013-12-09 16:39                 ` Arnd Bergmann
  0 siblings, 0 replies; 700+ messages in thread
From: Arnd Bergmann @ 2013-12-09 16:39 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: linux-kernel, linux-arm-kernel, Daniel Mack, Olof Johansson,
	Linus Walleij, Rob Herring, Pawel Moll, Mark Rutland,
	Stephen Warren, Ian Campbell, Russell King, Eric Miao,
	Haojian Zhuang, open list:OPEN FIRMWARE AND...,
	Dmitry Eremin-Solenikov

On Monday 09 December 2013, Sergei Ianovich wrote:
> anovich wrote:
> > On Mon, 2013-12-09 at 02:47 +0100, Arnd Bergmann wrote:
> > > On Sunday 08 December 2013, Sergei Ianovich wrote:
> > > > +
> > > > +#ifdef CONFIG_PXA27x
> > > > +extern void __init pxa27x_dt_init_irq(void);
> > 
> > > > +static void __init pxa27x_init_early(void)
> > > > +{
> > > > +     pxa27x_skip_init();
> > > > +}
> > > 
> > > I would prefer not to have an init_early function at all, and instead
> > > check "if (of_have_populated_dt())" in pxa27x_init, or to split
> > > that function into two.
> 
> Although this is counterintuitive, it works. Since of_populate_dt() is
> not required for of_have_populated_dt() to return true, should we rename
> of_have_populated_dt() to of_have_dt()?

I don't think it's worth the change. The explanation for the current
terminoligy is that of_unflatten() populates the DT device_node structures
in the kernel from the FTD blob, while of_platform_populate populates the
platform_device infrastructure from the device nodes.

	Arnd

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

* Re: [PATCH 9/9] ARM: pxa27x: device tree support ICP DAS LP-8x4x
@ 2013-12-09 16:39                 ` Arnd Bergmann
  0 siblings, 0 replies; 700+ messages in thread
From: Arnd Bergmann @ 2013-12-09 16:39 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Daniel Mack,
	Olof Johansson, Linus Walleij, Rob Herring, Pawel Moll,
	Mark Rutland, Stephen Warren, Ian Campbell, Russell King,
	Eric Miao, Haojian Zhuang, open list:OPEN FIRMWARE AND...,
	Dmitry Eremin-Solenikov

On Monday 09 December 2013, Sergei Ianovich wrote:
> anovich wrote:
> > On Mon, 2013-12-09 at 02:47 +0100, Arnd Bergmann wrote:
> > > On Sunday 08 December 2013, Sergei Ianovich wrote:
> > > > +
> > > > +#ifdef CONFIG_PXA27x
> > > > +extern void __init pxa27x_dt_init_irq(void);
> > 
> > > > +static void __init pxa27x_init_early(void)
> > > > +{
> > > > +     pxa27x_skip_init();
> > > > +}
> > > 
> > > I would prefer not to have an init_early function at all, and instead
> > > check "if (of_have_populated_dt())" in pxa27x_init, or to split
> > > that function into two.
> 
> Although this is counterintuitive, it works. Since of_populate_dt() is
> not required for of_have_populated_dt() to return true, should we rename
> of_have_populated_dt() to of_have_dt()?

I don't think it's worth the change. The explanation for the current
terminoligy is that of_unflatten() populates the DT device_node structures
in the kernel from the FTD blob, while of_platform_populate populates the
platform_device infrastructure from the device nodes.

	Arnd
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH 9/9] ARM: pxa27x: device tree support ICP DAS LP-8x4x
@ 2013-12-09 16:39                 ` Arnd Bergmann
  0 siblings, 0 replies; 700+ messages in thread
From: Arnd Bergmann @ 2013-12-09 16:39 UTC (permalink / raw)
  To: linux-arm-kernel

On Monday 09 December 2013, Sergei Ianovich wrote:
> anovich wrote:
> > On Mon, 2013-12-09 at 02:47 +0100, Arnd Bergmann wrote:
> > > On Sunday 08 December 2013, Sergei Ianovich wrote:
> > > > +
> > > > +#ifdef CONFIG_PXA27x
> > > > +extern void __init pxa27x_dt_init_irq(void);
> > 
> > > > +static void __init pxa27x_init_early(void)
> > > > +{
> > > > +     pxa27x_skip_init();
> > > > +}
> > > 
> > > I would prefer not to have an init_early function at all, and instead
> > > check "if (of_have_populated_dt())" in pxa27x_init, or to split
> > > that function into two.
> 
> Although this is counterintuitive, it works. Since of_populate_dt() is
> not required for of_have_populated_dt() to return true, should we rename
> of_have_populated_dt() to of_have_dt()?

I don't think it's worth the change. The explanation for the current
terminoligy is that of_unflatten() populates the DT device_node structures
in the kernel from the FTD blob, while of_platform_populate populates the
platform_device infrastructure from the device nodes.

	Arnd

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

* Re: [PATCH 0/9] ARM: support for ICP DAS LP-8x4x (with dts)
  2013-12-09  1:51         ` Arnd Bergmann
@ 2013-12-09 18:44           ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-09 18:44 UTC (permalink / raw)
  To: Arnd Bergmann; +Cc: linux-kernel, linux-arm-kernel, Daniel Mack

On Mon, 2013-12-09 at 02:51 +0100, Arnd Bergmann wrote:
> On Sunday 08 December 2013, Sergei Ianovich wrote:
> > 
> > Except for defconfig, this is a completely new series. The first
> > eight patches fix outstanding issues with device tree support
> > in PXA. The 9th boots ICP DAS LP-8x4x.
> 
> Awesome! That was very quick. The main comment I have is for the
> dmaengine support, you will need to rebase on Daniel's patches for
> that. I also found few minor details.

Thanks for review.

I've applied and tested changes to meet review remarks for all patches,
except 5/9. However, there is no point to respin the series until the
decision about DMA is made.

Daniel, could please CC me when you post update pxa-dma series?



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

* [PATCH 0/9] ARM: support for ICP DAS LP-8x4x (with dts)
@ 2013-12-09 18:44           ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-09 18:44 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, 2013-12-09 at 02:51 +0100, Arnd Bergmann wrote:
> On Sunday 08 December 2013, Sergei Ianovich wrote:
> > 
> > Except for defconfig, this is a completely new series. The first
> > eight patches fix outstanding issues with device tree support
> > in PXA. The 9th boots ICP DAS LP-8x4x.
> 
> Awesome! That was very quick. The main comment I have is for the
> dmaengine support, you will need to rebase on Daniel's patches for
> that. I also found few minor details.

Thanks for review.

I've applied and tested changes to meet review remarks for all patches,
except 5/9. However, there is no point to respin the series until the
decision about DMA is made.

Daniel, could please CC me when you post update pxa-dma series?

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

* Re: [PATCH 5/9] ARM: dts: provide DMA config to pxamci
  2013-12-09 12:09                   ` Sergei Ianovich
@ 2013-12-10  0:25                     ` Arnd Bergmann
  -1 siblings, 0 replies; 700+ messages in thread
From: Arnd Bergmann @ 2013-12-10  0:25 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: Daniel Mack, linux-kernel, linux-arm-kernel, Rob Herring,
	Pawel Moll, Mark Rutland, Stephen Warren, Ian Campbell,
	Rob Landley, Russell King, Chris Ball, Ulf Hansson,
	Jaehoon Chung, Seungwon Jeon, open list:OPEN FIRMWARE AND...,
	DOCUMENTATION, Robert Jarzmik

On Monday 09 December 2013, Sergei Ianovich wrote:
> On Mon, 2013-12-09 at 11:21 +0100, Daniel Mack wrote:
> > On 12/09/2013 10:34 AM, Sergei Ianovich wrote:
> > > Nice to have Daniel in this conversation. Your patch series is a big and
> > > important work. However, I am not sure I will ever land as is exactly
> > > for this reason.
> > 
> > Well, I wouldn't be so certain about that statement. As I wrote in the
> > cover letter, most of the work is actually done, and I successfully
> > tested the new DMA support with a some of the drivers I ported. Others
> > were ported blindly, and in case of no reaction, I'd dare to merge them
> > and wait for people to report back in case of trouble.
> 
> If breaking things is an option, I am definitely wrong. I assumed the
> opposite.

We never intentionally break things that people are using, but there are
cases where doing blind changes is the best way forward. We should
always try to find people to test patches on real hardware if possible,
which is only possible if there are people around that have the hardware
and that are going to run new kernels on them.

In case of PXA dmaengine support, I think the benefits of applying the
series far outweigh the breakage potential. A lot of the drivers are
shared with MMP, which is going to be DT-only eventually and will require
the new dmaengine code. Some PXA drivers may be shared with SA1100,
which has also converted to dmaengine although there are no plans to
ever support DT on sa1100.

> > > My proposal in to actually add new drivers for each platform device with
> > > DMA and mark new ones EXPERIMENTAL.
> > 
> > That would cause tree-wide cross-dependencies between drivers, because
> > the two DMA controllers can't be used at the same time, and the PXA
> > specific API will be unavailable when the mmp-dma driver is selected. My
> > patch series (and the DMA controller framework for that matter) aims for
> > the opposite - the unification of APIs and drivers.
> 
> Not sure I got this point. My proposal is to keep the existing DMA
> intact until we are ready to remove it. I understand this approach
> requires considerably more work inside DMA to allow both driver to
> coexist than wholesale replacement. I still think big change is risky.

We certainly need to be extra careful if we want to move things over
at once and cannot test all the drivers. I'd be happier if it could
be done gradually by having some drivers use the new interface and
other drivers use the old one, but I don't see how that can be done
here.

	Arnd

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

* [PATCH 5/9] ARM: dts: provide DMA config to pxamci
@ 2013-12-10  0:25                     ` Arnd Bergmann
  0 siblings, 0 replies; 700+ messages in thread
From: Arnd Bergmann @ 2013-12-10  0:25 UTC (permalink / raw)
  To: linux-arm-kernel

On Monday 09 December 2013, Sergei Ianovich wrote:
> On Mon, 2013-12-09 at 11:21 +0100, Daniel Mack wrote:
> > On 12/09/2013 10:34 AM, Sergei Ianovich wrote:
> > > Nice to have Daniel in this conversation. Your patch series is a big and
> > > important work. However, I am not sure I will ever land as is exactly
> > > for this reason.
> > 
> > Well, I wouldn't be so certain about that statement. As I wrote in the
> > cover letter, most of the work is actually done, and I successfully
> > tested the new DMA support with a some of the drivers I ported. Others
> > were ported blindly, and in case of no reaction, I'd dare to merge them
> > and wait for people to report back in case of trouble.
> 
> If breaking things is an option, I am definitely wrong. I assumed the
> opposite.

We never intentionally break things that people are using, but there are
cases where doing blind changes is the best way forward. We should
always try to find people to test patches on real hardware if possible,
which is only possible if there are people around that have the hardware
and that are going to run new kernels on them.

In case of PXA dmaengine support, I think the benefits of applying the
series far outweigh the breakage potential. A lot of the drivers are
shared with MMP, which is going to be DT-only eventually and will require
the new dmaengine code. Some PXA drivers may be shared with SA1100,
which has also converted to dmaengine although there are no plans to
ever support DT on sa1100.

> > > My proposal in to actually add new drivers for each platform device with
> > > DMA and mark new ones EXPERIMENTAL.
> > 
> > That would cause tree-wide cross-dependencies between drivers, because
> > the two DMA controllers can't be used at the same time, and the PXA
> > specific API will be unavailable when the mmp-dma driver is selected. My
> > patch series (and the DMA controller framework for that matter) aims for
> > the opposite - the unification of APIs and drivers.
> 
> Not sure I got this point. My proposal is to keep the existing DMA
> intact until we are ready to remove it. I understand this approach
> requires considerably more work inside DMA to allow both driver to
> coexist than wholesale replacement. I still think big change is risky.

We certainly need to be extra careful if we want to move things over
at once and cannot test all the drivers. I'd be happier if it could
be done gradually by having some drivers use the new interface and
other drivers use the old one, but I don't see how that can be done
here.

	Arnd

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

* Re: [PATCH 5/9] ARM: dts: provide DMA config to pxamci
  2013-12-10  0:25                     ` Arnd Bergmann
@ 2013-12-10  4:25                       ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-10  4:25 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Daniel Mack, linux-kernel, linux-arm-kernel, Rob Herring,
	Pawel Moll, Mark Rutland, Stephen Warren, Ian Campbell,
	Rob Landley, Russell King, Chris Ball, Ulf Hansson,
	Jaehoon Chung, Seungwon Jeon, open list:OPEN FIRMWARE AND...,
	DOCUMENTATION, Robert Jarzmik

On Tue, 2013-12-10 at 01:25 +0100, Arnd Bergmann wrote:
> We never intentionally break things that people are using, but there are
> cases where doing blind changes is the best way forward. We should
> always try to find people to test patches on real hardware if possible,
> which is only possible if there are people around that have the hardware
> and that are going to run new kernels on them.
> 
> In case of PXA dmaengine support, I think the benefits of applying the
> series far outweigh the breakage potential. A lot of the drivers are
> shared with MMP, which is going to be DT-only eventually and will require
> the new dmaengine code. Some PXA drivers may be shared with SA1100,
> which has also converted to dmaengine although there are no plans to
> ever support DT on sa1100.
> 
> We certainly need to be extra careful if we want to move things over
> at once and cannot test all the drivers. I'd be happier if it could
> be done gradually by having some drivers use the new interface and
> other drivers use the old one, but I don't see how that can be done
> here.

Thanks for detailed explanation. I see there is strong support for the
big change. Lets hope it'll be smooth. I'll strest test Daniel's changes
and report the results.



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

* [PATCH 5/9] ARM: dts: provide DMA config to pxamci
@ 2013-12-10  4:25                       ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-10  4:25 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, 2013-12-10 at 01:25 +0100, Arnd Bergmann wrote:
> We never intentionally break things that people are using, but there are
> cases where doing blind changes is the best way forward. We should
> always try to find people to test patches on real hardware if possible,
> which is only possible if there are people around that have the hardware
> and that are going to run new kernels on them.
> 
> In case of PXA dmaengine support, I think the benefits of applying the
> series far outweigh the breakage potential. A lot of the drivers are
> shared with MMP, which is going to be DT-only eventually and will require
> the new dmaengine code. Some PXA drivers may be shared with SA1100,
> which has also converted to dmaengine although there are no plans to
> ever support DT on sa1100.
> 
> We certainly need to be extra careful if we want to move things over
> at once and cannot test all the drivers. I'd be happier if it could
> be done gradually by having some drivers use the new interface and
> other drivers use the old one, but I don't see how that can be done
> here.

Thanks for detailed explanation. I see there is strong support for the
big change. Lets hope it'll be smooth. I'll strest test Daniel's changes
and report the results.

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

* Re: [PATCH 02/11] arm: pxa27x: support ICP DAS LP-8x4x
  2013-12-06 17:14         ` Arnd Bergmann
@ 2013-12-10 12:33           ` Linus Walleij
  -1 siblings, 0 replies; 700+ messages in thread
From: Linus Walleij @ 2013-12-10 12:33 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Sergei Ianovich, linux-arm-kernel, linux-kernel, Eric Miao,
	Russell King, Haojian Zhuang, Olof Johansson, Daniel Mack

On Fri, Dec 6, 2013 at 6:14 PM, Arnd Bergmann <arnd@arndb.de> wrote:
> On Friday 06 December 2013, Sergei Ianovich wrote:
>> On Fri, 2013-12-06 at 01:40 +0100, Arnd Bergmann wrote:
>>
>> > > +
>> > > +static struct irq_chip lp8x4x_irq_chip = {
>> > > +     .name                   = "FPGA",
>> > > +     .irq_ack                = lp8x4x_ack_irq,
>> > > +     .irq_mask               = lp8x4x_mask_irq,
>> > > +     .irq_unmask             = lp8x4x_unmask_irq,
>> > > +};
>> >
>> > Please try to move the irqchip code to drivers/irqchip/.
>>
>> CONFIG_IRQCHIP depends on CONFIG_OF_IRQ which in turn depends on Open
>> Firmware.
>
> Hmm, I wonder if we should try to change Kconfig then. Let's leave it
> alone for now, maybe Linus Walleij has some comments since he has
> been looking into moving drivers out in the past.

I don't get this, if the subarch has deps in place for IRQCHIP and
OF_IRQ just move the implementation to drivers/irqchip/foo.c
edit drivers/irqchip/Makefile to compile the file for ARCH_FOO.
What would the problem be? It's not like having the irqchip in the
object is optional...

I would prefer if you augment the code to use
IRQCHIP_DECLARE() so you can get rid of all the criss-cross
calls, but this init contains a comment saying that GPIO
has to be up before you initialize the irq_chip, can you please
explain why it's like that?

Another way is to create a separate Kconfig entry for it in
drivers/irqchip/Kconfig if you want the set-up to be more
distributed, but that is usually just done when the irqchip is
used on more than one platform.

Yours,
Linus Walleij

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

* [PATCH 02/11] arm: pxa27x: support ICP DAS LP-8x4x
@ 2013-12-10 12:33           ` Linus Walleij
  0 siblings, 0 replies; 700+ messages in thread
From: Linus Walleij @ 2013-12-10 12:33 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Dec 6, 2013 at 6:14 PM, Arnd Bergmann <arnd@arndb.de> wrote:
> On Friday 06 December 2013, Sergei Ianovich wrote:
>> On Fri, 2013-12-06 at 01:40 +0100, Arnd Bergmann wrote:
>>
>> > > +
>> > > +static struct irq_chip lp8x4x_irq_chip = {
>> > > +     .name                   = "FPGA",
>> > > +     .irq_ack                = lp8x4x_ack_irq,
>> > > +     .irq_mask               = lp8x4x_mask_irq,
>> > > +     .irq_unmask             = lp8x4x_unmask_irq,
>> > > +};
>> >
>> > Please try to move the irqchip code to drivers/irqchip/.
>>
>> CONFIG_IRQCHIP depends on CONFIG_OF_IRQ which in turn depends on Open
>> Firmware.
>
> Hmm, I wonder if we should try to change Kconfig then. Let's leave it
> alone for now, maybe Linus Walleij has some comments since he has
> been looking into moving drivers out in the past.

I don't get this, if the subarch has deps in place for IRQCHIP and
OF_IRQ just move the implementation to drivers/irqchip/foo.c
edit drivers/irqchip/Makefile to compile the file for ARCH_FOO.
What would the problem be? It's not like having the irqchip in the
object is optional...

I would prefer if you augment the code to use
IRQCHIP_DECLARE() so you can get rid of all the criss-cross
calls, but this init contains a comment saying that GPIO
has to be up before you initialize the irq_chip, can you please
explain why it's like that?

Another way is to create a separate Kconfig entry for it in
drivers/irqchip/Kconfig if you want the set-up to be more
distributed, but that is usually just done when the irqchip is
used on more than one platform.

Yours,
Linus Walleij

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

* Re: [PATCH v2 02/11] arm: pxa27x: support ICP DAS LP-8x4x
  2013-12-06 16:48     ` Sergei Ianovich
@ 2013-12-10 12:43       ` Linus Walleij
  -1 siblings, 0 replies; 700+ messages in thread
From: Linus Walleij @ 2013-12-10 12:43 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: linux-kernel, linux-arm-kernel, Eric Miao, Russell King,
	Haojian Zhuang, Arnd Bergmann, Haojian Zhuang

On Fri, Dec 6, 2013 at 5:48 PM, Sergei Ianovich <ynvich@gmail.com> wrote:

> ICP DAS calls LP-8x4x 'programmable automation controller'. It is
> an industrial computer based on PXA270 SoC. They ship it with a 2.6.19
> kernel and proprietary kernel module and userspace library to access
> its industrial IO.

OK... so we only have device tree support for PXA3xx and noone is
working on PXA2xx. And now we pile up some more legacy code.
Such is life. But this:

> +static unsigned long lp8x4x_pin_config[] = {
> +       /* MMC */
> +       GPIO32_MMC_CLK,
> +       GPIO112_MMC_CMD,
> +       GPIO92_MMC_DAT_0,
> +       GPIO109_MMC_DAT_1,
> +       GPIO110_MMC_DAT_2,
> +       GPIO111_MMC_DAT_3,
> +
> +       /* USB Host Port 1 */
> +       GPIO88_USBH1_PWR,
> +       GPIO89_USBH1_PEN,
> +};

(...)
> +static void __init lp8x4x_init(void)
> +{
> +       pxa2xx_mfp_config(ARRAY_AND_SIZE(lp8x4x_pin_config));
(...)

Argh! Now you're adding another user for a legacy custom pin control
implementation. But if noone is going to modernize PXA2xx what
can we do :-/

Yours,
Linus Walleij

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

* [PATCH v2 02/11] arm: pxa27x: support ICP DAS LP-8x4x
@ 2013-12-10 12:43       ` Linus Walleij
  0 siblings, 0 replies; 700+ messages in thread
From: Linus Walleij @ 2013-12-10 12:43 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Dec 6, 2013 at 5:48 PM, Sergei Ianovich <ynvich@gmail.com> wrote:

> ICP DAS calls LP-8x4x 'programmable automation controller'. It is
> an industrial computer based on PXA270 SoC. They ship it with a 2.6.19
> kernel and proprietary kernel module and userspace library to access
> its industrial IO.

OK... so we only have device tree support for PXA3xx and noone is
working on PXA2xx. And now we pile up some more legacy code.
Such is life. But this:

> +static unsigned long lp8x4x_pin_config[] = {
> +       /* MMC */
> +       GPIO32_MMC_CLK,
> +       GPIO112_MMC_CMD,
> +       GPIO92_MMC_DAT_0,
> +       GPIO109_MMC_DAT_1,
> +       GPIO110_MMC_DAT_2,
> +       GPIO111_MMC_DAT_3,
> +
> +       /* USB Host Port 1 */
> +       GPIO88_USBH1_PWR,
> +       GPIO89_USBH1_PEN,
> +};

(...)
> +static void __init lp8x4x_init(void)
> +{
> +       pxa2xx_mfp_config(ARRAY_AND_SIZE(lp8x4x_pin_config));
(...)

Argh! Now you're adding another user for a legacy custom pin control
implementation. But if noone is going to modernize PXA2xx what
can we do :-/

Yours,
Linus Walleij

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

* Re: [PATCH v2 02/11] arm: pxa27x: support ICP DAS LP-8x4x
  2013-12-10 12:43       ` Linus Walleij
@ 2013-12-10 12:47         ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-10 12:47 UTC (permalink / raw)
  To: Linus Walleij
  Cc: linux-kernel, linux-arm-kernel, Eric Miao, Russell King,
	Haojian Zhuang, Arnd Bergmann, Haojian Zhuang

On Tue, 2013-12-10 at 13:43 +0100, Linus Walleij wrote:
> Argh! Now you're adding another user for a legacy custom pin control
> implementation. But if noone is going to modernize PXA2xx what
> can we do :-/

I've rewritten the device to use device tree and posted patch series for
that.

I will also implement LP-8x4x custom irq controller in drivers/irqchip/


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

* [PATCH v2 02/11] arm: pxa27x: support ICP DAS LP-8x4x
@ 2013-12-10 12:47         ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-10 12:47 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, 2013-12-10 at 13:43 +0100, Linus Walleij wrote:
> Argh! Now you're adding another user for a legacy custom pin control
> implementation. But if noone is going to modernize PXA2xx what
> can we do :-/

I've rewritten the device to use device tree and posted patch series for
that.

I will also implement LP-8x4x custom irq controller in drivers/irqchip/

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

* Re: [PATCH v2 02/11] arm: pxa27x: support ICP DAS LP-8x4x
  2013-12-10 12:43       ` Linus Walleij
@ 2013-12-10 12:54         ` Vasily Khoruzhick
  -1 siblings, 0 replies; 700+ messages in thread
From: Vasily Khoruzhick @ 2013-12-10 12:54 UTC (permalink / raw)
  To: Linus Walleij
  Cc: Sergei Ianovich, Russell King, Arnd Bergmann, linux-kernel,
	Haojian Zhuang, Haojian Zhuang, Eric Miao, linux-arm-kernel

On Tue, Dec 10, 2013 at 3:43 PM, Linus Walleij <linus.walleij@linaro.org> wrote:
> On Fri, Dec 6, 2013 at 5:48 PM, Sergei Ianovich <ynvich@gmail.com> wrote:
>
>> ICP DAS calls LP-8x4x 'programmable automation controller'. It is
>> an industrial computer based on PXA270 SoC. They ship it with a 2.6.19
>> kernel and proprietary kernel module and userspace library to access
>> its industrial IO.
>
> OK... so we only have device tree support for PXA3xx and noone is
> working on PXA2xx. And now we pile up some more legacy code.
> Such is life. But this:
>
>> +static unsigned long lp8x4x_pin_config[] = {
>> +       /* MMC */
>> +       GPIO32_MMC_CLK,
>> +       GPIO112_MMC_CMD,
>> +       GPIO92_MMC_DAT_0,
>> +       GPIO109_MMC_DAT_1,
>> +       GPIO110_MMC_DAT_2,
>> +       GPIO111_MMC_DAT_3,
>> +
>> +       /* USB Host Port 1 */
>> +       GPIO88_USBH1_PWR,
>> +       GPIO89_USBH1_PEN,
>> +};
>
> (...)
>> +static void __init lp8x4x_init(void)
>> +{
>> +       pxa2xx_mfp_config(ARRAY_AND_SIZE(lp8x4x_pin_config));
> (...)
>
> Argh! Now you're adding another user for a legacy custom pin control
> implementation. But if noone is going to modernize PXA2xx what
> can we do :-/

I tried a ~year ago, but it's not so trivial. PXA2xx has no separate
pin control module, it's
highly integrated into GPIO controller. I've asked the maillist what
should I do for that case, but AFAIR no one answered.

Regards
Vasily

> Yours,
> Linus Walleij
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v2 02/11] arm: pxa27x: support ICP DAS LP-8x4x
@ 2013-12-10 12:54         ` Vasily Khoruzhick
  0 siblings, 0 replies; 700+ messages in thread
From: Vasily Khoruzhick @ 2013-12-10 12:54 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Dec 10, 2013 at 3:43 PM, Linus Walleij <linus.walleij@linaro.org> wrote:
> On Fri, Dec 6, 2013 at 5:48 PM, Sergei Ianovich <ynvich@gmail.com> wrote:
>
>> ICP DAS calls LP-8x4x 'programmable automation controller'. It is
>> an industrial computer based on PXA270 SoC. They ship it with a 2.6.19
>> kernel and proprietary kernel module and userspace library to access
>> its industrial IO.
>
> OK... so we only have device tree support for PXA3xx and noone is
> working on PXA2xx. And now we pile up some more legacy code.
> Such is life. But this:
>
>> +static unsigned long lp8x4x_pin_config[] = {
>> +       /* MMC */
>> +       GPIO32_MMC_CLK,
>> +       GPIO112_MMC_CMD,
>> +       GPIO92_MMC_DAT_0,
>> +       GPIO109_MMC_DAT_1,
>> +       GPIO110_MMC_DAT_2,
>> +       GPIO111_MMC_DAT_3,
>> +
>> +       /* USB Host Port 1 */
>> +       GPIO88_USBH1_PWR,
>> +       GPIO89_USBH1_PEN,
>> +};
>
> (...)
>> +static void __init lp8x4x_init(void)
>> +{
>> +       pxa2xx_mfp_config(ARRAY_AND_SIZE(lp8x4x_pin_config));
> (...)
>
> Argh! Now you're adding another user for a legacy custom pin control
> implementation. But if noone is going to modernize PXA2xx what
> can we do :-/

I tried a ~year ago, but it's not so trivial. PXA2xx has no separate
pin control module, it's
highly integrated into GPIO controller. I've asked the maillist what
should I do for that case, but AFAIR no one answered.

Regards
Vasily

> Yours,
> Linus Walleij
>
> _______________________________________________
> 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] 700+ messages in thread

* Re: [PATCH 02/11] arm: pxa27x: support ICP DAS LP-8x4x
  2013-12-10 12:33           ` Linus Walleij
@ 2013-12-10 20:20             ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-10 20:20 UTC (permalink / raw)
  To: Linus Walleij
  Cc: Arnd Bergmann, linux-arm-kernel, linux-kernel, Eric Miao,
	Russell King, Haojian Zhuang, Olof Johansson, Daniel Mack

On Tue, 2013-12-10 at 13:33 +0100, Linus Walleij wrote:
> On Fri, Dec 6, 2013 at 6:14 PM, Arnd Bergmann <arnd@arndb.de> wrote:
> > On Friday 06 December 2013, Sergei Ianovich wrote:
> >> On Fri, 2013-12-06 at 01:40 +0100, Arnd Bergmann wrote:
> >>
> >> > > +
> >> > > +static struct irq_chip lp8x4x_irq_chip = {
> >> > > +     .name                   = "FPGA",
> >> > > +     .irq_ack                = lp8x4x_ack_irq,
> >> > > +     .irq_mask               = lp8x4x_mask_irq,
> >> > > +     .irq_unmask             = lp8x4x_unmask_irq,
> >> > > +};
> >> >
> >> > Please try to move the irqchip code to drivers/irqchip/.
> >>
> >> CONFIG_IRQCHIP depends on CONFIG_OF_IRQ which in turn depends on Open
> >> Firmware.
> >
> > Hmm, I wonder if we should try to change Kconfig then. Let's leave it
> > alone for now, maybe Linus Walleij has some comments since he has
> > been looking into moving drivers out in the past.
> 
> I don't get this, if the subarch has deps in place for IRQCHIP and
> OF_IRQ just move the implementation to drivers/irqchip/foo.c
> edit drivers/irqchip/Makefile to compile the file for ARCH_FOO.
> What would the problem be? It's not like having the irqchip in the
> object is optional...

This chip is used only of one machine and only required for
machine-special devices. If those devices are not selected, the chip
will just waist memory.

> I would prefer if you augment the code to use
> IRQCHIP_DECLARE() so you can get rid of all the criss-cross
> calls, but this init contains a comment saying that GPIO
> has to be up before you initialize the irq_chip, can you please
> explain why it's like that?

This is a tertiary irq chip (primary is on CPU, secondary is GPIO). It
triggers a GPIO interrupt if it detects one of its own.

> Another way is to create a separate Kconfig entry for it in
> drivers/irqchip/Kconfig if you want the set-up to be more
> distributed, but that is usually just done when the irqchip is
> used on more than one platform.

Please consult, how to approach this driver using device tree. If I
assign an "interrupts" property in the node, and the property will point
to pxa-gpio interrupt controller using a phandle, is there a guaranty
that my device will be probed later than pxa-gpio interrupt controller?

Or how could that be achieved?


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

* [PATCH 02/11] arm: pxa27x: support ICP DAS LP-8x4x
@ 2013-12-10 20:20             ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-10 20:20 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, 2013-12-10 at 13:33 +0100, Linus Walleij wrote:
> On Fri, Dec 6, 2013 at 6:14 PM, Arnd Bergmann <arnd@arndb.de> wrote:
> > On Friday 06 December 2013, Sergei Ianovich wrote:
> >> On Fri, 2013-12-06 at 01:40 +0100, Arnd Bergmann wrote:
> >>
> >> > > +
> >> > > +static struct irq_chip lp8x4x_irq_chip = {
> >> > > +     .name                   = "FPGA",
> >> > > +     .irq_ack                = lp8x4x_ack_irq,
> >> > > +     .irq_mask               = lp8x4x_mask_irq,
> >> > > +     .irq_unmask             = lp8x4x_unmask_irq,
> >> > > +};
> >> >
> >> > Please try to move the irqchip code to drivers/irqchip/.
> >>
> >> CONFIG_IRQCHIP depends on CONFIG_OF_IRQ which in turn depends on Open
> >> Firmware.
> >
> > Hmm, I wonder if we should try to change Kconfig then. Let's leave it
> > alone for now, maybe Linus Walleij has some comments since he has
> > been looking into moving drivers out in the past.
> 
> I don't get this, if the subarch has deps in place for IRQCHIP and
> OF_IRQ just move the implementation to drivers/irqchip/foo.c
> edit drivers/irqchip/Makefile to compile the file for ARCH_FOO.
> What would the problem be? It's not like having the irqchip in the
> object is optional...

This chip is used only of one machine and only required for
machine-special devices. If those devices are not selected, the chip
will just waist memory.

> I would prefer if you augment the code to use
> IRQCHIP_DECLARE() so you can get rid of all the criss-cross
> calls, but this init contains a comment saying that GPIO
> has to be up before you initialize the irq_chip, can you please
> explain why it's like that?

This is a tertiary irq chip (primary is on CPU, secondary is GPIO). It
triggers a GPIO interrupt if it detects one of its own.

> Another way is to create a separate Kconfig entry for it in
> drivers/irqchip/Kconfig if you want the set-up to be more
> distributed, but that is usually just done when the irqchip is
> used on more than one platform.

Please consult, how to approach this driver using device tree. If I
assign an "interrupts" property in the node, and the property will point
to pxa-gpio interrupt controller using a phandle, is there a guaranty
that my device will be probed later than pxa-gpio interrupt controller?

Or how could that be achieved?

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

* Re: [PATCH 02/11] arm: pxa27x: support ICP DAS LP-8x4x
  2013-12-10 20:20             ` Sergei Ianovich
@ 2013-12-10 21:57               ` Arnd Bergmann
  -1 siblings, 0 replies; 700+ messages in thread
From: Arnd Bergmann @ 2013-12-10 21:57 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: Linus Walleij, linux-arm-kernel, linux-kernel, Eric Miao,
	Russell King, Haojian Zhuang, Olof Johansson, Daniel Mack

On Tuesday 10 December 2013, Sergei Ianovich wrote:
> On Tue, 2013-12-10 at 13:33 +0100, Linus Walleij wrote:
> > On Fri, Dec 6, 2013 at 6:14 PM, Arnd Bergmann <arnd@arndb.de> wrote:
> > > On Friday 06 December 2013, Sergei Ianovich wrote:
> > >> On Fri, 2013-12-06 at 01:40 +0100, Arnd Bergmann wrote:
> > >>
> > >> > > +
> > >> > > +static struct irq_chip lp8x4x_irq_chip = {
> > >> > > +     .name                   = "FPGA",
> > >> > > +     .irq_ack                = lp8x4x_ack_irq,
> > >> > > +     .irq_mask               = lp8x4x_mask_irq,
> > >> > > +     .irq_unmask             = lp8x4x_unmask_irq,
> > >> > > +};
> > >> >
> > >> > Please try to move the irqchip code to drivers/irqchip/.
> > >>
> > >> CONFIG_IRQCHIP depends on CONFIG_OF_IRQ which in turn depends on Open
> > >> Firmware.
> > >
> > > Hmm, I wonder if we should try to change Kconfig then. Let's leave it
> > > alone for now, maybe Linus Walleij has some comments since he has
> > > been looking into moving drivers out in the past.
> > 
> > I don't get this, if the subarch has deps in place for IRQCHIP and
> > OF_IRQ just move the implementation to drivers/irqchip/foo.c
> > edit drivers/irqchip/Makefile to compile the file for ARCH_FOO.
> > What would the problem be? It's not like having the irqchip in the
> > object is optional...
> 
> This chip is used only of one machine and only required for
> machine-special devices. If those devices are not selected, the chip
> will just waist memory.

It should be possible to make it a loadable module, with deferred
probing etc. You wouldn't use IRQCHIP_DECLARE() for this though,
but instead have a platform driver that sets up the irq domain.

It probably makes sense to have a single driver file for the
FPGA device that does this, and only split out the other devices
from it that consume the irqs.

> > Another way is to create a separate Kconfig entry for it in
> > drivers/irqchip/Kconfig if you want the set-up to be more
> > distributed, but that is usually just done when the irqchip is
> > used on more than one platform.
> 
> Please consult, how to approach this driver using device tree. If I
> assign an "interrupts" property in the node, and the property will point
> to pxa-gpio interrupt controller using a phandle, is there a guaranty
> that my device will be probed later than pxa-gpio interrupt controller?

Yes, the interrupt controllers get probed in the right order based
on their "interrupt-parent" properties, starting with the root
controller.

If you have a platform driver rather than IRQCHIP_DECLARE(), that gets
initialized after all IRQCHIP_DECLARE() calls, so it's not a problem.

If both the gpio chip and the fpga are loadable modules, it's still
fine, but the probe() function for the fpga needs to call
irq_of_parse_and_map() to get the parent IRQ and bail out of
-EPROBE_DEFER if it gets this error while trying to map the
gpio IRQ.

	Arnd

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

* [PATCH 02/11] arm: pxa27x: support ICP DAS LP-8x4x
@ 2013-12-10 21:57               ` Arnd Bergmann
  0 siblings, 0 replies; 700+ messages in thread
From: Arnd Bergmann @ 2013-12-10 21:57 UTC (permalink / raw)
  To: linux-arm-kernel

On Tuesday 10 December 2013, Sergei Ianovich wrote:
> On Tue, 2013-12-10 at 13:33 +0100, Linus Walleij wrote:
> > On Fri, Dec 6, 2013 at 6:14 PM, Arnd Bergmann <arnd@arndb.de> wrote:
> > > On Friday 06 December 2013, Sergei Ianovich wrote:
> > >> On Fri, 2013-12-06 at 01:40 +0100, Arnd Bergmann wrote:
> > >>
> > >> > > +
> > >> > > +static struct irq_chip lp8x4x_irq_chip = {
> > >> > > +     .name                   = "FPGA",
> > >> > > +     .irq_ack                = lp8x4x_ack_irq,
> > >> > > +     .irq_mask               = lp8x4x_mask_irq,
> > >> > > +     .irq_unmask             = lp8x4x_unmask_irq,
> > >> > > +};
> > >> >
> > >> > Please try to move the irqchip code to drivers/irqchip/.
> > >>
> > >> CONFIG_IRQCHIP depends on CONFIG_OF_IRQ which in turn depends on Open
> > >> Firmware.
> > >
> > > Hmm, I wonder if we should try to change Kconfig then. Let's leave it
> > > alone for now, maybe Linus Walleij has some comments since he has
> > > been looking into moving drivers out in the past.
> > 
> > I don't get this, if the subarch has deps in place for IRQCHIP and
> > OF_IRQ just move the implementation to drivers/irqchip/foo.c
> > edit drivers/irqchip/Makefile to compile the file for ARCH_FOO.
> > What would the problem be? It's not like having the irqchip in the
> > object is optional...
> 
> This chip is used only of one machine and only required for
> machine-special devices. If those devices are not selected, the chip
> will just waist memory.

It should be possible to make it a loadable module, with deferred
probing etc. You wouldn't use IRQCHIP_DECLARE() for this though,
but instead have a platform driver that sets up the irq domain.

It probably makes sense to have a single driver file for the
FPGA device that does this, and only split out the other devices
from it that consume the irqs.

> > Another way is to create a separate Kconfig entry for it in
> > drivers/irqchip/Kconfig if you want the set-up to be more
> > distributed, but that is usually just done when the irqchip is
> > used on more than one platform.
> 
> Please consult, how to approach this driver using device tree. If I
> assign an "interrupts" property in the node, and the property will point
> to pxa-gpio interrupt controller using a phandle, is there a guaranty
> that my device will be probed later than pxa-gpio interrupt controller?

Yes, the interrupt controllers get probed in the right order based
on their "interrupt-parent" properties, starting with the root
controller.

If you have a platform driver rather than IRQCHIP_DECLARE(), that gets
initialized after all IRQCHIP_DECLARE() calls, so it's not a problem.

If both the gpio chip and the fpga are loadable modules, it's still
fine, but the probe() function for the fpga needs to call
irq_of_parse_and_map() to get the parent IRQ and bail out of
-EPROBE_DEFER if it gets this error while trying to map the
gpio IRQ.

	Arnd

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

* Re: [PATCH v2 02/11] arm: pxa27x: support ICP DAS LP-8x4x
  2013-12-10 12:43       ` Linus Walleij
                         ` (2 preceding siblings ...)
  (?)
@ 2013-12-10 22:24       ` Dmitry Eremin-Solenikov
  -1 siblings, 0 replies; 700+ messages in thread
From: Dmitry Eremin-Solenikov @ 2013-12-10 22:24 UTC (permalink / raw)
  To: linux-kernel; +Cc: linux-arm-kernel

On Tue, 10 Dec 2013 13:43:27 +0100, Linus Walleij wrote:
 
> Argh! Now you're adding another user for a legacy custom pin control
> implementation. But if noone is going to modernize PXA2xx what can we do
> :-/

I plan to work on pxa2xx (pxa25x to be precise) after finishing with 
sa1100 - my second (well, first) PDA is Sharp SL-6000 (pxa255).

StrongARM somewhat resembles pxa2xx, so some of the drivers will be 
shared, some expertise will be shared, etc. I tried doing pxa first, but 
later found that it might be easier to update sa1100.

-- 
With best wishes
Dmitry


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

* Re: [PATCH 02/11] arm: pxa27x: support ICP DAS LP-8x4x
  2013-12-10 21:57               ` Arnd Bergmann
@ 2013-12-11  4:30                 ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-11  4:30 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Linus Walleij, linux-arm-kernel, linux-kernel, Eric Miao,
	Russell King, Haojian Zhuang, Olof Johansson, Daniel Mack

On Tue, 2013-12-10 at 22:57 +0100, Arnd Bergmann wrote:
> It should be possible to make it a loadable module, with deferred
> probing etc. You wouldn't use IRQCHIP_DECLARE() for this though,
> but instead have a platform driver that sets up the irq domain.

Thanks for explaning.

> It probably makes sense to have a single driver file for the
> FPGA device that does this, and only split out the other devices
> from it that consume the irqs.

Is drivers/irqchip/ the right place this driver?

I am asking because there is no tristate config options in
drivers/irqchip/Kconfig at the moment.



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

* [PATCH 02/11] arm: pxa27x: support ICP DAS LP-8x4x
@ 2013-12-11  4:30                 ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-11  4:30 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, 2013-12-10 at 22:57 +0100, Arnd Bergmann wrote:
> It should be possible to make it a loadable module, with deferred
> probing etc. You wouldn't use IRQCHIP_DECLARE() for this though,
> but instead have a platform driver that sets up the irq domain.

Thanks for explaning.

> It probably makes sense to have a single driver file for the
> FPGA device that does this, and only split out the other devices
> from it that consume the irqs.

Is drivers/irqchip/ the right place this driver?

I am asking because there is no tristate config options in
drivers/irqchip/Kconfig at the moment.

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

* Re: [PATCH 02/11] arm: pxa27x: support ICP DAS LP-8x4x
  2013-12-11  4:30                 ` Sergei Ianovich
@ 2013-12-11  5:11                   ` Arnd Bergmann
  -1 siblings, 0 replies; 700+ messages in thread
From: Arnd Bergmann @ 2013-12-11  5:11 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Sergei Ianovich, Russell King, Linus Walleij, linux-kernel,
	Haojian Zhuang, Daniel Mack, Olof Johansson, Eric Miao

On Wednesday 11 December 2013, Sergei Ianovich wrote:
> > It probably makes sense to have a single driver file for the
> > FPGA device that does this, and only split out the other devices
> > from it that consume the irqs.
> 
> Is drivers/irqchip/ the right place this driver?
> 
> I am asking because there is no tristate config options in
> drivers/irqchip/Kconfig at the moment.
> 

It depends: if the driver is for the entire FPGA and does
the irqchip stuff in addition, it should probably live
in drivers/mfd. If it's a pure irqchip driver, drivers/irqchip
is better. You have to be careful in the second case though
because devices pointing to this irqchip in DT won't get
an IRQ resource assigned automatically but have to use
irq_of_parse_and_map instead. This may have been fixed since
I last looked though, I would consider that behavior a
bug in the of_platform handling.

	Arnd

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

* [PATCH 02/11] arm: pxa27x: support ICP DAS LP-8x4x
@ 2013-12-11  5:11                   ` Arnd Bergmann
  0 siblings, 0 replies; 700+ messages in thread
From: Arnd Bergmann @ 2013-12-11  5:11 UTC (permalink / raw)
  To: linux-arm-kernel

On Wednesday 11 December 2013, Sergei Ianovich wrote:
> > It probably makes sense to have a single driver file for the
> > FPGA device that does this, and only split out the other devices
> > from it that consume the irqs.
> 
> Is drivers/irqchip/ the right place this driver?
> 
> I am asking because there is no tristate config options in
> drivers/irqchip/Kconfig at the moment.
> 

It depends: if the driver is for the entire FPGA and does
the irqchip stuff in addition, it should probably live
in drivers/mfd. If it's a pure irqchip driver, drivers/irqchip
is better. You have to be careful in the second case though
because devices pointing to this irqchip in DT won't get
an IRQ resource assigned automatically but have to use
irq_of_parse_and_map instead. This may have been fixed since
I last looked though, I would consider that behavior a
bug in the of_platform handling.

	Arnd

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

* Re: [PATCH 02/11] arm: pxa27x: support ICP DAS LP-8x4x
  2013-12-11  5:11                   ` Arnd Bergmann
@ 2013-12-11  5:41                     ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-11  5:41 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: linux-arm-kernel, Russell King, Linus Walleij, linux-kernel,
	Haojian Zhuang, Daniel Mack, Olof Johansson, Eric Miao

On Wed, 2013-12-11 at 06:11 +0100, Arnd Bergmann wrote:
> It depends: if the driver is for the entire FPGA and does
> the irqchip stuff in addition, it should probably live
> in drivers/mfd. If it's a pure irqchip driver, drivers/irqchip
> is better. You have to be careful in the second case though
> because devices pointing to this irqchip in DT won't get
> an IRQ resource assigned automatically but have to use
> irq_of_parse_and_map instead. This may have been fixed since
> I last looked though, I would consider that behavior a
> bug in the of_platform handling.

Thanks again for explaining.

Although FPGA is a MFD, its irq are used mostly by 8250 serial ports. It
will be enough to embed irqchip into serial driver for now.

If there is a need to use the chip in another driver, it will be
possible to introduce an artificial dependency there for the serial
driver to ensure the serial driver is loaded before the other one.

Is this plan acceptable?


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

* [PATCH 02/11] arm: pxa27x: support ICP DAS LP-8x4x
@ 2013-12-11  5:41                     ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-11  5:41 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, 2013-12-11 at 06:11 +0100, Arnd Bergmann wrote:
> It depends: if the driver is for the entire FPGA and does
> the irqchip stuff in addition, it should probably live
> in drivers/mfd. If it's a pure irqchip driver, drivers/irqchip
> is better. You have to be careful in the second case though
> because devices pointing to this irqchip in DT won't get
> an IRQ resource assigned automatically but have to use
> irq_of_parse_and_map instead. This may have been fixed since
> I last looked though, I would consider that behavior a
> bug in the of_platform handling.

Thanks again for explaining.

Although FPGA is a MFD, its irq are used mostly by 8250 serial ports. It
will be enough to embed irqchip into serial driver for now.

If there is a need to use the chip in another driver, it will be
possible to introduce an artificial dependency there for the serial
driver to ensure the serial driver is loaded before the other one.

Is this plan acceptable?

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

* Re: [PATCH 5/9] ARM: dts: provide DMA config to pxamci
  2013-12-09  9:04             ` Daniel Mack
  (?)
@ 2013-12-11  8:19               ` Robert Jarzmik
  -1 siblings, 0 replies; 700+ messages in thread
From: Robert Jarzmik @ 2013-12-11  8:19 UTC (permalink / raw)
  To: Daniel Mack
  Cc: Arnd Bergmann, Sergei Ianovich, linux-kernel, linux-arm-kernel,
	Rob Herring, Pawel Moll, Mark Rutland, Stephen Warren,
	Ian Campbell, Rob Landley, Russell King, Chris Ball, Ulf Hansson,
	Jaehoon Chung, Seungwon Jeon, devicetree, linux-doc

Daniel Mack <zonque@gmail.com> writes:

> In particular, the pxa camera driver is something Robert (cc) wanted to
> have a look at. Robert, any updates on this?
Oh yes, sorry, it's been monthes, I've been very busy.

This is my last status :
 - my current patch is in (1)

 - this patch doesn't work yet

 - if my memory serves me well, I have reached the conclusion that dmaengine
   pxa-mpp driver doesn't allow pxa_camera to work properly in the current
   state.  This is a long time since I checked, so take the following with
   caution until I have checked again.

This assertion is based on this required behaviour :
 - video buffers are queued, let's say 5
   => 5 dma are "prepared"

 - video buffers are submitted
   => 5 dma xfers are submitted

 - the userspace polls for each finished frame (ie. dma xfer termination), and
   on the third one, resubmits the 2 finished frames
     => scatter-gathers should mot be recomputed, just xfer should be
     resubmitted, with cache sync operations and first/last descriptors chaining

 - the pxa_camera driver needs a way to know if a dma channel is still running,
   for missed chaining transfers, because if a channel stopped, the dma xfers
   should not be submitted until IRQ "begin of frame" is encoutered. I didn't
   find a way for that.

Now, I will retry this weekend, but if I remember correctly the issues I had
were :
 - a transfer cannot be resubmitted, it has to be freed and recreated
 - if it is resubmitted, the completion is not signaled by the tasklet

Cheers.

--
Robert

(1)
commit 4741ba6 (pxa_camera_dmaengine, backup/pxa_camera_dmaengine)
Author: Robert Jarzmik <robert.jarzmik@free.fr>
Date:   Sat Aug 24 21:13:38 2013 +0200

    WIP: pxa_camera dmaengine conversion
    
    Only slightly tested, without much success.
    
    Signed-off-by: Robert Jarzmik <robert.jarzmik@free.fr>

diff --git a/drivers/media/platform/soc_camera/pxa_camera.c b/drivers/media/platform/soc_camera/pxa_camera.c
index d4df305..903ea03 100644
--- a/drivers/media/platform/soc_camera/pxa_camera.c
+++ b/drivers/media/platform/soc_camera/pxa_camera.c
@@ -9,7 +9,7 @@
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version.
  */
-
+#define DEBUG 1
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/io.h>
@@ -28,6 +28,9 @@
 #include <linux/clk.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
+#include <linux/dmaengine.h>
+#include <linux/dma-mapping.h>
+#include <linux/dma/mmp-pdma.h>
 
 #include <media/v4l2-common.h>
 #include <media/v4l2-dev.h>
@@ -37,7 +40,6 @@
 
 #include <linux/videodev2.h>
 
-#include <mach/dma.h>
 #include <linux/platform_data/camera-pxa.h>
 
 #define PXA_CAM_VERSION "0.0.6"
@@ -174,21 +176,13 @@ enum pxa_camera_active_dma {
 	DMA_V = 0x4,
 };
 
-/* descriptor needed for the PXA DMA engine */
-struct pxa_cam_dma {
-	dma_addr_t		sg_dma;
-	struct pxa_dma_desc	*sg_cpu;
-	size_t			sg_size;
-	int			sglen;
-};
-
 /* buffer for one video frame */
 struct pxa_buffer {
 	/* common v4l buffer stuff -- must be first */
 	struct videobuf_buffer		vb;
 	enum v4l2_mbus_pixelcode	code;
 	/* our descriptor lists for Y, U and V channels */
-	struct pxa_cam_dma		dmas[3];
+	struct dma_async_tx_descriptor	*descs[3];
 	int				inwork;
 	enum pxa_camera_active_dma	active_dma;
 };
@@ -206,7 +200,7 @@ struct pxa_camera_dev {
 	void __iomem		*base;
 
 	int			channels;
-	unsigned int		dma_chans[3];
+	struct dma_chan		*dma_chans[3];
 
 	struct pxacamera_platform_data *pdata;
 	struct resource		*res;
@@ -221,7 +215,6 @@ struct pxa_camera_dev {
 	spinlock_t		lock;
 
 	struct pxa_buffer	*active;
-	struct pxa_dma_desc	*sg_tail[3];
 
 	u32			save_cicr[5];
 };
@@ -273,40 +266,70 @@ static void free_buffer(struct videobuf_queue *vq, struct pxa_buffer *buf)
 	videobuf_waiton(vq, &buf->vb, 0, 0);
 	videobuf_dma_unmap(vq->dev, dma);
 	videobuf_dma_free(dma);
-
-	for (i = 0; i < ARRAY_SIZE(buf->dmas); i++) {
-		if (buf->dmas[i].sg_cpu)
-			dma_free_coherent(ici->v4l2_dev.dev,
-					  buf->dmas[i].sg_size,
-					  buf->dmas[i].sg_cpu,
-					  buf->dmas[i].sg_dma);
-		buf->dmas[i].sg_cpu = NULL;
-	}
+	/* FIXME: free buf->descs[0..2] */
 
 	buf->vb.state = VIDEOBUF_NEEDS_INIT;
+
+	dev_dbg(icd->parent, "%s end (vb=0x%p) 0x%08lx %d\n", __func__,
+		&buf->vb, buf->vb.baddr, buf->vb.bsize);
 }
 
-static int calculate_dma_sglen(struct scatterlist *sglist, int sglen,
-			       int sg_first_ofs, int size)
+static struct scatterlist *videobuf_sg_splice(struct scatterlist *sglist,
+					      int sglen, int offset, int size,
+					      int *new_sg_len)
 {
-	int i, offset, dma_len, xfer_len;
-	struct scatterlist *sg;
+	struct scatterlist *sg0, *sg;
+	int nfirst, i, dma_len, xfer_len;
 
-	offset = sg_first_ofs;
-	for_each_sg(sglist, sg, sglen, i) {
+	sg0 = kmalloc(sizeof(struct scatterlist) * sglen, GFP_KERNEL);
+	if (!sg0)
+		return NULL;
+	for_each_sg(sglist, sg, sglen, nfirst) {
 		dma_len = sg_dma_len(sg);
-
+		if (offset < dma_len)
+			break;
 		/* PXA27x Developer's Manual 27.4.4.1: round up to 8 bytes */
-		xfer_len = roundup(min(dma_len - offset, size), 8);
-
-		size = max(0, size - xfer_len);
-		offset = 0;
-		if (size == 0)
+		xfer_len = roundup(min(dma_len - offset, offset), 8);
+		offset = max(0, offset - xfer_len);
+	}
+	BUG_ON(sg_is_last(&sglist[nfirst]));
+	for_each_sg(&sglist[nfirst], sg, sglen - nfirst, i) {
+		sg0[i] = sglist[nfirst];
+		sg0[i].offset = offset;
+		sg_dma_len(&sg0[i]) -= offset;
+		if (size <= sg_dma_len(sg))
 			break;
+		offset = 0;
+		size -= roundup(sg_dma_len(sg), 8);
+	}
+	if (size) {
+		sg_dma_len(&sg0[i]) = size;
+		*new_sg_len = i + 1;
+	} else {
+		*new_sg_len = i;
 	}
 
-	BUG_ON(size != 0);
-	return i + 1;
+	return sg0;
+}
+static void pxa_camera_dma_irq(struct pxa_camera_dev *pcdev,
+			       enum pxa_camera_active_dma act_dma);
+
+static void pxa_camera_dma_irq_y(void *data)
+{
+	struct pxa_camera_dev *pcdev = data;
+	pxa_camera_dma_irq(pcdev, DMA_Y);
+}
+
+static void pxa_camera_dma_irq_u(void *data)
+{
+	struct pxa_camera_dev *pcdev = data;
+	pxa_camera_dma_irq(pcdev, DMA_U);
+}
+
+static void pxa_camera_dma_irq_v(void *data)
+{
+	struct pxa_camera_dev *pcdev = data;
+	pxa_camera_dma_irq(pcdev, DMA_V);
 }
 
 /**
@@ -317,91 +340,68 @@ static int calculate_dma_sglen(struct scatterlist *sglist, int sglen,
  * @channel: dma channel (0 => 'Y', 1 => 'U', 2 => 'V')
  * @cibr: camera Receive Buffer Register
  * @size: bytes to transfer
- * @sg_first: first element of sg_list
- * @sg_first_ofs: offset in first element of sg_list
+ * @offset: offset in videobuffer of the first byte to transfer
  *
  * Prepares the pxa dma descriptors to transfer one camera channel.
- * Beware sg_first and sg_first_ofs are both input and output parameters.
  *
- * Returns 0 or -ENOMEM if no coherent memory is available
+ * Returns 0 if success or -ENOMEM if no memory is available
  */
 static int pxa_init_dma_channel(struct pxa_camera_dev *pcdev,
 				struct pxa_buffer *buf,
 				struct videobuf_dmabuf *dma, int channel,
-				int cibr, int size,
-				struct scatterlist **sg_first, int *sg_first_ofs)
+				int cibr, int size, int offset)
 {
-	struct pxa_cam_dma *pxa_dma = &buf->dmas[channel];
-	struct device *dev = pcdev->soc_host.v4l2_dev.dev;
-	struct scatterlist *sg;
-	int i, offset, sglen;
-	int dma_len = 0, xfer_len = 0;
+	struct dma_chan *dma_chan = pcdev->dma_chans[channel];
+	struct scatterlist *sg = NULL;
+	int ret, sglen;
+	struct dma_slave_config config;
+	struct dma_async_tx_descriptor *tx;
 
-	if (pxa_dma->sg_cpu)
-		dma_free_coherent(dev, pxa_dma->sg_size,
-				  pxa_dma->sg_cpu, pxa_dma->sg_dma);
+	dmaengine_terminate_all(dma_chan);
 
-	sglen = calculate_dma_sglen(*sg_first, dma->sglen,
-				    *sg_first_ofs, size);
-
-	pxa_dma->sg_size = (sglen + 1) * sizeof(struct pxa_dma_desc);
-	pxa_dma->sg_cpu = dma_alloc_coherent(dev, pxa_dma->sg_size,
-					     &pxa_dma->sg_dma, GFP_KERNEL);
-	if (!pxa_dma->sg_cpu)
+	sg = videobuf_sg_splice(dma->sglist, dma->sglen, offset, size, &sglen);
+	if (!sg)
 		return -ENOMEM;
 
-	pxa_dma->sglen = sglen;
-	offset = *sg_first_ofs;
-
-	dev_dbg(dev, "DMA: sg_first=%p, sglen=%d, ofs=%d, dma.desc=%x\n",
-		*sg_first, sglen, *sg_first_ofs, pxa_dma->sg_dma);
-
+	memset(&config, 0, sizeof(config));
+	config.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; /* FIXME? */
+	config.src_maxburst = 8;
+	config.src_addr = pcdev->res->start + cibr;
+	config.direction = DMA_DEV_TO_MEM;
 
-	for_each_sg(*sg_first, sg, sglen, i) {
-		dma_len = sg_dma_len(sg);
-
-		/* PXA27x Developer's Manual 27.4.4.1: round up to 8 bytes */
-		xfer_len = roundup(min(dma_len - offset, size), 8);
-
-		size = max(0, size - xfer_len);
-
-		pxa_dma->sg_cpu[i].dsadr = pcdev->res->start + cibr;
-		pxa_dma->sg_cpu[i].dtadr = sg_dma_address(sg) + offset;
-		pxa_dma->sg_cpu[i].dcmd =
-			DCMD_FLOWSRC | DCMD_BURST8 | DCMD_INCTRGADDR | xfer_len;
-#ifdef DEBUG
-		if (!i)
-			pxa_dma->sg_cpu[i].dcmd |= DCMD_STARTIRQEN;
-#endif
-		pxa_dma->sg_cpu[i].ddadr =
-			pxa_dma->sg_dma + (i + 1) * sizeof(struct pxa_dma_desc);
-
-		dev_vdbg(dev, "DMA: desc.%08x->@phys=0x%08x, len=%d\n",
-			 pxa_dma->sg_dma + i * sizeof(struct pxa_dma_desc),
-			 sg_dma_address(sg) + offset, xfer_len);
-		offset = 0;
-
-		if (size == 0)
-			break;
+	ret = dmaengine_slave_config(dma_chan, &config);
+	if (ret < 0) {
+		printk("%s(): dma slave config failed: %d\n", __func__, ret);
+		return ret;
 	}
 
-	pxa_dma->sg_cpu[sglen].ddadr = DDADR_STOP;
-	pxa_dma->sg_cpu[sglen].dcmd  = DCMD_FLOWSRC | DCMD_BURST8 | DCMD_ENDIRQEN;
+	tx = dmaengine_prep_slave_sg(dma_chan, sg, sglen,
+				     config.direction,
+				     DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+	if (!tx) {
+		printk("%s(): prep_slave_sg() failed\n", __func__);
+		goto fail;
+	}
 
-	/*
-	 * Handle 1 special case :
-	 *  - in 3 planes (YUV422P format), we might finish with xfer_len equal
-	 *    to dma_len (end on PAGE boundary). In this case, the sg element
-	 *    for next plane should be the next after the last used to store the
-	 *    last scatter gather RAM page
-	 */
-	if (xfer_len >= dma_len) {
-		*sg_first_ofs = xfer_len - dma_len;
-		*sg_first = sg_next(sg);
-	} else {
-		*sg_first_ofs = xfer_len;
-		*sg_first = sg;
+	tx->callback_param = pcdev;
+	switch (channel) {
+	case 0:
+		tx->callback = pxa_camera_dma_irq_y;
+		break;
+	case 1:
+		tx->callback = pxa_camera_dma_irq_u;
+		break;
+	case 2:
+		tx->callback = pxa_camera_dma_irq_v;
+		break;
 	}
+fail:
+	kfree(sg);
+	buf->descs[channel] = tx;
+
+	dev_dbg(pcdev->soc_host.v4l2_dev.dev,
+		"%s (vb=0x%p) dma_tx=%p\n",
+		__func__, &buf->vb, tx);
 
 	return 0;
 }
@@ -470,11 +470,10 @@ static int pxa_videobuf_prepare(struct videobuf_queue *vq,
 		goto out;
 	}
 
-	if (vb->state == VIDEOBUF_NEEDS_INIT) {
+	//if (vb->state == VIDEOBUF_NEEDS_INIT) {
+	if (vb->state != VIDEOBUF_PREPARED) {
 		int size = vb->size;
-		int next_ofs = 0;
 		struct videobuf_dmabuf *dma = videobuf_to_dma(vb);
-		struct scatterlist *sg;
 
 		ret = videobuf_iolock(vq, vb, NULL);
 		if (ret)
@@ -487,11 +486,8 @@ static int pxa_videobuf_prepare(struct videobuf_queue *vq,
 			size_y = size;
 		}
 
-		sg = dma->sglist;
-
 		/* init DMA for Y channel */
-		ret = pxa_init_dma_channel(pcdev, buf, dma, 0, CIBR0, size_y,
-					   &sg, &next_ofs);
+		ret = pxa_init_dma_channel(pcdev, buf, dma, 0, CIBR0, size_y, 0);
 		if (ret) {
 			dev_err(dev, "DMA initialization for Y/RGB failed\n");
 			goto fail;
@@ -500,7 +496,7 @@ static int pxa_videobuf_prepare(struct videobuf_queue *vq,
 		/* init DMA for U channel */
 		if (size_u)
 			ret = pxa_init_dma_channel(pcdev, buf, dma, 1, CIBR1,
-						   size_u, &sg, &next_ofs);
+						   size_u, size_y);
 		if (ret) {
 			dev_err(dev, "DMA initialization for U failed\n");
 			goto fail_u;
@@ -509,7 +505,7 @@ static int pxa_videobuf_prepare(struct videobuf_queue *vq,
 		/* init DMA for V channel */
 		if (size_v)
 			ret = pxa_init_dma_channel(pcdev, buf, dma, 2, CIBR2,
-						   size_v, &sg, &next_ofs);
+						   size_v, size_y + size_u);
 		if (ret) {
 			dev_err(dev, "DMA initialization for V failed\n");
 			goto fail_v;
@@ -524,11 +520,7 @@ static int pxa_videobuf_prepare(struct videobuf_queue *vq,
 	return 0;
 
 fail_v:
-	dma_free_coherent(dev, buf->dmas[1].sg_size,
-			  buf->dmas[1].sg_cpu, buf->dmas[1].sg_dma);
 fail_u:
-	dma_free_coherent(dev, buf->dmas[0].sg_size,
-			  buf->dmas[0].sg_cpu, buf->dmas[0].sg_dma);
 fail:
 	free_buffer(vq, buf);
 out:
@@ -552,10 +544,8 @@ static void pxa_dma_start_channels(struct pxa_camera_dev *pcdev)
 
 	for (i = 0; i < pcdev->channels; i++) {
 		dev_dbg(pcdev->soc_host.v4l2_dev.dev,
-			"%s (channel=%d) ddadr=%08x\n", __func__,
-			i, active->dmas[i].sg_dma);
-		DDADR(pcdev->dma_chans[i]) = active->dmas[i].sg_dma;
-		DCSR(pcdev->dma_chans[i]) = DCSR_RUN;
+			"%s (channel=%d)\n", __func__, i);
+		dma_async_issue_pending(pcdev->dma_chans[i]);
 	}
 }
 
@@ -566,7 +556,7 @@ static void pxa_dma_stop_channels(struct pxa_camera_dev *pcdev)
 	for (i = 0; i < pcdev->channels; i++) {
 		dev_dbg(pcdev->soc_host.v4l2_dev.dev,
 			"%s (channel=%d)\n", __func__, i);
-		DCSR(pcdev->dma_chans[i]) = 0;
+		dmaengine_terminate_all(pcdev->dma_chans[i]);
 	}
 }
 
@@ -574,18 +564,12 @@ static void pxa_dma_add_tail_buf(struct pxa_camera_dev *pcdev,
 				 struct pxa_buffer *buf)
 {
 	int i;
-	struct pxa_dma_desc *buf_last_desc;
 
 	for (i = 0; i < pcdev->channels; i++) {
-		buf_last_desc = buf->dmas[i].sg_cpu + buf->dmas[i].sglen;
-		buf_last_desc->ddadr = DDADR_STOP;
-
-		if (pcdev->sg_tail[i])
-			/* Link the new buffer to the old tail */
-			pcdev->sg_tail[i]->ddadr = buf->dmas[i].sg_dma;
-
-		/* Update the channel tail */
-		pcdev->sg_tail[i] = buf_last_desc;
+		dmaengine_submit(buf->descs[i]);
+		dev_dbg(pcdev->soc_host.v4l2_dev.dev,
+			"%s (channel=%d) : submit vb=%p cookie=%d\n",
+			__func__, i, buf, buf->descs[i]->cookie);
 	}
 }
 
@@ -676,8 +660,6 @@ static void pxa_camera_wakeup(struct pxa_camera_dev *pcdev,
 			      struct videobuf_buffer *vb,
 			      struct pxa_buffer *buf)
 {
-	int i;
-
 	/* _init is used to debug races, see comment in pxa_camera_reqbufs() */
 	list_del_init(&vb->queue);
 	vb->state = VIDEOBUF_DONE;
@@ -689,8 +671,6 @@ static void pxa_camera_wakeup(struct pxa_camera_dev *pcdev,
 
 	if (list_empty(&pcdev->capture)) {
 		pxa_camera_stop_capture(pcdev);
-		for (i = 0; i < pcdev->channels; i++)
-			pcdev->sg_tail[i] = NULL;
 		return;
 	}
 
@@ -716,48 +696,33 @@ static void pxa_camera_wakeup(struct pxa_camera_dev *pcdev,
  */
 static void pxa_camera_check_link_miss(struct pxa_camera_dev *pcdev)
 {
-	int i, is_dma_stopped = 1;
+	/* FIXME: ask dmaengine if channel is still running */
+	int is_dma_stopped = 1;
 
-	for (i = 0; i < pcdev->channels; i++)
-		if (DDADR(pcdev->dma_chans[i]) != DDADR_STOP)
-			is_dma_stopped = 0;
 	dev_dbg(pcdev->soc_host.v4l2_dev.dev,
-		"%s : top queued buffer=%p, dma_stopped=%d\n",
-		__func__, pcdev->active, is_dma_stopped);
+		"%s : top queued buffer=%p\n", __func__, pcdev->active);
+	if (pcdev->active)
+		pxa_dma_start_channels(pcdev);
 	if (pcdev->active && is_dma_stopped)
 		pxa_camera_start_capture(pcdev);
 }
 
-static void pxa_camera_dma_irq(int channel, struct pxa_camera_dev *pcdev,
+static void pxa_camera_dma_irq(struct pxa_camera_dev *pcdev,
 			       enum pxa_camera_active_dma act_dma)
 {
 	struct device *dev = pcdev->soc_host.v4l2_dev.dev;
 	struct pxa_buffer *buf;
 	unsigned long flags;
-	u32 status, camera_status, overrun;
+	u32 camera_status, overrun;
 	struct videobuf_buffer *vb;
 
 	spin_lock_irqsave(&pcdev->lock, flags);
 
-	status = DCSR(channel);
-	DCSR(channel) = status;
-
 	camera_status = __raw_readl(pcdev->base + CISR);
 	overrun = CISR_IFO_0;
 	if (pcdev->channels == 3)
 		overrun |= CISR_IFO_1 | CISR_IFO_2;
 
-	if (status & DCSR_BUSERR) {
-		dev_err(dev, "DMA Bus Error IRQ!\n");
-		goto out;
-	}
-
-	if (!(status & (DCSR_ENDINTR | DCSR_STARTINTR))) {
-		dev_err(dev, "Unknown DMA IRQ source, status: 0x%08x\n",
-			status);
-		goto out;
-	}
-
 	/*
 	 * pcdev->active should not be NULL in DMA irq handler.
 	 *
@@ -777,52 +742,28 @@ static void pxa_camera_dma_irq(int channel, struct pxa_camera_dev *pcdev,
 	buf = container_of(vb, struct pxa_buffer, vb);
 	WARN_ON(buf->inwork || list_empty(&vb->queue));
 
-	dev_dbg(dev, "%s channel=%d %s%s(vb=0x%p) dma.desc=%x\n",
-		__func__, channel, status & DCSR_STARTINTR ? "SOF " : "",
-		status & DCSR_ENDINTR ? "EOF " : "", vb, DDADR(channel));
-
-	if (status & DCSR_ENDINTR) {
-		/*
-		 * It's normal if the last frame creates an overrun, as there
-		 * are no more DMA descriptors to fetch from QCI fifos
-		 */
-		if (camera_status & overrun &&
-		    !list_is_last(pcdev->capture.next, &pcdev->capture)) {
-			dev_dbg(dev, "FIFO overrun! CISR: %x\n",
-				camera_status);
-			pxa_camera_stop_capture(pcdev);
-			pxa_camera_start_capture(pcdev);
-			goto out;
-		}
-		buf->active_dma &= ~act_dma;
-		if (!buf->active_dma) {
-			pxa_camera_wakeup(pcdev, vb, buf);
-			pxa_camera_check_link_miss(pcdev);
-		}
+	/*
+	 * It's normal if the last frame creates an overrun, as there
+	 * are no more DMA descriptors to fetch from QCI fifos
+	 */
+	if (camera_status & overrun &&
+	    !list_is_last(pcdev->capture.next, &pcdev->capture)) {
+		dev_dbg(dev, "FIFO overrun! CISR: %x\n",
+			camera_status);
+		pxa_camera_stop_capture(pcdev);
+		pxa_camera_start_capture(pcdev);
+		goto out;
+	}
+	buf->active_dma &= ~act_dma;
+	if (!buf->active_dma) {
+		pxa_camera_wakeup(pcdev, vb, buf);
+		pxa_camera_check_link_miss(pcdev);
 	}
 
 out:
 	spin_unlock_irqrestore(&pcdev->lock, flags);
 }
 
-static void pxa_camera_dma_irq_y(int channel, void *data)
-{
-	struct pxa_camera_dev *pcdev = data;
-	pxa_camera_dma_irq(channel, pcdev, DMA_Y);
-}
-
-static void pxa_camera_dma_irq_u(int channel, void *data)
-{
-	struct pxa_camera_dev *pcdev = data;
-	pxa_camera_dma_irq(channel, pcdev, DMA_U);
-}
-
-static void pxa_camera_dma_irq_v(int channel, void *data)
-{
-	struct pxa_camera_dev *pcdev = data;
-	pxa_camera_dma_irq(channel, pcdev, DMA_V);
-}
-
 static struct videobuf_queue_ops pxa_videobuf_ops = {
 	.buf_setup      = pxa_videobuf_setup,
 	.buf_prepare    = pxa_videobuf_prepare,
@@ -992,10 +933,7 @@ static void pxa_camera_clock_stop(struct soc_camera_host *ici)
 	__raw_writel(0x3ff, pcdev->base + CICR0);
 
 	/* Stop DMA engine */
-	DCSR(pcdev->dma_chans[0]) = 0;
-	DCSR(pcdev->dma_chans[1]) = 0;
-	DCSR(pcdev->dma_chans[2]) = 0;
-
+	pxa_dma_stop_channels(pcdev);
 	pxa_camera_deactivate(pcdev);
 }
 
@@ -1608,10 +1546,6 @@ static int pxa_camera_resume(struct device *dev)
 	struct pxa_camera_dev *pcdev = ici->priv;
 	int i = 0, ret = 0;
 
-	DRCMR(68) = pcdev->dma_chans[0] | DRCMR_MAPVLD;
-	DRCMR(69) = pcdev->dma_chans[1] | DRCMR_MAPVLD;
-	DRCMR(70) = pcdev->dma_chans[2] | DRCMR_MAPVLD;
-
 	__raw_writel(pcdev->save_cicr[i++] & ~CICR0_ENB, pcdev->base + CICR0);
 	__raw_writel(pcdev->save_cicr[i++], pcdev->base + CICR1);
 	__raw_writel(pcdev->save_cicr[i++], pcdev->base + CICR2);
@@ -1655,6 +1589,8 @@ static int pxa_camera_probe(struct platform_device *pdev)
 	struct pxa_camera_dev *pcdev;
 	struct resource *res;
 	void __iomem *base;
+	dma_cap_mask_t mask;
+	unsigned int drcmr;
 	int irq;
 	int err = 0;
 
@@ -1717,36 +1653,35 @@ static int pxa_camera_probe(struct platform_device *pdev)
 	pcdev->base = base;
 
 	/* request dma */
-	err = pxa_request_dma("CI_Y", DMA_PRIO_HIGH,
-			      pxa_camera_dma_irq_y, pcdev);
-	if (err < 0) {
+	dma_cap_zero(mask);
+	dma_cap_set(DMA_SLAVE, mask);
+
+	drcmr = 68;
+	pcdev->dma_chans[0] =
+		dma_request_slave_channel_compat(mask, mmp_pdma_filter_fn,
+						 &drcmr, &pdev->dev, "CI_Y");
+	if (!pcdev->dma_chans[0]) {
 		dev_err(&pdev->dev, "Can't request DMA for Y\n");
-		return err;
+		return -ENODEV;
 	}
-	pcdev->dma_chans[0] = err;
-	dev_dbg(&pdev->dev, "got DMA channel %d\n", pcdev->dma_chans[0]);
 
-	err = pxa_request_dma("CI_U", DMA_PRIO_HIGH,
-			      pxa_camera_dma_irq_u, pcdev);
-	if (err < 0) {
-		dev_err(&pdev->dev, "Can't request DMA for U\n");
+	drcmr = 69;
+	pcdev->dma_chans[1] =
+		dma_request_slave_channel_compat(mask, mmp_pdma_filter_fn,
+						 &drcmr, &pdev->dev, "CI_U");
+	if (!pcdev->dma_chans[1]) {
+		dev_err(&pdev->dev, "Can't request DMA for Y\n");
 		goto exit_free_dma_y;
 	}
-	pcdev->dma_chans[1] = err;
-	dev_dbg(&pdev->dev, "got DMA channel (U) %d\n", pcdev->dma_chans[1]);
 
-	err = pxa_request_dma("CI_V", DMA_PRIO_HIGH,
-			      pxa_camera_dma_irq_v, pcdev);
-	if (err < 0) {
+	drcmr = 70;
+	pcdev->dma_chans[2] =
+		dma_request_slave_channel_compat(mask, mmp_pdma_filter_fn,
+						 &drcmr, &pdev->dev, "CI_V");
+	if (!pcdev->dma_chans[2]) {
 		dev_err(&pdev->dev, "Can't request DMA for V\n");
 		goto exit_free_dma_u;
 	}
-	pcdev->dma_chans[2] = err;
-	dev_dbg(&pdev->dev, "got DMA channel (V) %d\n", pcdev->dma_chans[2]);
-
-	DRCMR(68) = pcdev->dma_chans[0] | DRCMR_MAPVLD;
-	DRCMR(69) = pcdev->dma_chans[1] | DRCMR_MAPVLD;
-	DRCMR(70) = pcdev->dma_chans[2] | DRCMR_MAPVLD;
 
 	/* request irq */
 	err = devm_request_irq(&pdev->dev, pcdev->irq, pxa_camera_irq, 0,
@@ -1769,11 +1704,11 @@ static int pxa_camera_probe(struct platform_device *pdev)
 	return 0;
 
 exit_free_dma:
-	pxa_free_dma(pcdev->dma_chans[2]);
+	dma_release_channel(pcdev->dma_chans[2]);
 exit_free_dma_u:
-	pxa_free_dma(pcdev->dma_chans[1]);
+	dma_release_channel(pcdev->dma_chans[1]);
 exit_free_dma_y:
-	pxa_free_dma(pcdev->dma_chans[0]);
+	dma_release_channel(pcdev->dma_chans[0]);
 	return err;
 }
 
@@ -1783,9 +1718,9 @@ static int pxa_camera_remove(struct platform_device *pdev)
 	struct pxa_camera_dev *pcdev = container_of(soc_host,
 					struct pxa_camera_dev, soc_host);
 
-	pxa_free_dma(pcdev->dma_chans[0]);
-	pxa_free_dma(pcdev->dma_chans[1]);
-	pxa_free_dma(pcdev->dma_chans[2]);
+	dma_release_channel(pcdev->dma_chans[0]);
+	dma_release_channel(pcdev->dma_chans[1]);
+	dma_release_channel(pcdev->dma_chans[2]);
 
 	soc_camera_host_unregister(soc_host);
 
----------


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

* Re: [PATCH 5/9] ARM: dts: provide DMA config to pxamci
@ 2013-12-11  8:19               ` Robert Jarzmik
  0 siblings, 0 replies; 700+ messages in thread
From: Robert Jarzmik @ 2013-12-11  8:19 UTC (permalink / raw)
  To: Daniel Mack
  Cc: Arnd Bergmann, Sergei Ianovich, linux-kernel, linux-arm-kernel,
	Rob Herring, Pawel Moll, Mark Rutland, Stephen Warren,
	Ian Campbell, Rob Landley, Russell King, Chris Ball, Ulf Hansson,
	Jaehoon Chung, Seungwon Jeon, devicetree, linux-doc

Daniel Mack <zonque@gmail.com> writes:

> In particular, the pxa camera driver is something Robert (cc) wanted to
> have a look at. Robert, any updates on this?
Oh yes, sorry, it's been monthes, I've been very busy.

This is my last status :
 - my current patch is in (1)

 - this patch doesn't work yet

 - if my memory serves me well, I have reached the conclusion that dmaengine
   pxa-mpp driver doesn't allow pxa_camera to work properly in the current
   state.  This is a long time since I checked, so take the following with
   caution until I have checked again.

This assertion is based on this required behaviour :
 - video buffers are queued, let's say 5
   => 5 dma are "prepared"

 - video buffers are submitted
   => 5 dma xfers are submitted

 - the userspace polls for each finished frame (ie. dma xfer termination), and
   on the third one, resubmits the 2 finished frames
     => scatter-gathers should mot be recomputed, just xfer should be
     resubmitted, with cache sync operations and first/last descriptors chaining

 - the pxa_camera driver needs a way to know if a dma channel is still running,
   for missed chaining transfers, because if a channel stopped, the dma xfers
   should not be submitted until IRQ "begin of frame" is encoutered. I didn't
   find a way for that.

Now, I will retry this weekend, but if I remember correctly the issues I had
were :
 - a transfer cannot be resubmitted, it has to be freed and recreated
 - if it is resubmitted, the completion is not signaled by the tasklet

Cheers.

--
Robert

(1)
commit 4741ba6 (pxa_camera_dmaengine, backup/pxa_camera_dmaengine)
Author: Robert Jarzmik <robert.jarzmik@free.fr>
Date:   Sat Aug 24 21:13:38 2013 +0200

    WIP: pxa_camera dmaengine conversion
    
    Only slightly tested, without much success.
    
    Signed-off-by: Robert Jarzmik <robert.jarzmik@free.fr>

diff --git a/drivers/media/platform/soc_camera/pxa_camera.c b/drivers/media/platform/soc_camera/pxa_camera.c
index d4df305..903ea03 100644
--- a/drivers/media/platform/soc_camera/pxa_camera.c
+++ b/drivers/media/platform/soc_camera/pxa_camera.c
@@ -9,7 +9,7 @@
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version.
  */
-
+#define DEBUG 1
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/io.h>
@@ -28,6 +28,9 @@
 #include <linux/clk.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
+#include <linux/dmaengine.h>
+#include <linux/dma-mapping.h>
+#include <linux/dma/mmp-pdma.h>
 
 #include <media/v4l2-common.h>
 #include <media/v4l2-dev.h>
@@ -37,7 +40,6 @@
 
 #include <linux/videodev2.h>
 
-#include <mach/dma.h>
 #include <linux/platform_data/camera-pxa.h>
 
 #define PXA_CAM_VERSION "0.0.6"
@@ -174,21 +176,13 @@ enum pxa_camera_active_dma {
 	DMA_V = 0x4,
 };
 
-/* descriptor needed for the PXA DMA engine */
-struct pxa_cam_dma {
-	dma_addr_t		sg_dma;
-	struct pxa_dma_desc	*sg_cpu;
-	size_t			sg_size;
-	int			sglen;
-};
-
 /* buffer for one video frame */
 struct pxa_buffer {
 	/* common v4l buffer stuff -- must be first */
 	struct videobuf_buffer		vb;
 	enum v4l2_mbus_pixelcode	code;
 	/* our descriptor lists for Y, U and V channels */
-	struct pxa_cam_dma		dmas[3];
+	struct dma_async_tx_descriptor	*descs[3];
 	int				inwork;
 	enum pxa_camera_active_dma	active_dma;
 };
@@ -206,7 +200,7 @@ struct pxa_camera_dev {
 	void __iomem		*base;
 
 	int			channels;
-	unsigned int		dma_chans[3];
+	struct dma_chan		*dma_chans[3];
 
 	struct pxacamera_platform_data *pdata;
 	struct resource		*res;
@@ -221,7 +215,6 @@ struct pxa_camera_dev {
 	spinlock_t		lock;
 
 	struct pxa_buffer	*active;
-	struct pxa_dma_desc	*sg_tail[3];
 
 	u32			save_cicr[5];
 };
@@ -273,40 +266,70 @@ static void free_buffer(struct videobuf_queue *vq, struct pxa_buffer *buf)
 	videobuf_waiton(vq, &buf->vb, 0, 0);
 	videobuf_dma_unmap(vq->dev, dma);
 	videobuf_dma_free(dma);
-
-	for (i = 0; i < ARRAY_SIZE(buf->dmas); i++) {
-		if (buf->dmas[i].sg_cpu)
-			dma_free_coherent(ici->v4l2_dev.dev,
-					  buf->dmas[i].sg_size,
-					  buf->dmas[i].sg_cpu,
-					  buf->dmas[i].sg_dma);
-		buf->dmas[i].sg_cpu = NULL;
-	}
+	/* FIXME: free buf->descs[0..2] */
 
 	buf->vb.state = VIDEOBUF_NEEDS_INIT;
+
+	dev_dbg(icd->parent, "%s end (vb=0x%p) 0x%08lx %d\n", __func__,
+		&buf->vb, buf->vb.baddr, buf->vb.bsize);
 }
 
-static int calculate_dma_sglen(struct scatterlist *sglist, int sglen,
-			       int sg_first_ofs, int size)
+static struct scatterlist *videobuf_sg_splice(struct scatterlist *sglist,
+					      int sglen, int offset, int size,
+					      int *new_sg_len)
 {
-	int i, offset, dma_len, xfer_len;
-	struct scatterlist *sg;
+	struct scatterlist *sg0, *sg;
+	int nfirst, i, dma_len, xfer_len;
 
-	offset = sg_first_ofs;
-	for_each_sg(sglist, sg, sglen, i) {
+	sg0 = kmalloc(sizeof(struct scatterlist) * sglen, GFP_KERNEL);
+	if (!sg0)
+		return NULL;
+	for_each_sg(sglist, sg, sglen, nfirst) {
 		dma_len = sg_dma_len(sg);
-
+		if (offset < dma_len)
+			break;
 		/* PXA27x Developer's Manual 27.4.4.1: round up to 8 bytes */
-		xfer_len = roundup(min(dma_len - offset, size), 8);
-
-		size = max(0, size - xfer_len);
-		offset = 0;
-		if (size == 0)
+		xfer_len = roundup(min(dma_len - offset, offset), 8);
+		offset = max(0, offset - xfer_len);
+	}
+	BUG_ON(sg_is_last(&sglist[nfirst]));
+	for_each_sg(&sglist[nfirst], sg, sglen - nfirst, i) {
+		sg0[i] = sglist[nfirst];
+		sg0[i].offset = offset;
+		sg_dma_len(&sg0[i]) -= offset;
+		if (size <= sg_dma_len(sg))
 			break;
+		offset = 0;
+		size -= roundup(sg_dma_len(sg), 8);
+	}
+	if (size) {
+		sg_dma_len(&sg0[i]) = size;
+		*new_sg_len = i + 1;
+	} else {
+		*new_sg_len = i;
 	}
 
-	BUG_ON(size != 0);
-	return i + 1;
+	return sg0;
+}
+static void pxa_camera_dma_irq(struct pxa_camera_dev *pcdev,
+			       enum pxa_camera_active_dma act_dma);
+
+static void pxa_camera_dma_irq_y(void *data)
+{
+	struct pxa_camera_dev *pcdev = data;
+	pxa_camera_dma_irq(pcdev, DMA_Y);
+}
+
+static void pxa_camera_dma_irq_u(void *data)
+{
+	struct pxa_camera_dev *pcdev = data;
+	pxa_camera_dma_irq(pcdev, DMA_U);
+}
+
+static void pxa_camera_dma_irq_v(void *data)
+{
+	struct pxa_camera_dev *pcdev = data;
+	pxa_camera_dma_irq(pcdev, DMA_V);
 }
 
 /**
@@ -317,91 +340,68 @@ static int calculate_dma_sglen(struct scatterlist *sglist, int sglen,
  * @channel: dma channel (0 => 'Y', 1 => 'U', 2 => 'V')
  * @cibr: camera Receive Buffer Register
  * @size: bytes to transfer
- * @sg_first: first element of sg_list
- * @sg_first_ofs: offset in first element of sg_list
+ * @offset: offset in videobuffer of the first byte to transfer
  *
  * Prepares the pxa dma descriptors to transfer one camera channel.
- * Beware sg_first and sg_first_ofs are both input and output parameters.
  *
- * Returns 0 or -ENOMEM if no coherent memory is available
+ * Returns 0 if success or -ENOMEM if no memory is available
  */
 static int pxa_init_dma_channel(struct pxa_camera_dev *pcdev,
 				struct pxa_buffer *buf,
 				struct videobuf_dmabuf *dma, int channel,
-				int cibr, int size,
-				struct scatterlist **sg_first, int *sg_first_ofs)
+				int cibr, int size, int offset)
 {
-	struct pxa_cam_dma *pxa_dma = &buf->dmas[channel];
-	struct device *dev = pcdev->soc_host.v4l2_dev.dev;
-	struct scatterlist *sg;
-	int i, offset, sglen;
-	int dma_len = 0, xfer_len = 0;
+	struct dma_chan *dma_chan = pcdev->dma_chans[channel];
+	struct scatterlist *sg = NULL;
+	int ret, sglen;
+	struct dma_slave_config config;
+	struct dma_async_tx_descriptor *tx;
 
-	if (pxa_dma->sg_cpu)
-		dma_free_coherent(dev, pxa_dma->sg_size,
-				  pxa_dma->sg_cpu, pxa_dma->sg_dma);
+	dmaengine_terminate_all(dma_chan);
 
-	sglen = calculate_dma_sglen(*sg_first, dma->sglen,
-				    *sg_first_ofs, size);
-
-	pxa_dma->sg_size = (sglen + 1) * sizeof(struct pxa_dma_desc);
-	pxa_dma->sg_cpu = dma_alloc_coherent(dev, pxa_dma->sg_size,
-					     &pxa_dma->sg_dma, GFP_KERNEL);
-	if (!pxa_dma->sg_cpu)
+	sg = videobuf_sg_splice(dma->sglist, dma->sglen, offset, size, &sglen);
+	if (!sg)
 		return -ENOMEM;
 
-	pxa_dma->sglen = sglen;
-	offset = *sg_first_ofs;
-
-	dev_dbg(dev, "DMA: sg_first=%p, sglen=%d, ofs=%d, dma.desc=%x\n",
-		*sg_first, sglen, *sg_first_ofs, pxa_dma->sg_dma);
-
+	memset(&config, 0, sizeof(config));
+	config.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; /* FIXME? */
+	config.src_maxburst = 8;
+	config.src_addr = pcdev->res->start + cibr;
+	config.direction = DMA_DEV_TO_MEM;
 
-	for_each_sg(*sg_first, sg, sglen, i) {
-		dma_len = sg_dma_len(sg);
-
-		/* PXA27x Developer's Manual 27.4.4.1: round up to 8 bytes */
-		xfer_len = roundup(min(dma_len - offset, size), 8);
-
-		size = max(0, size - xfer_len);
-
-		pxa_dma->sg_cpu[i].dsadr = pcdev->res->start + cibr;
-		pxa_dma->sg_cpu[i].dtadr = sg_dma_address(sg) + offset;
-		pxa_dma->sg_cpu[i].dcmd =
-			DCMD_FLOWSRC | DCMD_BURST8 | DCMD_INCTRGADDR | xfer_len;
-#ifdef DEBUG
-		if (!i)
-			pxa_dma->sg_cpu[i].dcmd |= DCMD_STARTIRQEN;
-#endif
-		pxa_dma->sg_cpu[i].ddadr =
-			pxa_dma->sg_dma + (i + 1) * sizeof(struct pxa_dma_desc);
-
-		dev_vdbg(dev, "DMA: desc.%08x->@phys=0x%08x, len=%d\n",
-			 pxa_dma->sg_dma + i * sizeof(struct pxa_dma_desc),
-			 sg_dma_address(sg) + offset, xfer_len);
-		offset = 0;
-
-		if (size == 0)
-			break;
+	ret = dmaengine_slave_config(dma_chan, &config);
+	if (ret < 0) {
+		printk("%s(): dma slave config failed: %d\n", __func__, ret);
+		return ret;
 	}
 
-	pxa_dma->sg_cpu[sglen].ddadr = DDADR_STOP;
-	pxa_dma->sg_cpu[sglen].dcmd  = DCMD_FLOWSRC | DCMD_BURST8 | DCMD_ENDIRQEN;
+	tx = dmaengine_prep_slave_sg(dma_chan, sg, sglen,
+				     config.direction,
+				     DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+	if (!tx) {
+		printk("%s(): prep_slave_sg() failed\n", __func__);
+		goto fail;
+	}
 
-	/*
-	 * Handle 1 special case :
-	 *  - in 3 planes (YUV422P format), we might finish with xfer_len equal
-	 *    to dma_len (end on PAGE boundary). In this case, the sg element
-	 *    for next plane should be the next after the last used to store the
-	 *    last scatter gather RAM page
-	 */
-	if (xfer_len >= dma_len) {
-		*sg_first_ofs = xfer_len - dma_len;
-		*sg_first = sg_next(sg);
-	} else {
-		*sg_first_ofs = xfer_len;
-		*sg_first = sg;
+	tx->callback_param = pcdev;
+	switch (channel) {
+	case 0:
+		tx->callback = pxa_camera_dma_irq_y;
+		break;
+	case 1:
+		tx->callback = pxa_camera_dma_irq_u;
+		break;
+	case 2:
+		tx->callback = pxa_camera_dma_irq_v;
+		break;
 	}
+fail:
+	kfree(sg);
+	buf->descs[channel] = tx;
+
+	dev_dbg(pcdev->soc_host.v4l2_dev.dev,
+		"%s (vb=0x%p) dma_tx=%p\n",
+		__func__, &buf->vb, tx);
 
 	return 0;
 }
@@ -470,11 +470,10 @@ static int pxa_videobuf_prepare(struct videobuf_queue *vq,
 		goto out;
 	}
 
-	if (vb->state == VIDEOBUF_NEEDS_INIT) {
+	//if (vb->state == VIDEOBUF_NEEDS_INIT) {
+	if (vb->state != VIDEOBUF_PREPARED) {
 		int size = vb->size;
-		int next_ofs = 0;
 		struct videobuf_dmabuf *dma = videobuf_to_dma(vb);
-		struct scatterlist *sg;
 
 		ret = videobuf_iolock(vq, vb, NULL);
 		if (ret)
@@ -487,11 +486,8 @@ static int pxa_videobuf_prepare(struct videobuf_queue *vq,
 			size_y = size;
 		}
 
-		sg = dma->sglist;
-
 		/* init DMA for Y channel */
-		ret = pxa_init_dma_channel(pcdev, buf, dma, 0, CIBR0, size_y,
-					   &sg, &next_ofs);
+		ret = pxa_init_dma_channel(pcdev, buf, dma, 0, CIBR0, size_y, 0);
 		if (ret) {
 			dev_err(dev, "DMA initialization for Y/RGB failed\n");
 			goto fail;
@@ -500,7 +496,7 @@ static int pxa_videobuf_prepare(struct videobuf_queue *vq,
 		/* init DMA for U channel */
 		if (size_u)
 			ret = pxa_init_dma_channel(pcdev, buf, dma, 1, CIBR1,
-						   size_u, &sg, &next_ofs);
+						   size_u, size_y);
 		if (ret) {
 			dev_err(dev, "DMA initialization for U failed\n");
 			goto fail_u;
@@ -509,7 +505,7 @@ static int pxa_videobuf_prepare(struct videobuf_queue *vq,
 		/* init DMA for V channel */
 		if (size_v)
 			ret = pxa_init_dma_channel(pcdev, buf, dma, 2, CIBR2,
-						   size_v, &sg, &next_ofs);
+						   size_v, size_y + size_u);
 		if (ret) {
 			dev_err(dev, "DMA initialization for V failed\n");
 			goto fail_v;
@@ -524,11 +520,7 @@ static int pxa_videobuf_prepare(struct videobuf_queue *vq,
 	return 0;
 
 fail_v:
-	dma_free_coherent(dev, buf->dmas[1].sg_size,
-			  buf->dmas[1].sg_cpu, buf->dmas[1].sg_dma);
 fail_u:
-	dma_free_coherent(dev, buf->dmas[0].sg_size,
-			  buf->dmas[0].sg_cpu, buf->dmas[0].sg_dma);
 fail:
 	free_buffer(vq, buf);
 out:
@@ -552,10 +544,8 @@ static void pxa_dma_start_channels(struct pxa_camera_dev *pcdev)
 
 	for (i = 0; i < pcdev->channels; i++) {
 		dev_dbg(pcdev->soc_host.v4l2_dev.dev,
-			"%s (channel=%d) ddadr=%08x\n", __func__,
-			i, active->dmas[i].sg_dma);
-		DDADR(pcdev->dma_chans[i]) = active->dmas[i].sg_dma;
-		DCSR(pcdev->dma_chans[i]) = DCSR_RUN;
+			"%s (channel=%d)\n", __func__, i);
+		dma_async_issue_pending(pcdev->dma_chans[i]);
 	}
 }
 
@@ -566,7 +556,7 @@ static void pxa_dma_stop_channels(struct pxa_camera_dev *pcdev)
 	for (i = 0; i < pcdev->channels; i++) {
 		dev_dbg(pcdev->soc_host.v4l2_dev.dev,
 			"%s (channel=%d)\n", __func__, i);
-		DCSR(pcdev->dma_chans[i]) = 0;
+		dmaengine_terminate_all(pcdev->dma_chans[i]);
 	}
 }
 
@@ -574,18 +564,12 @@ static void pxa_dma_add_tail_buf(struct pxa_camera_dev *pcdev,
 				 struct pxa_buffer *buf)
 {
 	int i;
-	struct pxa_dma_desc *buf_last_desc;
 
 	for (i = 0; i < pcdev->channels; i++) {
-		buf_last_desc = buf->dmas[i].sg_cpu + buf->dmas[i].sglen;
-		buf_last_desc->ddadr = DDADR_STOP;
-
-		if (pcdev->sg_tail[i])
-			/* Link the new buffer to the old tail */
-			pcdev->sg_tail[i]->ddadr = buf->dmas[i].sg_dma;
-
-		/* Update the channel tail */
-		pcdev->sg_tail[i] = buf_last_desc;
+		dmaengine_submit(buf->descs[i]);
+		dev_dbg(pcdev->soc_host.v4l2_dev.dev,
+			"%s (channel=%d) : submit vb=%p cookie=%d\n",
+			__func__, i, buf, buf->descs[i]->cookie);
 	}
 }
 
@@ -676,8 +660,6 @@ static void pxa_camera_wakeup(struct pxa_camera_dev *pcdev,
 			      struct videobuf_buffer *vb,
 			      struct pxa_buffer *buf)
 {
-	int i;
-
 	/* _init is used to debug races, see comment in pxa_camera_reqbufs() */
 	list_del_init(&vb->queue);
 	vb->state = VIDEOBUF_DONE;
@@ -689,8 +671,6 @@ static void pxa_camera_wakeup(struct pxa_camera_dev *pcdev,
 
 	if (list_empty(&pcdev->capture)) {
 		pxa_camera_stop_capture(pcdev);
-		for (i = 0; i < pcdev->channels; i++)
-			pcdev->sg_tail[i] = NULL;
 		return;
 	}
 
@@ -716,48 +696,33 @@ static void pxa_camera_wakeup(struct pxa_camera_dev *pcdev,
  */
 static void pxa_camera_check_link_miss(struct pxa_camera_dev *pcdev)
 {
-	int i, is_dma_stopped = 1;
+	/* FIXME: ask dmaengine if channel is still running */
+	int is_dma_stopped = 1;
 
-	for (i = 0; i < pcdev->channels; i++)
-		if (DDADR(pcdev->dma_chans[i]) != DDADR_STOP)
-			is_dma_stopped = 0;
 	dev_dbg(pcdev->soc_host.v4l2_dev.dev,
-		"%s : top queued buffer=%p, dma_stopped=%d\n",
-		__func__, pcdev->active, is_dma_stopped);
+		"%s : top queued buffer=%p\n", __func__, pcdev->active);
+	if (pcdev->active)
+		pxa_dma_start_channels(pcdev);
 	if (pcdev->active && is_dma_stopped)
 		pxa_camera_start_capture(pcdev);
 }
 
-static void pxa_camera_dma_irq(int channel, struct pxa_camera_dev *pcdev,
+static void pxa_camera_dma_irq(struct pxa_camera_dev *pcdev,
 			       enum pxa_camera_active_dma act_dma)
 {
 	struct device *dev = pcdev->soc_host.v4l2_dev.dev;
 	struct pxa_buffer *buf;
 	unsigned long flags;
-	u32 status, camera_status, overrun;
+	u32 camera_status, overrun;
 	struct videobuf_buffer *vb;
 
 	spin_lock_irqsave(&pcdev->lock, flags);
 
-	status = DCSR(channel);
-	DCSR(channel) = status;
-
 	camera_status = __raw_readl(pcdev->base + CISR);
 	overrun = CISR_IFO_0;
 	if (pcdev->channels == 3)
 		overrun |= CISR_IFO_1 | CISR_IFO_2;
 
-	if (status & DCSR_BUSERR) {
-		dev_err(dev, "DMA Bus Error IRQ!\n");
-		goto out;
-	}
-
-	if (!(status & (DCSR_ENDINTR | DCSR_STARTINTR))) {
-		dev_err(dev, "Unknown DMA IRQ source, status: 0x%08x\n",
-			status);
-		goto out;
-	}
-
 	/*
 	 * pcdev->active should not be NULL in DMA irq handler.
 	 *
@@ -777,52 +742,28 @@ static void pxa_camera_dma_irq(int channel, struct pxa_camera_dev *pcdev,
 	buf = container_of(vb, struct pxa_buffer, vb);
 	WARN_ON(buf->inwork || list_empty(&vb->queue));
 
-	dev_dbg(dev, "%s channel=%d %s%s(vb=0x%p) dma.desc=%x\n",
-		__func__, channel, status & DCSR_STARTINTR ? "SOF " : "",
-		status & DCSR_ENDINTR ? "EOF " : "", vb, DDADR(channel));
-
-	if (status & DCSR_ENDINTR) {
-		/*
-		 * It's normal if the last frame creates an overrun, as there
-		 * are no more DMA descriptors to fetch from QCI fifos
-		 */
-		if (camera_status & overrun &&
-		    !list_is_last(pcdev->capture.next, &pcdev->capture)) {
-			dev_dbg(dev, "FIFO overrun! CISR: %x\n",
-				camera_status);
-			pxa_camera_stop_capture(pcdev);
-			pxa_camera_start_capture(pcdev);
-			goto out;
-		}
-		buf->active_dma &= ~act_dma;
-		if (!buf->active_dma) {
-			pxa_camera_wakeup(pcdev, vb, buf);
-			pxa_camera_check_link_miss(pcdev);
-		}
+	/*
+	 * It's normal if the last frame creates an overrun, as there
+	 * are no more DMA descriptors to fetch from QCI fifos
+	 */
+	if (camera_status & overrun &&
+	    !list_is_last(pcdev->capture.next, &pcdev->capture)) {
+		dev_dbg(dev, "FIFO overrun! CISR: %x\n",
+			camera_status);
+		pxa_camera_stop_capture(pcdev);
+		pxa_camera_start_capture(pcdev);
+		goto out;
+	}
+	buf->active_dma &= ~act_dma;
+	if (!buf->active_dma) {
+		pxa_camera_wakeup(pcdev, vb, buf);
+		pxa_camera_check_link_miss(pcdev);
 	}
 
 out:
 	spin_unlock_irqrestore(&pcdev->lock, flags);
 }
 
-static void pxa_camera_dma_irq_y(int channel, void *data)
-{
-	struct pxa_camera_dev *pcdev = data;
-	pxa_camera_dma_irq(channel, pcdev, DMA_Y);
-}
-
-static void pxa_camera_dma_irq_u(int channel, void *data)
-{
-	struct pxa_camera_dev *pcdev = data;
-	pxa_camera_dma_irq(channel, pcdev, DMA_U);
-}
-
-static void pxa_camera_dma_irq_v(int channel, void *data)
-{
-	struct pxa_camera_dev *pcdev = data;
-	pxa_camera_dma_irq(channel, pcdev, DMA_V);
-}
-
 static struct videobuf_queue_ops pxa_videobuf_ops = {
 	.buf_setup      = pxa_videobuf_setup,
 	.buf_prepare    = pxa_videobuf_prepare,
@@ -992,10 +933,7 @@ static void pxa_camera_clock_stop(struct soc_camera_host *ici)
 	__raw_writel(0x3ff, pcdev->base + CICR0);
 
 	/* Stop DMA engine */
-	DCSR(pcdev->dma_chans[0]) = 0;
-	DCSR(pcdev->dma_chans[1]) = 0;
-	DCSR(pcdev->dma_chans[2]) = 0;
-
+	pxa_dma_stop_channels(pcdev);
 	pxa_camera_deactivate(pcdev);
 }
 
@@ -1608,10 +1546,6 @@ static int pxa_camera_resume(struct device *dev)
 	struct pxa_camera_dev *pcdev = ici->priv;
 	int i = 0, ret = 0;
 
-	DRCMR(68) = pcdev->dma_chans[0] | DRCMR_MAPVLD;
-	DRCMR(69) = pcdev->dma_chans[1] | DRCMR_MAPVLD;
-	DRCMR(70) = pcdev->dma_chans[2] | DRCMR_MAPVLD;
-
 	__raw_writel(pcdev->save_cicr[i++] & ~CICR0_ENB, pcdev->base + CICR0);
 	__raw_writel(pcdev->save_cicr[i++], pcdev->base + CICR1);
 	__raw_writel(pcdev->save_cicr[i++], pcdev->base + CICR2);
@@ -1655,6 +1589,8 @@ static int pxa_camera_probe(struct platform_device *pdev)
 	struct pxa_camera_dev *pcdev;
 	struct resource *res;
 	void __iomem *base;
+	dma_cap_mask_t mask;
+	unsigned int drcmr;
 	int irq;
 	int err = 0;
 
@@ -1717,36 +1653,35 @@ static int pxa_camera_probe(struct platform_device *pdev)
 	pcdev->base = base;
 
 	/* request dma */
-	err = pxa_request_dma("CI_Y", DMA_PRIO_HIGH,
-			      pxa_camera_dma_irq_y, pcdev);
-	if (err < 0) {
+	dma_cap_zero(mask);
+	dma_cap_set(DMA_SLAVE, mask);
+
+	drcmr = 68;
+	pcdev->dma_chans[0] =
+		dma_request_slave_channel_compat(mask, mmp_pdma_filter_fn,
+						 &drcmr, &pdev->dev, "CI_Y");
+	if (!pcdev->dma_chans[0]) {
 		dev_err(&pdev->dev, "Can't request DMA for Y\n");
-		return err;
+		return -ENODEV;
 	}
-	pcdev->dma_chans[0] = err;
-	dev_dbg(&pdev->dev, "got DMA channel %d\n", pcdev->dma_chans[0]);
 
-	err = pxa_request_dma("CI_U", DMA_PRIO_HIGH,
-			      pxa_camera_dma_irq_u, pcdev);
-	if (err < 0) {
-		dev_err(&pdev->dev, "Can't request DMA for U\n");
+	drcmr = 69;
+	pcdev->dma_chans[1] =
+		dma_request_slave_channel_compat(mask, mmp_pdma_filter_fn,
+						 &drcmr, &pdev->dev, "CI_U");
+	if (!pcdev->dma_chans[1]) {
+		dev_err(&pdev->dev, "Can't request DMA for Y\n");
 		goto exit_free_dma_y;
 	}
-	pcdev->dma_chans[1] = err;
-	dev_dbg(&pdev->dev, "got DMA channel (U) %d\n", pcdev->dma_chans[1]);
 
-	err = pxa_request_dma("CI_V", DMA_PRIO_HIGH,
-			      pxa_camera_dma_irq_v, pcdev);
-	if (err < 0) {
+	drcmr = 70;
+	pcdev->dma_chans[2] =
+		dma_request_slave_channel_compat(mask, mmp_pdma_filter_fn,
+						 &drcmr, &pdev->dev, "CI_V");
+	if (!pcdev->dma_chans[2]) {
 		dev_err(&pdev->dev, "Can't request DMA for V\n");
 		goto exit_free_dma_u;
 	}
-	pcdev->dma_chans[2] = err;
-	dev_dbg(&pdev->dev, "got DMA channel (V) %d\n", pcdev->dma_chans[2]);
-
-	DRCMR(68) = pcdev->dma_chans[0] | DRCMR_MAPVLD;
-	DRCMR(69) = pcdev->dma_chans[1] | DRCMR_MAPVLD;
-	DRCMR(70) = pcdev->dma_chans[2] | DRCMR_MAPVLD;
 
 	/* request irq */
 	err = devm_request_irq(&pdev->dev, pcdev->irq, pxa_camera_irq, 0,
@@ -1769,11 +1704,11 @@ static int pxa_camera_probe(struct platform_device *pdev)
 	return 0;
 
 exit_free_dma:
-	pxa_free_dma(pcdev->dma_chans[2]);
+	dma_release_channel(pcdev->dma_chans[2]);
 exit_free_dma_u:
-	pxa_free_dma(pcdev->dma_chans[1]);
+	dma_release_channel(pcdev->dma_chans[1]);
 exit_free_dma_y:
-	pxa_free_dma(pcdev->dma_chans[0]);
+	dma_release_channel(pcdev->dma_chans[0]);
 	return err;
 }
 
@@ -1783,9 +1718,9 @@ static int pxa_camera_remove(struct platform_device *pdev)
 	struct pxa_camera_dev *pcdev = container_of(soc_host,
 					struct pxa_camera_dev, soc_host);
 
-	pxa_free_dma(pcdev->dma_chans[0]);
-	pxa_free_dma(pcdev->dma_chans[1]);
-	pxa_free_dma(pcdev->dma_chans[2]);
+	dma_release_channel(pcdev->dma_chans[0]);
+	dma_release_channel(pcdev->dma_chans[1]);
+	dma_release_channel(pcdev->dma_chans[2]);
 
 	soc_camera_host_unregister(soc_host);
 
----------


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

* [PATCH 5/9] ARM: dts: provide DMA config to pxamci
@ 2013-12-11  8:19               ` Robert Jarzmik
  0 siblings, 0 replies; 700+ messages in thread
From: Robert Jarzmik @ 2013-12-11  8:19 UTC (permalink / raw)
  To: linux-arm-kernel

Daniel Mack <zonque@gmail.com> writes:

> In particular, the pxa camera driver is something Robert (cc) wanted to
> have a look at. Robert, any updates on this?
Oh yes, sorry, it's been monthes, I've been very busy.

This is my last status :
 - my current patch is in (1)

 - this patch doesn't work yet

 - if my memory serves me well, I have reached the conclusion that dmaengine
   pxa-mpp driver doesn't allow pxa_camera to work properly in the current
   state.  This is a long time since I checked, so take the following with
   caution until I have checked again.

This assertion is based on this required behaviour :
 - video buffers are queued, let's say 5
   => 5 dma are "prepared"

 - video buffers are submitted
   => 5 dma xfers are submitted

 - the userspace polls for each finished frame (ie. dma xfer termination), and
   on the third one, resubmits the 2 finished frames
     => scatter-gathers should mot be recomputed, just xfer should be
     resubmitted, with cache sync operations and first/last descriptors chaining

 - the pxa_camera driver needs a way to know if a dma channel is still running,
   for missed chaining transfers, because if a channel stopped, the dma xfers
   should not be submitted until IRQ "begin of frame" is encoutered. I didn't
   find a way for that.

Now, I will retry this weekend, but if I remember correctly the issues I had
were :
 - a transfer cannot be resubmitted, it has to be freed and recreated
 - if it is resubmitted, the completion is not signaled by the tasklet

Cheers.

--
Robert

(1)
commit 4741ba6 (pxa_camera_dmaengine, backup/pxa_camera_dmaengine)
Author: Robert Jarzmik <robert.jarzmik@free.fr>
Date:   Sat Aug 24 21:13:38 2013 +0200

    WIP: pxa_camera dmaengine conversion
    
    Only slightly tested, without much success.
    
    Signed-off-by: Robert Jarzmik <robert.jarzmik@free.fr>

diff --git a/drivers/media/platform/soc_camera/pxa_camera.c b/drivers/media/platform/soc_camera/pxa_camera.c
index d4df305..903ea03 100644
--- a/drivers/media/platform/soc_camera/pxa_camera.c
+++ b/drivers/media/platform/soc_camera/pxa_camera.c
@@ -9,7 +9,7 @@
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version.
  */
-
+#define DEBUG 1
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/io.h>
@@ -28,6 +28,9 @@
 #include <linux/clk.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
+#include <linux/dmaengine.h>
+#include <linux/dma-mapping.h>
+#include <linux/dma/mmp-pdma.h>
 
 #include <media/v4l2-common.h>
 #include <media/v4l2-dev.h>
@@ -37,7 +40,6 @@
 
 #include <linux/videodev2.h>
 
-#include <mach/dma.h>
 #include <linux/platform_data/camera-pxa.h>
 
 #define PXA_CAM_VERSION "0.0.6"
@@ -174,21 +176,13 @@ enum pxa_camera_active_dma {
 	DMA_V = 0x4,
 };
 
-/* descriptor needed for the PXA DMA engine */
-struct pxa_cam_dma {
-	dma_addr_t		sg_dma;
-	struct pxa_dma_desc	*sg_cpu;
-	size_t			sg_size;
-	int			sglen;
-};
-
 /* buffer for one video frame */
 struct pxa_buffer {
 	/* common v4l buffer stuff -- must be first */
 	struct videobuf_buffer		vb;
 	enum v4l2_mbus_pixelcode	code;
 	/* our descriptor lists for Y, U and V channels */
-	struct pxa_cam_dma		dmas[3];
+	struct dma_async_tx_descriptor	*descs[3];
 	int				inwork;
 	enum pxa_camera_active_dma	active_dma;
 };
@@ -206,7 +200,7 @@ struct pxa_camera_dev {
 	void __iomem		*base;
 
 	int			channels;
-	unsigned int		dma_chans[3];
+	struct dma_chan		*dma_chans[3];
 
 	struct pxacamera_platform_data *pdata;
 	struct resource		*res;
@@ -221,7 +215,6 @@ struct pxa_camera_dev {
 	spinlock_t		lock;
 
 	struct pxa_buffer	*active;
-	struct pxa_dma_desc	*sg_tail[3];
 
 	u32			save_cicr[5];
 };
@@ -273,40 +266,70 @@ static void free_buffer(struct videobuf_queue *vq, struct pxa_buffer *buf)
 	videobuf_waiton(vq, &buf->vb, 0, 0);
 	videobuf_dma_unmap(vq->dev, dma);
 	videobuf_dma_free(dma);
-
-	for (i = 0; i < ARRAY_SIZE(buf->dmas); i++) {
-		if (buf->dmas[i].sg_cpu)
-			dma_free_coherent(ici->v4l2_dev.dev,
-					  buf->dmas[i].sg_size,
-					  buf->dmas[i].sg_cpu,
-					  buf->dmas[i].sg_dma);
-		buf->dmas[i].sg_cpu = NULL;
-	}
+	/* FIXME: free buf->descs[0..2] */
 
 	buf->vb.state = VIDEOBUF_NEEDS_INIT;
+
+	dev_dbg(icd->parent, "%s end (vb=0x%p) 0x%08lx %d\n", __func__,
+		&buf->vb, buf->vb.baddr, buf->vb.bsize);
 }
 
-static int calculate_dma_sglen(struct scatterlist *sglist, int sglen,
-			       int sg_first_ofs, int size)
+static struct scatterlist *videobuf_sg_splice(struct scatterlist *sglist,
+					      int sglen, int offset, int size,
+					      int *new_sg_len)
 {
-	int i, offset, dma_len, xfer_len;
-	struct scatterlist *sg;
+	struct scatterlist *sg0, *sg;
+	int nfirst, i, dma_len, xfer_len;
 
-	offset = sg_first_ofs;
-	for_each_sg(sglist, sg, sglen, i) {
+	sg0 = kmalloc(sizeof(struct scatterlist) * sglen, GFP_KERNEL);
+	if (!sg0)
+		return NULL;
+	for_each_sg(sglist, sg, sglen, nfirst) {
 		dma_len = sg_dma_len(sg);
-
+		if (offset < dma_len)
+			break;
 		/* PXA27x Developer's Manual 27.4.4.1: round up to 8 bytes */
-		xfer_len = roundup(min(dma_len - offset, size), 8);
-
-		size = max(0, size - xfer_len);
-		offset = 0;
-		if (size == 0)
+		xfer_len = roundup(min(dma_len - offset, offset), 8);
+		offset = max(0, offset - xfer_len);
+	}
+	BUG_ON(sg_is_last(&sglist[nfirst]));
+	for_each_sg(&sglist[nfirst], sg, sglen - nfirst, i) {
+		sg0[i] = sglist[nfirst];
+		sg0[i].offset = offset;
+		sg_dma_len(&sg0[i]) -= offset;
+		if (size <= sg_dma_len(sg))
 			break;
+		offset = 0;
+		size -= roundup(sg_dma_len(sg), 8);
+	}
+	if (size) {
+		sg_dma_len(&sg0[i]) = size;
+		*new_sg_len = i + 1;
+	} else {
+		*new_sg_len = i;
 	}
 
-	BUG_ON(size != 0);
-	return i + 1;
+	return sg0;
+}
+static void pxa_camera_dma_irq(struct pxa_camera_dev *pcdev,
+			       enum pxa_camera_active_dma act_dma);
+
+static void pxa_camera_dma_irq_y(void *data)
+{
+	struct pxa_camera_dev *pcdev = data;
+	pxa_camera_dma_irq(pcdev, DMA_Y);
+}
+
+static void pxa_camera_dma_irq_u(void *data)
+{
+	struct pxa_camera_dev *pcdev = data;
+	pxa_camera_dma_irq(pcdev, DMA_U);
+}
+
+static void pxa_camera_dma_irq_v(void *data)
+{
+	struct pxa_camera_dev *pcdev = data;
+	pxa_camera_dma_irq(pcdev, DMA_V);
 }
 
 /**
@@ -317,91 +340,68 @@ static int calculate_dma_sglen(struct scatterlist *sglist, int sglen,
  * @channel: dma channel (0 => 'Y', 1 => 'U', 2 => 'V')
  * @cibr: camera Receive Buffer Register
  * @size: bytes to transfer
- * @sg_first: first element of sg_list
- * @sg_first_ofs: offset in first element of sg_list
+ * @offset: offset in videobuffer of the first byte to transfer
  *
  * Prepares the pxa dma descriptors to transfer one camera channel.
- * Beware sg_first and sg_first_ofs are both input and output parameters.
  *
- * Returns 0 or -ENOMEM if no coherent memory is available
+ * Returns 0 if success or -ENOMEM if no memory is available
  */
 static int pxa_init_dma_channel(struct pxa_camera_dev *pcdev,
 				struct pxa_buffer *buf,
 				struct videobuf_dmabuf *dma, int channel,
-				int cibr, int size,
-				struct scatterlist **sg_first, int *sg_first_ofs)
+				int cibr, int size, int offset)
 {
-	struct pxa_cam_dma *pxa_dma = &buf->dmas[channel];
-	struct device *dev = pcdev->soc_host.v4l2_dev.dev;
-	struct scatterlist *sg;
-	int i, offset, sglen;
-	int dma_len = 0, xfer_len = 0;
+	struct dma_chan *dma_chan = pcdev->dma_chans[channel];
+	struct scatterlist *sg = NULL;
+	int ret, sglen;
+	struct dma_slave_config config;
+	struct dma_async_tx_descriptor *tx;
 
-	if (pxa_dma->sg_cpu)
-		dma_free_coherent(dev, pxa_dma->sg_size,
-				  pxa_dma->sg_cpu, pxa_dma->sg_dma);
+	dmaengine_terminate_all(dma_chan);
 
-	sglen = calculate_dma_sglen(*sg_first, dma->sglen,
-				    *sg_first_ofs, size);
-
-	pxa_dma->sg_size = (sglen + 1) * sizeof(struct pxa_dma_desc);
-	pxa_dma->sg_cpu = dma_alloc_coherent(dev, pxa_dma->sg_size,
-					     &pxa_dma->sg_dma, GFP_KERNEL);
-	if (!pxa_dma->sg_cpu)
+	sg = videobuf_sg_splice(dma->sglist, dma->sglen, offset, size, &sglen);
+	if (!sg)
 		return -ENOMEM;
 
-	pxa_dma->sglen = sglen;
-	offset = *sg_first_ofs;
-
-	dev_dbg(dev, "DMA: sg_first=%p, sglen=%d, ofs=%d, dma.desc=%x\n",
-		*sg_first, sglen, *sg_first_ofs, pxa_dma->sg_dma);
-
+	memset(&config, 0, sizeof(config));
+	config.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; /* FIXME? */
+	config.src_maxburst = 8;
+	config.src_addr = pcdev->res->start + cibr;
+	config.direction = DMA_DEV_TO_MEM;
 
-	for_each_sg(*sg_first, sg, sglen, i) {
-		dma_len = sg_dma_len(sg);
-
-		/* PXA27x Developer's Manual 27.4.4.1: round up to 8 bytes */
-		xfer_len = roundup(min(dma_len - offset, size), 8);
-
-		size = max(0, size - xfer_len);
-
-		pxa_dma->sg_cpu[i].dsadr = pcdev->res->start + cibr;
-		pxa_dma->sg_cpu[i].dtadr = sg_dma_address(sg) + offset;
-		pxa_dma->sg_cpu[i].dcmd =
-			DCMD_FLOWSRC | DCMD_BURST8 | DCMD_INCTRGADDR | xfer_len;
-#ifdef DEBUG
-		if (!i)
-			pxa_dma->sg_cpu[i].dcmd |= DCMD_STARTIRQEN;
-#endif
-		pxa_dma->sg_cpu[i].ddadr =
-			pxa_dma->sg_dma + (i + 1) * sizeof(struct pxa_dma_desc);
-
-		dev_vdbg(dev, "DMA: desc.%08x->@phys=0x%08x, len=%d\n",
-			 pxa_dma->sg_dma + i * sizeof(struct pxa_dma_desc),
-			 sg_dma_address(sg) + offset, xfer_len);
-		offset = 0;
-
-		if (size == 0)
-			break;
+	ret = dmaengine_slave_config(dma_chan, &config);
+	if (ret < 0) {
+		printk("%s(): dma slave config failed: %d\n", __func__, ret);
+		return ret;
 	}
 
-	pxa_dma->sg_cpu[sglen].ddadr = DDADR_STOP;
-	pxa_dma->sg_cpu[sglen].dcmd  = DCMD_FLOWSRC | DCMD_BURST8 | DCMD_ENDIRQEN;
+	tx = dmaengine_prep_slave_sg(dma_chan, sg, sglen,
+				     config.direction,
+				     DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+	if (!tx) {
+		printk("%s(): prep_slave_sg() failed\n", __func__);
+		goto fail;
+	}
 
-	/*
-	 * Handle 1 special case :
-	 *  - in 3 planes (YUV422P format), we might finish with xfer_len equal
-	 *    to dma_len (end on PAGE boundary). In this case, the sg element
-	 *    for next plane should be the next after the last used to store the
-	 *    last scatter gather RAM page
-	 */
-	if (xfer_len >= dma_len) {
-		*sg_first_ofs = xfer_len - dma_len;
-		*sg_first = sg_next(sg);
-	} else {
-		*sg_first_ofs = xfer_len;
-		*sg_first = sg;
+	tx->callback_param = pcdev;
+	switch (channel) {
+	case 0:
+		tx->callback = pxa_camera_dma_irq_y;
+		break;
+	case 1:
+		tx->callback = pxa_camera_dma_irq_u;
+		break;
+	case 2:
+		tx->callback = pxa_camera_dma_irq_v;
+		break;
 	}
+fail:
+	kfree(sg);
+	buf->descs[channel] = tx;
+
+	dev_dbg(pcdev->soc_host.v4l2_dev.dev,
+		"%s (vb=0x%p) dma_tx=%p\n",
+		__func__, &buf->vb, tx);
 
 	return 0;
 }
@@ -470,11 +470,10 @@ static int pxa_videobuf_prepare(struct videobuf_queue *vq,
 		goto out;
 	}
 
-	if (vb->state == VIDEOBUF_NEEDS_INIT) {
+	//if (vb->state == VIDEOBUF_NEEDS_INIT) {
+	if (vb->state != VIDEOBUF_PREPARED) {
 		int size = vb->size;
-		int next_ofs = 0;
 		struct videobuf_dmabuf *dma = videobuf_to_dma(vb);
-		struct scatterlist *sg;
 
 		ret = videobuf_iolock(vq, vb, NULL);
 		if (ret)
@@ -487,11 +486,8 @@ static int pxa_videobuf_prepare(struct videobuf_queue *vq,
 			size_y = size;
 		}
 
-		sg = dma->sglist;
-
 		/* init DMA for Y channel */
-		ret = pxa_init_dma_channel(pcdev, buf, dma, 0, CIBR0, size_y,
-					   &sg, &next_ofs);
+		ret = pxa_init_dma_channel(pcdev, buf, dma, 0, CIBR0, size_y, 0);
 		if (ret) {
 			dev_err(dev, "DMA initialization for Y/RGB failed\n");
 			goto fail;
@@ -500,7 +496,7 @@ static int pxa_videobuf_prepare(struct videobuf_queue *vq,
 		/* init DMA for U channel */
 		if (size_u)
 			ret = pxa_init_dma_channel(pcdev, buf, dma, 1, CIBR1,
-						   size_u, &sg, &next_ofs);
+						   size_u, size_y);
 		if (ret) {
 			dev_err(dev, "DMA initialization for U failed\n");
 			goto fail_u;
@@ -509,7 +505,7 @@ static int pxa_videobuf_prepare(struct videobuf_queue *vq,
 		/* init DMA for V channel */
 		if (size_v)
 			ret = pxa_init_dma_channel(pcdev, buf, dma, 2, CIBR2,
-						   size_v, &sg, &next_ofs);
+						   size_v, size_y + size_u);
 		if (ret) {
 			dev_err(dev, "DMA initialization for V failed\n");
 			goto fail_v;
@@ -524,11 +520,7 @@ static int pxa_videobuf_prepare(struct videobuf_queue *vq,
 	return 0;
 
 fail_v:
-	dma_free_coherent(dev, buf->dmas[1].sg_size,
-			  buf->dmas[1].sg_cpu, buf->dmas[1].sg_dma);
 fail_u:
-	dma_free_coherent(dev, buf->dmas[0].sg_size,
-			  buf->dmas[0].sg_cpu, buf->dmas[0].sg_dma);
 fail:
 	free_buffer(vq, buf);
 out:
@@ -552,10 +544,8 @@ static void pxa_dma_start_channels(struct pxa_camera_dev *pcdev)
 
 	for (i = 0; i < pcdev->channels; i++) {
 		dev_dbg(pcdev->soc_host.v4l2_dev.dev,
-			"%s (channel=%d) ddadr=%08x\n", __func__,
-			i, active->dmas[i].sg_dma);
-		DDADR(pcdev->dma_chans[i]) = active->dmas[i].sg_dma;
-		DCSR(pcdev->dma_chans[i]) = DCSR_RUN;
+			"%s (channel=%d)\n", __func__, i);
+		dma_async_issue_pending(pcdev->dma_chans[i]);
 	}
 }
 
@@ -566,7 +556,7 @@ static void pxa_dma_stop_channels(struct pxa_camera_dev *pcdev)
 	for (i = 0; i < pcdev->channels; i++) {
 		dev_dbg(pcdev->soc_host.v4l2_dev.dev,
 			"%s (channel=%d)\n", __func__, i);
-		DCSR(pcdev->dma_chans[i]) = 0;
+		dmaengine_terminate_all(pcdev->dma_chans[i]);
 	}
 }
 
@@ -574,18 +564,12 @@ static void pxa_dma_add_tail_buf(struct pxa_camera_dev *pcdev,
 				 struct pxa_buffer *buf)
 {
 	int i;
-	struct pxa_dma_desc *buf_last_desc;
 
 	for (i = 0; i < pcdev->channels; i++) {
-		buf_last_desc = buf->dmas[i].sg_cpu + buf->dmas[i].sglen;
-		buf_last_desc->ddadr = DDADR_STOP;
-
-		if (pcdev->sg_tail[i])
-			/* Link the new buffer to the old tail */
-			pcdev->sg_tail[i]->ddadr = buf->dmas[i].sg_dma;
-
-		/* Update the channel tail */
-		pcdev->sg_tail[i] = buf_last_desc;
+		dmaengine_submit(buf->descs[i]);
+		dev_dbg(pcdev->soc_host.v4l2_dev.dev,
+			"%s (channel=%d) : submit vb=%p cookie=%d\n",
+			__func__, i, buf, buf->descs[i]->cookie);
 	}
 }
 
@@ -676,8 +660,6 @@ static void pxa_camera_wakeup(struct pxa_camera_dev *pcdev,
 			      struct videobuf_buffer *vb,
 			      struct pxa_buffer *buf)
 {
-	int i;
-
 	/* _init is used to debug races, see comment in pxa_camera_reqbufs() */
 	list_del_init(&vb->queue);
 	vb->state = VIDEOBUF_DONE;
@@ -689,8 +671,6 @@ static void pxa_camera_wakeup(struct pxa_camera_dev *pcdev,
 
 	if (list_empty(&pcdev->capture)) {
 		pxa_camera_stop_capture(pcdev);
-		for (i = 0; i < pcdev->channels; i++)
-			pcdev->sg_tail[i] = NULL;
 		return;
 	}
 
@@ -716,48 +696,33 @@ static void pxa_camera_wakeup(struct pxa_camera_dev *pcdev,
  */
 static void pxa_camera_check_link_miss(struct pxa_camera_dev *pcdev)
 {
-	int i, is_dma_stopped = 1;
+	/* FIXME: ask dmaengine if channel is still running */
+	int is_dma_stopped = 1;
 
-	for (i = 0; i < pcdev->channels; i++)
-		if (DDADR(pcdev->dma_chans[i]) != DDADR_STOP)
-			is_dma_stopped = 0;
 	dev_dbg(pcdev->soc_host.v4l2_dev.dev,
-		"%s : top queued buffer=%p, dma_stopped=%d\n",
-		__func__, pcdev->active, is_dma_stopped);
+		"%s : top queued buffer=%p\n", __func__, pcdev->active);
+	if (pcdev->active)
+		pxa_dma_start_channels(pcdev);
 	if (pcdev->active && is_dma_stopped)
 		pxa_camera_start_capture(pcdev);
 }
 
-static void pxa_camera_dma_irq(int channel, struct pxa_camera_dev *pcdev,
+static void pxa_camera_dma_irq(struct pxa_camera_dev *pcdev,
 			       enum pxa_camera_active_dma act_dma)
 {
 	struct device *dev = pcdev->soc_host.v4l2_dev.dev;
 	struct pxa_buffer *buf;
 	unsigned long flags;
-	u32 status, camera_status, overrun;
+	u32 camera_status, overrun;
 	struct videobuf_buffer *vb;
 
 	spin_lock_irqsave(&pcdev->lock, flags);
 
-	status = DCSR(channel);
-	DCSR(channel) = status;
-
 	camera_status = __raw_readl(pcdev->base + CISR);
 	overrun = CISR_IFO_0;
 	if (pcdev->channels == 3)
 		overrun |= CISR_IFO_1 | CISR_IFO_2;
 
-	if (status & DCSR_BUSERR) {
-		dev_err(dev, "DMA Bus Error IRQ!\n");
-		goto out;
-	}
-
-	if (!(status & (DCSR_ENDINTR | DCSR_STARTINTR))) {
-		dev_err(dev, "Unknown DMA IRQ source, status: 0x%08x\n",
-			status);
-		goto out;
-	}
-
 	/*
 	 * pcdev->active should not be NULL in DMA irq handler.
 	 *
@@ -777,52 +742,28 @@ static void pxa_camera_dma_irq(int channel, struct pxa_camera_dev *pcdev,
 	buf = container_of(vb, struct pxa_buffer, vb);
 	WARN_ON(buf->inwork || list_empty(&vb->queue));
 
-	dev_dbg(dev, "%s channel=%d %s%s(vb=0x%p) dma.desc=%x\n",
-		__func__, channel, status & DCSR_STARTINTR ? "SOF " : "",
-		status & DCSR_ENDINTR ? "EOF " : "", vb, DDADR(channel));
-
-	if (status & DCSR_ENDINTR) {
-		/*
-		 * It's normal if the last frame creates an overrun, as there
-		 * are no more DMA descriptors to fetch from QCI fifos
-		 */
-		if (camera_status & overrun &&
-		    !list_is_last(pcdev->capture.next, &pcdev->capture)) {
-			dev_dbg(dev, "FIFO overrun! CISR: %x\n",
-				camera_status);
-			pxa_camera_stop_capture(pcdev);
-			pxa_camera_start_capture(pcdev);
-			goto out;
-		}
-		buf->active_dma &= ~act_dma;
-		if (!buf->active_dma) {
-			pxa_camera_wakeup(pcdev, vb, buf);
-			pxa_camera_check_link_miss(pcdev);
-		}
+	/*
+	 * It's normal if the last frame creates an overrun, as there
+	 * are no more DMA descriptors to fetch from QCI fifos
+	 */
+	if (camera_status & overrun &&
+	    !list_is_last(pcdev->capture.next, &pcdev->capture)) {
+		dev_dbg(dev, "FIFO overrun! CISR: %x\n",
+			camera_status);
+		pxa_camera_stop_capture(pcdev);
+		pxa_camera_start_capture(pcdev);
+		goto out;
+	}
+	buf->active_dma &= ~act_dma;
+	if (!buf->active_dma) {
+		pxa_camera_wakeup(pcdev, vb, buf);
+		pxa_camera_check_link_miss(pcdev);
 	}
 
 out:
 	spin_unlock_irqrestore(&pcdev->lock, flags);
 }
 
-static void pxa_camera_dma_irq_y(int channel, void *data)
-{
-	struct pxa_camera_dev *pcdev = data;
-	pxa_camera_dma_irq(channel, pcdev, DMA_Y);
-}
-
-static void pxa_camera_dma_irq_u(int channel, void *data)
-{
-	struct pxa_camera_dev *pcdev = data;
-	pxa_camera_dma_irq(channel, pcdev, DMA_U);
-}
-
-static void pxa_camera_dma_irq_v(int channel, void *data)
-{
-	struct pxa_camera_dev *pcdev = data;
-	pxa_camera_dma_irq(channel, pcdev, DMA_V);
-}
-
 static struct videobuf_queue_ops pxa_videobuf_ops = {
 	.buf_setup      = pxa_videobuf_setup,
 	.buf_prepare    = pxa_videobuf_prepare,
@@ -992,10 +933,7 @@ static void pxa_camera_clock_stop(struct soc_camera_host *ici)
 	__raw_writel(0x3ff, pcdev->base + CICR0);
 
 	/* Stop DMA engine */
-	DCSR(pcdev->dma_chans[0]) = 0;
-	DCSR(pcdev->dma_chans[1]) = 0;
-	DCSR(pcdev->dma_chans[2]) = 0;
-
+	pxa_dma_stop_channels(pcdev);
 	pxa_camera_deactivate(pcdev);
 }
 
@@ -1608,10 +1546,6 @@ static int pxa_camera_resume(struct device *dev)
 	struct pxa_camera_dev *pcdev = ici->priv;
 	int i = 0, ret = 0;
 
-	DRCMR(68) = pcdev->dma_chans[0] | DRCMR_MAPVLD;
-	DRCMR(69) = pcdev->dma_chans[1] | DRCMR_MAPVLD;
-	DRCMR(70) = pcdev->dma_chans[2] | DRCMR_MAPVLD;
-
 	__raw_writel(pcdev->save_cicr[i++] & ~CICR0_ENB, pcdev->base + CICR0);
 	__raw_writel(pcdev->save_cicr[i++], pcdev->base + CICR1);
 	__raw_writel(pcdev->save_cicr[i++], pcdev->base + CICR2);
@@ -1655,6 +1589,8 @@ static int pxa_camera_probe(struct platform_device *pdev)
 	struct pxa_camera_dev *pcdev;
 	struct resource *res;
 	void __iomem *base;
+	dma_cap_mask_t mask;
+	unsigned int drcmr;
 	int irq;
 	int err = 0;
 
@@ -1717,36 +1653,35 @@ static int pxa_camera_probe(struct platform_device *pdev)
 	pcdev->base = base;
 
 	/* request dma */
-	err = pxa_request_dma("CI_Y", DMA_PRIO_HIGH,
-			      pxa_camera_dma_irq_y, pcdev);
-	if (err < 0) {
+	dma_cap_zero(mask);
+	dma_cap_set(DMA_SLAVE, mask);
+
+	drcmr = 68;
+	pcdev->dma_chans[0] =
+		dma_request_slave_channel_compat(mask, mmp_pdma_filter_fn,
+						 &drcmr, &pdev->dev, "CI_Y");
+	if (!pcdev->dma_chans[0]) {
 		dev_err(&pdev->dev, "Can't request DMA for Y\n");
-		return err;
+		return -ENODEV;
 	}
-	pcdev->dma_chans[0] = err;
-	dev_dbg(&pdev->dev, "got DMA channel %d\n", pcdev->dma_chans[0]);
 
-	err = pxa_request_dma("CI_U", DMA_PRIO_HIGH,
-			      pxa_camera_dma_irq_u, pcdev);
-	if (err < 0) {
-		dev_err(&pdev->dev, "Can't request DMA for U\n");
+	drcmr = 69;
+	pcdev->dma_chans[1] =
+		dma_request_slave_channel_compat(mask, mmp_pdma_filter_fn,
+						 &drcmr, &pdev->dev, "CI_U");
+	if (!pcdev->dma_chans[1]) {
+		dev_err(&pdev->dev, "Can't request DMA for Y\n");
 		goto exit_free_dma_y;
 	}
-	pcdev->dma_chans[1] = err;
-	dev_dbg(&pdev->dev, "got DMA channel (U) %d\n", pcdev->dma_chans[1]);
 
-	err = pxa_request_dma("CI_V", DMA_PRIO_HIGH,
-			      pxa_camera_dma_irq_v, pcdev);
-	if (err < 0) {
+	drcmr = 70;
+	pcdev->dma_chans[2] =
+		dma_request_slave_channel_compat(mask, mmp_pdma_filter_fn,
+						 &drcmr, &pdev->dev, "CI_V");
+	if (!pcdev->dma_chans[2]) {
 		dev_err(&pdev->dev, "Can't request DMA for V\n");
 		goto exit_free_dma_u;
 	}
-	pcdev->dma_chans[2] = err;
-	dev_dbg(&pdev->dev, "got DMA channel (V) %d\n", pcdev->dma_chans[2]);
-
-	DRCMR(68) = pcdev->dma_chans[0] | DRCMR_MAPVLD;
-	DRCMR(69) = pcdev->dma_chans[1] | DRCMR_MAPVLD;
-	DRCMR(70) = pcdev->dma_chans[2] | DRCMR_MAPVLD;
 
 	/* request irq */
 	err = devm_request_irq(&pdev->dev, pcdev->irq, pxa_camera_irq, 0,
@@ -1769,11 +1704,11 @@ static int pxa_camera_probe(struct platform_device *pdev)
 	return 0;
 
 exit_free_dma:
-	pxa_free_dma(pcdev->dma_chans[2]);
+	dma_release_channel(pcdev->dma_chans[2]);
 exit_free_dma_u:
-	pxa_free_dma(pcdev->dma_chans[1]);
+	dma_release_channel(pcdev->dma_chans[1]);
 exit_free_dma_y:
-	pxa_free_dma(pcdev->dma_chans[0]);
+	dma_release_channel(pcdev->dma_chans[0]);
 	return err;
 }
 
@@ -1783,9 +1718,9 @@ static int pxa_camera_remove(struct platform_device *pdev)
 	struct pxa_camera_dev *pcdev = container_of(soc_host,
 					struct pxa_camera_dev, soc_host);
 
-	pxa_free_dma(pcdev->dma_chans[0]);
-	pxa_free_dma(pcdev->dma_chans[1]);
-	pxa_free_dma(pcdev->dma_chans[2]);
+	dma_release_channel(pcdev->dma_chans[0]);
+	dma_release_channel(pcdev->dma_chans[1]);
+	dma_release_channel(pcdev->dma_chans[2]);
 
 	soc_camera_host_unregister(soc_host);
 
----------

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

* Re: [PATCH 02/11] arm: pxa27x: support ICP DAS LP-8x4x
  2013-12-11  5:41                     ` Sergei Ianovich
@ 2013-12-11 14:53                       ` Arnd Bergmann
  -1 siblings, 0 replies; 700+ messages in thread
From: Arnd Bergmann @ 2013-12-11 14:53 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: linux-arm-kernel, Russell King, Linus Walleij, linux-kernel,
	Haojian Zhuang, Daniel Mack, Olof Johansson, Eric Miao

On Wednesday 11 December 2013, Sergei Ianovich wrote:
> On Wed, 2013-12-11 at 06:11 +0100, Arnd Bergmann wrote:
> > It depends: if the driver is for the entire FPGA and does
> > the irqchip stuff in addition, it should probably live
> > in drivers/mfd. If it's a pure irqchip driver, drivers/irqchip
> > is better. You have to be careful in the second case though
> > because devices pointing to this irqchip in DT won't get
> > an IRQ resource assigned automatically but have to use
> > irq_of_parse_and_map instead. This may have been fixed since
> > I last looked though, I would consider that behavior a
> > bug in the of_platform handling.
> 
> Thanks again for explaining.
> 
> Although FPGA is a MFD, its irq are used mostly by 8250 serial ports. It
> will be enough to embed irqchip into serial driver for now.
> 
> If there is a need to use the chip in another driver, it will be
> possible to introduce an artificial dependency there for the serial
> driver to ensure the serial driver is loaded before the other one.
> 
> Is this plan acceptable?
> 

If you already have an MFD driver, I think it's more logical to put
the irqchip in there, we have a number of other MFD drivers doing the
same but I have not seen a UART driver that comes with its own irqchip.

	Arnd

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

* [PATCH 02/11] arm: pxa27x: support ICP DAS LP-8x4x
@ 2013-12-11 14:53                       ` Arnd Bergmann
  0 siblings, 0 replies; 700+ messages in thread
From: Arnd Bergmann @ 2013-12-11 14:53 UTC (permalink / raw)
  To: linux-arm-kernel

On Wednesday 11 December 2013, Sergei Ianovich wrote:
> On Wed, 2013-12-11 at 06:11 +0100, Arnd Bergmann wrote:
> > It depends: if the driver is for the entire FPGA and does
> > the irqchip stuff in addition, it should probably live
> > in drivers/mfd. If it's a pure irqchip driver, drivers/irqchip
> > is better. You have to be careful in the second case though
> > because devices pointing to this irqchip in DT won't get
> > an IRQ resource assigned automatically but have to use
> > irq_of_parse_and_map instead. This may have been fixed since
> > I last looked though, I would consider that behavior a
> > bug in the of_platform handling.
> 
> Thanks again for explaining.
> 
> Although FPGA is a MFD, its irq are used mostly by 8250 serial ports. It
> will be enough to embed irqchip into serial driver for now.
> 
> If there is a need to use the chip in another driver, it will be
> possible to introduce an artificial dependency there for the serial
> driver to ensure the serial driver is loaded before the other one.
> 
> Is this plan acceptable?
> 

If you already have an MFD driver, I think it's more logical to put
the irqchip in there, we have a number of other MFD drivers doing the
same but I have not seen a UART driver that comes with its own irqchip.

	Arnd

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

* Re: [PATCH v2 02/11] arm: pxa27x: support ICP DAS LP-8x4x
  2013-12-10 12:47         ` Sergei Ianovich
@ 2013-12-12 19:58           ` Linus Walleij
  -1 siblings, 0 replies; 700+ messages in thread
From: Linus Walleij @ 2013-12-12 19:58 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: linux-kernel, linux-arm-kernel, Eric Miao, Russell King,
	Haojian Zhuang, Arnd Bergmann, Haojian Zhuang

On Tue, Dec 10, 2013 at 1:47 PM, Sergei Ianovich <ynvich@gmail.com> wrote:
> On Tue, 2013-12-10 at 13:43 +0100, Linus Walleij wrote:
>> Argh! Now you're adding another user for a legacy custom pin control
>> implementation. But if noone is going to modernize PXA2xx what
>> can we do :-/
>
> I've rewritten the device to use device tree and posted patch series for
> that.

THANKS! For doing this.

Yours,
Linus Walleij

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

* [PATCH v2 02/11] arm: pxa27x: support ICP DAS LP-8x4x
@ 2013-12-12 19:58           ` Linus Walleij
  0 siblings, 0 replies; 700+ messages in thread
From: Linus Walleij @ 2013-12-12 19:58 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Dec 10, 2013 at 1:47 PM, Sergei Ianovich <ynvich@gmail.com> wrote:
> On Tue, 2013-12-10 at 13:43 +0100, Linus Walleij wrote:
>> Argh! Now you're adding another user for a legacy custom pin control
>> implementation. But if noone is going to modernize PXA2xx what
>> can we do :-/
>
> I've rewritten the device to use device tree and posted patch series for
> that.

THANKS! For doing this.

Yours,
Linus Walleij

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

* Re: [PATCH v2 02/11] arm: pxa27x: support ICP DAS LP-8x4x
  2013-12-10 12:54         ` Vasily Khoruzhick
@ 2013-12-12 20:07           ` Linus Walleij
  -1 siblings, 0 replies; 700+ messages in thread
From: Linus Walleij @ 2013-12-12 20:07 UTC (permalink / raw)
  To: Vasily Khoruzhick
  Cc: Sergei Ianovich, Russell King, Arnd Bergmann, linux-kernel,
	Haojian Zhuang, Haojian Zhuang, Eric Miao, linux-arm-kernel,
	Bjorn Andersson

On Tue, Dec 10, 2013 at 1:54 PM, Vasily Khoruzhick <anarsoul@gmail.com> wrote:
> On Tue, Dec 10, 2013 at 3:43 PM, Linus Walleij <linus.walleij@linaro.org> wrote:

>> Argh! Now you're adding another user for a legacy custom pin control
>> implementation. But if noone is going to modernize PXA2xx what
>> can we do :-/
>
> I tried a ~year ago, but it's not so trivial. PXA2xx has no separate
> pin control module, it's
> highly integrated into GPIO controller. I've asked the maillist what
> should I do for that case, but AFAIR no one answered.

It is very common for pin controllers and GPIO blocks to
be integrated.

The usual solution is to make a combined driver that registers
both pinctrl and GPIO interfaces and put that into
drivers/pinctrl.

Here is a recent example that can be used as inspiration:
http://marc.info/?l=linux-doc&m=138629591206248&w=2

Yours,
Linus Walleij

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

* [PATCH v2 02/11] arm: pxa27x: support ICP DAS LP-8x4x
@ 2013-12-12 20:07           ` Linus Walleij
  0 siblings, 0 replies; 700+ messages in thread
From: Linus Walleij @ 2013-12-12 20:07 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Dec 10, 2013 at 1:54 PM, Vasily Khoruzhick <anarsoul@gmail.com> wrote:
> On Tue, Dec 10, 2013 at 3:43 PM, Linus Walleij <linus.walleij@linaro.org> wrote:

>> Argh! Now you're adding another user for a legacy custom pin control
>> implementation. But if noone is going to modernize PXA2xx what
>> can we do :-/
>
> I tried a ~year ago, but it's not so trivial. PXA2xx has no separate
> pin control module, it's
> highly integrated into GPIO controller. I've asked the maillist what
> should I do for that case, but AFAIR no one answered.

It is very common for pin controllers and GPIO blocks to
be integrated.

The usual solution is to make a combined driver that registers
both pinctrl and GPIO interfaces and put that into
drivers/pinctrl.

Here is a recent example that can be used as inspiration:
http://marc.info/?l=linux-doc&m=138629591206248&w=2

Yours,
Linus Walleij

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

* [PATCH v2 00/16] ARM: support for ICP DAS LP-8x4x (with dts)
  2013-12-08 22:53       ` Sergei Ianovich
@ 2013-12-13  2:27         ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-13  2:27 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Daniel Mack, Arnd Bergmann, Haojian Zhuang

Fixed most review requirements. Details in respective patches.

I've completely met the requirement for using dmaengine-based DMA
in patch v2-03/16. Tests showed new DMA was underperforming. It added
on top of a pre-existing problem with MMC bus width and made the system
barely usable. However, the new code in this patch work correctly with
both the existing and the new DMA. Even if the new DMA is compiled into
the kernel, the exisitng DMA initializes first.

I've also decided not to create a single mfd device for
machine-specific devices. Instead each type is supported by a separate
driver in respective subsystem. It was tempting to hardcode all the
constants in one source file, but that requires ugly initialization.
The taken way produces much cleaner code.

Sergei Ianovich (16):
  ARM: dts: pxa2xx fix compatible strings
  ARM: dts: fix pxa27x-gpio interrupts
  ARM: dts: provide DMA config to pxamci
  ARM: dts: pxa3xx: move declaration to header
  ARM: dts: pxa27x: irq init using device tree
  ARM: pxa27x: device tree support ICP DAS LP-8x4x
  rtc: support DS1302 RTC on ICP DAS LP-8x4x
  mtd: support BB SRAM on ICP DAS LP-8x4x
  ARM: pxa: support ICP DAS LP-8x4x FPGA irq
  serial: support for 16550A serial ports on LP-8x4x
  misc: support for LP-8x4x custom parallel bus
  misc: support for serial slots in LP-8x4x
  misc: support for parallel slots in LP-8x4x
  misc: support for I-8041 in LP-8x4x
  misc: support for I-8042 in LP-8x4x
  misc: support for I-8024 in LP-8x4x

 .../bindings/interrupt-controller/irq-lp8x4x.txt   |  49 ++
 .../devicetree/bindings/misc/lp8x4x-bus.txt        |  18 +
 Documentation/devicetree/bindings/mmc/pxa-mmc.txt  |   5 +
 .../devicetree/bindings/rtc/rtc-ds1302.txt         |  14 +
 .../devicetree/bindings/serial/lp8x4x-serial.txt   |  35 ++
 Documentation/misc-devices/lp8x4x_bus.txt          |  74 +++
 arch/arm/boot/dts/Makefile                         |   1 +
 arch/arm/boot/dts/pxa27x-lp8x4x.dts                | 165 ++++++
 arch/arm/boot/dts/pxa27x.dtsi                      |  20 +
 arch/arm/boot/dts/pxa2xx.dtsi                      |   5 +-
 arch/arm/configs/lp8x4x_defconfig                  | 164 ++++++
 arch/arm/mach-pxa/Kconfig                          |  15 +
 arch/arm/mach-pxa/Makefile                         |   1 +
 arch/arm/mach-pxa/include/mach/irqs.h              |   2 +
 arch/arm/mach-pxa/include/mach/pxa27x.h            |   1 +
 arch/arm/mach-pxa/pxa27x-dt.c                      |  64 +++
 arch/arm/mach-pxa/pxa27x.c                         |  10 +
 arch/arm/mach-pxa/pxa3xx.c                         |   2 -
 drivers/irqchip/Kconfig                            |   5 +
 drivers/irqchip/Makefile                           |   1 +
 drivers/irqchip/irq-lp8x4x.c                       | 238 +++++++++
 drivers/misc/Kconfig                               |  13 +
 drivers/misc/Makefile                              |   1 +
 drivers/misc/lp8x4x_bus.c                          | 570 +++++++++++++++++++++
 drivers/mmc/host/pxamci.c                          |  59 ++-
 drivers/mtd/devices/Kconfig                        |  14 +
 drivers/mtd/devices/Makefile                       |   1 +
 drivers/mtd/devices/sram_lp8x4x.c                  | 227 ++++++++
 drivers/rtc/Kconfig                                |   2 +-
 drivers/rtc/rtc-ds1302.c                           | 111 +++-
 drivers/tty/serial/8250/8250_lp8x4x.c              | 161 ++++++
 drivers/tty/serial/8250/Kconfig                    |  12 +
 drivers/tty/serial/8250/Makefile                   |   1 +
 33 files changed, 2042 insertions(+), 19 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/interrupt-controller/irq-lp8x4x.txt
 create mode 100644 Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
 create mode 100644 Documentation/devicetree/bindings/rtc/rtc-ds1302.txt
 create mode 100644 Documentation/devicetree/bindings/serial/lp8x4x-serial.txt
 create mode 100644 Documentation/misc-devices/lp8x4x_bus.txt
 create mode 100644 arch/arm/boot/dts/pxa27x-lp8x4x.dts
 create mode 100644 arch/arm/configs/lp8x4x_defconfig
 create mode 100644 arch/arm/mach-pxa/pxa27x-dt.c
 create mode 100644 drivers/irqchip/irq-lp8x4x.c
 create mode 100644 drivers/misc/lp8x4x_bus.c
 create mode 100644 drivers/mtd/devices/sram_lp8x4x.c
 create mode 100644 drivers/tty/serial/8250/8250_lp8x4x.c

-- 
1.8.4.3


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

* [PATCH v2 00/16] ARM: support for ICP DAS LP-8x4x (with dts)
@ 2013-12-13  2:27         ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-13  2:27 UTC (permalink / raw)
  To: linux-arm-kernel

Fixed most review requirements. Details in respective patches.

I've completely met the requirement for using dmaengine-based DMA
in patch v2-03/16. Tests showed new DMA was underperforming. It added
on top of a pre-existing problem with MMC bus width and made the system
barely usable. However, the new code in this patch work correctly with
both the existing and the new DMA. Even if the new DMA is compiled into
the kernel, the exisitng DMA initializes first.

I've also decided not to create a single mfd device for
machine-specific devices. Instead each type is supported by a separate
driver in respective subsystem. It was tempting to hardcode all the
constants in one source file, but that requires ugly initialization.
The taken way produces much cleaner code.

Sergei Ianovich (16):
  ARM: dts: pxa2xx fix compatible strings
  ARM: dts: fix pxa27x-gpio interrupts
  ARM: dts: provide DMA config to pxamci
  ARM: dts: pxa3xx: move declaration to header
  ARM: dts: pxa27x: irq init using device tree
  ARM: pxa27x: device tree support ICP DAS LP-8x4x
  rtc: support DS1302 RTC on ICP DAS LP-8x4x
  mtd: support BB SRAM on ICP DAS LP-8x4x
  ARM: pxa: support ICP DAS LP-8x4x FPGA irq
  serial: support for 16550A serial ports on LP-8x4x
  misc: support for LP-8x4x custom parallel bus
  misc: support for serial slots in LP-8x4x
  misc: support for parallel slots in LP-8x4x
  misc: support for I-8041 in LP-8x4x
  misc: support for I-8042 in LP-8x4x
  misc: support for I-8024 in LP-8x4x

 .../bindings/interrupt-controller/irq-lp8x4x.txt   |  49 ++
 .../devicetree/bindings/misc/lp8x4x-bus.txt        |  18 +
 Documentation/devicetree/bindings/mmc/pxa-mmc.txt  |   5 +
 .../devicetree/bindings/rtc/rtc-ds1302.txt         |  14 +
 .../devicetree/bindings/serial/lp8x4x-serial.txt   |  35 ++
 Documentation/misc-devices/lp8x4x_bus.txt          |  74 +++
 arch/arm/boot/dts/Makefile                         |   1 +
 arch/arm/boot/dts/pxa27x-lp8x4x.dts                | 165 ++++++
 arch/arm/boot/dts/pxa27x.dtsi                      |  20 +
 arch/arm/boot/dts/pxa2xx.dtsi                      |   5 +-
 arch/arm/configs/lp8x4x_defconfig                  | 164 ++++++
 arch/arm/mach-pxa/Kconfig                          |  15 +
 arch/arm/mach-pxa/Makefile                         |   1 +
 arch/arm/mach-pxa/include/mach/irqs.h              |   2 +
 arch/arm/mach-pxa/include/mach/pxa27x.h            |   1 +
 arch/arm/mach-pxa/pxa27x-dt.c                      |  64 +++
 arch/arm/mach-pxa/pxa27x.c                         |  10 +
 arch/arm/mach-pxa/pxa3xx.c                         |   2 -
 drivers/irqchip/Kconfig                            |   5 +
 drivers/irqchip/Makefile                           |   1 +
 drivers/irqchip/irq-lp8x4x.c                       | 238 +++++++++
 drivers/misc/Kconfig                               |  13 +
 drivers/misc/Makefile                              |   1 +
 drivers/misc/lp8x4x_bus.c                          | 570 +++++++++++++++++++++
 drivers/mmc/host/pxamci.c                          |  59 ++-
 drivers/mtd/devices/Kconfig                        |  14 +
 drivers/mtd/devices/Makefile                       |   1 +
 drivers/mtd/devices/sram_lp8x4x.c                  | 227 ++++++++
 drivers/rtc/Kconfig                                |   2 +-
 drivers/rtc/rtc-ds1302.c                           | 111 +++-
 drivers/tty/serial/8250/8250_lp8x4x.c              | 161 ++++++
 drivers/tty/serial/8250/Kconfig                    |  12 +
 drivers/tty/serial/8250/Makefile                   |   1 +
 33 files changed, 2042 insertions(+), 19 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/interrupt-controller/irq-lp8x4x.txt
 create mode 100644 Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
 create mode 100644 Documentation/devicetree/bindings/rtc/rtc-ds1302.txt
 create mode 100644 Documentation/devicetree/bindings/serial/lp8x4x-serial.txt
 create mode 100644 Documentation/misc-devices/lp8x4x_bus.txt
 create mode 100644 arch/arm/boot/dts/pxa27x-lp8x4x.dts
 create mode 100644 arch/arm/configs/lp8x4x_defconfig
 create mode 100644 arch/arm/mach-pxa/pxa27x-dt.c
 create mode 100644 drivers/irqchip/irq-lp8x4x.c
 create mode 100644 drivers/misc/lp8x4x_bus.c
 create mode 100644 drivers/mtd/devices/sram_lp8x4x.c
 create mode 100644 drivers/tty/serial/8250/8250_lp8x4x.c

-- 
1.8.4.3

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

* [PATCH v2 01/16] ARM: dts: pxa2xx fix compatible strings
  2013-12-13  2:27         ` Sergei Ianovich
  (?)
@ 2013-12-13  2:27           ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-13  2:27 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Daniel Mack, Arnd Bergmann, Rob Herring,
	Pawel Moll, Mark Rutland, Stephen Warren, Ian Campbell,
	Russell King, open list:OPEN FIRMWARE AND...

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Daniel Mack <zonque@gmail.com>
CC: Arnd Bergmann <arnd@arndb.de>
---
   v1..v2
   * no changes

 arch/arm/boot/dts/pxa2xx.dtsi | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/arch/arm/boot/dts/pxa2xx.dtsi b/arch/arm/boot/dts/pxa2xx.dtsi
index a5e90f0..3419f87 100644
--- a/arch/arm/boot/dts/pxa2xx.dtsi
+++ b/arch/arm/boot/dts/pxa2xx.dtsi
@@ -18,7 +18,6 @@
 		serial1 = &btuart;
 		serial2 = &stuart;
 		serial3 = &hwuart;
-		i2c0 = &pwri2c;
 		i2c1 = &pxai2c1;
 	};
 
@@ -113,14 +112,14 @@
 		};
 
 		usb0: ohci@4c000000 {
-			compatible = "mrvl,pxa-ohci";
+			compatible = "marvell,pxa-ohci";
 			reg = <0x4c000000 0x10000>;
 			interrupts = <3>;
 			status = "disabled";
 		};
 
 		mmc0: mmc@41100000 {
-			compatible = "mrvl,pxa-mmc";
+			compatible = "marvell,pxa-mmc";
 			reg = <0x41100000 0x1000>;
 			interrupts = <23>;
 			status = "disabled";
-- 
1.8.4.3


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

* [PATCH v2 01/16] ARM: dts: pxa2xx fix compatible strings
@ 2013-12-13  2:27           ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-13  2:27 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Daniel Mack, Arnd Bergmann, Rob Herring,
	Pawel Moll, Mark Rutland, Stephen Warren, Ian Campbell,
	Russell King, open list:OPEN FIRMWARE AND...

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Daniel Mack <zonque@gmail.com>
CC: Arnd Bergmann <arnd@arndb.de>
---
   v1..v2
   * no changes

 arch/arm/boot/dts/pxa2xx.dtsi | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/arch/arm/boot/dts/pxa2xx.dtsi b/arch/arm/boot/dts/pxa2xx.dtsi
index a5e90f0..3419f87 100644
--- a/arch/arm/boot/dts/pxa2xx.dtsi
+++ b/arch/arm/boot/dts/pxa2xx.dtsi
@@ -18,7 +18,6 @@
 		serial1 = &btuart;
 		serial2 = &stuart;
 		serial3 = &hwuart;
-		i2c0 = &pwri2c;
 		i2c1 = &pxai2c1;
 	};
 
@@ -113,14 +112,14 @@
 		};
 
 		usb0: ohci@4c000000 {
-			compatible = "mrvl,pxa-ohci";
+			compatible = "marvell,pxa-ohci";
 			reg = <0x4c000000 0x10000>;
 			interrupts = <3>;
 			status = "disabled";
 		};
 
 		mmc0: mmc@41100000 {
-			compatible = "mrvl,pxa-mmc";
+			compatible = "marvell,pxa-mmc";
 			reg = <0x41100000 0x1000>;
 			interrupts = <23>;
 			status = "disabled";
-- 
1.8.4.3

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

* [PATCH v2 01/16] ARM: dts: pxa2xx fix compatible strings
@ 2013-12-13  2:27           ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-13  2:27 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Daniel Mack <zonque@gmail.com>
CC: Arnd Bergmann <arnd@arndb.de>
---
   v1..v2
   * no changes

 arch/arm/boot/dts/pxa2xx.dtsi | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/arch/arm/boot/dts/pxa2xx.dtsi b/arch/arm/boot/dts/pxa2xx.dtsi
index a5e90f0..3419f87 100644
--- a/arch/arm/boot/dts/pxa2xx.dtsi
+++ b/arch/arm/boot/dts/pxa2xx.dtsi
@@ -18,7 +18,6 @@
 		serial1 = &btuart;
 		serial2 = &stuart;
 		serial3 = &hwuart;
-		i2c0 = &pwri2c;
 		i2c1 = &pxai2c1;
 	};
 
@@ -113,14 +112,14 @@
 		};
 
 		usb0: ohci at 4c000000 {
-			compatible = "mrvl,pxa-ohci";
+			compatible = "marvell,pxa-ohci";
 			reg = <0x4c000000 0x10000>;
 			interrupts = <3>;
 			status = "disabled";
 		};
 
 		mmc0: mmc at 41100000 {
-			compatible = "mrvl,pxa-mmc";
+			compatible = "marvell,pxa-mmc";
 			reg = <0x41100000 0x1000>;
 			interrupts = <23>;
 			status = "disabled";
-- 
1.8.4.3

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

* [PATCH v2 02/16] ARM: dts: fix pxa27x-gpio interrupts
  2013-12-13  2:27         ` Sergei Ianovich
  (?)
@ 2013-12-13  2:27           ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-13  2:27 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Daniel Mack, Arnd Bergmann, Rob Herring,
	Pawel Moll, Mark Rutland, Stephen Warren, Ian Campbell,
	Russell King, open list:OPEN FIRMWARE AND...

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Daniel Mack <zonque@gmail.com>
CC: Arnd Bergmann <arnd@arndb.de>
---
   v1..v2
   * no changes

 arch/arm/boot/dts/pxa27x.dtsi | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/arch/arm/boot/dts/pxa27x.dtsi b/arch/arm/boot/dts/pxa27x.dtsi
index d7c5d72..44df554 100644
--- a/arch/arm/boot/dts/pxa27x.dtsi
+++ b/arch/arm/boot/dts/pxa27x.dtsi
@@ -10,5 +10,11 @@
 			marvell,intc-priority;
 			marvell,intc-nr-irqs = <34>;
 		};
+
+		gpio: gpio@40e00000 {
+			compatible = "intel,pxa27x-gpio";
+			interrupts = <8>, <9>, <10>;
+			interrupt-names = "gpio0", "gpio1", "gpio_mux";
+		};
 	};
 };
-- 
1.8.4.3


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

* [PATCH v2 02/16] ARM: dts: fix pxa27x-gpio interrupts
@ 2013-12-13  2:27           ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-13  2:27 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Daniel Mack, Arnd Bergmann, Rob Herring,
	Pawel Moll, Mark Rutland, Stephen Warren, Ian Campbell,
	Russell King, open list:OPEN FIRMWARE AND...

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Daniel Mack <zonque@gmail.com>
CC: Arnd Bergmann <arnd@arndb.de>
---
   v1..v2
   * no changes

 arch/arm/boot/dts/pxa27x.dtsi | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/arch/arm/boot/dts/pxa27x.dtsi b/arch/arm/boot/dts/pxa27x.dtsi
index d7c5d72..44df554 100644
--- a/arch/arm/boot/dts/pxa27x.dtsi
+++ b/arch/arm/boot/dts/pxa27x.dtsi
@@ -10,5 +10,11 @@
 			marvell,intc-priority;
 			marvell,intc-nr-irqs = <34>;
 		};
+
+		gpio: gpio@40e00000 {
+			compatible = "intel,pxa27x-gpio";
+			interrupts = <8>, <9>, <10>;
+			interrupt-names = "gpio0", "gpio1", "gpio_mux";
+		};
 	};
 };
-- 
1.8.4.3

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

* [PATCH v2 02/16] ARM: dts: fix pxa27x-gpio interrupts
@ 2013-12-13  2:27           ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-13  2:27 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Daniel Mack <zonque@gmail.com>
CC: Arnd Bergmann <arnd@arndb.de>
---
   v1..v2
   * no changes

 arch/arm/boot/dts/pxa27x.dtsi | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/arch/arm/boot/dts/pxa27x.dtsi b/arch/arm/boot/dts/pxa27x.dtsi
index d7c5d72..44df554 100644
--- a/arch/arm/boot/dts/pxa27x.dtsi
+++ b/arch/arm/boot/dts/pxa27x.dtsi
@@ -10,5 +10,11 @@
 			marvell,intc-priority;
 			marvell,intc-nr-irqs = <34>;
 		};
+
+		gpio: gpio at 40e00000 {
+			compatible = "intel,pxa27x-gpio";
+			interrupts = <8>, <9>, <10>;
+			interrupt-names = "gpio0", "gpio1", "gpio_mux";
+		};
 	};
 };
-- 
1.8.4.3

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

* [PATCH v2 03/16] ARM: dts: provide DMA config to pxamci
  2013-12-13  2:27         ` Sergei Ianovich
  (?)
@ 2013-12-13  2:27           ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-13  2:27 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Daniel Mack, Arnd Bergmann, Rob Herring,
	Pawel Moll, Mark Rutland, Stephen Warren, Ian Campbell,
	Rob Landley, Russell King, Chris Ball, Viresh Kumar, Shawn Guo,
	Haojian Zhuang, open list:OPEN FIRMWARE AND...,
	open list:DOCUMENTATION, linux-mmc

Non-dts implementation supply required DMA channel numbers as
IORESOURCE_DMA. However, there is was no way to get them from
device tree.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Daniel Mack <zonque@gmail.com>
CC: Arnd Bergmann <arnd@arndb.de>
---
   v1..v2
   * add binding for next-gen dma controller
   * use correct dma declararion
   * number changed from 5 to 3

 Documentation/devicetree/bindings/mmc/pxa-mmc.txt |  5 ++
 arch/arm/boot/dts/pxa27x.dtsi                     | 14 ++++++
 drivers/mmc/host/pxamci.c                         | 59 ++++++++++++++++++-----
 3 files changed, 67 insertions(+), 11 deletions(-)

diff --git a/Documentation/devicetree/bindings/mmc/pxa-mmc.txt b/Documentation/devicetree/bindings/mmc/pxa-mmc.txt
index b7025de..9f54c69 100644
--- a/Documentation/devicetree/bindings/mmc/pxa-mmc.txt
+++ b/Documentation/devicetree/bindings/mmc/pxa-mmc.txt
@@ -5,6 +5,8 @@ Driver bindings for the PXA MCI (MMC/SDIO) interfaces
 Required properties:
 - compatible: Should be "marvell,pxa-mmc".
 - vmmc-supply: A regulator for VMMC
+- dmas: Should be DMA specifiers for RX and TX
+- dma-names: Should be "rx" and "tx"
 
 Optional properties:
 - marvell,detect-delay-ms: sets the detection delay timeout in ms.
@@ -21,5 +23,8 @@ mmc0: mmc@41100000 {
 	interrupts = <23>;
 	cd-gpios = <&gpio 23 0>;
 	wp-gpios = <&gpio 24 0>;
+	dmas = <&dma 21
+		&dma 22>;
+	dma-names = "rx", "tx";
 };
 
diff --git a/arch/arm/boot/dts/pxa27x.dtsi b/arch/arm/boot/dts/pxa27x.dtsi
index 44df554..c2a90c5 100644
--- a/arch/arm/boot/dts/pxa27x.dtsi
+++ b/arch/arm/boot/dts/pxa27x.dtsi
@@ -11,10 +11,24 @@
 			marvell,intc-nr-irqs = <34>;
 		};
 
+		dma: dma-controller@40000000 {
+			compatible = "marvell,pdma-1.0";
+			reg = <0x40000000 0x10000>;
+			interrupts = <25>;
+			#dma-cells = <1>;
+			dma-channels = <32>;
+		};
+
 		gpio: gpio@40e00000 {
 			compatible = "intel,pxa27x-gpio";
 			interrupts = <8>, <9>, <10>;
 			interrupt-names = "gpio0", "gpio1", "gpio_mux";
 		};
+
+		mmc@41100000 {
+			dmas = <&dma 21
+				&dma 22>;
+			dma-names = "rx", "tx";
+		};
 	};
 };
diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c
index 32fe113..6b67764 100644
--- a/drivers/mmc/host/pxamci.c
+++ b/drivers/mmc/host/pxamci.c
@@ -613,11 +613,46 @@ static int pxamci_of_init(struct platform_device *pdev)
 
         return 0;
 }
+
+static int pxamci_of_init_dma(struct platform_device *pdev,
+		struct pxamci_host *host)
+{
+	struct device_node *np = pdev->dev.of_node;
+	u32 tmp;
+	int i;
+	int ret;
+
+	i = of_property_match_string(np, "dma-names", "rx");
+	if (i < 0)
+		return i;
+
+	ret = of_property_read_u32_index(np, "dmas", 2 * i + 1, &tmp);
+	if (ret < 0)
+		return ret;
+	host->dma_drcmrrx = tmp;
+
+	i = of_property_match_string(np, "dma-names", "tx");
+	if (i < 0)
+		return i;
+
+	ret = of_property_read_u32_index(np, "dmas", 2 * i + 1, &tmp);
+	if (ret < 0)
+		return ret;
+	host->dma_drcmrtx = tmp;
+
+	return 0;
+}
 #else
 static int pxamci_of_init(struct platform_device *pdev)
 {
         return 0;
 }
+
+static int pxamci_of_init_dma(struct platform_device *pdev,
+		struct pxamci_host *host)
+{
+	return -ENODATA;
+}
 #endif
 
 static int pxamci_probe(struct platform_device *pdev)
@@ -741,19 +776,21 @@ static int pxamci_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, mmc);
 
-	dmarx = platform_get_resource(pdev, IORESOURCE_DMA, 0);
-	if (!dmarx) {
-		ret = -ENXIO;
-		goto out;
-	}
-	host->dma_drcmrrx = dmarx->start;
+	if (pxamci_of_init_dma(pdev, host) < 0) {
+		dmarx = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+		if (!dmarx) {
+			ret = -ENXIO;
+			goto out;
+		}
+		host->dma_drcmrrx = dmarx->start;
 
-	dmatx = platform_get_resource(pdev, IORESOURCE_DMA, 1);
-	if (!dmatx) {
-		ret = -ENXIO;
-		goto out;
+		dmatx = platform_get_resource(pdev, IORESOURCE_DMA, 1);
+		if (!dmatx) {
+			ret = -ENXIO;
+			goto out;
+		}
+		host->dma_drcmrtx = dmatx->start;
 	}
-	host->dma_drcmrtx = dmatx->start;
 
 	if (host->pdata) {
 		gpio_cd = host->pdata->gpio_card_detect;
-- 
1.8.4.3


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

* [PATCH v2 03/16] ARM: dts: provide DMA config to pxamci
@ 2013-12-13  2:27           ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-13  2:27 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Daniel Mack, Arnd Bergmann, Rob Herring,
	Pawel Moll, Mark Rutland, Stephen Warren, Ian Campbell,
	Rob Landley, Russell King, Chris Ball, Viresh Kumar, Shawn Guo,
	Haojian Zhuang, open list:OPEN FIRMWARE AND...,
	open list:DOCUMENTATION, linux-mmc

Non-dts implementation supply required DMA channel numbers as
IORESOURCE_DMA. However, there is was no way to get them from
device tree.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Daniel Mack <zonque@gmail.com>
CC: Arnd Bergmann <arnd@arndb.de>
---
   v1..v2
   * add binding for next-gen dma controller
   * use correct dma declararion
   * number changed from 5 to 3

 Documentation/devicetree/bindings/mmc/pxa-mmc.txt |  5 ++
 arch/arm/boot/dts/pxa27x.dtsi                     | 14 ++++++
 drivers/mmc/host/pxamci.c                         | 59 ++++++++++++++++++-----
 3 files changed, 67 insertions(+), 11 deletions(-)

diff --git a/Documentation/devicetree/bindings/mmc/pxa-mmc.txt b/Documentation/devicetree/bindings/mmc/pxa-mmc.txt
index b7025de..9f54c69 100644
--- a/Documentation/devicetree/bindings/mmc/pxa-mmc.txt
+++ b/Documentation/devicetree/bindings/mmc/pxa-mmc.txt
@@ -5,6 +5,8 @@ Driver bindings for the PXA MCI (MMC/SDIO) interfaces
 Required properties:
 - compatible: Should be "marvell,pxa-mmc".
 - vmmc-supply: A regulator for VMMC
+- dmas: Should be DMA specifiers for RX and TX
+- dma-names: Should be "rx" and "tx"
 
 Optional properties:
 - marvell,detect-delay-ms: sets the detection delay timeout in ms.
@@ -21,5 +23,8 @@ mmc0: mmc@41100000 {
 	interrupts = <23>;
 	cd-gpios = <&gpio 23 0>;
 	wp-gpios = <&gpio 24 0>;
+	dmas = <&dma 21
+		&dma 22>;
+	dma-names = "rx", "tx";
 };
 
diff --git a/arch/arm/boot/dts/pxa27x.dtsi b/arch/arm/boot/dts/pxa27x.dtsi
index 44df554..c2a90c5 100644
--- a/arch/arm/boot/dts/pxa27x.dtsi
+++ b/arch/arm/boot/dts/pxa27x.dtsi
@@ -11,10 +11,24 @@
 			marvell,intc-nr-irqs = <34>;
 		};
 
+		dma: dma-controller@40000000 {
+			compatible = "marvell,pdma-1.0";
+			reg = <0x40000000 0x10000>;
+			interrupts = <25>;
+			#dma-cells = <1>;
+			dma-channels = <32>;
+		};
+
 		gpio: gpio@40e00000 {
 			compatible = "intel,pxa27x-gpio";
 			interrupts = <8>, <9>, <10>;
 			interrupt-names = "gpio0", "gpio1", "gpio_mux";
 		};
+
+		mmc@41100000 {
+			dmas = <&dma 21
+				&dma 22>;
+			dma-names = "rx", "tx";
+		};
 	};
 };
diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c
index 32fe113..6b67764 100644
--- a/drivers/mmc/host/pxamci.c
+++ b/drivers/mmc/host/pxamci.c
@@ -613,11 +613,46 @@ static int pxamci_of_init(struct platform_device *pdev)
 
         return 0;
 }
+
+static int pxamci_of_init_dma(struct platform_device *pdev,
+		struct pxamci_host *host)
+{
+	struct device_node *np = pdev->dev.of_node;
+	u32 tmp;
+	int i;
+	int ret;
+
+	i = of_property_match_string(np, "dma-names", "rx");
+	if (i < 0)
+		return i;
+
+	ret = of_property_read_u32_index(np, "dmas", 2 * i + 1, &tmp);
+	if (ret < 0)
+		return ret;
+	host->dma_drcmrrx = tmp;
+
+	i = of_property_match_string(np, "dma-names", "tx");
+	if (i < 0)
+		return i;
+
+	ret = of_property_read_u32_index(np, "dmas", 2 * i + 1, &tmp);
+	if (ret < 0)
+		return ret;
+	host->dma_drcmrtx = tmp;
+
+	return 0;
+}
 #else
 static int pxamci_of_init(struct platform_device *pdev)
 {
         return 0;
 }
+
+static int pxamci_of_init_dma(struct platform_device *pdev,
+		struct pxamci_host *host)
+{
+	return -ENODATA;
+}
 #endif
 
 static int pxamci_probe(struct platform_device *pdev)
@@ -741,19 +776,21 @@ static int pxamci_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, mmc);
 
-	dmarx = platform_get_resource(pdev, IORESOURCE_DMA, 0);
-	if (!dmarx) {
-		ret = -ENXIO;
-		goto out;
-	}
-	host->dma_drcmrrx = dmarx->start;
+	if (pxamci_of_init_dma(pdev, host) < 0) {
+		dmarx = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+		if (!dmarx) {
+			ret = -ENXIO;
+			goto out;
+		}
+		host->dma_drcmrrx = dmarx->start;
 
-	dmatx = platform_get_resource(pdev, IORESOURCE_DMA, 1);
-	if (!dmatx) {
-		ret = -ENXIO;
-		goto out;
+		dmatx = platform_get_resource(pdev, IORESOURCE_DMA, 1);
+		if (!dmatx) {
+			ret = -ENXIO;
+			goto out;
+		}
+		host->dma_drcmrtx = dmatx->start;
 	}
-	host->dma_drcmrtx = dmatx->start;
 
 	if (host->pdata) {
 		gpio_cd = host->pdata->gpio_card_detect;
-- 
1.8.4.3


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

* [PATCH v2 03/16] ARM: dts: provide DMA config to pxamci
@ 2013-12-13  2:27           ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-13  2:27 UTC (permalink / raw)
  To: linux-arm-kernel

Non-dts implementation supply required DMA channel numbers as
IORESOURCE_DMA. However, there is was no way to get them from
device tree.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Daniel Mack <zonque@gmail.com>
CC: Arnd Bergmann <arnd@arndb.de>
---
   v1..v2
   * add binding for next-gen dma controller
   * use correct dma declararion
   * number changed from 5 to 3

 Documentation/devicetree/bindings/mmc/pxa-mmc.txt |  5 ++
 arch/arm/boot/dts/pxa27x.dtsi                     | 14 ++++++
 drivers/mmc/host/pxamci.c                         | 59 ++++++++++++++++++-----
 3 files changed, 67 insertions(+), 11 deletions(-)

diff --git a/Documentation/devicetree/bindings/mmc/pxa-mmc.txt b/Documentation/devicetree/bindings/mmc/pxa-mmc.txt
index b7025de..9f54c69 100644
--- a/Documentation/devicetree/bindings/mmc/pxa-mmc.txt
+++ b/Documentation/devicetree/bindings/mmc/pxa-mmc.txt
@@ -5,6 +5,8 @@ Driver bindings for the PXA MCI (MMC/SDIO) interfaces
 Required properties:
 - compatible: Should be "marvell,pxa-mmc".
 - vmmc-supply: A regulator for VMMC
+- dmas: Should be DMA specifiers for RX and TX
+- dma-names: Should be "rx" and "tx"
 
 Optional properties:
 - marvell,detect-delay-ms: sets the detection delay timeout in ms.
@@ -21,5 +23,8 @@ mmc0: mmc at 41100000 {
 	interrupts = <23>;
 	cd-gpios = <&gpio 23 0>;
 	wp-gpios = <&gpio 24 0>;
+	dmas = <&dma 21
+		&dma 22>;
+	dma-names = "rx", "tx";
 };
 
diff --git a/arch/arm/boot/dts/pxa27x.dtsi b/arch/arm/boot/dts/pxa27x.dtsi
index 44df554..c2a90c5 100644
--- a/arch/arm/boot/dts/pxa27x.dtsi
+++ b/arch/arm/boot/dts/pxa27x.dtsi
@@ -11,10 +11,24 @@
 			marvell,intc-nr-irqs = <34>;
 		};
 
+		dma: dma-controller at 40000000 {
+			compatible = "marvell,pdma-1.0";
+			reg = <0x40000000 0x10000>;
+			interrupts = <25>;
+			#dma-cells = <1>;
+			dma-channels = <32>;
+		};
+
 		gpio: gpio at 40e00000 {
 			compatible = "intel,pxa27x-gpio";
 			interrupts = <8>, <9>, <10>;
 			interrupt-names = "gpio0", "gpio1", "gpio_mux";
 		};
+
+		mmc at 41100000 {
+			dmas = <&dma 21
+				&dma 22>;
+			dma-names = "rx", "tx";
+		};
 	};
 };
diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c
index 32fe113..6b67764 100644
--- a/drivers/mmc/host/pxamci.c
+++ b/drivers/mmc/host/pxamci.c
@@ -613,11 +613,46 @@ static int pxamci_of_init(struct platform_device *pdev)
 
         return 0;
 }
+
+static int pxamci_of_init_dma(struct platform_device *pdev,
+		struct pxamci_host *host)
+{
+	struct device_node *np = pdev->dev.of_node;
+	u32 tmp;
+	int i;
+	int ret;
+
+	i = of_property_match_string(np, "dma-names", "rx");
+	if (i < 0)
+		return i;
+
+	ret = of_property_read_u32_index(np, "dmas", 2 * i + 1, &tmp);
+	if (ret < 0)
+		return ret;
+	host->dma_drcmrrx = tmp;
+
+	i = of_property_match_string(np, "dma-names", "tx");
+	if (i < 0)
+		return i;
+
+	ret = of_property_read_u32_index(np, "dmas", 2 * i + 1, &tmp);
+	if (ret < 0)
+		return ret;
+	host->dma_drcmrtx = tmp;
+
+	return 0;
+}
 #else
 static int pxamci_of_init(struct platform_device *pdev)
 {
         return 0;
 }
+
+static int pxamci_of_init_dma(struct platform_device *pdev,
+		struct pxamci_host *host)
+{
+	return -ENODATA;
+}
 #endif
 
 static int pxamci_probe(struct platform_device *pdev)
@@ -741,19 +776,21 @@ static int pxamci_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, mmc);
 
-	dmarx = platform_get_resource(pdev, IORESOURCE_DMA, 0);
-	if (!dmarx) {
-		ret = -ENXIO;
-		goto out;
-	}
-	host->dma_drcmrrx = dmarx->start;
+	if (pxamci_of_init_dma(pdev, host) < 0) {
+		dmarx = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+		if (!dmarx) {
+			ret = -ENXIO;
+			goto out;
+		}
+		host->dma_drcmrrx = dmarx->start;
 
-	dmatx = platform_get_resource(pdev, IORESOURCE_DMA, 1);
-	if (!dmatx) {
-		ret = -ENXIO;
-		goto out;
+		dmatx = platform_get_resource(pdev, IORESOURCE_DMA, 1);
+		if (!dmatx) {
+			ret = -ENXIO;
+			goto out;
+		}
+		host->dma_drcmrtx = dmatx->start;
 	}
-	host->dma_drcmrtx = dmatx->start;
 
 	if (host->pdata) {
 		gpio_cd = host->pdata->gpio_card_detect;
-- 
1.8.4.3

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

* [PATCH v2 04/16] ARM: dts: pxa3xx: move declaration to header
  2013-12-13  2:27         ` Sergei Ianovich
@ 2013-12-13  2:27           ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-13  2:27 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Daniel Mack, Arnd Bergmann, Eric Miao,
	Russell King, Haojian Zhuang

This way it will be more difficult to change the declaration in one
place, but not the other.

In addition, the change allows to use the binding for pxa-gpio on
other PXA CPUs.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Daniel Mack <zonque@gmail.com>
CC: Arnd Bergmann <arnd@arndb.de>
---
   v1..v2
   * drop #ifdef in header file
   * number changed from 6 to 4 (dropped patches)

 arch/arm/mach-pxa/include/mach/irqs.h | 2 ++
 arch/arm/mach-pxa/pxa3xx.c            | 2 --
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-pxa/include/mach/irqs.h b/arch/arm/mach-pxa/include/mach/irqs.h
index 48c2fd8..732315d 100644
--- a/arch/arm/mach-pxa/include/mach/irqs.h
+++ b/arch/arm/mach-pxa/include/mach/irqs.h
@@ -113,4 +113,6 @@ void ichp_handle_irq(struct pt_regs *);
 void pxa_init_irq(int irq_nr, int (*set_wake)(struct irq_data *, unsigned int));
 #endif
 
+extern void __init pxa_dt_irq_init(int (*fn)(struct irq_data *, unsigned int));
+
 #endif /* __ASM_MACH_IRQS_H */
diff --git a/arch/arm/mach-pxa/pxa3xx.c b/arch/arm/mach-pxa/pxa3xx.c
index 87011f3..2397dec 100644
--- a/arch/arm/mach-pxa/pxa3xx.c
+++ b/arch/arm/mach-pxa/pxa3xx.c
@@ -42,8 +42,6 @@
 #define PECR_IE(n)	((1 << ((n) * 2)) << 28)
 #define PECR_IS(n)	((1 << ((n) * 2)) << 29)
 
-extern void __init pxa_dt_irq_init(int (*fn)(struct irq_data *, unsigned int));
-
 static DEFINE_PXA3_CKEN(pxa3xx_ffuart, FFUART, 14857000, 1);
 static DEFINE_PXA3_CKEN(pxa3xx_btuart, BTUART, 14857000, 1);
 static DEFINE_PXA3_CKEN(pxa3xx_stuart, STUART, 14857000, 1);
-- 
1.8.4.3


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

* [PATCH v2 04/16] ARM: dts: pxa3xx: move declaration to header
@ 2013-12-13  2:27           ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-13  2:27 UTC (permalink / raw)
  To: linux-arm-kernel

This way it will be more difficult to change the declaration in one
place, but not the other.

In addition, the change allows to use the binding for pxa-gpio on
other PXA CPUs.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Daniel Mack <zonque@gmail.com>
CC: Arnd Bergmann <arnd@arndb.de>
---
   v1..v2
   * drop #ifdef in header file
   * number changed from 6 to 4 (dropped patches)

 arch/arm/mach-pxa/include/mach/irqs.h | 2 ++
 arch/arm/mach-pxa/pxa3xx.c            | 2 --
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-pxa/include/mach/irqs.h b/arch/arm/mach-pxa/include/mach/irqs.h
index 48c2fd8..732315d 100644
--- a/arch/arm/mach-pxa/include/mach/irqs.h
+++ b/arch/arm/mach-pxa/include/mach/irqs.h
@@ -113,4 +113,6 @@ void ichp_handle_irq(struct pt_regs *);
 void pxa_init_irq(int irq_nr, int (*set_wake)(struct irq_data *, unsigned int));
 #endif
 
+extern void __init pxa_dt_irq_init(int (*fn)(struct irq_data *, unsigned int));
+
 #endif /* __ASM_MACH_IRQS_H */
diff --git a/arch/arm/mach-pxa/pxa3xx.c b/arch/arm/mach-pxa/pxa3xx.c
index 87011f3..2397dec 100644
--- a/arch/arm/mach-pxa/pxa3xx.c
+++ b/arch/arm/mach-pxa/pxa3xx.c
@@ -42,8 +42,6 @@
 #define PECR_IE(n)	((1 << ((n) * 2)) << 28)
 #define PECR_IS(n)	((1 << ((n) * 2)) << 29)
 
-extern void __init pxa_dt_irq_init(int (*fn)(struct irq_data *, unsigned int));
-
 static DEFINE_PXA3_CKEN(pxa3xx_ffuart, FFUART, 14857000, 1);
 static DEFINE_PXA3_CKEN(pxa3xx_btuart, BTUART, 14857000, 1);
 static DEFINE_PXA3_CKEN(pxa3xx_stuart, STUART, 14857000, 1);
-- 
1.8.4.3

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

* [PATCH v2 05/16] ARM: dts: pxa27x: irq init using device tree
  2013-12-13  2:27         ` Sergei Ianovich
@ 2013-12-13  2:27           ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-13  2:27 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Daniel Mack, Arnd Bergmann, Eric Miao,
	Russell King, Haojian Zhuang

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Daniel Mack <zonque@gmail.com>
CC: Arnd Bergmann <arnd@arndb.de>
---
   v1..v2
   * use of_have_populated_dt() instead of a static variable
   * drop #ifdef in header file
   * number changed from 8 to 5 (dropped patches)

 arch/arm/mach-pxa/include/mach/pxa27x.h |  1 +
 arch/arm/mach-pxa/pxa27x.c              | 10 ++++++++++
 2 files changed, 11 insertions(+)

diff --git a/arch/arm/mach-pxa/include/mach/pxa27x.h b/arch/arm/mach-pxa/include/mach/pxa27x.h
index 7cff640..34a4d6f 100644
--- a/arch/arm/mach-pxa/include/mach/pxa27x.h
+++ b/arch/arm/mach-pxa/include/mach/pxa27x.h
@@ -23,6 +23,7 @@ extern void __init pxa27x_map_io(void);
 extern void __init pxa27x_init_irq(void);
 extern int __init pxa27x_set_pwrmode(unsigned int mode);
 extern void pxa27x_cpu_pm_enter(suspend_state_t state);
+extern void __init pxa27x_dt_init_irq(void);
 
 #define pxa27x_handle_irq	ichp_handle_irq
 
diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c
index 301471a..c6b54f8 100644
--- a/arch/arm/mach-pxa/pxa27x.c
+++ b/arch/arm/mach-pxa/pxa27x.c
@@ -398,6 +398,13 @@ void __init pxa27x_init_irq(void)
 	pxa_init_irq(34, pxa27x_set_wake);
 }
 
+#ifdef CONFIG_OF
+void __init pxa27x_dt_init_irq(void)
+{
+	pxa_dt_irq_init(pxa27x_set_wake);
+}
+#endif  /* CONFIG_OF */
+
 static struct map_desc pxa27x_io_desc[] __initdata = {
 	{	/* Mem Ctl */
 		.virtual	= (unsigned long)SMEMC_VIRT,
@@ -471,6 +478,9 @@ static int __init pxa27x_init(void)
 		register_syscore_ops(&pxa2xx_mfp_syscore_ops);
 		register_syscore_ops(&pxa2xx_clock_syscore_ops);
 
+		if (of_have_populated_dt())
+			return 0;
+
 		pxa_register_device(&pxa27x_device_gpio, &pxa27x_gpio_info);
 		ret = platform_add_devices(devices, ARRAY_SIZE(devices));
 	}
-- 
1.8.4.3


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

* [PATCH v2 05/16] ARM: dts: pxa27x: irq init using device tree
@ 2013-12-13  2:27           ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-13  2:27 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Daniel Mack <zonque@gmail.com>
CC: Arnd Bergmann <arnd@arndb.de>
---
   v1..v2
   * use of_have_populated_dt() instead of a static variable
   * drop #ifdef in header file
   * number changed from 8 to 5 (dropped patches)

 arch/arm/mach-pxa/include/mach/pxa27x.h |  1 +
 arch/arm/mach-pxa/pxa27x.c              | 10 ++++++++++
 2 files changed, 11 insertions(+)

diff --git a/arch/arm/mach-pxa/include/mach/pxa27x.h b/arch/arm/mach-pxa/include/mach/pxa27x.h
index 7cff640..34a4d6f 100644
--- a/arch/arm/mach-pxa/include/mach/pxa27x.h
+++ b/arch/arm/mach-pxa/include/mach/pxa27x.h
@@ -23,6 +23,7 @@ extern void __init pxa27x_map_io(void);
 extern void __init pxa27x_init_irq(void);
 extern int __init pxa27x_set_pwrmode(unsigned int mode);
 extern void pxa27x_cpu_pm_enter(suspend_state_t state);
+extern void __init pxa27x_dt_init_irq(void);
 
 #define pxa27x_handle_irq	ichp_handle_irq
 
diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c
index 301471a..c6b54f8 100644
--- a/arch/arm/mach-pxa/pxa27x.c
+++ b/arch/arm/mach-pxa/pxa27x.c
@@ -398,6 +398,13 @@ void __init pxa27x_init_irq(void)
 	pxa_init_irq(34, pxa27x_set_wake);
 }
 
+#ifdef CONFIG_OF
+void __init pxa27x_dt_init_irq(void)
+{
+	pxa_dt_irq_init(pxa27x_set_wake);
+}
+#endif  /* CONFIG_OF */
+
 static struct map_desc pxa27x_io_desc[] __initdata = {
 	{	/* Mem Ctl */
 		.virtual	= (unsigned long)SMEMC_VIRT,
@@ -471,6 +478,9 @@ static int __init pxa27x_init(void)
 		register_syscore_ops(&pxa2xx_mfp_syscore_ops);
 		register_syscore_ops(&pxa2xx_clock_syscore_ops);
 
+		if (of_have_populated_dt())
+			return 0;
+
 		pxa_register_device(&pxa27x_device_gpio, &pxa27x_gpio_info);
 		ret = platform_add_devices(devices, ARRAY_SIZE(devices));
 	}
-- 
1.8.4.3

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

* [PATCH v2 06/16] ARM: pxa27x: device tree support ICP DAS LP-8x4x
  2013-12-13  2:27         ` Sergei Ianovich
  (?)
@ 2013-12-13  2:27           ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-13  2:27 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Daniel Mack, Arnd Bergmann, Linus Walleij,
	Rob Herring, Pawel Moll, Mark Rutland, Stephen Warren,
	Ian Campbell, Russell King, Eric Miao, Haojian Zhuang,
	open list:OPEN FIRMWARE AND...

ICP DAS calls LP-8x4x 'programmable automation controller'. It is
an industrial computer based on PXA270 SoC. They ship it with a 2.6.19
kernel and proprietary kernel module and userspace library to access
its industrial IO.

This patch allows to boot the device with a modern kernel with device
tree. It adds support for:
* MMC card interface on PXA270
* USB 1.1 port on PXA270
* 2 NOR flash devices
* 2 onboard ethernet Davicom DM9000 devices
* 3 serial UART ports on PXA270

Support for these devices will be added in separate patches, since
they are not currently supported by the kernel:
* DS1302 RTC
* 512kiB SRAM
* FPGA irq chip
* 3 built-in and up to 32 pluggable 8250 serial UART ports
* industrial IO parallel bus
* digital and analog industrial IO modules for parallel bus
* serial interface for digital and analog industrial IO modules on
  parallel bus

Not supported for now:
* VGA interface on PXA270 for lack of dts binding

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Daniel Mack <zonque@gmail.com>
CC: Arnd Bergmann <arnd@arndb.de>
CC: Linus Walleij <linus.walleij@linaro.org>
---
   v1..v2
   * drop left-over extern declaration
   * use of_have_populated_dt() instead of a static variable
   * drop wildcards in compatible
   * drop machine-special machine description
   * number changed from 9 to 6 (dropped patches)

 arch/arm/boot/dts/Makefile          |   1 +
 arch/arm/boot/dts/pxa27x-lp8x4x.dts | 111 +++++++++++++++++++++++++
 arch/arm/configs/lp8x4x_defconfig   | 160 ++++++++++++++++++++++++++++++++++++
 arch/arm/mach-pxa/Kconfig           |  15 ++++
 arch/arm/mach-pxa/Makefile          |   1 +
 arch/arm/mach-pxa/pxa27x-dt.c       |  64 +++++++++++++++
 6 files changed, 352 insertions(+)
 create mode 100644 arch/arm/boot/dts/pxa27x-lp8x4x.dts
 create mode 100644 arch/arm/configs/lp8x4x_defconfig
 create mode 100644 arch/arm/mach-pxa/pxa27x-dt.c

diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index d57c1a6..c4752ff 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -206,6 +206,7 @@ dtb-$(CONFIG_ARCH_OMAP2PLUS) += omap2420-h4.dtb \
 	dra7-evm.dtb
 dtb-$(CONFIG_ARCH_ORION5X) += orion5x-lacie-ethernet-disk-mini-v2.dtb
 dtb-$(CONFIG_ARCH_PRIMA2) += prima2-evb.dtb
+dtb-$(CONFIG_MACH_PXA27X_DT) += pxa27x-lp8x4x.dtb
 dtb-$(CONFIG_ARCH_U8500) += ste-snowball.dtb \
 	ste-hrefprev60-stuib.dtb \
 	ste-hrefprev60-tvk.dtb \
diff --git a/arch/arm/boot/dts/pxa27x-lp8x4x.dts b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
new file mode 100644
index 0000000..a2a9183
--- /dev/null
+++ b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
@@ -0,0 +1,111 @@
+/* Device tree for ICP DAS LP-8x4x */
+/dts-v1/;
+
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include "pxa27x.dtsi"
+
+/ {
+	model = "ICP DAS LP-8x4x programmable automation controller";
+	compatible = "marvell,lp8x4x", "marvell,pxa270";
+
+	memory {
+		reg = <0xa0000000 0x08000000>;
+	};
+
+	regulators {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		vmmc: regulator@0 {
+			compatible = "regulator-fixed";
+			reg = <0>;
+			regulator-name = "vmmc";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-always-on;
+		};
+	};
+
+	flash@00000000 {
+		compatible = "cfi-flash";
+		reg = <0x0 0x02000000>;
+		bank-width = <4>;
+		device-width = <2>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		fs@0 {
+			label = "u-boot";
+			reg = <0 0x40000>;
+		};
+		fs@40000 {
+			label = "settings";
+			reg = <0x40000 0x40000>;
+		};
+		fs@80000 {
+			label = "kernel";
+			reg = <0x80000 0x280000>;
+		};
+		fs@300000 {
+			label = "root_fs";
+			reg = <0x300000 0x1d00000>;
+		};
+	};
+
+	flash@04000000 {
+		compatible = "cfi-flash";
+		reg = <0x04000000 0x02000000>;
+		bank-width = <2>;
+		device-width = <1>;
+	};
+
+	pxabus {
+		pxairq: interrupt-controller@40d00000 {
+			marvell,intc-priority;
+			marvell,intc-nr-irqs = <34>;
+		};
+
+		uart@40100000 {
+			status = "okay";
+		};
+
+		uart@40200000 {
+			status = "okay";
+		};
+
+		uart@40700000 {
+			status = "okay";
+		};
+
+		mmc@41100000 {
+			status = "okay";
+			vmmc-supply = <&vmmc>;
+			marvell,dma-channels = <21 22>;
+		};
+
+		ohci@4c000000 {
+			status = "okay";
+			marvell,port-mode = <3>;
+			marvell,oc-mode-perport;
+			marvell,enable-port1;
+		};
+
+		eth0: eth@0c000000 {
+			compatible = "davicom,dm9000";
+			reg = <0x0c000000 0x2
+			       0x0c004000 0x2>;
+			interrupt-parent = <&gpio>;
+			interrupts = <9 IRQ_TYPE_EDGE_RISING>;
+			status = "okay";
+		};
+
+		eth1: eth@0d000000 {
+			compatible = "davicom,dm9000";
+			reg = <0x0d000000 0x2
+			       0x0d004000 0x2>;
+			interrupt-parent = <&gpio>;
+			interrupts = <82 IRQ_TYPE_EDGE_RISING>;
+			status = "okay";
+		};
+	};
+};
diff --git a/arch/arm/configs/lp8x4x_defconfig b/arch/arm/configs/lp8x4x_defconfig
new file mode 100644
index 0000000..4421c03
--- /dev/null
+++ b/arch/arm/configs/lp8x4x_defconfig
@@ -0,0 +1,160 @@
+# CONFIG_LOCALVERSION_AUTO is not set
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_RCU_BOOST=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_NS is not set
+# CONFIG_IPC_NS is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+# CONFIG_UID16 is not set
+# CONFIG_SHMEM is not set
+CONFIG_EMBEDDED=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_SLOB=y
+CONFIG_JUMP_LABEL=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+# CONFIG_LBDAF is not set
+CONFIG_BLK_CMDLINE_PARSER=y
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_ARCH_PXA=y
+CONFIG_MACH_PXA27X_DT=y
+# CONFIG_ARM_THUMB is not set
+CONFIG_PREEMPT=y
+CONFIG_AEABI=y
+# CONFIG_COMPACTION is not set
+# CONFIG_CROSS_MEMORY_ATTACH is not set
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="init=/sbin/init root=/dev/mmcblk0p1 rw rootfstype=ext4 console=ttyS0,115200 mem=128M rootwait"
+# CONFIG_SUSPEND is not set
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_BRIDGE=m
+CONFIG_BRIDGE_VLAN_FILTERING=y
+CONFIG_VLAN_8021Q=m
+CONFIG_VLAN_8021Q_GVRP=y
+CONFIG_VLAN_8021Q_MVRP=y
+# CONFIG_WIRELESS is not set
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+# CONFIG_FW_LOADER is not set
+CONFIG_MTD=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_CFI_GEOMETRY=y
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_PHYSMAP_OF=y
+CONFIG_PROC_DEVICETREE=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_LOOP_MIN_COUNT=2
+CONFIG_SCSI=y
+# CONFIG_SCSI_PROC_FS is not set
+CONFIG_BLK_DEV_SD=y
+# CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_NETDEVICES=y
+CONFIG_BONDING=m
+CONFIG_MACVLAN=m
+CONFIG_MACVTAP=m
+CONFIG_TUN=m
+# CONFIG_NET_VENDOR_ARC is not set
+# CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_CIRRUS is not set
+CONFIG_DM9000=y
+CONFIG_DM9000_FORCE_SIMPLE_PHY_POLL=y
+# CONFIG_NET_VENDOR_FARADAY is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+CONFIG_PPP=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPPOE=m
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_SLIP=m
+CONFIG_SLIP_COMPRESSED=y
+# CONFIG_WLAN is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=800
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=600
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_SERIO is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_8250=y
+# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=40
+CONFIG_SERIAL_8250_RUNTIME_UARTS=40
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_PXA=y
+CONFIG_HW_RANDOM=y
+CONFIG_I2C=m
+# CONFIG_I2C_COMPAT is not set
+CONFIG_I2C_PXA=m
+CONFIG_I2C_PXA_SLAVE=y
+# CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_SA1100_WATCHDOG=m
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_FB=y
+CONFIG_FB_PXA=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_LOGO=y
+CONFIG_USB=m
+CONFIG_USB_OHCI_HCD=m
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+CONFIG_USB_STORAGE=m
+CONFIG_USB_SERIAL=m
+CONFIG_MMC=y
+CONFIG_MMC_PXA=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_PXA=m
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_EXT2_FS=m
+CONFIG_EXT3_FS=y
+CONFIG_EXT4_FS=y
+CONFIG_REISERFS_FS=m
+CONFIG_ISO9660_FS=m
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_NTFS_FS=m
+CONFIG_NTFS_RW=y
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V4=y
+CONFIG_ROOT_NFS=y
+CONFIG_CIFS=m
+CONFIG_CIFS_STATS=y
+CONFIG_CODA_FS=m
+CONFIG_NLS_DEFAULT="cp855"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_855=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_UTF8=y
+CONFIG_PRINTK_TIME=y
diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig
index 96100db..df3a79d 100644
--- a/arch/arm/mach-pxa/Kconfig
+++ b/arch/arm/mach-pxa/Kconfig
@@ -4,6 +4,21 @@ menu "Intel PXA2xx/PXA3xx Implementations"
 
 comment "Intel/Marvell Dev Platforms (sorted by hardware release time)"
 
+config MACH_PXA27X_DT
+	bool "Support PXA27x platforms from device tree"
+	select PXA27x
+	select USE_OF
+	help
+	  Include support for Marvell PXA27x based platforms using
+	  the device tree.
+
+	  While MACH_PXA27X_DT when enabled should boot any PXA27x
+	  compatible machine, it still makes sense to select specific
+	  machines. Those options will select required features and
+	  provide per-machine errata workarounds.
+
+	  If unsure, say Y.
+
 config MACH_PXA3XX_DT
 	bool "Support PXA3xx platforms from device tree"
 	select CPU_PXA300
diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile
index 648867a..adaa72a 100644
--- a/arch/arm/mach-pxa/Makefile
+++ b/arch/arm/mach-pxa/Makefile
@@ -20,6 +20,7 @@ obj-$(CONFIG_CPU_PXA930)	+= pxa930.o
 # NOTE: keep the order of boards in accordance to their order in Kconfig
 
 # Device Tree support
+obj-$(CONFIG_MACH_PXA27X_DT)	+= pxa27x-dt.o
 obj-$(CONFIG_MACH_PXA3XX_DT)	+= pxa-dt.o
 
 # Intel/Marvell Dev Platforms
diff --git a/arch/arm/mach-pxa/pxa27x-dt.c b/arch/arm/mach-pxa/pxa27x-dt.c
new file mode 100644
index 0000000..865cf46
--- /dev/null
+++ b/arch/arm/mach-pxa/pxa27x-dt.c
@@ -0,0 +1,64 @@
+/*
+ *  linux/arch/arm/mach-pxa/pxa27x-dt.c
+ *
+ *  Copyright (C) 2013 Sergei Ianovich
+ *
+ *  based mostly on linux/arch/arm/mach-pxa/pxa-dt.c by Daniel Mack
+ *
+ *  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
+ *  publishhed by the Free Software Foundation.
+ */
+
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <asm/io.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <mach/irqs.h>
+#include <mach/pxa27x.h>
+
+#include "generic.h"
+
+#ifdef CONFIG_PXA27x
+static const struct of_dev_auxdata pxa27x_auxdata_lookup[] __initconst = {
+	OF_DEV_AUXDATA("mrvl,pxa-uart",	    0x40100000, "pxa2xx-uart.0", NULL),
+	OF_DEV_AUXDATA("mrvl,pxa-uart",	    0x40200000, "pxa2xx-uart.1", NULL),
+	OF_DEV_AUXDATA("mrvl,pxa-uart",	    0x40700000, "pxa2xx-uart.2", NULL),
+	OF_DEV_AUXDATA("mrvl,pxa-uart",	    0x41600000, "pxa2xx-uart.3", NULL),
+	OF_DEV_AUXDATA("marvell,pxa-mmc",   0x41100000, "pxa2xx-mci.0", NULL),
+	OF_DEV_AUXDATA("intel,pxa27x-gpio", 0x40e00000, "pxa27x-gpio", NULL),
+	OF_DEV_AUXDATA("marvell,pxa-ohci",  0x4c000000, "pxa27x-ohci", NULL),
+	OF_DEV_AUXDATA("mrvl,pxa-i2c",	    0x40301680, "pxa2xx-i2c.0", NULL),
+	{}
+};
+
+static void __init pxa27x_dt_init(void)
+{
+	of_platform_populate(NULL, of_default_bus_match_table,
+			     pxa27x_auxdata_lookup, NULL);
+}
+
+static const char * const pxa27x_dt_board_compat[] __initconst = {
+	"marvell,pxa270",
+	"marvell,pxa271",
+	"marvell,pxa272",
+	NULL,
+};
+
+#endif
+
+#ifdef CONFIG_PXA27x
+DT_MACHINE_START(PXA27X_DT, "Marvell PXA27x (Device Tree Support)")
+	.map_io		= pxa27x_map_io,
+	.init_irq	= pxa27x_dt_init_irq,
+	.handle_irq	= pxa27x_handle_irq,
+	.init_time	= pxa_timer_init,
+	.restart	= pxa_restart,
+	.init_machine	= pxa27x_dt_init,
+	.dt_compat	= pxa27x_dt_board_compat,
+MACHINE_END
+
+#endif
-- 
1.8.4.3


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

* [PATCH v2 06/16] ARM: pxa27x: device tree support ICP DAS LP-8x4x
@ 2013-12-13  2:27           ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-13  2:27 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Daniel Mack, Arnd Bergmann, Linus Walleij,
	Rob Herring, Pawel Moll, Mark Rutland, Stephen Warren,
	Ian Campbell, Russell King, Eric Miao, Haojian Zhuang,
	open list:OPEN FIRMWARE AND...

ICP DAS calls LP-8x4x 'programmable automation controller'. It is
an industrial computer based on PXA270 SoC. They ship it with a 2.6.19
kernel and proprietary kernel module and userspace library to access
its industrial IO.

This patch allows to boot the device with a modern kernel with device
tree. It adds support for:
* MMC card interface on PXA270
* USB 1.1 port on PXA270
* 2 NOR flash devices
* 2 onboard ethernet Davicom DM9000 devices
* 3 serial UART ports on PXA270

Support for these devices will be added in separate patches, since
they are not currently supported by the kernel:
* DS1302 RTC
* 512kiB SRAM
* FPGA irq chip
* 3 built-in and up to 32 pluggable 8250 serial UART ports
* industrial IO parallel bus
* digital and analog industrial IO modules for parallel bus
* serial interface for digital and analog industrial IO modules on
  parallel bus

Not supported for now:
* VGA interface on PXA270 for lack of dts binding

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Daniel Mack <zonque@gmail.com>
CC: Arnd Bergmann <arnd@arndb.de>
CC: Linus Walleij <linus.walleij@linaro.org>
---
   v1..v2
   * drop left-over extern declaration
   * use of_have_populated_dt() instead of a static variable
   * drop wildcards in compatible
   * drop machine-special machine description
   * number changed from 9 to 6 (dropped patches)

 arch/arm/boot/dts/Makefile          |   1 +
 arch/arm/boot/dts/pxa27x-lp8x4x.dts | 111 +++++++++++++++++++++++++
 arch/arm/configs/lp8x4x_defconfig   | 160 ++++++++++++++++++++++++++++++++++++
 arch/arm/mach-pxa/Kconfig           |  15 ++++
 arch/arm/mach-pxa/Makefile          |   1 +
 arch/arm/mach-pxa/pxa27x-dt.c       |  64 +++++++++++++++
 6 files changed, 352 insertions(+)
 create mode 100644 arch/arm/boot/dts/pxa27x-lp8x4x.dts
 create mode 100644 arch/arm/configs/lp8x4x_defconfig
 create mode 100644 arch/arm/mach-pxa/pxa27x-dt.c

diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index d57c1a6..c4752ff 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -206,6 +206,7 @@ dtb-$(CONFIG_ARCH_OMAP2PLUS) += omap2420-h4.dtb \
 	dra7-evm.dtb
 dtb-$(CONFIG_ARCH_ORION5X) += orion5x-lacie-ethernet-disk-mini-v2.dtb
 dtb-$(CONFIG_ARCH_PRIMA2) += prima2-evb.dtb
+dtb-$(CONFIG_MACH_PXA27X_DT) += pxa27x-lp8x4x.dtb
 dtb-$(CONFIG_ARCH_U8500) += ste-snowball.dtb \
 	ste-hrefprev60-stuib.dtb \
 	ste-hrefprev60-tvk.dtb \
diff --git a/arch/arm/boot/dts/pxa27x-lp8x4x.dts b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
new file mode 100644
index 0000000..a2a9183
--- /dev/null
+++ b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
@@ -0,0 +1,111 @@
+/* Device tree for ICP DAS LP-8x4x */
+/dts-v1/;
+
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include "pxa27x.dtsi"
+
+/ {
+	model = "ICP DAS LP-8x4x programmable automation controller";
+	compatible = "marvell,lp8x4x", "marvell,pxa270";
+
+	memory {
+		reg = <0xa0000000 0x08000000>;
+	};
+
+	regulators {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		vmmc: regulator@0 {
+			compatible = "regulator-fixed";
+			reg = <0>;
+			regulator-name = "vmmc";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-always-on;
+		};
+	};
+
+	flash@00000000 {
+		compatible = "cfi-flash";
+		reg = <0x0 0x02000000>;
+		bank-width = <4>;
+		device-width = <2>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		fs@0 {
+			label = "u-boot";
+			reg = <0 0x40000>;
+		};
+		fs@40000 {
+			label = "settings";
+			reg = <0x40000 0x40000>;
+		};
+		fs@80000 {
+			label = "kernel";
+			reg = <0x80000 0x280000>;
+		};
+		fs@300000 {
+			label = "root_fs";
+			reg = <0x300000 0x1d00000>;
+		};
+	};
+
+	flash@04000000 {
+		compatible = "cfi-flash";
+		reg = <0x04000000 0x02000000>;
+		bank-width = <2>;
+		device-width = <1>;
+	};
+
+	pxabus {
+		pxairq: interrupt-controller@40d00000 {
+			marvell,intc-priority;
+			marvell,intc-nr-irqs = <34>;
+		};
+
+		uart@40100000 {
+			status = "okay";
+		};
+
+		uart@40200000 {
+			status = "okay";
+		};
+
+		uart@40700000 {
+			status = "okay";
+		};
+
+		mmc@41100000 {
+			status = "okay";
+			vmmc-supply = <&vmmc>;
+			marvell,dma-channels = <21 22>;
+		};
+
+		ohci@4c000000 {
+			status = "okay";
+			marvell,port-mode = <3>;
+			marvell,oc-mode-perport;
+			marvell,enable-port1;
+		};
+
+		eth0: eth@0c000000 {
+			compatible = "davicom,dm9000";
+			reg = <0x0c000000 0x2
+			       0x0c004000 0x2>;
+			interrupt-parent = <&gpio>;
+			interrupts = <9 IRQ_TYPE_EDGE_RISING>;
+			status = "okay";
+		};
+
+		eth1: eth@0d000000 {
+			compatible = "davicom,dm9000";
+			reg = <0x0d000000 0x2
+			       0x0d004000 0x2>;
+			interrupt-parent = <&gpio>;
+			interrupts = <82 IRQ_TYPE_EDGE_RISING>;
+			status = "okay";
+		};
+	};
+};
diff --git a/arch/arm/configs/lp8x4x_defconfig b/arch/arm/configs/lp8x4x_defconfig
new file mode 100644
index 0000000..4421c03
--- /dev/null
+++ b/arch/arm/configs/lp8x4x_defconfig
@@ -0,0 +1,160 @@
+# CONFIG_LOCALVERSION_AUTO is not set
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_RCU_BOOST=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_NS is not set
+# CONFIG_IPC_NS is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+# CONFIG_UID16 is not set
+# CONFIG_SHMEM is not set
+CONFIG_EMBEDDED=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_SLOB=y
+CONFIG_JUMP_LABEL=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+# CONFIG_LBDAF is not set
+CONFIG_BLK_CMDLINE_PARSER=y
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_ARCH_PXA=y
+CONFIG_MACH_PXA27X_DT=y
+# CONFIG_ARM_THUMB is not set
+CONFIG_PREEMPT=y
+CONFIG_AEABI=y
+# CONFIG_COMPACTION is not set
+# CONFIG_CROSS_MEMORY_ATTACH is not set
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="init=/sbin/init root=/dev/mmcblk0p1 rw rootfstype=ext4 console=ttyS0,115200 mem=128M rootwait"
+# CONFIG_SUSPEND is not set
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_BRIDGE=m
+CONFIG_BRIDGE_VLAN_FILTERING=y
+CONFIG_VLAN_8021Q=m
+CONFIG_VLAN_8021Q_GVRP=y
+CONFIG_VLAN_8021Q_MVRP=y
+# CONFIG_WIRELESS is not set
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+# CONFIG_FW_LOADER is not set
+CONFIG_MTD=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_CFI_GEOMETRY=y
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_PHYSMAP_OF=y
+CONFIG_PROC_DEVICETREE=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_LOOP_MIN_COUNT=2
+CONFIG_SCSI=y
+# CONFIG_SCSI_PROC_FS is not set
+CONFIG_BLK_DEV_SD=y
+# CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_NETDEVICES=y
+CONFIG_BONDING=m
+CONFIG_MACVLAN=m
+CONFIG_MACVTAP=m
+CONFIG_TUN=m
+# CONFIG_NET_VENDOR_ARC is not set
+# CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_CIRRUS is not set
+CONFIG_DM9000=y
+CONFIG_DM9000_FORCE_SIMPLE_PHY_POLL=y
+# CONFIG_NET_VENDOR_FARADAY is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+CONFIG_PPP=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPPOE=m
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_SLIP=m
+CONFIG_SLIP_COMPRESSED=y
+# CONFIG_WLAN is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=800
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=600
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_SERIO is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_8250=y
+# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=40
+CONFIG_SERIAL_8250_RUNTIME_UARTS=40
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_PXA=y
+CONFIG_HW_RANDOM=y
+CONFIG_I2C=m
+# CONFIG_I2C_COMPAT is not set
+CONFIG_I2C_PXA=m
+CONFIG_I2C_PXA_SLAVE=y
+# CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_SA1100_WATCHDOG=m
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_FB=y
+CONFIG_FB_PXA=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_LOGO=y
+CONFIG_USB=m
+CONFIG_USB_OHCI_HCD=m
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+CONFIG_USB_STORAGE=m
+CONFIG_USB_SERIAL=m
+CONFIG_MMC=y
+CONFIG_MMC_PXA=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_PXA=m
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_EXT2_FS=m
+CONFIG_EXT3_FS=y
+CONFIG_EXT4_FS=y
+CONFIG_REISERFS_FS=m
+CONFIG_ISO9660_FS=m
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_NTFS_FS=m
+CONFIG_NTFS_RW=y
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V4=y
+CONFIG_ROOT_NFS=y
+CONFIG_CIFS=m
+CONFIG_CIFS_STATS=y
+CONFIG_CODA_FS=m
+CONFIG_NLS_DEFAULT="cp855"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_855=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_UTF8=y
+CONFIG_PRINTK_TIME=y
diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig
index 96100db..df3a79d 100644
--- a/arch/arm/mach-pxa/Kconfig
+++ b/arch/arm/mach-pxa/Kconfig
@@ -4,6 +4,21 @@ menu "Intel PXA2xx/PXA3xx Implementations"
 
 comment "Intel/Marvell Dev Platforms (sorted by hardware release time)"
 
+config MACH_PXA27X_DT
+	bool "Support PXA27x platforms from device tree"
+	select PXA27x
+	select USE_OF
+	help
+	  Include support for Marvell PXA27x based platforms using
+	  the device tree.
+
+	  While MACH_PXA27X_DT when enabled should boot any PXA27x
+	  compatible machine, it still makes sense to select specific
+	  machines. Those options will select required features and
+	  provide per-machine errata workarounds.
+
+	  If unsure, say Y.
+
 config MACH_PXA3XX_DT
 	bool "Support PXA3xx platforms from device tree"
 	select CPU_PXA300
diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile
index 648867a..adaa72a 100644
--- a/arch/arm/mach-pxa/Makefile
+++ b/arch/arm/mach-pxa/Makefile
@@ -20,6 +20,7 @@ obj-$(CONFIG_CPU_PXA930)	+= pxa930.o
 # NOTE: keep the order of boards in accordance to their order in Kconfig
 
 # Device Tree support
+obj-$(CONFIG_MACH_PXA27X_DT)	+= pxa27x-dt.o
 obj-$(CONFIG_MACH_PXA3XX_DT)	+= pxa-dt.o
 
 # Intel/Marvell Dev Platforms
diff --git a/arch/arm/mach-pxa/pxa27x-dt.c b/arch/arm/mach-pxa/pxa27x-dt.c
new file mode 100644
index 0000000..865cf46
--- /dev/null
+++ b/arch/arm/mach-pxa/pxa27x-dt.c
@@ -0,0 +1,64 @@
+/*
+ *  linux/arch/arm/mach-pxa/pxa27x-dt.c
+ *
+ *  Copyright (C) 2013 Sergei Ianovich
+ *
+ *  based mostly on linux/arch/arm/mach-pxa/pxa-dt.c by Daniel Mack
+ *
+ *  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
+ *  publishhed by the Free Software Foundation.
+ */
+
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <asm/io.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <mach/irqs.h>
+#include <mach/pxa27x.h>
+
+#include "generic.h"
+
+#ifdef CONFIG_PXA27x
+static const struct of_dev_auxdata pxa27x_auxdata_lookup[] __initconst = {
+	OF_DEV_AUXDATA("mrvl,pxa-uart",	    0x40100000, "pxa2xx-uart.0", NULL),
+	OF_DEV_AUXDATA("mrvl,pxa-uart",	    0x40200000, "pxa2xx-uart.1", NULL),
+	OF_DEV_AUXDATA("mrvl,pxa-uart",	    0x40700000, "pxa2xx-uart.2", NULL),
+	OF_DEV_AUXDATA("mrvl,pxa-uart",	    0x41600000, "pxa2xx-uart.3", NULL),
+	OF_DEV_AUXDATA("marvell,pxa-mmc",   0x41100000, "pxa2xx-mci.0", NULL),
+	OF_DEV_AUXDATA("intel,pxa27x-gpio", 0x40e00000, "pxa27x-gpio", NULL),
+	OF_DEV_AUXDATA("marvell,pxa-ohci",  0x4c000000, "pxa27x-ohci", NULL),
+	OF_DEV_AUXDATA("mrvl,pxa-i2c",	    0x40301680, "pxa2xx-i2c.0", NULL),
+	{}
+};
+
+static void __init pxa27x_dt_init(void)
+{
+	of_platform_populate(NULL, of_default_bus_match_table,
+			     pxa27x_auxdata_lookup, NULL);
+}
+
+static const char * const pxa27x_dt_board_compat[] __initconst = {
+	"marvell,pxa270",
+	"marvell,pxa271",
+	"marvell,pxa272",
+	NULL,
+};
+
+#endif
+
+#ifdef CONFIG_PXA27x
+DT_MACHINE_START(PXA27X_DT, "Marvell PXA27x (Device Tree Support)")
+	.map_io		= pxa27x_map_io,
+	.init_irq	= pxa27x_dt_init_irq,
+	.handle_irq	= pxa27x_handle_irq,
+	.init_time	= pxa_timer_init,
+	.restart	= pxa_restart,
+	.init_machine	= pxa27x_dt_init,
+	.dt_compat	= pxa27x_dt_board_compat,
+MACHINE_END
+
+#endif
-- 
1.8.4.3

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

* [PATCH v2 06/16] ARM: pxa27x: device tree support ICP DAS LP-8x4x
@ 2013-12-13  2:27           ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-13  2:27 UTC (permalink / raw)
  To: linux-arm-kernel

ICP DAS calls LP-8x4x 'programmable automation controller'. It is
an industrial computer based on PXA270 SoC. They ship it with a 2.6.19
kernel and proprietary kernel module and userspace library to access
its industrial IO.

This patch allows to boot the device with a modern kernel with device
tree. It adds support for:
* MMC card interface on PXA270
* USB 1.1 port on PXA270
* 2 NOR flash devices
* 2 onboard ethernet Davicom DM9000 devices
* 3 serial UART ports on PXA270

Support for these devices will be added in separate patches, since
they are not currently supported by the kernel:
* DS1302 RTC
* 512kiB SRAM
* FPGA irq chip
* 3 built-in and up to 32 pluggable 8250 serial UART ports
* industrial IO parallel bus
* digital and analog industrial IO modules for parallel bus
* serial interface for digital and analog industrial IO modules on
  parallel bus

Not supported for now:
* VGA interface on PXA270 for lack of dts binding

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Daniel Mack <zonque@gmail.com>
CC: Arnd Bergmann <arnd@arndb.de>
CC: Linus Walleij <linus.walleij@linaro.org>
---
   v1..v2
   * drop left-over extern declaration
   * use of_have_populated_dt() instead of a static variable
   * drop wildcards in compatible
   * drop machine-special machine description
   * number changed from 9 to 6 (dropped patches)

 arch/arm/boot/dts/Makefile          |   1 +
 arch/arm/boot/dts/pxa27x-lp8x4x.dts | 111 +++++++++++++++++++++++++
 arch/arm/configs/lp8x4x_defconfig   | 160 ++++++++++++++++++++++++++++++++++++
 arch/arm/mach-pxa/Kconfig           |  15 ++++
 arch/arm/mach-pxa/Makefile          |   1 +
 arch/arm/mach-pxa/pxa27x-dt.c       |  64 +++++++++++++++
 6 files changed, 352 insertions(+)
 create mode 100644 arch/arm/boot/dts/pxa27x-lp8x4x.dts
 create mode 100644 arch/arm/configs/lp8x4x_defconfig
 create mode 100644 arch/arm/mach-pxa/pxa27x-dt.c

diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index d57c1a6..c4752ff 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -206,6 +206,7 @@ dtb-$(CONFIG_ARCH_OMAP2PLUS) += omap2420-h4.dtb \
 	dra7-evm.dtb
 dtb-$(CONFIG_ARCH_ORION5X) += orion5x-lacie-ethernet-disk-mini-v2.dtb
 dtb-$(CONFIG_ARCH_PRIMA2) += prima2-evb.dtb
+dtb-$(CONFIG_MACH_PXA27X_DT) += pxa27x-lp8x4x.dtb
 dtb-$(CONFIG_ARCH_U8500) += ste-snowball.dtb \
 	ste-hrefprev60-stuib.dtb \
 	ste-hrefprev60-tvk.dtb \
diff --git a/arch/arm/boot/dts/pxa27x-lp8x4x.dts b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
new file mode 100644
index 0000000..a2a9183
--- /dev/null
+++ b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
@@ -0,0 +1,111 @@
+/* Device tree for ICP DAS LP-8x4x */
+/dts-v1/;
+
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include "pxa27x.dtsi"
+
+/ {
+	model = "ICP DAS LP-8x4x programmable automation controller";
+	compatible = "marvell,lp8x4x", "marvell,pxa270";
+
+	memory {
+		reg = <0xa0000000 0x08000000>;
+	};
+
+	regulators {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		vmmc: regulator at 0 {
+			compatible = "regulator-fixed";
+			reg = <0>;
+			regulator-name = "vmmc";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-always-on;
+		};
+	};
+
+	flash at 00000000 {
+		compatible = "cfi-flash";
+		reg = <0x0 0x02000000>;
+		bank-width = <4>;
+		device-width = <2>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		fs at 0 {
+			label = "u-boot";
+			reg = <0 0x40000>;
+		};
+		fs at 40000 {
+			label = "settings";
+			reg = <0x40000 0x40000>;
+		};
+		fs at 80000 {
+			label = "kernel";
+			reg = <0x80000 0x280000>;
+		};
+		fs at 300000 {
+			label = "root_fs";
+			reg = <0x300000 0x1d00000>;
+		};
+	};
+
+	flash at 04000000 {
+		compatible = "cfi-flash";
+		reg = <0x04000000 0x02000000>;
+		bank-width = <2>;
+		device-width = <1>;
+	};
+
+	pxabus {
+		pxairq: interrupt-controller at 40d00000 {
+			marvell,intc-priority;
+			marvell,intc-nr-irqs = <34>;
+		};
+
+		uart at 40100000 {
+			status = "okay";
+		};
+
+		uart at 40200000 {
+			status = "okay";
+		};
+
+		uart at 40700000 {
+			status = "okay";
+		};
+
+		mmc at 41100000 {
+			status = "okay";
+			vmmc-supply = <&vmmc>;
+			marvell,dma-channels = <21 22>;
+		};
+
+		ohci at 4c000000 {
+			status = "okay";
+			marvell,port-mode = <3>;
+			marvell,oc-mode-perport;
+			marvell,enable-port1;
+		};
+
+		eth0: eth at 0c000000 {
+			compatible = "davicom,dm9000";
+			reg = <0x0c000000 0x2
+			       0x0c004000 0x2>;
+			interrupt-parent = <&gpio>;
+			interrupts = <9 IRQ_TYPE_EDGE_RISING>;
+			status = "okay";
+		};
+
+		eth1: eth at 0d000000 {
+			compatible = "davicom,dm9000";
+			reg = <0x0d000000 0x2
+			       0x0d004000 0x2>;
+			interrupt-parent = <&gpio>;
+			interrupts = <82 IRQ_TYPE_EDGE_RISING>;
+			status = "okay";
+		};
+	};
+};
diff --git a/arch/arm/configs/lp8x4x_defconfig b/arch/arm/configs/lp8x4x_defconfig
new file mode 100644
index 0000000..4421c03
--- /dev/null
+++ b/arch/arm/configs/lp8x4x_defconfig
@@ -0,0 +1,160 @@
+# CONFIG_LOCALVERSION_AUTO is not set
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_RCU_BOOST=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_NS is not set
+# CONFIG_IPC_NS is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+# CONFIG_UID16 is not set
+# CONFIG_SHMEM is not set
+CONFIG_EMBEDDED=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_SLOB=y
+CONFIG_JUMP_LABEL=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+# CONFIG_LBDAF is not set
+CONFIG_BLK_CMDLINE_PARSER=y
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_ARCH_PXA=y
+CONFIG_MACH_PXA27X_DT=y
+# CONFIG_ARM_THUMB is not set
+CONFIG_PREEMPT=y
+CONFIG_AEABI=y
+# CONFIG_COMPACTION is not set
+# CONFIG_CROSS_MEMORY_ATTACH is not set
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="init=/sbin/init root=/dev/mmcblk0p1 rw rootfstype=ext4 console=ttyS0,115200 mem=128M rootwait"
+# CONFIG_SUSPEND is not set
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_BRIDGE=m
+CONFIG_BRIDGE_VLAN_FILTERING=y
+CONFIG_VLAN_8021Q=m
+CONFIG_VLAN_8021Q_GVRP=y
+CONFIG_VLAN_8021Q_MVRP=y
+# CONFIG_WIRELESS is not set
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+# CONFIG_FW_LOADER is not set
+CONFIG_MTD=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_CFI_GEOMETRY=y
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_PHYSMAP_OF=y
+CONFIG_PROC_DEVICETREE=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_LOOP_MIN_COUNT=2
+CONFIG_SCSI=y
+# CONFIG_SCSI_PROC_FS is not set
+CONFIG_BLK_DEV_SD=y
+# CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_NETDEVICES=y
+CONFIG_BONDING=m
+CONFIG_MACVLAN=m
+CONFIG_MACVTAP=m
+CONFIG_TUN=m
+# CONFIG_NET_VENDOR_ARC is not set
+# CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_CIRRUS is not set
+CONFIG_DM9000=y
+CONFIG_DM9000_FORCE_SIMPLE_PHY_POLL=y
+# CONFIG_NET_VENDOR_FARADAY is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+CONFIG_PPP=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPPOE=m
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_SLIP=m
+CONFIG_SLIP_COMPRESSED=y
+# CONFIG_WLAN is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=800
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=600
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_SERIO is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_8250=y
+# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=40
+CONFIG_SERIAL_8250_RUNTIME_UARTS=40
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_PXA=y
+CONFIG_HW_RANDOM=y
+CONFIG_I2C=m
+# CONFIG_I2C_COMPAT is not set
+CONFIG_I2C_PXA=m
+CONFIG_I2C_PXA_SLAVE=y
+# CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_SA1100_WATCHDOG=m
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_FB=y
+CONFIG_FB_PXA=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_LOGO=y
+CONFIG_USB=m
+CONFIG_USB_OHCI_HCD=m
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+CONFIG_USB_STORAGE=m
+CONFIG_USB_SERIAL=m
+CONFIG_MMC=y
+CONFIG_MMC_PXA=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_PXA=m
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_EXT2_FS=m
+CONFIG_EXT3_FS=y
+CONFIG_EXT4_FS=y
+CONFIG_REISERFS_FS=m
+CONFIG_ISO9660_FS=m
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_NTFS_FS=m
+CONFIG_NTFS_RW=y
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V4=y
+CONFIG_ROOT_NFS=y
+CONFIG_CIFS=m
+CONFIG_CIFS_STATS=y
+CONFIG_CODA_FS=m
+CONFIG_NLS_DEFAULT="cp855"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_855=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_UTF8=y
+CONFIG_PRINTK_TIME=y
diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig
index 96100db..df3a79d 100644
--- a/arch/arm/mach-pxa/Kconfig
+++ b/arch/arm/mach-pxa/Kconfig
@@ -4,6 +4,21 @@ menu "Intel PXA2xx/PXA3xx Implementations"
 
 comment "Intel/Marvell Dev Platforms (sorted by hardware release time)"
 
+config MACH_PXA27X_DT
+	bool "Support PXA27x platforms from device tree"
+	select PXA27x
+	select USE_OF
+	help
+	  Include support for Marvell PXA27x based platforms using
+	  the device tree.
+
+	  While MACH_PXA27X_DT when enabled should boot any PXA27x
+	  compatible machine, it still makes sense to select specific
+	  machines. Those options will select required features and
+	  provide per-machine errata workarounds.
+
+	  If unsure, say Y.
+
 config MACH_PXA3XX_DT
 	bool "Support PXA3xx platforms from device tree"
 	select CPU_PXA300
diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile
index 648867a..adaa72a 100644
--- a/arch/arm/mach-pxa/Makefile
+++ b/arch/arm/mach-pxa/Makefile
@@ -20,6 +20,7 @@ obj-$(CONFIG_CPU_PXA930)	+= pxa930.o
 # NOTE: keep the order of boards in accordance to their order in Kconfig
 
 # Device Tree support
+obj-$(CONFIG_MACH_PXA27X_DT)	+= pxa27x-dt.o
 obj-$(CONFIG_MACH_PXA3XX_DT)	+= pxa-dt.o
 
 # Intel/Marvell Dev Platforms
diff --git a/arch/arm/mach-pxa/pxa27x-dt.c b/arch/arm/mach-pxa/pxa27x-dt.c
new file mode 100644
index 0000000..865cf46
--- /dev/null
+++ b/arch/arm/mach-pxa/pxa27x-dt.c
@@ -0,0 +1,64 @@
+/*
+ *  linux/arch/arm/mach-pxa/pxa27x-dt.c
+ *
+ *  Copyright (C) 2013 Sergei Ianovich
+ *
+ *  based mostly on linux/arch/arm/mach-pxa/pxa-dt.c by Daniel Mack
+ *
+ *  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
+ *  publishhed by the Free Software Foundation.
+ */
+
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <asm/io.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <mach/irqs.h>
+#include <mach/pxa27x.h>
+
+#include "generic.h"
+
+#ifdef CONFIG_PXA27x
+static const struct of_dev_auxdata pxa27x_auxdata_lookup[] __initconst = {
+	OF_DEV_AUXDATA("mrvl,pxa-uart",	    0x40100000, "pxa2xx-uart.0", NULL),
+	OF_DEV_AUXDATA("mrvl,pxa-uart",	    0x40200000, "pxa2xx-uart.1", NULL),
+	OF_DEV_AUXDATA("mrvl,pxa-uart",	    0x40700000, "pxa2xx-uart.2", NULL),
+	OF_DEV_AUXDATA("mrvl,pxa-uart",	    0x41600000, "pxa2xx-uart.3", NULL),
+	OF_DEV_AUXDATA("marvell,pxa-mmc",   0x41100000, "pxa2xx-mci.0", NULL),
+	OF_DEV_AUXDATA("intel,pxa27x-gpio", 0x40e00000, "pxa27x-gpio", NULL),
+	OF_DEV_AUXDATA("marvell,pxa-ohci",  0x4c000000, "pxa27x-ohci", NULL),
+	OF_DEV_AUXDATA("mrvl,pxa-i2c",	    0x40301680, "pxa2xx-i2c.0", NULL),
+	{}
+};
+
+static void __init pxa27x_dt_init(void)
+{
+	of_platform_populate(NULL, of_default_bus_match_table,
+			     pxa27x_auxdata_lookup, NULL);
+}
+
+static const char * const pxa27x_dt_board_compat[] __initconst = {
+	"marvell,pxa270",
+	"marvell,pxa271",
+	"marvell,pxa272",
+	NULL,
+};
+
+#endif
+
+#ifdef CONFIG_PXA27x
+DT_MACHINE_START(PXA27X_DT, "Marvell PXA27x (Device Tree Support)")
+	.map_io		= pxa27x_map_io,
+	.init_irq	= pxa27x_dt_init_irq,
+	.handle_irq	= pxa27x_handle_irq,
+	.init_time	= pxa_timer_init,
+	.restart	= pxa_restart,
+	.init_machine	= pxa27x_dt_init,
+	.dt_compat	= pxa27x_dt_board_compat,
+MACHINE_END
+
+#endif
-- 
1.8.4.3

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

* [PATCH v2 07/16] rtc: support DS1302 RTC on ICP DAS LP-8x4x
  2013-12-13  2:27         ` Sergei Ianovich
  (?)
@ 2013-12-13  2:27           ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-13  2:27 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Rob Herring, Pawel Moll, Mark Rutland,
	Stephen Warren, Ian Campbell, Rob Landley, Russell King,
	Alessandro Zummo, Grant Likely, open list:OPEN FIRMWARE AND...,
	open list:DOCUMENTATION, rtc-linux

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
   v0..v2
   * use device tree
   * use devm helpers where possible

 .../devicetree/bindings/rtc/rtc-ds1302.txt         |  14 +++
 arch/arm/boot/dts/pxa27x-lp8x4x.dts                |   6 ++
 arch/arm/configs/lp8x4x_defconfig                  |   1 +
 drivers/rtc/Kconfig                                |   2 +-
 drivers/rtc/rtc-ds1302.c                           | 111 ++++++++++++++++++++-
 5 files changed, 131 insertions(+), 3 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/rtc/rtc-ds1302.txt

diff --git a/Documentation/devicetree/bindings/rtc/rtc-ds1302.txt b/Documentation/devicetree/bindings/rtc/rtc-ds1302.txt
new file mode 100644
index 0000000..876297c
--- /dev/null
+++ b/Documentation/devicetree/bindings/rtc/rtc-ds1302.txt
@@ -0,0 +1,14 @@
+* Dallas Semiconductor DS-1302 RTC
+
+Simple device which could be used to store date/time between reboots.
+
+Required properties:
+- compatible : Should be "ds,rtc-ds1302"
+- reg : Should be address and size of IO memory region
+
+Examples:
+
+rtc@40900000 {
+	compatible = "ds,rtc-ds1302";
+	reg = <0x1700901c 0x1>;
+};
diff --git a/arch/arm/boot/dts/pxa27x-lp8x4x.dts b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
index a2a9183..574e853 100644
--- a/arch/arm/boot/dts/pxa27x-lp8x4x.dts
+++ b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
@@ -107,5 +107,11 @@
 			interrupts = <82 IRQ_TYPE_EDGE_RISING>;
 			status = "okay";
 		};
+
+		rtc@1700901c {
+			compatible = "ds,rtc-ds1302";
+			reg = <0x1700901c 0x1>;
+			status = "okay";
+		};
 	};
 };
diff --git a/arch/arm/configs/lp8x4x_defconfig b/arch/arm/configs/lp8x4x_defconfig
index 4421c03..57f2830 100644
--- a/arch/arm/configs/lp8x4x_defconfig
+++ b/arch/arm/configs/lp8x4x_defconfig
@@ -133,6 +133,7 @@ CONFIG_USB_SERIAL=m
 CONFIG_MMC=y
 CONFIG_MMC_PXA=y
 CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_DS1302=y
 CONFIG_RTC_DRV_PXA=m
 # CONFIG_IOMMU_SUPPORT is not set
 CONFIG_EXT2_FS=m
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 0077302..501055f 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -676,7 +676,7 @@ config RTC_DRV_DS1286
 
 config RTC_DRV_DS1302
 	tristate "Dallas DS1302"
-	depends on SH_SECUREEDGE5410
+	depends on SH_SECUREEDGE5410 || (ARCH_PXA && HIGH_RES_TIMERS)
 	help
 	  If you say yes here you get support for the Dallas DS1302 RTC chips.
 
diff --git a/drivers/rtc/rtc-ds1302.c b/drivers/rtc/rtc-ds1302.c
index 07e8d79..d88749c 100644
--- a/drivers/rtc/rtc-ds1302.c
+++ b/drivers/rtc/rtc-ds1302.c
@@ -50,7 +50,7 @@
 #define ds1302_set_tx()
 #define ds1302_set_rx()
 
-static inline int ds1302_hw_init(void)
+static inline int ds1302_hw_init(struct platform_device *pdev)
 {
 	return 0;
 }
@@ -86,6 +86,112 @@ static inline int ds1302_rxbit(void)
 	return !!(get_dp() & RTC_IODATA);
 }
 
+#elif defined(CONFIG_ARCH_PXA) && defined(CONFIG_HIGH_RES_TIMERS)
+
+#include <linux/hrtimer.h>
+#include <linux/of.h>
+#include <linux/sched.h>
+
+#define	RTC_CE		0x01
+#define	RTC_CLK		0x02
+#define	RTC_nWE		0x04
+#define	RTC_IODATA	0x08
+
+static unsigned long ds1302_state;
+
+static void *mem;
+
+void nsleep(unsigned long nanosec)
+{
+	ktime_t t = ns_to_ktime(nanosec);
+	long state = current->state;
+
+	__set_current_state(TASK_UNINTERRUPTIBLE);
+	schedule_hrtimeout(&t, HRTIMER_MODE_REL);
+	__set_current_state(state);
+}
+
+static inline int ds1302_hw_init(struct platform_device *pdev)
+{
+	struct resource *r;
+
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!r)
+		return -ENODEV;
+
+	mem = devm_ioremap_resource(&pdev->dev, r);
+	if (!mem)
+		return -EFAULT;
+
+	return 0;
+}
+
+static inline void ds1302_reset(void)
+{
+	ds1302_state = 0;
+	iowrite8(ds1302_state, mem);
+	nsleep(4000);
+}
+
+static inline void ds1302_clock(void)
+{
+	nsleep(1000);
+	ds1302_state |= RTC_CLK;
+	iowrite8(ds1302_state, mem);
+	nsleep(1000);
+	ds1302_state &= ~RTC_CLK;
+	iowrite8(ds1302_state, mem);
+}
+
+static inline void ds1302_start(void)
+{
+	ds1302_state &= ~RTC_CLK;
+	ds1302_state |= RTC_CE;
+	iowrite8(ds1302_state, mem);
+	nsleep(3000);
+}
+
+static inline void ds1302_stop(void)
+{
+	ds1302_state &= ~RTC_CE;
+	iowrite8(ds1302_state, mem);
+}
+
+static inline void ds1302_set_tx(void)
+{
+	ds1302_state &= ~RTC_nWE;
+	iowrite8(ds1302_state, mem);
+}
+
+static inline void ds1302_set_rx(void)
+{
+	ds1302_state |= RTC_nWE;
+	iowrite8(ds1302_state, mem);
+}
+
+static inline void ds1302_txbit(int bit)
+{
+	if (bit)
+		ds1302_state |= RTC_IODATA;
+	else
+		ds1302_state &= ~RTC_IODATA;
+	iowrite8(ds1302_state, mem);
+}
+
+static inline int ds1302_rxbit(void)
+{
+	return ioread8(mem) & 0x1;
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id ds1302_dt_ids[] = {
+	{ .compatible = "ds,rtc-ds1302" },
+	{ }
+};
+
+MODULE_DEVICE_TABLE(of, ds1302_dt_ids);
+#endif
+
 #else
 #error "Add support for your platform"
 #endif
@@ -216,7 +322,7 @@ static int __init ds1302_rtc_probe(struct platform_device *pdev)
 {
 	struct rtc_device *rtc;
 
-	if (ds1302_hw_init()) {
+	if (ds1302_hw_init(pdev)) {
 		dev_err(&pdev->dev, "Failed to init communication channel");
 		return -EINVAL;
 	}
@@ -245,6 +351,7 @@ static struct platform_driver ds1302_platform_driver = {
 	.driver		= {
 		.name	= DRV_NAME,
 		.owner	= THIS_MODULE,
+		.of_match_table = of_match_ptr(ds1302_dt_ids),
 	},
 };
 
-- 
1.8.4.3


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

* [PATCH v2 07/16] rtc: support DS1302 RTC on ICP DAS LP-8x4x
@ 2013-12-13  2:27           ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-13  2:27 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Rob Herring, Pawel Moll, Mark Rutland,
	Stephen Warren, Ian Campbell, Rob Landley, Russell King,
	Alessandro Zummo, Grant Likely, open list:OPEN FIRMWARE AND...,
	open list:DOCUMENTATION, rtc-linux

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
   v0..v2
   * use device tree
   * use devm helpers where possible

 .../devicetree/bindings/rtc/rtc-ds1302.txt         |  14 +++
 arch/arm/boot/dts/pxa27x-lp8x4x.dts                |   6 ++
 arch/arm/configs/lp8x4x_defconfig                  |   1 +
 drivers/rtc/Kconfig                                |   2 +-
 drivers/rtc/rtc-ds1302.c                           | 111 ++++++++++++++++++++-
 5 files changed, 131 insertions(+), 3 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/rtc/rtc-ds1302.txt

diff --git a/Documentation/devicetree/bindings/rtc/rtc-ds1302.txt b/Documentation/devicetree/bindings/rtc/rtc-ds1302.txt
new file mode 100644
index 0000000..876297c
--- /dev/null
+++ b/Documentation/devicetree/bindings/rtc/rtc-ds1302.txt
@@ -0,0 +1,14 @@
+* Dallas Semiconductor DS-1302 RTC
+
+Simple device which could be used to store date/time between reboots.
+
+Required properties:
+- compatible : Should be "ds,rtc-ds1302"
+- reg : Should be address and size of IO memory region
+
+Examples:
+
+rtc@40900000 {
+	compatible = "ds,rtc-ds1302";
+	reg = <0x1700901c 0x1>;
+};
diff --git a/arch/arm/boot/dts/pxa27x-lp8x4x.dts b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
index a2a9183..574e853 100644
--- a/arch/arm/boot/dts/pxa27x-lp8x4x.dts
+++ b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
@@ -107,5 +107,11 @@
 			interrupts = <82 IRQ_TYPE_EDGE_RISING>;
 			status = "okay";
 		};
+
+		rtc@1700901c {
+			compatible = "ds,rtc-ds1302";
+			reg = <0x1700901c 0x1>;
+			status = "okay";
+		};
 	};
 };
diff --git a/arch/arm/configs/lp8x4x_defconfig b/arch/arm/configs/lp8x4x_defconfig
index 4421c03..57f2830 100644
--- a/arch/arm/configs/lp8x4x_defconfig
+++ b/arch/arm/configs/lp8x4x_defconfig
@@ -133,6 +133,7 @@ CONFIG_USB_SERIAL=m
 CONFIG_MMC=y
 CONFIG_MMC_PXA=y
 CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_DS1302=y
 CONFIG_RTC_DRV_PXA=m
 # CONFIG_IOMMU_SUPPORT is not set
 CONFIG_EXT2_FS=m
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 0077302..501055f 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -676,7 +676,7 @@ config RTC_DRV_DS1286
 
 config RTC_DRV_DS1302
 	tristate "Dallas DS1302"
-	depends on SH_SECUREEDGE5410
+	depends on SH_SECUREEDGE5410 || (ARCH_PXA && HIGH_RES_TIMERS)
 	help
 	  If you say yes here you get support for the Dallas DS1302 RTC chips.
 
diff --git a/drivers/rtc/rtc-ds1302.c b/drivers/rtc/rtc-ds1302.c
index 07e8d79..d88749c 100644
--- a/drivers/rtc/rtc-ds1302.c
+++ b/drivers/rtc/rtc-ds1302.c
@@ -50,7 +50,7 @@
 #define ds1302_set_tx()
 #define ds1302_set_rx()
 
-static inline int ds1302_hw_init(void)
+static inline int ds1302_hw_init(struct platform_device *pdev)
 {
 	return 0;
 }
@@ -86,6 +86,112 @@ static inline int ds1302_rxbit(void)
 	return !!(get_dp() & RTC_IODATA);
 }
 
+#elif defined(CONFIG_ARCH_PXA) && defined(CONFIG_HIGH_RES_TIMERS)
+
+#include <linux/hrtimer.h>
+#include <linux/of.h>
+#include <linux/sched.h>
+
+#define	RTC_CE		0x01
+#define	RTC_CLK		0x02
+#define	RTC_nWE		0x04
+#define	RTC_IODATA	0x08
+
+static unsigned long ds1302_state;
+
+static void *mem;
+
+void nsleep(unsigned long nanosec)
+{
+	ktime_t t = ns_to_ktime(nanosec);
+	long state = current->state;
+
+	__set_current_state(TASK_UNINTERRUPTIBLE);
+	schedule_hrtimeout(&t, HRTIMER_MODE_REL);
+	__set_current_state(state);
+}
+
+static inline int ds1302_hw_init(struct platform_device *pdev)
+{
+	struct resource *r;
+
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!r)
+		return -ENODEV;
+
+	mem = devm_ioremap_resource(&pdev->dev, r);
+	if (!mem)
+		return -EFAULT;
+
+	return 0;
+}
+
+static inline void ds1302_reset(void)
+{
+	ds1302_state = 0;
+	iowrite8(ds1302_state, mem);
+	nsleep(4000);
+}
+
+static inline void ds1302_clock(void)
+{
+	nsleep(1000);
+	ds1302_state |= RTC_CLK;
+	iowrite8(ds1302_state, mem);
+	nsleep(1000);
+	ds1302_state &= ~RTC_CLK;
+	iowrite8(ds1302_state, mem);
+}
+
+static inline void ds1302_start(void)
+{
+	ds1302_state &= ~RTC_CLK;
+	ds1302_state |= RTC_CE;
+	iowrite8(ds1302_state, mem);
+	nsleep(3000);
+}
+
+static inline void ds1302_stop(void)
+{
+	ds1302_state &= ~RTC_CE;
+	iowrite8(ds1302_state, mem);
+}
+
+static inline void ds1302_set_tx(void)
+{
+	ds1302_state &= ~RTC_nWE;
+	iowrite8(ds1302_state, mem);
+}
+
+static inline void ds1302_set_rx(void)
+{
+	ds1302_state |= RTC_nWE;
+	iowrite8(ds1302_state, mem);
+}
+
+static inline void ds1302_txbit(int bit)
+{
+	if (bit)
+		ds1302_state |= RTC_IODATA;
+	else
+		ds1302_state &= ~RTC_IODATA;
+	iowrite8(ds1302_state, mem);
+}
+
+static inline int ds1302_rxbit(void)
+{
+	return ioread8(mem) & 0x1;
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id ds1302_dt_ids[] = {
+	{ .compatible = "ds,rtc-ds1302" },
+	{ }
+};
+
+MODULE_DEVICE_TABLE(of, ds1302_dt_ids);
+#endif
+
 #else
 #error "Add support for your platform"
 #endif
@@ -216,7 +322,7 @@ static int __init ds1302_rtc_probe(struct platform_device *pdev)
 {
 	struct rtc_device *rtc;
 
-	if (ds1302_hw_init()) {
+	if (ds1302_hw_init(pdev)) {
 		dev_err(&pdev->dev, "Failed to init communication channel");
 		return -EINVAL;
 	}
@@ -245,6 +351,7 @@ static struct platform_driver ds1302_platform_driver = {
 	.driver		= {
 		.name	= DRV_NAME,
 		.owner	= THIS_MODULE,
+		.of_match_table = of_match_ptr(ds1302_dt_ids),
 	},
 };
 
-- 
1.8.4.3

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

* [PATCH v2 07/16] rtc: support DS1302 RTC on ICP DAS LP-8x4x
@ 2013-12-13  2:27           ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-13  2:27 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
   v0..v2
   * use device tree
   * use devm helpers where possible

 .../devicetree/bindings/rtc/rtc-ds1302.txt         |  14 +++
 arch/arm/boot/dts/pxa27x-lp8x4x.dts                |   6 ++
 arch/arm/configs/lp8x4x_defconfig                  |   1 +
 drivers/rtc/Kconfig                                |   2 +-
 drivers/rtc/rtc-ds1302.c                           | 111 ++++++++++++++++++++-
 5 files changed, 131 insertions(+), 3 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/rtc/rtc-ds1302.txt

diff --git a/Documentation/devicetree/bindings/rtc/rtc-ds1302.txt b/Documentation/devicetree/bindings/rtc/rtc-ds1302.txt
new file mode 100644
index 0000000..876297c
--- /dev/null
+++ b/Documentation/devicetree/bindings/rtc/rtc-ds1302.txt
@@ -0,0 +1,14 @@
+* Dallas Semiconductor DS-1302 RTC
+
+Simple device which could be used to store date/time between reboots.
+
+Required properties:
+- compatible : Should be "ds,rtc-ds1302"
+- reg : Should be address and size of IO memory region
+
+Examples:
+
+rtc at 40900000 {
+	compatible = "ds,rtc-ds1302";
+	reg = <0x1700901c 0x1>;
+};
diff --git a/arch/arm/boot/dts/pxa27x-lp8x4x.dts b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
index a2a9183..574e853 100644
--- a/arch/arm/boot/dts/pxa27x-lp8x4x.dts
+++ b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
@@ -107,5 +107,11 @@
 			interrupts = <82 IRQ_TYPE_EDGE_RISING>;
 			status = "okay";
 		};
+
+		rtc at 1700901c {
+			compatible = "ds,rtc-ds1302";
+			reg = <0x1700901c 0x1>;
+			status = "okay";
+		};
 	};
 };
diff --git a/arch/arm/configs/lp8x4x_defconfig b/arch/arm/configs/lp8x4x_defconfig
index 4421c03..57f2830 100644
--- a/arch/arm/configs/lp8x4x_defconfig
+++ b/arch/arm/configs/lp8x4x_defconfig
@@ -133,6 +133,7 @@ CONFIG_USB_SERIAL=m
 CONFIG_MMC=y
 CONFIG_MMC_PXA=y
 CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_DS1302=y
 CONFIG_RTC_DRV_PXA=m
 # CONFIG_IOMMU_SUPPORT is not set
 CONFIG_EXT2_FS=m
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 0077302..501055f 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -676,7 +676,7 @@ config RTC_DRV_DS1286
 
 config RTC_DRV_DS1302
 	tristate "Dallas DS1302"
-	depends on SH_SECUREEDGE5410
+	depends on SH_SECUREEDGE5410 || (ARCH_PXA && HIGH_RES_TIMERS)
 	help
 	  If you say yes here you get support for the Dallas DS1302 RTC chips.
 
diff --git a/drivers/rtc/rtc-ds1302.c b/drivers/rtc/rtc-ds1302.c
index 07e8d79..d88749c 100644
--- a/drivers/rtc/rtc-ds1302.c
+++ b/drivers/rtc/rtc-ds1302.c
@@ -50,7 +50,7 @@
 #define ds1302_set_tx()
 #define ds1302_set_rx()
 
-static inline int ds1302_hw_init(void)
+static inline int ds1302_hw_init(struct platform_device *pdev)
 {
 	return 0;
 }
@@ -86,6 +86,112 @@ static inline int ds1302_rxbit(void)
 	return !!(get_dp() & RTC_IODATA);
 }
 
+#elif defined(CONFIG_ARCH_PXA) && defined(CONFIG_HIGH_RES_TIMERS)
+
+#include <linux/hrtimer.h>
+#include <linux/of.h>
+#include <linux/sched.h>
+
+#define	RTC_CE		0x01
+#define	RTC_CLK		0x02
+#define	RTC_nWE		0x04
+#define	RTC_IODATA	0x08
+
+static unsigned long ds1302_state;
+
+static void *mem;
+
+void nsleep(unsigned long nanosec)
+{
+	ktime_t t = ns_to_ktime(nanosec);
+	long state = current->state;
+
+	__set_current_state(TASK_UNINTERRUPTIBLE);
+	schedule_hrtimeout(&t, HRTIMER_MODE_REL);
+	__set_current_state(state);
+}
+
+static inline int ds1302_hw_init(struct platform_device *pdev)
+{
+	struct resource *r;
+
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!r)
+		return -ENODEV;
+
+	mem = devm_ioremap_resource(&pdev->dev, r);
+	if (!mem)
+		return -EFAULT;
+
+	return 0;
+}
+
+static inline void ds1302_reset(void)
+{
+	ds1302_state = 0;
+	iowrite8(ds1302_state, mem);
+	nsleep(4000);
+}
+
+static inline void ds1302_clock(void)
+{
+	nsleep(1000);
+	ds1302_state |= RTC_CLK;
+	iowrite8(ds1302_state, mem);
+	nsleep(1000);
+	ds1302_state &= ~RTC_CLK;
+	iowrite8(ds1302_state, mem);
+}
+
+static inline void ds1302_start(void)
+{
+	ds1302_state &= ~RTC_CLK;
+	ds1302_state |= RTC_CE;
+	iowrite8(ds1302_state, mem);
+	nsleep(3000);
+}
+
+static inline void ds1302_stop(void)
+{
+	ds1302_state &= ~RTC_CE;
+	iowrite8(ds1302_state, mem);
+}
+
+static inline void ds1302_set_tx(void)
+{
+	ds1302_state &= ~RTC_nWE;
+	iowrite8(ds1302_state, mem);
+}
+
+static inline void ds1302_set_rx(void)
+{
+	ds1302_state |= RTC_nWE;
+	iowrite8(ds1302_state, mem);
+}
+
+static inline void ds1302_txbit(int bit)
+{
+	if (bit)
+		ds1302_state |= RTC_IODATA;
+	else
+		ds1302_state &= ~RTC_IODATA;
+	iowrite8(ds1302_state, mem);
+}
+
+static inline int ds1302_rxbit(void)
+{
+	return ioread8(mem) & 0x1;
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id ds1302_dt_ids[] = {
+	{ .compatible = "ds,rtc-ds1302" },
+	{ }
+};
+
+MODULE_DEVICE_TABLE(of, ds1302_dt_ids);
+#endif
+
 #else
 #error "Add support for your platform"
 #endif
@@ -216,7 +322,7 @@ static int __init ds1302_rtc_probe(struct platform_device *pdev)
 {
 	struct rtc_device *rtc;
 
-	if (ds1302_hw_init()) {
+	if (ds1302_hw_init(pdev)) {
 		dev_err(&pdev->dev, "Failed to init communication channel");
 		return -EINVAL;
 	}
@@ -245,6 +351,7 @@ static struct platform_driver ds1302_platform_driver = {
 	.driver		= {
 		.name	= DRV_NAME,
 		.owner	= THIS_MODULE,
+		.of_match_table = of_match_ptr(ds1302_dt_ids),
 	},
 };
 
-- 
1.8.4.3

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

* [PATCH v2 08/16] mtd: support BB SRAM on ICP DAS LP-8x4x
  2013-12-13  2:27         ` Sergei Ianovich
  (?)
  (?)
@ 2013-12-13  2:27           ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-13  2:27 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Rob Herring, Pawel Moll, Mark Rutland,
	Stephen Warren, Ian Campbell, Russell King, David Woodhouse,
	Grant Likely, Artem Bityutskiy, Robert Jarzmik, Randy Dunlap,
	Kees Cook, Philip Avinash, open list:OPEN FIRMWARE AND...,
	open list:MEMORY TECHNOLOGY...

This provides an MTD device driver for 512kB of battery backed up SRAM
on ICPDAS LP-8X4X programmable automation controllers.

SRAM chip is connected via FPGA and is not accessible without a driver,
unlike flash memory which is wired to CPU MMU.

This SRAM becomes an excellent persisent storage of volatile process
data like counter values and sensor statuses. Storing those data in
flash or mmc card is not a viable solution.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
   v0..v2
   * use device tree
   * use devm helpers where possible

 arch/arm/boot/dts/pxa27x-lp8x4x.dts |   6 +
 arch/arm/configs/lp8x4x_defconfig   |   1 +
 drivers/mtd/devices/Kconfig         |  14 +++
 drivers/mtd/devices/Makefile        |   1 +
 drivers/mtd/devices/sram_lp8x4x.c   | 227 ++++++++++++++++++++++++++++++++++++
 5 files changed, 249 insertions(+)
 create mode 100644 drivers/mtd/devices/sram_lp8x4x.c

diff --git a/arch/arm/boot/dts/pxa27x-lp8x4x.dts b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
index 574e853..b7f8cfc 100644
--- a/arch/arm/boot/dts/pxa27x-lp8x4x.dts
+++ b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
@@ -59,6 +59,12 @@
 		device-width = <1>;
 	};
 
+	sram@1700a000 {
+		compatible = "icpdas,sram-lp8x4x";
+		reg = <0x1700a000 0x1000
+		       0x1700901e 0x1>;
+	};
+
 	pxabus {
 		pxairq: interrupt-controller@40d00000 {
 			marvell,intc-priority;
diff --git a/arch/arm/configs/lp8x4x_defconfig b/arch/arm/configs/lp8x4x_defconfig
index 57f2830..8fa871e 100644
--- a/arch/arm/configs/lp8x4x_defconfig
+++ b/arch/arm/configs/lp8x4x_defconfig
@@ -57,6 +57,7 @@ CONFIG_MTD_CFI_ADV_OPTIONS=y
 CONFIG_MTD_CFI_GEOMETRY=y
 CONFIG_MTD_CFI_INTELEXT=y
 CONFIG_MTD_PHYSMAP_OF=y
+CONFIG_MTD_SRAM_LP8X4X=y
 CONFIG_PROC_DEVICETREE=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_LOOP_MIN_COUNT=2
diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig
index 0128138..95f2075 100644
--- a/drivers/mtd/devices/Kconfig
+++ b/drivers/mtd/devices/Kconfig
@@ -217,4 +217,18 @@ config BCH_CONST_T
 	default 4
 endif
 
+config MTD_SRAM_LP8X4X
+	tristate "SRAM on ICPDAS LP-8X4X"
+	depends on OF && ARCH_PXA
+       ---help---
+	 This provides an MTD device driver for 512kiB of battery backed up SRAM
+	 on ICPDAS LP-8X4X programmable automation controllers.
+
+	 SRAM chip is connected via FPGA and is not accessible without a driver,
+	 unlike flash memory which is wired to CPU MMU.
+
+	 Say N, unless you plan to run this kernel on LP-8X4X.
+
+	 If you say M, the module will be called sram_lp8x4x.
+
 endmenu
diff --git a/drivers/mtd/devices/Makefile b/drivers/mtd/devices/Makefile
index d83bd73..56a74c9 100644
--- a/drivers/mtd/devices/Makefile
+++ b/drivers/mtd/devices/Makefile
@@ -16,6 +16,7 @@ obj-$(CONFIG_MTD_NAND_OMAP_BCH)	+= elm.o
 obj-$(CONFIG_MTD_SPEAR_SMI)	+= spear_smi.o
 obj-$(CONFIG_MTD_SST25L)	+= sst25l.o
 obj-$(CONFIG_MTD_BCM47XXSFLASH)	+= bcm47xxsflash.o
+obj-$(CONFIG_MTD_SRAM_LP8X4X)	+= sram_lp8x4x.o
 
 
 CFLAGS_docg3.o			+= -I$(src)
diff --git a/drivers/mtd/devices/sram_lp8x4x.c b/drivers/mtd/devices/sram_lp8x4x.c
new file mode 100644
index 0000000..9dc7149
--- /dev/null
+++ b/drivers/mtd/devices/sram_lp8x4x.c
@@ -0,0 +1,227 @@
+/*
+ *  linux/drivers/mtd/devices/lp8x4x_sram.c
+ *
+ *  MTD Driver for SRAM on ICPDAS LP-8x4x
+ *  Copyright (C) 2013 Sergei Ianovich <ynvich@gmail.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation or any later version.
+ */
+
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mtd/map.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/platform_device.h>
+#include <linux/of_device.h>
+#include <linux/slab.h>
+#include <linux/string_helpers.h>
+#include <linux/types.h>
+
+#include <asm/mach/flash.h>
+
+struct lp8x4x_sram_info {
+	void __iomem	*bank;
+	void __iomem	*virt;
+	struct mutex	lock;
+	unsigned	active_bank;
+	struct mtd_info	mtd;
+};
+
+static int
+lp8x4x_sram_erase(struct mtd_info *mtd, struct erase_info *instr)
+{
+	struct lp8x4x_sram_info *info = mtd->priv;
+	unsigned bank = instr->addr >> 11;
+	unsigned offset = (instr->addr & 0x7ff) << 1;
+	loff_t i;
+
+	mutex_lock(&info->lock);
+	if (unlikely(bank != info->active_bank)) {
+		info->active_bank = bank;
+		iowrite8(bank, info->bank);
+	}
+	for (i = 0; i < instr->len; i++) {
+		iowrite8(0xff, info->virt + offset);
+		offset += 2;
+		if (unlikely(offset == 0)) {
+			info->active_bank++;
+			iowrite8(info->active_bank, info->bank);
+		}
+	}
+	mutex_unlock(&info->lock);
+	instr->state = MTD_ERASE_DONE;
+	mtd_erase_callback(instr);
+
+	return 0;
+}
+
+static int
+lp8x4x_sram_write(struct mtd_info *mtd, loff_t to, size_t len,
+		size_t *retlen, const u_char *b)
+{
+	struct lp8x4x_sram_info *info = mtd->priv;
+	unsigned bank = to >> 11;
+	unsigned offset = (to & 0x7ff) << 1;
+	loff_t i;
+
+	mutex_lock(&info->lock);
+	if (unlikely(bank != info->active_bank)) {
+		info->active_bank = bank;
+		iowrite8(bank, info->bank);
+	}
+	for (i = 0; i < len; i++) {
+		iowrite8(b[i], info->virt + offset);
+		offset += 2;
+		if (unlikely(offset == 0)) {
+			info->active_bank++;
+			iowrite8(info->active_bank, info->bank);
+		}
+	}
+	mutex_unlock(&info->lock);
+	*retlen = len;
+	return 0;
+}
+
+static int
+lp8x4x_sram_read(struct mtd_info *mtd, loff_t from, size_t len,
+		size_t *retlen, u_char *b)
+{
+	struct lp8x4x_sram_info *info = mtd->priv;
+	unsigned bank = from >> 11;
+	unsigned offset = (from & 0x7ff) << 1;
+	loff_t i;
+
+	mutex_lock(&info->lock);
+	if (unlikely(bank != info->active_bank)) {
+		info->active_bank = bank;
+		iowrite8(bank, info->bank);
+	}
+	for (i = 0; i < len; i++) {
+		b[i] = ioread8(info->virt + offset);
+		offset += 2;
+		if (unlikely(offset == 0)) {
+			info->active_bank++;
+			iowrite8(info->active_bank, info->bank);
+		}
+	}
+	mutex_unlock(&info->lock);
+	*retlen = len;
+	return 0;
+}
+
+static void
+lp8x4x_sram_sync(struct mtd_info *mtd)
+{
+}
+
+static struct of_device_id of_flash_match[] = {
+	{
+		.compatible	= "icpdas,sram-lp8x4x",
+	},
+	{ },
+};
+MODULE_DEVICE_TABLE(of, of_flash_match);
+
+static const char * const probe_types[] = {
+	"cmdlinepart", "RedBoot", "ofpart", "ofoldpart", NULL };
+
+static int
+lp8x4x_sram_probe(struct platform_device *pdev)
+{
+	const struct of_device_id *match;
+	struct lp8x4x_sram_info *info;
+	struct resource *r1, *r2;
+	char sz_str[16];
+	struct mtd_part_parser_data ppdata;
+	int err = 0;
+
+	match = of_match_device(of_flash_match, &pdev->dev);
+	if (!match)
+		return -EINVAL;
+
+	r1 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	r2 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	if (!r1 || !r2)
+		return -ENODEV;
+
+	info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
+	if (!info)
+		return -ENOMEM;
+
+	info->virt =  devm_ioremap_resource(&pdev->dev, r1);
+	if (!info->virt) {
+		dev_err(&pdev->dev, "Failed to ioremap %p\n",
+		       info->virt);
+		return -EFAULT;
+	}
+
+	info->bank = devm_ioremap_resource(&pdev->dev, r2);
+	if (!info->bank) {
+		dev_err(&pdev->dev, "Failed to ioremap %p\n",
+		       info->bank);
+		return -EFAULT;
+	}
+
+	info->mtd.priv = info;
+	info->mtd.name = "SRAM";
+	info->mtd.type = MTD_RAM;
+	info->mtd.flags = MTD_CAP_RAM;
+	info->mtd.size = resource_size(r1) << 7;
+	info->mtd.erasesize = 512;
+	info->mtd.writesize = 4;
+	info->mtd._erase = lp8x4x_sram_erase;
+	info->mtd._write = lp8x4x_sram_write;
+	info->mtd._read = lp8x4x_sram_read;
+	info->mtd._sync = lp8x4x_sram_sync;
+	info->mtd.owner = THIS_MODULE;
+
+	mutex_init(&info->lock);
+	iowrite8(info->active_bank, info->bank);
+	platform_set_drvdata(pdev, info);
+
+	ppdata.of_node = pdev->dev.of_node;
+	err = mtd_device_parse_register(&info->mtd, probe_types, &ppdata,
+			NULL, 0);
+
+	if (err < 0) {
+		dev_err(&pdev->dev, "Failed to register platform device\n");
+		return err;
+	}
+
+	string_get_size(info->mtd.size, STRING_UNITS_2, sz_str,
+			sizeof(sz_str));
+	dev_info(&pdev->dev, "using %s SRAM on LP-8X4X as %s\n", sz_str,
+			dev_name(&info->mtd.dev));
+	return 0;
+}
+
+static int
+lp8x4x_sram_remove(struct platform_device *dev)
+{
+	struct lp8x4x_sram_info *info = platform_get_drvdata(dev);
+
+	mtd_device_unregister(&info->mtd);
+	platform_set_drvdata(dev, NULL);
+	return 0;
+}
+
+static struct platform_driver lp8x4x_sram_driver = {
+	.driver = {
+		.name		= "sram-lp8x4x",
+		.owner		= THIS_MODULE,
+		.of_match_table = of_flash_match,
+	},
+	.probe		= lp8x4x_sram_probe,
+	.remove		= lp8x4x_sram_remove,
+};
+
+module_platform_driver(lp8x4x_sram_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Sergei Ianovich <ynvich@gmail.com>");
+MODULE_DESCRIPTION("MTD driver for SRAM on ICPDAS LP-8x4x");
-- 
1.8.4.3


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

* [PATCH v2 08/16] mtd: support BB SRAM on ICP DAS LP-8x4x
@ 2013-12-13  2:27           ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-13  2:27 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Rob Herring, Pawel Moll, Mark Rutland,
	Stephen Warren, Ian Campbell, Russell King, David Woodhouse,
	Grant Likely, Artem Bityutskiy, Robert Jarzmik, Randy Dunlap,
	Kees Cook, Philip Avinash, open list:OPEN FIRMWARE AND...,
	open list:MEMORY TECHNOLOGY...

This provides an MTD device driver for 512kB of battery backed up SRAM
on ICPDAS LP-8X4X programmable automation controllers.

SRAM chip is connected via FPGA and is not accessible without a driver,
unlike flash memory which is wired to CPU MMU.

This SRAM becomes an excellent persisent storage of volatile process
data like counter values and sensor statuses. Storing those data in
flash or mmc card is not a viable solution.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
   v0..v2
   * use device tree
   * use devm helpers where possible

 arch/arm/boot/dts/pxa27x-lp8x4x.dts |   6 +
 arch/arm/configs/lp8x4x_defconfig   |   1 +
 drivers/mtd/devices/Kconfig         |  14 +++
 drivers/mtd/devices/Makefile        |   1 +
 drivers/mtd/devices/sram_lp8x4x.c   | 227 ++++++++++++++++++++++++++++++++++++
 5 files changed, 249 insertions(+)
 create mode 100644 drivers/mtd/devices/sram_lp8x4x.c

diff --git a/arch/arm/boot/dts/pxa27x-lp8x4x.dts b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
index 574e853..b7f8cfc 100644
--- a/arch/arm/boot/dts/pxa27x-lp8x4x.dts
+++ b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
@@ -59,6 +59,12 @@
 		device-width = <1>;
 	};
 
+	sram@1700a000 {
+		compatible = "icpdas,sram-lp8x4x";
+		reg = <0x1700a000 0x1000
+		       0x1700901e 0x1>;
+	};
+
 	pxabus {
 		pxairq: interrupt-controller@40d00000 {
 			marvell,intc-priority;
diff --git a/arch/arm/configs/lp8x4x_defconfig b/arch/arm/configs/lp8x4x_defconfig
index 57f2830..8fa871e 100644
--- a/arch/arm/configs/lp8x4x_defconfig
+++ b/arch/arm/configs/lp8x4x_defconfig
@@ -57,6 +57,7 @@ CONFIG_MTD_CFI_ADV_OPTIONS=y
 CONFIG_MTD_CFI_GEOMETRY=y
 CONFIG_MTD_CFI_INTELEXT=y
 CONFIG_MTD_PHYSMAP_OF=y
+CONFIG_MTD_SRAM_LP8X4X=y
 CONFIG_PROC_DEVICETREE=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_LOOP_MIN_COUNT=2
diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig
index 0128138..95f2075 100644
--- a/drivers/mtd/devices/Kconfig
+++ b/drivers/mtd/devices/Kconfig
@@ -217,4 +217,18 @@ config BCH_CONST_T
 	default 4
 endif
 
+config MTD_SRAM_LP8X4X
+	tristate "SRAM on ICPDAS LP-8X4X"
+	depends on OF && ARCH_PXA
+       ---help---
+	 This provides an MTD device driver for 512kiB of battery backed up SRAM
+	 on ICPDAS LP-8X4X programmable automation controllers.
+
+	 SRAM chip is connected via FPGA and is not accessible without a driver,
+	 unlike flash memory which is wired to CPU MMU.
+
+	 Say N, unless you plan to run this kernel on LP-8X4X.
+
+	 If you say M, the module will be called sram_lp8x4x.
+
 endmenu
diff --git a/drivers/mtd/devices/Makefile b/drivers/mtd/devices/Makefile
index d83bd73..56a74c9 100644
--- a/drivers/mtd/devices/Makefile
+++ b/drivers/mtd/devices/Makefile
@@ -16,6 +16,7 @@ obj-$(CONFIG_MTD_NAND_OMAP_BCH)	+= elm.o
 obj-$(CONFIG_MTD_SPEAR_SMI)	+= spear_smi.o
 obj-$(CONFIG_MTD_SST25L)	+= sst25l.o
 obj-$(CONFIG_MTD_BCM47XXSFLASH)	+= bcm47xxsflash.o
+obj-$(CONFIG_MTD_SRAM_LP8X4X)	+= sram_lp8x4x.o
 
 
 CFLAGS_docg3.o			+= -I$(src)
diff --git a/drivers/mtd/devices/sram_lp8x4x.c b/drivers/mtd/devices/sram_lp8x4x.c
new file mode 100644
index 0000000..9dc7149
--- /dev/null
+++ b/drivers/mtd/devices/sram_lp8x4x.c
@@ -0,0 +1,227 @@
+/*
+ *  linux/drivers/mtd/devices/lp8x4x_sram.c
+ *
+ *  MTD Driver for SRAM on ICPDAS LP-8x4x
+ *  Copyright (C) 2013 Sergei Ianovich <ynvich@gmail.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation or any later version.
+ */
+
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mtd/map.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/platform_device.h>
+#include <linux/of_device.h>
+#include <linux/slab.h>
+#include <linux/string_helpers.h>
+#include <linux/types.h>
+
+#include <asm/mach/flash.h>
+
+struct lp8x4x_sram_info {
+	void __iomem	*bank;
+	void __iomem	*virt;
+	struct mutex	lock;
+	unsigned	active_bank;
+	struct mtd_info	mtd;
+};
+
+static int
+lp8x4x_sram_erase(struct mtd_info *mtd, struct erase_info *instr)
+{
+	struct lp8x4x_sram_info *info = mtd->priv;
+	unsigned bank = instr->addr >> 11;
+	unsigned offset = (instr->addr & 0x7ff) << 1;
+	loff_t i;
+
+	mutex_lock(&info->lock);
+	if (unlikely(bank != info->active_bank)) {
+		info->active_bank = bank;
+		iowrite8(bank, info->bank);
+	}
+	for (i = 0; i < instr->len; i++) {
+		iowrite8(0xff, info->virt + offset);
+		offset += 2;
+		if (unlikely(offset == 0)) {
+			info->active_bank++;
+			iowrite8(info->active_bank, info->bank);
+		}
+	}
+	mutex_unlock(&info->lock);
+	instr->state = MTD_ERASE_DONE;
+	mtd_erase_callback(instr);
+
+	return 0;
+}
+
+static int
+lp8x4x_sram_write(struct mtd_info *mtd, loff_t to, size_t len,
+		size_t *retlen, const u_char *b)
+{
+	struct lp8x4x_sram_info *info = mtd->priv;
+	unsigned bank = to >> 11;
+	unsigned offset = (to & 0x7ff) << 1;
+	loff_t i;
+
+	mutex_lock(&info->lock);
+	if (unlikely(bank != info->active_bank)) {
+		info->active_bank = bank;
+		iowrite8(bank, info->bank);
+	}
+	for (i = 0; i < len; i++) {
+		iowrite8(b[i], info->virt + offset);
+		offset += 2;
+		if (unlikely(offset == 0)) {
+			info->active_bank++;
+			iowrite8(info->active_bank, info->bank);
+		}
+	}
+	mutex_unlock(&info->lock);
+	*retlen = len;
+	return 0;
+}
+
+static int
+lp8x4x_sram_read(struct mtd_info *mtd, loff_t from, size_t len,
+		size_t *retlen, u_char *b)
+{
+	struct lp8x4x_sram_info *info = mtd->priv;
+	unsigned bank = from >> 11;
+	unsigned offset = (from & 0x7ff) << 1;
+	loff_t i;
+
+	mutex_lock(&info->lock);
+	if (unlikely(bank != info->active_bank)) {
+		info->active_bank = bank;
+		iowrite8(bank, info->bank);
+	}
+	for (i = 0; i < len; i++) {
+		b[i] = ioread8(info->virt + offset);
+		offset += 2;
+		if (unlikely(offset == 0)) {
+			info->active_bank++;
+			iowrite8(info->active_bank, info->bank);
+		}
+	}
+	mutex_unlock(&info->lock);
+	*retlen = len;
+	return 0;
+}
+
+static void
+lp8x4x_sram_sync(struct mtd_info *mtd)
+{
+}
+
+static struct of_device_id of_flash_match[] = {
+	{
+		.compatible	= "icpdas,sram-lp8x4x",
+	},
+	{ },
+};
+MODULE_DEVICE_TABLE(of, of_flash_match);
+
+static const char * const probe_types[] = {
+	"cmdlinepart", "RedBoot", "ofpart", "ofoldpart", NULL };
+
+static int
+lp8x4x_sram_probe(struct platform_device *pdev)
+{
+	const struct of_device_id *match;
+	struct lp8x4x_sram_info *info;
+	struct resource *r1, *r2;
+	char sz_str[16];
+	struct mtd_part_parser_data ppdata;
+	int err = 0;
+
+	match = of_match_device(of_flash_match, &pdev->dev);
+	if (!match)
+		return -EINVAL;
+
+	r1 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	r2 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	if (!r1 || !r2)
+		return -ENODEV;
+
+	info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
+	if (!info)
+		return -ENOMEM;
+
+	info->virt =  devm_ioremap_resource(&pdev->dev, r1);
+	if (!info->virt) {
+		dev_err(&pdev->dev, "Failed to ioremap %p\n",
+		       info->virt);
+		return -EFAULT;
+	}
+
+	info->bank = devm_ioremap_resource(&pdev->dev, r2);
+	if (!info->bank) {
+		dev_err(&pdev->dev, "Failed to ioremap %p\n",
+		       info->bank);
+		return -EFAULT;
+	}
+
+	info->mtd.priv = info;
+	info->mtd.name = "SRAM";
+	info->mtd.type = MTD_RAM;
+	info->mtd.flags = MTD_CAP_RAM;
+	info->mtd.size = resource_size(r1) << 7;
+	info->mtd.erasesize = 512;
+	info->mtd.writesize = 4;
+	info->mtd._erase = lp8x4x_sram_erase;
+	info->mtd._write = lp8x4x_sram_write;
+	info->mtd._read = lp8x4x_sram_read;
+	info->mtd._sync = lp8x4x_sram_sync;
+	info->mtd.owner = THIS_MODULE;
+
+	mutex_init(&info->lock);
+	iowrite8(info->active_bank, info->bank);
+	platform_set_drvdata(pdev, info);
+
+	ppdata.of_node = pdev->dev.of_node;
+	err = mtd_device_parse_register(&info->mtd, probe_types, &ppdata,
+			NULL, 0);
+
+	if (err < 0) {
+		dev_err(&pdev->dev, "Failed to register platform device\n");
+		return err;
+	}
+
+	string_get_size(info->mtd.size, STRING_UNITS_2, sz_str,
+			sizeof(sz_str));
+	dev_info(&pdev->dev, "using %s SRAM on LP-8X4X as %s\n", sz_str,
+			dev_name(&info->mtd.dev));
+	return 0;
+}
+
+static int
+lp8x4x_sram_remove(struct platform_device *dev)
+{
+	struct lp8x4x_sram_info *info = platform_get_drvdata(dev);
+
+	mtd_device_unregister(&info->mtd);
+	platform_set_drvdata(dev, NULL);
+	return 0;
+}
+
+static struct platform_driver lp8x4x_sram_driver = {
+	.driver = {
+		.name		= "sram-lp8x4x",
+		.owner		= THIS_MODULE,
+		.of_match_table = of_flash_match,
+	},
+	.probe		= lp8x4x_sram_probe,
+	.remove		= lp8x4x_sram_remove,
+};
+
+module_platform_driver(lp8x4x_sram_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Sergei Ianovich <ynvich@gmail.com>");
+MODULE_DESCRIPTION("MTD driver for SRAM on ICPDAS LP-8x4x");
-- 
1.8.4.3

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

* [PATCH v2 08/16] mtd: support BB SRAM on ICP DAS LP-8x4x
@ 2013-12-13  2:27           ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-13  2:27 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Mark Rutland, open list:OPEN FIRMWARE AND...,
	Randy Dunlap, Russell King, Kees Cook, Pawel Moll, Ian Campbell,
	Artem Bityutskiy, Robert Jarzmik, Stephen Warren, Rob Herring,
	Sergei Ianovich, Philip Avinash, Grant Likely,
	open list:MEMORY TECHNOLOGY...,
	David Woodhouse

This provides an MTD device driver for 512kB of battery backed up SRAM
on ICPDAS LP-8X4X programmable automation controllers.

SRAM chip is connected via FPGA and is not accessible without a driver,
unlike flash memory which is wired to CPU MMU.

This SRAM becomes an excellent persisent storage of volatile process
data like counter values and sensor statuses. Storing those data in
flash or mmc card is not a viable solution.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
   v0..v2
   * use device tree
   * use devm helpers where possible

 arch/arm/boot/dts/pxa27x-lp8x4x.dts |   6 +
 arch/arm/configs/lp8x4x_defconfig   |   1 +
 drivers/mtd/devices/Kconfig         |  14 +++
 drivers/mtd/devices/Makefile        |   1 +
 drivers/mtd/devices/sram_lp8x4x.c   | 227 ++++++++++++++++++++++++++++++++++++
 5 files changed, 249 insertions(+)
 create mode 100644 drivers/mtd/devices/sram_lp8x4x.c

diff --git a/arch/arm/boot/dts/pxa27x-lp8x4x.dts b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
index 574e853..b7f8cfc 100644
--- a/arch/arm/boot/dts/pxa27x-lp8x4x.dts
+++ b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
@@ -59,6 +59,12 @@
 		device-width = <1>;
 	};
 
+	sram@1700a000 {
+		compatible = "icpdas,sram-lp8x4x";
+		reg = <0x1700a000 0x1000
+		       0x1700901e 0x1>;
+	};
+
 	pxabus {
 		pxairq: interrupt-controller@40d00000 {
 			marvell,intc-priority;
diff --git a/arch/arm/configs/lp8x4x_defconfig b/arch/arm/configs/lp8x4x_defconfig
index 57f2830..8fa871e 100644
--- a/arch/arm/configs/lp8x4x_defconfig
+++ b/arch/arm/configs/lp8x4x_defconfig
@@ -57,6 +57,7 @@ CONFIG_MTD_CFI_ADV_OPTIONS=y
 CONFIG_MTD_CFI_GEOMETRY=y
 CONFIG_MTD_CFI_INTELEXT=y
 CONFIG_MTD_PHYSMAP_OF=y
+CONFIG_MTD_SRAM_LP8X4X=y
 CONFIG_PROC_DEVICETREE=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_LOOP_MIN_COUNT=2
diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig
index 0128138..95f2075 100644
--- a/drivers/mtd/devices/Kconfig
+++ b/drivers/mtd/devices/Kconfig
@@ -217,4 +217,18 @@ config BCH_CONST_T
 	default 4
 endif
 
+config MTD_SRAM_LP8X4X
+	tristate "SRAM on ICPDAS LP-8X4X"
+	depends on OF && ARCH_PXA
+       ---help---
+	 This provides an MTD device driver for 512kiB of battery backed up SRAM
+	 on ICPDAS LP-8X4X programmable automation controllers.
+
+	 SRAM chip is connected via FPGA and is not accessible without a driver,
+	 unlike flash memory which is wired to CPU MMU.
+
+	 Say N, unless you plan to run this kernel on LP-8X4X.
+
+	 If you say M, the module will be called sram_lp8x4x.
+
 endmenu
diff --git a/drivers/mtd/devices/Makefile b/drivers/mtd/devices/Makefile
index d83bd73..56a74c9 100644
--- a/drivers/mtd/devices/Makefile
+++ b/drivers/mtd/devices/Makefile
@@ -16,6 +16,7 @@ obj-$(CONFIG_MTD_NAND_OMAP_BCH)	+= elm.o
 obj-$(CONFIG_MTD_SPEAR_SMI)	+= spear_smi.o
 obj-$(CONFIG_MTD_SST25L)	+= sst25l.o
 obj-$(CONFIG_MTD_BCM47XXSFLASH)	+= bcm47xxsflash.o
+obj-$(CONFIG_MTD_SRAM_LP8X4X)	+= sram_lp8x4x.o
 
 
 CFLAGS_docg3.o			+= -I$(src)
diff --git a/drivers/mtd/devices/sram_lp8x4x.c b/drivers/mtd/devices/sram_lp8x4x.c
new file mode 100644
index 0000000..9dc7149
--- /dev/null
+++ b/drivers/mtd/devices/sram_lp8x4x.c
@@ -0,0 +1,227 @@
+/*
+ *  linux/drivers/mtd/devices/lp8x4x_sram.c
+ *
+ *  MTD Driver for SRAM on ICPDAS LP-8x4x
+ *  Copyright (C) 2013 Sergei Ianovich <ynvich@gmail.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation or any later version.
+ */
+
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mtd/map.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/platform_device.h>
+#include <linux/of_device.h>
+#include <linux/slab.h>
+#include <linux/string_helpers.h>
+#include <linux/types.h>
+
+#include <asm/mach/flash.h>
+
+struct lp8x4x_sram_info {
+	void __iomem	*bank;
+	void __iomem	*virt;
+	struct mutex	lock;
+	unsigned	active_bank;
+	struct mtd_info	mtd;
+};
+
+static int
+lp8x4x_sram_erase(struct mtd_info *mtd, struct erase_info *instr)
+{
+	struct lp8x4x_sram_info *info = mtd->priv;
+	unsigned bank = instr->addr >> 11;
+	unsigned offset = (instr->addr & 0x7ff) << 1;
+	loff_t i;
+
+	mutex_lock(&info->lock);
+	if (unlikely(bank != info->active_bank)) {
+		info->active_bank = bank;
+		iowrite8(bank, info->bank);
+	}
+	for (i = 0; i < instr->len; i++) {
+		iowrite8(0xff, info->virt + offset);
+		offset += 2;
+		if (unlikely(offset == 0)) {
+			info->active_bank++;
+			iowrite8(info->active_bank, info->bank);
+		}
+	}
+	mutex_unlock(&info->lock);
+	instr->state = MTD_ERASE_DONE;
+	mtd_erase_callback(instr);
+
+	return 0;
+}
+
+static int
+lp8x4x_sram_write(struct mtd_info *mtd, loff_t to, size_t len,
+		size_t *retlen, const u_char *b)
+{
+	struct lp8x4x_sram_info *info = mtd->priv;
+	unsigned bank = to >> 11;
+	unsigned offset = (to & 0x7ff) << 1;
+	loff_t i;
+
+	mutex_lock(&info->lock);
+	if (unlikely(bank != info->active_bank)) {
+		info->active_bank = bank;
+		iowrite8(bank, info->bank);
+	}
+	for (i = 0; i < len; i++) {
+		iowrite8(b[i], info->virt + offset);
+		offset += 2;
+		if (unlikely(offset == 0)) {
+			info->active_bank++;
+			iowrite8(info->active_bank, info->bank);
+		}
+	}
+	mutex_unlock(&info->lock);
+	*retlen = len;
+	return 0;
+}
+
+static int
+lp8x4x_sram_read(struct mtd_info *mtd, loff_t from, size_t len,
+		size_t *retlen, u_char *b)
+{
+	struct lp8x4x_sram_info *info = mtd->priv;
+	unsigned bank = from >> 11;
+	unsigned offset = (from & 0x7ff) << 1;
+	loff_t i;
+
+	mutex_lock(&info->lock);
+	if (unlikely(bank != info->active_bank)) {
+		info->active_bank = bank;
+		iowrite8(bank, info->bank);
+	}
+	for (i = 0; i < len; i++) {
+		b[i] = ioread8(info->virt + offset);
+		offset += 2;
+		if (unlikely(offset == 0)) {
+			info->active_bank++;
+			iowrite8(info->active_bank, info->bank);
+		}
+	}
+	mutex_unlock(&info->lock);
+	*retlen = len;
+	return 0;
+}
+
+static void
+lp8x4x_sram_sync(struct mtd_info *mtd)
+{
+}
+
+static struct of_device_id of_flash_match[] = {
+	{
+		.compatible	= "icpdas,sram-lp8x4x",
+	},
+	{ },
+};
+MODULE_DEVICE_TABLE(of, of_flash_match);
+
+static const char * const probe_types[] = {
+	"cmdlinepart", "RedBoot", "ofpart", "ofoldpart", NULL };
+
+static int
+lp8x4x_sram_probe(struct platform_device *pdev)
+{
+	const struct of_device_id *match;
+	struct lp8x4x_sram_info *info;
+	struct resource *r1, *r2;
+	char sz_str[16];
+	struct mtd_part_parser_data ppdata;
+	int err = 0;
+
+	match = of_match_device(of_flash_match, &pdev->dev);
+	if (!match)
+		return -EINVAL;
+
+	r1 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	r2 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	if (!r1 || !r2)
+		return -ENODEV;
+
+	info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
+	if (!info)
+		return -ENOMEM;
+
+	info->virt =  devm_ioremap_resource(&pdev->dev, r1);
+	if (!info->virt) {
+		dev_err(&pdev->dev, "Failed to ioremap %p\n",
+		       info->virt);
+		return -EFAULT;
+	}
+
+	info->bank = devm_ioremap_resource(&pdev->dev, r2);
+	if (!info->bank) {
+		dev_err(&pdev->dev, "Failed to ioremap %p\n",
+		       info->bank);
+		return -EFAULT;
+	}
+
+	info->mtd.priv = info;
+	info->mtd.name = "SRAM";
+	info->mtd.type = MTD_RAM;
+	info->mtd.flags = MTD_CAP_RAM;
+	info->mtd.size = resource_size(r1) << 7;
+	info->mtd.erasesize = 512;
+	info->mtd.writesize = 4;
+	info->mtd._erase = lp8x4x_sram_erase;
+	info->mtd._write = lp8x4x_sram_write;
+	info->mtd._read = lp8x4x_sram_read;
+	info->mtd._sync = lp8x4x_sram_sync;
+	info->mtd.owner = THIS_MODULE;
+
+	mutex_init(&info->lock);
+	iowrite8(info->active_bank, info->bank);
+	platform_set_drvdata(pdev, info);
+
+	ppdata.of_node = pdev->dev.of_node;
+	err = mtd_device_parse_register(&info->mtd, probe_types, &ppdata,
+			NULL, 0);
+
+	if (err < 0) {
+		dev_err(&pdev->dev, "Failed to register platform device\n");
+		return err;
+	}
+
+	string_get_size(info->mtd.size, STRING_UNITS_2, sz_str,
+			sizeof(sz_str));
+	dev_info(&pdev->dev, "using %s SRAM on LP-8X4X as %s\n", sz_str,
+			dev_name(&info->mtd.dev));
+	return 0;
+}
+
+static int
+lp8x4x_sram_remove(struct platform_device *dev)
+{
+	struct lp8x4x_sram_info *info = platform_get_drvdata(dev);
+
+	mtd_device_unregister(&info->mtd);
+	platform_set_drvdata(dev, NULL);
+	return 0;
+}
+
+static struct platform_driver lp8x4x_sram_driver = {
+	.driver = {
+		.name		= "sram-lp8x4x",
+		.owner		= THIS_MODULE,
+		.of_match_table = of_flash_match,
+	},
+	.probe		= lp8x4x_sram_probe,
+	.remove		= lp8x4x_sram_remove,
+};
+
+module_platform_driver(lp8x4x_sram_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Sergei Ianovich <ynvich@gmail.com>");
+MODULE_DESCRIPTION("MTD driver for SRAM on ICPDAS LP-8x4x");
-- 
1.8.4.3

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

* [PATCH v2 08/16] mtd: support BB SRAM on ICP DAS LP-8x4x
@ 2013-12-13  2:27           ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-13  2:27 UTC (permalink / raw)
  To: linux-arm-kernel

This provides an MTD device driver for 512kB of battery backed up SRAM
on ICPDAS LP-8X4X programmable automation controllers.

SRAM chip is connected via FPGA and is not accessible without a driver,
unlike flash memory which is wired to CPU MMU.

This SRAM becomes an excellent persisent storage of volatile process
data like counter values and sensor statuses. Storing those data in
flash or mmc card is not a viable solution.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
   v0..v2
   * use device tree
   * use devm helpers where possible

 arch/arm/boot/dts/pxa27x-lp8x4x.dts |   6 +
 arch/arm/configs/lp8x4x_defconfig   |   1 +
 drivers/mtd/devices/Kconfig         |  14 +++
 drivers/mtd/devices/Makefile        |   1 +
 drivers/mtd/devices/sram_lp8x4x.c   | 227 ++++++++++++++++++++++++++++++++++++
 5 files changed, 249 insertions(+)
 create mode 100644 drivers/mtd/devices/sram_lp8x4x.c

diff --git a/arch/arm/boot/dts/pxa27x-lp8x4x.dts b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
index 574e853..b7f8cfc 100644
--- a/arch/arm/boot/dts/pxa27x-lp8x4x.dts
+++ b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
@@ -59,6 +59,12 @@
 		device-width = <1>;
 	};
 
+	sram at 1700a000 {
+		compatible = "icpdas,sram-lp8x4x";
+		reg = <0x1700a000 0x1000
+		       0x1700901e 0x1>;
+	};
+
 	pxabus {
 		pxairq: interrupt-controller at 40d00000 {
 			marvell,intc-priority;
diff --git a/arch/arm/configs/lp8x4x_defconfig b/arch/arm/configs/lp8x4x_defconfig
index 57f2830..8fa871e 100644
--- a/arch/arm/configs/lp8x4x_defconfig
+++ b/arch/arm/configs/lp8x4x_defconfig
@@ -57,6 +57,7 @@ CONFIG_MTD_CFI_ADV_OPTIONS=y
 CONFIG_MTD_CFI_GEOMETRY=y
 CONFIG_MTD_CFI_INTELEXT=y
 CONFIG_MTD_PHYSMAP_OF=y
+CONFIG_MTD_SRAM_LP8X4X=y
 CONFIG_PROC_DEVICETREE=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_LOOP_MIN_COUNT=2
diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig
index 0128138..95f2075 100644
--- a/drivers/mtd/devices/Kconfig
+++ b/drivers/mtd/devices/Kconfig
@@ -217,4 +217,18 @@ config BCH_CONST_T
 	default 4
 endif
 
+config MTD_SRAM_LP8X4X
+	tristate "SRAM on ICPDAS LP-8X4X"
+	depends on OF && ARCH_PXA
+       ---help---
+	 This provides an MTD device driver for 512kiB of battery backed up SRAM
+	 on ICPDAS LP-8X4X programmable automation controllers.
+
+	 SRAM chip is connected via FPGA and is not accessible without a driver,
+	 unlike flash memory which is wired to CPU MMU.
+
+	 Say N, unless you plan to run this kernel on LP-8X4X.
+
+	 If you say M, the module will be called sram_lp8x4x.
+
 endmenu
diff --git a/drivers/mtd/devices/Makefile b/drivers/mtd/devices/Makefile
index d83bd73..56a74c9 100644
--- a/drivers/mtd/devices/Makefile
+++ b/drivers/mtd/devices/Makefile
@@ -16,6 +16,7 @@ obj-$(CONFIG_MTD_NAND_OMAP_BCH)	+= elm.o
 obj-$(CONFIG_MTD_SPEAR_SMI)	+= spear_smi.o
 obj-$(CONFIG_MTD_SST25L)	+= sst25l.o
 obj-$(CONFIG_MTD_BCM47XXSFLASH)	+= bcm47xxsflash.o
+obj-$(CONFIG_MTD_SRAM_LP8X4X)	+= sram_lp8x4x.o
 
 
 CFLAGS_docg3.o			+= -I$(src)
diff --git a/drivers/mtd/devices/sram_lp8x4x.c b/drivers/mtd/devices/sram_lp8x4x.c
new file mode 100644
index 0000000..9dc7149
--- /dev/null
+++ b/drivers/mtd/devices/sram_lp8x4x.c
@@ -0,0 +1,227 @@
+/*
+ *  linux/drivers/mtd/devices/lp8x4x_sram.c
+ *
+ *  MTD Driver for SRAM on ICPDAS LP-8x4x
+ *  Copyright (C) 2013 Sergei Ianovich <ynvich@gmail.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation or any later version.
+ */
+
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mtd/map.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/platform_device.h>
+#include <linux/of_device.h>
+#include <linux/slab.h>
+#include <linux/string_helpers.h>
+#include <linux/types.h>
+
+#include <asm/mach/flash.h>
+
+struct lp8x4x_sram_info {
+	void __iomem	*bank;
+	void __iomem	*virt;
+	struct mutex	lock;
+	unsigned	active_bank;
+	struct mtd_info	mtd;
+};
+
+static int
+lp8x4x_sram_erase(struct mtd_info *mtd, struct erase_info *instr)
+{
+	struct lp8x4x_sram_info *info = mtd->priv;
+	unsigned bank = instr->addr >> 11;
+	unsigned offset = (instr->addr & 0x7ff) << 1;
+	loff_t i;
+
+	mutex_lock(&info->lock);
+	if (unlikely(bank != info->active_bank)) {
+		info->active_bank = bank;
+		iowrite8(bank, info->bank);
+	}
+	for (i = 0; i < instr->len; i++) {
+		iowrite8(0xff, info->virt + offset);
+		offset += 2;
+		if (unlikely(offset == 0)) {
+			info->active_bank++;
+			iowrite8(info->active_bank, info->bank);
+		}
+	}
+	mutex_unlock(&info->lock);
+	instr->state = MTD_ERASE_DONE;
+	mtd_erase_callback(instr);
+
+	return 0;
+}
+
+static int
+lp8x4x_sram_write(struct mtd_info *mtd, loff_t to, size_t len,
+		size_t *retlen, const u_char *b)
+{
+	struct lp8x4x_sram_info *info = mtd->priv;
+	unsigned bank = to >> 11;
+	unsigned offset = (to & 0x7ff) << 1;
+	loff_t i;
+
+	mutex_lock(&info->lock);
+	if (unlikely(bank != info->active_bank)) {
+		info->active_bank = bank;
+		iowrite8(bank, info->bank);
+	}
+	for (i = 0; i < len; i++) {
+		iowrite8(b[i], info->virt + offset);
+		offset += 2;
+		if (unlikely(offset == 0)) {
+			info->active_bank++;
+			iowrite8(info->active_bank, info->bank);
+		}
+	}
+	mutex_unlock(&info->lock);
+	*retlen = len;
+	return 0;
+}
+
+static int
+lp8x4x_sram_read(struct mtd_info *mtd, loff_t from, size_t len,
+		size_t *retlen, u_char *b)
+{
+	struct lp8x4x_sram_info *info = mtd->priv;
+	unsigned bank = from >> 11;
+	unsigned offset = (from & 0x7ff) << 1;
+	loff_t i;
+
+	mutex_lock(&info->lock);
+	if (unlikely(bank != info->active_bank)) {
+		info->active_bank = bank;
+		iowrite8(bank, info->bank);
+	}
+	for (i = 0; i < len; i++) {
+		b[i] = ioread8(info->virt + offset);
+		offset += 2;
+		if (unlikely(offset == 0)) {
+			info->active_bank++;
+			iowrite8(info->active_bank, info->bank);
+		}
+	}
+	mutex_unlock(&info->lock);
+	*retlen = len;
+	return 0;
+}
+
+static void
+lp8x4x_sram_sync(struct mtd_info *mtd)
+{
+}
+
+static struct of_device_id of_flash_match[] = {
+	{
+		.compatible	= "icpdas,sram-lp8x4x",
+	},
+	{ },
+};
+MODULE_DEVICE_TABLE(of, of_flash_match);
+
+static const char * const probe_types[] = {
+	"cmdlinepart", "RedBoot", "ofpart", "ofoldpart", NULL };
+
+static int
+lp8x4x_sram_probe(struct platform_device *pdev)
+{
+	const struct of_device_id *match;
+	struct lp8x4x_sram_info *info;
+	struct resource *r1, *r2;
+	char sz_str[16];
+	struct mtd_part_parser_data ppdata;
+	int err = 0;
+
+	match = of_match_device(of_flash_match, &pdev->dev);
+	if (!match)
+		return -EINVAL;
+
+	r1 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	r2 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	if (!r1 || !r2)
+		return -ENODEV;
+
+	info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
+	if (!info)
+		return -ENOMEM;
+
+	info->virt =  devm_ioremap_resource(&pdev->dev, r1);
+	if (!info->virt) {
+		dev_err(&pdev->dev, "Failed to ioremap %p\n",
+		       info->virt);
+		return -EFAULT;
+	}
+
+	info->bank = devm_ioremap_resource(&pdev->dev, r2);
+	if (!info->bank) {
+		dev_err(&pdev->dev, "Failed to ioremap %p\n",
+		       info->bank);
+		return -EFAULT;
+	}
+
+	info->mtd.priv = info;
+	info->mtd.name = "SRAM";
+	info->mtd.type = MTD_RAM;
+	info->mtd.flags = MTD_CAP_RAM;
+	info->mtd.size = resource_size(r1) << 7;
+	info->mtd.erasesize = 512;
+	info->mtd.writesize = 4;
+	info->mtd._erase = lp8x4x_sram_erase;
+	info->mtd._write = lp8x4x_sram_write;
+	info->mtd._read = lp8x4x_sram_read;
+	info->mtd._sync = lp8x4x_sram_sync;
+	info->mtd.owner = THIS_MODULE;
+
+	mutex_init(&info->lock);
+	iowrite8(info->active_bank, info->bank);
+	platform_set_drvdata(pdev, info);
+
+	ppdata.of_node = pdev->dev.of_node;
+	err = mtd_device_parse_register(&info->mtd, probe_types, &ppdata,
+			NULL, 0);
+
+	if (err < 0) {
+		dev_err(&pdev->dev, "Failed to register platform device\n");
+		return err;
+	}
+
+	string_get_size(info->mtd.size, STRING_UNITS_2, sz_str,
+			sizeof(sz_str));
+	dev_info(&pdev->dev, "using %s SRAM on LP-8X4X as %s\n", sz_str,
+			dev_name(&info->mtd.dev));
+	return 0;
+}
+
+static int
+lp8x4x_sram_remove(struct platform_device *dev)
+{
+	struct lp8x4x_sram_info *info = platform_get_drvdata(dev);
+
+	mtd_device_unregister(&info->mtd);
+	platform_set_drvdata(dev, NULL);
+	return 0;
+}
+
+static struct platform_driver lp8x4x_sram_driver = {
+	.driver = {
+		.name		= "sram-lp8x4x",
+		.owner		= THIS_MODULE,
+		.of_match_table = of_flash_match,
+	},
+	.probe		= lp8x4x_sram_probe,
+	.remove		= lp8x4x_sram_remove,
+};
+
+module_platform_driver(lp8x4x_sram_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Sergei Ianovich <ynvich@gmail.com>");
+MODULE_DESCRIPTION("MTD driver for SRAM on ICPDAS LP-8x4x");
-- 
1.8.4.3

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

* [PATCH v2 09/16] ARM: pxa: support ICP DAS LP-8x4x FPGA irq
@ 2013-12-13  2:27           ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-13  2:27 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Arnd Bergmann, Linus Walleij, Rob Herring,
	Pawel Moll, Mark Rutland, Stephen Warren, Ian Campbell,
	Rob Landley, Russell King, Thomas Gleixner, Grant Likely,
	open list:OPEN FIRMWARE AND...,
	open list:DOCUMENTATION

ICP DAS LP-8x4x contains FPGA chip. The chip functions as a interrupt
source providing 16 additional interrupts among other things. The
interrupt lines are muxed to a GPIO pin. GPIO pins are in turn muxed
to a CPU interrupt line.

Until pxa is completely converted to device tree, it is impossible
to use IRQCHIP_DECLARE() and the irqdomain needs to added manually.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Arnd Bergmann <arnd@arndb.de>
CC: Linus Walleij <linus.walleij@linaro.org>
---
   v0..v2
   * extract irqchip and move to drivers/irqchip/
   * use device tree
   * use devm helpers where possible

 .../bindings/interrupt-controller/irq-lp8x4x.txt   |  49 +++++
 arch/arm/boot/dts/pxa27x-lp8x4x.dts                |  10 +
 drivers/irqchip/Kconfig                            |   5 +
 drivers/irqchip/Makefile                           |   1 +
 drivers/irqchip/irq-lp8x4x.c                       | 205 +++++++++++++++++++++
 5 files changed, 270 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/interrupt-controller/irq-lp8x4x.txt
 create mode 100644 drivers/irqchip/irq-lp8x4x.c

diff --git a/Documentation/devicetree/bindings/interrupt-controller/irq-lp8x4x.txt b/Documentation/devicetree/bindings/interrupt-controller/irq-lp8x4x.txt
new file mode 100644
index 0000000..c8940d2
--- /dev/null
+++ b/Documentation/devicetree/bindings/interrupt-controller/irq-lp8x4x.txt
@@ -0,0 +1,49 @@
+ICP DAS LP-8x4x FPGA Interrupt Controller
+
+ICP DAS LP-8x4x contains FPGA chip. The chip functions as a interrupt
+source providing 16 additional interrupts among other things.
+
+Required properties:
+- compatible : should be "icpdas,irq-lp8x4x"
+
+- reg: physical base address of the controller and length of memory mapped
+  region.
+
+- interrupt-controller : identifies the node as an interrupt controller
+
+- #interrupt-cells : should be 1
+
+- interrupts : should provide interrupt
+
+- interrupt-parent : should provide a link to interrupt controller either
+		     explicitly and implicitly from a parent node
+
+Example:
+
+	fpga: fpga@17000006 {
+		compatible = "icpdas,irq-lp8x4x";
+		reg = <0x17000006 0x16>;
+		interrupt-parent = <&gpio>;
+		interrupts = <3 IRQ_TYPE_EDGE_RISING>;
+		#interrupt-cells = <1>;
+		interrupt-controller;
+		status = "okay";
+	};
+
+	uart@17009050 {
+		compatible = "icpdas,uart-lp8x4x";
+		reg = <0x17009050 0x10
+		       0x17009030 0x02>;
+		interrupt-parent = <&fpga>;
+		interrupts = <13>;
+		status = "okay";
+	};
+
+	uart@17009060 {
+		compatible = "icpdas,uart-lp8x4x";
+		reg = <0x17009060 0x10
+		       0x17009032 0x02>;
+		interrupt-parent = <&fpga>;
+		interrupts = <14>;
+		status = "okay";
+	};
diff --git a/arch/arm/boot/dts/pxa27x-lp8x4x.dts b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
index b7f8cfc..2704760 100644
--- a/arch/arm/boot/dts/pxa27x-lp8x4x.dts
+++ b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
@@ -119,5 +119,15 @@
 			reg = <0x1700901c 0x1>;
 			status = "okay";
 		};
+
+		fpga: fpga@17009006 {
+			compatible = "icpdas,irq-lp8x4x";
+			reg = <0x17009006 0x16>;
+			interrupt-parent = <&gpio>;
+			interrupts = <3 IRQ_TYPE_EDGE_BOTH>;
+			#interrupt-cells = <1>;
+			interrupt-controller;
+			status = "okay";
+		};
 	};
 };
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index 3792a1a..7e22729 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -35,6 +35,11 @@ config IMGPDC_IRQ
 	select GENERIC_IRQ_CHIP
 	select IRQ_DOMAIN
 
+config LP8X4X_IRQ
+	bool
+	depends on OF
+	select IRQ_DOMAIN
+
 config ORION_IRQCHIP
 	bool
 	select IRQ_DOMAIN
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index c60b901..8a28927 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -22,3 +22,4 @@ obj-$(CONFIG_RENESAS_IRQC)		+= irq-renesas-irqc.o
 obj-$(CONFIG_VERSATILE_FPGA_IRQ)	+= irq-versatile-fpga.o
 obj-$(CONFIG_ARCH_VT8500)		+= irq-vt8500.o
 obj-$(CONFIG_TB10X_IRQC)		+= irq-tb10x.o
+obj-$(CONFIG_LP8X4X_IRQ)		+= irq-lp8x4x.o
diff --git a/drivers/irqchip/irq-lp8x4x.c b/drivers/irqchip/irq-lp8x4x.c
new file mode 100644
index 0000000..5d44880b
--- /dev/null
+++ b/drivers/irqchip/irq-lp8x4x.c
@@ -0,0 +1,205 @@
+/*
+ *  linux/drivers/irqchip/irq-lp8x4x.c
+ *
+ *  Support for ICP DAS LP-8x4x FPGA irq
+ *  Copyright (C) 2013 Sergei Ianovich <ynvich@gmail.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation or any later version.
+ */
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/irqchip/chained_irq.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+#define EOI			0x00000000
+#define INSINT			0x00000002
+#define ENSYSINT		0x00000004
+#define PRIMINT			0x00000006
+#define SECOINT			0x00000008
+#define ENRISEINT		0x0000000A
+#define CLRRISEINT		0x0000000C
+#define ENHILVINT		0x0000000E
+#define CLRHILVINT		0x00000010
+#define ENFALLINT		0x00000012
+#define CLRFALLINT		0x00000014
+#define LP8X4X_IRQ_MEM_SIZE	0x00000016
+
+static unsigned char irq_sys_enabled;
+static unsigned char irq_high_enabled;
+static void *base;
+static int irq_base;
+static int num_irq = 16;
+
+static void lp8x4x_mask_irq(struct irq_data *d)
+{
+	unsigned mask;
+	int irq = d->irq - irq_base;
+
+	if (irq < 0 || irq > 15) {
+		pr_err("lp8x4x: wrong irq handler for irq %i\n", d->irq);
+		return;
+	}
+
+	if (irq < 8) {
+		irq_high_enabled &= ~(1 << irq);
+
+		mask = ioread8(base + ENHILVINT);
+		mask &= ~(1 << irq);
+		iowrite8(mask, base + ENHILVINT);
+	} else {
+		irq -= 8;
+		irq_sys_enabled &= ~(1 << irq);
+
+		mask = ioread8(base + ENSYSINT);
+		mask &= ~(1 << irq);
+		iowrite8(mask, base + ENSYSINT);
+	}
+}
+
+static void lp8x4x_unmask_irq(struct irq_data *d)
+{
+	unsigned mask;
+	int irq = d->irq - irq_base;
+
+	if (irq < 0 || irq > 15) {
+		pr_err("wrong irq handler for irq %i\n", d->irq);
+		return;
+	}
+
+	if (irq < 8) {
+		irq_high_enabled |= 1 << irq;
+		mask = ioread8(base + CLRHILVINT);
+		mask |= 1 << irq;
+		iowrite8(mask, base + CLRHILVINT);
+
+		mask = ioread8(base + ENHILVINT);
+		mask |= 1 << irq;
+		iowrite8(mask, base + ENHILVINT);
+	} else {
+		irq -= 8;
+		irq_sys_enabled |= 1 << irq;
+
+		mask = ioread8(base + SECOINT);
+		mask |= 1 << irq;
+		iowrite8(mask, base + SECOINT);
+
+		mask = ioread8(base + ENSYSINT);
+		mask |= 1 << irq;
+		iowrite8(mask, base + ENSYSINT);
+	}
+}
+
+static struct irq_chip lp8x4x_irq_chip = {
+	.name			= "FPGA",
+	.irq_ack		= lp8x4x_mask_irq,
+	.irq_mask		= lp8x4x_mask_irq,
+	.irq_mask_ack		= lp8x4x_mask_irq,
+	.irq_unmask		= lp8x4x_unmask_irq,
+};
+
+static void lp8x4x_irq_handler(unsigned int irq, struct irq_desc *desc)
+{
+	int loop, n;
+	unsigned long mask;
+	struct irq_chip *chip = irq_desc_get_chip(desc);
+
+	chained_irq_enter(chip, desc);
+
+	do {
+		loop = 0;
+		mask = ioread8(base + CLRHILVINT) & 0xff;
+		mask |= (ioread8(base + SECOINT) & 0x1f) << 8;
+		mask |= (ioread8(base + PRIMINT) & 0xe0) << 8;
+		mask &= (irq_high_enabled | (irq_sys_enabled << 8));
+		for_each_set_bit(n, &mask, BITS_PER_LONG) {
+			loop = 1;
+
+			generic_handle_irq(irq_base + n);
+		}
+	} while (loop);
+
+	iowrite8(0, base + EOI);
+	chained_irq_exit(chip, desc);
+}
+
+static int lp8x4x_irq_domain_map(struct irq_domain *d, unsigned int irq,
+				 irq_hw_number_t hw)
+{
+	irq_set_chip_and_handler(irq, &lp8x4x_irq_chip,
+				 handle_level_irq);
+	set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+	return 0;
+}
+
+const struct irq_domain_ops lp8x4x_irq_domain_ops = {
+	.map	= lp8x4x_irq_domain_map,
+	.xlate	= irq_domain_xlate_onecell,
+};
+
+static struct of_device_id lp8x4x_irq_dt_ids[] = {
+	{ .compatible = "icpdas,irq-lp8x4x", },
+	{}
+};
+
+static int lp8x4x_irq_probe(struct platform_device *pdev)
+{
+	struct resource *rm, *ri;
+	struct device_node *np = pdev->dev.of_node;
+	struct irq_domain *domain;
+
+	rm = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	ri = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!rm || !ri || resource_size(rm) < LP8X4X_IRQ_MEM_SIZE)
+		return -ENODEV;
+
+	base = devm_ioremap_resource(&pdev->dev, rm);
+	if (!base) {
+		dev_err(&pdev->dev, "Failed to ioremap %p\n", base);
+		return -EFAULT;
+	}
+
+	irq_base = irq_alloc_descs(-1, 0, num_irq, 0);
+	if (irq_base < 0) {
+		dev_err(&pdev->dev, "Failed to allocate IRQ numbers\n");
+		return irq_base;
+	}
+
+	domain = irq_domain_add_legacy(np, num_irq, irq_base, 0,
+				       &lp8x4x_irq_domain_ops, NULL);
+	if (!domain) {
+		dev_err(&pdev->dev, "Failed to add IRQ domain\n");
+		return -ENOMEM;
+	}
+
+	iowrite8(0, base + CLRRISEINT);
+	iowrite8(0, base + ENRISEINT);
+	iowrite8(0, base + CLRFALLINT);
+	iowrite8(0, base + ENFALLINT);
+	iowrite8(0, base + CLRHILVINT);
+	iowrite8(0, base + ENHILVINT);
+	iowrite8(0, base + ENSYSINT);
+	iowrite8(0, base + SECOINT);
+
+	irq_set_chained_handler(ri->start, lp8x4x_irq_handler);
+
+	return 0;
+}
+
+static struct platform_driver lp8x4x_irq_driver = {
+	.probe		= lp8x4x_irq_probe,
+	.driver		= {
+		.name	= "irq-lp8x4x",
+		.of_match_table = lp8x4x_irq_dt_ids,
+	},
+};
+
+static int __init lp8x4x_irq_init(void)
+{
+	return platform_driver_register(&lp8x4x_irq_driver);
+}
+postcore_initcall(lp8x4x_irq_init);
-- 
1.8.4.3


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

* [PATCH v2 09/16] ARM: pxa: support ICP DAS LP-8x4x FPGA irq
@ 2013-12-13  2:27           ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-13  2:27 UTC (permalink / raw)
  To: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
  Cc: Sergei Ianovich, Arnd Bergmann, Linus Walleij, Rob Herring,
	Pawel Moll, Mark Rutland, Stephen Warren, Ian Campbell,
	Rob Landley, Russell King, Thomas Gleixner, Grant Likely,
	open list:OPEN FIRMWARE AND...,
	open list:DOCUMENTATION

ICP DAS LP-8x4x contains FPGA chip. The chip functions as a interrupt
source providing 16 additional interrupts among other things. The
interrupt lines are muxed to a GPIO pin. GPIO pins are in turn muxed
to a CPU interrupt line.

Until pxa is completely converted to device tree, it is impossible
to use IRQCHIP_DECLARE() and the irqdomain needs to added manually.

Signed-off-by: Sergei Ianovich <ynvich-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
CC: Arnd Bergmann <arnd-r2nGTMty4D4@public.gmane.org>
CC: Linus Walleij <linus.walleij-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
---
   v0..v2
   * extract irqchip and move to drivers/irqchip/
   * use device tree
   * use devm helpers where possible

 .../bindings/interrupt-controller/irq-lp8x4x.txt   |  49 +++++
 arch/arm/boot/dts/pxa27x-lp8x4x.dts                |  10 +
 drivers/irqchip/Kconfig                            |   5 +
 drivers/irqchip/Makefile                           |   1 +
 drivers/irqchip/irq-lp8x4x.c                       | 205 +++++++++++++++++++++
 5 files changed, 270 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/interrupt-controller/irq-lp8x4x.txt
 create mode 100644 drivers/irqchip/irq-lp8x4x.c

diff --git a/Documentation/devicetree/bindings/interrupt-controller/irq-lp8x4x.txt b/Documentation/devicetree/bindings/interrupt-controller/irq-lp8x4x.txt
new file mode 100644
index 0000000..c8940d2
--- /dev/null
+++ b/Documentation/devicetree/bindings/interrupt-controller/irq-lp8x4x.txt
@@ -0,0 +1,49 @@
+ICP DAS LP-8x4x FPGA Interrupt Controller
+
+ICP DAS LP-8x4x contains FPGA chip. The chip functions as a interrupt
+source providing 16 additional interrupts among other things.
+
+Required properties:
+- compatible : should be "icpdas,irq-lp8x4x"
+
+- reg: physical base address of the controller and length of memory mapped
+  region.
+
+- interrupt-controller : identifies the node as an interrupt controller
+
+- #interrupt-cells : should be 1
+
+- interrupts : should provide interrupt
+
+- interrupt-parent : should provide a link to interrupt controller either
+		     explicitly and implicitly from a parent node
+
+Example:
+
+	fpga: fpga@17000006 {
+		compatible = "icpdas,irq-lp8x4x";
+		reg = <0x17000006 0x16>;
+		interrupt-parent = <&gpio>;
+		interrupts = <3 IRQ_TYPE_EDGE_RISING>;
+		#interrupt-cells = <1>;
+		interrupt-controller;
+		status = "okay";
+	};
+
+	uart@17009050 {
+		compatible = "icpdas,uart-lp8x4x";
+		reg = <0x17009050 0x10
+		       0x17009030 0x02>;
+		interrupt-parent = <&fpga>;
+		interrupts = <13>;
+		status = "okay";
+	};
+
+	uart@17009060 {
+		compatible = "icpdas,uart-lp8x4x";
+		reg = <0x17009060 0x10
+		       0x17009032 0x02>;
+		interrupt-parent = <&fpga>;
+		interrupts = <14>;
+		status = "okay";
+	};
diff --git a/arch/arm/boot/dts/pxa27x-lp8x4x.dts b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
index b7f8cfc..2704760 100644
--- a/arch/arm/boot/dts/pxa27x-lp8x4x.dts
+++ b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
@@ -119,5 +119,15 @@
 			reg = <0x1700901c 0x1>;
 			status = "okay";
 		};
+
+		fpga: fpga@17009006 {
+			compatible = "icpdas,irq-lp8x4x";
+			reg = <0x17009006 0x16>;
+			interrupt-parent = <&gpio>;
+			interrupts = <3 IRQ_TYPE_EDGE_BOTH>;
+			#interrupt-cells = <1>;
+			interrupt-controller;
+			status = "okay";
+		};
 	};
 };
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index 3792a1a..7e22729 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -35,6 +35,11 @@ config IMGPDC_IRQ
 	select GENERIC_IRQ_CHIP
 	select IRQ_DOMAIN
 
+config LP8X4X_IRQ
+	bool
+	depends on OF
+	select IRQ_DOMAIN
+
 config ORION_IRQCHIP
 	bool
 	select IRQ_DOMAIN
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index c60b901..8a28927 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -22,3 +22,4 @@ obj-$(CONFIG_RENESAS_IRQC)		+= irq-renesas-irqc.o
 obj-$(CONFIG_VERSATILE_FPGA_IRQ)	+= irq-versatile-fpga.o
 obj-$(CONFIG_ARCH_VT8500)		+= irq-vt8500.o
 obj-$(CONFIG_TB10X_IRQC)		+= irq-tb10x.o
+obj-$(CONFIG_LP8X4X_IRQ)		+= irq-lp8x4x.o
diff --git a/drivers/irqchip/irq-lp8x4x.c b/drivers/irqchip/irq-lp8x4x.c
new file mode 100644
index 0000000..5d44880b
--- /dev/null
+++ b/drivers/irqchip/irq-lp8x4x.c
@@ -0,0 +1,205 @@
+/*
+ *  linux/drivers/irqchip/irq-lp8x4x.c
+ *
+ *  Support for ICP DAS LP-8x4x FPGA irq
+ *  Copyright (C) 2013 Sergei Ianovich <ynvich-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation or any later version.
+ */
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/irqchip/chained_irq.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+#define EOI			0x00000000
+#define INSINT			0x00000002
+#define ENSYSINT		0x00000004
+#define PRIMINT			0x00000006
+#define SECOINT			0x00000008
+#define ENRISEINT		0x0000000A
+#define CLRRISEINT		0x0000000C
+#define ENHILVINT		0x0000000E
+#define CLRHILVINT		0x00000010
+#define ENFALLINT		0x00000012
+#define CLRFALLINT		0x00000014
+#define LP8X4X_IRQ_MEM_SIZE	0x00000016
+
+static unsigned char irq_sys_enabled;
+static unsigned char irq_high_enabled;
+static void *base;
+static int irq_base;
+static int num_irq = 16;
+
+static void lp8x4x_mask_irq(struct irq_data *d)
+{
+	unsigned mask;
+	int irq = d->irq - irq_base;
+
+	if (irq < 0 || irq > 15) {
+		pr_err("lp8x4x: wrong irq handler for irq %i\n", d->irq);
+		return;
+	}
+
+	if (irq < 8) {
+		irq_high_enabled &= ~(1 << irq);
+
+		mask = ioread8(base + ENHILVINT);
+		mask &= ~(1 << irq);
+		iowrite8(mask, base + ENHILVINT);
+	} else {
+		irq -= 8;
+		irq_sys_enabled &= ~(1 << irq);
+
+		mask = ioread8(base + ENSYSINT);
+		mask &= ~(1 << irq);
+		iowrite8(mask, base + ENSYSINT);
+	}
+}
+
+static void lp8x4x_unmask_irq(struct irq_data *d)
+{
+	unsigned mask;
+	int irq = d->irq - irq_base;
+
+	if (irq < 0 || irq > 15) {
+		pr_err("wrong irq handler for irq %i\n", d->irq);
+		return;
+	}
+
+	if (irq < 8) {
+		irq_high_enabled |= 1 << irq;
+		mask = ioread8(base + CLRHILVINT);
+		mask |= 1 << irq;
+		iowrite8(mask, base + CLRHILVINT);
+
+		mask = ioread8(base + ENHILVINT);
+		mask |= 1 << irq;
+		iowrite8(mask, base + ENHILVINT);
+	} else {
+		irq -= 8;
+		irq_sys_enabled |= 1 << irq;
+
+		mask = ioread8(base + SECOINT);
+		mask |= 1 << irq;
+		iowrite8(mask, base + SECOINT);
+
+		mask = ioread8(base + ENSYSINT);
+		mask |= 1 << irq;
+		iowrite8(mask, base + ENSYSINT);
+	}
+}
+
+static struct irq_chip lp8x4x_irq_chip = {
+	.name			= "FPGA",
+	.irq_ack		= lp8x4x_mask_irq,
+	.irq_mask		= lp8x4x_mask_irq,
+	.irq_mask_ack		= lp8x4x_mask_irq,
+	.irq_unmask		= lp8x4x_unmask_irq,
+};
+
+static void lp8x4x_irq_handler(unsigned int irq, struct irq_desc *desc)
+{
+	int loop, n;
+	unsigned long mask;
+	struct irq_chip *chip = irq_desc_get_chip(desc);
+
+	chained_irq_enter(chip, desc);
+
+	do {
+		loop = 0;
+		mask = ioread8(base + CLRHILVINT) & 0xff;
+		mask |= (ioread8(base + SECOINT) & 0x1f) << 8;
+		mask |= (ioread8(base + PRIMINT) & 0xe0) << 8;
+		mask &= (irq_high_enabled | (irq_sys_enabled << 8));
+		for_each_set_bit(n, &mask, BITS_PER_LONG) {
+			loop = 1;
+
+			generic_handle_irq(irq_base + n);
+		}
+	} while (loop);
+
+	iowrite8(0, base + EOI);
+	chained_irq_exit(chip, desc);
+}
+
+static int lp8x4x_irq_domain_map(struct irq_domain *d, unsigned int irq,
+				 irq_hw_number_t hw)
+{
+	irq_set_chip_and_handler(irq, &lp8x4x_irq_chip,
+				 handle_level_irq);
+	set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+	return 0;
+}
+
+const struct irq_domain_ops lp8x4x_irq_domain_ops = {
+	.map	= lp8x4x_irq_domain_map,
+	.xlate	= irq_domain_xlate_onecell,
+};
+
+static struct of_device_id lp8x4x_irq_dt_ids[] = {
+	{ .compatible = "icpdas,irq-lp8x4x", },
+	{}
+};
+
+static int lp8x4x_irq_probe(struct platform_device *pdev)
+{
+	struct resource *rm, *ri;
+	struct device_node *np = pdev->dev.of_node;
+	struct irq_domain *domain;
+
+	rm = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	ri = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!rm || !ri || resource_size(rm) < LP8X4X_IRQ_MEM_SIZE)
+		return -ENODEV;
+
+	base = devm_ioremap_resource(&pdev->dev, rm);
+	if (!base) {
+		dev_err(&pdev->dev, "Failed to ioremap %p\n", base);
+		return -EFAULT;
+	}
+
+	irq_base = irq_alloc_descs(-1, 0, num_irq, 0);
+	if (irq_base < 0) {
+		dev_err(&pdev->dev, "Failed to allocate IRQ numbers\n");
+		return irq_base;
+	}
+
+	domain = irq_domain_add_legacy(np, num_irq, irq_base, 0,
+				       &lp8x4x_irq_domain_ops, NULL);
+	if (!domain) {
+		dev_err(&pdev->dev, "Failed to add IRQ domain\n");
+		return -ENOMEM;
+	}
+
+	iowrite8(0, base + CLRRISEINT);
+	iowrite8(0, base + ENRISEINT);
+	iowrite8(0, base + CLRFALLINT);
+	iowrite8(0, base + ENFALLINT);
+	iowrite8(0, base + CLRHILVINT);
+	iowrite8(0, base + ENHILVINT);
+	iowrite8(0, base + ENSYSINT);
+	iowrite8(0, base + SECOINT);
+
+	irq_set_chained_handler(ri->start, lp8x4x_irq_handler);
+
+	return 0;
+}
+
+static struct platform_driver lp8x4x_irq_driver = {
+	.probe		= lp8x4x_irq_probe,
+	.driver		= {
+		.name	= "irq-lp8x4x",
+		.of_match_table = lp8x4x_irq_dt_ids,
+	},
+};
+
+static int __init lp8x4x_irq_init(void)
+{
+	return platform_driver_register(&lp8x4x_irq_driver);
+}
+postcore_initcall(lp8x4x_irq_init);
-- 
1.8.4.3

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH v2 09/16] ARM: pxa: support ICP DAS LP-8x4x FPGA irq
@ 2013-12-13  2:27           ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-13  2:27 UTC (permalink / raw)
  To: linux-arm-kernel

ICP DAS LP-8x4x contains FPGA chip. The chip functions as a interrupt
source providing 16 additional interrupts among other things. The
interrupt lines are muxed to a GPIO pin. GPIO pins are in turn muxed
to a CPU interrupt line.

Until pxa is completely converted to device tree, it is impossible
to use IRQCHIP_DECLARE() and the irqdomain needs to added manually.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Arnd Bergmann <arnd@arndb.de>
CC: Linus Walleij <linus.walleij@linaro.org>
---
   v0..v2
   * extract irqchip and move to drivers/irqchip/
   * use device tree
   * use devm helpers where possible

 .../bindings/interrupt-controller/irq-lp8x4x.txt   |  49 +++++
 arch/arm/boot/dts/pxa27x-lp8x4x.dts                |  10 +
 drivers/irqchip/Kconfig                            |   5 +
 drivers/irqchip/Makefile                           |   1 +
 drivers/irqchip/irq-lp8x4x.c                       | 205 +++++++++++++++++++++
 5 files changed, 270 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/interrupt-controller/irq-lp8x4x.txt
 create mode 100644 drivers/irqchip/irq-lp8x4x.c

diff --git a/Documentation/devicetree/bindings/interrupt-controller/irq-lp8x4x.txt b/Documentation/devicetree/bindings/interrupt-controller/irq-lp8x4x.txt
new file mode 100644
index 0000000..c8940d2
--- /dev/null
+++ b/Documentation/devicetree/bindings/interrupt-controller/irq-lp8x4x.txt
@@ -0,0 +1,49 @@
+ICP DAS LP-8x4x FPGA Interrupt Controller
+
+ICP DAS LP-8x4x contains FPGA chip. The chip functions as a interrupt
+source providing 16 additional interrupts among other things.
+
+Required properties:
+- compatible : should be "icpdas,irq-lp8x4x"
+
+- reg: physical base address of the controller and length of memory mapped
+  region.
+
+- interrupt-controller : identifies the node as an interrupt controller
+
+- #interrupt-cells : should be 1
+
+- interrupts : should provide interrupt
+
+- interrupt-parent : should provide a link to interrupt controller either
+		     explicitly and implicitly from a parent node
+
+Example:
+
+	fpga: fpga at 17000006 {
+		compatible = "icpdas,irq-lp8x4x";
+		reg = <0x17000006 0x16>;
+		interrupt-parent = <&gpio>;
+		interrupts = <3 IRQ_TYPE_EDGE_RISING>;
+		#interrupt-cells = <1>;
+		interrupt-controller;
+		status = "okay";
+	};
+
+	uart at 17009050 {
+		compatible = "icpdas,uart-lp8x4x";
+		reg = <0x17009050 0x10
+		       0x17009030 0x02>;
+		interrupt-parent = <&fpga>;
+		interrupts = <13>;
+		status = "okay";
+	};
+
+	uart at 17009060 {
+		compatible = "icpdas,uart-lp8x4x";
+		reg = <0x17009060 0x10
+		       0x17009032 0x02>;
+		interrupt-parent = <&fpga>;
+		interrupts = <14>;
+		status = "okay";
+	};
diff --git a/arch/arm/boot/dts/pxa27x-lp8x4x.dts b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
index b7f8cfc..2704760 100644
--- a/arch/arm/boot/dts/pxa27x-lp8x4x.dts
+++ b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
@@ -119,5 +119,15 @@
 			reg = <0x1700901c 0x1>;
 			status = "okay";
 		};
+
+		fpga: fpga at 17009006 {
+			compatible = "icpdas,irq-lp8x4x";
+			reg = <0x17009006 0x16>;
+			interrupt-parent = <&gpio>;
+			interrupts = <3 IRQ_TYPE_EDGE_BOTH>;
+			#interrupt-cells = <1>;
+			interrupt-controller;
+			status = "okay";
+		};
 	};
 };
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index 3792a1a..7e22729 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -35,6 +35,11 @@ config IMGPDC_IRQ
 	select GENERIC_IRQ_CHIP
 	select IRQ_DOMAIN
 
+config LP8X4X_IRQ
+	bool
+	depends on OF
+	select IRQ_DOMAIN
+
 config ORION_IRQCHIP
 	bool
 	select IRQ_DOMAIN
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index c60b901..8a28927 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -22,3 +22,4 @@ obj-$(CONFIG_RENESAS_IRQC)		+= irq-renesas-irqc.o
 obj-$(CONFIG_VERSATILE_FPGA_IRQ)	+= irq-versatile-fpga.o
 obj-$(CONFIG_ARCH_VT8500)		+= irq-vt8500.o
 obj-$(CONFIG_TB10X_IRQC)		+= irq-tb10x.o
+obj-$(CONFIG_LP8X4X_IRQ)		+= irq-lp8x4x.o
diff --git a/drivers/irqchip/irq-lp8x4x.c b/drivers/irqchip/irq-lp8x4x.c
new file mode 100644
index 0000000..5d44880b
--- /dev/null
+++ b/drivers/irqchip/irq-lp8x4x.c
@@ -0,0 +1,205 @@
+/*
+ *  linux/drivers/irqchip/irq-lp8x4x.c
+ *
+ *  Support for ICP DAS LP-8x4x FPGA irq
+ *  Copyright (C) 2013 Sergei Ianovich <ynvich@gmail.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation or any later version.
+ */
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/irqchip/chained_irq.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+#define EOI			0x00000000
+#define INSINT			0x00000002
+#define ENSYSINT		0x00000004
+#define PRIMINT			0x00000006
+#define SECOINT			0x00000008
+#define ENRISEINT		0x0000000A
+#define CLRRISEINT		0x0000000C
+#define ENHILVINT		0x0000000E
+#define CLRHILVINT		0x00000010
+#define ENFALLINT		0x00000012
+#define CLRFALLINT		0x00000014
+#define LP8X4X_IRQ_MEM_SIZE	0x00000016
+
+static unsigned char irq_sys_enabled;
+static unsigned char irq_high_enabled;
+static void *base;
+static int irq_base;
+static int num_irq = 16;
+
+static void lp8x4x_mask_irq(struct irq_data *d)
+{
+	unsigned mask;
+	int irq = d->irq - irq_base;
+
+	if (irq < 0 || irq > 15) {
+		pr_err("lp8x4x: wrong irq handler for irq %i\n", d->irq);
+		return;
+	}
+
+	if (irq < 8) {
+		irq_high_enabled &= ~(1 << irq);
+
+		mask = ioread8(base + ENHILVINT);
+		mask &= ~(1 << irq);
+		iowrite8(mask, base + ENHILVINT);
+	} else {
+		irq -= 8;
+		irq_sys_enabled &= ~(1 << irq);
+
+		mask = ioread8(base + ENSYSINT);
+		mask &= ~(1 << irq);
+		iowrite8(mask, base + ENSYSINT);
+	}
+}
+
+static void lp8x4x_unmask_irq(struct irq_data *d)
+{
+	unsigned mask;
+	int irq = d->irq - irq_base;
+
+	if (irq < 0 || irq > 15) {
+		pr_err("wrong irq handler for irq %i\n", d->irq);
+		return;
+	}
+
+	if (irq < 8) {
+		irq_high_enabled |= 1 << irq;
+		mask = ioread8(base + CLRHILVINT);
+		mask |= 1 << irq;
+		iowrite8(mask, base + CLRHILVINT);
+
+		mask = ioread8(base + ENHILVINT);
+		mask |= 1 << irq;
+		iowrite8(mask, base + ENHILVINT);
+	} else {
+		irq -= 8;
+		irq_sys_enabled |= 1 << irq;
+
+		mask = ioread8(base + SECOINT);
+		mask |= 1 << irq;
+		iowrite8(mask, base + SECOINT);
+
+		mask = ioread8(base + ENSYSINT);
+		mask |= 1 << irq;
+		iowrite8(mask, base + ENSYSINT);
+	}
+}
+
+static struct irq_chip lp8x4x_irq_chip = {
+	.name			= "FPGA",
+	.irq_ack		= lp8x4x_mask_irq,
+	.irq_mask		= lp8x4x_mask_irq,
+	.irq_mask_ack		= lp8x4x_mask_irq,
+	.irq_unmask		= lp8x4x_unmask_irq,
+};
+
+static void lp8x4x_irq_handler(unsigned int irq, struct irq_desc *desc)
+{
+	int loop, n;
+	unsigned long mask;
+	struct irq_chip *chip = irq_desc_get_chip(desc);
+
+	chained_irq_enter(chip, desc);
+
+	do {
+		loop = 0;
+		mask = ioread8(base + CLRHILVINT) & 0xff;
+		mask |= (ioread8(base + SECOINT) & 0x1f) << 8;
+		mask |= (ioread8(base + PRIMINT) & 0xe0) << 8;
+		mask &= (irq_high_enabled | (irq_sys_enabled << 8));
+		for_each_set_bit(n, &mask, BITS_PER_LONG) {
+			loop = 1;
+
+			generic_handle_irq(irq_base + n);
+		}
+	} while (loop);
+
+	iowrite8(0, base + EOI);
+	chained_irq_exit(chip, desc);
+}
+
+static int lp8x4x_irq_domain_map(struct irq_domain *d, unsigned int irq,
+				 irq_hw_number_t hw)
+{
+	irq_set_chip_and_handler(irq, &lp8x4x_irq_chip,
+				 handle_level_irq);
+	set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+	return 0;
+}
+
+const struct irq_domain_ops lp8x4x_irq_domain_ops = {
+	.map	= lp8x4x_irq_domain_map,
+	.xlate	= irq_domain_xlate_onecell,
+};
+
+static struct of_device_id lp8x4x_irq_dt_ids[] = {
+	{ .compatible = "icpdas,irq-lp8x4x", },
+	{}
+};
+
+static int lp8x4x_irq_probe(struct platform_device *pdev)
+{
+	struct resource *rm, *ri;
+	struct device_node *np = pdev->dev.of_node;
+	struct irq_domain *domain;
+
+	rm = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	ri = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!rm || !ri || resource_size(rm) < LP8X4X_IRQ_MEM_SIZE)
+		return -ENODEV;
+
+	base = devm_ioremap_resource(&pdev->dev, rm);
+	if (!base) {
+		dev_err(&pdev->dev, "Failed to ioremap %p\n", base);
+		return -EFAULT;
+	}
+
+	irq_base = irq_alloc_descs(-1, 0, num_irq, 0);
+	if (irq_base < 0) {
+		dev_err(&pdev->dev, "Failed to allocate IRQ numbers\n");
+		return irq_base;
+	}
+
+	domain = irq_domain_add_legacy(np, num_irq, irq_base, 0,
+				       &lp8x4x_irq_domain_ops, NULL);
+	if (!domain) {
+		dev_err(&pdev->dev, "Failed to add IRQ domain\n");
+		return -ENOMEM;
+	}
+
+	iowrite8(0, base + CLRRISEINT);
+	iowrite8(0, base + ENRISEINT);
+	iowrite8(0, base + CLRFALLINT);
+	iowrite8(0, base + ENFALLINT);
+	iowrite8(0, base + CLRHILVINT);
+	iowrite8(0, base + ENHILVINT);
+	iowrite8(0, base + ENSYSINT);
+	iowrite8(0, base + SECOINT);
+
+	irq_set_chained_handler(ri->start, lp8x4x_irq_handler);
+
+	return 0;
+}
+
+static struct platform_driver lp8x4x_irq_driver = {
+	.probe		= lp8x4x_irq_probe,
+	.driver		= {
+		.name	= "irq-lp8x4x",
+		.of_match_table = lp8x4x_irq_dt_ids,
+	},
+};
+
+static int __init lp8x4x_irq_init(void)
+{
+	return platform_driver_register(&lp8x4x_irq_driver);
+}
+postcore_initcall(lp8x4x_irq_init);
-- 
1.8.4.3

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

* [PATCH v2 10/16] serial: support for 16550A serial ports on LP-8x4x
  2013-12-13  2:27         ` Sergei Ianovich
  (?)
@ 2013-12-13  2:27           ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-13  2:27 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Heikki Krogerus, Rob Herring, Pawel Moll,
	Mark Rutland, Stephen Warren, Ian Campbell, Rob Landley,
	Russell King, Greg Kroah-Hartman, Jiri Slaby, Grant Likely,
	Paul Bolle, James Cameron, open list:OPEN FIRMWARE AND...,
	open list:DOCUMENTATION, open list:SERIAL DRIVERS

The patch adds support for 3 additional LP-8x4x built-in serial
ports.

The device can also host up to 8 extension cards with 4 serial ports
on each card for a total of 35 ports. However, I don't have
the hardware to test extension cards, so they are not supported, yet.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Heikki Krogerus <heikki.krogerus@linux.intel.com>
---
   v0..v2
   * register platform driver instead of platform device
   * use device tree
   * use devm helpers where possible

 .../devicetree/bindings/serial/lp8x4x-serial.txt   |  35 +++++
 arch/arm/boot/dts/pxa27x-lp8x4x.dts                |  27 ++++
 arch/arm/configs/lp8x4x_defconfig                  |   1 +
 drivers/tty/serial/8250/8250_lp8x4x.c              | 162 +++++++++++++++++++++
 drivers/tty/serial/8250/Kconfig                    |  12 ++
 drivers/tty/serial/8250/Makefile                   |   1 +
 6 files changed, 238 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/serial/lp8x4x-serial.txt
 create mode 100644 drivers/tty/serial/8250/8250_lp8x4x.c

diff --git a/Documentation/devicetree/bindings/serial/lp8x4x-serial.txt b/Documentation/devicetree/bindings/serial/lp8x4x-serial.txt
new file mode 100644
index 0000000..eed4ffc
--- /dev/null
+++ b/Documentation/devicetree/bindings/serial/lp8x4x-serial.txt
@@ -0,0 +1,35 @@
+UART ports on ICP DAS LP-8x4x
+
+ICP DAS LP-8x4x contains three additional serial ports interfaced via
+Analog Devices ADM213EA chips in addition to 3 serial ports on PXA CPU.
+
+Required properties:
+- compatible : should be "icpdas,uart-lp8x4x"
+
+- reg : should provide 16 byte man IO memory region and 1 byte region for
+	termios
+
+- interrupts : should provide interrupt
+
+- interrupt-parent : should provide a link to interrupt controller either
+		     explicitly and implicitly from a parent node
+
+Examples (from pxa27x-lp8x4x.dts):
+
+		uart@17009050 {
+			compatible = "icpdas,uart-lp8x4x";
+			reg = <0x17009050 0x10
+			       0x17009030 0x02>;
+			interrupt-parent = <&fpga>;
+			interrupts = <13>;
+			status = "okay";
+		};
+
+		uart@17009060 {
+			compatible = "icpdas,uart-lp8x4x";
+			reg = <0x17009060 0x10
+			       0x17009032 0x02>;
+			interrupt-parent = <&fpga>;
+			interrupts = <14>;
+			status = "okay";
+		};
diff --git a/arch/arm/boot/dts/pxa27x-lp8x4x.dts b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
index 2704760..4bcf400 100644
--- a/arch/arm/boot/dts/pxa27x-lp8x4x.dts
+++ b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
@@ -129,5 +129,32 @@
 			interrupt-controller;
 			status = "okay";
 		};
+
+		uart@17009050 {
+			compatible = "icpdas,uart-lp8x4x";
+			reg = <0x17009050 0x10
+			       0x17009030 0x02>;
+			interrupt-parent = <&fpga>;
+			interrupts = <13>;
+			status = "okay";
+		};
+
+		uart@17009060 {
+			compatible = "icpdas,uart-lp8x4x";
+			reg = <0x17009060 0x10
+			       0x17009032 0x02>;
+			interrupt-parent = <&fpga>;
+			interrupts = <14>;
+			status = "okay";
+		};
+
+		uart@17009070 {
+			compatible = "icpdas,uart-lp8x4x";
+			reg = <0x17009070 0x10
+			       0x17009034 0x02>;
+			interrupt-parent = <&fpga>;
+			interrupts = <15>;
+			status = "okay";
+		};
 	};
 };
diff --git a/arch/arm/configs/lp8x4x_defconfig b/arch/arm/configs/lp8x4x_defconfig
index 8fa871e..ea1a4b8 100644
--- a/arch/arm/configs/lp8x4x_defconfig
+++ b/arch/arm/configs/lp8x4x_defconfig
@@ -111,6 +111,7 @@ CONFIG_SERIAL_8250_EXTENDED=y
 CONFIG_SERIAL_8250_MANY_PORTS=y
 CONFIG_SERIAL_8250_SHARE_IRQ=y
 CONFIG_SERIAL_PXA=y
+CONFIG_SERIAL_8250_LP8X4X=m
 CONFIG_HW_RANDOM=y
 CONFIG_I2C=m
 # CONFIG_I2C_COMPAT is not set
diff --git a/drivers/tty/serial/8250/8250_lp8x4x.c b/drivers/tty/serial/8250/8250_lp8x4x.c
new file mode 100644
index 0000000..ec2f215
--- /dev/null
+++ b/drivers/tty/serial/8250/8250_lp8x4x.c
@@ -0,0 +1,162 @@
+/*  linux/drivers/tty/serial/8250/8250_lp8x4x.c
+ *
+ *  Support for 16550A serial ports on ICP DAS LP-8x4x
+ *
+ *  Copyright (C) 2013 Sergei Ianovich <ynvich@gmail.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/module.h>
+#include <linux/serial_8250.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+struct lp8x4x_serial_data {
+	int			line;
+	void			*ios_mem;
+};
+
+static void lp8x4x_serial_set_termios(struct uart_port *port,
+		struct ktermios *termios, struct ktermios *old)
+{
+	unsigned int len;
+	unsigned int baud;
+	struct lp8x4x_serial_data *data = port->private_data;
+
+	switch (termios->c_cflag & CSIZE) {
+	case CS5:
+		len = 7;
+		break;
+	case CS6:
+		len = 8;
+		break;
+	case CS7:
+		len = 9;
+		break;
+	default:
+	case CS8:
+		len = 10;
+		break;
+	}
+
+	if (termios->c_cflag & CSTOPB)
+		len++;
+	if (termios->c_cflag & PARENB)
+		len++;
+	if (!(termios->c_cflag & PARODD))
+		len++;
+#ifdef CMSPAR
+	if (termios->c_cflag & CMSPAR)
+		len++;
+#endif
+
+	len -= 9;
+	len &= 3;
+	len <<= 3;
+	/*
+	 * Ask the core to calculate the divisor for us.
+	 */
+	baud = uart_get_baud_rate(port, termios, old,
+				  port->uartclk / 16 / 0xffff,
+				  port->uartclk / 16);
+	switch (baud) {
+	case 2400:
+		len |= 1;
+	case 4800:
+		len |= 2;
+	case 19200:
+		len |= 4;
+	case 38400:
+		len |= 5;
+	case 57600:
+		len |= 6;
+	case 115200:
+		len |= 7;
+	case 9600:
+	default:
+		len |= 3;
+	};
+	iowrite8(len, data->ios_mem);
+
+	serial8250_do_set_termios(port, termios, old);
+}
+
+static struct of_device_id lp8x4x_serial_dt_ids[] = {
+	{ .compatible = "icpdas,uart-lp8x4x", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, lp8x4x_serial_dt_ids);
+
+static int lp8x4x_serial_probe(struct platform_device *pdev)
+{
+	struct uart_8250_port uart = {};
+	struct lp8x4x_serial_data *data;
+	struct resource *mmres, *mires, *irqres;
+	int ret;
+
+	mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	mires = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	irqres = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!mmres || !mires || !irqres)
+		return -ENODEV;
+
+	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->ios_mem = devm_ioremap_resource(&pdev->dev, mires);
+	if (!data->ios_mem)
+		return -EFAULT;
+
+	uart.port.iotype = UPIO_MEM;
+	uart.port.mapbase = mmres->start;
+	uart.port.iobase = mmres->start;
+	uart.port.regshift = 1;
+	uart.port.irq = irqres->start;
+	uart.port.flags = UPF_IOREMAP;
+	uart.port.dev = &pdev->dev;
+	uart.port.uartclk = 14745600;
+	uart.port.set_termios = lp8x4x_serial_set_termios;
+	uart.port.private_data = data;
+
+	ret = serial8250_register_8250_port(&uart);
+	if (ret < 0)
+		return ret;
+
+	data->line = ret;
+
+	platform_set_drvdata(pdev, data);
+
+	return 0;
+}
+
+static int lp8x4x_serial_remove(struct platform_device *pdev)
+{
+	struct lp8x4x_serial_data *data = platform_get_drvdata(pdev);
+
+	serial8250_unregister_port(data->line);
+
+	return 0;
+}
+
+static struct platform_driver lp8x4x_serial_driver = {
+	.probe          = lp8x4x_serial_probe,
+	.remove         = lp8x4x_serial_remove,
+
+	.driver		= {
+		.name	= "uart-lp8x4x",
+		.owner	= THIS_MODULE,
+		.of_match_table = lp8x4x_serial_dt_ids,
+	},
+};
+
+module_platform_driver(lp8x4x_serial_driver);
+
+MODULE_AUTHOR("Sergei Ianovich");
+MODULE_DESCRIPTION("8250 serial port module for LP-8x4x");
+MODULE_LICENSE("GPL");
diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
index 81bd7c9..9fb0fbb 100644
--- a/drivers/tty/serial/8250/Kconfig
+++ b/drivers/tty/serial/8250/Kconfig
@@ -311,3 +311,15 @@ config SERIAL_PXA
 	  can enable its onboard serial ports by enabling this option.
 
 	  If you choose M here, the module name will be 8250_pxa.
+
+config SERIAL_8250_LP8X4X
+	tristate "Support 16550A ports on ICP DAS LP-8x4x"
+	depends on OF && SERIAL_8250 && SERIAL_8250_MANY_PORTS && ARCH_PXA
+	select LP8X4X_IRQ
+	help
+	  In addition to serial ports on PXA270 SoC, LP-8x4x has 1 dual
+	  RS232/RS485 port, 1 RS485 port and 1 RS232 port.
+
+	  Say N here, unless you plan to run this kernel on a LP-8x4x system.
+
+	  If you choose M here, the module name will be 8250_lp8x4x.
diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile
index b7d1b61..7370bfb 100644
--- a/drivers/tty/serial/8250/Makefile
+++ b/drivers/tty/serial/8250/Makefile
@@ -17,6 +17,7 @@ obj-$(CONFIG_SERIAL_8250_ACCENT)	+= 8250_accent.o
 obj-$(CONFIG_SERIAL_8250_BOCA)		+= 8250_boca.o
 obj-$(CONFIG_SERIAL_8250_EXAR_ST16C554)	+= 8250_exar_st16c554.o
 obj-$(CONFIG_SERIAL_8250_HUB6)		+= 8250_hub6.o
+obj-$(CONFIG_SERIAL_8250_LP8X4X)	+= 8250_lp8x4x.o
 obj-$(CONFIG_SERIAL_8250_FSL)		+= 8250_fsl.o
 obj-$(CONFIG_SERIAL_8250_DW)		+= 8250_dw.o
 obj-$(CONFIG_SERIAL_8250_EM)		+= 8250_em.o
-- 
1.8.4.3


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

* [PATCH v2 10/16] serial: support for 16550A serial ports on LP-8x4x
@ 2013-12-13  2:27           ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-13  2:27 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Heikki Krogerus, Rob Herring, Pawel Moll,
	Mark Rutland, Stephen Warren, Ian Campbell, Rob Landley,
	Russell King, Greg Kroah-Hartman, Jiri Slaby, Grant Likely,
	Paul Bolle, James Cameron, open list:OPEN FIRMWARE AND...,
	open list:DOCUMENTATION, open list:SERIAL DRIVERS

The patch adds support for 3 additional LP-8x4x built-in serial
ports.

The device can also host up to 8 extension cards with 4 serial ports
on each card for a total of 35 ports. However, I don't have
the hardware to test extension cards, so they are not supported, yet.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Heikki Krogerus <heikki.krogerus@linux.intel.com>
---
   v0..v2
   * register platform driver instead of platform device
   * use device tree
   * use devm helpers where possible

 .../devicetree/bindings/serial/lp8x4x-serial.txt   |  35 +++++
 arch/arm/boot/dts/pxa27x-lp8x4x.dts                |  27 ++++
 arch/arm/configs/lp8x4x_defconfig                  |   1 +
 drivers/tty/serial/8250/8250_lp8x4x.c              | 162 +++++++++++++++++++++
 drivers/tty/serial/8250/Kconfig                    |  12 ++
 drivers/tty/serial/8250/Makefile                   |   1 +
 6 files changed, 238 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/serial/lp8x4x-serial.txt
 create mode 100644 drivers/tty/serial/8250/8250_lp8x4x.c

diff --git a/Documentation/devicetree/bindings/serial/lp8x4x-serial.txt b/Documentation/devicetree/bindings/serial/lp8x4x-serial.txt
new file mode 100644
index 0000000..eed4ffc
--- /dev/null
+++ b/Documentation/devicetree/bindings/serial/lp8x4x-serial.txt
@@ -0,0 +1,35 @@
+UART ports on ICP DAS LP-8x4x
+
+ICP DAS LP-8x4x contains three additional serial ports interfaced via
+Analog Devices ADM213EA chips in addition to 3 serial ports on PXA CPU.
+
+Required properties:
+- compatible : should be "icpdas,uart-lp8x4x"
+
+- reg : should provide 16 byte man IO memory region and 1 byte region for
+	termios
+
+- interrupts : should provide interrupt
+
+- interrupt-parent : should provide a link to interrupt controller either
+		     explicitly and implicitly from a parent node
+
+Examples (from pxa27x-lp8x4x.dts):
+
+		uart@17009050 {
+			compatible = "icpdas,uart-lp8x4x";
+			reg = <0x17009050 0x10
+			       0x17009030 0x02>;
+			interrupt-parent = <&fpga>;
+			interrupts = <13>;
+			status = "okay";
+		};
+
+		uart@17009060 {
+			compatible = "icpdas,uart-lp8x4x";
+			reg = <0x17009060 0x10
+			       0x17009032 0x02>;
+			interrupt-parent = <&fpga>;
+			interrupts = <14>;
+			status = "okay";
+		};
diff --git a/arch/arm/boot/dts/pxa27x-lp8x4x.dts b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
index 2704760..4bcf400 100644
--- a/arch/arm/boot/dts/pxa27x-lp8x4x.dts
+++ b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
@@ -129,5 +129,32 @@
 			interrupt-controller;
 			status = "okay";
 		};
+
+		uart@17009050 {
+			compatible = "icpdas,uart-lp8x4x";
+			reg = <0x17009050 0x10
+			       0x17009030 0x02>;
+			interrupt-parent = <&fpga>;
+			interrupts = <13>;
+			status = "okay";
+		};
+
+		uart@17009060 {
+			compatible = "icpdas,uart-lp8x4x";
+			reg = <0x17009060 0x10
+			       0x17009032 0x02>;
+			interrupt-parent = <&fpga>;
+			interrupts = <14>;
+			status = "okay";
+		};
+
+		uart@17009070 {
+			compatible = "icpdas,uart-lp8x4x";
+			reg = <0x17009070 0x10
+			       0x17009034 0x02>;
+			interrupt-parent = <&fpga>;
+			interrupts = <15>;
+			status = "okay";
+		};
 	};
 };
diff --git a/arch/arm/configs/lp8x4x_defconfig b/arch/arm/configs/lp8x4x_defconfig
index 8fa871e..ea1a4b8 100644
--- a/arch/arm/configs/lp8x4x_defconfig
+++ b/arch/arm/configs/lp8x4x_defconfig
@@ -111,6 +111,7 @@ CONFIG_SERIAL_8250_EXTENDED=y
 CONFIG_SERIAL_8250_MANY_PORTS=y
 CONFIG_SERIAL_8250_SHARE_IRQ=y
 CONFIG_SERIAL_PXA=y
+CONFIG_SERIAL_8250_LP8X4X=m
 CONFIG_HW_RANDOM=y
 CONFIG_I2C=m
 # CONFIG_I2C_COMPAT is not set
diff --git a/drivers/tty/serial/8250/8250_lp8x4x.c b/drivers/tty/serial/8250/8250_lp8x4x.c
new file mode 100644
index 0000000..ec2f215
--- /dev/null
+++ b/drivers/tty/serial/8250/8250_lp8x4x.c
@@ -0,0 +1,162 @@
+/*  linux/drivers/tty/serial/8250/8250_lp8x4x.c
+ *
+ *  Support for 16550A serial ports on ICP DAS LP-8x4x
+ *
+ *  Copyright (C) 2013 Sergei Ianovich <ynvich@gmail.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/module.h>
+#include <linux/serial_8250.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+struct lp8x4x_serial_data {
+	int			line;
+	void			*ios_mem;
+};
+
+static void lp8x4x_serial_set_termios(struct uart_port *port,
+		struct ktermios *termios, struct ktermios *old)
+{
+	unsigned int len;
+	unsigned int baud;
+	struct lp8x4x_serial_data *data = port->private_data;
+
+	switch (termios->c_cflag & CSIZE) {
+	case CS5:
+		len = 7;
+		break;
+	case CS6:
+		len = 8;
+		break;
+	case CS7:
+		len = 9;
+		break;
+	default:
+	case CS8:
+		len = 10;
+		break;
+	}
+
+	if (termios->c_cflag & CSTOPB)
+		len++;
+	if (termios->c_cflag & PARENB)
+		len++;
+	if (!(termios->c_cflag & PARODD))
+		len++;
+#ifdef CMSPAR
+	if (termios->c_cflag & CMSPAR)
+		len++;
+#endif
+
+	len -= 9;
+	len &= 3;
+	len <<= 3;
+	/*
+	 * Ask the core to calculate the divisor for us.
+	 */
+	baud = uart_get_baud_rate(port, termios, old,
+				  port->uartclk / 16 / 0xffff,
+				  port->uartclk / 16);
+	switch (baud) {
+	case 2400:
+		len |= 1;
+	case 4800:
+		len |= 2;
+	case 19200:
+		len |= 4;
+	case 38400:
+		len |= 5;
+	case 57600:
+		len |= 6;
+	case 115200:
+		len |= 7;
+	case 9600:
+	default:
+		len |= 3;
+	};
+	iowrite8(len, data->ios_mem);
+
+	serial8250_do_set_termios(port, termios, old);
+}
+
+static struct of_device_id lp8x4x_serial_dt_ids[] = {
+	{ .compatible = "icpdas,uart-lp8x4x", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, lp8x4x_serial_dt_ids);
+
+static int lp8x4x_serial_probe(struct platform_device *pdev)
+{
+	struct uart_8250_port uart = {};
+	struct lp8x4x_serial_data *data;
+	struct resource *mmres, *mires, *irqres;
+	int ret;
+
+	mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	mires = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	irqres = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!mmres || !mires || !irqres)
+		return -ENODEV;
+
+	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->ios_mem = devm_ioremap_resource(&pdev->dev, mires);
+	if (!data->ios_mem)
+		return -EFAULT;
+
+	uart.port.iotype = UPIO_MEM;
+	uart.port.mapbase = mmres->start;
+	uart.port.iobase = mmres->start;
+	uart.port.regshift = 1;
+	uart.port.irq = irqres->start;
+	uart.port.flags = UPF_IOREMAP;
+	uart.port.dev = &pdev->dev;
+	uart.port.uartclk = 14745600;
+	uart.port.set_termios = lp8x4x_serial_set_termios;
+	uart.port.private_data = data;
+
+	ret = serial8250_register_8250_port(&uart);
+	if (ret < 0)
+		return ret;
+
+	data->line = ret;
+
+	platform_set_drvdata(pdev, data);
+
+	return 0;
+}
+
+static int lp8x4x_serial_remove(struct platform_device *pdev)
+{
+	struct lp8x4x_serial_data *data = platform_get_drvdata(pdev);
+
+	serial8250_unregister_port(data->line);
+
+	return 0;
+}
+
+static struct platform_driver lp8x4x_serial_driver = {
+	.probe          = lp8x4x_serial_probe,
+	.remove         = lp8x4x_serial_remove,
+
+	.driver		= {
+		.name	= "uart-lp8x4x",
+		.owner	= THIS_MODULE,
+		.of_match_table = lp8x4x_serial_dt_ids,
+	},
+};
+
+module_platform_driver(lp8x4x_serial_driver);
+
+MODULE_AUTHOR("Sergei Ianovich");
+MODULE_DESCRIPTION("8250 serial port module for LP-8x4x");
+MODULE_LICENSE("GPL");
diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
index 81bd7c9..9fb0fbb 100644
--- a/drivers/tty/serial/8250/Kconfig
+++ b/drivers/tty/serial/8250/Kconfig
@@ -311,3 +311,15 @@ config SERIAL_PXA
 	  can enable its onboard serial ports by enabling this option.
 
 	  If you choose M here, the module name will be 8250_pxa.
+
+config SERIAL_8250_LP8X4X
+	tristate "Support 16550A ports on ICP DAS LP-8x4x"
+	depends on OF && SERIAL_8250 && SERIAL_8250_MANY_PORTS && ARCH_PXA
+	select LP8X4X_IRQ
+	help
+	  In addition to serial ports on PXA270 SoC, LP-8x4x has 1 dual
+	  RS232/RS485 port, 1 RS485 port and 1 RS232 port.
+
+	  Say N here, unless you plan to run this kernel on a LP-8x4x system.
+
+	  If you choose M here, the module name will be 8250_lp8x4x.
diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile
index b7d1b61..7370bfb 100644
--- a/drivers/tty/serial/8250/Makefile
+++ b/drivers/tty/serial/8250/Makefile
@@ -17,6 +17,7 @@ obj-$(CONFIG_SERIAL_8250_ACCENT)	+= 8250_accent.o
 obj-$(CONFIG_SERIAL_8250_BOCA)		+= 8250_boca.o
 obj-$(CONFIG_SERIAL_8250_EXAR_ST16C554)	+= 8250_exar_st16c554.o
 obj-$(CONFIG_SERIAL_8250_HUB6)		+= 8250_hub6.o
+obj-$(CONFIG_SERIAL_8250_LP8X4X)	+= 8250_lp8x4x.o
 obj-$(CONFIG_SERIAL_8250_FSL)		+= 8250_fsl.o
 obj-$(CONFIG_SERIAL_8250_DW)		+= 8250_dw.o
 obj-$(CONFIG_SERIAL_8250_EM)		+= 8250_em.o
-- 
1.8.4.3


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

* [PATCH v2 10/16] serial: support for 16550A serial ports on LP-8x4x
@ 2013-12-13  2:27           ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-13  2:27 UTC (permalink / raw)
  To: linux-arm-kernel

The patch adds support for 3 additional LP-8x4x built-in serial
ports.

The device can also host up to 8 extension cards with 4 serial ports
on each card for a total of 35 ports. However, I don't have
the hardware to test extension cards, so they are not supported, yet.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Heikki Krogerus <heikki.krogerus@linux.intel.com>
---
   v0..v2
   * register platform driver instead of platform device
   * use device tree
   * use devm helpers where possible

 .../devicetree/bindings/serial/lp8x4x-serial.txt   |  35 +++++
 arch/arm/boot/dts/pxa27x-lp8x4x.dts                |  27 ++++
 arch/arm/configs/lp8x4x_defconfig                  |   1 +
 drivers/tty/serial/8250/8250_lp8x4x.c              | 162 +++++++++++++++++++++
 drivers/tty/serial/8250/Kconfig                    |  12 ++
 drivers/tty/serial/8250/Makefile                   |   1 +
 6 files changed, 238 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/serial/lp8x4x-serial.txt
 create mode 100644 drivers/tty/serial/8250/8250_lp8x4x.c

diff --git a/Documentation/devicetree/bindings/serial/lp8x4x-serial.txt b/Documentation/devicetree/bindings/serial/lp8x4x-serial.txt
new file mode 100644
index 0000000..eed4ffc
--- /dev/null
+++ b/Documentation/devicetree/bindings/serial/lp8x4x-serial.txt
@@ -0,0 +1,35 @@
+UART ports on ICP DAS LP-8x4x
+
+ICP DAS LP-8x4x contains three additional serial ports interfaced via
+Analog Devices ADM213EA chips in addition to 3 serial ports on PXA CPU.
+
+Required properties:
+- compatible : should be "icpdas,uart-lp8x4x"
+
+- reg : should provide 16 byte man IO memory region and 1 byte region for
+	termios
+
+- interrupts : should provide interrupt
+
+- interrupt-parent : should provide a link to interrupt controller either
+		     explicitly and implicitly from a parent node
+
+Examples (from pxa27x-lp8x4x.dts):
+
+		uart at 17009050 {
+			compatible = "icpdas,uart-lp8x4x";
+			reg = <0x17009050 0x10
+			       0x17009030 0x02>;
+			interrupt-parent = <&fpga>;
+			interrupts = <13>;
+			status = "okay";
+		};
+
+		uart at 17009060 {
+			compatible = "icpdas,uart-lp8x4x";
+			reg = <0x17009060 0x10
+			       0x17009032 0x02>;
+			interrupt-parent = <&fpga>;
+			interrupts = <14>;
+			status = "okay";
+		};
diff --git a/arch/arm/boot/dts/pxa27x-lp8x4x.dts b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
index 2704760..4bcf400 100644
--- a/arch/arm/boot/dts/pxa27x-lp8x4x.dts
+++ b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
@@ -129,5 +129,32 @@
 			interrupt-controller;
 			status = "okay";
 		};
+
+		uart at 17009050 {
+			compatible = "icpdas,uart-lp8x4x";
+			reg = <0x17009050 0x10
+			       0x17009030 0x02>;
+			interrupt-parent = <&fpga>;
+			interrupts = <13>;
+			status = "okay";
+		};
+
+		uart at 17009060 {
+			compatible = "icpdas,uart-lp8x4x";
+			reg = <0x17009060 0x10
+			       0x17009032 0x02>;
+			interrupt-parent = <&fpga>;
+			interrupts = <14>;
+			status = "okay";
+		};
+
+		uart at 17009070 {
+			compatible = "icpdas,uart-lp8x4x";
+			reg = <0x17009070 0x10
+			       0x17009034 0x02>;
+			interrupt-parent = <&fpga>;
+			interrupts = <15>;
+			status = "okay";
+		};
 	};
 };
diff --git a/arch/arm/configs/lp8x4x_defconfig b/arch/arm/configs/lp8x4x_defconfig
index 8fa871e..ea1a4b8 100644
--- a/arch/arm/configs/lp8x4x_defconfig
+++ b/arch/arm/configs/lp8x4x_defconfig
@@ -111,6 +111,7 @@ CONFIG_SERIAL_8250_EXTENDED=y
 CONFIG_SERIAL_8250_MANY_PORTS=y
 CONFIG_SERIAL_8250_SHARE_IRQ=y
 CONFIG_SERIAL_PXA=y
+CONFIG_SERIAL_8250_LP8X4X=m
 CONFIG_HW_RANDOM=y
 CONFIG_I2C=m
 # CONFIG_I2C_COMPAT is not set
diff --git a/drivers/tty/serial/8250/8250_lp8x4x.c b/drivers/tty/serial/8250/8250_lp8x4x.c
new file mode 100644
index 0000000..ec2f215
--- /dev/null
+++ b/drivers/tty/serial/8250/8250_lp8x4x.c
@@ -0,0 +1,162 @@
+/*  linux/drivers/tty/serial/8250/8250_lp8x4x.c
+ *
+ *  Support for 16550A serial ports on ICP DAS LP-8x4x
+ *
+ *  Copyright (C) 2013 Sergei Ianovich <ynvich@gmail.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/module.h>
+#include <linux/serial_8250.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+struct lp8x4x_serial_data {
+	int			line;
+	void			*ios_mem;
+};
+
+static void lp8x4x_serial_set_termios(struct uart_port *port,
+		struct ktermios *termios, struct ktermios *old)
+{
+	unsigned int len;
+	unsigned int baud;
+	struct lp8x4x_serial_data *data = port->private_data;
+
+	switch (termios->c_cflag & CSIZE) {
+	case CS5:
+		len = 7;
+		break;
+	case CS6:
+		len = 8;
+		break;
+	case CS7:
+		len = 9;
+		break;
+	default:
+	case CS8:
+		len = 10;
+		break;
+	}
+
+	if (termios->c_cflag & CSTOPB)
+		len++;
+	if (termios->c_cflag & PARENB)
+		len++;
+	if (!(termios->c_cflag & PARODD))
+		len++;
+#ifdef CMSPAR
+	if (termios->c_cflag & CMSPAR)
+		len++;
+#endif
+
+	len -= 9;
+	len &= 3;
+	len <<= 3;
+	/*
+	 * Ask the core to calculate the divisor for us.
+	 */
+	baud = uart_get_baud_rate(port, termios, old,
+				  port->uartclk / 16 / 0xffff,
+				  port->uartclk / 16);
+	switch (baud) {
+	case 2400:
+		len |= 1;
+	case 4800:
+		len |= 2;
+	case 19200:
+		len |= 4;
+	case 38400:
+		len |= 5;
+	case 57600:
+		len |= 6;
+	case 115200:
+		len |= 7;
+	case 9600:
+	default:
+		len |= 3;
+	};
+	iowrite8(len, data->ios_mem);
+
+	serial8250_do_set_termios(port, termios, old);
+}
+
+static struct of_device_id lp8x4x_serial_dt_ids[] = {
+	{ .compatible = "icpdas,uart-lp8x4x", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, lp8x4x_serial_dt_ids);
+
+static int lp8x4x_serial_probe(struct platform_device *pdev)
+{
+	struct uart_8250_port uart = {};
+	struct lp8x4x_serial_data *data;
+	struct resource *mmres, *mires, *irqres;
+	int ret;
+
+	mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	mires = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	irqres = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!mmres || !mires || !irqres)
+		return -ENODEV;
+
+	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->ios_mem = devm_ioremap_resource(&pdev->dev, mires);
+	if (!data->ios_mem)
+		return -EFAULT;
+
+	uart.port.iotype = UPIO_MEM;
+	uart.port.mapbase = mmres->start;
+	uart.port.iobase = mmres->start;
+	uart.port.regshift = 1;
+	uart.port.irq = irqres->start;
+	uart.port.flags = UPF_IOREMAP;
+	uart.port.dev = &pdev->dev;
+	uart.port.uartclk = 14745600;
+	uart.port.set_termios = lp8x4x_serial_set_termios;
+	uart.port.private_data = data;
+
+	ret = serial8250_register_8250_port(&uart);
+	if (ret < 0)
+		return ret;
+
+	data->line = ret;
+
+	platform_set_drvdata(pdev, data);
+
+	return 0;
+}
+
+static int lp8x4x_serial_remove(struct platform_device *pdev)
+{
+	struct lp8x4x_serial_data *data = platform_get_drvdata(pdev);
+
+	serial8250_unregister_port(data->line);
+
+	return 0;
+}
+
+static struct platform_driver lp8x4x_serial_driver = {
+	.probe          = lp8x4x_serial_probe,
+	.remove         = lp8x4x_serial_remove,
+
+	.driver		= {
+		.name	= "uart-lp8x4x",
+		.owner	= THIS_MODULE,
+		.of_match_table = lp8x4x_serial_dt_ids,
+	},
+};
+
+module_platform_driver(lp8x4x_serial_driver);
+
+MODULE_AUTHOR("Sergei Ianovich");
+MODULE_DESCRIPTION("8250 serial port module for LP-8x4x");
+MODULE_LICENSE("GPL");
diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
index 81bd7c9..9fb0fbb 100644
--- a/drivers/tty/serial/8250/Kconfig
+++ b/drivers/tty/serial/8250/Kconfig
@@ -311,3 +311,15 @@ config SERIAL_PXA
 	  can enable its onboard serial ports by enabling this option.
 
 	  If you choose M here, the module name will be 8250_pxa.
+
+config SERIAL_8250_LP8X4X
+	tristate "Support 16550A ports on ICP DAS LP-8x4x"
+	depends on OF && SERIAL_8250 && SERIAL_8250_MANY_PORTS && ARCH_PXA
+	select LP8X4X_IRQ
+	help
+	  In addition to serial ports on PXA270 SoC, LP-8x4x has 1 dual
+	  RS232/RS485 port, 1 RS485 port and 1 RS232 port.
+
+	  Say N here, unless you plan to run this kernel on a LP-8x4x system.
+
+	  If you choose M here, the module name will be 8250_lp8x4x.
diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile
index b7d1b61..7370bfb 100644
--- a/drivers/tty/serial/8250/Makefile
+++ b/drivers/tty/serial/8250/Makefile
@@ -17,6 +17,7 @@ obj-$(CONFIG_SERIAL_8250_ACCENT)	+= 8250_accent.o
 obj-$(CONFIG_SERIAL_8250_BOCA)		+= 8250_boca.o
 obj-$(CONFIG_SERIAL_8250_EXAR_ST16C554)	+= 8250_exar_st16c554.o
 obj-$(CONFIG_SERIAL_8250_HUB6)		+= 8250_hub6.o
+obj-$(CONFIG_SERIAL_8250_LP8X4X)	+= 8250_lp8x4x.o
 obj-$(CONFIG_SERIAL_8250_FSL)		+= 8250_fsl.o
 obj-$(CONFIG_SERIAL_8250_DW)		+= 8250_dw.o
 obj-$(CONFIG_SERIAL_8250_EM)		+= 8250_em.o
-- 
1.8.4.3

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

* [PATCH v2 11/16] misc: support for LP-8x4x custom parallel bus
  2013-12-13  2:27         ` Sergei Ianovich
  (?)
@ 2013-12-13  2:27           ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-13  2:27 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Rob Herring, Pawel Moll, Mark Rutland,
	Stephen Warren, Ian Campbell, Rob Landley, Russell King,
	Arnd Bergmann, Greg Kroah-Hartman, Grant Likely,
	open list:OPEN FIRMWARE AND...,
	open list:DOCUMENTATION

This patch implements probing for the bus and reporting the number
of available expansion slots.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
   v0..v2
   * use device tree
   * use devm helpers where possible

 .../devicetree/bindings/misc/lp8x4x-bus.txt        |  16 ++
 Documentation/misc-devices/lp8x4x_bus.txt          |  30 ++++
 arch/arm/boot/dts/pxa27x-lp8x4x.dts                |   5 +
 arch/arm/configs/lp8x4x_defconfig                  |   1 +
 drivers/misc/Kconfig                               |  13 ++
 drivers/misc/Makefile                              |   1 +
 drivers/misc/lp8x4x_bus.c                          | 165 +++++++++++++++++++++
 7 files changed, 231 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
 create mode 100644 Documentation/misc-devices/lp8x4x_bus.txt
 create mode 100644 drivers/misc/lp8x4x_bus.c

diff --git a/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt b/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
new file mode 100644
index 0000000..1c87a29
--- /dev/null
+++ b/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
@@ -0,0 +1,16 @@
+Custom parallel bus on ICP DAS LP-8x4x industrial computers
+
+See Documentation/misc-devices/lp8x4x_bus.txt for details.
+
+Required properties:
+- compatible : should be "icpdas,backplane-lp8x4x"
+
+- reg: physical base address of the slot count register and the length
+       of the memory mapped region.
+
+Example:
+
+	backplane {
+		compatible = "icpdas,backplane-lp8x4x";
+		reg = <0x17009046 0x2>;
+	};
diff --git a/Documentation/misc-devices/lp8x4x_bus.txt b/Documentation/misc-devices/lp8x4x_bus.txt
new file mode 100644
index 0000000..f5392b3
--- /dev/null
+++ b/Documentation/misc-devices/lp8x4x_bus.txt
@@ -0,0 +1,30 @@
+Kernel driver lpx8x4x_bus
+======================
+
+Supported hardare:
+Custom parallel bus on ICP DAS LP-8x4x industrial computers
+
+Data sheet:
+Not freely available
+
+Author:
+Sergei Ianovich <ynvich@gmail.com>
+
+Description
+-----------
+
+http://www.icpdas.com/root/product/solutions/pac/linpac/lp-8x4x_hardware.html
+
+LP-8x4x is an ARM-based industrial computer with a custom parallel bus to
+connect expansion modules with digital input/output, analog input/output,
+serial, CAN and other types of ports.
+
+The bus is implemented by a FPGA.
+
+SYSFS
+-----
+
+/sys/bus/icpdas/devices/backplane:
+
+slot_count
+	RO - shows total number of expansion slots on the device
diff --git a/arch/arm/boot/dts/pxa27x-lp8x4x.dts b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
index 138de0a..6c8e8e6 100644
--- a/arch/arm/boot/dts/pxa27x-lp8x4x.dts
+++ b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
@@ -156,5 +156,10 @@
 			interrupts = <15>;
 			status = "okay";
 		};
+
+		backplane {
+			compatible = "icpdas,backplane-lp8x4x";
+			reg = <0x17009046 0x2>;
+		};
 	};
 };
diff --git a/arch/arm/configs/lp8x4x_defconfig b/arch/arm/configs/lp8x4x_defconfig
index ea1a4b8..31cf46e 100644
--- a/arch/arm/configs/lp8x4x_defconfig
+++ b/arch/arm/configs/lp8x4x_defconfig
@@ -61,6 +61,7 @@ CONFIG_MTD_SRAM_LP8X4X=y
 CONFIG_PROC_DEVICETREE=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_LOOP_MIN_COUNT=2
+CONFIG_LP8X4X_BUS=m
 CONFIG_SCSI=y
 # CONFIG_SCSI_PROC_FS is not set
 CONFIG_BLK_DEV_SD=y
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index a3e291d..e4d52da 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -515,6 +515,19 @@ config SRAM
 	  the genalloc API. It is supposed to be used for small on-chip SRAM
 	  areas found on many SoCs.
 
+config LP8X4X_BUS
+	tristate "ICP DAS LP-8x4x industrial IO bus"
+	depends on OF && ARCH_PXA
+	select SYSFS
+	---help---
+	  This is a driver for ICP DAS LP-8x4x programmable automation
+	  controller. It exposes a custom parallel bus. The bus services
+	  data acquisition and control modules.
+
+	  Say N, unless you plan to run this kernel on a LP-8x4x system.
+
+	  If you say M here, the module will be called lp8x4x_bus.
+
 source "drivers/misc/c2port/Kconfig"
 source "drivers/misc/eeprom/Kconfig"
 source "drivers/misc/cb710/Kconfig"
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index f45473e..7578cff 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -53,3 +53,4 @@ obj-$(CONFIG_VMWARE_VMCI)	+= vmw_vmci/
 obj-$(CONFIG_LATTICE_ECP3_CONFIG)	+= lattice-ecp3-config.o
 obj-$(CONFIG_SRAM)		+= sram.o
 obj-y				+= mic/
+obj-$(CONFIG_LP8X4X_BUS)	+= lp8x4x_bus.o
diff --git a/drivers/misc/lp8x4x_bus.c b/drivers/misc/lp8x4x_bus.c
new file mode 100644
index 0000000..7119738
--- /dev/null
+++ b/drivers/misc/lp8x4x_bus.c
@@ -0,0 +1,165 @@
+/*
+ *  linux/misc/lp8x4x_bus.c
+ *
+ *  Support for ICP DAS LP-8x4x programmable automation controller bus
+ *  Copyright (C) 2013 Sergei Ianovich <ynvich@gmail.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation or any later version.
+ */
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#define MODULE_NAME	"lp8x4x-bus"
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Sergei Ianovich <ynvich@gmail.com>");
+MODULE_DESCRIPTION("ICP DAS LP-8x4x parallel bus driver");
+
+struct lp8x4x_master {
+	unsigned int		slot_count;
+	void			*count_addr;
+	struct device		dev;
+};
+
+static int lp8x4x_match(struct device *dev, struct device_driver *drv)
+{
+	return 1;
+}
+
+static struct bus_type lp8x4x_bus_type = {
+	.name		= "icpdas",
+	.match		= lp8x4x_match,
+};
+
+static void lp8x4x_master_release(struct device *dev)
+{
+	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
+	WARN_ON(!dev);
+
+	kfree(m);
+}
+
+static ssize_t slot_count_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
+
+	return sprintf(buf, "%u\n", m->slot_count);
+}
+
+static DEVICE_ATTR_RO(slot_count);
+
+static struct attribute *master_dev_attrs[] = {
+	&dev_attr_slot_count.attr,
+	NULL,
+};
+ATTRIBUTE_GROUPS(master_dev);
+
+
+static void devm_lp8x4x_bus_release(struct device *dev, void *res)
+{
+	struct lp8x4x_master *m = *(struct lp8x4x_master **)res;
+
+	dev_dbg(dev, "releasing devices\n");
+	device_unregister(&m->dev);
+	bus_unregister(&lp8x4x_bus_type);
+}
+
+static int __init lp8x4x_bus_probe(struct platform_device *pdev)
+{
+	struct lp8x4x_master *m, **p;
+	struct resource *res;
+	int err = 0;
+
+	m = kzalloc(sizeof(*m), GFP_KERNEL);
+	if (!m)
+		return -ENOMEM;
+
+	p = devres_alloc(devm_lp8x4x_bus_release, sizeof(*p), GFP_KERNEL);
+	if (!m) {
+		err = -ENOMEM;
+		goto err1;
+	}
+	*p = m;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		err = -ENODEV;
+		goto err2;
+	}
+
+	m->count_addr = devm_ioremap_resource(&pdev->dev, res);
+	if (!m->count_addr) {
+		dev_err(&pdev->dev, "Failed to ioremap %p\n",
+		       m->count_addr);
+		err = -EFAULT;
+		goto err2;
+	}
+
+	m->slot_count = ioread8(m->count_addr);
+	switch (m->slot_count) {
+	case 1:
+	case 4:
+		break;
+	case 7:
+		m->slot_count = 8;
+		break;
+	default:
+		dev_err(&pdev->dev, "unexpected slot number(%u)",
+				m->slot_count);
+		goto err2;
+	};
+
+	dev_info(&pdev->dev, "found bus with up to %u slots\n", m->slot_count);
+
+	err = bus_register(&lp8x4x_bus_type);
+	if (err < 0) {
+		dev_err(&pdev->dev, "failed to register bus type\n");
+		goto err3;
+	}
+
+	m->dev.bus = &lp8x4x_bus_type;
+	dev_set_name(&m->dev, "backplane");
+	m->dev.parent = &pdev->dev;
+	m->dev.release = lp8x4x_master_release;
+	m->dev.groups = master_dev_groups;
+
+	err = device_register(&m->dev);
+	if (err < 0) {
+		dev_err(&pdev->dev, "failed to register backplane device\n");
+		goto err3;
+	}
+
+	devres_add(&pdev->dev, p);
+	return 0;
+
+err3:
+	bus_unregister(&lp8x4x_bus_type);
+err2:
+	devres_free(p);
+err1:
+	kfree(m);
+	return err;
+}
+
+static const struct of_device_id lp8x4x_bus_dt_ids[] = {
+	{ .compatible = "icpdas,backplane-lp8x4x" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, lp8x4x_bus_dt_ids);
+
+static struct platform_driver lp8x4x_bus_driver = {
+	.driver		= {
+		.name	= MODULE_NAME,
+		.owner	= THIS_MODULE,
+		.of_match_table = lp8x4x_bus_dt_ids,
+	},
+};
+
+module_platform_driver_probe(lp8x4x_bus_driver, lp8x4x_bus_probe);
-- 
1.8.4.3


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

* [PATCH v2 11/16] misc: support for LP-8x4x custom parallel bus
@ 2013-12-13  2:27           ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-13  2:27 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Rob Herring, Pawel Moll, Mark Rutland,
	Stephen Warren, Ian Campbell, Rob Landley, Russell King,
	Arnd Bergmann, Greg Kroah-Hartman, Grant Likely,
	open list:OPEN FIRMWARE AND...,
	open list:DOCUMENTATION

This patch implements probing for the bus and reporting the number
of available expansion slots.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
   v0..v2
   * use device tree
   * use devm helpers where possible

 .../devicetree/bindings/misc/lp8x4x-bus.txt        |  16 ++
 Documentation/misc-devices/lp8x4x_bus.txt          |  30 ++++
 arch/arm/boot/dts/pxa27x-lp8x4x.dts                |   5 +
 arch/arm/configs/lp8x4x_defconfig                  |   1 +
 drivers/misc/Kconfig                               |  13 ++
 drivers/misc/Makefile                              |   1 +
 drivers/misc/lp8x4x_bus.c                          | 165 +++++++++++++++++++++
 7 files changed, 231 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
 create mode 100644 Documentation/misc-devices/lp8x4x_bus.txt
 create mode 100644 drivers/misc/lp8x4x_bus.c

diff --git a/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt b/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
new file mode 100644
index 0000000..1c87a29
--- /dev/null
+++ b/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
@@ -0,0 +1,16 @@
+Custom parallel bus on ICP DAS LP-8x4x industrial computers
+
+See Documentation/misc-devices/lp8x4x_bus.txt for details.
+
+Required properties:
+- compatible : should be "icpdas,backplane-lp8x4x"
+
+- reg: physical base address of the slot count register and the length
+       of the memory mapped region.
+
+Example:
+
+	backplane {
+		compatible = "icpdas,backplane-lp8x4x";
+		reg = <0x17009046 0x2>;
+	};
diff --git a/Documentation/misc-devices/lp8x4x_bus.txt b/Documentation/misc-devices/lp8x4x_bus.txt
new file mode 100644
index 0000000..f5392b3
--- /dev/null
+++ b/Documentation/misc-devices/lp8x4x_bus.txt
@@ -0,0 +1,30 @@
+Kernel driver lpx8x4x_bus
+======================
+
+Supported hardare:
+Custom parallel bus on ICP DAS LP-8x4x industrial computers
+
+Data sheet:
+Not freely available
+
+Author:
+Sergei Ianovich <ynvich@gmail.com>
+
+Description
+-----------
+
+http://www.icpdas.com/root/product/solutions/pac/linpac/lp-8x4x_hardware.html
+
+LP-8x4x is an ARM-based industrial computer with a custom parallel bus to
+connect expansion modules with digital input/output, analog input/output,
+serial, CAN and other types of ports.
+
+The bus is implemented by a FPGA.
+
+SYSFS
+-----
+
+/sys/bus/icpdas/devices/backplane:
+
+slot_count
+	RO - shows total number of expansion slots on the device
diff --git a/arch/arm/boot/dts/pxa27x-lp8x4x.dts b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
index 138de0a..6c8e8e6 100644
--- a/arch/arm/boot/dts/pxa27x-lp8x4x.dts
+++ b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
@@ -156,5 +156,10 @@
 			interrupts = <15>;
 			status = "okay";
 		};
+
+		backplane {
+			compatible = "icpdas,backplane-lp8x4x";
+			reg = <0x17009046 0x2>;
+		};
 	};
 };
diff --git a/arch/arm/configs/lp8x4x_defconfig b/arch/arm/configs/lp8x4x_defconfig
index ea1a4b8..31cf46e 100644
--- a/arch/arm/configs/lp8x4x_defconfig
+++ b/arch/arm/configs/lp8x4x_defconfig
@@ -61,6 +61,7 @@ CONFIG_MTD_SRAM_LP8X4X=y
 CONFIG_PROC_DEVICETREE=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_LOOP_MIN_COUNT=2
+CONFIG_LP8X4X_BUS=m
 CONFIG_SCSI=y
 # CONFIG_SCSI_PROC_FS is not set
 CONFIG_BLK_DEV_SD=y
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index a3e291d..e4d52da 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -515,6 +515,19 @@ config SRAM
 	  the genalloc API. It is supposed to be used for small on-chip SRAM
 	  areas found on many SoCs.
 
+config LP8X4X_BUS
+	tristate "ICP DAS LP-8x4x industrial IO bus"
+	depends on OF && ARCH_PXA
+	select SYSFS
+	---help---
+	  This is a driver for ICP DAS LP-8x4x programmable automation
+	  controller. It exposes a custom parallel bus. The bus services
+	  data acquisition and control modules.
+
+	  Say N, unless you plan to run this kernel on a LP-8x4x system.
+
+	  If you say M here, the module will be called lp8x4x_bus.
+
 source "drivers/misc/c2port/Kconfig"
 source "drivers/misc/eeprom/Kconfig"
 source "drivers/misc/cb710/Kconfig"
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index f45473e..7578cff 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -53,3 +53,4 @@ obj-$(CONFIG_VMWARE_VMCI)	+= vmw_vmci/
 obj-$(CONFIG_LATTICE_ECP3_CONFIG)	+= lattice-ecp3-config.o
 obj-$(CONFIG_SRAM)		+= sram.o
 obj-y				+= mic/
+obj-$(CONFIG_LP8X4X_BUS)	+= lp8x4x_bus.o
diff --git a/drivers/misc/lp8x4x_bus.c b/drivers/misc/lp8x4x_bus.c
new file mode 100644
index 0000000..7119738
--- /dev/null
+++ b/drivers/misc/lp8x4x_bus.c
@@ -0,0 +1,165 @@
+/*
+ *  linux/misc/lp8x4x_bus.c
+ *
+ *  Support for ICP DAS LP-8x4x programmable automation controller bus
+ *  Copyright (C) 2013 Sergei Ianovich <ynvich@gmail.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation or any later version.
+ */
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#define MODULE_NAME	"lp8x4x-bus"
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Sergei Ianovich <ynvich@gmail.com>");
+MODULE_DESCRIPTION("ICP DAS LP-8x4x parallel bus driver");
+
+struct lp8x4x_master {
+	unsigned int		slot_count;
+	void			*count_addr;
+	struct device		dev;
+};
+
+static int lp8x4x_match(struct device *dev, struct device_driver *drv)
+{
+	return 1;
+}
+
+static struct bus_type lp8x4x_bus_type = {
+	.name		= "icpdas",
+	.match		= lp8x4x_match,
+};
+
+static void lp8x4x_master_release(struct device *dev)
+{
+	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
+	WARN_ON(!dev);
+
+	kfree(m);
+}
+
+static ssize_t slot_count_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
+
+	return sprintf(buf, "%u\n", m->slot_count);
+}
+
+static DEVICE_ATTR_RO(slot_count);
+
+static struct attribute *master_dev_attrs[] = {
+	&dev_attr_slot_count.attr,
+	NULL,
+};
+ATTRIBUTE_GROUPS(master_dev);
+
+
+static void devm_lp8x4x_bus_release(struct device *dev, void *res)
+{
+	struct lp8x4x_master *m = *(struct lp8x4x_master **)res;
+
+	dev_dbg(dev, "releasing devices\n");
+	device_unregister(&m->dev);
+	bus_unregister(&lp8x4x_bus_type);
+}
+
+static int __init lp8x4x_bus_probe(struct platform_device *pdev)
+{
+	struct lp8x4x_master *m, **p;
+	struct resource *res;
+	int err = 0;
+
+	m = kzalloc(sizeof(*m), GFP_KERNEL);
+	if (!m)
+		return -ENOMEM;
+
+	p = devres_alloc(devm_lp8x4x_bus_release, sizeof(*p), GFP_KERNEL);
+	if (!m) {
+		err = -ENOMEM;
+		goto err1;
+	}
+	*p = m;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		err = -ENODEV;
+		goto err2;
+	}
+
+	m->count_addr = devm_ioremap_resource(&pdev->dev, res);
+	if (!m->count_addr) {
+		dev_err(&pdev->dev, "Failed to ioremap %p\n",
+		       m->count_addr);
+		err = -EFAULT;
+		goto err2;
+	}
+
+	m->slot_count = ioread8(m->count_addr);
+	switch (m->slot_count) {
+	case 1:
+	case 4:
+		break;
+	case 7:
+		m->slot_count = 8;
+		break;
+	default:
+		dev_err(&pdev->dev, "unexpected slot number(%u)",
+				m->slot_count);
+		goto err2;
+	};
+
+	dev_info(&pdev->dev, "found bus with up to %u slots\n", m->slot_count);
+
+	err = bus_register(&lp8x4x_bus_type);
+	if (err < 0) {
+		dev_err(&pdev->dev, "failed to register bus type\n");
+		goto err3;
+	}
+
+	m->dev.bus = &lp8x4x_bus_type;
+	dev_set_name(&m->dev, "backplane");
+	m->dev.parent = &pdev->dev;
+	m->dev.release = lp8x4x_master_release;
+	m->dev.groups = master_dev_groups;
+
+	err = device_register(&m->dev);
+	if (err < 0) {
+		dev_err(&pdev->dev, "failed to register backplane device\n");
+		goto err3;
+	}
+
+	devres_add(&pdev->dev, p);
+	return 0;
+
+err3:
+	bus_unregister(&lp8x4x_bus_type);
+err2:
+	devres_free(p);
+err1:
+	kfree(m);
+	return err;
+}
+
+static const struct of_device_id lp8x4x_bus_dt_ids[] = {
+	{ .compatible = "icpdas,backplane-lp8x4x" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, lp8x4x_bus_dt_ids);
+
+static struct platform_driver lp8x4x_bus_driver = {
+	.driver		= {
+		.name	= MODULE_NAME,
+		.owner	= THIS_MODULE,
+		.of_match_table = lp8x4x_bus_dt_ids,
+	},
+};
+
+module_platform_driver_probe(lp8x4x_bus_driver, lp8x4x_bus_probe);
-- 
1.8.4.3

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

* [PATCH v2 11/16] misc: support for LP-8x4x custom parallel bus
@ 2013-12-13  2:27           ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-13  2:27 UTC (permalink / raw)
  To: linux-arm-kernel

This patch implements probing for the bus and reporting the number
of available expansion slots.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
   v0..v2
   * use device tree
   * use devm helpers where possible

 .../devicetree/bindings/misc/lp8x4x-bus.txt        |  16 ++
 Documentation/misc-devices/lp8x4x_bus.txt          |  30 ++++
 arch/arm/boot/dts/pxa27x-lp8x4x.dts                |   5 +
 arch/arm/configs/lp8x4x_defconfig                  |   1 +
 drivers/misc/Kconfig                               |  13 ++
 drivers/misc/Makefile                              |   1 +
 drivers/misc/lp8x4x_bus.c                          | 165 +++++++++++++++++++++
 7 files changed, 231 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
 create mode 100644 Documentation/misc-devices/lp8x4x_bus.txt
 create mode 100644 drivers/misc/lp8x4x_bus.c

diff --git a/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt b/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
new file mode 100644
index 0000000..1c87a29
--- /dev/null
+++ b/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
@@ -0,0 +1,16 @@
+Custom parallel bus on ICP DAS LP-8x4x industrial computers
+
+See Documentation/misc-devices/lp8x4x_bus.txt for details.
+
+Required properties:
+- compatible : should be "icpdas,backplane-lp8x4x"
+
+- reg: physical base address of the slot count register and the length
+       of the memory mapped region.
+
+Example:
+
+	backplane {
+		compatible = "icpdas,backplane-lp8x4x";
+		reg = <0x17009046 0x2>;
+	};
diff --git a/Documentation/misc-devices/lp8x4x_bus.txt b/Documentation/misc-devices/lp8x4x_bus.txt
new file mode 100644
index 0000000..f5392b3
--- /dev/null
+++ b/Documentation/misc-devices/lp8x4x_bus.txt
@@ -0,0 +1,30 @@
+Kernel driver lpx8x4x_bus
+======================
+
+Supported hardare:
+Custom parallel bus on ICP DAS LP-8x4x industrial computers
+
+Data sheet:
+Not freely available
+
+Author:
+Sergei Ianovich <ynvich@gmail.com>
+
+Description
+-----------
+
+http://www.icpdas.com/root/product/solutions/pac/linpac/lp-8x4x_hardware.html
+
+LP-8x4x is an ARM-based industrial computer with a custom parallel bus to
+connect expansion modules with digital input/output, analog input/output,
+serial, CAN and other types of ports.
+
+The bus is implemented by a FPGA.
+
+SYSFS
+-----
+
+/sys/bus/icpdas/devices/backplane:
+
+slot_count
+	RO - shows total number of expansion slots on the device
diff --git a/arch/arm/boot/dts/pxa27x-lp8x4x.dts b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
index 138de0a..6c8e8e6 100644
--- a/arch/arm/boot/dts/pxa27x-lp8x4x.dts
+++ b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
@@ -156,5 +156,10 @@
 			interrupts = <15>;
 			status = "okay";
 		};
+
+		backplane {
+			compatible = "icpdas,backplane-lp8x4x";
+			reg = <0x17009046 0x2>;
+		};
 	};
 };
diff --git a/arch/arm/configs/lp8x4x_defconfig b/arch/arm/configs/lp8x4x_defconfig
index ea1a4b8..31cf46e 100644
--- a/arch/arm/configs/lp8x4x_defconfig
+++ b/arch/arm/configs/lp8x4x_defconfig
@@ -61,6 +61,7 @@ CONFIG_MTD_SRAM_LP8X4X=y
 CONFIG_PROC_DEVICETREE=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_LOOP_MIN_COUNT=2
+CONFIG_LP8X4X_BUS=m
 CONFIG_SCSI=y
 # CONFIG_SCSI_PROC_FS is not set
 CONFIG_BLK_DEV_SD=y
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index a3e291d..e4d52da 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -515,6 +515,19 @@ config SRAM
 	  the genalloc API. It is supposed to be used for small on-chip SRAM
 	  areas found on many SoCs.
 
+config LP8X4X_BUS
+	tristate "ICP DAS LP-8x4x industrial IO bus"
+	depends on OF && ARCH_PXA
+	select SYSFS
+	---help---
+	  This is a driver for ICP DAS LP-8x4x programmable automation
+	  controller. It exposes a custom parallel bus. The bus services
+	  data acquisition and control modules.
+
+	  Say N, unless you plan to run this kernel on a LP-8x4x system.
+
+	  If you say M here, the module will be called lp8x4x_bus.
+
 source "drivers/misc/c2port/Kconfig"
 source "drivers/misc/eeprom/Kconfig"
 source "drivers/misc/cb710/Kconfig"
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index f45473e..7578cff 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -53,3 +53,4 @@ obj-$(CONFIG_VMWARE_VMCI)	+= vmw_vmci/
 obj-$(CONFIG_LATTICE_ECP3_CONFIG)	+= lattice-ecp3-config.o
 obj-$(CONFIG_SRAM)		+= sram.o
 obj-y				+= mic/
+obj-$(CONFIG_LP8X4X_BUS)	+= lp8x4x_bus.o
diff --git a/drivers/misc/lp8x4x_bus.c b/drivers/misc/lp8x4x_bus.c
new file mode 100644
index 0000000..7119738
--- /dev/null
+++ b/drivers/misc/lp8x4x_bus.c
@@ -0,0 +1,165 @@
+/*
+ *  linux/misc/lp8x4x_bus.c
+ *
+ *  Support for ICP DAS LP-8x4x programmable automation controller bus
+ *  Copyright (C) 2013 Sergei Ianovich <ynvich@gmail.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation or any later version.
+ */
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#define MODULE_NAME	"lp8x4x-bus"
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Sergei Ianovich <ynvich@gmail.com>");
+MODULE_DESCRIPTION("ICP DAS LP-8x4x parallel bus driver");
+
+struct lp8x4x_master {
+	unsigned int		slot_count;
+	void			*count_addr;
+	struct device		dev;
+};
+
+static int lp8x4x_match(struct device *dev, struct device_driver *drv)
+{
+	return 1;
+}
+
+static struct bus_type lp8x4x_bus_type = {
+	.name		= "icpdas",
+	.match		= lp8x4x_match,
+};
+
+static void lp8x4x_master_release(struct device *dev)
+{
+	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
+	WARN_ON(!dev);
+
+	kfree(m);
+}
+
+static ssize_t slot_count_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
+
+	return sprintf(buf, "%u\n", m->slot_count);
+}
+
+static DEVICE_ATTR_RO(slot_count);
+
+static struct attribute *master_dev_attrs[] = {
+	&dev_attr_slot_count.attr,
+	NULL,
+};
+ATTRIBUTE_GROUPS(master_dev);
+
+
+static void devm_lp8x4x_bus_release(struct device *dev, void *res)
+{
+	struct lp8x4x_master *m = *(struct lp8x4x_master **)res;
+
+	dev_dbg(dev, "releasing devices\n");
+	device_unregister(&m->dev);
+	bus_unregister(&lp8x4x_bus_type);
+}
+
+static int __init lp8x4x_bus_probe(struct platform_device *pdev)
+{
+	struct lp8x4x_master *m, **p;
+	struct resource *res;
+	int err = 0;
+
+	m = kzalloc(sizeof(*m), GFP_KERNEL);
+	if (!m)
+		return -ENOMEM;
+
+	p = devres_alloc(devm_lp8x4x_bus_release, sizeof(*p), GFP_KERNEL);
+	if (!m) {
+		err = -ENOMEM;
+		goto err1;
+	}
+	*p = m;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		err = -ENODEV;
+		goto err2;
+	}
+
+	m->count_addr = devm_ioremap_resource(&pdev->dev, res);
+	if (!m->count_addr) {
+		dev_err(&pdev->dev, "Failed to ioremap %p\n",
+		       m->count_addr);
+		err = -EFAULT;
+		goto err2;
+	}
+
+	m->slot_count = ioread8(m->count_addr);
+	switch (m->slot_count) {
+	case 1:
+	case 4:
+		break;
+	case 7:
+		m->slot_count = 8;
+		break;
+	default:
+		dev_err(&pdev->dev, "unexpected slot number(%u)",
+				m->slot_count);
+		goto err2;
+	};
+
+	dev_info(&pdev->dev, "found bus with up to %u slots\n", m->slot_count);
+
+	err = bus_register(&lp8x4x_bus_type);
+	if (err < 0) {
+		dev_err(&pdev->dev, "failed to register bus type\n");
+		goto err3;
+	}
+
+	m->dev.bus = &lp8x4x_bus_type;
+	dev_set_name(&m->dev, "backplane");
+	m->dev.parent = &pdev->dev;
+	m->dev.release = lp8x4x_master_release;
+	m->dev.groups = master_dev_groups;
+
+	err = device_register(&m->dev);
+	if (err < 0) {
+		dev_err(&pdev->dev, "failed to register backplane device\n");
+		goto err3;
+	}
+
+	devres_add(&pdev->dev, p);
+	return 0;
+
+err3:
+	bus_unregister(&lp8x4x_bus_type);
+err2:
+	devres_free(p);
+err1:
+	kfree(m);
+	return err;
+}
+
+static const struct of_device_id lp8x4x_bus_dt_ids[] = {
+	{ .compatible = "icpdas,backplane-lp8x4x" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, lp8x4x_bus_dt_ids);
+
+static struct platform_driver lp8x4x_bus_driver = {
+	.driver		= {
+		.name	= MODULE_NAME,
+		.owner	= THIS_MODULE,
+		.of_match_table = lp8x4x_bus_dt_ids,
+	},
+};
+
+module_platform_driver_probe(lp8x4x_bus_driver, lp8x4x_bus_probe);
-- 
1.8.4.3

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

* [PATCH v2 12/16] misc: support for serial slots in LP-8x4x
  2013-12-13  2:27         ` Sergei Ianovich
  (?)
@ 2013-12-13  2:27           ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-13  2:27 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Rob Herring, Pawel Moll, Mark Rutland,
	Stephen Warren, Ian Campbell, Rob Landley, Arnd Bergmann,
	Greg Kroah-Hartman, open list:OPEN FIRMWARE AND...,
	open list:DOCUMENTATION

Serial modules (I-870xxW series) implement DCON protocol which
allows one-master-many-slaves configuration over RS-485. When
these modules are installed into the device, they could be
accessed using the 2nd PXA built-in UART port (/dev/ttySA1).
However, it seems that addresses are not processed by the modules.
So the parallel bus needs to select which slot is connected.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
   v0..v2
   * use device tree
   * use devm helpers where possible

 .../devicetree/bindings/misc/lp8x4x-bus.txt        |  8 ++-
 Documentation/misc-devices/lp8x4x_bus.txt          | 15 ++++-
 drivers/misc/lp8x4x_bus.c                          | 75 ++++++++++++++++++++--
 3 files changed, 87 insertions(+), 11 deletions(-)

diff --git a/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt b/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
index 1c87a29..61ac96e 100644
--- a/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
+++ b/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
@@ -5,12 +5,14 @@ See Documentation/misc-devices/lp8x4x_bus.txt for details.
 Required properties:
 - compatible : should be "icpdas,backplane-lp8x4x"
 
-- reg: physical base address of the slot count register and the length
-       of the memory mapped region.
+- reg: physical base addresses and region lengths of
+       * the slot count register
+       * the serial slot select register
 
 Example:
 
 	backplane {
 		compatible = "icpdas,backplane-lp8x4x";
-		reg = <0x17009046 0x2>;
+		reg = <0x17009046 0x2
+		       0x17009004 0x2>;
 	};
diff --git a/Documentation/misc-devices/lp8x4x_bus.txt b/Documentation/misc-devices/lp8x4x_bus.txt
index f5392b3..d9a069d 100644
--- a/Documentation/misc-devices/lp8x4x_bus.txt
+++ b/Documentation/misc-devices/lp8x4x_bus.txt
@@ -19,7 +19,14 @@ LP-8x4x is an ARM-based industrial computer with a custom parallel bus to
 connect expansion modules with digital input/output, analog input/output,
 serial, CAN and other types of ports.
 
-The bus is implemented by a FPGA.
+The bus is implemented by a FPGA. There are two major groups of expansion
+modules: serial and parallel.
+
+Serial modules (I-870xxW series) implement DCON protocol which allows one-
+master-many-slaves configuration over RS-485. When these modules are installed
+into the device, they could be accessed using the 2nd PXA built-in UART port
+(/dev/ttyS1). However, it seems that addresses are not processed by
+the modules. So the parallel bus needs to select which slot is connected.
 
 SYSFS
 -----
@@ -28,3 +35,9 @@ SYSFS
 
 slot_count
 	RO - shows total number of expansion slots on the device
+
+active_slot
+	RW - connects the select slot for serial communications. If there
+	     is a parallel module in the selected slot, it simply ignores
+	     incoming packets. So it is safe to activate any available
+	     slot.
diff --git a/drivers/misc/lp8x4x_bus.c b/drivers/misc/lp8x4x_bus.c
index 7119738..cffe121 100644
--- a/drivers/misc/lp8x4x_bus.c
+++ b/drivers/misc/lp8x4x_bus.c
@@ -24,6 +24,8 @@ MODULE_DESCRIPTION("ICP DAS LP-8x4x parallel bus driver");
 struct lp8x4x_master {
 	unsigned int		slot_count;
 	void			*count_addr;
+	unsigned int		active_slot;
+	void			*switch_addr;
 	struct device		dev;
 };
 
@@ -55,8 +57,45 @@ static ssize_t slot_count_show(struct device *dev,
 
 static DEVICE_ATTR_RO(slot_count);
 
+static ssize_t active_slot_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
+
+	return sprintf(buf, "%u\n", m->active_slot);
+}
+
+static ssize_t active_slot_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
+	unsigned int active_slot = 0;
+	int err;
+
+	if (!buf)
+		return count;
+	if (0 == count)
+		return count;
+
+	err = kstrtouint(buf, 10, &active_slot);
+	if (err != 0 || !active_slot || active_slot > m->slot_count) {
+		dev_err(dev, "slot number is out of range 1..%u\n",
+				m->slot_count);
+		return count;
+	}
+
+	m->active_slot = active_slot;
+
+	iowrite8((1 << (m->active_slot - 1)) ^ 0xff, m->switch_addr);
+
+	return count;
+}
+
+static DEVICE_ATTR_RW(active_slot);
+
 static struct attribute *master_dev_attrs[] = {
 	&dev_attr_slot_count.attr,
+	&dev_attr_active_slot.attr,
 	NULL,
 };
 ATTRIBUTE_GROUPS(master_dev);
@@ -69,6 +108,9 @@ static void devm_lp8x4x_bus_release(struct device *dev, void *res)
 	dev_dbg(dev, "releasing devices\n");
 	device_unregister(&m->dev);
 	bus_unregister(&lp8x4x_bus_type);
+
+	/* Disable serial communications */
+	iowrite8(0xff, m->switch_addr);
 }
 
 static int __init lp8x4x_bus_probe(struct platform_device *pdev)
@@ -90,8 +132,9 @@ static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!res) {
+		dev_err(&pdev->dev, "Failed to get slot number address\n");
 		err = -ENODEV;
-		goto err2;
+		goto err_free;
 	}
 
 	m->count_addr = devm_ioremap_resource(&pdev->dev, res);
@@ -99,7 +142,22 @@ static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 		dev_err(&pdev->dev, "Failed to ioremap %p\n",
 		       m->count_addr);
 		err = -EFAULT;
-		goto err2;
+		goto err_free;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	if (!res) {
+		dev_err(&pdev->dev, "Failed to get slot switch address\n");
+		err = -ENODEV;
+		goto err_free;
+	}
+
+	m->switch_addr = devm_ioremap_resource(&pdev->dev, res);
+	if (!m->switch_addr) {
+		dev_err(&pdev->dev, "Failed to ioremap %p\n",
+		       m->switch_addr);
+		err = -EFAULT;
+		goto err_free;
 	}
 
 	m->slot_count = ioread8(m->count_addr);
@@ -113,15 +171,18 @@ static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 	default:
 		dev_err(&pdev->dev, "unexpected slot number(%u)",
 				m->slot_count);
-		goto err2;
+		goto err_free;
 	};
 
 	dev_info(&pdev->dev, "found bus with up to %u slots\n", m->slot_count);
 
+	/* Disable serial communications until explicitly enabled */
+	iowrite8(0xff, m->switch_addr);
+
 	err = bus_register(&lp8x4x_bus_type);
 	if (err < 0) {
 		dev_err(&pdev->dev, "failed to register bus type\n");
-		goto err3;
+		goto err_free;
 	}
 
 	m->dev.bus = &lp8x4x_bus_type;
@@ -133,15 +194,15 @@ static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 	err = device_register(&m->dev);
 	if (err < 0) {
 		dev_err(&pdev->dev, "failed to register backplane device\n");
-		goto err3;
+		goto err_bus;
 	}
 
 	devres_add(&pdev->dev, p);
 	return 0;
 
-err3:
+err_bus:
 	bus_unregister(&lp8x4x_bus_type);
-err2:
+err_free:
 	devres_free(p);
 err1:
 	kfree(m);
-- 
1.8.4.3


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

* [PATCH v2 12/16] misc: support for serial slots in LP-8x4x
@ 2013-12-13  2:27           ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-13  2:27 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Rob Herring, Pawel Moll, Mark Rutland,
	Stephen Warren, Ian Campbell, Rob Landley, Arnd Bergmann,
	Greg Kroah-Hartman, open list:OPEN FIRMWARE AND...,
	open list:DOCUMENTATION

Serial modules (I-870xxW series) implement DCON protocol which
allows one-master-many-slaves configuration over RS-485. When
these modules are installed into the device, they could be
accessed using the 2nd PXA built-in UART port (/dev/ttySA1).
However, it seems that addresses are not processed by the modules.
So the parallel bus needs to select which slot is connected.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
   v0..v2
   * use device tree
   * use devm helpers where possible

 .../devicetree/bindings/misc/lp8x4x-bus.txt        |  8 ++-
 Documentation/misc-devices/lp8x4x_bus.txt          | 15 ++++-
 drivers/misc/lp8x4x_bus.c                          | 75 ++++++++++++++++++++--
 3 files changed, 87 insertions(+), 11 deletions(-)

diff --git a/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt b/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
index 1c87a29..61ac96e 100644
--- a/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
+++ b/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
@@ -5,12 +5,14 @@ See Documentation/misc-devices/lp8x4x_bus.txt for details.
 Required properties:
 - compatible : should be "icpdas,backplane-lp8x4x"
 
-- reg: physical base address of the slot count register and the length
-       of the memory mapped region.
+- reg: physical base addresses and region lengths of
+       * the slot count register
+       * the serial slot select register
 
 Example:
 
 	backplane {
 		compatible = "icpdas,backplane-lp8x4x";
-		reg = <0x17009046 0x2>;
+		reg = <0x17009046 0x2
+		       0x17009004 0x2>;
 	};
diff --git a/Documentation/misc-devices/lp8x4x_bus.txt b/Documentation/misc-devices/lp8x4x_bus.txt
index f5392b3..d9a069d 100644
--- a/Documentation/misc-devices/lp8x4x_bus.txt
+++ b/Documentation/misc-devices/lp8x4x_bus.txt
@@ -19,7 +19,14 @@ LP-8x4x is an ARM-based industrial computer with a custom parallel bus to
 connect expansion modules with digital input/output, analog input/output,
 serial, CAN and other types of ports.
 
-The bus is implemented by a FPGA.
+The bus is implemented by a FPGA. There are two major groups of expansion
+modules: serial and parallel.
+
+Serial modules (I-870xxW series) implement DCON protocol which allows one-
+master-many-slaves configuration over RS-485. When these modules are installed
+into the device, they could be accessed using the 2nd PXA built-in UART port
+(/dev/ttyS1). However, it seems that addresses are not processed by
+the modules. So the parallel bus needs to select which slot is connected.
 
 SYSFS
 -----
@@ -28,3 +35,9 @@ SYSFS
 
 slot_count
 	RO - shows total number of expansion slots on the device
+
+active_slot
+	RW - connects the select slot for serial communications. If there
+	     is a parallel module in the selected slot, it simply ignores
+	     incoming packets. So it is safe to activate any available
+	     slot.
diff --git a/drivers/misc/lp8x4x_bus.c b/drivers/misc/lp8x4x_bus.c
index 7119738..cffe121 100644
--- a/drivers/misc/lp8x4x_bus.c
+++ b/drivers/misc/lp8x4x_bus.c
@@ -24,6 +24,8 @@ MODULE_DESCRIPTION("ICP DAS LP-8x4x parallel bus driver");
 struct lp8x4x_master {
 	unsigned int		slot_count;
 	void			*count_addr;
+	unsigned int		active_slot;
+	void			*switch_addr;
 	struct device		dev;
 };
 
@@ -55,8 +57,45 @@ static ssize_t slot_count_show(struct device *dev,
 
 static DEVICE_ATTR_RO(slot_count);
 
+static ssize_t active_slot_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
+
+	return sprintf(buf, "%u\n", m->active_slot);
+}
+
+static ssize_t active_slot_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
+	unsigned int active_slot = 0;
+	int err;
+
+	if (!buf)
+		return count;
+	if (0 == count)
+		return count;
+
+	err = kstrtouint(buf, 10, &active_slot);
+	if (err != 0 || !active_slot || active_slot > m->slot_count) {
+		dev_err(dev, "slot number is out of range 1..%u\n",
+				m->slot_count);
+		return count;
+	}
+
+	m->active_slot = active_slot;
+
+	iowrite8((1 << (m->active_slot - 1)) ^ 0xff, m->switch_addr);
+
+	return count;
+}
+
+static DEVICE_ATTR_RW(active_slot);
+
 static struct attribute *master_dev_attrs[] = {
 	&dev_attr_slot_count.attr,
+	&dev_attr_active_slot.attr,
 	NULL,
 };
 ATTRIBUTE_GROUPS(master_dev);
@@ -69,6 +108,9 @@ static void devm_lp8x4x_bus_release(struct device *dev, void *res)
 	dev_dbg(dev, "releasing devices\n");
 	device_unregister(&m->dev);
 	bus_unregister(&lp8x4x_bus_type);
+
+	/* Disable serial communications */
+	iowrite8(0xff, m->switch_addr);
 }
 
 static int __init lp8x4x_bus_probe(struct platform_device *pdev)
@@ -90,8 +132,9 @@ static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!res) {
+		dev_err(&pdev->dev, "Failed to get slot number address\n");
 		err = -ENODEV;
-		goto err2;
+		goto err_free;
 	}
 
 	m->count_addr = devm_ioremap_resource(&pdev->dev, res);
@@ -99,7 +142,22 @@ static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 		dev_err(&pdev->dev, "Failed to ioremap %p\n",
 		       m->count_addr);
 		err = -EFAULT;
-		goto err2;
+		goto err_free;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	if (!res) {
+		dev_err(&pdev->dev, "Failed to get slot switch address\n");
+		err = -ENODEV;
+		goto err_free;
+	}
+
+	m->switch_addr = devm_ioremap_resource(&pdev->dev, res);
+	if (!m->switch_addr) {
+		dev_err(&pdev->dev, "Failed to ioremap %p\n",
+		       m->switch_addr);
+		err = -EFAULT;
+		goto err_free;
 	}
 
 	m->slot_count = ioread8(m->count_addr);
@@ -113,15 +171,18 @@ static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 	default:
 		dev_err(&pdev->dev, "unexpected slot number(%u)",
 				m->slot_count);
-		goto err2;
+		goto err_free;
 	};
 
 	dev_info(&pdev->dev, "found bus with up to %u slots\n", m->slot_count);
 
+	/* Disable serial communications until explicitly enabled */
+	iowrite8(0xff, m->switch_addr);
+
 	err = bus_register(&lp8x4x_bus_type);
 	if (err < 0) {
 		dev_err(&pdev->dev, "failed to register bus type\n");
-		goto err3;
+		goto err_free;
 	}
 
 	m->dev.bus = &lp8x4x_bus_type;
@@ -133,15 +194,15 @@ static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 	err = device_register(&m->dev);
 	if (err < 0) {
 		dev_err(&pdev->dev, "failed to register backplane device\n");
-		goto err3;
+		goto err_bus;
 	}
 
 	devres_add(&pdev->dev, p);
 	return 0;
 
-err3:
+err_bus:
 	bus_unregister(&lp8x4x_bus_type);
-err2:
+err_free:
 	devres_free(p);
 err1:
 	kfree(m);
-- 
1.8.4.3

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

* [PATCH v2 12/16] misc: support for serial slots in LP-8x4x
@ 2013-12-13  2:27           ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-13  2:27 UTC (permalink / raw)
  To: linux-arm-kernel

Serial modules (I-870xxW series) implement DCON protocol which
allows one-master-many-slaves configuration over RS-485. When
these modules are installed into the device, they could be
accessed using the 2nd PXA built-in UART port (/dev/ttySA1).
However, it seems that addresses are not processed by the modules.
So the parallel bus needs to select which slot is connected.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
   v0..v2
   * use device tree
   * use devm helpers where possible

 .../devicetree/bindings/misc/lp8x4x-bus.txt        |  8 ++-
 Documentation/misc-devices/lp8x4x_bus.txt          | 15 ++++-
 drivers/misc/lp8x4x_bus.c                          | 75 ++++++++++++++++++++--
 3 files changed, 87 insertions(+), 11 deletions(-)

diff --git a/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt b/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
index 1c87a29..61ac96e 100644
--- a/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
+++ b/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
@@ -5,12 +5,14 @@ See Documentation/misc-devices/lp8x4x_bus.txt for details.
 Required properties:
 - compatible : should be "icpdas,backplane-lp8x4x"
 
-- reg: physical base address of the slot count register and the length
-       of the memory mapped region.
+- reg: physical base addresses and region lengths of
+       * the slot count register
+       * the serial slot select register
 
 Example:
 
 	backplane {
 		compatible = "icpdas,backplane-lp8x4x";
-		reg = <0x17009046 0x2>;
+		reg = <0x17009046 0x2
+		       0x17009004 0x2>;
 	};
diff --git a/Documentation/misc-devices/lp8x4x_bus.txt b/Documentation/misc-devices/lp8x4x_bus.txt
index f5392b3..d9a069d 100644
--- a/Documentation/misc-devices/lp8x4x_bus.txt
+++ b/Documentation/misc-devices/lp8x4x_bus.txt
@@ -19,7 +19,14 @@ LP-8x4x is an ARM-based industrial computer with a custom parallel bus to
 connect expansion modules with digital input/output, analog input/output,
 serial, CAN and other types of ports.
 
-The bus is implemented by a FPGA.
+The bus is implemented by a FPGA. There are two major groups of expansion
+modules: serial and parallel.
+
+Serial modules (I-870xxW series) implement DCON protocol which allows one-
+master-many-slaves configuration over RS-485. When these modules are installed
+into the device, they could be accessed using the 2nd PXA built-in UART port
+(/dev/ttyS1). However, it seems that addresses are not processed by
+the modules. So the parallel bus needs to select which slot is connected.
 
 SYSFS
 -----
@@ -28,3 +35,9 @@ SYSFS
 
 slot_count
 	RO - shows total number of expansion slots on the device
+
+active_slot
+	RW - connects the select slot for serial communications. If there
+	     is a parallel module in the selected slot, it simply ignores
+	     incoming packets. So it is safe to activate any available
+	     slot.
diff --git a/drivers/misc/lp8x4x_bus.c b/drivers/misc/lp8x4x_bus.c
index 7119738..cffe121 100644
--- a/drivers/misc/lp8x4x_bus.c
+++ b/drivers/misc/lp8x4x_bus.c
@@ -24,6 +24,8 @@ MODULE_DESCRIPTION("ICP DAS LP-8x4x parallel bus driver");
 struct lp8x4x_master {
 	unsigned int		slot_count;
 	void			*count_addr;
+	unsigned int		active_slot;
+	void			*switch_addr;
 	struct device		dev;
 };
 
@@ -55,8 +57,45 @@ static ssize_t slot_count_show(struct device *dev,
 
 static DEVICE_ATTR_RO(slot_count);
 
+static ssize_t active_slot_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
+
+	return sprintf(buf, "%u\n", m->active_slot);
+}
+
+static ssize_t active_slot_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
+	unsigned int active_slot = 0;
+	int err;
+
+	if (!buf)
+		return count;
+	if (0 == count)
+		return count;
+
+	err = kstrtouint(buf, 10, &active_slot);
+	if (err != 0 || !active_slot || active_slot > m->slot_count) {
+		dev_err(dev, "slot number is out of range 1..%u\n",
+				m->slot_count);
+		return count;
+	}
+
+	m->active_slot = active_slot;
+
+	iowrite8((1 << (m->active_slot - 1)) ^ 0xff, m->switch_addr);
+
+	return count;
+}
+
+static DEVICE_ATTR_RW(active_slot);
+
 static struct attribute *master_dev_attrs[] = {
 	&dev_attr_slot_count.attr,
+	&dev_attr_active_slot.attr,
 	NULL,
 };
 ATTRIBUTE_GROUPS(master_dev);
@@ -69,6 +108,9 @@ static void devm_lp8x4x_bus_release(struct device *dev, void *res)
 	dev_dbg(dev, "releasing devices\n");
 	device_unregister(&m->dev);
 	bus_unregister(&lp8x4x_bus_type);
+
+	/* Disable serial communications */
+	iowrite8(0xff, m->switch_addr);
 }
 
 static int __init lp8x4x_bus_probe(struct platform_device *pdev)
@@ -90,8 +132,9 @@ static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!res) {
+		dev_err(&pdev->dev, "Failed to get slot number address\n");
 		err = -ENODEV;
-		goto err2;
+		goto err_free;
 	}
 
 	m->count_addr = devm_ioremap_resource(&pdev->dev, res);
@@ -99,7 +142,22 @@ static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 		dev_err(&pdev->dev, "Failed to ioremap %p\n",
 		       m->count_addr);
 		err = -EFAULT;
-		goto err2;
+		goto err_free;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	if (!res) {
+		dev_err(&pdev->dev, "Failed to get slot switch address\n");
+		err = -ENODEV;
+		goto err_free;
+	}
+
+	m->switch_addr = devm_ioremap_resource(&pdev->dev, res);
+	if (!m->switch_addr) {
+		dev_err(&pdev->dev, "Failed to ioremap %p\n",
+		       m->switch_addr);
+		err = -EFAULT;
+		goto err_free;
 	}
 
 	m->slot_count = ioread8(m->count_addr);
@@ -113,15 +171,18 @@ static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 	default:
 		dev_err(&pdev->dev, "unexpected slot number(%u)",
 				m->slot_count);
-		goto err2;
+		goto err_free;
 	};
 
 	dev_info(&pdev->dev, "found bus with up to %u slots\n", m->slot_count);
 
+	/* Disable serial communications until explicitly enabled */
+	iowrite8(0xff, m->switch_addr);
+
 	err = bus_register(&lp8x4x_bus_type);
 	if (err < 0) {
 		dev_err(&pdev->dev, "failed to register bus type\n");
-		goto err3;
+		goto err_free;
 	}
 
 	m->dev.bus = &lp8x4x_bus_type;
@@ -133,15 +194,15 @@ static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 	err = device_register(&m->dev);
 	if (err < 0) {
 		dev_err(&pdev->dev, "failed to register backplane device\n");
-		goto err3;
+		goto err_bus;
 	}
 
 	devres_add(&pdev->dev, p);
 	return 0;
 
-err3:
+err_bus:
 	bus_unregister(&lp8x4x_bus_type);
-err2:
+err_free:
 	devres_free(p);
 err1:
 	kfree(m);
-- 
1.8.4.3

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

* [PATCH v2 13/16] misc: support for parallel slots in LP-8x4x
  2013-12-13  2:27         ` Sergei Ianovich
@ 2013-12-13  2:27           ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-13  2:27 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Rob Landley, Arnd Bergmann, Greg Kroah-Hartman,
	open list:DOCUMENTATION

This patch enumerates parallel modules in expansion slots and exposes
model numbers via sysfs.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
   v0..v2
   * use device tree
   * use devm helpers where possible

 Documentation/misc-devices/lp8x4x_bus.txt |   8 ++
 drivers/misc/lp8x4x_bus.c                 | 120 ++++++++++++++++++++++++++++++
 2 files changed, 128 insertions(+)

diff --git a/Documentation/misc-devices/lp8x4x_bus.txt b/Documentation/misc-devices/lp8x4x_bus.txt
index d9a069d..9285fdc 100644
--- a/Documentation/misc-devices/lp8x4x_bus.txt
+++ b/Documentation/misc-devices/lp8x4x_bus.txt
@@ -28,6 +28,9 @@ into the device, they could be accessed using the 2nd PXA built-in UART port
 (/dev/ttySA1). However, it seems that addresses are not processed by
 the modules. So the parallel bus needs to select which slot is connected.
 
+Parallel modules allow much faster communication. There are accessed using
+IO memory through the FPGA. Their ports are exposed via sysfs.
+
 SYSFS
 -----
 
@@ -41,3 +44,8 @@ active_slot
 	     is a parallel module in the selected slot, it simply ignores
 	     incoming packets. So it is safe to activate any available
 	     slot.
+
+/sys/bus/icpdas/devices/slot%02i:
+
+model
+	RO - shows expansion module model number
diff --git a/drivers/misc/lp8x4x_bus.c b/drivers/misc/lp8x4x_bus.c
index cffe121..324e922 100644
--- a/drivers/misc/lp8x4x_bus.c
+++ b/drivers/misc/lp8x4x_bus.c
@@ -21,14 +21,57 @@ MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Sergei Ianovich <ynvich@gmail.com>");
 MODULE_DESCRIPTION("ICP DAS LP-8x4x parallel bus driver");
 
+struct lp8x4x_slot {
+	void			*data_addr;
+	unsigned int		model;
+	struct device		dev;
+};
+
+#define LP8X4X_MAX_SLOT_COUNT	8
 struct lp8x4x_master {
 	unsigned int		slot_count;
 	void			*count_addr;
 	unsigned int		active_slot;
 	void			*switch_addr;
+	struct lp8x4x_slot	slot[LP8X4X_MAX_SLOT_COUNT];
 	struct device		dev;
 };
 
+static unsigned char lp8x4x_model[256] = {
+	   0,    0,    0, 0x11,    0, 0x18, 0x13, 0x11,
+	0x0e, 0x11,    0,    0,    0, 0x5a, 0x5b, 0x5c,
+	0x3c, 0x44, 0x34, 0x3a, 0x39, 0x36, 0x37, 0x33,
+	0x35, 0x40, 0x41, 0x42, 0x38, 0x3f, 0x32, 0x45,
+	0xac, 0x70, 0x8e, 0x8e, 0x1e, 0x72, 0x90, 0x29,
+	0x4a, 0x22, 0xd3, 0xd2, 0x28, 0x25, 0x2a, 0x29,
+	0x48, 0x49, 0x5d, 0x1f, 0x20, 0x23, 0x24, 0x4d,
+	0x3d, 0x3e,    0,    0,    0,    0,    0,    0,
+	   0, 0x78, 0x72, 0x2b, 0x5e, 0x5e, 0x36, 0xae,
+	0x30,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0, 0x5c, 0x5e,    0, 0x5e,    0,    0,
+	   0, 0x3b,    0,    0,    0,    0,    0,    0,
+	   0, 0x50, 0x2e,    0, 0x58,    0,    0, 0x43,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0, 0x54,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0
+};
+
 static int lp8x4x_match(struct device *dev, struct device_driver *drv)
 {
 	return 1;
@@ -39,6 +82,26 @@ static struct bus_type lp8x4x_bus_type = {
 	.match		= lp8x4x_match,
 };
 
+static void lp8x4x_slot_release(struct device *dev)
+{
+}
+
+static ssize_t model_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct lp8x4x_slot *s = container_of(dev, struct lp8x4x_slot, dev);
+
+	return sprintf(buf, "%u\n", s->model + 8000);
+}
+
+static DEVICE_ATTR_RO(model);
+
+static struct attribute *slot_dev_attrs[] = {
+	&dev_attr_model.attr,
+	NULL,
+};
+ATTRIBUTE_GROUPS(slot_dev);
+
 static void lp8x4x_master_release(struct device *dev)
 {
 	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
@@ -104,8 +167,15 @@ ATTRIBUTE_GROUPS(master_dev);
 static void devm_lp8x4x_bus_release(struct device *dev, void *res)
 {
 	struct lp8x4x_master *m = *(struct lp8x4x_master **)res;
+	struct lp8x4x_slot *s;
+	int i;
 
 	dev_dbg(dev, "releasing devices\n");
+	for (i = 0; i < LP8X4X_MAX_SLOT_COUNT; i++) {
+		s = &m->slot[i];
+		if (s->model)
+			device_unregister(&s->dev);
+	}
 	device_unregister(&m->dev);
 	bus_unregister(&lp8x4x_bus_type);
 
@@ -113,11 +183,36 @@ static void devm_lp8x4x_bus_release(struct device *dev, void *res)
 	iowrite8(0xff, m->switch_addr);
 }
 
+static void __init lp8x4x_bus_probe_slot(struct lp8x4x_master *m, int i,
+		unsigned char model)
+{
+	struct lp8x4x_slot *s = &m->slot[i];
+	int err;
+
+	dev_info(&m->dev, "found %u in slot %i\n", 8000 + model, i + 1);
+
+	s->dev.bus = &lp8x4x_bus_type;
+	dev_set_name(&s->dev, "slot%02i", i + 1);
+	s->dev.parent = &m->dev;
+	s->dev.release = lp8x4x_slot_release;
+	s->dev.groups = slot_dev_groups;
+	s->model = model;
+
+	err = device_register(&s->dev);
+	if (err < 0) {
+		dev_err(&s->dev, "failed to register device\n");
+		s->model = 0;
+		return;
+	}
+}
+
 static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 {
 	struct lp8x4x_master *m, **p;
 	struct resource *res;
+	int i;
 	int err = 0;
+	unsigned int model;
 
 	m = kzalloc(sizeof(*m), GFP_KERNEL);
 	if (!m)
@@ -160,6 +255,24 @@ static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 		goto err_free;
 	}
 
+	for (i = 0; i < LP8X4X_MAX_SLOT_COUNT; i++) {
+		res = platform_get_resource(pdev, IORESOURCE_MEM, i + 2);
+		if (!res) {
+			dev_err(&pdev->dev, "Failed to get slot %i address\n",
+					i);
+			err = -ENODEV;
+			goto err_free;
+		}
+
+		m->slot[i].data_addr = devm_ioremap_resource(&pdev->dev, res);
+		if (!m->slot[i].data_addr) {
+			dev_err(&pdev->dev, "Failed to ioremap %p\n",
+					m->slot[i].data_addr);
+			err = -EFAULT;
+			goto err_free;
+		}
+	}
+
 	m->slot_count = ioread8(m->count_addr);
 	switch (m->slot_count) {
 	case 1:
@@ -198,6 +311,13 @@ static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 	}
 
 	devres_add(&pdev->dev, p);
+	for (i = 0; i < LP8X4X_MAX_SLOT_COUNT; i++) {
+		model = lp8x4x_model[ioread8(m->slot[i].data_addr)];
+		if (!model)
+			continue;
+
+		lp8x4x_bus_probe_slot(m, i, model);
+	}
 	return 0;
 
 err_bus:
-- 
1.8.4.3


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

* [PATCH v2 13/16] misc: support for parallel slots in LP-8x4x
@ 2013-12-13  2:27           ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-13  2:27 UTC (permalink / raw)
  To: linux-arm-kernel

This patch enumerates parallel modules in expansion slots and exposes
model numbers via sysfs.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
   v0..v2
   * use device tree
   * use devm helpers where possible

 Documentation/misc-devices/lp8x4x_bus.txt |   8 ++
 drivers/misc/lp8x4x_bus.c                 | 120 ++++++++++++++++++++++++++++++
 2 files changed, 128 insertions(+)

diff --git a/Documentation/misc-devices/lp8x4x_bus.txt b/Documentation/misc-devices/lp8x4x_bus.txt
index d9a069d..9285fdc 100644
--- a/Documentation/misc-devices/lp8x4x_bus.txt
+++ b/Documentation/misc-devices/lp8x4x_bus.txt
@@ -28,6 +28,9 @@ into the device, they could be accessed using the 2nd PXA built-in UART port
 (/dev/ttySA1). However, it seems that addresses are not processed by
 the modules. So the parallel bus needs to select which slot is connected.
 
+Parallel modules allow much faster communication. There are accessed using
+IO memory through the FPGA. Their ports are exposed via sysfs.
+
 SYSFS
 -----
 
@@ -41,3 +44,8 @@ active_slot
 	     is a parallel module in the selected slot, it simply ignores
 	     incoming packets. So it is safe to activate any available
 	     slot.
+
+/sys/bus/icpdas/devices/slot%02i:
+
+model
+	RO - shows expansion module model number
diff --git a/drivers/misc/lp8x4x_bus.c b/drivers/misc/lp8x4x_bus.c
index cffe121..324e922 100644
--- a/drivers/misc/lp8x4x_bus.c
+++ b/drivers/misc/lp8x4x_bus.c
@@ -21,14 +21,57 @@ MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Sergei Ianovich <ynvich@gmail.com>");
 MODULE_DESCRIPTION("ICP DAS LP-8x4x parallel bus driver");
 
+struct lp8x4x_slot {
+	void			*data_addr;
+	unsigned int		model;
+	struct device		dev;
+};
+
+#define LP8X4X_MAX_SLOT_COUNT	8
 struct lp8x4x_master {
 	unsigned int		slot_count;
 	void			*count_addr;
 	unsigned int		active_slot;
 	void			*switch_addr;
+	struct lp8x4x_slot	slot[LP8X4X_MAX_SLOT_COUNT];
 	struct device		dev;
 };
 
+static unsigned char lp8x4x_model[256] = {
+	   0,    0,    0, 0x11,    0, 0x18, 0x13, 0x11,
+	0x0e, 0x11,    0,    0,    0, 0x5a, 0x5b, 0x5c,
+	0x3c, 0x44, 0x34, 0x3a, 0x39, 0x36, 0x37, 0x33,
+	0x35, 0x40, 0x41, 0x42, 0x38, 0x3f, 0x32, 0x45,
+	0xac, 0x70, 0x8e, 0x8e, 0x1e, 0x72, 0x90, 0x29,
+	0x4a, 0x22, 0xd3, 0xd2, 0x28, 0x25, 0x2a, 0x29,
+	0x48, 0x49, 0x5d, 0x1f, 0x20, 0x23, 0x24, 0x4d,
+	0x3d, 0x3e,    0,    0,    0,    0,    0,    0,
+	   0, 0x78, 0x72, 0x2b, 0x5e, 0x5e, 0x36, 0xae,
+	0x30,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0, 0x5c, 0x5e,    0, 0x5e,    0,    0,
+	   0, 0x3b,    0,    0,    0,    0,    0,    0,
+	   0, 0x50, 0x2e,    0, 0x58,    0,    0, 0x43,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0, 0x54,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0
+};
+
 static int lp8x4x_match(struct device *dev, struct device_driver *drv)
 {
 	return 1;
@@ -39,6 +82,26 @@ static struct bus_type lp8x4x_bus_type = {
 	.match		= lp8x4x_match,
 };
 
+static void lp8x4x_slot_release(struct device *dev)
+{
+}
+
+static ssize_t model_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct lp8x4x_slot *s = container_of(dev, struct lp8x4x_slot, dev);
+
+	return sprintf(buf, "%u\n", s->model + 8000);
+}
+
+static DEVICE_ATTR_RO(model);
+
+static struct attribute *slot_dev_attrs[] = {
+	&dev_attr_model.attr,
+	NULL,
+};
+ATTRIBUTE_GROUPS(slot_dev);
+
 static void lp8x4x_master_release(struct device *dev)
 {
 	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
@@ -104,8 +167,15 @@ ATTRIBUTE_GROUPS(master_dev);
 static void devm_lp8x4x_bus_release(struct device *dev, void *res)
 {
 	struct lp8x4x_master *m = *(struct lp8x4x_master **)res;
+	struct lp8x4x_slot *s;
+	int i;
 
 	dev_dbg(dev, "releasing devices\n");
+	for (i = 0; i < LP8X4X_MAX_SLOT_COUNT; i++) {
+		s = &m->slot[i];
+		if (s->model)
+			device_unregister(&s->dev);
+	}
 	device_unregister(&m->dev);
 	bus_unregister(&lp8x4x_bus_type);
 
@@ -113,11 +183,36 @@ static void devm_lp8x4x_bus_release(struct device *dev, void *res)
 	iowrite8(0xff, m->switch_addr);
 }
 
+static void __init lp8x4x_bus_probe_slot(struct lp8x4x_master *m, int i,
+		unsigned char model)
+{
+	struct lp8x4x_slot *s = &m->slot[i];
+	int err;
+
+	dev_info(&m->dev, "found %u in slot %i\n", 8000 + model, i + 1);
+
+	s->dev.bus = &lp8x4x_bus_type;
+	dev_set_name(&s->dev, "slot%02i", i + 1);
+	s->dev.parent = &m->dev;
+	s->dev.release = lp8x4x_slot_release;
+	s->dev.groups = slot_dev_groups;
+	s->model = model;
+
+	err = device_register(&s->dev);
+	if (err < 0) {
+		dev_err(&s->dev, "failed to register device\n");
+		s->model = 0;
+		return;
+	}
+}
+
 static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 {
 	struct lp8x4x_master *m, **p;
 	struct resource *res;
+	int i;
 	int err = 0;
+	unsigned int model;
 
 	m = kzalloc(sizeof(*m), GFP_KERNEL);
 	if (!m)
@@ -160,6 +255,24 @@ static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 		goto err_free;
 	}
 
+	for (i = 0; i < LP8X4X_MAX_SLOT_COUNT; i++) {
+		res = platform_get_resource(pdev, IORESOURCE_MEM, i + 2);
+		if (!res) {
+			dev_err(&pdev->dev, "Failed to get slot %i address\n",
+					i);
+			err = -ENODEV;
+			goto err_free;
+		}
+
+		m->slot[i].data_addr = devm_ioremap_resource(&pdev->dev, res);
+		if (!m->slot[i].data_addr) {
+			dev_err(&pdev->dev, "Failed to ioremap %p\n",
+					m->slot[i].data_addr);
+			err = -EFAULT;
+			goto err_free;
+		}
+	}
+
 	m->slot_count = ioread8(m->count_addr);
 	switch (m->slot_count) {
 	case 1:
@@ -198,6 +311,13 @@ static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 	}
 
 	devres_add(&pdev->dev, p);
+	for (i = 0; i < LP8X4X_MAX_SLOT_COUNT; i++) {
+		model = lp8x4x_model[ioread8(m->slot[i].data_addr)];
+		if (!model)
+			continue;
+
+		lp8x4x_bus_probe_slot(m, i, model);
+	}
 	return 0;
 
 err_bus:
-- 
1.8.4.3

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

* [PATCH v2 14/16] misc: support for I-8041 in LP-8x4x
  2013-12-13  2:27         ` Sergei Ianovich
@ 2013-12-13  2:27           ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-13  2:27 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Rob Landley, Arnd Bergmann, Greg Kroah-Hartman,
	open list:DOCUMENTATION

Status of I-8041 32 digital output channels can be managed via
sysfs now.

http://www.icpdas.com/products/Remote_IO/i-8ke/i-8041w.htm

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
   v0..v2
   * no changes

 Documentation/misc-devices/lp8x4x_bus.txt |  4 ++
 drivers/misc/lp8x4x_bus.c                 | 67 ++++++++++++++++++++++++++++++-
 2 files changed, 69 insertions(+), 2 deletions(-)

diff --git a/Documentation/misc-devices/lp8x4x_bus.txt b/Documentation/misc-devices/lp8x4x_bus.txt
index 9285fdc..74df10b 100644
--- a/Documentation/misc-devices/lp8x4x_bus.txt
+++ b/Documentation/misc-devices/lp8x4x_bus.txt
@@ -49,3 +49,7 @@ active_slot
 
 model
 	RO - shows expansion module model number
+
+output_status
+	RW - set status of digital output channels on the module in
+	     the expansion slot. Value can be read back.
diff --git a/drivers/misc/lp8x4x_bus.c b/drivers/misc/lp8x4x_bus.c
index 324e922..1ef1726 100644
--- a/drivers/misc/lp8x4x_bus.c
+++ b/drivers/misc/lp8x4x_bus.c
@@ -24,6 +24,9 @@ MODULE_DESCRIPTION("ICP DAS LP-8x4x parallel bus driver");
 struct lp8x4x_slot {
 	void			*data_addr;
 	unsigned int		model;
+	struct mutex		lock;
+	unsigned int		DO_len;
+	u32			DO;
 	struct device		dev;
 };
 
@@ -86,6 +89,45 @@ static void lp8x4x_slot_release(struct device *dev)
 {
 }
 
+static void lp8x4x_slot_set_DO(struct lp8x4x_slot *s)
+{
+	int i;
+	mutex_lock(&s->lock);
+	for (i = 0; i < s->DO_len; i++)
+		iowrite8((s->DO >> (i * 8)) & 0xff, s->data_addr + 2 * i);
+	mutex_unlock(&s->lock);
+}
+
+static ssize_t output_status_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct lp8x4x_slot *s = container_of(dev, struct lp8x4x_slot, dev);
+
+	return sprintf(buf, "0x%08x\n", s->DO);
+}
+
+static ssize_t output_status_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct lp8x4x_slot *s = container_of(dev, struct lp8x4x_slot, dev);
+
+	if (!buf)
+		return count;
+	if (0 == count)
+		return count;
+
+	if (kstrtouint(buf, 16, &s->DO) != 0) {
+		dev_err(dev, "bad input\n");
+		return count;
+	}
+
+	lp8x4x_slot_set_DO(s);
+
+	return count;
+}
+
+static DEVICE_ATTR_RW(output_status);
+
 static ssize_t model_show(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
@@ -102,6 +144,13 @@ static struct attribute *slot_dev_attrs[] = {
 };
 ATTRIBUTE_GROUPS(slot_dev);
 
+static struct attribute *do_slot_dev_attrs[] = {
+	&dev_attr_model.attr,
+	&dev_attr_output_status.attr,
+	NULL,
+};
+ATTRIBUTE_GROUPS(do_slot_dev);
+
 static void lp8x4x_master_release(struct device *dev)
 {
 	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
@@ -173,8 +222,10 @@ static void devm_lp8x4x_bus_release(struct device *dev, void *res)
 	dev_dbg(dev, "releasing devices\n");
 	for (i = 0; i < LP8X4X_MAX_SLOT_COUNT; i++) {
 		s = &m->slot[i];
-		if (s->model)
+		if (s->model) {
 			device_unregister(&s->dev);
+			mutex_destroy(&s->lock);
+		}
 	}
 	device_unregister(&m->dev);
 	bus_unregister(&lp8x4x_bus_type);
@@ -195,13 +246,25 @@ static void __init lp8x4x_bus_probe_slot(struct lp8x4x_master *m, int i,
 	dev_set_name(&s->dev, "slot%02i", i + 1);
 	s->dev.parent = &m->dev;
 	s->dev.release = lp8x4x_slot_release;
-	s->dev.groups = slot_dev_groups;
 	s->model = model;
+	mutex_init(&s->lock);
+
+	switch (model) {
+	case 41:
+		s->DO_len = 4;
+		lp8x4x_slot_set_DO(s);
+		s->dev.groups = do_slot_dev_groups;
+		break;
+	default:
+		s->dev.groups = slot_dev_groups;
+		break;
+	};
 
 	err = device_register(&s->dev);
 	if (err < 0) {
 		dev_err(&s->dev, "failed to register device\n");
 		s->model = 0;
+		mutex_destroy(&s->lock);
 		return;
 	}
 }
-- 
1.8.4.3


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

* [PATCH v2 14/16] misc: support for I-8041 in LP-8x4x
@ 2013-12-13  2:27           ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-13  2:27 UTC (permalink / raw)
  To: linux-arm-kernel

Status of I-8041 32 digital output channels can be managed via
sysfs now.

http://www.icpdas.com/products/Remote_IO/i-8ke/i-8041w.htm

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
   v0..v2
   * no changes

 Documentation/misc-devices/lp8x4x_bus.txt |  4 ++
 drivers/misc/lp8x4x_bus.c                 | 67 ++++++++++++++++++++++++++++++-
 2 files changed, 69 insertions(+), 2 deletions(-)

diff --git a/Documentation/misc-devices/lp8x4x_bus.txt b/Documentation/misc-devices/lp8x4x_bus.txt
index 9285fdc..74df10b 100644
--- a/Documentation/misc-devices/lp8x4x_bus.txt
+++ b/Documentation/misc-devices/lp8x4x_bus.txt
@@ -49,3 +49,7 @@ active_slot
 
 model
 	RO - shows expansion module model number
+
+output_status
+	RW - set status of digital output channels on the module in
+	     the expansion slot. Value can be read back.
diff --git a/drivers/misc/lp8x4x_bus.c b/drivers/misc/lp8x4x_bus.c
index 324e922..1ef1726 100644
--- a/drivers/misc/lp8x4x_bus.c
+++ b/drivers/misc/lp8x4x_bus.c
@@ -24,6 +24,9 @@ MODULE_DESCRIPTION("ICP DAS LP-8x4x parallel bus driver");
 struct lp8x4x_slot {
 	void			*data_addr;
 	unsigned int		model;
+	struct mutex		lock;
+	unsigned int		DO_len;
+	u32			DO;
 	struct device		dev;
 };
 
@@ -86,6 +89,45 @@ static void lp8x4x_slot_release(struct device *dev)
 {
 }
 
+static void lp8x4x_slot_set_DO(struct lp8x4x_slot *s)
+{
+	int i;
+	mutex_lock(&s->lock);
+	for (i = 0; i < s->DO_len; i++)
+		iowrite8((s->DO >> (i * 8)) & 0xff, s->data_addr + 2 * i);
+	mutex_unlock(&s->lock);
+}
+
+static ssize_t output_status_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct lp8x4x_slot *s = container_of(dev, struct lp8x4x_slot, dev);
+
+	return sprintf(buf, "0x%08x\n", s->DO);
+}
+
+static ssize_t output_status_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct lp8x4x_slot *s = container_of(dev, struct lp8x4x_slot, dev);
+
+	if (!buf)
+		return count;
+	if (0 == count)
+		return count;
+
+	if (kstrtouint(buf, 16, &s->DO) != 0) {
+		dev_err(dev, "bad input\n");
+		return count;
+	}
+
+	lp8x4x_slot_set_DO(s);
+
+	return count;
+}
+
+static DEVICE_ATTR_RW(output_status);
+
 static ssize_t model_show(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
@@ -102,6 +144,13 @@ static struct attribute *slot_dev_attrs[] = {
 };
 ATTRIBUTE_GROUPS(slot_dev);
 
+static struct attribute *do_slot_dev_attrs[] = {
+	&dev_attr_model.attr,
+	&dev_attr_output_status.attr,
+	NULL,
+};
+ATTRIBUTE_GROUPS(do_slot_dev);
+
 static void lp8x4x_master_release(struct device *dev)
 {
 	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
@@ -173,8 +222,10 @@ static void devm_lp8x4x_bus_release(struct device *dev, void *res)
 	dev_dbg(dev, "releasing devices\n");
 	for (i = 0; i < LP8X4X_MAX_SLOT_COUNT; i++) {
 		s = &m->slot[i];
-		if (s->model)
+		if (s->model) {
 			device_unregister(&s->dev);
+			mutex_destroy(&s->lock);
+		}
 	}
 	device_unregister(&m->dev);
 	bus_unregister(&lp8x4x_bus_type);
@@ -195,13 +246,25 @@ static void __init lp8x4x_bus_probe_slot(struct lp8x4x_master *m, int i,
 	dev_set_name(&s->dev, "slot%02i", i + 1);
 	s->dev.parent = &m->dev;
 	s->dev.release = lp8x4x_slot_release;
-	s->dev.groups = slot_dev_groups;
 	s->model = model;
+	mutex_init(&s->lock);
+
+	switch (model) {
+	case 41:
+		s->DO_len = 4;
+		lp8x4x_slot_set_DO(s);
+		s->dev.groups = do_slot_dev_groups;
+		break;
+	default:
+		s->dev.groups = slot_dev_groups;
+		break;
+	};
 
 	err = device_register(&s->dev);
 	if (err < 0) {
 		dev_err(&s->dev, "failed to register device\n");
 		s->model = 0;
+		mutex_destroy(&s->lock);
 		return;
 	}
 }
-- 
1.8.4.3

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

* [PATCH v2 15/16] misc: support for I-8042 in LP-8x4x
  2013-12-13  2:27         ` Sergei Ianovich
@ 2013-12-13  2:27           ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-13  2:27 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Rob Landley, Arnd Bergmann, Greg Kroah-Hartman,
	open list:DOCUMENTATION

Status of I-8042 16 digital output channels can be managed via
sysfs.

Status of I-8042 16 digital input channels can be read via sysfs.

http://www.icpdas.com/products/Remote_IO/i-8ke/i-8042w.htm

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
   v0..v2
   * no changes

 Documentation/misc-devices/lp8x4x_bus.txt |  4 ++
 drivers/misc/lp8x4x_bus.c                 | 76 ++++++++++++++++++++++++++++++-
 2 files changed, 78 insertions(+), 2 deletions(-)

diff --git a/Documentation/misc-devices/lp8x4x_bus.txt b/Documentation/misc-devices/lp8x4x_bus.txt
index 74df10b..e3a8bcf 100644
--- a/Documentation/misc-devices/lp8x4x_bus.txt
+++ b/Documentation/misc-devices/lp8x4x_bus.txt
@@ -50,6 +50,10 @@ active_slot
 model
 	RO - shows expansion module model number
 
+input_status
+	RO - get status of digital input channels on the module in
+	     the expansion slot.
+
 output_status
 	RW - set status of digital output channels on the module in
 	     the expansion slot. Value can be read back.
diff --git a/drivers/misc/lp8x4x_bus.c b/drivers/misc/lp8x4x_bus.c
index 1ef1726..684e640 100644
--- a/drivers/misc/lp8x4x_bus.c
+++ b/drivers/misc/lp8x4x_bus.c
@@ -27,6 +27,8 @@ struct lp8x4x_slot {
 	struct mutex		lock;
 	unsigned int		DO_len;
 	u32			DO;
+	unsigned int		DI_len;
+	u32			DI;
 	struct device		dev;
 };
 
@@ -89,6 +91,21 @@ static void lp8x4x_slot_release(struct device *dev)
 {
 }
 
+static void lp8x4x_slot_get_DI(struct lp8x4x_slot *s)
+{
+	int i;
+	u32 b;
+
+	mutex_lock(&s->lock);
+	s->DI = 0;
+	for (i = 0; i < s->DI_len; i++) {
+		b = ioread8(s->data_addr + 2 * (i + 1));
+		b ^= 0xff;
+		s->DI += b << (i * 8);
+	}
+	mutex_unlock(&s->lock);
+}
+
 static void lp8x4x_slot_set_DO(struct lp8x4x_slot *s)
 {
 	int i;
@@ -98,29 +115,70 @@ static void lp8x4x_slot_set_DO(struct lp8x4x_slot *s)
 	mutex_unlock(&s->lock);
 }
 
+static ssize_t input_status_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct lp8x4x_slot *s = container_of(dev, struct lp8x4x_slot, dev);
+
+	lp8x4x_slot_get_DI(s);
+	switch (s->DI_len) {
+	case 4:
+		return sprintf(buf, "0x%08x\n", s->DI);
+	case 2:
+		return sprintf(buf, "0x%04x\n", s->DI);
+	case 1:
+		return sprintf(buf, "0x%02x\n", s->DI);
+	default:
+		break;
+	}
+	return sprintf(buf, "0x%x\n", s->DI);
+}
+
+static DEVICE_ATTR_RO(input_status);
+
 static ssize_t output_status_show(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
 	struct lp8x4x_slot *s = container_of(dev, struct lp8x4x_slot, dev);
 
-	return sprintf(buf, "0x%08x\n", s->DO);
+	switch (s->DO_len) {
+	case 4:
+		return sprintf(buf, "0x%08x\n", s->DO);
+	case 2:
+		return sprintf(buf, "0x%04x\n", s->DO);
+	case 1:
+		return sprintf(buf, "0x%02x\n", s->DO);
+	default:
+		break;
+	}
+	return sprintf(buf, "0x%x\n", s->DO);
 }
 
 static ssize_t output_status_store(struct device *dev,
 		struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct lp8x4x_slot *s = container_of(dev, struct lp8x4x_slot, dev);
+	u32 DO;
+	u8 *b = (void *) &DO;
+	int i;
 
 	if (!buf)
 		return count;
 	if (0 == count)
 		return count;
 
-	if (kstrtouint(buf, 16, &s->DO) != 0) {
+	if (kstrtouint(buf, 16, &DO) != 0) {
 		dev_err(dev, "bad input\n");
 		return count;
 	}
 
+	for (i = 4; i > s->DO_len; i--)
+		if (b[i - 1] != 0) {
+			dev_err(dev, "bad input\n");
+			return count;
+		}
+
+	s->DO = DO;
 	lp8x4x_slot_set_DO(s);
 
 	return count;
@@ -151,6 +209,14 @@ static struct attribute *do_slot_dev_attrs[] = {
 };
 ATTRIBUTE_GROUPS(do_slot_dev);
 
+static struct attribute *dio_slot_dev_attrs[] = {
+	&dev_attr_model.attr,
+	&dev_attr_output_status.attr,
+	&dev_attr_input_status.attr,
+	NULL,
+};
+ATTRIBUTE_GROUPS(dio_slot_dev);
+
 static void lp8x4x_master_release(struct device *dev)
 {
 	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
@@ -255,6 +321,12 @@ static void __init lp8x4x_bus_probe_slot(struct lp8x4x_master *m, int i,
 		lp8x4x_slot_set_DO(s);
 		s->dev.groups = do_slot_dev_groups;
 		break;
+	case 42:
+		s->DI_len = 2;
+		s->DO_len = 2;
+		lp8x4x_slot_set_DO(s);
+		s->dev.groups = dio_slot_dev_groups;
+		break;
 	default:
 		s->dev.groups = slot_dev_groups;
 		break;
-- 
1.8.4.3


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

* [PATCH v2 15/16] misc: support for I-8042 in LP-8x4x
@ 2013-12-13  2:27           ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-13  2:27 UTC (permalink / raw)
  To: linux-arm-kernel

Status of I-8042 16 digital output channels can be managed via
sysfs.

Status of I-8042 16 digital input channels can be read via sysfs.

http://www.icpdas.com/products/Remote_IO/i-8ke/i-8042w.htm

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
   v0..v2
   * no changes

 Documentation/misc-devices/lp8x4x_bus.txt |  4 ++
 drivers/misc/lp8x4x_bus.c                 | 76 ++++++++++++++++++++++++++++++-
 2 files changed, 78 insertions(+), 2 deletions(-)

diff --git a/Documentation/misc-devices/lp8x4x_bus.txt b/Documentation/misc-devices/lp8x4x_bus.txt
index 74df10b..e3a8bcf 100644
--- a/Documentation/misc-devices/lp8x4x_bus.txt
+++ b/Documentation/misc-devices/lp8x4x_bus.txt
@@ -50,6 +50,10 @@ active_slot
 model
 	RO - shows expansion module model number
 
+input_status
+	RO - get status of digital input channels on the module in
+	     the expansion slot.
+
 output_status
 	RW - set status of digital output channels on the module in
 	     the expansion slot. Value can be read back.
diff --git a/drivers/misc/lp8x4x_bus.c b/drivers/misc/lp8x4x_bus.c
index 1ef1726..684e640 100644
--- a/drivers/misc/lp8x4x_bus.c
+++ b/drivers/misc/lp8x4x_bus.c
@@ -27,6 +27,8 @@ struct lp8x4x_slot {
 	struct mutex		lock;
 	unsigned int		DO_len;
 	u32			DO;
+	unsigned int		DI_len;
+	u32			DI;
 	struct device		dev;
 };
 
@@ -89,6 +91,21 @@ static void lp8x4x_slot_release(struct device *dev)
 {
 }
 
+static void lp8x4x_slot_get_DI(struct lp8x4x_slot *s)
+{
+	int i;
+	u32 b;
+
+	mutex_lock(&s->lock);
+	s->DI = 0;
+	for (i = 0; i < s->DI_len; i++) {
+		b = ioread8(s->data_addr + 2 * (i + 1));
+		b ^= 0xff;
+		s->DI += b << (i * 8);
+	}
+	mutex_unlock(&s->lock);
+}
+
 static void lp8x4x_slot_set_DO(struct lp8x4x_slot *s)
 {
 	int i;
@@ -98,29 +115,70 @@ static void lp8x4x_slot_set_DO(struct lp8x4x_slot *s)
 	mutex_unlock(&s->lock);
 }
 
+static ssize_t input_status_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct lp8x4x_slot *s = container_of(dev, struct lp8x4x_slot, dev);
+
+	lp8x4x_slot_get_DI(s);
+	switch (s->DI_len) {
+	case 4:
+		return sprintf(buf, "0x%08x\n", s->DI);
+	case 2:
+		return sprintf(buf, "0x%04x\n", s->DI);
+	case 1:
+		return sprintf(buf, "0x%02x\n", s->DI);
+	default:
+		break;
+	}
+	return sprintf(buf, "0x%x\n", s->DI);
+}
+
+static DEVICE_ATTR_RO(input_status);
+
 static ssize_t output_status_show(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
 	struct lp8x4x_slot *s = container_of(dev, struct lp8x4x_slot, dev);
 
-	return sprintf(buf, "0x%08x\n", s->DO);
+	switch (s->DO_len) {
+	case 4:
+		return sprintf(buf, "0x%08x\n", s->DO);
+	case 2:
+		return sprintf(buf, "0x%04x\n", s->DO);
+	case 1:
+		return sprintf(buf, "0x%02x\n", s->DO);
+	default:
+		break;
+	}
+	return sprintf(buf, "0x%x\n", s->DO);
 }
 
 static ssize_t output_status_store(struct device *dev,
 		struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct lp8x4x_slot *s = container_of(dev, struct lp8x4x_slot, dev);
+	u32 DO;
+	u8 *b = (void *) &DO;
+	int i;
 
 	if (!buf)
 		return count;
 	if (0 == count)
 		return count;
 
-	if (kstrtouint(buf, 16, &s->DO) != 0) {
+	if (kstrtouint(buf, 16, &DO) != 0) {
 		dev_err(dev, "bad input\n");
 		return count;
 	}
 
+	for (i = 4; i > s->DO_len; i--)
+		if (b[i - 1] != 0) {
+			dev_err(dev, "bad input\n");
+			return count;
+		}
+
+	s->DO = DO;
 	lp8x4x_slot_set_DO(s);
 
 	return count;
@@ -151,6 +209,14 @@ static struct attribute *do_slot_dev_attrs[] = {
 };
 ATTRIBUTE_GROUPS(do_slot_dev);
 
+static struct attribute *dio_slot_dev_attrs[] = {
+	&dev_attr_model.attr,
+	&dev_attr_output_status.attr,
+	&dev_attr_input_status.attr,
+	NULL,
+};
+ATTRIBUTE_GROUPS(dio_slot_dev);
+
 static void lp8x4x_master_release(struct device *dev)
 {
 	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
@@ -255,6 +321,12 @@ static void __init lp8x4x_bus_probe_slot(struct lp8x4x_master *m, int i,
 		lp8x4x_slot_set_DO(s);
 		s->dev.groups = do_slot_dev_groups;
 		break;
+	case 42:
+		s->DI_len = 2;
+		s->DO_len = 2;
+		lp8x4x_slot_set_DO(s);
+		s->dev.groups = dio_slot_dev_groups;
+		break;
 	default:
 		s->dev.groups = slot_dev_groups;
 		break;
-- 
1.8.4.3

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

* [PATCH v2 16/16] misc: support for I-8024 in LP-8x4x
  2013-12-13  2:27         ` Sergei Ianovich
@ 2013-12-13  2:27           ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-13  2:27 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Rob Landley, Arnd Bergmann, Greg Kroah-Hartman,
	open list:DOCUMENTATION

Status of I-8042 4 analog output channels can be managed via
sysfs.

http://www.icpdas.com/root/product/solutions/remote_io/rs-485/i-8k_i-87k/i-8024w.html

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
   v0..v2
   * no changes

 Documentation/misc-devices/lp8x4x_bus.txt | 15 ++++++
 drivers/misc/lp8x4x_bus.c                 | 89 +++++++++++++++++++++++++++++++
 2 files changed, 104 insertions(+)

diff --git a/Documentation/misc-devices/lp8x4x_bus.txt b/Documentation/misc-devices/lp8x4x_bus.txt
index e3a8bcf..08419d1 100644
--- a/Documentation/misc-devices/lp8x4x_bus.txt
+++ b/Documentation/misc-devices/lp8x4x_bus.txt
@@ -57,3 +57,18 @@ input_status
 output_status
 	RW - set status of digital output channels on the module in
 	     the expansion slot. Value can be read back.
+
+analog_output
+	RW - set status of analog output channels on the module in
+	     the expansion slot. Tested with voltage output. Bits 0-13:
+	     0x00c0 is -10.0V
+	     0x2000 is   0.0V
+	     0x3f40 is +10.0V
+
+	     So 1 unit of output is 1.25 mV.
+
+	     Bits 15 and 14 determine which channel to apply the value:
+	     0x0000 is channel 1
+	     0x4000 is channel 2
+	     0x8000 is channel 3
+	     0xc000 is channel 4
diff --git a/drivers/misc/lp8x4x_bus.c b/drivers/misc/lp8x4x_bus.c
index 684e640..58cfc8c 100644
--- a/drivers/misc/lp8x4x_bus.c
+++ b/drivers/misc/lp8x4x_bus.c
@@ -8,12 +8,14 @@
  *  it under the terms of the GNU General Public License version 2 as
  *  published by the Free Software Foundation or any later version.
  */
+#include <linux/hrtimer.h>
 #include <linux/init.h>
 #include <linux/io.h>
 #include <linux/list.h>
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/platform_device.h>
+#include <linux/sched.h>
 #include <linux/slab.h>
 
 #define MODULE_NAME	"lp8x4x-bus"
@@ -21,6 +23,7 @@ MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Sergei Ianovich <ynvich@gmail.com>");
 MODULE_DESCRIPTION("ICP DAS LP-8x4x parallel bus driver");
 
+#define LP8X4X_MAX_AO_CHANNELS	4
 struct lp8x4x_slot {
 	void			*data_addr;
 	unsigned int		model;
@@ -29,6 +32,8 @@ struct lp8x4x_slot {
 	u32			DO;
 	unsigned int		DI_len;
 	u32			DI;
+	unsigned int		AO_len;
+	u32			AO[LP8X4X_MAX_AO_CHANNELS];
 	struct device		dev;
 };
 
@@ -115,6 +120,36 @@ static void lp8x4x_slot_set_DO(struct lp8x4x_slot *s)
 	mutex_unlock(&s->lock);
 }
 
+void nsleep(unsigned long nanosec)
+{
+	ktime_t t = ns_to_ktime(nanosec);
+	long state = current->state;
+
+	__set_current_state(TASK_UNINTERRUPTIBLE);
+	schedule_hrtimeout(&t, HRTIMER_MODE_REL);
+	__set_current_state(state);
+}
+
+static void lp8x4x_slot_reset_AO(struct lp8x4x_slot *s)
+{
+	int i;
+	mutex_lock(&s->lock);
+	for (i = 0; i < s->AO_len; i++)
+		s->AO[i] = 0x2000;
+	iowrite8(0x00, s->data_addr);
+	nsleep(450);
+	iowrite8(0xff, s->data_addr);
+	mutex_unlock(&s->lock);
+}
+
+static void lp8x4x_slot_set_AO(struct lp8x4x_slot *s, u32 val)
+{
+	mutex_lock(&s->lock);
+	iowrite8(val & 0xff, s->data_addr + 2);
+	iowrite8((val >> 8) & 0xff, s->data_addr + 4);
+	mutex_unlock(&s->lock);
+}
+
 static ssize_t input_status_show(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
@@ -186,6 +221,48 @@ static ssize_t output_status_store(struct device *dev,
 
 static DEVICE_ATTR_RW(output_status);
 
+static ssize_t analog_output_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct lp8x4x_slot *s = container_of(dev, struct lp8x4x_slot, dev);
+	int i, c = 0;
+
+	for (i = 0; i < s->AO_len; i++)
+		c += sprintf(&buf[c], "0x%04x\n", s->AO[i]);
+	return c;
+}
+
+static ssize_t analog_output_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct lp8x4x_slot *s = container_of(dev, struct lp8x4x_slot, dev);
+	u32 AO;
+	int i;
+
+	if (!buf)
+		return count;
+	if (0 == count)
+		return count;
+
+	if (kstrtouint(buf, 16, &AO) != 0) {
+		dev_err(dev, "bad input\n");
+		return count;
+	}
+
+	if (AO & 0xffff0000) {
+		dev_err(dev, "bad input\n");
+		return count;
+	}
+
+	i = AO >> 14;
+	s->AO[i] = AO & 0x3fff;
+	lp8x4x_slot_set_AO(s, AO);
+
+	return count;
+}
+
+static DEVICE_ATTR_RW(analog_output);
+
 static ssize_t model_show(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
@@ -217,6 +294,13 @@ static struct attribute *dio_slot_dev_attrs[] = {
 };
 ATTRIBUTE_GROUPS(dio_slot_dev);
 
+static struct attribute *ao_slot_dev_attrs[] = {
+	&dev_attr_model.attr,
+	&dev_attr_analog_output.attr,
+	NULL,
+};
+ATTRIBUTE_GROUPS(ao_slot_dev);
+
 static void lp8x4x_master_release(struct device *dev)
 {
 	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
@@ -316,6 +400,11 @@ static void __init lp8x4x_bus_probe_slot(struct lp8x4x_master *m, int i,
 	mutex_init(&s->lock);
 
 	switch (model) {
+	case 24:
+		s->AO_len = 4;
+		lp8x4x_slot_reset_AO(s);
+		s->dev.groups = ao_slot_dev_groups;
+		break;
 	case 41:
 		s->DO_len = 4;
 		lp8x4x_slot_set_DO(s);
-- 
1.8.4.3


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

* [PATCH v2 16/16] misc: support for I-8024 in LP-8x4x
@ 2013-12-13  2:27           ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-13  2:27 UTC (permalink / raw)
  To: linux-arm-kernel

Status of I-8042 4 analog output channels can be managed via
sysfs.

http://www.icpdas.com/root/product/solutions/remote_io/rs-485/i-8k_i-87k/i-8024w.html

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
   v0..v2
   * no changes

 Documentation/misc-devices/lp8x4x_bus.txt | 15 ++++++
 drivers/misc/lp8x4x_bus.c                 | 89 +++++++++++++++++++++++++++++++
 2 files changed, 104 insertions(+)

diff --git a/Documentation/misc-devices/lp8x4x_bus.txt b/Documentation/misc-devices/lp8x4x_bus.txt
index e3a8bcf..08419d1 100644
--- a/Documentation/misc-devices/lp8x4x_bus.txt
+++ b/Documentation/misc-devices/lp8x4x_bus.txt
@@ -57,3 +57,18 @@ input_status
 output_status
 	RW - set status of digital output channels on the module in
 	     the expansion slot. Value can be read back.
+
+analog_output
+	RW - set status of analog output channels on the module in
+	     the expansion slot. Tested with voltage output. Bits 0-13:
+	     0x00c0 is -10.0V
+	     0x2000 is   0.0V
+	     0x3f40 is +10.0V
+
+	     So 1 unit of output is 1.25 mV.
+
+	     Bits 15 and 14 determine which channel to apply the value:
+	     0x0000 is channel 1
+	     0x4000 is channel 2
+	     0x8000 is channel 3
+	     0xc000 is channel 4
diff --git a/drivers/misc/lp8x4x_bus.c b/drivers/misc/lp8x4x_bus.c
index 684e640..58cfc8c 100644
--- a/drivers/misc/lp8x4x_bus.c
+++ b/drivers/misc/lp8x4x_bus.c
@@ -8,12 +8,14 @@
  *  it under the terms of the GNU General Public License version 2 as
  *  published by the Free Software Foundation or any later version.
  */
+#include <linux/hrtimer.h>
 #include <linux/init.h>
 #include <linux/io.h>
 #include <linux/list.h>
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/platform_device.h>
+#include <linux/sched.h>
 #include <linux/slab.h>
 
 #define MODULE_NAME	"lp8x4x-bus"
@@ -21,6 +23,7 @@ MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Sergei Ianovich <ynvich@gmail.com>");
 MODULE_DESCRIPTION("ICP DAS LP-8x4x parallel bus driver");
 
+#define LP8X4X_MAX_AO_CHANNELS	4
 struct lp8x4x_slot {
 	void			*data_addr;
 	unsigned int		model;
@@ -29,6 +32,8 @@ struct lp8x4x_slot {
 	u32			DO;
 	unsigned int		DI_len;
 	u32			DI;
+	unsigned int		AO_len;
+	u32			AO[LP8X4X_MAX_AO_CHANNELS];
 	struct device		dev;
 };
 
@@ -115,6 +120,36 @@ static void lp8x4x_slot_set_DO(struct lp8x4x_slot *s)
 	mutex_unlock(&s->lock);
 }
 
+void nsleep(unsigned long nanosec)
+{
+	ktime_t t = ns_to_ktime(nanosec);
+	long state = current->state;
+
+	__set_current_state(TASK_UNINTERRUPTIBLE);
+	schedule_hrtimeout(&t, HRTIMER_MODE_REL);
+	__set_current_state(state);
+}
+
+static void lp8x4x_slot_reset_AO(struct lp8x4x_slot *s)
+{
+	int i;
+	mutex_lock(&s->lock);
+	for (i = 0; i < s->AO_len; i++)
+		s->AO[i] = 0x2000;
+	iowrite8(0x00, s->data_addr);
+	nsleep(450);
+	iowrite8(0xff, s->data_addr);
+	mutex_unlock(&s->lock);
+}
+
+static void lp8x4x_slot_set_AO(struct lp8x4x_slot *s, u32 val)
+{
+	mutex_lock(&s->lock);
+	iowrite8(val & 0xff, s->data_addr + 2);
+	iowrite8((val >> 8) & 0xff, s->data_addr + 4);
+	mutex_unlock(&s->lock);
+}
+
 static ssize_t input_status_show(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
@@ -186,6 +221,48 @@ static ssize_t output_status_store(struct device *dev,
 
 static DEVICE_ATTR_RW(output_status);
 
+static ssize_t analog_output_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct lp8x4x_slot *s = container_of(dev, struct lp8x4x_slot, dev);
+	int i, c = 0;
+
+	for (i = 0; i < s->AO_len; i++)
+		c += sprintf(&buf[c], "0x%04x\n", s->AO[i]);
+	return c;
+}
+
+static ssize_t analog_output_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct lp8x4x_slot *s = container_of(dev, struct lp8x4x_slot, dev);
+	u32 AO;
+	int i;
+
+	if (!buf)
+		return count;
+	if (0 == count)
+		return count;
+
+	if (kstrtouint(buf, 16, &AO) != 0) {
+		dev_err(dev, "bad input\n");
+		return count;
+	}
+
+	if (AO & 0xffff0000) {
+		dev_err(dev, "bad input\n");
+		return count;
+	}
+
+	i = AO >> 14;
+	s->AO[i] = AO & 0x3fff;
+	lp8x4x_slot_set_AO(s, AO);
+
+	return count;
+}
+
+static DEVICE_ATTR_RW(analog_output);
+
 static ssize_t model_show(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
@@ -217,6 +294,13 @@ static struct attribute *dio_slot_dev_attrs[] = {
 };
 ATTRIBUTE_GROUPS(dio_slot_dev);
 
+static struct attribute *ao_slot_dev_attrs[] = {
+	&dev_attr_model.attr,
+	&dev_attr_analog_output.attr,
+	NULL,
+};
+ATTRIBUTE_GROUPS(ao_slot_dev);
+
 static void lp8x4x_master_release(struct device *dev)
 {
 	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
@@ -316,6 +400,11 @@ static void __init lp8x4x_bus_probe_slot(struct lp8x4x_master *m, int i,
 	mutex_init(&s->lock);
 
 	switch (model) {
+	case 24:
+		s->AO_len = 4;
+		lp8x4x_slot_reset_AO(s);
+		s->dev.groups = ao_slot_dev_groups;
+		break;
 	case 41:
 		s->DO_len = 4;
 		lp8x4x_slot_set_DO(s);
-- 
1.8.4.3

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

* Re: [PATCH v2 00/16] ARM: support for ICP DAS LP-8x4x (with dts)
  2013-12-13  2:27         ` Sergei Ianovich
@ 2013-12-13  2:33           ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-13  2:33 UTC (permalink / raw)
  To: linux-kernel; +Cc: linux-arm-kernel, Daniel Mack, Arnd Bergmann, Haojian Zhuang

On Fri, 2013-12-13 at 06:27 +0400, Sergei Ianovich wrote:
> Fixed most review requirements. Details in respective patches.
> 
> I've completely met the requirement for using dmaengine-based DMA
> in patch v2-03/16. Tests showed new DMA was underperforming. It added
> on top of a pre-existing problem with MMC bus width and made the system
> barely usable. However, the new code in this patch work correctly with
> both the existing and the new DMA. Even if the new DMA is compiled into
> the kernel, the exisitng DMA initializes first.

s/I've/I've not/


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

* [PATCH v2 00/16] ARM: support for ICP DAS LP-8x4x (with dts)
@ 2013-12-13  2:33           ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-13  2:33 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, 2013-12-13 at 06:27 +0400, Sergei Ianovich wrote:
> Fixed most review requirements. Details in respective patches.
> 
> I've completely met the requirement for using dmaengine-based DMA
> in patch v2-03/16. Tests showed new DMA was underperforming. It added
> on top of a pre-existing problem with MMC bus width and made the system
> barely usable. However, the new code in this patch work correctly with
> both the existing and the new DMA. Even if the new DMA is compiled into
> the kernel, the exisitng DMA initializes first.

s/I've/I've not/

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

* Re: [PATCH v2 03/16] ARM: dts: provide DMA config to pxamci
  2013-12-13  2:27           ` Sergei Ianovich
  (?)
@ 2013-12-14 19:06             ` Arnd Bergmann
  -1 siblings, 0 replies; 700+ messages in thread
From: Arnd Bergmann @ 2013-12-14 19:06 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: linux-kernel, linux-arm-kernel, Daniel Mack, Rob Herring,
	Pawel Moll, Mark Rutland, Stephen Warren, Ian Campbell,
	Rob Landley, Russell King, Chris Ball, Viresh Kumar, Shawn Guo,
	Haojian Zhuang, open list:OPEN FIRMWARE AND...,
	open list:DOCUMENTATION, linux-mmc

On Friday 13 December 2013, Sergei Ianovich wrote:
> Non-dts implementation supply required DMA channel numbers as
> IORESOURCE_DMA. However, there is was no way to get them from
> device tree.

Please update this changeset comment, I think it still refers to
the earlier version.
 
> Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
> CC: Daniel Mack <zonque@gmail.com>
> CC: Arnd Bergmann <arnd@arndb.de>

The patch looks ok in case we are merging your patches for 3.14
and Daniel's patches later than that. If they end up in the
same merge window however, we'd have to be care to resolve
the obvious conflict in a proper way.

	Arnd

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

* Re: [PATCH v2 03/16] ARM: dts: provide DMA config to pxamci
@ 2013-12-14 19:06             ` Arnd Bergmann
  0 siblings, 0 replies; 700+ messages in thread
From: Arnd Bergmann @ 2013-12-14 19:06 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: Mark Rutland, open list:OPEN FIRMWARE AND...,
	Shawn Guo, Russell King, Pawel Moll, Stephen Warren,
	Viresh Kumar, Ian Campbell, open list:DOCUMENTATION,
	linux-kernel, Rob Herring, Daniel Mack, Haojian Zhuang,
	Rob Landley, linux-mmc, Chris Ball, linux-arm-kernel

On Friday 13 December 2013, Sergei Ianovich wrote:
> Non-dts implementation supply required DMA channel numbers as
> IORESOURCE_DMA. However, there is was no way to get them from
> device tree.

Please update this changeset comment, I think it still refers to
the earlier version.
 
> Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
> CC: Daniel Mack <zonque@gmail.com>
> CC: Arnd Bergmann <arnd@arndb.de>

The patch looks ok in case we are merging your patches for 3.14
and Daniel's patches later than that. If they end up in the
same merge window however, we'd have to be care to resolve
the obvious conflict in a proper way.

	Arnd

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

* [PATCH v2 03/16] ARM: dts: provide DMA config to pxamci
@ 2013-12-14 19:06             ` Arnd Bergmann
  0 siblings, 0 replies; 700+ messages in thread
From: Arnd Bergmann @ 2013-12-14 19:06 UTC (permalink / raw)
  To: linux-arm-kernel

On Friday 13 December 2013, Sergei Ianovich wrote:
> Non-dts implementation supply required DMA channel numbers as
> IORESOURCE_DMA. However, there is was no way to get them from
> device tree.

Please update this changeset comment, I think it still refers to
the earlier version.
 
> Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
> CC: Daniel Mack <zonque@gmail.com>
> CC: Arnd Bergmann <arnd@arndb.de>

The patch looks ok in case we are merging your patches for 3.14
and Daniel's patches later than that. If they end up in the
same merge window however, we'd have to be care to resolve
the obvious conflict in a proper way.

	Arnd

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

* Re: [PATCH v2 03/16] ARM: dts: provide DMA config to pxamci
  2013-12-14 19:06             ` Arnd Bergmann
@ 2013-12-14 19:34               ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-14 19:34 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: linux-kernel, linux-arm-kernel, Daniel Mack, Rob Herring,
	Pawel Moll, Mark Rutland, Stephen Warren, Ian Campbell,
	Rob Landley, Russell King, Chris Ball, Viresh Kumar, Shawn Guo,
	Haojian Zhuang, open list:OPEN FIRMWARE AND...,
	open list:DOCUMENTATION, linux-mmc

On Sat, 2013-12-14 at 20:06 +0100, Arnd Bergmann wrote:
> On Friday 13 December 2013, Sergei Ianovich wrote:
> > Non-dts implementation supply required DMA channel numbers as
> > IORESOURCE_DMA. However, there is was no way to get them from
> > device tree.
> 
> Please update this changeset comment, I think it still refers to
> the earlier version.

---
Non-dts implementation supply required DMA channel numbers as
IORESOURCE_DMA. We can also get them from the device tree, if it
is present.
---

Is this fine?

Should I post v3, if so? 

> > Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
> > CC: Daniel Mack <zonque@gmail.com>
> > CC: Arnd Bergmann <arnd@arndb.de>
> 
> The patch looks ok in case we are merging your patches for 3.14
> and Daniel's patches later than that. If they end up in the
> same merge window however, we'd have to be care to resolve
> the obvious conflict in a proper way.

The most recently published Daniel's patch (Aug 2013) wraps
IORESOURCE_DMA handling on DT presence in a similar way, but doesn't do
any actual DT processing. So there is no conflict at the moment. Daniel
can comment better on this, though.



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

* [PATCH v2 03/16] ARM: dts: provide DMA config to pxamci
@ 2013-12-14 19:34               ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-14 19:34 UTC (permalink / raw)
  To: linux-arm-kernel

On Sat, 2013-12-14 at 20:06 +0100, Arnd Bergmann wrote:
> On Friday 13 December 2013, Sergei Ianovich wrote:
> > Non-dts implementation supply required DMA channel numbers as
> > IORESOURCE_DMA. However, there is was no way to get them from
> > device tree.
> 
> Please update this changeset comment, I think it still refers to
> the earlier version.

---
Non-dts implementation supply required DMA channel numbers as
IORESOURCE_DMA. We can also get them from the device tree, if it
is present.
---

Is this fine?

Should I post v3, if so? 

> > Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
> > CC: Daniel Mack <zonque@gmail.com>
> > CC: Arnd Bergmann <arnd@arndb.de>
> 
> The patch looks ok in case we are merging your patches for 3.14
> and Daniel's patches later than that. If they end up in the
> same merge window however, we'd have to be care to resolve
> the obvious conflict in a proper way.

The most recently published Daniel's patch (Aug 2013) wraps
IORESOURCE_DMA handling on DT presence in a similar way, but doesn't do
any actual DT processing. So there is no conflict at the moment. Daniel
can comment better on this, though.

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

* Re: [PATCH v2 16/16] misc: support for I-8024 in LP-8x4x
  2013-12-13  2:27           ` Sergei Ianovich
@ 2013-12-14 20:59             ` Arnd Bergmann
  -1 siblings, 0 replies; 700+ messages in thread
From: Arnd Bergmann @ 2013-12-14 20:59 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: linux-kernel, linux-arm-kernel, Rob Landley, Greg Kroah-Hartman,
	open list:DOCUMENTATION

On Friday 13 December 2013, Sergei Ianovich wrote:
> +void nsleep(unsigned long nanosec)
> +{
> +       ktime_t t = ns_to_ktime(nanosec);
> +       long state = current->state;
> +
> +       __set_current_state(TASK_UNINTERRUPTIBLE);
> +       schedule_hrtimeout(&t, HRTIMER_MODE_REL);
> +       __set_current_state(state);
> +}
> +
> +static void lp8x4x_slot_reset_AO(struct lp8x4x_slot *s)
> +{
> +       int i;
> +       mutex_lock(&s->lock);
> +       for (i = 0; i < s->AO_len; i++)
> +               s->AO[i] = 0x2000;
> +       iowrite8(0x00, s->data_addr);
> +       nsleep(450);
> +       iowrite8(0xff, s->data_addr);
> +       mutex_unlock(&s->lock);
> +}

Have you checked that the nsleep definition actually does the
right thing here? 450 nanoseconds must be close the latency
you get from calling schedule_hrtimeout(). I'd suggest using
either ndelay() or usleep_range() instead, depending on your
needs.

If nsleep is really useful here, we should probably add that
as a generic API rather than having it in one driver.

	Arnd

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

* [PATCH v2 16/16] misc: support for I-8024 in LP-8x4x
@ 2013-12-14 20:59             ` Arnd Bergmann
  0 siblings, 0 replies; 700+ messages in thread
From: Arnd Bergmann @ 2013-12-14 20:59 UTC (permalink / raw)
  To: linux-arm-kernel

On Friday 13 December 2013, Sergei Ianovich wrote:
> +void nsleep(unsigned long nanosec)
> +{
> +       ktime_t t = ns_to_ktime(nanosec);
> +       long state = current->state;
> +
> +       __set_current_state(TASK_UNINTERRUPTIBLE);
> +       schedule_hrtimeout(&t, HRTIMER_MODE_REL);
> +       __set_current_state(state);
> +}
> +
> +static void lp8x4x_slot_reset_AO(struct lp8x4x_slot *s)
> +{
> +       int i;
> +       mutex_lock(&s->lock);
> +       for (i = 0; i < s->AO_len; i++)
> +               s->AO[i] = 0x2000;
> +       iowrite8(0x00, s->data_addr);
> +       nsleep(450);
> +       iowrite8(0xff, s->data_addr);
> +       mutex_unlock(&s->lock);
> +}

Have you checked that the nsleep definition actually does the
right thing here? 450 nanoseconds must be close the latency
you get from calling schedule_hrtimeout(). I'd suggest using
either ndelay() or usleep_range() instead, depending on your
needs.

If nsleep is really useful here, we should probably add that
as a generic API rather than having it in one driver.

	Arnd

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

* Re: [PATCH v2 00/16] ARM: support for ICP DAS LP-8x4x (with dts)
  2013-12-13  2:27         ` Sergei Ianovich
@ 2013-12-14 21:03           ` Arnd Bergmann
  -1 siblings, 0 replies; 700+ messages in thread
From: Arnd Bergmann @ 2013-12-14 21:03 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: linux-kernel, linux-arm-kernel, Daniel Mack, Haojian Zhuang

On Friday 13 December 2013, Sergei Ianovich wrote:
> Fixed most review requirements. Details in respective patches.
> 
> I've completely met the requirement for using dmaengine-based DMA
> in patch v2-03/16. Tests showed new DMA was underperforming. It added
> on top of a pre-existing problem with MMC bus width and made the system
> barely usable. However, the new code in this patch work correctly with
> both the existing and the new DMA. Even if the new DMA is compiled into
> the kernel, the exisitng DMA initializes first.

As mentioned, I think this is a good approach, as long as it's coordinated
with Daniel's patches for the dmaengine. I would expect that once we
get to the bottom of this, there will only be a small overhead from
not directly using the dma registers but going through the dmaengine
API.

> I've also decided not to create a single mfd device for
> machine-specific devices. Instead each type is supported by a separate
> driver in respective subsystem. It was tempting to hardcode all the
> constants in one source file, but that requires ugly initialization.
> The taken way produces much cleaner code.

I think you should at least change the DT representation for the FPGA
to show one device as the actual FPGA and attach children to that,
multiple indirection levels if necessary.

I suspect that the fpga is on some external-bus port with a specific
chip-select, so I would model this as

	extbus {
		compatible = "simple-bus";
		#address-cells = <1>;
		#size-cells = <1>;
		/* bus addresses 0-0xfffff mapped to 0x17000000 */
		ranges = <0 0x17000000 0x100000>;
		interrupt-parent = <&fpga-irq>;

		fpga-irq: irq@6 {
			regs = <6 16>; /* translated addresses
			...
		};

		fgpa-bus {
			#address-cells = <1>;
			#size-cells = <1>;
			ranges;

			serial@9050 {
				...
			};
		};
	};

I also think you don't need to make the devices quite as fine-grained
here but instead group things together more. I would probably indeed
put everything that is not on one of the slots into a common device,
including the irqchip.

	Arnd

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

* [PATCH v2 00/16] ARM: support for ICP DAS LP-8x4x (with dts)
@ 2013-12-14 21:03           ` Arnd Bergmann
  0 siblings, 0 replies; 700+ messages in thread
From: Arnd Bergmann @ 2013-12-14 21:03 UTC (permalink / raw)
  To: linux-arm-kernel

On Friday 13 December 2013, Sergei Ianovich wrote:
> Fixed most review requirements. Details in respective patches.
> 
> I've completely met the requirement for using dmaengine-based DMA
> in patch v2-03/16. Tests showed new DMA was underperforming. It added
> on top of a pre-existing problem with MMC bus width and made the system
> barely usable. However, the new code in this patch work correctly with
> both the existing and the new DMA. Even if the new DMA is compiled into
> the kernel, the exisitng DMA initializes first.

As mentioned, I think this is a good approach, as long as it's coordinated
with Daniel's patches for the dmaengine. I would expect that once we
get to the bottom of this, there will only be a small overhead from
not directly using the dma registers but going through the dmaengine
API.

> I've also decided not to create a single mfd device for
> machine-specific devices. Instead each type is supported by a separate
> driver in respective subsystem. It was tempting to hardcode all the
> constants in one source file, but that requires ugly initialization.
> The taken way produces much cleaner code.

I think you should at least change the DT representation for the FPGA
to show one device as the actual FPGA and attach children to that,
multiple indirection levels if necessary.

I suspect that the fpga is on some external-bus port with a specific
chip-select, so I would model this as

	extbus {
		compatible = "simple-bus";
		#address-cells = <1>;
		#size-cells = <1>;
		/* bus addresses 0-0xfffff mapped to 0x17000000 */
		ranges = <0 0x17000000 0x100000>;
		interrupt-parent = <&fpga-irq>;

		fpga-irq: irq at 6 {
			regs = <6 16>; /* translated addresses
			...
		};

		fgpa-bus {
			#address-cells = <1>;
			#size-cells = <1>;
			ranges;

			serial at 9050 {
				...
			};
		};
	};

I also think you don't need to make the devices quite as fine-grained
here but instead group things together more. I would probably indeed
put everything that is not on one of the slots into a common device,
including the irqchip.

	Arnd

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

* Re: [PATCH v2 00/16] ARM: support for ICP DAS LP-8x4x (with dts)
  2013-12-14 21:03           ` Arnd Bergmann
@ 2013-12-14 21:55             ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-14 21:55 UTC (permalink / raw)
  To: Arnd Bergmann; +Cc: linux-kernel, linux-arm-kernel, Daniel Mack, Haojian Zhuang

On Sat, 2013-12-14 at 22:03 +0100, Arnd Bergmann wrote:
> On Friday 13 December 2013, Sergei Ianovich wrote:
> > I've also decided not to create a single mfd device for
> > machine-specific devices. Instead each type is supported by a separate
> > driver in respective subsystem. It was tempting to hardcode all the
> > constants in one source file, but that requires ugly initialization.
> > The taken way produces much cleaner code.
> 
> I think you should at least change the DT representation for the FPGA
> to show one device as the actual FPGA and attach children to that,
> multiple indirection levels if necessary.
> 
> I suspect that the fpga is on some external-bus port with a specific
> chip-select, so I would model this as
> 
>         extbus {
>                 compatible = "simple-bus";
>                 #address-cells = <1>;
>                 #size-cells = <1>;
>                 /* bus addresses 0-0xfffff mapped to 0x17000000 */
>                 ranges = <0 0x17000000 0x100000>;
>                 interrupt-parent = <&fpga-irq>;
> 
>                 fpga-irq: irq@6 {
>                         regs = <6 16>; /* translated addresses
>                         ...
>                 };
> 
>                 fgpa-bus {
>                         #address-cells = <1>;
>                         #size-cells = <1>;
>                         ranges;
> 
>                         serial@9050 {
>                                 ...
>                         };
>                 };
>         };
> 
> I also think you don't need to make the devices quite as fine-grained
> here but instead group things together more. I would probably indeed
> put everything that is not on one of the slots into a common device,
> including the irqchip.

There are basically 2 options: one-for-all mfd device and one-for-one
device drivers.

MFD
pros:
* easy to add into the tree (one file)
* easy config (one option)

Separate devices
* easy to support devices as respective subsystems evolve
* easy to add new feature without breaking existing ones. Eg. it may
make sense to provide industrial IO interface on analog IO devices
* possible to have fine-grained configuration (eg. SRAM in kernel,
serial and slot as modules)
* proper device tree serves as a datasheet for the machine, so anyone
who needs to work on it will have a decent view of the internals

I believe long-term benefits of separate devices outweigh immediate
effects of an MFD. However, I certainly don't see the big picture and
will accept your decision. Please make one.


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

* [PATCH v2 00/16] ARM: support for ICP DAS LP-8x4x (with dts)
@ 2013-12-14 21:55             ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-14 21:55 UTC (permalink / raw)
  To: linux-arm-kernel

On Sat, 2013-12-14 at 22:03 +0100, Arnd Bergmann wrote:
> On Friday 13 December 2013, Sergei Ianovich wrote:
> > I've also decided not to create a single mfd device for
> > machine-specific devices. Instead each type is supported by a separate
> > driver in respective subsystem. It was tempting to hardcode all the
> > constants in one source file, but that requires ugly initialization.
> > The taken way produces much cleaner code.
> 
> I think you should at least change the DT representation for the FPGA
> to show one device as the actual FPGA and attach children to that,
> multiple indirection levels if necessary.
> 
> I suspect that the fpga is on some external-bus port with a specific
> chip-select, so I would model this as
> 
>         extbus {
>                 compatible = "simple-bus";
>                 #address-cells = <1>;
>                 #size-cells = <1>;
>                 /* bus addresses 0-0xfffff mapped to 0x17000000 */
>                 ranges = <0 0x17000000 0x100000>;
>                 interrupt-parent = <&fpga-irq>;
> 
>                 fpga-irq: irq at 6 {
>                         regs = <6 16>; /* translated addresses
>                         ...
>                 };
> 
>                 fgpa-bus {
>                         #address-cells = <1>;
>                         #size-cells = <1>;
>                         ranges;
> 
>                         serial at 9050 {
>                                 ...
>                         };
>                 };
>         };
> 
> I also think you don't need to make the devices quite as fine-grained
> here but instead group things together more. I would probably indeed
> put everything that is not on one of the slots into a common device,
> including the irqchip.

There are basically 2 options: one-for-all mfd device and one-for-one
device drivers.

MFD
pros:
* easy to add into the tree (one file)
* easy config (one option)

Separate devices
* easy to support devices as respective subsystems evolve
* easy to add new feature without breaking existing ones. Eg. it may
make sense to provide industrial IO interface on analog IO devices
* possible to have fine-grained configuration (eg. SRAM in kernel,
serial and slot as modules)
* proper device tree serves as a datasheet for the machine, so anyone
who needs to work on it will have a decent view of the internals

I believe long-term benefits of separate devices outweigh immediate
effects of an MFD. However, I certainly don't see the big picture and
will accept your decision. Please make one.

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

* Re: [PATCH v2 16/16] misc: support for I-8024 in LP-8x4x
  2013-12-14 20:59             ` Arnd Bergmann
@ 2013-12-14 23:03               ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-14 23:03 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: linux-kernel, linux-arm-kernel, Rob Landley, Greg Kroah-Hartman,
	open list:DOCUMENTATION

On Sat, 2013-12-14 at 21:59 +0100, Arnd Bergmann wrote:
> Have you checked that the nsleep definition actually does the
> right thing here? 450 nanoseconds must be close the latency
> you get from calling schedule_hrtimeout(). I'd suggest using
> either ndelay() or usleep_range() instead, depending on your
> needs.

Documentation/timers/timers-howto.txt stated there was a significant
overhead when setting up usleep_range. I studied implementation and
found that schedule_hrtimeout was certainly less than 520000 CPU cycles
that udelay(1) would consume.

It worked. I haven't checked actual delay time. However, machines with
the driver (based on 3.8) are in production since May 2013 without
issues.

> If nsleep is really useful here, we should probably add that
> as a generic API rather than having it in one driver.

I've also used this nsleep for driving RTC clock (DS1302) since May
2013.

Now I see that my code is a clone of usleep_range(x, x). I will convert
my code to use it.



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

* [PATCH v2 16/16] misc: support for I-8024 in LP-8x4x
@ 2013-12-14 23:03               ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-14 23:03 UTC (permalink / raw)
  To: linux-arm-kernel

On Sat, 2013-12-14 at 21:59 +0100, Arnd Bergmann wrote:
> Have you checked that the nsleep definition actually does the
> right thing here? 450 nanoseconds must be close the latency
> you get from calling schedule_hrtimeout(). I'd suggest using
> either ndelay() or usleep_range() instead, depending on your
> needs.

Documentation/timers/timers-howto.txt stated there was a significant
overhead when setting up usleep_range. I studied implementation and
found that schedule_hrtimeout was certainly less than 520000 CPU cycles
that udelay(1) would consume.

It worked. I haven't checked actual delay time. However, machines with
the driver (based on 3.8) are in production since May 2013 without
issues.

> If nsleep is really useful here, we should probably add that
> as a generic API rather than having it in one driver.

I've also used this nsleep for driving RTC clock (DS1302) since May
2013.

Now I see that my code is a clone of usleep_range(x, x). I will convert
my code to use it.

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

* Re: [PATCH v2 03/16] ARM: dts: provide DMA config to pxamci
  2013-12-14 19:34               ` Sergei Ianovich
@ 2013-12-14 23:39                 ` Arnd Bergmann
  -1 siblings, 0 replies; 700+ messages in thread
From: Arnd Bergmann @ 2013-12-14 23:39 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: linux-kernel, linux-arm-kernel, Daniel Mack, Rob Herring,
	Pawel Moll, Mark Rutland, Stephen Warren, Ian Campbell,
	Rob Landley, Russell King, Chris Ball, Viresh Kumar, Shawn Guo,
	Haojian Zhuang, open list:OPEN FIRMWARE AND...,
	open list:DOCUMENTATION, linux-mmc

On Saturday 14 December 2013, Sergei Ianovich wrote:
> On Sat, 2013-12-14 at 20:06 +0100, Arnd Bergmann wrote:
> > On Friday 13 December 2013, Sergei Ianovich wrote:
> > > Non-dts implementation supply required DMA channel numbers as
> > > IORESOURCE_DMA. However, there is was no way to get them from
> > > device tree.
> > 
> > Please update this changeset comment, I think it still refers to
> > the earlier version.
> 
> ---
> Non-dts implementation supply required DMA channel numbers as
> IORESOURCE_DMA. We can also get them from the device tree, if it
> is present.
> ---
> 
> Is this fine?

I would mention that the binding is designed to work with the dmaengine
framework as soon as we have figured out how to make that work without
the problems you found.

> Should I post v3, if so? 

I'd wait a little longer for more comments.

	Arnd

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

* [PATCH v2 03/16] ARM: dts: provide DMA config to pxamci
@ 2013-12-14 23:39                 ` Arnd Bergmann
  0 siblings, 0 replies; 700+ messages in thread
From: Arnd Bergmann @ 2013-12-14 23:39 UTC (permalink / raw)
  To: linux-arm-kernel

On Saturday 14 December 2013, Sergei Ianovich wrote:
> On Sat, 2013-12-14 at 20:06 +0100, Arnd Bergmann wrote:
> > On Friday 13 December 2013, Sergei Ianovich wrote:
> > > Non-dts implementation supply required DMA channel numbers as
> > > IORESOURCE_DMA. However, there is was no way to get them from
> > > device tree.
> > 
> > Please update this changeset comment, I think it still refers to
> > the earlier version.
> 
> ---
> Non-dts implementation supply required DMA channel numbers as
> IORESOURCE_DMA. We can also get them from the device tree, if it
> is present.
> ---
> 
> Is this fine?

I would mention that the binding is designed to work with the dmaengine
framework as soon as we have figured out how to make that work without
the problems you found.

> Should I post v3, if so? 

I'd wait a little longer for more comments.

	Arnd

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

* Re: [PATCH v2 00/16] ARM: support for ICP DAS LP-8x4x (with dts)
  2013-12-14 21:55             ` Sergei Ianovich
@ 2013-12-15  0:53               ` Arnd Bergmann
  -1 siblings, 0 replies; 700+ messages in thread
From: Arnd Bergmann @ 2013-12-15  0:53 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: linux-kernel, linux-arm-kernel, Daniel Mack, Haojian Zhuang

On Saturday 14 December 2013, Sergei Ianovich wrote:
> On Sat, 2013-12-14 at 22:03 +0100, Arnd Bergmann wrote:
> > On Friday 13 December 2013, Sergei Ianovich wrote:
> > > I've also decided not to create a single mfd device for
> > > machine-specific devices. Instead each type is supported by a separate
> > > driver in respective subsystem. It was tempting to hardcode all the
> > > constants in one source file, but that requires ugly initialization.
> > > The taken way produces much cleaner code.
> > 
> > I think you should at least change the DT representation for the FPGA
> > to show one device as the actual FPGA and attach children to that,
> > multiple indirection levels if necessary.
> > 
> > I suspect that the fpga is on some external-bus port with a specific
> > chip-select, so I would model this as
> > 
> >         extbus {
> >                 compatible = "simple-bus";
> >                 #address-cells = <1>;
> >                 #size-cells = <1>;
> >                 /* bus addresses 0-0xfffff mapped to 0x17000000 */
> >                 ranges = <0 0x17000000 0x100000>;
> >                 interrupt-parent = <&fpga-irq>;
> > 
> >                 fpga-irq: irq@6 {
> >                         regs = <6 16>; /* translated addresses
> >                         ...
> >                 };
> > 
> >                 fgpa-bus {
> >                         #address-cells = <1>;
> >                         #size-cells = <1>;
> >                         ranges;
> > 
> >                         serial@9050 {
> >                                 ...
> >                         };
> >                 };
> >         };
> > 
> > I also think you don't need to make the devices quite as fine-grained
> > here but instead group things together more. I would probably indeed
> > put everything that is not on one of the slots into a common device,
> > including the irqchip.
> 
> There are basically 2 options: one-for-all mfd device and one-for-one
> device drivers.
> 
> MFD
> pros:
> * easy to add into the tree (one file)
> * easy config (one option)
> 
> Separate devices
> * easy to support devices as respective subsystems evolve
> * easy to add new feature without breaking existing ones. Eg. it may
> make sense to provide industrial IO interface on analog IO devices
> * possible to have fine-grained configuration (eg. SRAM in kernel,
> serial and slot as modules)
> * proper device tree serves as a datasheet for the machine, so anyone
> who needs to work on it will have a decent view of the internals
> 
> I believe long-term benefits of separate devices outweigh immediate
> effects of an MFD. However, I certainly don't see the big picture and
> will accept your decision. Please make one.

Unfortunately I don't have a good way to judge the tradeoffs without
understanding more about the design of the hardware. Did I understand
you right that you expect future versions of the FPGA bitstream
to implement additional features or have a different set of endpoint
devices?

If so, I would argue that anything that you consider an optional
sub-device should have its own device node in the device tree.

Also, do you have to model hardware that is connected to the FPGA
rather than being part of it?

I suspect that you may have a different understanding of the term
MFD than what I was suggesting: A typical MFD driver in Linux is
basically a container device that has some registers on its own
like a version detection or the irqchip but mainly is there to
create sub-devices that each have a subset of the available
registers. The sub-devices may or may not be describe in DT in this
case.

	Arnd

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

* [PATCH v2 00/16] ARM: support for ICP DAS LP-8x4x (with dts)
@ 2013-12-15  0:53               ` Arnd Bergmann
  0 siblings, 0 replies; 700+ messages in thread
From: Arnd Bergmann @ 2013-12-15  0:53 UTC (permalink / raw)
  To: linux-arm-kernel

On Saturday 14 December 2013, Sergei Ianovich wrote:
> On Sat, 2013-12-14 at 22:03 +0100, Arnd Bergmann wrote:
> > On Friday 13 December 2013, Sergei Ianovich wrote:
> > > I've also decided not to create a single mfd device for
> > > machine-specific devices. Instead each type is supported by a separate
> > > driver in respective subsystem. It was tempting to hardcode all the
> > > constants in one source file, but that requires ugly initialization.
> > > The taken way produces much cleaner code.
> > 
> > I think you should at least change the DT representation for the FPGA
> > to show one device as the actual FPGA and attach children to that,
> > multiple indirection levels if necessary.
> > 
> > I suspect that the fpga is on some external-bus port with a specific
> > chip-select, so I would model this as
> > 
> >         extbus {
> >                 compatible = "simple-bus";
> >                 #address-cells = <1>;
> >                 #size-cells = <1>;
> >                 /* bus addresses 0-0xfffff mapped to 0x17000000 */
> >                 ranges = <0 0x17000000 0x100000>;
> >                 interrupt-parent = <&fpga-irq>;
> > 
> >                 fpga-irq: irq at 6 {
> >                         regs = <6 16>; /* translated addresses
> >                         ...
> >                 };
> > 
> >                 fgpa-bus {
> >                         #address-cells = <1>;
> >                         #size-cells = <1>;
> >                         ranges;
> > 
> >                         serial at 9050 {
> >                                 ...
> >                         };
> >                 };
> >         };
> > 
> > I also think you don't need to make the devices quite as fine-grained
> > here but instead group things together more. I would probably indeed
> > put everything that is not on one of the slots into a common device,
> > including the irqchip.
> 
> There are basically 2 options: one-for-all mfd device and one-for-one
> device drivers.
> 
> MFD
> pros:
> * easy to add into the tree (one file)
> * easy config (one option)
> 
> Separate devices
> * easy to support devices as respective subsystems evolve
> * easy to add new feature without breaking existing ones. Eg. it may
> make sense to provide industrial IO interface on analog IO devices
> * possible to have fine-grained configuration (eg. SRAM in kernel,
> serial and slot as modules)
> * proper device tree serves as a datasheet for the machine, so anyone
> who needs to work on it will have a decent view of the internals
> 
> I believe long-term benefits of separate devices outweigh immediate
> effects of an MFD. However, I certainly don't see the big picture and
> will accept your decision. Please make one.

Unfortunately I don't have a good way to judge the tradeoffs without
understanding more about the design of the hardware. Did I understand
you right that you expect future versions of the FPGA bitstream
to implement additional features or have a different set of endpoint
devices?

If so, I would argue that anything that you consider an optional
sub-device should have its own device node in the device tree.

Also, do you have to model hardware that is connected to the FPGA
rather than being part of it?

I suspect that you may have a different understanding of the term
MFD than what I was suggesting: A typical MFD driver in Linux is
basically a container device that has some registers on its own
like a version detection or the irqchip but mainly is there to
create sub-devices that each have a subset of the available
registers. The sub-devices may or may not be describe in DT in this
case.

	Arnd

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

* Re: [PATCH v2 00/16] ARM: support for ICP DAS LP-8x4x (with dts)
  2013-12-15  0:53               ` Arnd Bergmann
@ 2013-12-15  2:12                 ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-15  2:12 UTC (permalink / raw)
  To: Arnd Bergmann; +Cc: linux-kernel, linux-arm-kernel, Daniel Mack, Haojian Zhuang

On Sun, 2013-12-15 at 01:53 +0100, Arnd Bergmann wrote:
> On Saturday 14 December 2013, Sergei Ianovich wrote:
> > There are basically 2 options: one-for-all mfd device and one-for-one
> > device drivers.
> > 
> > MFD
> > pros:
> > * easy to add into the tree (one file)
> > * easy config (one option)
> > 
> > Separate devices
> > * easy to support devices as respective subsystems evolve
> > * easy to add new feature without breaking existing ones. Eg. it may
> > make sense to provide industrial IO interface on analog IO devices
> > * possible to have fine-grained configuration (eg. SRAM in kernel,
> > serial and slot as modules)
> > * proper device tree serves as a datasheet for the machine, so anyone
> > who needs to work on it will have a decent view of the internals
> > 
> > I believe long-term benefits of separate devices outweigh immediate
> > effects of an MFD. However, I certainly don't see the big picture and
> > will accept your decision. Please make one.
> 
> Unfortunately I don't have a good way to judge the tradeoffs without
> understanding more about the design of the hardware. Did I understand
> you right that you expect future versions of the FPGA bitstream
> to implement additional features or have a different set of endpoint
> devices?

I am trying to reduce time you spend on review as much as possible.
Please feel free to say if I do something to the opposite.

I could write a lengthy description of the machine as I understand it,
if need be. I am not related to its vendor in any way, so it may or may
not be correct.

I've made to work 100% of features my client needs in the machine. It is
~80% of the devices on the frame and ~10% of possible slot modules.
There are chances someone else will work on the rest, eg. the device
vendor.

This page contains a photo, if there is any interest to see how it looks
like:
http://www.icpdas.com/root/product/solutions/pac/linpac/lp-8x4x_hardware.html

> If so, I would argue that anything that you consider an optional
> sub-device should have its own device node in the device tree.
> 
> Also, do you have to model hardware that is connected to the FPGA
> rather than being part of it?

Anything that can be plugged into the device is discoverable, so doesn't
require to be in the device tree.

> I suspect that you may have a different understanding of the term
> MFD than what I was suggesting: A typical MFD driver in Linux is
> basically a container device that has some registers on its own
> like a version detection or the irqchip but mainly is there to
> create sub-devices that each have a subset of the available
> registers. The sub-devices may or may not be describe in DT in this
> case.

I may be missing something. My general understanding seems to be as
follows. MFD will have probe/remove functionality of drivers for SRAM,
RTC, serial modules in the patch series. MFD will be to FPGA what C
language machine file was to machine: lots of hardcoded constants and
functions which implement non-standard behavior (like set_termios in
8250_lp8x4x.c). This seems to be wrong to me, as device tree is
specifically designed to handle platform device initialization.

The tree you drafted in the previous mail was 100% correct. I though
about doing something like that. I decided not to, since all devices
behind the FPGA are transparently accessed by CPU. I like the idea. I
haven't resent a series with FPGA bus only because you wrote in the same
mail that we need an MFD.

If you say so, we will have an MFD.


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

* [PATCH v2 00/16] ARM: support for ICP DAS LP-8x4x (with dts)
@ 2013-12-15  2:12                 ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-15  2:12 UTC (permalink / raw)
  To: linux-arm-kernel

On Sun, 2013-12-15 at 01:53 +0100, Arnd Bergmann wrote:
> On Saturday 14 December 2013, Sergei Ianovich wrote:
> > There are basically 2 options: one-for-all mfd device and one-for-one
> > device drivers.
> > 
> > MFD
> > pros:
> > * easy to add into the tree (one file)
> > * easy config (one option)
> > 
> > Separate devices
> > * easy to support devices as respective subsystems evolve
> > * easy to add new feature without breaking existing ones. Eg. it may
> > make sense to provide industrial IO interface on analog IO devices
> > * possible to have fine-grained configuration (eg. SRAM in kernel,
> > serial and slot as modules)
> > * proper device tree serves as a datasheet for the machine, so anyone
> > who needs to work on it will have a decent view of the internals
> > 
> > I believe long-term benefits of separate devices outweigh immediate
> > effects of an MFD. However, I certainly don't see the big picture and
> > will accept your decision. Please make one.
> 
> Unfortunately I don't have a good way to judge the tradeoffs without
> understanding more about the design of the hardware. Did I understand
> you right that you expect future versions of the FPGA bitstream
> to implement additional features or have a different set of endpoint
> devices?

I am trying to reduce time you spend on review as much as possible.
Please feel free to say if I do something to the opposite.

I could write a lengthy description of the machine as I understand it,
if need be. I am not related to its vendor in any way, so it may or may
not be correct.

I've made to work 100% of features my client needs in the machine. It is
~80% of the devices on the frame and ~10% of possible slot modules.
There are chances someone else will work on the rest, eg. the device
vendor.

This page contains a photo, if there is any interest to see how it looks
like:
http://www.icpdas.com/root/product/solutions/pac/linpac/lp-8x4x_hardware.html

> If so, I would argue that anything that you consider an optional
> sub-device should have its own device node in the device tree.
> 
> Also, do you have to model hardware that is connected to the FPGA
> rather than being part of it?

Anything that can be plugged into the device is discoverable, so doesn't
require to be in the device tree.

> I suspect that you may have a different understanding of the term
> MFD than what I was suggesting: A typical MFD driver in Linux is
> basically a container device that has some registers on its own
> like a version detection or the irqchip but mainly is there to
> create sub-devices that each have a subset of the available
> registers. The sub-devices may or may not be describe in DT in this
> case.

I may be missing something. My general understanding seems to be as
follows. MFD will have probe/remove functionality of drivers for SRAM,
RTC, serial modules in the patch series. MFD will be to FPGA what C
language machine file was to machine: lots of hardcoded constants and
functions which implement non-standard behavior (like set_termios in
8250_lp8x4x.c). This seems to be wrong to me, as device tree is
specifically designed to handle platform device initialization.

The tree you drafted in the previous mail was 100% correct. I though
about doing something like that. I decided not to, since all devices
behind the FPGA are transparently accessed by CPU. I like the idea. I
haven't resent a series with FPGA bus only because you wrote in the same
mail that we need an MFD.

If you say so, we will have an MFD.

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

* Re: [PATCH v2 00/16] ARM: support for ICP DAS LP-8x4x (with dts)
  2013-12-15  2:12                 ` Sergei Ianovich
@ 2013-12-15  2:55                   ` Arnd Bergmann
  -1 siblings, 0 replies; 700+ messages in thread
From: Arnd Bergmann @ 2013-12-15  2:55 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: linux-kernel, linux-arm-kernel, Daniel Mack, Haojian Zhuang

On Sunday 15 December 2013, Sergei Ianovich wrote:
> On Sun, 2013-12-15 at 01:53 +0100, Arnd Bergmann wrote:
> > On Saturday 14 December 2013, Sergei Ianovich wrote:
> > Unfortunately I don't have a good way to judge the tradeoffs without
> > understanding more about the design of the hardware. Did I understand
> > you right that you expect future versions of the FPGA bitstream
> > to implement additional features or have a different set of endpoint
> > devices?
> 
> I am trying to reduce time you spend on review as much as possible.
> Please feel free to say if I do something to the opposite.
> 
> I could write a lengthy description of the machine as I understand it,
> if need be. I am not related to its vendor in any way, so it may or may
> not be correct.
> 
> I've made to work 100% of features my client needs in the machine. It is
> ~80% of the devices on the frame and ~10% of possible slot modules.
> There are chances someone else will work on the rest, eg. the device
> vendor.
> 
> This page contains a photo, if there is any interest to see how it looks
> like:
> http://www.icpdas.com/root/product/solutions/pac/linpac/lp-8x4x_hardware.html

I see, thanks for the clarification.

> > If so, I would argue that anything that you consider an optional
> > sub-device should have its own device node in the device tree.
> > 
> > Also, do you have to model hardware that is connected to the FPGA
> > rather than being part of it?
> 
> Anything that can be plugged into the device is discoverable, so doesn't
> require to be in the device tree.

Ah, good.

> > I suspect that you may have a different understanding of the term
> > MFD than what I was suggesting: A typical MFD driver in Linux is
> > basically a container device that has some registers on its own
> > like a version detection or the irqchip but mainly is there to
> > create sub-devices that each have a subset of the available
> > registers. The sub-devices may or may not be describe in DT in this
> > case.
> 
> I may be missing something. My general understanding seems to be as
> follows. MFD will have probe/remove functionality of drivers for SRAM,
> RTC, serial modules in the patch series. MFD will be to FPGA what C
> language machine file was to machine: lots of hardcoded constants and
> functions which implement non-standard behavior (like set_termios in
> 8250_lp8x4x.c). This seems to be wrong to me, as device tree is
> specifically designed to handle platform device initialization.
> 
> The tree you drafted in the previous mail was 100% correct. I though
> about doing something like that. I decided not to, since all devices
> behind the FPGA are transparently accessed by CPU. I like the idea. I
> haven't resent a series with FPGA bus only because you wrote in the same
> mail that we need an MFD.
> 
> If you say so, we will have an MFD.

I think I was confused by the fact that the FPGA both has multiple
integrated devices and multiple pluggable devices. Given your explanations,
I think the way you have structured your code is good, and an MFD would
not help. Please just restructure the DT representation to contain the
external-bus and/or the fpga connected to it. You probably don't need both,
but it doesn't hurt to show them as different device-nodes either.
Your choice.

	Arnd

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

* [PATCH v2 00/16] ARM: support for ICP DAS LP-8x4x (with dts)
@ 2013-12-15  2:55                   ` Arnd Bergmann
  0 siblings, 0 replies; 700+ messages in thread
From: Arnd Bergmann @ 2013-12-15  2:55 UTC (permalink / raw)
  To: linux-arm-kernel

On Sunday 15 December 2013, Sergei Ianovich wrote:
> On Sun, 2013-12-15 at 01:53 +0100, Arnd Bergmann wrote:
> > On Saturday 14 December 2013, Sergei Ianovich wrote:
> > Unfortunately I don't have a good way to judge the tradeoffs without
> > understanding more about the design of the hardware. Did I understand
> > you right that you expect future versions of the FPGA bitstream
> > to implement additional features or have a different set of endpoint
> > devices?
> 
> I am trying to reduce time you spend on review as much as possible.
> Please feel free to say if I do something to the opposite.
> 
> I could write a lengthy description of the machine as I understand it,
> if need be. I am not related to its vendor in any way, so it may or may
> not be correct.
> 
> I've made to work 100% of features my client needs in the machine. It is
> ~80% of the devices on the frame and ~10% of possible slot modules.
> There are chances someone else will work on the rest, eg. the device
> vendor.
> 
> This page contains a photo, if there is any interest to see how it looks
> like:
> http://www.icpdas.com/root/product/solutions/pac/linpac/lp-8x4x_hardware.html

I see, thanks for the clarification.

> > If so, I would argue that anything that you consider an optional
> > sub-device should have its own device node in the device tree.
> > 
> > Also, do you have to model hardware that is connected to the FPGA
> > rather than being part of it?
> 
> Anything that can be plugged into the device is discoverable, so doesn't
> require to be in the device tree.

Ah, good.

> > I suspect that you may have a different understanding of the term
> > MFD than what I was suggesting: A typical MFD driver in Linux is
> > basically a container device that has some registers on its own
> > like a version detection or the irqchip but mainly is there to
> > create sub-devices that each have a subset of the available
> > registers. The sub-devices may or may not be describe in DT in this
> > case.
> 
> I may be missing something. My general understanding seems to be as
> follows. MFD will have probe/remove functionality of drivers for SRAM,
> RTC, serial modules in the patch series. MFD will be to FPGA what C
> language machine file was to machine: lots of hardcoded constants and
> functions which implement non-standard behavior (like set_termios in
> 8250_lp8x4x.c). This seems to be wrong to me, as device tree is
> specifically designed to handle platform device initialization.
> 
> The tree you drafted in the previous mail was 100% correct. I though
> about doing something like that. I decided not to, since all devices
> behind the FPGA are transparently accessed by CPU. I like the idea. I
> haven't resent a series with FPGA bus only because you wrote in the same
> mail that we need an MFD.
> 
> If you say so, we will have an MFD.

I think I was confused by the fact that the FPGA both has multiple
integrated devices and multiple pluggable devices. Given your explanations,
I think the way you have structured your code is good, and an MFD would
not help. Please just restructure the DT representation to contain the
external-bus and/or the fpga connected to it. You probably don't need both,
but it doesn't hurt to show them as different device-nodes either.
Your choice.

	Arnd

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

* Re: [PATCH v2 03/16] ARM: dts: provide DMA config to pxamci
  2013-12-14 19:34               ` Sergei Ianovich
@ 2013-12-16  9:58                 ` Daniel Mack
  -1 siblings, 0 replies; 700+ messages in thread
From: Daniel Mack @ 2013-12-16  9:58 UTC (permalink / raw)
  To: Sergei Ianovich, Arnd Bergmann
  Cc: Mark Rutland, open list:OPEN FIRMWARE AND...,
	Shawn Guo, Russell King, Pawel Moll, Stephen Warren,
	Viresh Kumar, Ian Campbell, DOCUMENTATION, linux-kernel,
	Rob Herring, Haojian Zhuang, Rob Landley, linux-mmc, Chris Ball,
	linux-arm-kernel

On 12/14/2013 08:34 PM, Sergei Ianovich wrote:
> On Sat, 2013-12-14 at 20:06 +0100, Arnd Bergmann wrote:

>> The patch looks ok in case we are merging your patches for 3.14
>> and Daniel's patches later than that. If they end up in the
>> same merge window however, we'd have to be care to resolve
>> the obvious conflict in a proper way.
> 
> The most recently published Daniel's patch (Aug 2013) wraps
> IORESOURCE_DMA handling on DT presence in a similar way,

Erm, no it doesn't. My patch uses dma_request_slave_channel_compat() in
DT case, and that works fine with the current version of pdma, and
there's no need to read the "dmas" properties directly.

If you want to provide a way to simply denote the dma channel numbers,
without looking at the actual phandle, then yes, we could merge this
patch first, but it would be effectively reverted a proper implementation.


Daniel

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

* [PATCH v2 03/16] ARM: dts: provide DMA config to pxamci
@ 2013-12-16  9:58                 ` Daniel Mack
  0 siblings, 0 replies; 700+ messages in thread
From: Daniel Mack @ 2013-12-16  9:58 UTC (permalink / raw)
  To: linux-arm-kernel

On 12/14/2013 08:34 PM, Sergei Ianovich wrote:
> On Sat, 2013-12-14 at 20:06 +0100, Arnd Bergmann wrote:

>> The patch looks ok in case we are merging your patches for 3.14
>> and Daniel's patches later than that. If they end up in the
>> same merge window however, we'd have to be care to resolve
>> the obvious conflict in a proper way.
> 
> The most recently published Daniel's patch (Aug 2013) wraps
> IORESOURCE_DMA handling on DT presence in a similar way,

Erm, no it doesn't. My patch uses dma_request_slave_channel_compat() in
DT case, and that works fine with the current version of pdma, and
there's no need to read the "dmas" properties directly.

If you want to provide a way to simply denote the dma channel numbers,
without looking at the actual phandle, then yes, we could merge this
patch first, but it would be effectively reverted a proper implementation.


Daniel

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

* Re: [PATCH v2 03/16] ARM: dts: provide DMA config to pxamci
  2013-12-16  9:58                 ` Daniel Mack
@ 2013-12-16 11:47                   ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-16 11:47 UTC (permalink / raw)
  To: Daniel Mack
  Cc: Arnd Bergmann, linux-kernel, linux-arm-kernel, Rob Herring,
	Pawel Moll, Mark Rutland, Stephen Warren, Ian Campbell,
	Rob Landley, Russell King, Chris Ball, Viresh Kumar, Shawn Guo,
	Haojian Zhuang, open list:OPEN FIRMWARE AND...,
	DOCUMENTATION, linux-mmc

On Mon, 2013-12-16 at 10:58 +0100, Daniel Mack wrote:
> On 12/14/2013 08:34 PM, Sergei Ianovich wrote:
> > On Sat, 2013-12-14 at 20:06 +0100, Arnd Bergmann wrote:
> 
> >> The patch looks ok in case we are merging your patches for 3.14
> >> and Daniel's patches later than that. If they end up in the
> >> same merge window however, we'd have to be care to resolve
> >> the obvious conflict in a proper way.
> > 
> > The most recently published Daniel's patch (Aug 2013) wraps
> > IORESOURCE_DMA handling on DT presence in a similar way,
> 
> Erm, no it doesn't. My patch uses dma_request_slave_channel_compat() in
> DT case, and that works fine with the current version of pdma, and
> there's no need to read the "dmas" properties directly.
> 
> If you want to provide a way to simply denote the dma channel numbers,
> without looking at the actual phandle, then yes, we could merge this
> patch first, but it would be effectively reverted a proper implementation.

Daniel is right. His patch doesn't need to read "dmas" directly. So my
patch won't need to change drivers/mmc/host/pxamci.c at all, if it is
applied after Daniel's one.

What are we going to do in this context?


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

* [PATCH v2 03/16] ARM: dts: provide DMA config to pxamci
@ 2013-12-16 11:47                   ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-16 11:47 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, 2013-12-16 at 10:58 +0100, Daniel Mack wrote:
> On 12/14/2013 08:34 PM, Sergei Ianovich wrote:
> > On Sat, 2013-12-14 at 20:06 +0100, Arnd Bergmann wrote:
> 
> >> The patch looks ok in case we are merging your patches for 3.14
> >> and Daniel's patches later than that. If they end up in the
> >> same merge window however, we'd have to be care to resolve
> >> the obvious conflict in a proper way.
> > 
> > The most recently published Daniel's patch (Aug 2013) wraps
> > IORESOURCE_DMA handling on DT presence in a similar way,
> 
> Erm, no it doesn't. My patch uses dma_request_slave_channel_compat() in
> DT case, and that works fine with the current version of pdma, and
> there's no need to read the "dmas" properties directly.
> 
> If you want to provide a way to simply denote the dma channel numbers,
> without looking at the actual phandle, then yes, we could merge this
> patch first, but it would be effectively reverted a proper implementation.

Daniel is right. His patch doesn't need to read "dmas" directly. So my
patch won't need to change drivers/mmc/host/pxamci.c at all, if it is
applied after Daniel's one.

What are we going to do in this context?

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

* Re: [PATCH v2 03/16] ARM: dts: provide DMA config to pxamci
@ 2013-12-16 11:58                     ` Lars-Peter Clausen
  0 siblings, 0 replies; 700+ messages in thread
From: Lars-Peter Clausen @ 2013-12-16 11:58 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: Daniel Mack, Arnd Bergmann, linux-kernel, linux-arm-kernel,
	Rob Herring, Pawel Moll, Mark Rutland, Stephen Warren,
	Ian Campbell, Rob Landley, Russell King, Chris Ball,
	Viresh Kumar, Shawn Guo, Haojian Zhuang,
	open list:OPEN FIRMWARE AND...,
	DOCUMENTATION, linux-mmc

On 12/16/2013 12:47 PM, Sergei Ianovich wrote:
> On Mon, 2013-12-16 at 10:58 +0100, Daniel Mack wrote:
>> On 12/14/2013 08:34 PM, Sergei Ianovich wrote:
>>> On Sat, 2013-12-14 at 20:06 +0100, Arnd Bergmann wrote:
>>
>>>> The patch looks ok in case we are merging your patches for 3.14
>>>> and Daniel's patches later than that. If they end up in the
>>>> same merge window however, we'd have to be care to resolve
>>>> the obvious conflict in a proper way.
>>>
>>> The most recently published Daniel's patch (Aug 2013) wraps
>>> IORESOURCE_DMA handling on DT presence in a similar way,
>>
>> Erm, no it doesn't. My patch uses dma_request_slave_channel_compat() in
>> DT case, and that works fine with the current version of pdma, and
>> there's no need to read the "dmas" properties directly.
>>
>> If you want to provide a way to simply denote the dma channel numbers,
>> without looking at the actual phandle, then yes, we could merge this
>> patch first, but it would be effectively reverted a proper implementation.
> 
> Daniel is right. His patch doesn't need to read "dmas" directly. So my
> patch won't need to change drivers/mmc/host/pxamci.c at all, if it is
> applied after Daniel's one.
> 

Btw. any driver that parses the dmas property manually should be considered
broken. This is a classical layering violation. The layout of the dma
specifier is DMA controller specific and should be completely transparent to
the device driver.

- Lars

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

* Re: [PATCH v2 03/16] ARM: dts: provide DMA config to pxamci
@ 2013-12-16 11:58                     ` Lars-Peter Clausen
  0 siblings, 0 replies; 700+ messages in thread
From: Lars-Peter Clausen @ 2013-12-16 11:58 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: Daniel Mack, Arnd Bergmann, linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Rob Herring,
	Pawel Moll, Mark Rutland, Stephen Warren, Ian Campbell,
	Rob Landley, Russell King, Chris Ball, Viresh Kumar, Shawn Guo,
	Haojian Zhuang, open list:OPEN FIRMWARE AND...,
	DOCUMENTATION, linux-mmc-u79uwXL29TY76Z2rM5mHXA

On 12/16/2013 12:47 PM, Sergei Ianovich wrote:
> On Mon, 2013-12-16 at 10:58 +0100, Daniel Mack wrote:
>> On 12/14/2013 08:34 PM, Sergei Ianovich wrote:
>>> On Sat, 2013-12-14 at 20:06 +0100, Arnd Bergmann wrote:
>>
>>>> The patch looks ok in case we are merging your patches for 3.14
>>>> and Daniel's patches later than that. If they end up in the
>>>> same merge window however, we'd have to be care to resolve
>>>> the obvious conflict in a proper way.
>>>
>>> The most recently published Daniel's patch (Aug 2013) wraps
>>> IORESOURCE_DMA handling on DT presence in a similar way,
>>
>> Erm, no it doesn't. My patch uses dma_request_slave_channel_compat() in
>> DT case, and that works fine with the current version of pdma, and
>> there's no need to read the "dmas" properties directly.
>>
>> If you want to provide a way to simply denote the dma channel numbers,
>> without looking at the actual phandle, then yes, we could merge this
>> patch first, but it would be effectively reverted a proper implementation.
> 
> Daniel is right. His patch doesn't need to read "dmas" directly. So my
> patch won't need to change drivers/mmc/host/pxamci.c at all, if it is
> applied after Daniel's one.
> 

Btw. any driver that parses the dmas property manually should be considered
broken. This is a classical layering violation. The layout of the dma
specifier is DMA controller specific and should be completely transparent to
the device driver.

- Lars
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH v2 03/16] ARM: dts: provide DMA config to pxamci
@ 2013-12-16 11:58                     ` Lars-Peter Clausen
  0 siblings, 0 replies; 700+ messages in thread
From: Lars-Peter Clausen @ 2013-12-16 11:58 UTC (permalink / raw)
  To: linux-arm-kernel

On 12/16/2013 12:47 PM, Sergei Ianovich wrote:
> On Mon, 2013-12-16 at 10:58 +0100, Daniel Mack wrote:
>> On 12/14/2013 08:34 PM, Sergei Ianovich wrote:
>>> On Sat, 2013-12-14 at 20:06 +0100, Arnd Bergmann wrote:
>>
>>>> The patch looks ok in case we are merging your patches for 3.14
>>>> and Daniel's patches later than that. If they end up in the
>>>> same merge window however, we'd have to be care to resolve
>>>> the obvious conflict in a proper way.
>>>
>>> The most recently published Daniel's patch (Aug 2013) wraps
>>> IORESOURCE_DMA handling on DT presence in a similar way,
>>
>> Erm, no it doesn't. My patch uses dma_request_slave_channel_compat() in
>> DT case, and that works fine with the current version of pdma, and
>> there's no need to read the "dmas" properties directly.
>>
>> If you want to provide a way to simply denote the dma channel numbers,
>> without looking at the actual phandle, then yes, we could merge this
>> patch first, but it would be effectively reverted a proper implementation.
> 
> Daniel is right. His patch doesn't need to read "dmas" directly. So my
> patch won't need to change drivers/mmc/host/pxamci.c at all, if it is
> applied after Daniel's one.
> 

Btw. any driver that parses the dmas property manually should be considered
broken. This is a classical layering violation. The layout of the dma
specifier is DMA controller specific and should be completely transparent to
the device driver.

- Lars

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

* Re: [PATCH v2 03/16] ARM: dts: provide DMA config to pxamci
  2013-12-16 11:58                     ` Lars-Peter Clausen
@ 2013-12-16 12:03                       ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-16 12:03 UTC (permalink / raw)
  To: Lars-Peter Clausen
  Cc: Daniel Mack, Arnd Bergmann, linux-kernel, linux-arm-kernel,
	Rob Herring, Pawel Moll, Mark Rutland, Stephen Warren,
	Ian Campbell, Rob Landley, Russell King, Chris Ball,
	Viresh Kumar, Shawn Guo, Haojian Zhuang,
	open list:OPEN FIRMWARE AND...,
	DOCUMENTATION, linux-mmc

On Mon, 2013-12-16 at 12:58 +0100, Lars-Peter Clausen wrote:
> Btw. any driver that parses the dmas property manually should be considered
> broken. This is a classical layering violation. The layout of the dma
> specifier is DMA controller specific and should be completely transparent to
> the device driver.

PXA as a whole is broken in this respect at the moment. The problem is
how to move to a "fixed" state without breaking things which work now.


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

* [PATCH v2 03/16] ARM: dts: provide DMA config to pxamci
@ 2013-12-16 12:03                       ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-16 12:03 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, 2013-12-16 at 12:58 +0100, Lars-Peter Clausen wrote:
> Btw. any driver that parses the dmas property manually should be considered
> broken. This is a classical layering violation. The layout of the dma
> specifier is DMA controller specific and should be completely transparent to
> the device driver.

PXA as a whole is broken in this respect at the moment. The problem is
how to move to a "fixed" state without breaking things which work now.

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

* Re: [PATCH v2 00/16] ARM: support for ICP DAS LP-8x4x (with dts)
  2013-12-15  2:55                   ` Arnd Bergmann
@ 2013-12-16 13:01                     ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-16 13:01 UTC (permalink / raw)
  To: Arnd Bergmann; +Cc: linux-kernel, linux-arm-kernel, Daniel Mack, Haojian Zhuang

On Sun, 2013-12-15 at 03:55 +0100, Arnd Bergmann wrote:
> On Sunday 15 December 2013, Sergei Ianovich wrote:
> ...
> I think the way you have structured your code is good, and an MFD would
> not help. Please just restructure the DT representation to contain the
> external-bus and/or the fpga connected to it. You probably don't need both,
> but it doesn't hurt to show them as different device-nodes either.
> Your choice.

PXA27x memory bus can have up to 10 devices: up to 6 slower
flash/SRAM/variable-latency-IO selected by nCS<0> to <5>, and up to 4
partions of SDRAM selected by nSDCS<0> to <3>.

It appears that the FPGA is directly connected to the memory bus and is
selected by nCS<5>. According to MSC2 configuration (already in the
mainstream U-Boot), the FPGA is configured as a synchronous SRAM with
access cycle of 30x memory bus cycles. So I made it a top-level bus like
pxabus.

Ethernet devices are also connected to the memory bus via some kind of
gate array. This one is a bit faster -- 15x memory cycles, which is
still a lot. It explains why network transfers are never faster than 15
Mbit/s.

The final tree looks like this:

diff --git a/arch/arm/boot/dts/pxa27x-lp8x4x.dts b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
new file mode 100644
index 0000000..cb2a31d
--- /dev/null
+++ b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
@@ -0,0 +1,208 @@
+/* Device tree for ICP DAS LP-8x4x */
+/dts-v1/;
+
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include "pxa27x.dtsi"
+
+/ {
+	model = "ICP DAS LP-8x4x programmable automation controller";
+	compatible = "marvell,lp8x4x", "marvell,pxa270";
+
+	aliases {
+		ethernet0 = &eth0;
+		ethernet1 = &eth1;
+	};
+
+	memory {
+		/*
+		 * SDRAM
+		 * connected to CPU via nSDCS<0>
+		 */
+		reg = <0xa0000000 0x08000000>;
+	};
+
+	regulators {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		vmmc: regulator@0 {
+			compatible = "regulator-fixed";
+			reg = <0>;
+			regulator-name = "vmmc";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-always-on;
+		};
+	};
+
+	flash@00000000 {
+		/*
+		 * Boot memory
+		 * connected to CPU via nCS<0>
+		 */
+		compatible = "cfi-flash";
+		reg = <0x0 0x02000000>;
+		bank-width = <4>;
+		device-width = <2>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		fs@0 {
+			label = "u-boot";
+			reg = <0 0x40000>;
+		};
+		fs@40000 {
+			label = "settings";
+			reg = <0x40000 0x40000>;
+		};
+		fs@80000 {
+			label = "kernel";
+			reg = <0x80000 0x280000>;
+		};
+		fs@300000 {
+			label = "root_fs";
+			reg = <0x300000 0x1d00000>;
+		};
+	};
+
+	flash@04000000 {
+		/*
+		 * connected to CPU via nCS<1>
+		 */
+		compatible = "cfi-flash";
+		reg = <0x04000000 0x02000000>;
+		bank-width = <2>;
+		device-width = <1>;
+	};
+
+	pxabus {
+		pxairq: interrupt-controller@40d00000 {
+			marvell,intc-priority;
+			marvell,intc-nr-irqs = <34>;
+		};
+
+		uart@40100000 {
+			status = "okay";
+		};
+
+		uart@40200000 {
+			status = "okay";
+		};
+
+		uart@40700000 {
+			status = "okay";
+		};
+
+		mmc@41100000 {
+			status = "okay";
+			vmmc-supply = <&vmmc>;
+		};
+
+		ohci@4c000000 {
+			status = "okay";
+			marvell,port-mode = <3>;
+			marvell,oc-mode-perport;
+			marvell,enable-port1;
+		};
+	};
+
+	extbus {
+		/*
+		 * Transparent bus, 2 byte-wide access
+		 * connected to CPU via nCS<3>
+		 */
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+		interrupt-parent = <&gpio>;
+
+		eth0: eth@0c000000 {
+			compatible = "davicom,dm9000";
+			reg = <0x0c000000 0x2
+			       0x0c004000 0x2>;
+			interrupts = <9 IRQ_TYPE_EDGE_RISING>;
+			status = "okay";
+		};
+
+		eth1: eth@0d000000 {
+			compatible = "davicom,dm9000";
+			reg = <0x0d000000 0x2
+			       0x0d004000 0x2>;
+			interrupts = <82 IRQ_TYPE_EDGE_RISING>;
+			status = "okay";
+		};
+	};
+
+	fpgabus {
+		/*
+		 * Transparent bus, 1 byte-wide access, even addresses only
+		 * connected to CPU via nCS<5>
+		 */
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges = <0 0x17000000 0x10000>;
+		interrupt-parent = <&fpga>;
+
+		rtc@901c {
+			compatible = "ds,rtc-ds1302";
+			reg = <0x901c 0x1>;
+			status = "okay";
+		};
+
+		sram@a000 {
+			compatible = "icpdas,sram-lp8x4x";
+			reg = <0xa000 0x1000
+			       0x901e 0x1>;
+		};
+
+		fpga: irq@9006 {
+			compatible = "icpdas,irq-lp8x4x";
+			reg = <0x9006 0x16>;
+			interrupt-parent = <&gpio>;
+			interrupts = <3 IRQ_TYPE_EDGE_FALLING>;
+			#interrupt-cells = <1>;
+			interrupt-controller;
+			status = "okay";
+		};
+
+		uart@9050 {
+			compatible = "icpdas,uart-lp8x4x";
+			reg = <0x9050 0x10
+			       0x9030 0x02>;
+			interrupts = <13>;
+			status = "okay";
+		};
+
+		uart@9060 {
+			compatible = "icpdas,uart-lp8x4x";
+			reg = <0x9060 0x10
+			       0x9032 0x02>;
+			interrupts = <14>;
+			status = "okay";
+		};
+
+		uart@9070 {
+			compatible = "icpdas,uart-lp8x4x";
+			reg = <0x9070 0x10
+			       0x9034 0x02>;
+			interrupts = <15>;
+			status = "okay";
+		};
+
+		backplane@9046 {
+			compatible = "icpdas,backplane-lp8x4x";
+			reg = <0x9046 0x2
+			       0x9004 0x2
+			       0x1000 0x10
+			       0x2000 0x10
+			       0x3000 0x10
+			       0x4000 0x10
+			       0x5000 0x10
+			       0x6000 0x10
+			       0x7000 0x10
+			       0x8000 0x10>;
+		};
+	};
+};




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

* [PATCH v2 00/16] ARM: support for ICP DAS LP-8x4x (with dts)
@ 2013-12-16 13:01                     ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-16 13:01 UTC (permalink / raw)
  To: linux-arm-kernel

On Sun, 2013-12-15 at 03:55 +0100, Arnd Bergmann wrote:
> On Sunday 15 December 2013, Sergei Ianovich wrote:
> ...
> I think the way you have structured your code is good, and an MFD would
> not help. Please just restructure the DT representation to contain the
> external-bus and/or the fpga connected to it. You probably don't need both,
> but it doesn't hurt to show them as different device-nodes either.
> Your choice.

PXA27x memory bus can have up to 10 devices: up to 6 slower
flash/SRAM/variable-latency-IO selected by nCS<0> to <5>, and up to 4
partions of SDRAM selected by nSDCS<0> to <3>.

It appears that the FPGA is directly connected to the memory bus and is
selected by nCS<5>. According to MSC2 configuration (already in the
mainstream U-Boot), the FPGA is configured as a synchronous SRAM with
access cycle of 30x memory bus cycles. So I made it a top-level bus like
pxabus.

Ethernet devices are also connected to the memory bus via some kind of
gate array. This one is a bit faster -- 15x memory cycles, which is
still a lot. It explains why network transfers are never faster than 15
Mbit/s.

The final tree looks like this:

diff --git a/arch/arm/boot/dts/pxa27x-lp8x4x.dts b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
new file mode 100644
index 0000000..cb2a31d
--- /dev/null
+++ b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
@@ -0,0 +1,208 @@
+/* Device tree for ICP DAS LP-8x4x */
+/dts-v1/;
+
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include "pxa27x.dtsi"
+
+/ {
+	model = "ICP DAS LP-8x4x programmable automation controller";
+	compatible = "marvell,lp8x4x", "marvell,pxa270";
+
+	aliases {
+		ethernet0 = &eth0;
+		ethernet1 = &eth1;
+	};
+
+	memory {
+		/*
+		 * SDRAM
+		 * connected to CPU via nSDCS<0>
+		 */
+		reg = <0xa0000000 0x08000000>;
+	};
+
+	regulators {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		vmmc: regulator at 0 {
+			compatible = "regulator-fixed";
+			reg = <0>;
+			regulator-name = "vmmc";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-always-on;
+		};
+	};
+
+	flash at 00000000 {
+		/*
+		 * Boot memory
+		 * connected to CPU via nCS<0>
+		 */
+		compatible = "cfi-flash";
+		reg = <0x0 0x02000000>;
+		bank-width = <4>;
+		device-width = <2>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		fs at 0 {
+			label = "u-boot";
+			reg = <0 0x40000>;
+		};
+		fs at 40000 {
+			label = "settings";
+			reg = <0x40000 0x40000>;
+		};
+		fs at 80000 {
+			label = "kernel";
+			reg = <0x80000 0x280000>;
+		};
+		fs at 300000 {
+			label = "root_fs";
+			reg = <0x300000 0x1d00000>;
+		};
+	};
+
+	flash at 04000000 {
+		/*
+		 * connected to CPU via nCS<1>
+		 */
+		compatible = "cfi-flash";
+		reg = <0x04000000 0x02000000>;
+		bank-width = <2>;
+		device-width = <1>;
+	};
+
+	pxabus {
+		pxairq: interrupt-controller at 40d00000 {
+			marvell,intc-priority;
+			marvell,intc-nr-irqs = <34>;
+		};
+
+		uart at 40100000 {
+			status = "okay";
+		};
+
+		uart at 40200000 {
+			status = "okay";
+		};
+
+		uart at 40700000 {
+			status = "okay";
+		};
+
+		mmc at 41100000 {
+			status = "okay";
+			vmmc-supply = <&vmmc>;
+		};
+
+		ohci at 4c000000 {
+			status = "okay";
+			marvell,port-mode = <3>;
+			marvell,oc-mode-perport;
+			marvell,enable-port1;
+		};
+	};
+
+	extbus {
+		/*
+		 * Transparent bus, 2 byte-wide access
+		 * connected to CPU via nCS<3>
+		 */
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+		interrupt-parent = <&gpio>;
+
+		eth0: eth at 0c000000 {
+			compatible = "davicom,dm9000";
+			reg = <0x0c000000 0x2
+			       0x0c004000 0x2>;
+			interrupts = <9 IRQ_TYPE_EDGE_RISING>;
+			status = "okay";
+		};
+
+		eth1: eth at 0d000000 {
+			compatible = "davicom,dm9000";
+			reg = <0x0d000000 0x2
+			       0x0d004000 0x2>;
+			interrupts = <82 IRQ_TYPE_EDGE_RISING>;
+			status = "okay";
+		};
+	};
+
+	fpgabus {
+		/*
+		 * Transparent bus, 1 byte-wide access, even addresses only
+		 * connected to CPU via nCS<5>
+		 */
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges = <0 0x17000000 0x10000>;
+		interrupt-parent = <&fpga>;
+
+		rtc at 901c {
+			compatible = "ds,rtc-ds1302";
+			reg = <0x901c 0x1>;
+			status = "okay";
+		};
+
+		sram at a000 {
+			compatible = "icpdas,sram-lp8x4x";
+			reg = <0xa000 0x1000
+			       0x901e 0x1>;
+		};
+
+		fpga: irq at 9006 {
+			compatible = "icpdas,irq-lp8x4x";
+			reg = <0x9006 0x16>;
+			interrupt-parent = <&gpio>;
+			interrupts = <3 IRQ_TYPE_EDGE_FALLING>;
+			#interrupt-cells = <1>;
+			interrupt-controller;
+			status = "okay";
+		};
+
+		uart at 9050 {
+			compatible = "icpdas,uart-lp8x4x";
+			reg = <0x9050 0x10
+			       0x9030 0x02>;
+			interrupts = <13>;
+			status = "okay";
+		};
+
+		uart at 9060 {
+			compatible = "icpdas,uart-lp8x4x";
+			reg = <0x9060 0x10
+			       0x9032 0x02>;
+			interrupts = <14>;
+			status = "okay";
+		};
+
+		uart at 9070 {
+			compatible = "icpdas,uart-lp8x4x";
+			reg = <0x9070 0x10
+			       0x9034 0x02>;
+			interrupts = <15>;
+			status = "okay";
+		};
+
+		backplane at 9046 {
+			compatible = "icpdas,backplane-lp8x4x";
+			reg = <0x9046 0x2
+			       0x9004 0x2
+			       0x1000 0x10
+			       0x2000 0x10
+			       0x3000 0x10
+			       0x4000 0x10
+			       0x5000 0x10
+			       0x6000 0x10
+			       0x7000 0x10
+			       0x8000 0x10>;
+		};
+	};
+};

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

* Re: [PATCH v2 00/16] ARM: support for ICP DAS LP-8x4x (with dts)
  2013-12-16 13:01                     ` Sergei Ianovich
@ 2013-12-16 17:56                       ` Arnd Bergmann
  -1 siblings, 0 replies; 700+ messages in thread
From: Arnd Bergmann @ 2013-12-16 17:56 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: linux-kernel, linux-arm-kernel, Daniel Mack, Haojian Zhuang

On Monday 16 December 2013, Sergei Ianovich wrote:
> PXA27x memory bus can have up to 10 devices: up to 6 slower
> flash/SRAM/variable-latency-IO selected by nCS<0> to <5>, and up to 4
> partions of SDRAM selected by nSDCS<0> to <3>.
> 
> It appears that the FPGA is directly connected to the memory bus and is
> selected by nCS<5>. According to MSC2 configuration (already in the
> mainstream U-Boot), the FPGA is configured as a synchronous SRAM with
> access cycle of 30x memory bus cycles. So I made it a top-level bus like
> pxabus.
> 
> Ethernet devices are also connected to the memory bus via some kind of
> gate array. This one is a bit faster -- 15x memory cycles, which is
> still a lot. It explains why network transfers are never faster than 15
> Mbit/s.

Ok, I see. This sounds like some of the other platforms we have with
external memory buses. If there is a chance that Linux ever has to
program the per-CS settings into the bus controller, I would suggest
to represent that as well as a separate node, like this

extbus {
	compatible = "simple-bus";

	#address-cells = <2>; /* first cell is nCS, second is address */
	#size-cells = <1>;

	ranges = <0 0 0 0x04000000>
		 <1 0 0x04000000 0x04000000>
		 <2 0 0x08000000 0x04000000>
		 <3 0 0x0c000000 0x04000000>
	  	 <4 0 0x10000000 0x04000000>
	  	 <5 0 0x14000000 0x04000000>;

	timings = ...;

	flash@0 {
		reg = <0 0x0 0x02000000>;
		...
	};

	flash@1 {
		reg = <1 0x0 0x02000000>;
		...
	};

	fpga@5 {
		#address-cells = <1>;
		#size-cells = <1>;
		ranges = <0 5 0x03000000 0x10000>;
		...
	};
};

In case there is a driver for the extbus node, I would not make it
"simple-bus" but instead add a separate compatible string to match
the driver, and let that driver call of_platform_populate
to probe the children after the bus is set up.

	Arnd

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

* [PATCH v2 00/16] ARM: support for ICP DAS LP-8x4x (with dts)
@ 2013-12-16 17:56                       ` Arnd Bergmann
  0 siblings, 0 replies; 700+ messages in thread
From: Arnd Bergmann @ 2013-12-16 17:56 UTC (permalink / raw)
  To: linux-arm-kernel

On Monday 16 December 2013, Sergei Ianovich wrote:
> PXA27x memory bus can have up to 10 devices: up to 6 slower
> flash/SRAM/variable-latency-IO selected by nCS<0> to <5>, and up to 4
> partions of SDRAM selected by nSDCS<0> to <3>.
> 
> It appears that the FPGA is directly connected to the memory bus and is
> selected by nCS<5>. According to MSC2 configuration (already in the
> mainstream U-Boot), the FPGA is configured as a synchronous SRAM with
> access cycle of 30x memory bus cycles. So I made it a top-level bus like
> pxabus.
> 
> Ethernet devices are also connected to the memory bus via some kind of
> gate array. This one is a bit faster -- 15x memory cycles, which is
> still a lot. It explains why network transfers are never faster than 15
> Mbit/s.

Ok, I see. This sounds like some of the other platforms we have with
external memory buses. If there is a chance that Linux ever has to
program the per-CS settings into the bus controller, I would suggest
to represent that as well as a separate node, like this

extbus {
	compatible = "simple-bus";

	#address-cells = <2>; /* first cell is nCS, second is address */
	#size-cells = <1>;

	ranges = <0 0 0 0x04000000>
		 <1 0 0x04000000 0x04000000>
		 <2 0 0x08000000 0x04000000>
		 <3 0 0x0c000000 0x04000000>
	  	 <4 0 0x10000000 0x04000000>
	  	 <5 0 0x14000000 0x04000000>;

	timings = ...;

	flash at 0 {
		reg = <0 0x0 0x02000000>;
		...
	};

	flash at 1 {
		reg = <1 0x0 0x02000000>;
		...
	};

	fpga at 5 {
		#address-cells = <1>;
		#size-cells = <1>;
		ranges = <0 5 0x03000000 0x10000>;
		...
	};
};

In case there is a driver for the extbus node, I would not make it
"simple-bus" but instead add a separate compatible string to match
the driver, and let that driver call of_platform_populate
to probe the children after the bus is set up.

	Arnd

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

* Re: [PATCH v2 00/16] ARM: support for ICP DAS LP-8x4x (with dts)
  2013-12-16 17:56                       ` Arnd Bergmann
@ 2013-12-16 20:38                         ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-16 20:38 UTC (permalink / raw)
  To: Arnd Bergmann; +Cc: linux-kernel, linux-arm-kernel, Daniel Mack, Haojian Zhuang

On Mon, 2013-12-16 at 18:56 +0100, Arnd Bergmann wrote:
> Ok, I see. This sounds like some of the other platforms we have with
> external memory buses. If there is a chance that Linux ever has to
> program the per-CS settings into the bus controller, I would suggest
> to represent that as well as a separate node, like this

This is a platform-specific bus (PXA27x). Should it go into pxa27x.dtsi
rather than machine dts?

> In case there is a driver for the extbus node, I would not make it
> "simple-bus" but instead add a separate compatible string to match
> the driver, and let that driver call of_platform_populate
> to probe the children after the bus is set up.

There seems to be none at the moment. However, some machines need to
setup these partitions as a part of their initialization. So complete
migration to DT will require this driver.

In LP-8x4x case everything is setup by the bootloader. So "simple-bus"
works for me.



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

* [PATCH v2 00/16] ARM: support for ICP DAS LP-8x4x (with dts)
@ 2013-12-16 20:38                         ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-16 20:38 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, 2013-12-16 at 18:56 +0100, Arnd Bergmann wrote:
> Ok, I see. This sounds like some of the other platforms we have with
> external memory buses. If there is a chance that Linux ever has to
> program the per-CS settings into the bus controller, I would suggest
> to represent that as well as a separate node, like this

This is a platform-specific bus (PXA27x). Should it go into pxa27x.dtsi
rather than machine dts?

> In case there is a driver for the extbus node, I would not make it
> "simple-bus" but instead add a separate compatible string to match
> the driver, and let that driver call of_platform_populate
> to probe the children after the bus is set up.

There seems to be none at the moment. However, some machines need to
setup these partitions as a part of their initialization. So complete
migration to DT will require this driver.

In LP-8x4x case everything is setup by the bootloader. So "simple-bus"
works for me.

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

* [PATCH v3 00/21] ARM: support for ICP DAS LP-8x4x (with dts)
  2013-12-13  2:27         ` Sergei Ianovich
@ 2013-12-17 19:37           ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-17 19:37 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Daniel Mack, Arnd Bergmann, Haojian Zhuang

Two review comments are not finally settled:

1. Use of new DMA
My  best guess is to split the patch in two, so that Daniel could easily
revert the workaround, once a solution is ready.

2. Device tree representation
I've put extbus into platform include file, since the bus is platform-
specific, not board-specific.

Frame support is now close to 95%, pluggable module support is
at around 20%. Most modules should be possible to handele by already
working get_DI/DO/AO set_DO/AO functions. I am not including support,
since I didn't actually tested the hardware. The same about RS232/485
pluggable port.

ICP DAS calls LP-8x4x 'programmable automation controller'. It is
an industrial computer based on PXA270 SoC. They ship it with a 2.6.19
kernel and proprietary kernel module and userspace library to access
its industrial IO.

This patch allows to boot the device with a modern kernel with device
tree. It adds support for:
* MMC card interface on PXA270
* USB 1.1 port on PXA270
* 2 NOR flash devices
* 2 onboard ethernet Davicom DM9000 devices
* 3 serial UART ports on PXA270
* front panel red LED
* 64bit 1-wire system ID chip
* 16 kiB EEPROM (reading)

Support for these devices will be added in separate patches, since
they are not currently supported by the kernel:
* DS1302 RTC
* 512kiB SRAM
* FPGA irq chip
* 3 built-in 16550A serial UART ports
* industrial IO parallel bus
* 10 position rotary switch
* 8 pin DIP switch
* 16 kiB EEPROM (writing)
* serial interface for digital and analog industrial IO modules on
  parallel bus (all I-87... modules)
* digital and analog industrial IO modules for parallel bus:
  ** I-8024 4 port analog output
  ** I-8041 32 port digital output
  ** I-8042 16 port digital output/16 port digital input

Not supported for now:
* VGA interface on PXA270 for lack of dts binding
* the rest of parallel bus (I-8...) modules for lack of hardware
* GPIO reset for lack of relevance (watchdog reset is working)

NOTE: USB support requires U-Boot patch series which setups GPIO.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Daniel Mack <zonque@gmail.com>
CC: Arnd Bergmann <arnd@arndb.de>
CC: Haojian Zhuang <haojian.zhuang@gmail.com>

Sergei Ianovich (21):
  serial: rewrite pxa2xx-uart to use 8250_core
  ARM: dts: pxa2xx fix compatible strings
  ARM: dts: fix pxa27x-gpio interrupts
  ARM: dts: pxa3xx: move declaration to header
  ARM: dts: pxa27x: irq init using device tree
  ARM: dts: provide DMA config to pxamci on PXA27x
  ARM: dts: parse DMA config in pxamci
  ARM: pxa27x: device tree support ICP DAS LP-8x4x
  rtc: support DS1302 RTC on ICP DAS LP-8x4x
  mtd: support BB SRAM on ICP DAS LP-8x4x
  ARM: pxa: support ICP DAS LP-8x4x FPGA irq
  serial: support for 16550A serial ports on LP-8x4x
  misc: support for LP-8x4x custom parallel bus
  misc: support for LP-8x4x rotary switch
  misc: support for LP-8x4x DIP switch
  misc: support for writing to LP-8x4x EEPROM
  misc: support for serial slots in LP-8x4x
  misc: support for parallel slots in LP-8x4x
  misc: support for I-8041 in LP-8x4x
  misc: support for I-8042 in LP-8x4x
  misc: support for I-8024 in LP-8x4x

 .../bindings/interrupt-controller/irq-lp8x4x.txt   |  49 ++
 .../devicetree/bindings/misc/lp8x4x-bus.txt        |  34 +
 Documentation/devicetree/bindings/mmc/pxa-mmc.txt  |   5 +
 .../devicetree/bindings/rtc/rtc-ds1302.txt         |  14 +
 .../devicetree/bindings/serial/lp8x4x-serial.txt   |  35 +
 Documentation/misc-devices/lp8x4x_bus.txt          |  83 ++
 arch/arm/boot/dts/Makefile                         |   1 +
 arch/arm/boot/dts/pxa27x-lp8x4x.dts                | 224 +++++
 arch/arm/boot/dts/pxa27x.dtsi                      |  37 +
 arch/arm/boot/dts/pxa2xx.dtsi                      |   5 +-
 arch/arm/configs/am200epdkit_defconfig             |   3 +-
 arch/arm/configs/cm_x2xx_defconfig                 |   3 +-
 arch/arm/configs/cm_x300_defconfig                 |   3 +-
 arch/arm/configs/colibri_pxa270_defconfig          |   3 +-
 arch/arm/configs/colibri_pxa300_defconfig          |   3 +-
 arch/arm/configs/corgi_defconfig                   |   4 +-
 arch/arm/configs/em_x270_defconfig                 |   3 +-
 arch/arm/configs/ezx_defconfig                     |   3 +-
 arch/arm/configs/h5000_defconfig                   |   3 +-
 arch/arm/configs/imote2_defconfig                  |   3 +-
 arch/arm/configs/lp8x4x_defconfig                  | 172 ++++
 arch/arm/configs/lpd270_defconfig                  |   3 +-
 arch/arm/configs/lubbock_defconfig                 |   3 +-
 arch/arm/configs/mainstone_defconfig               |   3 +-
 arch/arm/configs/mmp2_defconfig                    |   3 +-
 arch/arm/configs/pcm027_defconfig                  |   3 +-
 arch/arm/configs/pxa168_defconfig                  |   3 +-
 arch/arm/configs/pxa255-idp_defconfig              |   3 +-
 arch/arm/configs/pxa3xx_defconfig                  |   3 +-
 arch/arm/configs/pxa910_defconfig                  |   3 +-
 arch/arm/configs/raumfeld_defconfig                |   3 +-
 arch/arm/configs/spitz_defconfig                   |   4 +-
 arch/arm/configs/trizeps4_defconfig                |   3 +-
 arch/arm/configs/viper_defconfig                   |   4 +-
 arch/arm/configs/xcep_defconfig                    |   3 +-
 arch/arm/mach-pxa/Kconfig                          |  15 +
 arch/arm/mach-pxa/Makefile                         |   1 +
 arch/arm/mach-pxa/include/mach/irqs.h              |   2 +
 arch/arm/mach-pxa/include/mach/pxa27x.h            |   1 +
 arch/arm/mach-pxa/pxa27x-dt.c                      |  64 ++
 arch/arm/mach-pxa/pxa27x.c                         |  10 +
 arch/arm/mach-pxa/pxa3xx.c                         |   2 -
 drivers/irqchip/Kconfig                            |   5 +
 drivers/irqchip/Makefile                           |   1 +
 drivers/irqchip/irq-lp8x4x.c                       | 205 +++++
 drivers/misc/Kconfig                               |  13 +
 drivers/misc/Makefile                              |   1 +
 drivers/misc/lp8x4x_bus.c                          | 665 ++++++++++++++
 drivers/mmc/host/pxamci.c                          |  59 +-
 drivers/mtd/devices/Kconfig                        |  14 +
 drivers/mtd/devices/Makefile                       |   1 +
 drivers/mtd/devices/sram_lp8x4x.c                  | 227 +++++
 drivers/rtc/Kconfig                                |   2 +-
 drivers/rtc/rtc-ds1302.c                           | 100 ++-
 drivers/tty/serial/8250/8250_lp8x4x.c              | 162 ++++
 drivers/tty/serial/8250/8250_pxa.c                 | 178 ++++
 drivers/tty/serial/8250/Kconfig                    |  21 +
 drivers/tty/serial/8250/Makefile                   |   2 +
 drivers/tty/serial/Kconfig                         |  23 -
 drivers/tty/serial/Makefile                        |   1 -
 drivers/tty/serial/pxa.c                           | 971 ---------------------
 61 files changed, 2439 insertions(+), 1041 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/interrupt-controller/irq-lp8x4x.txt
 create mode 100644 Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
 create mode 100644 Documentation/devicetree/bindings/rtc/rtc-ds1302.txt
 create mode 100644 Documentation/devicetree/bindings/serial/lp8x4x-serial.txt
 create mode 100644 Documentation/misc-devices/lp8x4x_bus.txt
 create mode 100644 arch/arm/boot/dts/pxa27x-lp8x4x.dts
 create mode 100644 arch/arm/configs/lp8x4x_defconfig
 create mode 100644 arch/arm/mach-pxa/pxa27x-dt.c
 create mode 100644 drivers/irqchip/irq-lp8x4x.c
 create mode 100644 drivers/misc/lp8x4x_bus.c
 create mode 100644 drivers/mtd/devices/sram_lp8x4x.c
 create mode 100644 drivers/tty/serial/8250/8250_lp8x4x.c
 create mode 100644 drivers/tty/serial/8250/8250_pxa.c
 delete mode 100644 drivers/tty/serial/pxa.c

-- 
1.8.4.2


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

* [PATCH v3 00/21] ARM: support for ICP DAS LP-8x4x (with dts)
@ 2013-12-17 19:37           ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-17 19:37 UTC (permalink / raw)
  To: linux-arm-kernel

Two review comments are not finally settled:

1. Use of new DMA
My  best guess is to split the patch in two, so that Daniel could easily
revert the workaround, once a solution is ready.

2. Device tree representation
I've put extbus into platform include file, since the bus is platform-
specific, not board-specific.

Frame support is now close to 95%, pluggable module support is
at around 20%. Most modules should be possible to handele by already
working get_DI/DO/AO set_DO/AO functions. I am not including support,
since I didn't actually tested the hardware. The same about RS232/485
pluggable port.

ICP DAS calls LP-8x4x 'programmable automation controller'. It is
an industrial computer based on PXA270 SoC. They ship it with a 2.6.19
kernel and proprietary kernel module and userspace library to access
its industrial IO.

This patch allows to boot the device with a modern kernel with device
tree. It adds support for:
* MMC card interface on PXA270
* USB 1.1 port on PXA270
* 2 NOR flash devices
* 2 onboard ethernet Davicom DM9000 devices
* 3 serial UART ports on PXA270
* front panel red LED
* 64bit 1-wire system ID chip
* 16 kiB EEPROM (reading)

Support for these devices will be added in separate patches, since
they are not currently supported by the kernel:
* DS1302 RTC
* 512kiB SRAM
* FPGA irq chip
* 3 built-in 16550A serial UART ports
* industrial IO parallel bus
* 10 position rotary switch
* 8 pin DIP switch
* 16 kiB EEPROM (writing)
* serial interface for digital and analog industrial IO modules on
  parallel bus (all I-87... modules)
* digital and analog industrial IO modules for parallel bus:
  ** I-8024 4 port analog output
  ** I-8041 32 port digital output
  ** I-8042 16 port digital output/16 port digital input

Not supported for now:
* VGA interface on PXA270 for lack of dts binding
* the rest of parallel bus (I-8...) modules for lack of hardware
* GPIO reset for lack of relevance (watchdog reset is working)

NOTE: USB support requires U-Boot patch series which setups GPIO.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Daniel Mack <zonque@gmail.com>
CC: Arnd Bergmann <arnd@arndb.de>
CC: Haojian Zhuang <haojian.zhuang@gmail.com>

Sergei Ianovich (21):
  serial: rewrite pxa2xx-uart to use 8250_core
  ARM: dts: pxa2xx fix compatible strings
  ARM: dts: fix pxa27x-gpio interrupts
  ARM: dts: pxa3xx: move declaration to header
  ARM: dts: pxa27x: irq init using device tree
  ARM: dts: provide DMA config to pxamci on PXA27x
  ARM: dts: parse DMA config in pxamci
  ARM: pxa27x: device tree support ICP DAS LP-8x4x
  rtc: support DS1302 RTC on ICP DAS LP-8x4x
  mtd: support BB SRAM on ICP DAS LP-8x4x
  ARM: pxa: support ICP DAS LP-8x4x FPGA irq
  serial: support for 16550A serial ports on LP-8x4x
  misc: support for LP-8x4x custom parallel bus
  misc: support for LP-8x4x rotary switch
  misc: support for LP-8x4x DIP switch
  misc: support for writing to LP-8x4x EEPROM
  misc: support for serial slots in LP-8x4x
  misc: support for parallel slots in LP-8x4x
  misc: support for I-8041 in LP-8x4x
  misc: support for I-8042 in LP-8x4x
  misc: support for I-8024 in LP-8x4x

 .../bindings/interrupt-controller/irq-lp8x4x.txt   |  49 ++
 .../devicetree/bindings/misc/lp8x4x-bus.txt        |  34 +
 Documentation/devicetree/bindings/mmc/pxa-mmc.txt  |   5 +
 .../devicetree/bindings/rtc/rtc-ds1302.txt         |  14 +
 .../devicetree/bindings/serial/lp8x4x-serial.txt   |  35 +
 Documentation/misc-devices/lp8x4x_bus.txt          |  83 ++
 arch/arm/boot/dts/Makefile                         |   1 +
 arch/arm/boot/dts/pxa27x-lp8x4x.dts                | 224 +++++
 arch/arm/boot/dts/pxa27x.dtsi                      |  37 +
 arch/arm/boot/dts/pxa2xx.dtsi                      |   5 +-
 arch/arm/configs/am200epdkit_defconfig             |   3 +-
 arch/arm/configs/cm_x2xx_defconfig                 |   3 +-
 arch/arm/configs/cm_x300_defconfig                 |   3 +-
 arch/arm/configs/colibri_pxa270_defconfig          |   3 +-
 arch/arm/configs/colibri_pxa300_defconfig          |   3 +-
 arch/arm/configs/corgi_defconfig                   |   4 +-
 arch/arm/configs/em_x270_defconfig                 |   3 +-
 arch/arm/configs/ezx_defconfig                     |   3 +-
 arch/arm/configs/h5000_defconfig                   |   3 +-
 arch/arm/configs/imote2_defconfig                  |   3 +-
 arch/arm/configs/lp8x4x_defconfig                  | 172 ++++
 arch/arm/configs/lpd270_defconfig                  |   3 +-
 arch/arm/configs/lubbock_defconfig                 |   3 +-
 arch/arm/configs/mainstone_defconfig               |   3 +-
 arch/arm/configs/mmp2_defconfig                    |   3 +-
 arch/arm/configs/pcm027_defconfig                  |   3 +-
 arch/arm/configs/pxa168_defconfig                  |   3 +-
 arch/arm/configs/pxa255-idp_defconfig              |   3 +-
 arch/arm/configs/pxa3xx_defconfig                  |   3 +-
 arch/arm/configs/pxa910_defconfig                  |   3 +-
 arch/arm/configs/raumfeld_defconfig                |   3 +-
 arch/arm/configs/spitz_defconfig                   |   4 +-
 arch/arm/configs/trizeps4_defconfig                |   3 +-
 arch/arm/configs/viper_defconfig                   |   4 +-
 arch/arm/configs/xcep_defconfig                    |   3 +-
 arch/arm/mach-pxa/Kconfig                          |  15 +
 arch/arm/mach-pxa/Makefile                         |   1 +
 arch/arm/mach-pxa/include/mach/irqs.h              |   2 +
 arch/arm/mach-pxa/include/mach/pxa27x.h            |   1 +
 arch/arm/mach-pxa/pxa27x-dt.c                      |  64 ++
 arch/arm/mach-pxa/pxa27x.c                         |  10 +
 arch/arm/mach-pxa/pxa3xx.c                         |   2 -
 drivers/irqchip/Kconfig                            |   5 +
 drivers/irqchip/Makefile                           |   1 +
 drivers/irqchip/irq-lp8x4x.c                       | 205 +++++
 drivers/misc/Kconfig                               |  13 +
 drivers/misc/Makefile                              |   1 +
 drivers/misc/lp8x4x_bus.c                          | 665 ++++++++++++++
 drivers/mmc/host/pxamci.c                          |  59 +-
 drivers/mtd/devices/Kconfig                        |  14 +
 drivers/mtd/devices/Makefile                       |   1 +
 drivers/mtd/devices/sram_lp8x4x.c                  | 227 +++++
 drivers/rtc/Kconfig                                |   2 +-
 drivers/rtc/rtc-ds1302.c                           | 100 ++-
 drivers/tty/serial/8250/8250_lp8x4x.c              | 162 ++++
 drivers/tty/serial/8250/8250_pxa.c                 | 178 ++++
 drivers/tty/serial/8250/Kconfig                    |  21 +
 drivers/tty/serial/8250/Makefile                   |   2 +
 drivers/tty/serial/Kconfig                         |  23 -
 drivers/tty/serial/Makefile                        |   1 -
 drivers/tty/serial/pxa.c                           | 971 ---------------------
 61 files changed, 2439 insertions(+), 1041 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/interrupt-controller/irq-lp8x4x.txt
 create mode 100644 Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
 create mode 100644 Documentation/devicetree/bindings/rtc/rtc-ds1302.txt
 create mode 100644 Documentation/devicetree/bindings/serial/lp8x4x-serial.txt
 create mode 100644 Documentation/misc-devices/lp8x4x_bus.txt
 create mode 100644 arch/arm/boot/dts/pxa27x-lp8x4x.dts
 create mode 100644 arch/arm/configs/lp8x4x_defconfig
 create mode 100644 arch/arm/mach-pxa/pxa27x-dt.c
 create mode 100644 drivers/irqchip/irq-lp8x4x.c
 create mode 100644 drivers/misc/lp8x4x_bus.c
 create mode 100644 drivers/mtd/devices/sram_lp8x4x.c
 create mode 100644 drivers/tty/serial/8250/8250_lp8x4x.c
 create mode 100644 drivers/tty/serial/8250/8250_pxa.c
 delete mode 100644 drivers/tty/serial/pxa.c

-- 
1.8.4.2

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

* [PATCH v3 01/21 resend] serial: rewrite pxa2xx-uart to use 8250_core
  2013-12-17 19:37           ` Sergei Ianovich
  (?)
@ 2013-12-17 19:37             ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-17 19:37 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Greg Kroah-Hartman, Russell King, Jiri Slaby,
	Grant Likely, Rob Herring, Heikki Krogerus, James Cameron,
	Zhou Zhu, Haojian Zhuang, Arnd Bergmann,
	open list:SERIAL DRIVERS, open list:OPEN FIRMWARE AND...

pxa2xx-uart was a separate uart platform driver. It was declaring
the same device names and numbers as 8250 driver. As a result,
it was impossible to use 8250 driver on PXA SoCs.

Upon closer examination pxa2xx-uart turned out to be a clone of
8250_core driver.

Workaround for Erratum #19 according to Marvel(R) PXA270M Processor
Specification Update (April 19, 2010) is dropped. 8250_core reads
from FIFO immediately after checking DR bit in LSR.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Reviewed-by: James Cameron <quozl@laptop.org>
CC: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 Resenging together with the rest of the series as the series
 breaks with this one at [PATCH 12/21]

 changes v2..v3
 * remove devm_free/put as suggested by Heikki Krogerus
 * use SET_SYSTEM_SLEEP_PM_OPS macro to set pm ops as suggested
   by Heikki Krogerus

 changes v1..v2
 * actually implement workaround for E74 in dl_write as spooted
   by James Cameron
 * added comment about E19 in commit message

 arch/arm/configs/am200epdkit_defconfig    |   3 +-
 arch/arm/configs/cm_x2xx_defconfig        |   3 +-
 arch/arm/configs/cm_x300_defconfig        |   3 +-
 arch/arm/configs/colibri_pxa270_defconfig |   3 +-
 arch/arm/configs/colibri_pxa300_defconfig |   3 +-
 arch/arm/configs/corgi_defconfig          |   4 +-
 arch/arm/configs/em_x270_defconfig        |   3 +-
 arch/arm/configs/ezx_defconfig            |   3 +-
 arch/arm/configs/h5000_defconfig          |   3 +-
 arch/arm/configs/imote2_defconfig         |   3 +-
 arch/arm/configs/lpd270_defconfig         |   3 +-
 arch/arm/configs/lubbock_defconfig        |   3 +-
 arch/arm/configs/mainstone_defconfig      |   3 +-
 arch/arm/configs/mmp2_defconfig           |   3 +-
 arch/arm/configs/pcm027_defconfig         |   3 +-
 arch/arm/configs/pxa168_defconfig         |   3 +-
 arch/arm/configs/pxa255-idp_defconfig     |   3 +-
 arch/arm/configs/pxa3xx_defconfig         |   3 +-
 arch/arm/configs/pxa910_defconfig         |   3 +-
 arch/arm/configs/raumfeld_defconfig       |   3 +-
 arch/arm/configs/spitz_defconfig          |   4 +-
 arch/arm/configs/trizeps4_defconfig       |   3 +-
 arch/arm/configs/viper_defconfig          |   4 +-
 arch/arm/configs/xcep_defconfig           |   3 +-
 drivers/tty/serial/8250/8250_pxa.c        | 178 ++++++
 drivers/tty/serial/8250/Kconfig           |   9 +
 drivers/tty/serial/8250/Makefile          |   1 +
 drivers/tty/serial/Kconfig                |  23 -
 drivers/tty/serial/Makefile               |   1 -
 drivers/tty/serial/pxa.c                  | 971 ------------------------------
 30 files changed, 236 insertions(+), 1022 deletions(-)
 create mode 100644 drivers/tty/serial/8250/8250_pxa.c
 delete mode 100644 drivers/tty/serial/pxa.c

diff --git a/arch/arm/configs/am200epdkit_defconfig b/arch/arm/configs/am200epdkit_defconfig
index f0dea52..0cde234 100644
--- a/arch/arm/configs/am200epdkit_defconfig
+++ b/arch/arm/configs/am200epdkit_defconfig
@@ -60,8 +60,9 @@ CONFIG_BLK_DEV_IDECS=m
 CONFIG_NETDEVICES=y
 CONFIG_NET_ETHERNET=y
 CONFIG_SMC91X=m
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 # CONFIG_HWMON is not set
diff --git a/arch/arm/configs/cm_x2xx_defconfig b/arch/arm/configs/cm_x2xx_defconfig
index a93ff8d..b9fbe65 100644
--- a/arch/arm/configs/cm_x2xx_defconfig
+++ b/arch/arm/configs/cm_x2xx_defconfig
@@ -96,8 +96,9 @@ CONFIG_KEYBOARD_PXA27x=m
 CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_TOUCHSCREEN_UCB1400=m
 # CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_LEGACY_PTY_COUNT=16
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/cm_x300_defconfig b/arch/arm/configs/cm_x300_defconfig
index f4b7672..53a82ae 100644
--- a/arch/arm/configs/cm_x300_defconfig
+++ b/arch/arm/configs/cm_x300_defconfig
@@ -80,8 +80,9 @@ CONFIG_TOUCHSCREEN_WM97XX=m
 # CONFIG_TOUCHSCREEN_WM9713 is not set
 # CONFIG_SERIO is not set
 # CONFIG_LEGACY_PTYS is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
 CONFIG_I2C_PXA=y
diff --git a/arch/arm/configs/colibri_pxa270_defconfig b/arch/arm/configs/colibri_pxa270_defconfig
index 2ef2c5e..1ce0409 100644
--- a/arch/arm/configs/colibri_pxa270_defconfig
+++ b/arch/arm/configs/colibri_pxa270_defconfig
@@ -103,8 +103,9 @@ CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=m
 CONFIG_SERIO_LIBPS2=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_HW_RANDOM=y
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
diff --git a/arch/arm/configs/colibri_pxa300_defconfig b/arch/arm/configs/colibri_pxa300_defconfig
index b985334..f96bda0 100644
--- a/arch/arm/configs/colibri_pxa300_defconfig
+++ b/arch/arm/configs/colibri_pxa300_defconfig
@@ -31,8 +31,9 @@ CONFIG_INPUT_EVDEV=y
 # CONFIG_INPUT_MOUSE is not set
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_GPIO_ROTARY_ENCODER=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_HW_RANDOM=y
 CONFIG_DEBUG_GPIO=y
 # CONFIG_HWMON is not set
diff --git a/arch/arm/configs/corgi_defconfig b/arch/arm/configs/corgi_defconfig
index 1fd1d1d..bb4842d 100644
--- a/arch/arm/configs/corgi_defconfig
+++ b/arch/arm/configs/corgi_defconfig
@@ -131,10 +131,10 @@ CONFIG_TOUCHSCREEN_ADS7846=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=m
 # CONFIG_SERIO is not set
-CONFIG_SERIAL_8250=m
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_CS=m
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 CONFIG_I2C=y
 CONFIG_I2C_PXA=y
diff --git a/arch/arm/configs/em_x270_defconfig b/arch/arm/configs/em_x270_defconfig
index 60a21e0..ec0ec54 100644
--- a/arch/arm/configs/em_x270_defconfig
+++ b/arch/arm/configs/em_x270_defconfig
@@ -90,8 +90,9 @@ CONFIG_TOUCHSCREEN_WM97XX=m
 # CONFIG_TOUCHSCREEN_WM9705 is not set
 # CONFIG_TOUCHSCREEN_WM9713 is not set
 # CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_LEGACY_PTY_COUNT=16
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/ezx_defconfig b/arch/arm/configs/ezx_defconfig
index d95763d..631e2ec 100644
--- a/arch/arm/configs/ezx_defconfig
+++ b/arch/arm/configs/ezx_defconfig
@@ -215,8 +215,9 @@ CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=y
 CONFIG_INPUT_PCAP=y
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_LEGACY_PTY_COUNT=8
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/h5000_defconfig b/arch/arm/configs/h5000_defconfig
index 37903e3..655b735 100644
--- a/arch/arm/configs/h5000_defconfig
+++ b/arch/arm/configs/h5000_defconfig
@@ -47,8 +47,9 @@ CONFIG_MTD_PHYSMAP=y
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_LEGACY_PTY_COUNT=32
 # CONFIG_HW_RANDOM is not set
 # CONFIG_HWMON is not set
diff --git a/arch/arm/configs/imote2_defconfig b/arch/arm/configs/imote2_defconfig
index fd996bb..49d45e9 100644
--- a/arch/arm/configs/imote2_defconfig
+++ b/arch/arm/configs/imote2_defconfig
@@ -193,8 +193,9 @@ CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=y
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_LEGACY_PTY_COUNT=8
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/lpd270_defconfig b/arch/arm/configs/lpd270_defconfig
index 1c8c9ee..c3927b6 100644
--- a/arch/arm/configs/lpd270_defconfig
+++ b/arch/arm/configs/lpd270_defconfig
@@ -38,8 +38,9 @@ CONFIG_SMC91X=y
 CONFIG_INPUT_EVDEV=y
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_HW_RANDOM is not set
 CONFIG_FB=y
 CONFIG_FB_PXA=y
diff --git a/arch/arm/configs/lubbock_defconfig b/arch/arm/configs/lubbock_defconfig
index c4ba274..c8b0436 100644
--- a/arch/arm/configs/lubbock_defconfig
+++ b/arch/arm/configs/lubbock_defconfig
@@ -37,8 +37,9 @@ CONFIG_PCMCIA_PCNET=y
 CONFIG_INPUT_EVDEV=y
 # CONFIG_SERIO_SERPORT is not set
 CONFIG_SERIO_SA1111=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_USB_GADGET=y
 CONFIG_USB_G_SERIAL=m
diff --git a/arch/arm/configs/mainstone_defconfig b/arch/arm/configs/mainstone_defconfig
index 04efa1b..768892c 100644
--- a/arch/arm/configs/mainstone_defconfig
+++ b/arch/arm/configs/mainstone_defconfig
@@ -34,8 +34,9 @@ CONFIG_SMC91X=y
 CONFIG_INPUT_EVDEV=y
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_FB=y
 CONFIG_FB_PXA=y
 # CONFIG_VGA_CONSOLE is not set
diff --git a/arch/arm/configs/mmp2_defconfig b/arch/arm/configs/mmp2_defconfig
index f1cb95e..1ced9df 100644
--- a/arch/arm/configs/mmp2_defconfig
+++ b/arch/arm/configs/mmp2_defconfig
@@ -44,8 +44,9 @@ CONFIG_SMC91X=y
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/pcm027_defconfig b/arch/arm/configs/pcm027_defconfig
index 2f136c3..1280128 100644
--- a/arch/arm/configs/pcm027_defconfig
+++ b/arch/arm/configs/pcm027_defconfig
@@ -60,8 +60,9 @@ CONFIG_SMC91X=y
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/pxa168_defconfig b/arch/arm/configs/pxa168_defconfig
index 74d7e01..1668dac 100644
--- a/arch/arm/configs/pxa168_defconfig
+++ b/arch/arm/configs/pxa168_defconfig
@@ -40,8 +40,9 @@ CONFIG_SMC91X=y
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 # CONFIG_HWMON is not set
diff --git a/arch/arm/configs/pxa255-idp_defconfig b/arch/arm/configs/pxa255-idp_defconfig
index 917a070..399a706 100644
--- a/arch/arm/configs/pxa255-idp_defconfig
+++ b/arch/arm/configs/pxa255-idp_defconfig
@@ -35,8 +35,9 @@ CONFIG_SMC91X=y
 CONFIG_INPUT_EVDEV=y
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_FB=y
 CONFIG_FB_PXA=y
 # CONFIG_VGA_CONSOLE is not set
diff --git a/arch/arm/configs/pxa3xx_defconfig b/arch/arm/configs/pxa3xx_defconfig
index 60e3138..7c3e052 100644
--- a/arch/arm/configs/pxa3xx_defconfig
+++ b/arch/arm/configs/pxa3xx_defconfig
@@ -56,8 +56,9 @@ CONFIG_KEYBOARD_PXA27x=y
 CONFIG_KEYBOARD_PXA930_ROTARY=y
 CONFIG_MOUSE_PXA930_TRKBALL=y
 CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/pxa910_defconfig b/arch/arm/configs/pxa910_defconfig
index 3bb7771..cdacfcb 100644
--- a/arch/arm/configs/pxa910_defconfig
+++ b/arch/arm/configs/pxa910_defconfig
@@ -40,8 +40,9 @@ CONFIG_SMC91X=y
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_SPI=y
 CONFIG_FB=y
 CONFIG_MMP_DISP=y
diff --git a/arch/arm/configs/raumfeld_defconfig b/arch/arm/configs/raumfeld_defconfig
index f7caa90..f1e16f2 100644
--- a/arch/arm/configs/raumfeld_defconfig
+++ b/arch/arm/configs/raumfeld_defconfig
@@ -67,8 +67,9 @@ CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_TOUCHSCREEN_EETI=m
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_GPIO_ROTARY_ENCODER=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_HW_RANDOM=y
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
diff --git a/arch/arm/configs/spitz_defconfig b/arch/arm/configs/spitz_defconfig
index 2e0419d..b6efcf5 100644
--- a/arch/arm/configs/spitz_defconfig
+++ b/arch/arm/configs/spitz_defconfig
@@ -128,10 +128,10 @@ CONFIG_TOUCHSCREEN_ADS7846=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=m
 # CONFIG_SERIO is not set
-CONFIG_SERIAL_8250=m
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_CS=m
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 CONFIG_SPI=y
 CONFIG_SPI_PXA2XX=y
diff --git a/arch/arm/configs/trizeps4_defconfig b/arch/arm/configs/trizeps4_defconfig
index 3162173..453c79c 100644
--- a/arch/arm/configs/trizeps4_defconfig
+++ b/arch/arm/configs/trizeps4_defconfig
@@ -132,8 +132,9 @@ CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=m
 CONFIG_SERIO_LIBPS2=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_HW_RANDOM=y
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
diff --git a/arch/arm/configs/viper_defconfig b/arch/arm/configs/viper_defconfig
index d36e0d3..4efac06 100644
--- a/arch/arm/configs/viper_defconfig
+++ b/arch/arm/configs/viper_defconfig
@@ -101,11 +101,11 @@ CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=m
 # CONFIG_CONSOLE_TRANSLATIONS is not set
 # CONFIG_VT_CONSOLE is not set
-CONFIG_SERIAL_8250=m
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_NR_UARTS=5
 CONFIG_SERIAL_8250_RUNTIME_UARTS=5
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
diff --git a/arch/arm/configs/xcep_defconfig b/arch/arm/configs/xcep_defconfig
index 721832f..b67aeaf 100644
--- a/arch/arm/configs/xcep_defconfig
+++ b/arch/arm/configs/xcep_defconfig
@@ -60,8 +60,9 @@ CONFIG_NET_ETHERNET=y
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
 # CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=m
diff --git a/drivers/tty/serial/8250/8250_pxa.c b/drivers/tty/serial/8250/8250_pxa.c
new file mode 100644
index 0000000..0da0d40
--- /dev/null
+++ b/drivers/tty/serial/8250/8250_pxa.c
@@ -0,0 +1,178 @@
+/*
+ *  drivers/tty/serial/8250/8250_pxa.c -- driver for PXA on-board UARTS
+ *  Copyright:	(C) 2013 Sergei Ianovich <ynvich@gmail.com>
+ *
+ *  replaces drivers/serial/pxa.c by Nicolas Pitre
+ *  Created:	Feb 20, 2003
+ *  Copyright:	(C) 2003 Monta Vista Software, Inc.
+ *
+ *  Based on drivers/serial/8250.c by Russell King.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/serial_8250.h>
+#include <linux/serial_core.h>
+#include <linux/serial_reg.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
+#include <linux/pm_runtime.h>
+
+#include "8250.h"
+
+struct pxa8250_data {
+	int			line;
+	struct clk		*clk;
+};
+
+#ifdef CONFIG_PM
+static int serial_pxa_suspend(struct device *dev)
+{
+	struct pxa8250_data *data = dev_get_drvdata(dev);
+
+	serial8250_suspend_port(data->line);
+
+	return 0;
+}
+
+static int serial_pxa_resume(struct device *dev)
+{
+	struct pxa8250_data *data = dev_get_drvdata(dev);
+
+	serial8250_resume_port(data->line);
+
+	return 0;
+}
+#endif
+
+static const struct dev_pm_ops serial_pxa_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(serial_pxa_suspend, serial_pxa_resume)
+};
+
+static struct of_device_id serial_pxa_dt_ids[] = {
+	{ .compatible = "mrvl,pxa-uart", },
+	{ .compatible = "mrvl,mmp-uart", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, serial_pxa_dt_ids);
+
+/* Uart divisor latch write */
+static void serial_pxa_dl_write(struct uart_8250_port *up, int value)
+{
+	unsigned int dll;
+
+	serial_out(up, UART_DLL, value & 0xff);
+	/*
+	 * work around Erratum #74 according to Marvel(R) PXA270M Processor
+	 * Specification Update (April 19, 2010)
+	 */
+	dll = serial_in(up, UART_DLL);
+	WARN_ON(dll != (value & 0xff));
+
+	serial_out(up, UART_DLM, value >> 8 & 0xff);
+}
+
+
+static void serial_pxa_pm(struct uart_port *port, unsigned int state,
+	      unsigned int oldstate)
+{
+	struct pxa8250_data *data = port->private_data;
+
+	if (!state)
+		clk_prepare_enable(data->clk);
+	else
+		clk_disable_unprepare(data->clk);
+}
+
+static int serial_pxa_probe(struct platform_device *pdev)
+{
+	struct uart_8250_port uart = {};
+	struct pxa8250_data *data;
+	struct resource *mmres, *irqres;
+	int ret;
+
+	mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	irqres = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!mmres || !irqres)
+		return -ENODEV;
+
+	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(data->clk))
+		return PTR_ERR(data->clk);
+
+	ret = clk_prepare(data->clk);
+	if (ret)
+		return ret;
+
+	uart.port.type = PORT_XSCALE;
+	uart.port.iotype = UPIO_MEM32;
+	uart.port.mapbase = mmres->start;
+	uart.port.regshift = 2;
+	uart.port.irq = irqres->start;
+	uart.port.fifosize = 64;
+	uart.port.flags = UPF_IOREMAP | UPF_SKIP_TEST;
+	uart.port.dev = &pdev->dev;
+	uart.port.uartclk = clk_get_rate(data->clk);
+	uart.port.pm = serial_pxa_pm;
+	uart.port.private_data = data;
+	uart.dl_write = serial_pxa_dl_write;
+
+	ret = serial8250_register_8250_port(&uart);
+	if (ret < 0)
+		goto err_clk;
+
+	data->line = ret;
+
+	platform_set_drvdata(pdev, data);
+
+	return 0;
+
+ err_clk:
+	clk_unprepare(data->clk);
+	return ret;
+}
+
+static int serial_pxa_remove(struct platform_device *pdev)
+{
+	struct pxa8250_data *data = platform_get_drvdata(pdev);
+
+	serial8250_unregister_port(data->line);
+
+	clk_unprepare(data->clk);
+
+	return 0;
+}
+
+static struct platform_driver serial_pxa_driver = {
+	.probe          = serial_pxa_probe,
+	.remove         = serial_pxa_remove,
+
+	.driver		= {
+		.name	= "pxa2xx-uart",
+		.owner	= THIS_MODULE,
+		.pm	= &serial_pxa_pm_ops,
+		.of_match_table = serial_pxa_dt_ids,
+	},
+};
+
+module_platform_driver(serial_pxa_driver);
+
+MODULE_AUTHOR("Sergei Ianovich");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:pxa2xx-uart");
diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
index 2332991..81bd7c9 100644
--- a/drivers/tty/serial/8250/Kconfig
+++ b/drivers/tty/serial/8250/Kconfig
@@ -302,3 +302,12 @@ config SERIAL_8250_RT288X
 	  If you have a Ralink RT288x/RT305x SoC based board and want to use the
 	  serial port, say Y to this option. The driver can handle up to 2 serial
 	  ports. If unsure, say N.
+
+config SERIAL_PXA
+	tristate "PXA serial port support"
+	depends on SERIAL_8250 && (ARCH_PXA || ARCH_MMP)
+	help
+	  If you have a machine based on an Intel XScale PXA2xx CPU you
+	  can enable its onboard serial ports by enabling this option.
+
+	  If you choose M here, the module name will be 8250_pxa.
diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile
index 36d68d0..b7d1b61 100644
--- a/drivers/tty/serial/8250/Makefile
+++ b/drivers/tty/serial/8250/Makefile
@@ -20,3 +20,4 @@ obj-$(CONFIG_SERIAL_8250_HUB6)		+= 8250_hub6.o
 obj-$(CONFIG_SERIAL_8250_FSL)		+= 8250_fsl.o
 obj-$(CONFIG_SERIAL_8250_DW)		+= 8250_dw.o
 obj-$(CONFIG_SERIAL_8250_EM)		+= 8250_em.o
+obj-$(CONFIG_SERIAL_PXA)		+= 8250_pxa.o
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index a3817ab..2ad7184b 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -396,29 +396,6 @@ config SERIAL_MPSC_CONSOLE
 	help
 	  Say Y here if you want to support a serial console on a Marvell MPSC.
 
-config SERIAL_PXA
-	bool "PXA serial port support"
-	depends on ARCH_PXA || ARCH_MMP
-	select SERIAL_CORE
-	help
-	  If you have a machine based on an Intel XScale PXA2xx CPU you
-	  can enable its onboard serial ports by enabling this option.
-
-config SERIAL_PXA_CONSOLE
-	bool "Console on PXA serial port"
-	depends on SERIAL_PXA
-	select SERIAL_CORE_CONSOLE
-	help
-	  If you have enabled the serial port on the Intel XScale PXA
-	  CPU you can make it the console by answering Y to this option.
-
-	  Even if you say Y here, the currently visible virtual console
-	  (/dev/tty0) will still be used as the system console by default, but
-	  you can alter that using a kernel command line option such as
-	  "console=ttySA0". (Try "man bootparam" or see the documentation of
-	  your boot loader (lilo or loadlin) about how to pass options to the
-	  kernel at boot time.)
-
 config SERIAL_SA1100
 	bool "SA1100 serial port support"
 	depends on ARCH_SA1100
diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile
index 3068c77..4ac337b 100644
--- a/drivers/tty/serial/Makefile
+++ b/drivers/tty/serial/Makefile
@@ -20,7 +20,6 @@ obj-$(CONFIG_SERIAL_8250) += 8250/
 obj-$(CONFIG_SERIAL_AMBA_PL010) += amba-pl010.o
 obj-$(CONFIG_SERIAL_AMBA_PL011) += amba-pl011.o
 obj-$(CONFIG_SERIAL_CLPS711X) += clps711x.o
-obj-$(CONFIG_SERIAL_PXA) += pxa.o
 obj-$(CONFIG_SERIAL_PNX8XXX) += pnx8xxx_uart.o
 obj-$(CONFIG_SERIAL_SA1100) += sa1100.o
 obj-$(CONFIG_SERIAL_BCM63XX) += bcm63xx_uart.o
diff --git a/drivers/tty/serial/pxa.c b/drivers/tty/serial/pxa.c
deleted file mode 100644
index f9f20f3..0000000
--- a/drivers/tty/serial/pxa.c
+++ /dev/null
@@ -1,971 +0,0 @@
-/*
- *  Based on drivers/serial/8250.c by Russell King.
- *
- *  Author:	Nicolas Pitre
- *  Created:	Feb 20, 2003
- *  Copyright:	(C) 2003 Monta Vista Software, Inc.
- *
- * 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.
- *
- * Note 1: This driver is made separate from the already too overloaded
- * 8250.c because it needs some kirks of its own and that'll make it
- * easier to add DMA support.
- *
- * Note 2: I'm too sick of device allocation policies for serial ports.
- * If someone else wants to request an "official" allocation of major/minor
- * for this driver please be my guest.  And don't forget that new hardware
- * to come from Intel might have more than 3 or 4 of those UARTs.  Let's
- * hope for a better port registration and dynamic device allocation scheme
- * with the serial core maintainer satisfaction to appear soon.
- */
-
-
-#if defined(CONFIG_SERIAL_PXA_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-#define SUPPORT_SYSRQ
-#endif
-
-#include <linux/module.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-#include <linux/console.h>
-#include <linux/sysrq.h>
-#include <linux/serial_reg.h>
-#include <linux/circ_buf.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/of.h>
-#include <linux/platform_device.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/serial_core.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-
-#define PXA_NAME_LEN		8
-
-struct uart_pxa_port {
-	struct uart_port        port;
-	unsigned char           ier;
-	unsigned char           lcr;
-	unsigned char           mcr;
-	unsigned int            lsr_break_flag;
-	struct clk		*clk;
-	char			name[PXA_NAME_LEN];
-};
-
-static inline unsigned int serial_in(struct uart_pxa_port *up, int offset)
-{
-	offset <<= 2;
-	return readl(up->port.membase + offset);
-}
-
-static inline void serial_out(struct uart_pxa_port *up, int offset, int value)
-{
-	offset <<= 2;
-	writel(value, up->port.membase + offset);
-}
-
-static void serial_pxa_enable_ms(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	up->ier |= UART_IER_MSI;
-	serial_out(up, UART_IER, up->ier);
-}
-
-static void serial_pxa_stop_tx(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	if (up->ier & UART_IER_THRI) {
-		up->ier &= ~UART_IER_THRI;
-		serial_out(up, UART_IER, up->ier);
-	}
-}
-
-static void serial_pxa_stop_rx(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	up->ier &= ~UART_IER_RLSI;
-	up->port.read_status_mask &= ~UART_LSR_DR;
-	serial_out(up, UART_IER, up->ier);
-}
-
-static inline void receive_chars(struct uart_pxa_port *up, int *status)
-{
-	unsigned int ch, flag;
-	int max_count = 256;
-
-	do {
-		/* work around Errata #20 according to
-		 * Intel(R) PXA27x Processor Family
-		 * Specification Update (May 2005)
-		 *
-		 * Step 2
-		 * Disable the Reciever Time Out Interrupt via IER[RTOEI]
-		 */
-		up->ier &= ~UART_IER_RTOIE;
-		serial_out(up, UART_IER, up->ier);
-
-		ch = serial_in(up, UART_RX);
-		flag = TTY_NORMAL;
-		up->port.icount.rx++;
-
-		if (unlikely(*status & (UART_LSR_BI | UART_LSR_PE |
-				       UART_LSR_FE | UART_LSR_OE))) {
-			/*
-			 * For statistics only
-			 */
-			if (*status & UART_LSR_BI) {
-				*status &= ~(UART_LSR_FE | UART_LSR_PE);
-				up->port.icount.brk++;
-				/*
-				 * We do the SysRQ and SAK checking
-				 * here because otherwise the break
-				 * may get masked by ignore_status_mask
-				 * or read_status_mask.
-				 */
-				if (uart_handle_break(&up->port))
-					goto ignore_char;
-			} else if (*status & UART_LSR_PE)
-				up->port.icount.parity++;
-			else if (*status & UART_LSR_FE)
-				up->port.icount.frame++;
-			if (*status & UART_LSR_OE)
-				up->port.icount.overrun++;
-
-			/*
-			 * Mask off conditions which should be ignored.
-			 */
-			*status &= up->port.read_status_mask;
-
-#ifdef CONFIG_SERIAL_PXA_CONSOLE
-			if (up->port.line == up->port.cons->index) {
-				/* Recover the break flag from console xmit */
-				*status |= up->lsr_break_flag;
-				up->lsr_break_flag = 0;
-			}
-#endif
-			if (*status & UART_LSR_BI) {
-				flag = TTY_BREAK;
-			} else if (*status & UART_LSR_PE)
-				flag = TTY_PARITY;
-			else if (*status & UART_LSR_FE)
-				flag = TTY_FRAME;
-		}
-
-		if (uart_handle_sysrq_char(&up->port, ch))
-			goto ignore_char;
-
-		uart_insert_char(&up->port, *status, UART_LSR_OE, ch, flag);
-
-	ignore_char:
-		*status = serial_in(up, UART_LSR);
-	} while ((*status & UART_LSR_DR) && (max_count-- > 0));
-	tty_flip_buffer_push(&up->port.state->port);
-
-	/* work around Errata #20 according to
-	 * Intel(R) PXA27x Processor Family
-	 * Specification Update (May 2005)
-	 *
-	 * Step 6:
-	 * No more data in FIFO: Re-enable RTO interrupt via IER[RTOIE]
-	 */
-	up->ier |= UART_IER_RTOIE;
-	serial_out(up, UART_IER, up->ier);
-}
-
-static void transmit_chars(struct uart_pxa_port *up)
-{
-	struct circ_buf *xmit = &up->port.state->xmit;
-	int count;
-
-	if (up->port.x_char) {
-		serial_out(up, UART_TX, up->port.x_char);
-		up->port.icount.tx++;
-		up->port.x_char = 0;
-		return;
-	}
-	if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) {
-		serial_pxa_stop_tx(&up->port);
-		return;
-	}
-
-	count = up->port.fifosize / 2;
-	do {
-		serial_out(up, UART_TX, xmit->buf[xmit->tail]);
-		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
-		up->port.icount.tx++;
-		if (uart_circ_empty(xmit))
-			break;
-	} while (--count > 0);
-
-	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
-		uart_write_wakeup(&up->port);
-
-
-	if (uart_circ_empty(xmit))
-		serial_pxa_stop_tx(&up->port);
-}
-
-static void serial_pxa_start_tx(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	if (!(up->ier & UART_IER_THRI)) {
-		up->ier |= UART_IER_THRI;
-		serial_out(up, UART_IER, up->ier);
-	}
-}
-
-static inline void check_modem_status(struct uart_pxa_port *up)
-{
-	int status;
-
-	status = serial_in(up, UART_MSR);
-
-	if ((status & UART_MSR_ANY_DELTA) == 0)
-		return;
-
-	if (status & UART_MSR_TERI)
-		up->port.icount.rng++;
-	if (status & UART_MSR_DDSR)
-		up->port.icount.dsr++;
-	if (status & UART_MSR_DDCD)
-		uart_handle_dcd_change(&up->port, status & UART_MSR_DCD);
-	if (status & UART_MSR_DCTS)
-		uart_handle_cts_change(&up->port, status & UART_MSR_CTS);
-
-	wake_up_interruptible(&up->port.state->port.delta_msr_wait);
-}
-
-/*
- * This handles the interrupt from one port.
- */
-static inline irqreturn_t serial_pxa_irq(int irq, void *dev_id)
-{
-	struct uart_pxa_port *up = dev_id;
-	unsigned int iir, lsr;
-
-	iir = serial_in(up, UART_IIR);
-	if (iir & UART_IIR_NO_INT)
-		return IRQ_NONE;
-	lsr = serial_in(up, UART_LSR);
-	if (lsr & UART_LSR_DR)
-		receive_chars(up, &lsr);
-	check_modem_status(up);
-	if (lsr & UART_LSR_THRE)
-		transmit_chars(up);
-	return IRQ_HANDLED;
-}
-
-static unsigned int serial_pxa_tx_empty(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned long flags;
-	unsigned int ret;
-
-	spin_lock_irqsave(&up->port.lock, flags);
-	ret = serial_in(up, UART_LSR) & UART_LSR_TEMT ? TIOCSER_TEMT : 0;
-	spin_unlock_irqrestore(&up->port.lock, flags);
-
-	return ret;
-}
-
-static unsigned int serial_pxa_get_mctrl(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned char status;
-	unsigned int ret;
-
-	status = serial_in(up, UART_MSR);
-
-	ret = 0;
-	if (status & UART_MSR_DCD)
-		ret |= TIOCM_CAR;
-	if (status & UART_MSR_RI)
-		ret |= TIOCM_RNG;
-	if (status & UART_MSR_DSR)
-		ret |= TIOCM_DSR;
-	if (status & UART_MSR_CTS)
-		ret |= TIOCM_CTS;
-	return ret;
-}
-
-static void serial_pxa_set_mctrl(struct uart_port *port, unsigned int mctrl)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned char mcr = 0;
-
-	if (mctrl & TIOCM_RTS)
-		mcr |= UART_MCR_RTS;
-	if (mctrl & TIOCM_DTR)
-		mcr |= UART_MCR_DTR;
-	if (mctrl & TIOCM_OUT1)
-		mcr |= UART_MCR_OUT1;
-	if (mctrl & TIOCM_OUT2)
-		mcr |= UART_MCR_OUT2;
-	if (mctrl & TIOCM_LOOP)
-		mcr |= UART_MCR_LOOP;
-
-	mcr |= up->mcr;
-
-	serial_out(up, UART_MCR, mcr);
-}
-
-static void serial_pxa_break_ctl(struct uart_port *port, int break_state)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned long flags;
-
-	spin_lock_irqsave(&up->port.lock, flags);
-	if (break_state == -1)
-		up->lcr |= UART_LCR_SBC;
-	else
-		up->lcr &= ~UART_LCR_SBC;
-	serial_out(up, UART_LCR, up->lcr);
-	spin_unlock_irqrestore(&up->port.lock, flags);
-}
-
-static int serial_pxa_startup(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned long flags;
-	int retval;
-
-	if (port->line == 3) /* HWUART */
-		up->mcr |= UART_MCR_AFE;
-	else
-		up->mcr = 0;
-
-	up->port.uartclk = clk_get_rate(up->clk);
-
-	/*
-	 * Allocate the IRQ
-	 */
-	retval = request_irq(up->port.irq, serial_pxa_irq, 0, up->name, up);
-	if (retval)
-		return retval;
-
-	/*
-	 * Clear the FIFO buffers and disable them.
-	 * (they will be reenabled in set_termios())
-	 */
-	serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO);
-	serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO |
-			UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
-	serial_out(up, UART_FCR, 0);
-
-	/*
-	 * Clear the interrupt registers.
-	 */
-	(void) serial_in(up, UART_LSR);
-	(void) serial_in(up, UART_RX);
-	(void) serial_in(up, UART_IIR);
-	(void) serial_in(up, UART_MSR);
-
-	/*
-	 * Now, initialize the UART
-	 */
-	serial_out(up, UART_LCR, UART_LCR_WLEN8);
-
-	spin_lock_irqsave(&up->port.lock, flags);
-	up->port.mctrl |= TIOCM_OUT2;
-	serial_pxa_set_mctrl(&up->port, up->port.mctrl);
-	spin_unlock_irqrestore(&up->port.lock, flags);
-
-	/*
-	 * Finally, enable interrupts.  Note: Modem status interrupts
-	 * are set via set_termios(), which will be occurring imminently
-	 * anyway, so we don't enable them here.
-	 */
-	up->ier = UART_IER_RLSI | UART_IER_RDI | UART_IER_RTOIE | UART_IER_UUE;
-	serial_out(up, UART_IER, up->ier);
-
-	/*
-	 * And clear the interrupt registers again for luck.
-	 */
-	(void) serial_in(up, UART_LSR);
-	(void) serial_in(up, UART_RX);
-	(void) serial_in(up, UART_IIR);
-	(void) serial_in(up, UART_MSR);
-
-	return 0;
-}
-
-static void serial_pxa_shutdown(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned long flags;
-
-	free_irq(up->port.irq, up);
-
-	/*
-	 * Disable interrupts from this port
-	 */
-	up->ier = 0;
-	serial_out(up, UART_IER, 0);
-
-	spin_lock_irqsave(&up->port.lock, flags);
-	up->port.mctrl &= ~TIOCM_OUT2;
-	serial_pxa_set_mctrl(&up->port, up->port.mctrl);
-	spin_unlock_irqrestore(&up->port.lock, flags);
-
-	/*
-	 * Disable break condition and FIFOs
-	 */
-	serial_out(up, UART_LCR, serial_in(up, UART_LCR) & ~UART_LCR_SBC);
-	serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO |
-				  UART_FCR_CLEAR_RCVR |
-				  UART_FCR_CLEAR_XMIT);
-	serial_out(up, UART_FCR, 0);
-}
-
-static void
-serial_pxa_set_termios(struct uart_port *port, struct ktermios *termios,
-		       struct ktermios *old)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned char cval, fcr = 0;
-	unsigned long flags;
-	unsigned int baud, quot;
-	unsigned int dll;
-
-	switch (termios->c_cflag & CSIZE) {
-	case CS5:
-		cval = UART_LCR_WLEN5;
-		break;
-	case CS6:
-		cval = UART_LCR_WLEN6;
-		break;
-	case CS7:
-		cval = UART_LCR_WLEN7;
-		break;
-	default:
-	case CS8:
-		cval = UART_LCR_WLEN8;
-		break;
-	}
-
-	if (termios->c_cflag & CSTOPB)
-		cval |= UART_LCR_STOP;
-	if (termios->c_cflag & PARENB)
-		cval |= UART_LCR_PARITY;
-	if (!(termios->c_cflag & PARODD))
-		cval |= UART_LCR_EPAR;
-
-	/*
-	 * Ask the core to calculate the divisor for us.
-	 */
-	baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
-	quot = uart_get_divisor(port, baud);
-
-	if ((up->port.uartclk / quot) < (2400 * 16))
-		fcr = UART_FCR_ENABLE_FIFO | UART_FCR_PXAR1;
-	else if ((up->port.uartclk / quot) < (230400 * 16))
-		fcr = UART_FCR_ENABLE_FIFO | UART_FCR_PXAR8;
-	else
-		fcr = UART_FCR_ENABLE_FIFO | UART_FCR_PXAR32;
-
-	/*
-	 * Ok, we're now changing the port state.  Do it with
-	 * interrupts disabled.
-	 */
-	spin_lock_irqsave(&up->port.lock, flags);
-
-	/*
-	 * Ensure the port will be enabled.
-	 * This is required especially for serial console.
-	 */
-	up->ier |= UART_IER_UUE;
-
-	/*
-	 * Update the per-port timeout.
-	 */
-	uart_update_timeout(port, termios->c_cflag, baud);
-
-	up->port.read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;
-	if (termios->c_iflag & INPCK)
-		up->port.read_status_mask |= UART_LSR_FE | UART_LSR_PE;
-	if (termios->c_iflag & (BRKINT | PARMRK))
-		up->port.read_status_mask |= UART_LSR_BI;
-
-	/*
-	 * Characters to ignore
-	 */
-	up->port.ignore_status_mask = 0;
-	if (termios->c_iflag & IGNPAR)
-		up->port.ignore_status_mask |= UART_LSR_PE | UART_LSR_FE;
-	if (termios->c_iflag & IGNBRK) {
-		up->port.ignore_status_mask |= UART_LSR_BI;
-		/*
-		 * If we're ignoring parity and break indicators,
-		 * ignore overruns too (for real raw support).
-		 */
-		if (termios->c_iflag & IGNPAR)
-			up->port.ignore_status_mask |= UART_LSR_OE;
-	}
-
-	/*
-	 * ignore all characters if CREAD is not set
-	 */
-	if ((termios->c_cflag & CREAD) == 0)
-		up->port.ignore_status_mask |= UART_LSR_DR;
-
-	/*
-	 * CTS flow control flag and modem status interrupts
-	 */
-	up->ier &= ~UART_IER_MSI;
-	if (UART_ENABLE_MS(&up->port, termios->c_cflag))
-		up->ier |= UART_IER_MSI;
-
-	serial_out(up, UART_IER, up->ier);
-
-	if (termios->c_cflag & CRTSCTS)
-		up->mcr |= UART_MCR_AFE;
-	else
-		up->mcr &= ~UART_MCR_AFE;
-
-	serial_out(up, UART_LCR, cval | UART_LCR_DLAB);	/* set DLAB */
-	serial_out(up, UART_DLL, quot & 0xff);		/* LS of divisor */
-
-	/*
-	 * work around Errata #75 according to Intel(R) PXA27x Processor Family
-	 * Specification Update (Nov 2005)
-	 */
-	dll = serial_in(up, UART_DLL);
-	WARN_ON(dll != (quot & 0xff));
-
-	serial_out(up, UART_DLM, quot >> 8);		/* MS of divisor */
-	serial_out(up, UART_LCR, cval);			/* reset DLAB */
-	up->lcr = cval;					/* Save LCR */
-	serial_pxa_set_mctrl(&up->port, up->port.mctrl);
-	serial_out(up, UART_FCR, fcr);
-	spin_unlock_irqrestore(&up->port.lock, flags);
-}
-
-static void
-serial_pxa_pm(struct uart_port *port, unsigned int state,
-	      unsigned int oldstate)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	if (!state)
-		clk_prepare_enable(up->clk);
-	else
-		clk_disable_unprepare(up->clk);
-}
-
-static void serial_pxa_release_port(struct uart_port *port)
-{
-}
-
-static int serial_pxa_request_port(struct uart_port *port)
-{
-	return 0;
-}
-
-static void serial_pxa_config_port(struct uart_port *port, int flags)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	up->port.type = PORT_PXA;
-}
-
-static int
-serial_pxa_verify_port(struct uart_port *port, struct serial_struct *ser)
-{
-	/* we don't want the core code to modify any port params */
-	return -EINVAL;
-}
-
-static const char *
-serial_pxa_type(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	return up->name;
-}
-
-static struct uart_pxa_port *serial_pxa_ports[4];
-static struct uart_driver serial_pxa_reg;
-
-#ifdef CONFIG_SERIAL_PXA_CONSOLE
-
-#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
-
-/*
- *	Wait for transmitter & holding register to empty
- */
-static inline void wait_for_xmitr(struct uart_pxa_port *up)
-{
-	unsigned int status, tmout = 10000;
-
-	/* Wait up to 10ms for the character(s) to be sent. */
-	do {
-		status = serial_in(up, UART_LSR);
-
-		if (status & UART_LSR_BI)
-			up->lsr_break_flag = UART_LSR_BI;
-
-		if (--tmout == 0)
-			break;
-		udelay(1);
-	} while ((status & BOTH_EMPTY) != BOTH_EMPTY);
-
-	/* Wait up to 1s for flow control if necessary */
-	if (up->port.flags & UPF_CONS_FLOW) {
-		tmout = 1000000;
-		while (--tmout &&
-		       ((serial_in(up, UART_MSR) & UART_MSR_CTS) == 0))
-			udelay(1);
-	}
-}
-
-static void serial_pxa_console_putchar(struct uart_port *port, int ch)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	wait_for_xmitr(up);
-	serial_out(up, UART_TX, ch);
-}
-
-/*
- * Print a string to the serial port trying not to disturb
- * any possible real use of the port...
- *
- *	The console_lock must be held when we get here.
- */
-static void
-serial_pxa_console_write(struct console *co, const char *s, unsigned int count)
-{
-	struct uart_pxa_port *up = serial_pxa_ports[co->index];
-	unsigned int ier;
-	unsigned long flags;
-	int locked = 1;
-
-	clk_enable(up->clk);
-	local_irq_save(flags);
-	if (up->port.sysrq)
-		locked = 0;
-	else if (oops_in_progress)
-		locked = spin_trylock(&up->port.lock);
-	else
-		spin_lock(&up->port.lock);
-
-	/*
-	 *	First save the IER then disable the interrupts
-	 */
-	ier = serial_in(up, UART_IER);
-	serial_out(up, UART_IER, UART_IER_UUE);
-
-	uart_console_write(&up->port, s, count, serial_pxa_console_putchar);
-
-	/*
-	 *	Finally, wait for transmitter to become empty
-	 *	and restore the IER
-	 */
-	wait_for_xmitr(up);
-	serial_out(up, UART_IER, ier);
-
-	if (locked)
-		spin_unlock(&up->port.lock);
-	local_irq_restore(flags);
-	clk_disable(up->clk);
-
-}
-
-#ifdef CONFIG_CONSOLE_POLL
-/*
- * Console polling routines for writing and reading from the uart while
- * in an interrupt or debug context.
- */
-
-static int serial_pxa_get_poll_char(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned char lsr = serial_in(up, UART_LSR);
-
-	while (!(lsr & UART_LSR_DR))
-		lsr = serial_in(up, UART_LSR);
-
-	return serial_in(up, UART_RX);
-}
-
-
-static void serial_pxa_put_poll_char(struct uart_port *port,
-			 unsigned char c)
-{
-	unsigned int ier;
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	/*
-	 *	First save the IER then disable the interrupts
-	 */
-	ier = serial_in(up, UART_IER);
-	serial_out(up, UART_IER, UART_IER_UUE);
-
-	wait_for_xmitr(up);
-	/*
-	 *	Send the character out.
-	 *	If a LF, also do CR...
-	 */
-	serial_out(up, UART_TX, c);
-	if (c == 10) {
-		wait_for_xmitr(up);
-		serial_out(up, UART_TX, 13);
-	}
-
-	/*
-	 *	Finally, wait for transmitter to become empty
-	 *	and restore the IER
-	 */
-	wait_for_xmitr(up);
-	serial_out(up, UART_IER, ier);
-}
-
-#endif /* CONFIG_CONSOLE_POLL */
-
-static int __init
-serial_pxa_console_setup(struct console *co, char *options)
-{
-	struct uart_pxa_port *up;
-	int baud = 9600;
-	int bits = 8;
-	int parity = 'n';
-	int flow = 'n';
-
-	if (co->index == -1 || co->index >= serial_pxa_reg.nr)
-		co->index = 0;
-	up = serial_pxa_ports[co->index];
-	if (!up)
-		return -ENODEV;
-
-	if (options)
-		uart_parse_options(options, &baud, &parity, &bits, &flow);
-
-	return uart_set_options(&up->port, co, baud, parity, bits, flow);
-}
-
-static struct console serial_pxa_console = {
-	.name		= "ttyS",
-	.write		= serial_pxa_console_write,
-	.device		= uart_console_device,
-	.setup		= serial_pxa_console_setup,
-	.flags		= CON_PRINTBUFFER,
-	.index		= -1,
-	.data		= &serial_pxa_reg,
-};
-
-#define PXA_CONSOLE	&serial_pxa_console
-#else
-#define PXA_CONSOLE	NULL
-#endif
-
-static struct uart_ops serial_pxa_pops = {
-	.tx_empty	= serial_pxa_tx_empty,
-	.set_mctrl	= serial_pxa_set_mctrl,
-	.get_mctrl	= serial_pxa_get_mctrl,
-	.stop_tx	= serial_pxa_stop_tx,
-	.start_tx	= serial_pxa_start_tx,
-	.stop_rx	= serial_pxa_stop_rx,
-	.enable_ms	= serial_pxa_enable_ms,
-	.break_ctl	= serial_pxa_break_ctl,
-	.startup	= serial_pxa_startup,
-	.shutdown	= serial_pxa_shutdown,
-	.set_termios	= serial_pxa_set_termios,
-	.pm		= serial_pxa_pm,
-	.type		= serial_pxa_type,
-	.release_port	= serial_pxa_release_port,
-	.request_port	= serial_pxa_request_port,
-	.config_port	= serial_pxa_config_port,
-	.verify_port	= serial_pxa_verify_port,
-#ifdef CONFIG_CONSOLE_POLL
-	.poll_get_char = serial_pxa_get_poll_char,
-	.poll_put_char = serial_pxa_put_poll_char,
-#endif
-};
-
-static struct uart_driver serial_pxa_reg = {
-	.owner		= THIS_MODULE,
-	.driver_name	= "PXA serial",
-	.dev_name	= "ttyS",
-	.major		= TTY_MAJOR,
-	.minor		= 64,
-	.nr		= 4,
-	.cons		= PXA_CONSOLE,
-};
-
-#ifdef CONFIG_PM
-static int serial_pxa_suspend(struct device *dev)
-{
-        struct uart_pxa_port *sport = dev_get_drvdata(dev);
-
-        if (sport)
-                uart_suspend_port(&serial_pxa_reg, &sport->port);
-
-        return 0;
-}
-
-static int serial_pxa_resume(struct device *dev)
-{
-        struct uart_pxa_port *sport = dev_get_drvdata(dev);
-
-        if (sport)
-                uart_resume_port(&serial_pxa_reg, &sport->port);
-
-        return 0;
-}
-
-static const struct dev_pm_ops serial_pxa_pm_ops = {
-	.suspend	= serial_pxa_suspend,
-	.resume		= serial_pxa_resume,
-};
-#endif
-
-static struct of_device_id serial_pxa_dt_ids[] = {
-	{ .compatible = "mrvl,pxa-uart", },
-	{ .compatible = "mrvl,mmp-uart", },
-	{}
-};
-MODULE_DEVICE_TABLE(of, serial_pxa_dt_ids);
-
-static int serial_pxa_probe_dt(struct platform_device *pdev,
-			       struct uart_pxa_port *sport)
-{
-	struct device_node *np = pdev->dev.of_node;
-	int ret;
-
-	if (!np)
-		return 1;
-
-	ret = of_alias_get_id(np, "serial");
-	if (ret < 0) {
-		dev_err(&pdev->dev, "failed to get alias id, errno %d\n", ret);
-		return ret;
-	}
-	sport->port.line = ret;
-	return 0;
-}
-
-static int serial_pxa_probe(struct platform_device *dev)
-{
-	struct uart_pxa_port *sport;
-	struct resource *mmres, *irqres;
-	int ret;
-
-	mmres = platform_get_resource(dev, IORESOURCE_MEM, 0);
-	irqres = platform_get_resource(dev, IORESOURCE_IRQ, 0);
-	if (!mmres || !irqres)
-		return -ENODEV;
-
-	sport = kzalloc(sizeof(struct uart_pxa_port), GFP_KERNEL);
-	if (!sport)
-		return -ENOMEM;
-
-	sport->clk = clk_get(&dev->dev, NULL);
-	if (IS_ERR(sport->clk)) {
-		ret = PTR_ERR(sport->clk);
-		goto err_free;
-	}
-
-	ret = clk_prepare(sport->clk);
-	if (ret) {
-		clk_put(sport->clk);
-		goto err_free;
-	}
-
-	sport->port.type = PORT_PXA;
-	sport->port.iotype = UPIO_MEM;
-	sport->port.mapbase = mmres->start;
-	sport->port.irq = irqres->start;
-	sport->port.fifosize = 64;
-	sport->port.ops = &serial_pxa_pops;
-	sport->port.dev = &dev->dev;
-	sport->port.flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF;
-	sport->port.uartclk = clk_get_rate(sport->clk);
-
-	ret = serial_pxa_probe_dt(dev, sport);
-	if (ret > 0)
-		sport->port.line = dev->id;
-	else if (ret < 0)
-		goto err_clk;
-	snprintf(sport->name, PXA_NAME_LEN - 1, "UART%d", sport->port.line + 1);
-
-	sport->port.membase = ioremap(mmres->start, resource_size(mmres));
-	if (!sport->port.membase) {
-		ret = -ENOMEM;
-		goto err_clk;
-	}
-
-	serial_pxa_ports[sport->port.line] = sport;
-
-	uart_add_one_port(&serial_pxa_reg, &sport->port);
-	platform_set_drvdata(dev, sport);
-
-	return 0;
-
- err_clk:
-	clk_unprepare(sport->clk);
-	clk_put(sport->clk);
- err_free:
-	kfree(sport);
-	return ret;
-}
-
-static int serial_pxa_remove(struct platform_device *dev)
-{
-	struct uart_pxa_port *sport = platform_get_drvdata(dev);
-
-	uart_remove_one_port(&serial_pxa_reg, &sport->port);
-
-	clk_unprepare(sport->clk);
-	clk_put(sport->clk);
-	kfree(sport);
-
-	return 0;
-}
-
-static struct platform_driver serial_pxa_driver = {
-        .probe          = serial_pxa_probe,
-        .remove         = serial_pxa_remove,
-
-	.driver		= {
-	        .name	= "pxa2xx-uart",
-		.owner	= THIS_MODULE,
-#ifdef CONFIG_PM
-		.pm	= &serial_pxa_pm_ops,
-#endif
-		.of_match_table = serial_pxa_dt_ids,
-	},
-};
-
-static int __init serial_pxa_init(void)
-{
-	int ret;
-
-	ret = uart_register_driver(&serial_pxa_reg);
-	if (ret != 0)
-		return ret;
-
-	ret = platform_driver_register(&serial_pxa_driver);
-	if (ret != 0)
-		uart_unregister_driver(&serial_pxa_reg);
-
-	return ret;
-}
-
-static void __exit serial_pxa_exit(void)
-{
-	platform_driver_unregister(&serial_pxa_driver);
-	uart_unregister_driver(&serial_pxa_reg);
-}
-
-module_init(serial_pxa_init);
-module_exit(serial_pxa_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:pxa2xx-uart");
-- 
1.8.4.2


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

* [PATCH v3 01/21 resend] serial: rewrite pxa2xx-uart to use 8250_core
@ 2013-12-17 19:37             ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-17 19:37 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Greg Kroah-Hartman, Russell King, Jiri Slaby,
	Grant Likely, Rob Herring, Heikki Krogerus, James Cameron,
	Zhou Zhu, Haojian Zhuang, Arnd Bergmann,
	open list:SERIAL DRIVERS, open list:OPEN FIRMWARE AND...

pxa2xx-uart was a separate uart platform driver. It was declaring
the same device names and numbers as 8250 driver. As a result,
it was impossible to use 8250 driver on PXA SoCs.

Upon closer examination pxa2xx-uart turned out to be a clone of
8250_core driver.

Workaround for Erratum #19 according to Marvel(R) PXA270M Processor
Specification Update (April 19, 2010) is dropped. 8250_core reads
from FIFO immediately after checking DR bit in LSR.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Reviewed-by: James Cameron <quozl@laptop.org>
CC: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 Resenging together with the rest of the series as the series
 breaks with this one at [PATCH 12/21]

 changes v2..v3
 * remove devm_free/put as suggested by Heikki Krogerus
 * use SET_SYSTEM_SLEEP_PM_OPS macro to set pm ops as suggested
   by Heikki Krogerus

 changes v1..v2
 * actually implement workaround for E74 in dl_write as spooted
   by James Cameron
 * added comment about E19 in commit message

 arch/arm/configs/am200epdkit_defconfig    |   3 +-
 arch/arm/configs/cm_x2xx_defconfig        |   3 +-
 arch/arm/configs/cm_x300_defconfig        |   3 +-
 arch/arm/configs/colibri_pxa270_defconfig |   3 +-
 arch/arm/configs/colibri_pxa300_defconfig |   3 +-
 arch/arm/configs/corgi_defconfig          |   4 +-
 arch/arm/configs/em_x270_defconfig        |   3 +-
 arch/arm/configs/ezx_defconfig            |   3 +-
 arch/arm/configs/h5000_defconfig          |   3 +-
 arch/arm/configs/imote2_defconfig         |   3 +-
 arch/arm/configs/lpd270_defconfig         |   3 +-
 arch/arm/configs/lubbock_defconfig        |   3 +-
 arch/arm/configs/mainstone_defconfig      |   3 +-
 arch/arm/configs/mmp2_defconfig           |   3 +-
 arch/arm/configs/pcm027_defconfig         |   3 +-
 arch/arm/configs/pxa168_defconfig         |   3 +-
 arch/arm/configs/pxa255-idp_defconfig     |   3 +-
 arch/arm/configs/pxa3xx_defconfig         |   3 +-
 arch/arm/configs/pxa910_defconfig         |   3 +-
 arch/arm/configs/raumfeld_defconfig       |   3 +-
 arch/arm/configs/spitz_defconfig          |   4 +-
 arch/arm/configs/trizeps4_defconfig       |   3 +-
 arch/arm/configs/viper_defconfig          |   4 +-
 arch/arm/configs/xcep_defconfig           |   3 +-
 drivers/tty/serial/8250/8250_pxa.c        | 178 ++++++
 drivers/tty/serial/8250/Kconfig           |   9 +
 drivers/tty/serial/8250/Makefile          |   1 +
 drivers/tty/serial/Kconfig                |  23 -
 drivers/tty/serial/Makefile               |   1 -
 drivers/tty/serial/pxa.c                  | 971 ------------------------------
 30 files changed, 236 insertions(+), 1022 deletions(-)
 create mode 100644 drivers/tty/serial/8250/8250_pxa.c
 delete mode 100644 drivers/tty/serial/pxa.c

diff --git a/arch/arm/configs/am200epdkit_defconfig b/arch/arm/configs/am200epdkit_defconfig
index f0dea52..0cde234 100644
--- a/arch/arm/configs/am200epdkit_defconfig
+++ b/arch/arm/configs/am200epdkit_defconfig
@@ -60,8 +60,9 @@ CONFIG_BLK_DEV_IDECS=m
 CONFIG_NETDEVICES=y
 CONFIG_NET_ETHERNET=y
 CONFIG_SMC91X=m
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 # CONFIG_HWMON is not set
diff --git a/arch/arm/configs/cm_x2xx_defconfig b/arch/arm/configs/cm_x2xx_defconfig
index a93ff8d..b9fbe65 100644
--- a/arch/arm/configs/cm_x2xx_defconfig
+++ b/arch/arm/configs/cm_x2xx_defconfig
@@ -96,8 +96,9 @@ CONFIG_KEYBOARD_PXA27x=m
 CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_TOUCHSCREEN_UCB1400=m
 # CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_LEGACY_PTY_COUNT=16
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/cm_x300_defconfig b/arch/arm/configs/cm_x300_defconfig
index f4b7672..53a82ae 100644
--- a/arch/arm/configs/cm_x300_defconfig
+++ b/arch/arm/configs/cm_x300_defconfig
@@ -80,8 +80,9 @@ CONFIG_TOUCHSCREEN_WM97XX=m
 # CONFIG_TOUCHSCREEN_WM9713 is not set
 # CONFIG_SERIO is not set
 # CONFIG_LEGACY_PTYS is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
 CONFIG_I2C_PXA=y
diff --git a/arch/arm/configs/colibri_pxa270_defconfig b/arch/arm/configs/colibri_pxa270_defconfig
index 2ef2c5e..1ce0409 100644
--- a/arch/arm/configs/colibri_pxa270_defconfig
+++ b/arch/arm/configs/colibri_pxa270_defconfig
@@ -103,8 +103,9 @@ CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=m
 CONFIG_SERIO_LIBPS2=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_HW_RANDOM=y
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
diff --git a/arch/arm/configs/colibri_pxa300_defconfig b/arch/arm/configs/colibri_pxa300_defconfig
index b985334..f96bda0 100644
--- a/arch/arm/configs/colibri_pxa300_defconfig
+++ b/arch/arm/configs/colibri_pxa300_defconfig
@@ -31,8 +31,9 @@ CONFIG_INPUT_EVDEV=y
 # CONFIG_INPUT_MOUSE is not set
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_GPIO_ROTARY_ENCODER=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_HW_RANDOM=y
 CONFIG_DEBUG_GPIO=y
 # CONFIG_HWMON is not set
diff --git a/arch/arm/configs/corgi_defconfig b/arch/arm/configs/corgi_defconfig
index 1fd1d1d..bb4842d 100644
--- a/arch/arm/configs/corgi_defconfig
+++ b/arch/arm/configs/corgi_defconfig
@@ -131,10 +131,10 @@ CONFIG_TOUCHSCREEN_ADS7846=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=m
 # CONFIG_SERIO is not set
-CONFIG_SERIAL_8250=m
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_CS=m
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 CONFIG_I2C=y
 CONFIG_I2C_PXA=y
diff --git a/arch/arm/configs/em_x270_defconfig b/arch/arm/configs/em_x270_defconfig
index 60a21e0..ec0ec54 100644
--- a/arch/arm/configs/em_x270_defconfig
+++ b/arch/arm/configs/em_x270_defconfig
@@ -90,8 +90,9 @@ CONFIG_TOUCHSCREEN_WM97XX=m
 # CONFIG_TOUCHSCREEN_WM9705 is not set
 # CONFIG_TOUCHSCREEN_WM9713 is not set
 # CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_LEGACY_PTY_COUNT=16
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/ezx_defconfig b/arch/arm/configs/ezx_defconfig
index d95763d..631e2ec 100644
--- a/arch/arm/configs/ezx_defconfig
+++ b/arch/arm/configs/ezx_defconfig
@@ -215,8 +215,9 @@ CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=y
 CONFIG_INPUT_PCAP=y
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_LEGACY_PTY_COUNT=8
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/h5000_defconfig b/arch/arm/configs/h5000_defconfig
index 37903e3..655b735 100644
--- a/arch/arm/configs/h5000_defconfig
+++ b/arch/arm/configs/h5000_defconfig
@@ -47,8 +47,9 @@ CONFIG_MTD_PHYSMAP=y
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_LEGACY_PTY_COUNT=32
 # CONFIG_HW_RANDOM is not set
 # CONFIG_HWMON is not set
diff --git a/arch/arm/configs/imote2_defconfig b/arch/arm/configs/imote2_defconfig
index fd996bb..49d45e9 100644
--- a/arch/arm/configs/imote2_defconfig
+++ b/arch/arm/configs/imote2_defconfig
@@ -193,8 +193,9 @@ CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=y
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_LEGACY_PTY_COUNT=8
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/lpd270_defconfig b/arch/arm/configs/lpd270_defconfig
index 1c8c9ee..c3927b6 100644
--- a/arch/arm/configs/lpd270_defconfig
+++ b/arch/arm/configs/lpd270_defconfig
@@ -38,8 +38,9 @@ CONFIG_SMC91X=y
 CONFIG_INPUT_EVDEV=y
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_HW_RANDOM is not set
 CONFIG_FB=y
 CONFIG_FB_PXA=y
diff --git a/arch/arm/configs/lubbock_defconfig b/arch/arm/configs/lubbock_defconfig
index c4ba274..c8b0436 100644
--- a/arch/arm/configs/lubbock_defconfig
+++ b/arch/arm/configs/lubbock_defconfig
@@ -37,8 +37,9 @@ CONFIG_PCMCIA_PCNET=y
 CONFIG_INPUT_EVDEV=y
 # CONFIG_SERIO_SERPORT is not set
 CONFIG_SERIO_SA1111=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_USB_GADGET=y
 CONFIG_USB_G_SERIAL=m
diff --git a/arch/arm/configs/mainstone_defconfig b/arch/arm/configs/mainstone_defconfig
index 04efa1b..768892c 100644
--- a/arch/arm/configs/mainstone_defconfig
+++ b/arch/arm/configs/mainstone_defconfig
@@ -34,8 +34,9 @@ CONFIG_SMC91X=y
 CONFIG_INPUT_EVDEV=y
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_FB=y
 CONFIG_FB_PXA=y
 # CONFIG_VGA_CONSOLE is not set
diff --git a/arch/arm/configs/mmp2_defconfig b/arch/arm/configs/mmp2_defconfig
index f1cb95e..1ced9df 100644
--- a/arch/arm/configs/mmp2_defconfig
+++ b/arch/arm/configs/mmp2_defconfig
@@ -44,8 +44,9 @@ CONFIG_SMC91X=y
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/pcm027_defconfig b/arch/arm/configs/pcm027_defconfig
index 2f136c3..1280128 100644
--- a/arch/arm/configs/pcm027_defconfig
+++ b/arch/arm/configs/pcm027_defconfig
@@ -60,8 +60,9 @@ CONFIG_SMC91X=y
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/pxa168_defconfig b/arch/arm/configs/pxa168_defconfig
index 74d7e01..1668dac 100644
--- a/arch/arm/configs/pxa168_defconfig
+++ b/arch/arm/configs/pxa168_defconfig
@@ -40,8 +40,9 @@ CONFIG_SMC91X=y
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 # CONFIG_HWMON is not set
diff --git a/arch/arm/configs/pxa255-idp_defconfig b/arch/arm/configs/pxa255-idp_defconfig
index 917a070..399a706 100644
--- a/arch/arm/configs/pxa255-idp_defconfig
+++ b/arch/arm/configs/pxa255-idp_defconfig
@@ -35,8 +35,9 @@ CONFIG_SMC91X=y
 CONFIG_INPUT_EVDEV=y
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_FB=y
 CONFIG_FB_PXA=y
 # CONFIG_VGA_CONSOLE is not set
diff --git a/arch/arm/configs/pxa3xx_defconfig b/arch/arm/configs/pxa3xx_defconfig
index 60e3138..7c3e052 100644
--- a/arch/arm/configs/pxa3xx_defconfig
+++ b/arch/arm/configs/pxa3xx_defconfig
@@ -56,8 +56,9 @@ CONFIG_KEYBOARD_PXA27x=y
 CONFIG_KEYBOARD_PXA930_ROTARY=y
 CONFIG_MOUSE_PXA930_TRKBALL=y
 CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/pxa910_defconfig b/arch/arm/configs/pxa910_defconfig
index 3bb7771..cdacfcb 100644
--- a/arch/arm/configs/pxa910_defconfig
+++ b/arch/arm/configs/pxa910_defconfig
@@ -40,8 +40,9 @@ CONFIG_SMC91X=y
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_SPI=y
 CONFIG_FB=y
 CONFIG_MMP_DISP=y
diff --git a/arch/arm/configs/raumfeld_defconfig b/arch/arm/configs/raumfeld_defconfig
index f7caa90..f1e16f2 100644
--- a/arch/arm/configs/raumfeld_defconfig
+++ b/arch/arm/configs/raumfeld_defconfig
@@ -67,8 +67,9 @@ CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_TOUCHSCREEN_EETI=m
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_GPIO_ROTARY_ENCODER=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_HW_RANDOM=y
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
diff --git a/arch/arm/configs/spitz_defconfig b/arch/arm/configs/spitz_defconfig
index 2e0419d..b6efcf5 100644
--- a/arch/arm/configs/spitz_defconfig
+++ b/arch/arm/configs/spitz_defconfig
@@ -128,10 +128,10 @@ CONFIG_TOUCHSCREEN_ADS7846=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=m
 # CONFIG_SERIO is not set
-CONFIG_SERIAL_8250=m
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_CS=m
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 CONFIG_SPI=y
 CONFIG_SPI_PXA2XX=y
diff --git a/arch/arm/configs/trizeps4_defconfig b/arch/arm/configs/trizeps4_defconfig
index 3162173..453c79c 100644
--- a/arch/arm/configs/trizeps4_defconfig
+++ b/arch/arm/configs/trizeps4_defconfig
@@ -132,8 +132,9 @@ CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=m
 CONFIG_SERIO_LIBPS2=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_HW_RANDOM=y
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
diff --git a/arch/arm/configs/viper_defconfig b/arch/arm/configs/viper_defconfig
index d36e0d3..4efac06 100644
--- a/arch/arm/configs/viper_defconfig
+++ b/arch/arm/configs/viper_defconfig
@@ -101,11 +101,11 @@ CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=m
 # CONFIG_CONSOLE_TRANSLATIONS is not set
 # CONFIG_VT_CONSOLE is not set
-CONFIG_SERIAL_8250=m
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_NR_UARTS=5
 CONFIG_SERIAL_8250_RUNTIME_UARTS=5
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
diff --git a/arch/arm/configs/xcep_defconfig b/arch/arm/configs/xcep_defconfig
index 721832f..b67aeaf 100644
--- a/arch/arm/configs/xcep_defconfig
+++ b/arch/arm/configs/xcep_defconfig
@@ -60,8 +60,9 @@ CONFIG_NET_ETHERNET=y
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
 # CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=m
diff --git a/drivers/tty/serial/8250/8250_pxa.c b/drivers/tty/serial/8250/8250_pxa.c
new file mode 100644
index 0000000..0da0d40
--- /dev/null
+++ b/drivers/tty/serial/8250/8250_pxa.c
@@ -0,0 +1,178 @@
+/*
+ *  drivers/tty/serial/8250/8250_pxa.c -- driver for PXA on-board UARTS
+ *  Copyright:	(C) 2013 Sergei Ianovich <ynvich@gmail.com>
+ *
+ *  replaces drivers/serial/pxa.c by Nicolas Pitre
+ *  Created:	Feb 20, 2003
+ *  Copyright:	(C) 2003 Monta Vista Software, Inc.
+ *
+ *  Based on drivers/serial/8250.c by Russell King.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/serial_8250.h>
+#include <linux/serial_core.h>
+#include <linux/serial_reg.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
+#include <linux/pm_runtime.h>
+
+#include "8250.h"
+
+struct pxa8250_data {
+	int			line;
+	struct clk		*clk;
+};
+
+#ifdef CONFIG_PM
+static int serial_pxa_suspend(struct device *dev)
+{
+	struct pxa8250_data *data = dev_get_drvdata(dev);
+
+	serial8250_suspend_port(data->line);
+
+	return 0;
+}
+
+static int serial_pxa_resume(struct device *dev)
+{
+	struct pxa8250_data *data = dev_get_drvdata(dev);
+
+	serial8250_resume_port(data->line);
+
+	return 0;
+}
+#endif
+
+static const struct dev_pm_ops serial_pxa_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(serial_pxa_suspend, serial_pxa_resume)
+};
+
+static struct of_device_id serial_pxa_dt_ids[] = {
+	{ .compatible = "mrvl,pxa-uart", },
+	{ .compatible = "mrvl,mmp-uart", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, serial_pxa_dt_ids);
+
+/* Uart divisor latch write */
+static void serial_pxa_dl_write(struct uart_8250_port *up, int value)
+{
+	unsigned int dll;
+
+	serial_out(up, UART_DLL, value & 0xff);
+	/*
+	 * work around Erratum #74 according to Marvel(R) PXA270M Processor
+	 * Specification Update (April 19, 2010)
+	 */
+	dll = serial_in(up, UART_DLL);
+	WARN_ON(dll != (value & 0xff));
+
+	serial_out(up, UART_DLM, value >> 8 & 0xff);
+}
+
+
+static void serial_pxa_pm(struct uart_port *port, unsigned int state,
+	      unsigned int oldstate)
+{
+	struct pxa8250_data *data = port->private_data;
+
+	if (!state)
+		clk_prepare_enable(data->clk);
+	else
+		clk_disable_unprepare(data->clk);
+}
+
+static int serial_pxa_probe(struct platform_device *pdev)
+{
+	struct uart_8250_port uart = {};
+	struct pxa8250_data *data;
+	struct resource *mmres, *irqres;
+	int ret;
+
+	mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	irqres = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!mmres || !irqres)
+		return -ENODEV;
+
+	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(data->clk))
+		return PTR_ERR(data->clk);
+
+	ret = clk_prepare(data->clk);
+	if (ret)
+		return ret;
+
+	uart.port.type = PORT_XSCALE;
+	uart.port.iotype = UPIO_MEM32;
+	uart.port.mapbase = mmres->start;
+	uart.port.regshift = 2;
+	uart.port.irq = irqres->start;
+	uart.port.fifosize = 64;
+	uart.port.flags = UPF_IOREMAP | UPF_SKIP_TEST;
+	uart.port.dev = &pdev->dev;
+	uart.port.uartclk = clk_get_rate(data->clk);
+	uart.port.pm = serial_pxa_pm;
+	uart.port.private_data = data;
+	uart.dl_write = serial_pxa_dl_write;
+
+	ret = serial8250_register_8250_port(&uart);
+	if (ret < 0)
+		goto err_clk;
+
+	data->line = ret;
+
+	platform_set_drvdata(pdev, data);
+
+	return 0;
+
+ err_clk:
+	clk_unprepare(data->clk);
+	return ret;
+}
+
+static int serial_pxa_remove(struct platform_device *pdev)
+{
+	struct pxa8250_data *data = platform_get_drvdata(pdev);
+
+	serial8250_unregister_port(data->line);
+
+	clk_unprepare(data->clk);
+
+	return 0;
+}
+
+static struct platform_driver serial_pxa_driver = {
+	.probe          = serial_pxa_probe,
+	.remove         = serial_pxa_remove,
+
+	.driver		= {
+		.name	= "pxa2xx-uart",
+		.owner	= THIS_MODULE,
+		.pm	= &serial_pxa_pm_ops,
+		.of_match_table = serial_pxa_dt_ids,
+	},
+};
+
+module_platform_driver(serial_pxa_driver);
+
+MODULE_AUTHOR("Sergei Ianovich");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:pxa2xx-uart");
diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
index 2332991..81bd7c9 100644
--- a/drivers/tty/serial/8250/Kconfig
+++ b/drivers/tty/serial/8250/Kconfig
@@ -302,3 +302,12 @@ config SERIAL_8250_RT288X
 	  If you have a Ralink RT288x/RT305x SoC based board and want to use the
 	  serial port, say Y to this option. The driver can handle up to 2 serial
 	  ports. If unsure, say N.
+
+config SERIAL_PXA
+	tristate "PXA serial port support"
+	depends on SERIAL_8250 && (ARCH_PXA || ARCH_MMP)
+	help
+	  If you have a machine based on an Intel XScale PXA2xx CPU you
+	  can enable its onboard serial ports by enabling this option.
+
+	  If you choose M here, the module name will be 8250_pxa.
diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile
index 36d68d0..b7d1b61 100644
--- a/drivers/tty/serial/8250/Makefile
+++ b/drivers/tty/serial/8250/Makefile
@@ -20,3 +20,4 @@ obj-$(CONFIG_SERIAL_8250_HUB6)		+= 8250_hub6.o
 obj-$(CONFIG_SERIAL_8250_FSL)		+= 8250_fsl.o
 obj-$(CONFIG_SERIAL_8250_DW)		+= 8250_dw.o
 obj-$(CONFIG_SERIAL_8250_EM)		+= 8250_em.o
+obj-$(CONFIG_SERIAL_PXA)		+= 8250_pxa.o
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index a3817ab..2ad7184b 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -396,29 +396,6 @@ config SERIAL_MPSC_CONSOLE
 	help
 	  Say Y here if you want to support a serial console on a Marvell MPSC.
 
-config SERIAL_PXA
-	bool "PXA serial port support"
-	depends on ARCH_PXA || ARCH_MMP
-	select SERIAL_CORE
-	help
-	  If you have a machine based on an Intel XScale PXA2xx CPU you
-	  can enable its onboard serial ports by enabling this option.
-
-config SERIAL_PXA_CONSOLE
-	bool "Console on PXA serial port"
-	depends on SERIAL_PXA
-	select SERIAL_CORE_CONSOLE
-	help
-	  If you have enabled the serial port on the Intel XScale PXA
-	  CPU you can make it the console by answering Y to this option.
-
-	  Even if you say Y here, the currently visible virtual console
-	  (/dev/tty0) will still be used as the system console by default, but
-	  you can alter that using a kernel command line option such as
-	  "console=ttySA0". (Try "man bootparam" or see the documentation of
-	  your boot loader (lilo or loadlin) about how to pass options to the
-	  kernel at boot time.)
-
 config SERIAL_SA1100
 	bool "SA1100 serial port support"
 	depends on ARCH_SA1100
diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile
index 3068c77..4ac337b 100644
--- a/drivers/tty/serial/Makefile
+++ b/drivers/tty/serial/Makefile
@@ -20,7 +20,6 @@ obj-$(CONFIG_SERIAL_8250) += 8250/
 obj-$(CONFIG_SERIAL_AMBA_PL010) += amba-pl010.o
 obj-$(CONFIG_SERIAL_AMBA_PL011) += amba-pl011.o
 obj-$(CONFIG_SERIAL_CLPS711X) += clps711x.o
-obj-$(CONFIG_SERIAL_PXA) += pxa.o
 obj-$(CONFIG_SERIAL_PNX8XXX) += pnx8xxx_uart.o
 obj-$(CONFIG_SERIAL_SA1100) += sa1100.o
 obj-$(CONFIG_SERIAL_BCM63XX) += bcm63xx_uart.o
diff --git a/drivers/tty/serial/pxa.c b/drivers/tty/serial/pxa.c
deleted file mode 100644
index f9f20f3..0000000
--- a/drivers/tty/serial/pxa.c
+++ /dev/null
@@ -1,971 +0,0 @@
-/*
- *  Based on drivers/serial/8250.c by Russell King.
- *
- *  Author:	Nicolas Pitre
- *  Created:	Feb 20, 2003
- *  Copyright:	(C) 2003 Monta Vista Software, Inc.
- *
- * 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.
- *
- * Note 1: This driver is made separate from the already too overloaded
- * 8250.c because it needs some kirks of its own and that'll make it
- * easier to add DMA support.
- *
- * Note 2: I'm too sick of device allocation policies for serial ports.
- * If someone else wants to request an "official" allocation of major/minor
- * for this driver please be my guest.  And don't forget that new hardware
- * to come from Intel might have more than 3 or 4 of those UARTs.  Let's
- * hope for a better port registration and dynamic device allocation scheme
- * with the serial core maintainer satisfaction to appear soon.
- */
-
-
-#if defined(CONFIG_SERIAL_PXA_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-#define SUPPORT_SYSRQ
-#endif
-
-#include <linux/module.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-#include <linux/console.h>
-#include <linux/sysrq.h>
-#include <linux/serial_reg.h>
-#include <linux/circ_buf.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/of.h>
-#include <linux/platform_device.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/serial_core.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-
-#define PXA_NAME_LEN		8
-
-struct uart_pxa_port {
-	struct uart_port        port;
-	unsigned char           ier;
-	unsigned char           lcr;
-	unsigned char           mcr;
-	unsigned int            lsr_break_flag;
-	struct clk		*clk;
-	char			name[PXA_NAME_LEN];
-};
-
-static inline unsigned int serial_in(struct uart_pxa_port *up, int offset)
-{
-	offset <<= 2;
-	return readl(up->port.membase + offset);
-}
-
-static inline void serial_out(struct uart_pxa_port *up, int offset, int value)
-{
-	offset <<= 2;
-	writel(value, up->port.membase + offset);
-}
-
-static void serial_pxa_enable_ms(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	up->ier |= UART_IER_MSI;
-	serial_out(up, UART_IER, up->ier);
-}
-
-static void serial_pxa_stop_tx(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	if (up->ier & UART_IER_THRI) {
-		up->ier &= ~UART_IER_THRI;
-		serial_out(up, UART_IER, up->ier);
-	}
-}
-
-static void serial_pxa_stop_rx(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	up->ier &= ~UART_IER_RLSI;
-	up->port.read_status_mask &= ~UART_LSR_DR;
-	serial_out(up, UART_IER, up->ier);
-}
-
-static inline void receive_chars(struct uart_pxa_port *up, int *status)
-{
-	unsigned int ch, flag;
-	int max_count = 256;
-
-	do {
-		/* work around Errata #20 according to
-		 * Intel(R) PXA27x Processor Family
-		 * Specification Update (May 2005)
-		 *
-		 * Step 2
-		 * Disable the Reciever Time Out Interrupt via IER[RTOEI]
-		 */
-		up->ier &= ~UART_IER_RTOIE;
-		serial_out(up, UART_IER, up->ier);
-
-		ch = serial_in(up, UART_RX);
-		flag = TTY_NORMAL;
-		up->port.icount.rx++;
-
-		if (unlikely(*status & (UART_LSR_BI | UART_LSR_PE |
-				       UART_LSR_FE | UART_LSR_OE))) {
-			/*
-			 * For statistics only
-			 */
-			if (*status & UART_LSR_BI) {
-				*status &= ~(UART_LSR_FE | UART_LSR_PE);
-				up->port.icount.brk++;
-				/*
-				 * We do the SysRQ and SAK checking
-				 * here because otherwise the break
-				 * may get masked by ignore_status_mask
-				 * or read_status_mask.
-				 */
-				if (uart_handle_break(&up->port))
-					goto ignore_char;
-			} else if (*status & UART_LSR_PE)
-				up->port.icount.parity++;
-			else if (*status & UART_LSR_FE)
-				up->port.icount.frame++;
-			if (*status & UART_LSR_OE)
-				up->port.icount.overrun++;
-
-			/*
-			 * Mask off conditions which should be ignored.
-			 */
-			*status &= up->port.read_status_mask;
-
-#ifdef CONFIG_SERIAL_PXA_CONSOLE
-			if (up->port.line == up->port.cons->index) {
-				/* Recover the break flag from console xmit */
-				*status |= up->lsr_break_flag;
-				up->lsr_break_flag = 0;
-			}
-#endif
-			if (*status & UART_LSR_BI) {
-				flag = TTY_BREAK;
-			} else if (*status & UART_LSR_PE)
-				flag = TTY_PARITY;
-			else if (*status & UART_LSR_FE)
-				flag = TTY_FRAME;
-		}
-
-		if (uart_handle_sysrq_char(&up->port, ch))
-			goto ignore_char;
-
-		uart_insert_char(&up->port, *status, UART_LSR_OE, ch, flag);
-
-	ignore_char:
-		*status = serial_in(up, UART_LSR);
-	} while ((*status & UART_LSR_DR) && (max_count-- > 0));
-	tty_flip_buffer_push(&up->port.state->port);
-
-	/* work around Errata #20 according to
-	 * Intel(R) PXA27x Processor Family
-	 * Specification Update (May 2005)
-	 *
-	 * Step 6:
-	 * No more data in FIFO: Re-enable RTO interrupt via IER[RTOIE]
-	 */
-	up->ier |= UART_IER_RTOIE;
-	serial_out(up, UART_IER, up->ier);
-}
-
-static void transmit_chars(struct uart_pxa_port *up)
-{
-	struct circ_buf *xmit = &up->port.state->xmit;
-	int count;
-
-	if (up->port.x_char) {
-		serial_out(up, UART_TX, up->port.x_char);
-		up->port.icount.tx++;
-		up->port.x_char = 0;
-		return;
-	}
-	if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) {
-		serial_pxa_stop_tx(&up->port);
-		return;
-	}
-
-	count = up->port.fifosize / 2;
-	do {
-		serial_out(up, UART_TX, xmit->buf[xmit->tail]);
-		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
-		up->port.icount.tx++;
-		if (uart_circ_empty(xmit))
-			break;
-	} while (--count > 0);
-
-	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
-		uart_write_wakeup(&up->port);
-
-
-	if (uart_circ_empty(xmit))
-		serial_pxa_stop_tx(&up->port);
-}
-
-static void serial_pxa_start_tx(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	if (!(up->ier & UART_IER_THRI)) {
-		up->ier |= UART_IER_THRI;
-		serial_out(up, UART_IER, up->ier);
-	}
-}
-
-static inline void check_modem_status(struct uart_pxa_port *up)
-{
-	int status;
-
-	status = serial_in(up, UART_MSR);
-
-	if ((status & UART_MSR_ANY_DELTA) == 0)
-		return;
-
-	if (status & UART_MSR_TERI)
-		up->port.icount.rng++;
-	if (status & UART_MSR_DDSR)
-		up->port.icount.dsr++;
-	if (status & UART_MSR_DDCD)
-		uart_handle_dcd_change(&up->port, status & UART_MSR_DCD);
-	if (status & UART_MSR_DCTS)
-		uart_handle_cts_change(&up->port, status & UART_MSR_CTS);
-
-	wake_up_interruptible(&up->port.state->port.delta_msr_wait);
-}
-
-/*
- * This handles the interrupt from one port.
- */
-static inline irqreturn_t serial_pxa_irq(int irq, void *dev_id)
-{
-	struct uart_pxa_port *up = dev_id;
-	unsigned int iir, lsr;
-
-	iir = serial_in(up, UART_IIR);
-	if (iir & UART_IIR_NO_INT)
-		return IRQ_NONE;
-	lsr = serial_in(up, UART_LSR);
-	if (lsr & UART_LSR_DR)
-		receive_chars(up, &lsr);
-	check_modem_status(up);
-	if (lsr & UART_LSR_THRE)
-		transmit_chars(up);
-	return IRQ_HANDLED;
-}
-
-static unsigned int serial_pxa_tx_empty(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned long flags;
-	unsigned int ret;
-
-	spin_lock_irqsave(&up->port.lock, flags);
-	ret = serial_in(up, UART_LSR) & UART_LSR_TEMT ? TIOCSER_TEMT : 0;
-	spin_unlock_irqrestore(&up->port.lock, flags);
-
-	return ret;
-}
-
-static unsigned int serial_pxa_get_mctrl(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned char status;
-	unsigned int ret;
-
-	status = serial_in(up, UART_MSR);
-
-	ret = 0;
-	if (status & UART_MSR_DCD)
-		ret |= TIOCM_CAR;
-	if (status & UART_MSR_RI)
-		ret |= TIOCM_RNG;
-	if (status & UART_MSR_DSR)
-		ret |= TIOCM_DSR;
-	if (status & UART_MSR_CTS)
-		ret |= TIOCM_CTS;
-	return ret;
-}
-
-static void serial_pxa_set_mctrl(struct uart_port *port, unsigned int mctrl)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned char mcr = 0;
-
-	if (mctrl & TIOCM_RTS)
-		mcr |= UART_MCR_RTS;
-	if (mctrl & TIOCM_DTR)
-		mcr |= UART_MCR_DTR;
-	if (mctrl & TIOCM_OUT1)
-		mcr |= UART_MCR_OUT1;
-	if (mctrl & TIOCM_OUT2)
-		mcr |= UART_MCR_OUT2;
-	if (mctrl & TIOCM_LOOP)
-		mcr |= UART_MCR_LOOP;
-
-	mcr |= up->mcr;
-
-	serial_out(up, UART_MCR, mcr);
-}
-
-static void serial_pxa_break_ctl(struct uart_port *port, int break_state)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned long flags;
-
-	spin_lock_irqsave(&up->port.lock, flags);
-	if (break_state == -1)
-		up->lcr |= UART_LCR_SBC;
-	else
-		up->lcr &= ~UART_LCR_SBC;
-	serial_out(up, UART_LCR, up->lcr);
-	spin_unlock_irqrestore(&up->port.lock, flags);
-}
-
-static int serial_pxa_startup(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned long flags;
-	int retval;
-
-	if (port->line == 3) /* HWUART */
-		up->mcr |= UART_MCR_AFE;
-	else
-		up->mcr = 0;
-
-	up->port.uartclk = clk_get_rate(up->clk);
-
-	/*
-	 * Allocate the IRQ
-	 */
-	retval = request_irq(up->port.irq, serial_pxa_irq, 0, up->name, up);
-	if (retval)
-		return retval;
-
-	/*
-	 * Clear the FIFO buffers and disable them.
-	 * (they will be reenabled in set_termios())
-	 */
-	serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO);
-	serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO |
-			UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
-	serial_out(up, UART_FCR, 0);
-
-	/*
-	 * Clear the interrupt registers.
-	 */
-	(void) serial_in(up, UART_LSR);
-	(void) serial_in(up, UART_RX);
-	(void) serial_in(up, UART_IIR);
-	(void) serial_in(up, UART_MSR);
-
-	/*
-	 * Now, initialize the UART
-	 */
-	serial_out(up, UART_LCR, UART_LCR_WLEN8);
-
-	spin_lock_irqsave(&up->port.lock, flags);
-	up->port.mctrl |= TIOCM_OUT2;
-	serial_pxa_set_mctrl(&up->port, up->port.mctrl);
-	spin_unlock_irqrestore(&up->port.lock, flags);
-
-	/*
-	 * Finally, enable interrupts.  Note: Modem status interrupts
-	 * are set via set_termios(), which will be occurring imminently
-	 * anyway, so we don't enable them here.
-	 */
-	up->ier = UART_IER_RLSI | UART_IER_RDI | UART_IER_RTOIE | UART_IER_UUE;
-	serial_out(up, UART_IER, up->ier);
-
-	/*
-	 * And clear the interrupt registers again for luck.
-	 */
-	(void) serial_in(up, UART_LSR);
-	(void) serial_in(up, UART_RX);
-	(void) serial_in(up, UART_IIR);
-	(void) serial_in(up, UART_MSR);
-
-	return 0;
-}
-
-static void serial_pxa_shutdown(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned long flags;
-
-	free_irq(up->port.irq, up);
-
-	/*
-	 * Disable interrupts from this port
-	 */
-	up->ier = 0;
-	serial_out(up, UART_IER, 0);
-
-	spin_lock_irqsave(&up->port.lock, flags);
-	up->port.mctrl &= ~TIOCM_OUT2;
-	serial_pxa_set_mctrl(&up->port, up->port.mctrl);
-	spin_unlock_irqrestore(&up->port.lock, flags);
-
-	/*
-	 * Disable break condition and FIFOs
-	 */
-	serial_out(up, UART_LCR, serial_in(up, UART_LCR) & ~UART_LCR_SBC);
-	serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO |
-				  UART_FCR_CLEAR_RCVR |
-				  UART_FCR_CLEAR_XMIT);
-	serial_out(up, UART_FCR, 0);
-}
-
-static void
-serial_pxa_set_termios(struct uart_port *port, struct ktermios *termios,
-		       struct ktermios *old)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned char cval, fcr = 0;
-	unsigned long flags;
-	unsigned int baud, quot;
-	unsigned int dll;
-
-	switch (termios->c_cflag & CSIZE) {
-	case CS5:
-		cval = UART_LCR_WLEN5;
-		break;
-	case CS6:
-		cval = UART_LCR_WLEN6;
-		break;
-	case CS7:
-		cval = UART_LCR_WLEN7;
-		break;
-	default:
-	case CS8:
-		cval = UART_LCR_WLEN8;
-		break;
-	}
-
-	if (termios->c_cflag & CSTOPB)
-		cval |= UART_LCR_STOP;
-	if (termios->c_cflag & PARENB)
-		cval |= UART_LCR_PARITY;
-	if (!(termios->c_cflag & PARODD))
-		cval |= UART_LCR_EPAR;
-
-	/*
-	 * Ask the core to calculate the divisor for us.
-	 */
-	baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
-	quot = uart_get_divisor(port, baud);
-
-	if ((up->port.uartclk / quot) < (2400 * 16))
-		fcr = UART_FCR_ENABLE_FIFO | UART_FCR_PXAR1;
-	else if ((up->port.uartclk / quot) < (230400 * 16))
-		fcr = UART_FCR_ENABLE_FIFO | UART_FCR_PXAR8;
-	else
-		fcr = UART_FCR_ENABLE_FIFO | UART_FCR_PXAR32;
-
-	/*
-	 * Ok, we're now changing the port state.  Do it with
-	 * interrupts disabled.
-	 */
-	spin_lock_irqsave(&up->port.lock, flags);
-
-	/*
-	 * Ensure the port will be enabled.
-	 * This is required especially for serial console.
-	 */
-	up->ier |= UART_IER_UUE;
-
-	/*
-	 * Update the per-port timeout.
-	 */
-	uart_update_timeout(port, termios->c_cflag, baud);
-
-	up->port.read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;
-	if (termios->c_iflag & INPCK)
-		up->port.read_status_mask |= UART_LSR_FE | UART_LSR_PE;
-	if (termios->c_iflag & (BRKINT | PARMRK))
-		up->port.read_status_mask |= UART_LSR_BI;
-
-	/*
-	 * Characters to ignore
-	 */
-	up->port.ignore_status_mask = 0;
-	if (termios->c_iflag & IGNPAR)
-		up->port.ignore_status_mask |= UART_LSR_PE | UART_LSR_FE;
-	if (termios->c_iflag & IGNBRK) {
-		up->port.ignore_status_mask |= UART_LSR_BI;
-		/*
-		 * If we're ignoring parity and break indicators,
-		 * ignore overruns too (for real raw support).
-		 */
-		if (termios->c_iflag & IGNPAR)
-			up->port.ignore_status_mask |= UART_LSR_OE;
-	}
-
-	/*
-	 * ignore all characters if CREAD is not set
-	 */
-	if ((termios->c_cflag & CREAD) == 0)
-		up->port.ignore_status_mask |= UART_LSR_DR;
-
-	/*
-	 * CTS flow control flag and modem status interrupts
-	 */
-	up->ier &= ~UART_IER_MSI;
-	if (UART_ENABLE_MS(&up->port, termios->c_cflag))
-		up->ier |= UART_IER_MSI;
-
-	serial_out(up, UART_IER, up->ier);
-
-	if (termios->c_cflag & CRTSCTS)
-		up->mcr |= UART_MCR_AFE;
-	else
-		up->mcr &= ~UART_MCR_AFE;
-
-	serial_out(up, UART_LCR, cval | UART_LCR_DLAB);	/* set DLAB */
-	serial_out(up, UART_DLL, quot & 0xff);		/* LS of divisor */
-
-	/*
-	 * work around Errata #75 according to Intel(R) PXA27x Processor Family
-	 * Specification Update (Nov 2005)
-	 */
-	dll = serial_in(up, UART_DLL);
-	WARN_ON(dll != (quot & 0xff));
-
-	serial_out(up, UART_DLM, quot >> 8);		/* MS of divisor */
-	serial_out(up, UART_LCR, cval);			/* reset DLAB */
-	up->lcr = cval;					/* Save LCR */
-	serial_pxa_set_mctrl(&up->port, up->port.mctrl);
-	serial_out(up, UART_FCR, fcr);
-	spin_unlock_irqrestore(&up->port.lock, flags);
-}
-
-static void
-serial_pxa_pm(struct uart_port *port, unsigned int state,
-	      unsigned int oldstate)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	if (!state)
-		clk_prepare_enable(up->clk);
-	else
-		clk_disable_unprepare(up->clk);
-}
-
-static void serial_pxa_release_port(struct uart_port *port)
-{
-}
-
-static int serial_pxa_request_port(struct uart_port *port)
-{
-	return 0;
-}
-
-static void serial_pxa_config_port(struct uart_port *port, int flags)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	up->port.type = PORT_PXA;
-}
-
-static int
-serial_pxa_verify_port(struct uart_port *port, struct serial_struct *ser)
-{
-	/* we don't want the core code to modify any port params */
-	return -EINVAL;
-}
-
-static const char *
-serial_pxa_type(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	return up->name;
-}
-
-static struct uart_pxa_port *serial_pxa_ports[4];
-static struct uart_driver serial_pxa_reg;
-
-#ifdef CONFIG_SERIAL_PXA_CONSOLE
-
-#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
-
-/*
- *	Wait for transmitter & holding register to empty
- */
-static inline void wait_for_xmitr(struct uart_pxa_port *up)
-{
-	unsigned int status, tmout = 10000;
-
-	/* Wait up to 10ms for the character(s) to be sent. */
-	do {
-		status = serial_in(up, UART_LSR);
-
-		if (status & UART_LSR_BI)
-			up->lsr_break_flag = UART_LSR_BI;
-
-		if (--tmout == 0)
-			break;
-		udelay(1);
-	} while ((status & BOTH_EMPTY) != BOTH_EMPTY);
-
-	/* Wait up to 1s for flow control if necessary */
-	if (up->port.flags & UPF_CONS_FLOW) {
-		tmout = 1000000;
-		while (--tmout &&
-		       ((serial_in(up, UART_MSR) & UART_MSR_CTS) == 0))
-			udelay(1);
-	}
-}
-
-static void serial_pxa_console_putchar(struct uart_port *port, int ch)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	wait_for_xmitr(up);
-	serial_out(up, UART_TX, ch);
-}
-
-/*
- * Print a string to the serial port trying not to disturb
- * any possible real use of the port...
- *
- *	The console_lock must be held when we get here.
- */
-static void
-serial_pxa_console_write(struct console *co, const char *s, unsigned int count)
-{
-	struct uart_pxa_port *up = serial_pxa_ports[co->index];
-	unsigned int ier;
-	unsigned long flags;
-	int locked = 1;
-
-	clk_enable(up->clk);
-	local_irq_save(flags);
-	if (up->port.sysrq)
-		locked = 0;
-	else if (oops_in_progress)
-		locked = spin_trylock(&up->port.lock);
-	else
-		spin_lock(&up->port.lock);
-
-	/*
-	 *	First save the IER then disable the interrupts
-	 */
-	ier = serial_in(up, UART_IER);
-	serial_out(up, UART_IER, UART_IER_UUE);
-
-	uart_console_write(&up->port, s, count, serial_pxa_console_putchar);
-
-	/*
-	 *	Finally, wait for transmitter to become empty
-	 *	and restore the IER
-	 */
-	wait_for_xmitr(up);
-	serial_out(up, UART_IER, ier);
-
-	if (locked)
-		spin_unlock(&up->port.lock);
-	local_irq_restore(flags);
-	clk_disable(up->clk);
-
-}
-
-#ifdef CONFIG_CONSOLE_POLL
-/*
- * Console polling routines for writing and reading from the uart while
- * in an interrupt or debug context.
- */
-
-static int serial_pxa_get_poll_char(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned char lsr = serial_in(up, UART_LSR);
-
-	while (!(lsr & UART_LSR_DR))
-		lsr = serial_in(up, UART_LSR);
-
-	return serial_in(up, UART_RX);
-}
-
-
-static void serial_pxa_put_poll_char(struct uart_port *port,
-			 unsigned char c)
-{
-	unsigned int ier;
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	/*
-	 *	First save the IER then disable the interrupts
-	 */
-	ier = serial_in(up, UART_IER);
-	serial_out(up, UART_IER, UART_IER_UUE);
-
-	wait_for_xmitr(up);
-	/*
-	 *	Send the character out.
-	 *	If a LF, also do CR...
-	 */
-	serial_out(up, UART_TX, c);
-	if (c == 10) {
-		wait_for_xmitr(up);
-		serial_out(up, UART_TX, 13);
-	}
-
-	/*
-	 *	Finally, wait for transmitter to become empty
-	 *	and restore the IER
-	 */
-	wait_for_xmitr(up);
-	serial_out(up, UART_IER, ier);
-}
-
-#endif /* CONFIG_CONSOLE_POLL */
-
-static int __init
-serial_pxa_console_setup(struct console *co, char *options)
-{
-	struct uart_pxa_port *up;
-	int baud = 9600;
-	int bits = 8;
-	int parity = 'n';
-	int flow = 'n';
-
-	if (co->index == -1 || co->index >= serial_pxa_reg.nr)
-		co->index = 0;
-	up = serial_pxa_ports[co->index];
-	if (!up)
-		return -ENODEV;
-
-	if (options)
-		uart_parse_options(options, &baud, &parity, &bits, &flow);
-
-	return uart_set_options(&up->port, co, baud, parity, bits, flow);
-}
-
-static struct console serial_pxa_console = {
-	.name		= "ttyS",
-	.write		= serial_pxa_console_write,
-	.device		= uart_console_device,
-	.setup		= serial_pxa_console_setup,
-	.flags		= CON_PRINTBUFFER,
-	.index		= -1,
-	.data		= &serial_pxa_reg,
-};
-
-#define PXA_CONSOLE	&serial_pxa_console
-#else
-#define PXA_CONSOLE	NULL
-#endif
-
-static struct uart_ops serial_pxa_pops = {
-	.tx_empty	= serial_pxa_tx_empty,
-	.set_mctrl	= serial_pxa_set_mctrl,
-	.get_mctrl	= serial_pxa_get_mctrl,
-	.stop_tx	= serial_pxa_stop_tx,
-	.start_tx	= serial_pxa_start_tx,
-	.stop_rx	= serial_pxa_stop_rx,
-	.enable_ms	= serial_pxa_enable_ms,
-	.break_ctl	= serial_pxa_break_ctl,
-	.startup	= serial_pxa_startup,
-	.shutdown	= serial_pxa_shutdown,
-	.set_termios	= serial_pxa_set_termios,
-	.pm		= serial_pxa_pm,
-	.type		= serial_pxa_type,
-	.release_port	= serial_pxa_release_port,
-	.request_port	= serial_pxa_request_port,
-	.config_port	= serial_pxa_config_port,
-	.verify_port	= serial_pxa_verify_port,
-#ifdef CONFIG_CONSOLE_POLL
-	.poll_get_char = serial_pxa_get_poll_char,
-	.poll_put_char = serial_pxa_put_poll_char,
-#endif
-};
-
-static struct uart_driver serial_pxa_reg = {
-	.owner		= THIS_MODULE,
-	.driver_name	= "PXA serial",
-	.dev_name	= "ttyS",
-	.major		= TTY_MAJOR,
-	.minor		= 64,
-	.nr		= 4,
-	.cons		= PXA_CONSOLE,
-};
-
-#ifdef CONFIG_PM
-static int serial_pxa_suspend(struct device *dev)
-{
-        struct uart_pxa_port *sport = dev_get_drvdata(dev);
-
-        if (sport)
-                uart_suspend_port(&serial_pxa_reg, &sport->port);
-
-        return 0;
-}
-
-static int serial_pxa_resume(struct device *dev)
-{
-        struct uart_pxa_port *sport = dev_get_drvdata(dev);
-
-        if (sport)
-                uart_resume_port(&serial_pxa_reg, &sport->port);
-
-        return 0;
-}
-
-static const struct dev_pm_ops serial_pxa_pm_ops = {
-	.suspend	= serial_pxa_suspend,
-	.resume		= serial_pxa_resume,
-};
-#endif
-
-static struct of_device_id serial_pxa_dt_ids[] = {
-	{ .compatible = "mrvl,pxa-uart", },
-	{ .compatible = "mrvl,mmp-uart", },
-	{}
-};
-MODULE_DEVICE_TABLE(of, serial_pxa_dt_ids);
-
-static int serial_pxa_probe_dt(struct platform_device *pdev,
-			       struct uart_pxa_port *sport)
-{
-	struct device_node *np = pdev->dev.of_node;
-	int ret;
-
-	if (!np)
-		return 1;
-
-	ret = of_alias_get_id(np, "serial");
-	if (ret < 0) {
-		dev_err(&pdev->dev, "failed to get alias id, errno %d\n", ret);
-		return ret;
-	}
-	sport->port.line = ret;
-	return 0;
-}
-
-static int serial_pxa_probe(struct platform_device *dev)
-{
-	struct uart_pxa_port *sport;
-	struct resource *mmres, *irqres;
-	int ret;
-
-	mmres = platform_get_resource(dev, IORESOURCE_MEM, 0);
-	irqres = platform_get_resource(dev, IORESOURCE_IRQ, 0);
-	if (!mmres || !irqres)
-		return -ENODEV;
-
-	sport = kzalloc(sizeof(struct uart_pxa_port), GFP_KERNEL);
-	if (!sport)
-		return -ENOMEM;
-
-	sport->clk = clk_get(&dev->dev, NULL);
-	if (IS_ERR(sport->clk)) {
-		ret = PTR_ERR(sport->clk);
-		goto err_free;
-	}
-
-	ret = clk_prepare(sport->clk);
-	if (ret) {
-		clk_put(sport->clk);
-		goto err_free;
-	}
-
-	sport->port.type = PORT_PXA;
-	sport->port.iotype = UPIO_MEM;
-	sport->port.mapbase = mmres->start;
-	sport->port.irq = irqres->start;
-	sport->port.fifosize = 64;
-	sport->port.ops = &serial_pxa_pops;
-	sport->port.dev = &dev->dev;
-	sport->port.flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF;
-	sport->port.uartclk = clk_get_rate(sport->clk);
-
-	ret = serial_pxa_probe_dt(dev, sport);
-	if (ret > 0)
-		sport->port.line = dev->id;
-	else if (ret < 0)
-		goto err_clk;
-	snprintf(sport->name, PXA_NAME_LEN - 1, "UART%d", sport->port.line + 1);
-
-	sport->port.membase = ioremap(mmres->start, resource_size(mmres));
-	if (!sport->port.membase) {
-		ret = -ENOMEM;
-		goto err_clk;
-	}
-
-	serial_pxa_ports[sport->port.line] = sport;
-
-	uart_add_one_port(&serial_pxa_reg, &sport->port);
-	platform_set_drvdata(dev, sport);
-
-	return 0;
-
- err_clk:
-	clk_unprepare(sport->clk);
-	clk_put(sport->clk);
- err_free:
-	kfree(sport);
-	return ret;
-}
-
-static int serial_pxa_remove(struct platform_device *dev)
-{
-	struct uart_pxa_port *sport = platform_get_drvdata(dev);
-
-	uart_remove_one_port(&serial_pxa_reg, &sport->port);
-
-	clk_unprepare(sport->clk);
-	clk_put(sport->clk);
-	kfree(sport);
-
-	return 0;
-}
-
-static struct platform_driver serial_pxa_driver = {
-        .probe          = serial_pxa_probe,
-        .remove         = serial_pxa_remove,
-
-	.driver		= {
-	        .name	= "pxa2xx-uart",
-		.owner	= THIS_MODULE,
-#ifdef CONFIG_PM
-		.pm	= &serial_pxa_pm_ops,
-#endif
-		.of_match_table = serial_pxa_dt_ids,
-	},
-};
-
-static int __init serial_pxa_init(void)
-{
-	int ret;
-
-	ret = uart_register_driver(&serial_pxa_reg);
-	if (ret != 0)
-		return ret;
-
-	ret = platform_driver_register(&serial_pxa_driver);
-	if (ret != 0)
-		uart_unregister_driver(&serial_pxa_reg);
-
-	return ret;
-}
-
-static void __exit serial_pxa_exit(void)
-{
-	platform_driver_unregister(&serial_pxa_driver);
-	uart_unregister_driver(&serial_pxa_reg);
-}
-
-module_init(serial_pxa_init);
-module_exit(serial_pxa_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:pxa2xx-uart");
-- 
1.8.4.2


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

* [PATCH v3 01/21 resend] serial: rewrite pxa2xx-uart to use 8250_core
@ 2013-12-17 19:37             ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-17 19:37 UTC (permalink / raw)
  To: linux-arm-kernel

pxa2xx-uart was a separate uart platform driver. It was declaring
the same device names and numbers as 8250 driver. As a result,
it was impossible to use 8250 driver on PXA SoCs.

Upon closer examination pxa2xx-uart turned out to be a clone of
8250_core driver.

Workaround for Erratum #19 according to Marvel(R) PXA270M Processor
Specification Update (April 19, 2010) is dropped. 8250_core reads
from FIFO immediately after checking DR bit in LSR.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Reviewed-by: James Cameron <quozl@laptop.org>
CC: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 Resenging together with the rest of the series as the series
 breaks with this one at [PATCH 12/21]

 changes v2..v3
 * remove devm_free/put as suggested by Heikki Krogerus
 * use SET_SYSTEM_SLEEP_PM_OPS macro to set pm ops as suggested
   by Heikki Krogerus

 changes v1..v2
 * actually implement workaround for E74 in dl_write as spooted
   by James Cameron
 * added comment about E19 in commit message

 arch/arm/configs/am200epdkit_defconfig    |   3 +-
 arch/arm/configs/cm_x2xx_defconfig        |   3 +-
 arch/arm/configs/cm_x300_defconfig        |   3 +-
 arch/arm/configs/colibri_pxa270_defconfig |   3 +-
 arch/arm/configs/colibri_pxa300_defconfig |   3 +-
 arch/arm/configs/corgi_defconfig          |   4 +-
 arch/arm/configs/em_x270_defconfig        |   3 +-
 arch/arm/configs/ezx_defconfig            |   3 +-
 arch/arm/configs/h5000_defconfig          |   3 +-
 arch/arm/configs/imote2_defconfig         |   3 +-
 arch/arm/configs/lpd270_defconfig         |   3 +-
 arch/arm/configs/lubbock_defconfig        |   3 +-
 arch/arm/configs/mainstone_defconfig      |   3 +-
 arch/arm/configs/mmp2_defconfig           |   3 +-
 arch/arm/configs/pcm027_defconfig         |   3 +-
 arch/arm/configs/pxa168_defconfig         |   3 +-
 arch/arm/configs/pxa255-idp_defconfig     |   3 +-
 arch/arm/configs/pxa3xx_defconfig         |   3 +-
 arch/arm/configs/pxa910_defconfig         |   3 +-
 arch/arm/configs/raumfeld_defconfig       |   3 +-
 arch/arm/configs/spitz_defconfig          |   4 +-
 arch/arm/configs/trizeps4_defconfig       |   3 +-
 arch/arm/configs/viper_defconfig          |   4 +-
 arch/arm/configs/xcep_defconfig           |   3 +-
 drivers/tty/serial/8250/8250_pxa.c        | 178 ++++++
 drivers/tty/serial/8250/Kconfig           |   9 +
 drivers/tty/serial/8250/Makefile          |   1 +
 drivers/tty/serial/Kconfig                |  23 -
 drivers/tty/serial/Makefile               |   1 -
 drivers/tty/serial/pxa.c                  | 971 ------------------------------
 30 files changed, 236 insertions(+), 1022 deletions(-)
 create mode 100644 drivers/tty/serial/8250/8250_pxa.c
 delete mode 100644 drivers/tty/serial/pxa.c

diff --git a/arch/arm/configs/am200epdkit_defconfig b/arch/arm/configs/am200epdkit_defconfig
index f0dea52..0cde234 100644
--- a/arch/arm/configs/am200epdkit_defconfig
+++ b/arch/arm/configs/am200epdkit_defconfig
@@ -60,8 +60,9 @@ CONFIG_BLK_DEV_IDECS=m
 CONFIG_NETDEVICES=y
 CONFIG_NET_ETHERNET=y
 CONFIG_SMC91X=m
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 # CONFIG_HWMON is not set
diff --git a/arch/arm/configs/cm_x2xx_defconfig b/arch/arm/configs/cm_x2xx_defconfig
index a93ff8d..b9fbe65 100644
--- a/arch/arm/configs/cm_x2xx_defconfig
+++ b/arch/arm/configs/cm_x2xx_defconfig
@@ -96,8 +96,9 @@ CONFIG_KEYBOARD_PXA27x=m
 CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_TOUCHSCREEN_UCB1400=m
 # CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_LEGACY_PTY_COUNT=16
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/cm_x300_defconfig b/arch/arm/configs/cm_x300_defconfig
index f4b7672..53a82ae 100644
--- a/arch/arm/configs/cm_x300_defconfig
+++ b/arch/arm/configs/cm_x300_defconfig
@@ -80,8 +80,9 @@ CONFIG_TOUCHSCREEN_WM97XX=m
 # CONFIG_TOUCHSCREEN_WM9713 is not set
 # CONFIG_SERIO is not set
 # CONFIG_LEGACY_PTYS is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
 CONFIG_I2C_PXA=y
diff --git a/arch/arm/configs/colibri_pxa270_defconfig b/arch/arm/configs/colibri_pxa270_defconfig
index 2ef2c5e..1ce0409 100644
--- a/arch/arm/configs/colibri_pxa270_defconfig
+++ b/arch/arm/configs/colibri_pxa270_defconfig
@@ -103,8 +103,9 @@ CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=m
 CONFIG_SERIO_LIBPS2=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_HW_RANDOM=y
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
diff --git a/arch/arm/configs/colibri_pxa300_defconfig b/arch/arm/configs/colibri_pxa300_defconfig
index b985334..f96bda0 100644
--- a/arch/arm/configs/colibri_pxa300_defconfig
+++ b/arch/arm/configs/colibri_pxa300_defconfig
@@ -31,8 +31,9 @@ CONFIG_INPUT_EVDEV=y
 # CONFIG_INPUT_MOUSE is not set
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_GPIO_ROTARY_ENCODER=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_HW_RANDOM=y
 CONFIG_DEBUG_GPIO=y
 # CONFIG_HWMON is not set
diff --git a/arch/arm/configs/corgi_defconfig b/arch/arm/configs/corgi_defconfig
index 1fd1d1d..bb4842d 100644
--- a/arch/arm/configs/corgi_defconfig
+++ b/arch/arm/configs/corgi_defconfig
@@ -131,10 +131,10 @@ CONFIG_TOUCHSCREEN_ADS7846=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=m
 # CONFIG_SERIO is not set
-CONFIG_SERIAL_8250=m
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_CS=m
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 CONFIG_I2C=y
 CONFIG_I2C_PXA=y
diff --git a/arch/arm/configs/em_x270_defconfig b/arch/arm/configs/em_x270_defconfig
index 60a21e0..ec0ec54 100644
--- a/arch/arm/configs/em_x270_defconfig
+++ b/arch/arm/configs/em_x270_defconfig
@@ -90,8 +90,9 @@ CONFIG_TOUCHSCREEN_WM97XX=m
 # CONFIG_TOUCHSCREEN_WM9705 is not set
 # CONFIG_TOUCHSCREEN_WM9713 is not set
 # CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_LEGACY_PTY_COUNT=16
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/ezx_defconfig b/arch/arm/configs/ezx_defconfig
index d95763d..631e2ec 100644
--- a/arch/arm/configs/ezx_defconfig
+++ b/arch/arm/configs/ezx_defconfig
@@ -215,8 +215,9 @@ CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=y
 CONFIG_INPUT_PCAP=y
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_LEGACY_PTY_COUNT=8
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/h5000_defconfig b/arch/arm/configs/h5000_defconfig
index 37903e3..655b735 100644
--- a/arch/arm/configs/h5000_defconfig
+++ b/arch/arm/configs/h5000_defconfig
@@ -47,8 +47,9 @@ CONFIG_MTD_PHYSMAP=y
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_LEGACY_PTY_COUNT=32
 # CONFIG_HW_RANDOM is not set
 # CONFIG_HWMON is not set
diff --git a/arch/arm/configs/imote2_defconfig b/arch/arm/configs/imote2_defconfig
index fd996bb..49d45e9 100644
--- a/arch/arm/configs/imote2_defconfig
+++ b/arch/arm/configs/imote2_defconfig
@@ -193,8 +193,9 @@ CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=y
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_LEGACY_PTY_COUNT=8
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/lpd270_defconfig b/arch/arm/configs/lpd270_defconfig
index 1c8c9ee..c3927b6 100644
--- a/arch/arm/configs/lpd270_defconfig
+++ b/arch/arm/configs/lpd270_defconfig
@@ -38,8 +38,9 @@ CONFIG_SMC91X=y
 CONFIG_INPUT_EVDEV=y
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_HW_RANDOM is not set
 CONFIG_FB=y
 CONFIG_FB_PXA=y
diff --git a/arch/arm/configs/lubbock_defconfig b/arch/arm/configs/lubbock_defconfig
index c4ba274..c8b0436 100644
--- a/arch/arm/configs/lubbock_defconfig
+++ b/arch/arm/configs/lubbock_defconfig
@@ -37,8 +37,9 @@ CONFIG_PCMCIA_PCNET=y
 CONFIG_INPUT_EVDEV=y
 # CONFIG_SERIO_SERPORT is not set
 CONFIG_SERIO_SA1111=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_USB_GADGET=y
 CONFIG_USB_G_SERIAL=m
diff --git a/arch/arm/configs/mainstone_defconfig b/arch/arm/configs/mainstone_defconfig
index 04efa1b..768892c 100644
--- a/arch/arm/configs/mainstone_defconfig
+++ b/arch/arm/configs/mainstone_defconfig
@@ -34,8 +34,9 @@ CONFIG_SMC91X=y
 CONFIG_INPUT_EVDEV=y
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_FB=y
 CONFIG_FB_PXA=y
 # CONFIG_VGA_CONSOLE is not set
diff --git a/arch/arm/configs/mmp2_defconfig b/arch/arm/configs/mmp2_defconfig
index f1cb95e..1ced9df 100644
--- a/arch/arm/configs/mmp2_defconfig
+++ b/arch/arm/configs/mmp2_defconfig
@@ -44,8 +44,9 @@ CONFIG_SMC91X=y
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/pcm027_defconfig b/arch/arm/configs/pcm027_defconfig
index 2f136c3..1280128 100644
--- a/arch/arm/configs/pcm027_defconfig
+++ b/arch/arm/configs/pcm027_defconfig
@@ -60,8 +60,9 @@ CONFIG_SMC91X=y
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/pxa168_defconfig b/arch/arm/configs/pxa168_defconfig
index 74d7e01..1668dac 100644
--- a/arch/arm/configs/pxa168_defconfig
+++ b/arch/arm/configs/pxa168_defconfig
@@ -40,8 +40,9 @@ CONFIG_SMC91X=y
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 # CONFIG_HWMON is not set
diff --git a/arch/arm/configs/pxa255-idp_defconfig b/arch/arm/configs/pxa255-idp_defconfig
index 917a070..399a706 100644
--- a/arch/arm/configs/pxa255-idp_defconfig
+++ b/arch/arm/configs/pxa255-idp_defconfig
@@ -35,8 +35,9 @@ CONFIG_SMC91X=y
 CONFIG_INPUT_EVDEV=y
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_FB=y
 CONFIG_FB_PXA=y
 # CONFIG_VGA_CONSOLE is not set
diff --git a/arch/arm/configs/pxa3xx_defconfig b/arch/arm/configs/pxa3xx_defconfig
index 60e3138..7c3e052 100644
--- a/arch/arm/configs/pxa3xx_defconfig
+++ b/arch/arm/configs/pxa3xx_defconfig
@@ -56,8 +56,9 @@ CONFIG_KEYBOARD_PXA27x=y
 CONFIG_KEYBOARD_PXA930_ROTARY=y
 CONFIG_MOUSE_PXA930_TRKBALL=y
 CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/pxa910_defconfig b/arch/arm/configs/pxa910_defconfig
index 3bb7771..cdacfcb 100644
--- a/arch/arm/configs/pxa910_defconfig
+++ b/arch/arm/configs/pxa910_defconfig
@@ -40,8 +40,9 @@ CONFIG_SMC91X=y
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_SPI=y
 CONFIG_FB=y
 CONFIG_MMP_DISP=y
diff --git a/arch/arm/configs/raumfeld_defconfig b/arch/arm/configs/raumfeld_defconfig
index f7caa90..f1e16f2 100644
--- a/arch/arm/configs/raumfeld_defconfig
+++ b/arch/arm/configs/raumfeld_defconfig
@@ -67,8 +67,9 @@ CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_TOUCHSCREEN_EETI=m
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_GPIO_ROTARY_ENCODER=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_HW_RANDOM=y
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
diff --git a/arch/arm/configs/spitz_defconfig b/arch/arm/configs/spitz_defconfig
index 2e0419d..b6efcf5 100644
--- a/arch/arm/configs/spitz_defconfig
+++ b/arch/arm/configs/spitz_defconfig
@@ -128,10 +128,10 @@ CONFIG_TOUCHSCREEN_ADS7846=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=m
 # CONFIG_SERIO is not set
-CONFIG_SERIAL_8250=m
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_CS=m
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 CONFIG_SPI=y
 CONFIG_SPI_PXA2XX=y
diff --git a/arch/arm/configs/trizeps4_defconfig b/arch/arm/configs/trizeps4_defconfig
index 3162173..453c79c 100644
--- a/arch/arm/configs/trizeps4_defconfig
+++ b/arch/arm/configs/trizeps4_defconfig
@@ -132,8 +132,9 @@ CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=m
 CONFIG_SERIO_LIBPS2=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_HW_RANDOM=y
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
diff --git a/arch/arm/configs/viper_defconfig b/arch/arm/configs/viper_defconfig
index d36e0d3..4efac06 100644
--- a/arch/arm/configs/viper_defconfig
+++ b/arch/arm/configs/viper_defconfig
@@ -101,11 +101,11 @@ CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=m
 # CONFIG_CONSOLE_TRANSLATIONS is not set
 # CONFIG_VT_CONSOLE is not set
-CONFIG_SERIAL_8250=m
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_NR_UARTS=5
 CONFIG_SERIAL_8250_RUNTIME_UARTS=5
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
diff --git a/arch/arm/configs/xcep_defconfig b/arch/arm/configs/xcep_defconfig
index 721832f..b67aeaf 100644
--- a/arch/arm/configs/xcep_defconfig
+++ b/arch/arm/configs/xcep_defconfig
@@ -60,8 +60,9 @@ CONFIG_NET_ETHERNET=y
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
 # CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=m
diff --git a/drivers/tty/serial/8250/8250_pxa.c b/drivers/tty/serial/8250/8250_pxa.c
new file mode 100644
index 0000000..0da0d40
--- /dev/null
+++ b/drivers/tty/serial/8250/8250_pxa.c
@@ -0,0 +1,178 @@
+/*
+ *  drivers/tty/serial/8250/8250_pxa.c -- driver for PXA on-board UARTS
+ *  Copyright:	(C) 2013 Sergei Ianovich <ynvich@gmail.com>
+ *
+ *  replaces drivers/serial/pxa.c by Nicolas Pitre
+ *  Created:	Feb 20, 2003
+ *  Copyright:	(C) 2003 Monta Vista Software, Inc.
+ *
+ *  Based on drivers/serial/8250.c by Russell King.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/serial_8250.h>
+#include <linux/serial_core.h>
+#include <linux/serial_reg.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
+#include <linux/pm_runtime.h>
+
+#include "8250.h"
+
+struct pxa8250_data {
+	int			line;
+	struct clk		*clk;
+};
+
+#ifdef CONFIG_PM
+static int serial_pxa_suspend(struct device *dev)
+{
+	struct pxa8250_data *data = dev_get_drvdata(dev);
+
+	serial8250_suspend_port(data->line);
+
+	return 0;
+}
+
+static int serial_pxa_resume(struct device *dev)
+{
+	struct pxa8250_data *data = dev_get_drvdata(dev);
+
+	serial8250_resume_port(data->line);
+
+	return 0;
+}
+#endif
+
+static const struct dev_pm_ops serial_pxa_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(serial_pxa_suspend, serial_pxa_resume)
+};
+
+static struct of_device_id serial_pxa_dt_ids[] = {
+	{ .compatible = "mrvl,pxa-uart", },
+	{ .compatible = "mrvl,mmp-uart", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, serial_pxa_dt_ids);
+
+/* Uart divisor latch write */
+static void serial_pxa_dl_write(struct uart_8250_port *up, int value)
+{
+	unsigned int dll;
+
+	serial_out(up, UART_DLL, value & 0xff);
+	/*
+	 * work around Erratum #74 according to Marvel(R) PXA270M Processor
+	 * Specification Update (April 19, 2010)
+	 */
+	dll = serial_in(up, UART_DLL);
+	WARN_ON(dll != (value & 0xff));
+
+	serial_out(up, UART_DLM, value >> 8 & 0xff);
+}
+
+
+static void serial_pxa_pm(struct uart_port *port, unsigned int state,
+	      unsigned int oldstate)
+{
+	struct pxa8250_data *data = port->private_data;
+
+	if (!state)
+		clk_prepare_enable(data->clk);
+	else
+		clk_disable_unprepare(data->clk);
+}
+
+static int serial_pxa_probe(struct platform_device *pdev)
+{
+	struct uart_8250_port uart = {};
+	struct pxa8250_data *data;
+	struct resource *mmres, *irqres;
+	int ret;
+
+	mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	irqres = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!mmres || !irqres)
+		return -ENODEV;
+
+	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(data->clk))
+		return PTR_ERR(data->clk);
+
+	ret = clk_prepare(data->clk);
+	if (ret)
+		return ret;
+
+	uart.port.type = PORT_XSCALE;
+	uart.port.iotype = UPIO_MEM32;
+	uart.port.mapbase = mmres->start;
+	uart.port.regshift = 2;
+	uart.port.irq = irqres->start;
+	uart.port.fifosize = 64;
+	uart.port.flags = UPF_IOREMAP | UPF_SKIP_TEST;
+	uart.port.dev = &pdev->dev;
+	uart.port.uartclk = clk_get_rate(data->clk);
+	uart.port.pm = serial_pxa_pm;
+	uart.port.private_data = data;
+	uart.dl_write = serial_pxa_dl_write;
+
+	ret = serial8250_register_8250_port(&uart);
+	if (ret < 0)
+		goto err_clk;
+
+	data->line = ret;
+
+	platform_set_drvdata(pdev, data);
+
+	return 0;
+
+ err_clk:
+	clk_unprepare(data->clk);
+	return ret;
+}
+
+static int serial_pxa_remove(struct platform_device *pdev)
+{
+	struct pxa8250_data *data = platform_get_drvdata(pdev);
+
+	serial8250_unregister_port(data->line);
+
+	clk_unprepare(data->clk);
+
+	return 0;
+}
+
+static struct platform_driver serial_pxa_driver = {
+	.probe          = serial_pxa_probe,
+	.remove         = serial_pxa_remove,
+
+	.driver		= {
+		.name	= "pxa2xx-uart",
+		.owner	= THIS_MODULE,
+		.pm	= &serial_pxa_pm_ops,
+		.of_match_table = serial_pxa_dt_ids,
+	},
+};
+
+module_platform_driver(serial_pxa_driver);
+
+MODULE_AUTHOR("Sergei Ianovich");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:pxa2xx-uart");
diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
index 2332991..81bd7c9 100644
--- a/drivers/tty/serial/8250/Kconfig
+++ b/drivers/tty/serial/8250/Kconfig
@@ -302,3 +302,12 @@ config SERIAL_8250_RT288X
 	  If you have a Ralink RT288x/RT305x SoC based board and want to use the
 	  serial port, say Y to this option. The driver can handle up to 2 serial
 	  ports. If unsure, say N.
+
+config SERIAL_PXA
+	tristate "PXA serial port support"
+	depends on SERIAL_8250 && (ARCH_PXA || ARCH_MMP)
+	help
+	  If you have a machine based on an Intel XScale PXA2xx CPU you
+	  can enable its onboard serial ports by enabling this option.
+
+	  If you choose M here, the module name will be 8250_pxa.
diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile
index 36d68d0..b7d1b61 100644
--- a/drivers/tty/serial/8250/Makefile
+++ b/drivers/tty/serial/8250/Makefile
@@ -20,3 +20,4 @@ obj-$(CONFIG_SERIAL_8250_HUB6)		+= 8250_hub6.o
 obj-$(CONFIG_SERIAL_8250_FSL)		+= 8250_fsl.o
 obj-$(CONFIG_SERIAL_8250_DW)		+= 8250_dw.o
 obj-$(CONFIG_SERIAL_8250_EM)		+= 8250_em.o
+obj-$(CONFIG_SERIAL_PXA)		+= 8250_pxa.o
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index a3817ab..2ad7184b 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -396,29 +396,6 @@ config SERIAL_MPSC_CONSOLE
 	help
 	  Say Y here if you want to support a serial console on a Marvell MPSC.
 
-config SERIAL_PXA
-	bool "PXA serial port support"
-	depends on ARCH_PXA || ARCH_MMP
-	select SERIAL_CORE
-	help
-	  If you have a machine based on an Intel XScale PXA2xx CPU you
-	  can enable its onboard serial ports by enabling this option.
-
-config SERIAL_PXA_CONSOLE
-	bool "Console on PXA serial port"
-	depends on SERIAL_PXA
-	select SERIAL_CORE_CONSOLE
-	help
-	  If you have enabled the serial port on the Intel XScale PXA
-	  CPU you can make it the console by answering Y to this option.
-
-	  Even if you say Y here, the currently visible virtual console
-	  (/dev/tty0) will still be used as the system console by default, but
-	  you can alter that using a kernel command line option such as
-	  "console=ttySA0". (Try "man bootparam" or see the documentation of
-	  your boot loader (lilo or loadlin) about how to pass options to the
-	  kernel at boot time.)
-
 config SERIAL_SA1100
 	bool "SA1100 serial port support"
 	depends on ARCH_SA1100
diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile
index 3068c77..4ac337b 100644
--- a/drivers/tty/serial/Makefile
+++ b/drivers/tty/serial/Makefile
@@ -20,7 +20,6 @@ obj-$(CONFIG_SERIAL_8250) += 8250/
 obj-$(CONFIG_SERIAL_AMBA_PL010) += amba-pl010.o
 obj-$(CONFIG_SERIAL_AMBA_PL011) += amba-pl011.o
 obj-$(CONFIG_SERIAL_CLPS711X) += clps711x.o
-obj-$(CONFIG_SERIAL_PXA) += pxa.o
 obj-$(CONFIG_SERIAL_PNX8XXX) += pnx8xxx_uart.o
 obj-$(CONFIG_SERIAL_SA1100) += sa1100.o
 obj-$(CONFIG_SERIAL_BCM63XX) += bcm63xx_uart.o
diff --git a/drivers/tty/serial/pxa.c b/drivers/tty/serial/pxa.c
deleted file mode 100644
index f9f20f3..0000000
--- a/drivers/tty/serial/pxa.c
+++ /dev/null
@@ -1,971 +0,0 @@
-/*
- *  Based on drivers/serial/8250.c by Russell King.
- *
- *  Author:	Nicolas Pitre
- *  Created:	Feb 20, 2003
- *  Copyright:	(C) 2003 Monta Vista Software, Inc.
- *
- * 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.
- *
- * Note 1: This driver is made separate from the already too overloaded
- * 8250.c because it needs some kirks of its own and that'll make it
- * easier to add DMA support.
- *
- * Note 2: I'm too sick of device allocation policies for serial ports.
- * If someone else wants to request an "official" allocation of major/minor
- * for this driver please be my guest.  And don't forget that new hardware
- * to come from Intel might have more than 3 or 4 of those UARTs.  Let's
- * hope for a better port registration and dynamic device allocation scheme
- * with the serial core maintainer satisfaction to appear soon.
- */
-
-
-#if defined(CONFIG_SERIAL_PXA_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-#define SUPPORT_SYSRQ
-#endif
-
-#include <linux/module.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-#include <linux/console.h>
-#include <linux/sysrq.h>
-#include <linux/serial_reg.h>
-#include <linux/circ_buf.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/of.h>
-#include <linux/platform_device.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/serial_core.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-
-#define PXA_NAME_LEN		8
-
-struct uart_pxa_port {
-	struct uart_port        port;
-	unsigned char           ier;
-	unsigned char           lcr;
-	unsigned char           mcr;
-	unsigned int            lsr_break_flag;
-	struct clk		*clk;
-	char			name[PXA_NAME_LEN];
-};
-
-static inline unsigned int serial_in(struct uart_pxa_port *up, int offset)
-{
-	offset <<= 2;
-	return readl(up->port.membase + offset);
-}
-
-static inline void serial_out(struct uart_pxa_port *up, int offset, int value)
-{
-	offset <<= 2;
-	writel(value, up->port.membase + offset);
-}
-
-static void serial_pxa_enable_ms(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	up->ier |= UART_IER_MSI;
-	serial_out(up, UART_IER, up->ier);
-}
-
-static void serial_pxa_stop_tx(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	if (up->ier & UART_IER_THRI) {
-		up->ier &= ~UART_IER_THRI;
-		serial_out(up, UART_IER, up->ier);
-	}
-}
-
-static void serial_pxa_stop_rx(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	up->ier &= ~UART_IER_RLSI;
-	up->port.read_status_mask &= ~UART_LSR_DR;
-	serial_out(up, UART_IER, up->ier);
-}
-
-static inline void receive_chars(struct uart_pxa_port *up, int *status)
-{
-	unsigned int ch, flag;
-	int max_count = 256;
-
-	do {
-		/* work around Errata #20 according to
-		 * Intel(R) PXA27x Processor Family
-		 * Specification Update (May 2005)
-		 *
-		 * Step 2
-		 * Disable the Reciever Time Out Interrupt via IER[RTOEI]
-		 */
-		up->ier &= ~UART_IER_RTOIE;
-		serial_out(up, UART_IER, up->ier);
-
-		ch = serial_in(up, UART_RX);
-		flag = TTY_NORMAL;
-		up->port.icount.rx++;
-
-		if (unlikely(*status & (UART_LSR_BI | UART_LSR_PE |
-				       UART_LSR_FE | UART_LSR_OE))) {
-			/*
-			 * For statistics only
-			 */
-			if (*status & UART_LSR_BI) {
-				*status &= ~(UART_LSR_FE | UART_LSR_PE);
-				up->port.icount.brk++;
-				/*
-				 * We do the SysRQ and SAK checking
-				 * here because otherwise the break
-				 * may get masked by ignore_status_mask
-				 * or read_status_mask.
-				 */
-				if (uart_handle_break(&up->port))
-					goto ignore_char;
-			} else if (*status & UART_LSR_PE)
-				up->port.icount.parity++;
-			else if (*status & UART_LSR_FE)
-				up->port.icount.frame++;
-			if (*status & UART_LSR_OE)
-				up->port.icount.overrun++;
-
-			/*
-			 * Mask off conditions which should be ignored.
-			 */
-			*status &= up->port.read_status_mask;
-
-#ifdef CONFIG_SERIAL_PXA_CONSOLE
-			if (up->port.line == up->port.cons->index) {
-				/* Recover the break flag from console xmit */
-				*status |= up->lsr_break_flag;
-				up->lsr_break_flag = 0;
-			}
-#endif
-			if (*status & UART_LSR_BI) {
-				flag = TTY_BREAK;
-			} else if (*status & UART_LSR_PE)
-				flag = TTY_PARITY;
-			else if (*status & UART_LSR_FE)
-				flag = TTY_FRAME;
-		}
-
-		if (uart_handle_sysrq_char(&up->port, ch))
-			goto ignore_char;
-
-		uart_insert_char(&up->port, *status, UART_LSR_OE, ch, flag);
-
-	ignore_char:
-		*status = serial_in(up, UART_LSR);
-	} while ((*status & UART_LSR_DR) && (max_count-- > 0));
-	tty_flip_buffer_push(&up->port.state->port);
-
-	/* work around Errata #20 according to
-	 * Intel(R) PXA27x Processor Family
-	 * Specification Update (May 2005)
-	 *
-	 * Step 6:
-	 * No more data in FIFO: Re-enable RTO interrupt via IER[RTOIE]
-	 */
-	up->ier |= UART_IER_RTOIE;
-	serial_out(up, UART_IER, up->ier);
-}
-
-static void transmit_chars(struct uart_pxa_port *up)
-{
-	struct circ_buf *xmit = &up->port.state->xmit;
-	int count;
-
-	if (up->port.x_char) {
-		serial_out(up, UART_TX, up->port.x_char);
-		up->port.icount.tx++;
-		up->port.x_char = 0;
-		return;
-	}
-	if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) {
-		serial_pxa_stop_tx(&up->port);
-		return;
-	}
-
-	count = up->port.fifosize / 2;
-	do {
-		serial_out(up, UART_TX, xmit->buf[xmit->tail]);
-		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
-		up->port.icount.tx++;
-		if (uart_circ_empty(xmit))
-			break;
-	} while (--count > 0);
-
-	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
-		uart_write_wakeup(&up->port);
-
-
-	if (uart_circ_empty(xmit))
-		serial_pxa_stop_tx(&up->port);
-}
-
-static void serial_pxa_start_tx(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	if (!(up->ier & UART_IER_THRI)) {
-		up->ier |= UART_IER_THRI;
-		serial_out(up, UART_IER, up->ier);
-	}
-}
-
-static inline void check_modem_status(struct uart_pxa_port *up)
-{
-	int status;
-
-	status = serial_in(up, UART_MSR);
-
-	if ((status & UART_MSR_ANY_DELTA) == 0)
-		return;
-
-	if (status & UART_MSR_TERI)
-		up->port.icount.rng++;
-	if (status & UART_MSR_DDSR)
-		up->port.icount.dsr++;
-	if (status & UART_MSR_DDCD)
-		uart_handle_dcd_change(&up->port, status & UART_MSR_DCD);
-	if (status & UART_MSR_DCTS)
-		uart_handle_cts_change(&up->port, status & UART_MSR_CTS);
-
-	wake_up_interruptible(&up->port.state->port.delta_msr_wait);
-}
-
-/*
- * This handles the interrupt from one port.
- */
-static inline irqreturn_t serial_pxa_irq(int irq, void *dev_id)
-{
-	struct uart_pxa_port *up = dev_id;
-	unsigned int iir, lsr;
-
-	iir = serial_in(up, UART_IIR);
-	if (iir & UART_IIR_NO_INT)
-		return IRQ_NONE;
-	lsr = serial_in(up, UART_LSR);
-	if (lsr & UART_LSR_DR)
-		receive_chars(up, &lsr);
-	check_modem_status(up);
-	if (lsr & UART_LSR_THRE)
-		transmit_chars(up);
-	return IRQ_HANDLED;
-}
-
-static unsigned int serial_pxa_tx_empty(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned long flags;
-	unsigned int ret;
-
-	spin_lock_irqsave(&up->port.lock, flags);
-	ret = serial_in(up, UART_LSR) & UART_LSR_TEMT ? TIOCSER_TEMT : 0;
-	spin_unlock_irqrestore(&up->port.lock, flags);
-
-	return ret;
-}
-
-static unsigned int serial_pxa_get_mctrl(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned char status;
-	unsigned int ret;
-
-	status = serial_in(up, UART_MSR);
-
-	ret = 0;
-	if (status & UART_MSR_DCD)
-		ret |= TIOCM_CAR;
-	if (status & UART_MSR_RI)
-		ret |= TIOCM_RNG;
-	if (status & UART_MSR_DSR)
-		ret |= TIOCM_DSR;
-	if (status & UART_MSR_CTS)
-		ret |= TIOCM_CTS;
-	return ret;
-}
-
-static void serial_pxa_set_mctrl(struct uart_port *port, unsigned int mctrl)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned char mcr = 0;
-
-	if (mctrl & TIOCM_RTS)
-		mcr |= UART_MCR_RTS;
-	if (mctrl & TIOCM_DTR)
-		mcr |= UART_MCR_DTR;
-	if (mctrl & TIOCM_OUT1)
-		mcr |= UART_MCR_OUT1;
-	if (mctrl & TIOCM_OUT2)
-		mcr |= UART_MCR_OUT2;
-	if (mctrl & TIOCM_LOOP)
-		mcr |= UART_MCR_LOOP;
-
-	mcr |= up->mcr;
-
-	serial_out(up, UART_MCR, mcr);
-}
-
-static void serial_pxa_break_ctl(struct uart_port *port, int break_state)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned long flags;
-
-	spin_lock_irqsave(&up->port.lock, flags);
-	if (break_state == -1)
-		up->lcr |= UART_LCR_SBC;
-	else
-		up->lcr &= ~UART_LCR_SBC;
-	serial_out(up, UART_LCR, up->lcr);
-	spin_unlock_irqrestore(&up->port.lock, flags);
-}
-
-static int serial_pxa_startup(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned long flags;
-	int retval;
-
-	if (port->line == 3) /* HWUART */
-		up->mcr |= UART_MCR_AFE;
-	else
-		up->mcr = 0;
-
-	up->port.uartclk = clk_get_rate(up->clk);
-
-	/*
-	 * Allocate the IRQ
-	 */
-	retval = request_irq(up->port.irq, serial_pxa_irq, 0, up->name, up);
-	if (retval)
-		return retval;
-
-	/*
-	 * Clear the FIFO buffers and disable them.
-	 * (they will be reenabled in set_termios())
-	 */
-	serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO);
-	serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO |
-			UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
-	serial_out(up, UART_FCR, 0);
-
-	/*
-	 * Clear the interrupt registers.
-	 */
-	(void) serial_in(up, UART_LSR);
-	(void) serial_in(up, UART_RX);
-	(void) serial_in(up, UART_IIR);
-	(void) serial_in(up, UART_MSR);
-
-	/*
-	 * Now, initialize the UART
-	 */
-	serial_out(up, UART_LCR, UART_LCR_WLEN8);
-
-	spin_lock_irqsave(&up->port.lock, flags);
-	up->port.mctrl |= TIOCM_OUT2;
-	serial_pxa_set_mctrl(&up->port, up->port.mctrl);
-	spin_unlock_irqrestore(&up->port.lock, flags);
-
-	/*
-	 * Finally, enable interrupts.  Note: Modem status interrupts
-	 * are set via set_termios(), which will be occurring imminently
-	 * anyway, so we don't enable them here.
-	 */
-	up->ier = UART_IER_RLSI | UART_IER_RDI | UART_IER_RTOIE | UART_IER_UUE;
-	serial_out(up, UART_IER, up->ier);
-
-	/*
-	 * And clear the interrupt registers again for luck.
-	 */
-	(void) serial_in(up, UART_LSR);
-	(void) serial_in(up, UART_RX);
-	(void) serial_in(up, UART_IIR);
-	(void) serial_in(up, UART_MSR);
-
-	return 0;
-}
-
-static void serial_pxa_shutdown(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned long flags;
-
-	free_irq(up->port.irq, up);
-
-	/*
-	 * Disable interrupts from this port
-	 */
-	up->ier = 0;
-	serial_out(up, UART_IER, 0);
-
-	spin_lock_irqsave(&up->port.lock, flags);
-	up->port.mctrl &= ~TIOCM_OUT2;
-	serial_pxa_set_mctrl(&up->port, up->port.mctrl);
-	spin_unlock_irqrestore(&up->port.lock, flags);
-
-	/*
-	 * Disable break condition and FIFOs
-	 */
-	serial_out(up, UART_LCR, serial_in(up, UART_LCR) & ~UART_LCR_SBC);
-	serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO |
-				  UART_FCR_CLEAR_RCVR |
-				  UART_FCR_CLEAR_XMIT);
-	serial_out(up, UART_FCR, 0);
-}
-
-static void
-serial_pxa_set_termios(struct uart_port *port, struct ktermios *termios,
-		       struct ktermios *old)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned char cval, fcr = 0;
-	unsigned long flags;
-	unsigned int baud, quot;
-	unsigned int dll;
-
-	switch (termios->c_cflag & CSIZE) {
-	case CS5:
-		cval = UART_LCR_WLEN5;
-		break;
-	case CS6:
-		cval = UART_LCR_WLEN6;
-		break;
-	case CS7:
-		cval = UART_LCR_WLEN7;
-		break;
-	default:
-	case CS8:
-		cval = UART_LCR_WLEN8;
-		break;
-	}
-
-	if (termios->c_cflag & CSTOPB)
-		cval |= UART_LCR_STOP;
-	if (termios->c_cflag & PARENB)
-		cval |= UART_LCR_PARITY;
-	if (!(termios->c_cflag & PARODD))
-		cval |= UART_LCR_EPAR;
-
-	/*
-	 * Ask the core to calculate the divisor for us.
-	 */
-	baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
-	quot = uart_get_divisor(port, baud);
-
-	if ((up->port.uartclk / quot) < (2400 * 16))
-		fcr = UART_FCR_ENABLE_FIFO | UART_FCR_PXAR1;
-	else if ((up->port.uartclk / quot) < (230400 * 16))
-		fcr = UART_FCR_ENABLE_FIFO | UART_FCR_PXAR8;
-	else
-		fcr = UART_FCR_ENABLE_FIFO | UART_FCR_PXAR32;
-
-	/*
-	 * Ok, we're now changing the port state.  Do it with
-	 * interrupts disabled.
-	 */
-	spin_lock_irqsave(&up->port.lock, flags);
-
-	/*
-	 * Ensure the port will be enabled.
-	 * This is required especially for serial console.
-	 */
-	up->ier |= UART_IER_UUE;
-
-	/*
-	 * Update the per-port timeout.
-	 */
-	uart_update_timeout(port, termios->c_cflag, baud);
-
-	up->port.read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;
-	if (termios->c_iflag & INPCK)
-		up->port.read_status_mask |= UART_LSR_FE | UART_LSR_PE;
-	if (termios->c_iflag & (BRKINT | PARMRK))
-		up->port.read_status_mask |= UART_LSR_BI;
-
-	/*
-	 * Characters to ignore
-	 */
-	up->port.ignore_status_mask = 0;
-	if (termios->c_iflag & IGNPAR)
-		up->port.ignore_status_mask |= UART_LSR_PE | UART_LSR_FE;
-	if (termios->c_iflag & IGNBRK) {
-		up->port.ignore_status_mask |= UART_LSR_BI;
-		/*
-		 * If we're ignoring parity and break indicators,
-		 * ignore overruns too (for real raw support).
-		 */
-		if (termios->c_iflag & IGNPAR)
-			up->port.ignore_status_mask |= UART_LSR_OE;
-	}
-
-	/*
-	 * ignore all characters if CREAD is not set
-	 */
-	if ((termios->c_cflag & CREAD) == 0)
-		up->port.ignore_status_mask |= UART_LSR_DR;
-
-	/*
-	 * CTS flow control flag and modem status interrupts
-	 */
-	up->ier &= ~UART_IER_MSI;
-	if (UART_ENABLE_MS(&up->port, termios->c_cflag))
-		up->ier |= UART_IER_MSI;
-
-	serial_out(up, UART_IER, up->ier);
-
-	if (termios->c_cflag & CRTSCTS)
-		up->mcr |= UART_MCR_AFE;
-	else
-		up->mcr &= ~UART_MCR_AFE;
-
-	serial_out(up, UART_LCR, cval | UART_LCR_DLAB);	/* set DLAB */
-	serial_out(up, UART_DLL, quot & 0xff);		/* LS of divisor */
-
-	/*
-	 * work around Errata #75 according to Intel(R) PXA27x Processor Family
-	 * Specification Update (Nov 2005)
-	 */
-	dll = serial_in(up, UART_DLL);
-	WARN_ON(dll != (quot & 0xff));
-
-	serial_out(up, UART_DLM, quot >> 8);		/* MS of divisor */
-	serial_out(up, UART_LCR, cval);			/* reset DLAB */
-	up->lcr = cval;					/* Save LCR */
-	serial_pxa_set_mctrl(&up->port, up->port.mctrl);
-	serial_out(up, UART_FCR, fcr);
-	spin_unlock_irqrestore(&up->port.lock, flags);
-}
-
-static void
-serial_pxa_pm(struct uart_port *port, unsigned int state,
-	      unsigned int oldstate)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	if (!state)
-		clk_prepare_enable(up->clk);
-	else
-		clk_disable_unprepare(up->clk);
-}
-
-static void serial_pxa_release_port(struct uart_port *port)
-{
-}
-
-static int serial_pxa_request_port(struct uart_port *port)
-{
-	return 0;
-}
-
-static void serial_pxa_config_port(struct uart_port *port, int flags)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	up->port.type = PORT_PXA;
-}
-
-static int
-serial_pxa_verify_port(struct uart_port *port, struct serial_struct *ser)
-{
-	/* we don't want the core code to modify any port params */
-	return -EINVAL;
-}
-
-static const char *
-serial_pxa_type(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	return up->name;
-}
-
-static struct uart_pxa_port *serial_pxa_ports[4];
-static struct uart_driver serial_pxa_reg;
-
-#ifdef CONFIG_SERIAL_PXA_CONSOLE
-
-#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
-
-/*
- *	Wait for transmitter & holding register to empty
- */
-static inline void wait_for_xmitr(struct uart_pxa_port *up)
-{
-	unsigned int status, tmout = 10000;
-
-	/* Wait up to 10ms for the character(s) to be sent. */
-	do {
-		status = serial_in(up, UART_LSR);
-
-		if (status & UART_LSR_BI)
-			up->lsr_break_flag = UART_LSR_BI;
-
-		if (--tmout == 0)
-			break;
-		udelay(1);
-	} while ((status & BOTH_EMPTY) != BOTH_EMPTY);
-
-	/* Wait up to 1s for flow control if necessary */
-	if (up->port.flags & UPF_CONS_FLOW) {
-		tmout = 1000000;
-		while (--tmout &&
-		       ((serial_in(up, UART_MSR) & UART_MSR_CTS) == 0))
-			udelay(1);
-	}
-}
-
-static void serial_pxa_console_putchar(struct uart_port *port, int ch)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	wait_for_xmitr(up);
-	serial_out(up, UART_TX, ch);
-}
-
-/*
- * Print a string to the serial port trying not to disturb
- * any possible real use of the port...
- *
- *	The console_lock must be held when we get here.
- */
-static void
-serial_pxa_console_write(struct console *co, const char *s, unsigned int count)
-{
-	struct uart_pxa_port *up = serial_pxa_ports[co->index];
-	unsigned int ier;
-	unsigned long flags;
-	int locked = 1;
-
-	clk_enable(up->clk);
-	local_irq_save(flags);
-	if (up->port.sysrq)
-		locked = 0;
-	else if (oops_in_progress)
-		locked = spin_trylock(&up->port.lock);
-	else
-		spin_lock(&up->port.lock);
-
-	/*
-	 *	First save the IER then disable the interrupts
-	 */
-	ier = serial_in(up, UART_IER);
-	serial_out(up, UART_IER, UART_IER_UUE);
-
-	uart_console_write(&up->port, s, count, serial_pxa_console_putchar);
-
-	/*
-	 *	Finally, wait for transmitter to become empty
-	 *	and restore the IER
-	 */
-	wait_for_xmitr(up);
-	serial_out(up, UART_IER, ier);
-
-	if (locked)
-		spin_unlock(&up->port.lock);
-	local_irq_restore(flags);
-	clk_disable(up->clk);
-
-}
-
-#ifdef CONFIG_CONSOLE_POLL
-/*
- * Console polling routines for writing and reading from the uart while
- * in an interrupt or debug context.
- */
-
-static int serial_pxa_get_poll_char(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned char lsr = serial_in(up, UART_LSR);
-
-	while (!(lsr & UART_LSR_DR))
-		lsr = serial_in(up, UART_LSR);
-
-	return serial_in(up, UART_RX);
-}
-
-
-static void serial_pxa_put_poll_char(struct uart_port *port,
-			 unsigned char c)
-{
-	unsigned int ier;
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	/*
-	 *	First save the IER then disable the interrupts
-	 */
-	ier = serial_in(up, UART_IER);
-	serial_out(up, UART_IER, UART_IER_UUE);
-
-	wait_for_xmitr(up);
-	/*
-	 *	Send the character out.
-	 *	If a LF, also do CR...
-	 */
-	serial_out(up, UART_TX, c);
-	if (c == 10) {
-		wait_for_xmitr(up);
-		serial_out(up, UART_TX, 13);
-	}
-
-	/*
-	 *	Finally, wait for transmitter to become empty
-	 *	and restore the IER
-	 */
-	wait_for_xmitr(up);
-	serial_out(up, UART_IER, ier);
-}
-
-#endif /* CONFIG_CONSOLE_POLL */
-
-static int __init
-serial_pxa_console_setup(struct console *co, char *options)
-{
-	struct uart_pxa_port *up;
-	int baud = 9600;
-	int bits = 8;
-	int parity = 'n';
-	int flow = 'n';
-
-	if (co->index == -1 || co->index >= serial_pxa_reg.nr)
-		co->index = 0;
-	up = serial_pxa_ports[co->index];
-	if (!up)
-		return -ENODEV;
-
-	if (options)
-		uart_parse_options(options, &baud, &parity, &bits, &flow);
-
-	return uart_set_options(&up->port, co, baud, parity, bits, flow);
-}
-
-static struct console serial_pxa_console = {
-	.name		= "ttyS",
-	.write		= serial_pxa_console_write,
-	.device		= uart_console_device,
-	.setup		= serial_pxa_console_setup,
-	.flags		= CON_PRINTBUFFER,
-	.index		= -1,
-	.data		= &serial_pxa_reg,
-};
-
-#define PXA_CONSOLE	&serial_pxa_console
-#else
-#define PXA_CONSOLE	NULL
-#endif
-
-static struct uart_ops serial_pxa_pops = {
-	.tx_empty	= serial_pxa_tx_empty,
-	.set_mctrl	= serial_pxa_set_mctrl,
-	.get_mctrl	= serial_pxa_get_mctrl,
-	.stop_tx	= serial_pxa_stop_tx,
-	.start_tx	= serial_pxa_start_tx,
-	.stop_rx	= serial_pxa_stop_rx,
-	.enable_ms	= serial_pxa_enable_ms,
-	.break_ctl	= serial_pxa_break_ctl,
-	.startup	= serial_pxa_startup,
-	.shutdown	= serial_pxa_shutdown,
-	.set_termios	= serial_pxa_set_termios,
-	.pm		= serial_pxa_pm,
-	.type		= serial_pxa_type,
-	.release_port	= serial_pxa_release_port,
-	.request_port	= serial_pxa_request_port,
-	.config_port	= serial_pxa_config_port,
-	.verify_port	= serial_pxa_verify_port,
-#ifdef CONFIG_CONSOLE_POLL
-	.poll_get_char = serial_pxa_get_poll_char,
-	.poll_put_char = serial_pxa_put_poll_char,
-#endif
-};
-
-static struct uart_driver serial_pxa_reg = {
-	.owner		= THIS_MODULE,
-	.driver_name	= "PXA serial",
-	.dev_name	= "ttyS",
-	.major		= TTY_MAJOR,
-	.minor		= 64,
-	.nr		= 4,
-	.cons		= PXA_CONSOLE,
-};
-
-#ifdef CONFIG_PM
-static int serial_pxa_suspend(struct device *dev)
-{
-        struct uart_pxa_port *sport = dev_get_drvdata(dev);
-
-        if (sport)
-                uart_suspend_port(&serial_pxa_reg, &sport->port);
-
-        return 0;
-}
-
-static int serial_pxa_resume(struct device *dev)
-{
-        struct uart_pxa_port *sport = dev_get_drvdata(dev);
-
-        if (sport)
-                uart_resume_port(&serial_pxa_reg, &sport->port);
-
-        return 0;
-}
-
-static const struct dev_pm_ops serial_pxa_pm_ops = {
-	.suspend	= serial_pxa_suspend,
-	.resume		= serial_pxa_resume,
-};
-#endif
-
-static struct of_device_id serial_pxa_dt_ids[] = {
-	{ .compatible = "mrvl,pxa-uart", },
-	{ .compatible = "mrvl,mmp-uart", },
-	{}
-};
-MODULE_DEVICE_TABLE(of, serial_pxa_dt_ids);
-
-static int serial_pxa_probe_dt(struct platform_device *pdev,
-			       struct uart_pxa_port *sport)
-{
-	struct device_node *np = pdev->dev.of_node;
-	int ret;
-
-	if (!np)
-		return 1;
-
-	ret = of_alias_get_id(np, "serial");
-	if (ret < 0) {
-		dev_err(&pdev->dev, "failed to get alias id, errno %d\n", ret);
-		return ret;
-	}
-	sport->port.line = ret;
-	return 0;
-}
-
-static int serial_pxa_probe(struct platform_device *dev)
-{
-	struct uart_pxa_port *sport;
-	struct resource *mmres, *irqres;
-	int ret;
-
-	mmres = platform_get_resource(dev, IORESOURCE_MEM, 0);
-	irqres = platform_get_resource(dev, IORESOURCE_IRQ, 0);
-	if (!mmres || !irqres)
-		return -ENODEV;
-
-	sport = kzalloc(sizeof(struct uart_pxa_port), GFP_KERNEL);
-	if (!sport)
-		return -ENOMEM;
-
-	sport->clk = clk_get(&dev->dev, NULL);
-	if (IS_ERR(sport->clk)) {
-		ret = PTR_ERR(sport->clk);
-		goto err_free;
-	}
-
-	ret = clk_prepare(sport->clk);
-	if (ret) {
-		clk_put(sport->clk);
-		goto err_free;
-	}
-
-	sport->port.type = PORT_PXA;
-	sport->port.iotype = UPIO_MEM;
-	sport->port.mapbase = mmres->start;
-	sport->port.irq = irqres->start;
-	sport->port.fifosize = 64;
-	sport->port.ops = &serial_pxa_pops;
-	sport->port.dev = &dev->dev;
-	sport->port.flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF;
-	sport->port.uartclk = clk_get_rate(sport->clk);
-
-	ret = serial_pxa_probe_dt(dev, sport);
-	if (ret > 0)
-		sport->port.line = dev->id;
-	else if (ret < 0)
-		goto err_clk;
-	snprintf(sport->name, PXA_NAME_LEN - 1, "UART%d", sport->port.line + 1);
-
-	sport->port.membase = ioremap(mmres->start, resource_size(mmres));
-	if (!sport->port.membase) {
-		ret = -ENOMEM;
-		goto err_clk;
-	}
-
-	serial_pxa_ports[sport->port.line] = sport;
-
-	uart_add_one_port(&serial_pxa_reg, &sport->port);
-	platform_set_drvdata(dev, sport);
-
-	return 0;
-
- err_clk:
-	clk_unprepare(sport->clk);
-	clk_put(sport->clk);
- err_free:
-	kfree(sport);
-	return ret;
-}
-
-static int serial_pxa_remove(struct platform_device *dev)
-{
-	struct uart_pxa_port *sport = platform_get_drvdata(dev);
-
-	uart_remove_one_port(&serial_pxa_reg, &sport->port);
-
-	clk_unprepare(sport->clk);
-	clk_put(sport->clk);
-	kfree(sport);
-
-	return 0;
-}
-
-static struct platform_driver serial_pxa_driver = {
-        .probe          = serial_pxa_probe,
-        .remove         = serial_pxa_remove,
-
-	.driver		= {
-	        .name	= "pxa2xx-uart",
-		.owner	= THIS_MODULE,
-#ifdef CONFIG_PM
-		.pm	= &serial_pxa_pm_ops,
-#endif
-		.of_match_table = serial_pxa_dt_ids,
-	},
-};
-
-static int __init serial_pxa_init(void)
-{
-	int ret;
-
-	ret = uart_register_driver(&serial_pxa_reg);
-	if (ret != 0)
-		return ret;
-
-	ret = platform_driver_register(&serial_pxa_driver);
-	if (ret != 0)
-		uart_unregister_driver(&serial_pxa_reg);
-
-	return ret;
-}
-
-static void __exit serial_pxa_exit(void)
-{
-	platform_driver_unregister(&serial_pxa_driver);
-	uart_unregister_driver(&serial_pxa_reg);
-}
-
-module_init(serial_pxa_init);
-module_exit(serial_pxa_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:pxa2xx-uart");
-- 
1.8.4.2

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

* [PATCH v3 02/21] ARM: dts: pxa2xx fix compatible strings
  2013-12-17 19:37           ` Sergei Ianovich
  (?)
@ 2013-12-17 19:37             ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-17 19:37 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Daniel Mack, Arnd Bergmann, Rob Herring,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala, Russell King,
	open list:OPEN FIRMWARE AND...

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Daniel Mack <zonque@gmail.com>
CC: Arnd Bergmann <arnd@arndb.de>
---
   v2..v3
   v1..v2
   * no changes

 arch/arm/boot/dts/pxa2xx.dtsi | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/arch/arm/boot/dts/pxa2xx.dtsi b/arch/arm/boot/dts/pxa2xx.dtsi
index a5e90f0..3419f87 100644
--- a/arch/arm/boot/dts/pxa2xx.dtsi
+++ b/arch/arm/boot/dts/pxa2xx.dtsi
@@ -18,7 +18,6 @@
 		serial1 = &btuart;
 		serial2 = &stuart;
 		serial3 = &hwuart;
-		i2c0 = &pwri2c;
 		i2c1 = &pxai2c1;
 	};
 
@@ -113,14 +112,14 @@
 		};
 
 		usb0: ohci@4c000000 {
-			compatible = "mrvl,pxa-ohci";
+			compatible = "marvell,pxa-ohci";
 			reg = <0x4c000000 0x10000>;
 			interrupts = <3>;
 			status = "disabled";
 		};
 
 		mmc0: mmc@41100000 {
-			compatible = "mrvl,pxa-mmc";
+			compatible = "marvell,pxa-mmc";
 			reg = <0x41100000 0x1000>;
 			interrupts = <23>;
 			status = "disabled";
-- 
1.8.4.2


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

* [PATCH v3 02/21] ARM: dts: pxa2xx fix compatible strings
@ 2013-12-17 19:37             ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-17 19:37 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Daniel Mack, Arnd Bergmann, Rob Herring,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala, Russell King,
	open list:OPEN FIRMWARE AND...

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Daniel Mack <zonque@gmail.com>
CC: Arnd Bergmann <arnd@arndb.de>
---
   v2..v3
   v1..v2
   * no changes

 arch/arm/boot/dts/pxa2xx.dtsi | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/arch/arm/boot/dts/pxa2xx.dtsi b/arch/arm/boot/dts/pxa2xx.dtsi
index a5e90f0..3419f87 100644
--- a/arch/arm/boot/dts/pxa2xx.dtsi
+++ b/arch/arm/boot/dts/pxa2xx.dtsi
@@ -18,7 +18,6 @@
 		serial1 = &btuart;
 		serial2 = &stuart;
 		serial3 = &hwuart;
-		i2c0 = &pwri2c;
 		i2c1 = &pxai2c1;
 	};
 
@@ -113,14 +112,14 @@
 		};
 
 		usb0: ohci@4c000000 {
-			compatible = "mrvl,pxa-ohci";
+			compatible = "marvell,pxa-ohci";
 			reg = <0x4c000000 0x10000>;
 			interrupts = <3>;
 			status = "disabled";
 		};
 
 		mmc0: mmc@41100000 {
-			compatible = "mrvl,pxa-mmc";
+			compatible = "marvell,pxa-mmc";
 			reg = <0x41100000 0x1000>;
 			interrupts = <23>;
 			status = "disabled";
-- 
1.8.4.2

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

* [PATCH v3 02/21] ARM: dts: pxa2xx fix compatible strings
@ 2013-12-17 19:37             ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-17 19:37 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Daniel Mack <zonque@gmail.com>
CC: Arnd Bergmann <arnd@arndb.de>
---
   v2..v3
   v1..v2
   * no changes

 arch/arm/boot/dts/pxa2xx.dtsi | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/arch/arm/boot/dts/pxa2xx.dtsi b/arch/arm/boot/dts/pxa2xx.dtsi
index a5e90f0..3419f87 100644
--- a/arch/arm/boot/dts/pxa2xx.dtsi
+++ b/arch/arm/boot/dts/pxa2xx.dtsi
@@ -18,7 +18,6 @@
 		serial1 = &btuart;
 		serial2 = &stuart;
 		serial3 = &hwuart;
-		i2c0 = &pwri2c;
 		i2c1 = &pxai2c1;
 	};
 
@@ -113,14 +112,14 @@
 		};
 
 		usb0: ohci at 4c000000 {
-			compatible = "mrvl,pxa-ohci";
+			compatible = "marvell,pxa-ohci";
 			reg = <0x4c000000 0x10000>;
 			interrupts = <3>;
 			status = "disabled";
 		};
 
 		mmc0: mmc at 41100000 {
-			compatible = "mrvl,pxa-mmc";
+			compatible = "marvell,pxa-mmc";
 			reg = <0x41100000 0x1000>;
 			interrupts = <23>;
 			status = "disabled";
-- 
1.8.4.2

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

* [PATCH v3 03/21] ARM: dts: fix pxa27x-gpio interrupts
@ 2013-12-17 19:37             ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-17 19:37 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Daniel Mack, Arnd Bergmann, Rob Herring,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala, Russell King,
	open list:OPEN FIRMWARE AND...

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Daniel Mack <zonque@gmail.com>
CC: Arnd Bergmann <arnd@arndb.de>
---
   v2..v3
   v1..v2
   * no changes

 arch/arm/boot/dts/pxa27x.dtsi | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/arch/arm/boot/dts/pxa27x.dtsi b/arch/arm/boot/dts/pxa27x.dtsi
index d7c5d72..44df554 100644
--- a/arch/arm/boot/dts/pxa27x.dtsi
+++ b/arch/arm/boot/dts/pxa27x.dtsi
@@ -10,5 +10,11 @@
 			marvell,intc-priority;
 			marvell,intc-nr-irqs = <34>;
 		};
+
+		gpio: gpio@40e00000 {
+			compatible = "intel,pxa27x-gpio";
+			interrupts = <8>, <9>, <10>;
+			interrupt-names = "gpio0", "gpio1", "gpio_mux";
+		};
 	};
 };
-- 
1.8.4.2


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

* [PATCH v3 03/21] ARM: dts: fix pxa27x-gpio interrupts
@ 2013-12-17 19:37             ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-17 19:37 UTC (permalink / raw)
  To: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
  Cc: Sergei Ianovich, Daniel Mack, Arnd Bergmann, Rob Herring,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala, Russell King,
	open list:OPEN FIRMWARE AND...

Signed-off-by: Sergei Ianovich <ynvich-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
CC: Daniel Mack <zonque-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
CC: Arnd Bergmann <arnd-r2nGTMty4D4@public.gmane.org>
---
   v2..v3
   v1..v2
   * no changes

 arch/arm/boot/dts/pxa27x.dtsi | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/arch/arm/boot/dts/pxa27x.dtsi b/arch/arm/boot/dts/pxa27x.dtsi
index d7c5d72..44df554 100644
--- a/arch/arm/boot/dts/pxa27x.dtsi
+++ b/arch/arm/boot/dts/pxa27x.dtsi
@@ -10,5 +10,11 @@
 			marvell,intc-priority;
 			marvell,intc-nr-irqs = <34>;
 		};
+
+		gpio: gpio@40e00000 {
+			compatible = "intel,pxa27x-gpio";
+			interrupts = <8>, <9>, <10>;
+			interrupt-names = "gpio0", "gpio1", "gpio_mux";
+		};
 	};
 };
-- 
1.8.4.2

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH v3 03/21] ARM: dts: fix pxa27x-gpio interrupts
@ 2013-12-17 19:37             ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-17 19:37 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Daniel Mack <zonque@gmail.com>
CC: Arnd Bergmann <arnd@arndb.de>
---
   v2..v3
   v1..v2
   * no changes

 arch/arm/boot/dts/pxa27x.dtsi | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/arch/arm/boot/dts/pxa27x.dtsi b/arch/arm/boot/dts/pxa27x.dtsi
index d7c5d72..44df554 100644
--- a/arch/arm/boot/dts/pxa27x.dtsi
+++ b/arch/arm/boot/dts/pxa27x.dtsi
@@ -10,5 +10,11 @@
 			marvell,intc-priority;
 			marvell,intc-nr-irqs = <34>;
 		};
+
+		gpio: gpio at 40e00000 {
+			compatible = "intel,pxa27x-gpio";
+			interrupts = <8>, <9>, <10>;
+			interrupt-names = "gpio0", "gpio1", "gpio_mux";
+		};
 	};
 };
-- 
1.8.4.2

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

* [PATCH v3 04/21] ARM: dts: pxa3xx: move declaration to header
  2013-12-17 19:37           ` Sergei Ianovich
@ 2013-12-17 19:37             ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-17 19:37 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Daniel Mack, Arnd Bergmann, Eric Miao,
	Russell King, Haojian Zhuang

This way it will be more difficult to change the declaration in one
place, but not the other.

In addition, the change allows to use the binding for pxa-gpio on
other PXA CPUs.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Daniel Mack <zonque@gmail.com>
CC: Arnd Bergmann <arnd@arndb.de>
---
   v2..v3
   * no changes

   v1..v2
   * drop #ifdef in header file
   * number changed from 6 to 4 (dropped patches)

 arch/arm/mach-pxa/include/mach/irqs.h | 2 ++
 arch/arm/mach-pxa/pxa3xx.c            | 2 --
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-pxa/include/mach/irqs.h b/arch/arm/mach-pxa/include/mach/irqs.h
index 48c2fd8..732315d 100644
--- a/arch/arm/mach-pxa/include/mach/irqs.h
+++ b/arch/arm/mach-pxa/include/mach/irqs.h
@@ -113,4 +113,6 @@ void ichp_handle_irq(struct pt_regs *);
 void pxa_init_irq(int irq_nr, int (*set_wake)(struct irq_data *, unsigned int));
 #endif
 
+extern void __init pxa_dt_irq_init(int (*fn)(struct irq_data *, unsigned int));
+
 #endif /* __ASM_MACH_IRQS_H */
diff --git a/arch/arm/mach-pxa/pxa3xx.c b/arch/arm/mach-pxa/pxa3xx.c
index 87011f3..2397dec 100644
--- a/arch/arm/mach-pxa/pxa3xx.c
+++ b/arch/arm/mach-pxa/pxa3xx.c
@@ -42,8 +42,6 @@
 #define PECR_IE(n)	((1 << ((n) * 2)) << 28)
 #define PECR_IS(n)	((1 << ((n) * 2)) << 29)
 
-extern void __init pxa_dt_irq_init(int (*fn)(struct irq_data *, unsigned int));
-
 static DEFINE_PXA3_CKEN(pxa3xx_ffuart, FFUART, 14857000, 1);
 static DEFINE_PXA3_CKEN(pxa3xx_btuart, BTUART, 14857000, 1);
 static DEFINE_PXA3_CKEN(pxa3xx_stuart, STUART, 14857000, 1);
-- 
1.8.4.2


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

* [PATCH v3 04/21] ARM: dts: pxa3xx: move declaration to header
@ 2013-12-17 19:37             ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-17 19:37 UTC (permalink / raw)
  To: linux-arm-kernel

This way it will be more difficult to change the declaration in one
place, but not the other.

In addition, the change allows to use the binding for pxa-gpio on
other PXA CPUs.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Daniel Mack <zonque@gmail.com>
CC: Arnd Bergmann <arnd@arndb.de>
---
   v2..v3
   * no changes

   v1..v2
   * drop #ifdef in header file
   * number changed from 6 to 4 (dropped patches)

 arch/arm/mach-pxa/include/mach/irqs.h | 2 ++
 arch/arm/mach-pxa/pxa3xx.c            | 2 --
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-pxa/include/mach/irqs.h b/arch/arm/mach-pxa/include/mach/irqs.h
index 48c2fd8..732315d 100644
--- a/arch/arm/mach-pxa/include/mach/irqs.h
+++ b/arch/arm/mach-pxa/include/mach/irqs.h
@@ -113,4 +113,6 @@ void ichp_handle_irq(struct pt_regs *);
 void pxa_init_irq(int irq_nr, int (*set_wake)(struct irq_data *, unsigned int));
 #endif
 
+extern void __init pxa_dt_irq_init(int (*fn)(struct irq_data *, unsigned int));
+
 #endif /* __ASM_MACH_IRQS_H */
diff --git a/arch/arm/mach-pxa/pxa3xx.c b/arch/arm/mach-pxa/pxa3xx.c
index 87011f3..2397dec 100644
--- a/arch/arm/mach-pxa/pxa3xx.c
+++ b/arch/arm/mach-pxa/pxa3xx.c
@@ -42,8 +42,6 @@
 #define PECR_IE(n)	((1 << ((n) * 2)) << 28)
 #define PECR_IS(n)	((1 << ((n) * 2)) << 29)
 
-extern void __init pxa_dt_irq_init(int (*fn)(struct irq_data *, unsigned int));
-
 static DEFINE_PXA3_CKEN(pxa3xx_ffuart, FFUART, 14857000, 1);
 static DEFINE_PXA3_CKEN(pxa3xx_btuart, BTUART, 14857000, 1);
 static DEFINE_PXA3_CKEN(pxa3xx_stuart, STUART, 14857000, 1);
-- 
1.8.4.2

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

* [PATCH v3 05/21] ARM: dts: pxa27x: irq init using device tree
  2013-12-17 19:37           ` Sergei Ianovich
@ 2013-12-17 19:37             ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-17 19:37 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Daniel Mack, Arnd Bergmann, Eric Miao,
	Russell King, Haojian Zhuang

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Daniel Mack <zonque@gmail.com>
CC: Arnd Bergmann <arnd@arndb.de>
---
   v2..v3
   * no changes

   v1..v2
   * use of_have_populated_dt() instead of a static variable
   * drop #ifdef in header file
   * number changed from 8 to 5 (dropped patches)

 arch/arm/mach-pxa/include/mach/pxa27x.h |  1 +
 arch/arm/mach-pxa/pxa27x.c              | 10 ++++++++++
 2 files changed, 11 insertions(+)

diff --git a/arch/arm/mach-pxa/include/mach/pxa27x.h b/arch/arm/mach-pxa/include/mach/pxa27x.h
index 7cff640..34a4d6f 100644
--- a/arch/arm/mach-pxa/include/mach/pxa27x.h
+++ b/arch/arm/mach-pxa/include/mach/pxa27x.h
@@ -23,6 +23,7 @@ extern void __init pxa27x_map_io(void);
 extern void __init pxa27x_init_irq(void);
 extern int __init pxa27x_set_pwrmode(unsigned int mode);
 extern void pxa27x_cpu_pm_enter(suspend_state_t state);
+extern void __init pxa27x_dt_init_irq(void);
 
 #define pxa27x_handle_irq	ichp_handle_irq
 
diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c
index 301471a..c6b54f8 100644
--- a/arch/arm/mach-pxa/pxa27x.c
+++ b/arch/arm/mach-pxa/pxa27x.c
@@ -398,6 +398,13 @@ void __init pxa27x_init_irq(void)
 	pxa_init_irq(34, pxa27x_set_wake);
 }
 
+#ifdef CONFIG_OF
+void __init pxa27x_dt_init_irq(void)
+{
+	pxa_dt_irq_init(pxa27x_set_wake);
+}
+#endif  /* CONFIG_OF */
+
 static struct map_desc pxa27x_io_desc[] __initdata = {
 	{	/* Mem Ctl */
 		.virtual	= (unsigned long)SMEMC_VIRT,
@@ -471,6 +478,9 @@ static int __init pxa27x_init(void)
 		register_syscore_ops(&pxa2xx_mfp_syscore_ops);
 		register_syscore_ops(&pxa2xx_clock_syscore_ops);
 
+		if (of_have_populated_dt())
+			return 0;
+
 		pxa_register_device(&pxa27x_device_gpio, &pxa27x_gpio_info);
 		ret = platform_add_devices(devices, ARRAY_SIZE(devices));
 	}
-- 
1.8.4.2


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

* [PATCH v3 05/21] ARM: dts: pxa27x: irq init using device tree
@ 2013-12-17 19:37             ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-17 19:37 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Daniel Mack <zonque@gmail.com>
CC: Arnd Bergmann <arnd@arndb.de>
---
   v2..v3
   * no changes

   v1..v2
   * use of_have_populated_dt() instead of a static variable
   * drop #ifdef in header file
   * number changed from 8 to 5 (dropped patches)

 arch/arm/mach-pxa/include/mach/pxa27x.h |  1 +
 arch/arm/mach-pxa/pxa27x.c              | 10 ++++++++++
 2 files changed, 11 insertions(+)

diff --git a/arch/arm/mach-pxa/include/mach/pxa27x.h b/arch/arm/mach-pxa/include/mach/pxa27x.h
index 7cff640..34a4d6f 100644
--- a/arch/arm/mach-pxa/include/mach/pxa27x.h
+++ b/arch/arm/mach-pxa/include/mach/pxa27x.h
@@ -23,6 +23,7 @@ extern void __init pxa27x_map_io(void);
 extern void __init pxa27x_init_irq(void);
 extern int __init pxa27x_set_pwrmode(unsigned int mode);
 extern void pxa27x_cpu_pm_enter(suspend_state_t state);
+extern void __init pxa27x_dt_init_irq(void);
 
 #define pxa27x_handle_irq	ichp_handle_irq
 
diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c
index 301471a..c6b54f8 100644
--- a/arch/arm/mach-pxa/pxa27x.c
+++ b/arch/arm/mach-pxa/pxa27x.c
@@ -398,6 +398,13 @@ void __init pxa27x_init_irq(void)
 	pxa_init_irq(34, pxa27x_set_wake);
 }
 
+#ifdef CONFIG_OF
+void __init pxa27x_dt_init_irq(void)
+{
+	pxa_dt_irq_init(pxa27x_set_wake);
+}
+#endif  /* CONFIG_OF */
+
 static struct map_desc pxa27x_io_desc[] __initdata = {
 	{	/* Mem Ctl */
 		.virtual	= (unsigned long)SMEMC_VIRT,
@@ -471,6 +478,9 @@ static int __init pxa27x_init(void)
 		register_syscore_ops(&pxa2xx_mfp_syscore_ops);
 		register_syscore_ops(&pxa2xx_clock_syscore_ops);
 
+		if (of_have_populated_dt())
+			return 0;
+
 		pxa_register_device(&pxa27x_device_gpio, &pxa27x_gpio_info);
 		ret = platform_add_devices(devices, ARRAY_SIZE(devices));
 	}
-- 
1.8.4.2

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

* [PATCH v3 06/21] ARM: dts: provide DMA config to pxamci on PXA27x
  2013-12-17 19:37           ` Sergei Ianovich
  (?)
@ 2013-12-17 19:37             ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-17 19:37 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Daniel Mack, Arnd Bergmann, Rob Herring,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala, Rob Landley,
	Russell King, open list:OPEN FIRMWARE AND...,
	open list:DOCUMENTATION

Non-dts implementation supply required DMA channel numbers as
IORESOURCE_DMA. We can also get them from the device tree, if it
is present.

This patch updates device tree with the proper dmaengine-based
"marvell,pdma-1.0" DMA.

There is no actual data handling in this patch, because the existing
driver cannot get DMA channel number from dmaengine API. The patch
in the series will provide temporary workaround by manually parsing
node attributes, until Daniel's series is ready to be merged.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Daniel Mack <zonque@gmail.com>
CC: Arnd Bergmann <arnd@arndb.de>
---
   v2..v3
   * split into good (this one) and temporary (PATCH 07/21) parts

   v1..v2
   * add binding for next-gen dma controller
   * use correct dma declararion
   * number changed from 5 to 3

 Documentation/devicetree/bindings/mmc/pxa-mmc.txt |  5 +++++
 arch/arm/boot/dts/pxa27x.dtsi                     | 14 ++++++++++++++
 2 files changed, 19 insertions(+)

diff --git a/Documentation/devicetree/bindings/mmc/pxa-mmc.txt b/Documentation/devicetree/bindings/mmc/pxa-mmc.txt
index b7025de..9f54c69 100644
--- a/Documentation/devicetree/bindings/mmc/pxa-mmc.txt
+++ b/Documentation/devicetree/bindings/mmc/pxa-mmc.txt
@@ -5,6 +5,8 @@ Driver bindings for the PXA MCI (MMC/SDIO) interfaces
 Required properties:
 - compatible: Should be "marvell,pxa-mmc".
 - vmmc-supply: A regulator for VMMC
+- dmas: Should be DMA specifiers for RX and TX
+- dma-names: Should be "rx" and "tx"
 
 Optional properties:
 - marvell,detect-delay-ms: sets the detection delay timeout in ms.
@@ -21,5 +23,8 @@ mmc0: mmc@41100000 {
 	interrupts = <23>;
 	cd-gpios = <&gpio 23 0>;
 	wp-gpios = <&gpio 24 0>;
+	dmas = <&dma 21
+		&dma 22>;
+	dma-names = "rx", "tx";
 };
 
diff --git a/arch/arm/boot/dts/pxa27x.dtsi b/arch/arm/boot/dts/pxa27x.dtsi
index 44df554..c2a90c5 100644
--- a/arch/arm/boot/dts/pxa27x.dtsi
+++ b/arch/arm/boot/dts/pxa27x.dtsi
@@ -11,10 +11,24 @@
 			marvell,intc-nr-irqs = <34>;
 		};
 
+		dma: dma-controller@40000000 {
+			compatible = "marvell,pdma-1.0";
+			reg = <0x40000000 0x10000>;
+			interrupts = <25>;
+			#dma-cells = <1>;
+			dma-channels = <32>;
+		};
+
 		gpio: gpio@40e00000 {
 			compatible = "intel,pxa27x-gpio";
 			interrupts = <8>, <9>, <10>;
 			interrupt-names = "gpio0", "gpio1", "gpio_mux";
 		};
+
+		mmc@41100000 {
+			dmas = <&dma 21
+				&dma 22>;
+			dma-names = "rx", "tx";
+		};
 	};
 };
-- 
1.8.4.2


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

* [PATCH v3 06/21] ARM: dts: provide DMA config to pxamci on PXA27x
@ 2013-12-17 19:37             ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-17 19:37 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Daniel Mack, Arnd Bergmann, Rob Herring,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala, Rob Landley,
	Russell King, open list:OPEN FIRMWARE AND...,
	open list:DOCUMENTATION

Non-dts implementation supply required DMA channel numbers as
IORESOURCE_DMA. We can also get them from the device tree, if it
is present.

This patch updates device tree with the proper dmaengine-based
"marvell,pdma-1.0" DMA.

There is no actual data handling in this patch, because the existing
driver cannot get DMA channel number from dmaengine API. The patch
in the series will provide temporary workaround by manually parsing
node attributes, until Daniel's series is ready to be merged.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Daniel Mack <zonque@gmail.com>
CC: Arnd Bergmann <arnd@arndb.de>
---
   v2..v3
   * split into good (this one) and temporary (PATCH 07/21) parts

   v1..v2
   * add binding for next-gen dma controller
   * use correct dma declararion
   * number changed from 5 to 3

 Documentation/devicetree/bindings/mmc/pxa-mmc.txt |  5 +++++
 arch/arm/boot/dts/pxa27x.dtsi                     | 14 ++++++++++++++
 2 files changed, 19 insertions(+)

diff --git a/Documentation/devicetree/bindings/mmc/pxa-mmc.txt b/Documentation/devicetree/bindings/mmc/pxa-mmc.txt
index b7025de..9f54c69 100644
--- a/Documentation/devicetree/bindings/mmc/pxa-mmc.txt
+++ b/Documentation/devicetree/bindings/mmc/pxa-mmc.txt
@@ -5,6 +5,8 @@ Driver bindings for the PXA MCI (MMC/SDIO) interfaces
 Required properties:
 - compatible: Should be "marvell,pxa-mmc".
 - vmmc-supply: A regulator for VMMC
+- dmas: Should be DMA specifiers for RX and TX
+- dma-names: Should be "rx" and "tx"
 
 Optional properties:
 - marvell,detect-delay-ms: sets the detection delay timeout in ms.
@@ -21,5 +23,8 @@ mmc0: mmc@41100000 {
 	interrupts = <23>;
 	cd-gpios = <&gpio 23 0>;
 	wp-gpios = <&gpio 24 0>;
+	dmas = <&dma 21
+		&dma 22>;
+	dma-names = "rx", "tx";
 };
 
diff --git a/arch/arm/boot/dts/pxa27x.dtsi b/arch/arm/boot/dts/pxa27x.dtsi
index 44df554..c2a90c5 100644
--- a/arch/arm/boot/dts/pxa27x.dtsi
+++ b/arch/arm/boot/dts/pxa27x.dtsi
@@ -11,10 +11,24 @@
 			marvell,intc-nr-irqs = <34>;
 		};
 
+		dma: dma-controller@40000000 {
+			compatible = "marvell,pdma-1.0";
+			reg = <0x40000000 0x10000>;
+			interrupts = <25>;
+			#dma-cells = <1>;
+			dma-channels = <32>;
+		};
+
 		gpio: gpio@40e00000 {
 			compatible = "intel,pxa27x-gpio";
 			interrupts = <8>, <9>, <10>;
 			interrupt-names = "gpio0", "gpio1", "gpio_mux";
 		};
+
+		mmc@41100000 {
+			dmas = <&dma 21
+				&dma 22>;
+			dma-names = "rx", "tx";
+		};
 	};
 };
-- 
1.8.4.2

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

* [PATCH v3 06/21] ARM: dts: provide DMA config to pxamci on PXA27x
@ 2013-12-17 19:37             ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-17 19:37 UTC (permalink / raw)
  To: linux-arm-kernel

Non-dts implementation supply required DMA channel numbers as
IORESOURCE_DMA. We can also get them from the device tree, if it
is present.

This patch updates device tree with the proper dmaengine-based
"marvell,pdma-1.0" DMA.

There is no actual data handling in this patch, because the existing
driver cannot get DMA channel number from dmaengine API. The patch
in the series will provide temporary workaround by manually parsing
node attributes, until Daniel's series is ready to be merged.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Daniel Mack <zonque@gmail.com>
CC: Arnd Bergmann <arnd@arndb.de>
---
   v2..v3
   * split into good (this one) and temporary (PATCH 07/21) parts

   v1..v2
   * add binding for next-gen dma controller
   * use correct dma declararion
   * number changed from 5 to 3

 Documentation/devicetree/bindings/mmc/pxa-mmc.txt |  5 +++++
 arch/arm/boot/dts/pxa27x.dtsi                     | 14 ++++++++++++++
 2 files changed, 19 insertions(+)

diff --git a/Documentation/devicetree/bindings/mmc/pxa-mmc.txt b/Documentation/devicetree/bindings/mmc/pxa-mmc.txt
index b7025de..9f54c69 100644
--- a/Documentation/devicetree/bindings/mmc/pxa-mmc.txt
+++ b/Documentation/devicetree/bindings/mmc/pxa-mmc.txt
@@ -5,6 +5,8 @@ Driver bindings for the PXA MCI (MMC/SDIO) interfaces
 Required properties:
 - compatible: Should be "marvell,pxa-mmc".
 - vmmc-supply: A regulator for VMMC
+- dmas: Should be DMA specifiers for RX and TX
+- dma-names: Should be "rx" and "tx"
 
 Optional properties:
 - marvell,detect-delay-ms: sets the detection delay timeout in ms.
@@ -21,5 +23,8 @@ mmc0: mmc at 41100000 {
 	interrupts = <23>;
 	cd-gpios = <&gpio 23 0>;
 	wp-gpios = <&gpio 24 0>;
+	dmas = <&dma 21
+		&dma 22>;
+	dma-names = "rx", "tx";
 };
 
diff --git a/arch/arm/boot/dts/pxa27x.dtsi b/arch/arm/boot/dts/pxa27x.dtsi
index 44df554..c2a90c5 100644
--- a/arch/arm/boot/dts/pxa27x.dtsi
+++ b/arch/arm/boot/dts/pxa27x.dtsi
@@ -11,10 +11,24 @@
 			marvell,intc-nr-irqs = <34>;
 		};
 
+		dma: dma-controller at 40000000 {
+			compatible = "marvell,pdma-1.0";
+			reg = <0x40000000 0x10000>;
+			interrupts = <25>;
+			#dma-cells = <1>;
+			dma-channels = <32>;
+		};
+
 		gpio: gpio at 40e00000 {
 			compatible = "intel,pxa27x-gpio";
 			interrupts = <8>, <9>, <10>;
 			interrupt-names = "gpio0", "gpio1", "gpio_mux";
 		};
+
+		mmc at 41100000 {
+			dmas = <&dma 21
+				&dma 22>;
+			dma-names = "rx", "tx";
+		};
 	};
 };
-- 
1.8.4.2

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

* [PATCH v3 07/21] ARM: dts: parse DMA config in pxamci
  2013-12-17 19:37           ` Sergei Ianovich
@ 2013-12-17 19:37             ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-17 19:37 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Daniel Mack, Arnd Bergmann, Chris Ball,
	Mark Brown, Ulf Hansson, Jingoo Han, Adrian Hunter, linux-mmc

The existing PXA MMC driver cannot get DMA channels in a proper
way from the respective device tree binding.

This patch provides temporary workaround which allows using the
existing driver in DT machines by pointing to the proper
dmaengine-based "marvell,pdma-1.0" DMA.

Even though the new DMA provider is not present we can parse device node
attributes manually and use channel numbers to acquire DMA channel
from the existing non-dmaengine provider.

When Daniel's DMA series is merged there will be no need to manually
parse for "dmas" and this patch can be safely reverted.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Daniel Mack <zonque@gmail.com>
CC: Arnd Bergmann <arnd@arndb.de>
---
   v2..v3
   * split into good (PATCH 07/21) and temporary (this one) parts

   v1..v2
   * add binding for next-gen dma controller
   * use correct dma declararion
   * number changed from 5 to 3

 drivers/mmc/host/pxamci.c | 59 ++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 48 insertions(+), 11 deletions(-)

diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c
index 32fe113..6b67764 100644
--- a/drivers/mmc/host/pxamci.c
+++ b/drivers/mmc/host/pxamci.c
@@ -613,11 +613,46 @@ static int pxamci_of_init(struct platform_device *pdev)
 
         return 0;
 }
+
+static int pxamci_of_init_dma(struct platform_device *pdev,
+		struct pxamci_host *host)
+{
+	struct device_node *np = pdev->dev.of_node;
+	u32 tmp;
+	int i;
+	int ret;
+
+	i = of_property_match_string(np, "dma-names", "rx");
+	if (i < 0)
+		return i;
+
+	ret = of_property_read_u32_index(np, "dmas", 2 * i + 1, &tmp);
+	if (ret < 0)
+		return ret;
+	host->dma_drcmrrx = tmp;
+
+	i = of_property_match_string(np, "dma-names", "tx");
+	if (i < 0)
+		return i;
+
+	ret = of_property_read_u32_index(np, "dmas", 2 * i + 1, &tmp);
+	if (ret < 0)
+		return ret;
+	host->dma_drcmrtx = tmp;
+
+	return 0;
+}
 #else
 static int pxamci_of_init(struct platform_device *pdev)
 {
         return 0;
 }
+
+static int pxamci_of_init_dma(struct platform_device *pdev,
+		struct pxamci_host *host)
+{
+	return -ENODATA;
+}
 #endif
 
 static int pxamci_probe(struct platform_device *pdev)
@@ -741,19 +776,21 @@ static int pxamci_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, mmc);
 
-	dmarx = platform_get_resource(pdev, IORESOURCE_DMA, 0);
-	if (!dmarx) {
-		ret = -ENXIO;
-		goto out;
-	}
-	host->dma_drcmrrx = dmarx->start;
+	if (pxamci_of_init_dma(pdev, host) < 0) {
+		dmarx = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+		if (!dmarx) {
+			ret = -ENXIO;
+			goto out;
+		}
+		host->dma_drcmrrx = dmarx->start;
 
-	dmatx = platform_get_resource(pdev, IORESOURCE_DMA, 1);
-	if (!dmatx) {
-		ret = -ENXIO;
-		goto out;
+		dmatx = platform_get_resource(pdev, IORESOURCE_DMA, 1);
+		if (!dmatx) {
+			ret = -ENXIO;
+			goto out;
+		}
+		host->dma_drcmrtx = dmatx->start;
 	}
-	host->dma_drcmrtx = dmatx->start;
 
 	if (host->pdata) {
 		gpio_cd = host->pdata->gpio_card_detect;
-- 
1.8.4.2


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

* [PATCH v3 07/21] ARM: dts: parse DMA config in pxamci
@ 2013-12-17 19:37             ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-17 19:37 UTC (permalink / raw)
  To: linux-arm-kernel

The existing PXA MMC driver cannot get DMA channels in a proper
way from the respective device tree binding.

This patch provides temporary workaround which allows using the
existing driver in DT machines by pointing to the proper
dmaengine-based "marvell,pdma-1.0" DMA.

Even though the new DMA provider is not present we can parse device node
attributes manually and use channel numbers to acquire DMA channel
from the existing non-dmaengine provider.

When Daniel's DMA series is merged there will be no need to manually
parse for "dmas" and this patch can be safely reverted.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Daniel Mack <zonque@gmail.com>
CC: Arnd Bergmann <arnd@arndb.de>
---
   v2..v3
   * split into good (PATCH 07/21) and temporary (this one) parts

   v1..v2
   * add binding for next-gen dma controller
   * use correct dma declararion
   * number changed from 5 to 3

 drivers/mmc/host/pxamci.c | 59 ++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 48 insertions(+), 11 deletions(-)

diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c
index 32fe113..6b67764 100644
--- a/drivers/mmc/host/pxamci.c
+++ b/drivers/mmc/host/pxamci.c
@@ -613,11 +613,46 @@ static int pxamci_of_init(struct platform_device *pdev)
 
         return 0;
 }
+
+static int pxamci_of_init_dma(struct platform_device *pdev,
+		struct pxamci_host *host)
+{
+	struct device_node *np = pdev->dev.of_node;
+	u32 tmp;
+	int i;
+	int ret;
+
+	i = of_property_match_string(np, "dma-names", "rx");
+	if (i < 0)
+		return i;
+
+	ret = of_property_read_u32_index(np, "dmas", 2 * i + 1, &tmp);
+	if (ret < 0)
+		return ret;
+	host->dma_drcmrrx = tmp;
+
+	i = of_property_match_string(np, "dma-names", "tx");
+	if (i < 0)
+		return i;
+
+	ret = of_property_read_u32_index(np, "dmas", 2 * i + 1, &tmp);
+	if (ret < 0)
+		return ret;
+	host->dma_drcmrtx = tmp;
+
+	return 0;
+}
 #else
 static int pxamci_of_init(struct platform_device *pdev)
 {
         return 0;
 }
+
+static int pxamci_of_init_dma(struct platform_device *pdev,
+		struct pxamci_host *host)
+{
+	return -ENODATA;
+}
 #endif
 
 static int pxamci_probe(struct platform_device *pdev)
@@ -741,19 +776,21 @@ static int pxamci_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, mmc);
 
-	dmarx = platform_get_resource(pdev, IORESOURCE_DMA, 0);
-	if (!dmarx) {
-		ret = -ENXIO;
-		goto out;
-	}
-	host->dma_drcmrrx = dmarx->start;
+	if (pxamci_of_init_dma(pdev, host) < 0) {
+		dmarx = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+		if (!dmarx) {
+			ret = -ENXIO;
+			goto out;
+		}
+		host->dma_drcmrrx = dmarx->start;
 
-	dmatx = platform_get_resource(pdev, IORESOURCE_DMA, 1);
-	if (!dmatx) {
-		ret = -ENXIO;
-		goto out;
+		dmatx = platform_get_resource(pdev, IORESOURCE_DMA, 1);
+		if (!dmatx) {
+			ret = -ENXIO;
+			goto out;
+		}
+		host->dma_drcmrtx = dmatx->start;
 	}
-	host->dma_drcmrtx = dmatx->start;
 
 	if (host->pdata) {
 		gpio_cd = host->pdata->gpio_card_detect;
-- 
1.8.4.2

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

* [PATCH v3 08/21] ARM: pxa27x: device tree support ICP DAS LP-8x4x
  2013-12-17 19:37           ` Sergei Ianovich
  (?)
@ 2013-12-17 19:37             ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-17 19:37 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Daniel Mack, Arnd Bergmann, Rob Herring,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala, Russell King,
	Eric Miao, Haojian Zhuang, open list:OPEN FIRMWARE AND...

ICP DAS calls LP-8x4x 'programmable automation controller'. It is
an industrial computer based on PXA270 SoC. They ship it with a 2.6.19
kernel and proprietary kernel module and userspace library to access
its industrial IO.

This patch allows to boot the device with a modern kernel with device
tree. It adds support for:
* MMC card interface on PXA270
* USB 1.1 port on PXA270
* 2 NOR flash devices
* 2 onboard ethernet Davicom DM9000 devices
* 3 serial UART ports on PXA270
* front panel red LED
* 64bit 1-wire system ID chip
* 16 kiB EEPROM (reading)

Support for these devices will be added in separate patches, since
they are not currently supported by the kernel:
* DS1302 RTC
* 512kiB SRAM
* FPGA irq chip
* 3 built-in 16550A serial UART ports
* industrial IO parallel bus
* 10 position rotary switch
* 8 pin DIP switch
* 16 kiB EEPROM (writing)
* serial interface for digital and analog industrial IO modules on
  parallel bus (all I-87... modules)
* digital and analog industrial IO modules for parallel bus:
  ** I-8024 4 port analog output
  ** I-8041 32 port digital output
  ** I-8042 16 port digital output/16 port digital input

Not supported for now:
* VGA interface on PXA270 for lack of dts binding
* the rest of parallel bus (I-8...) modules for lack of hardware
* GPIO reset for lack of relevance (watchdog reset is working)

NOTE: USB support requires U-Boot patch series which setups GPIO.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Daniel Mack <zonque@gmail.com>
CC: Arnd Bergmann <arnd@arndb.de>
---
   v2..v3
   * added extbus which maps synchronous, static, and variable-latency
     I/O (VLIO) interfaces of PXA27x SoC as suggested by Arnd Bergmann
   * map is placed into platform include
   * configured existing kernel drivers to support:
     - front panel LED using gpio-leds
     - 64bit 1-wire system ID chip using w1-gpio
     - 16 kiB EEPROM using at24 over i2c-gpio
   * number change (06/16 -> 08/21)

   v1..v2
   * drop left-over extern declaration
   * use of_have_populated_dt() instead of a static variable
   * drop wildcards in compatible
   * drop machine-special machine description
   * number changed from 9 to 6 (dropped patches)

 arch/arm/boot/dts/Makefile          |   1 +
 arch/arm/boot/dts/pxa27x-lp8x4x.dts | 153 ++++++++++++++++++++++++++++++++
 arch/arm/boot/dts/pxa27x.dtsi       |  17 ++++
 arch/arm/configs/lp8x4x_defconfig   | 168 ++++++++++++++++++++++++++++++++++++
 arch/arm/mach-pxa/Kconfig           |  15 ++++
 arch/arm/mach-pxa/Makefile          |   1 +
 arch/arm/mach-pxa/pxa27x-dt.c       |  64 ++++++++++++++
 7 files changed, 419 insertions(+)
 create mode 100644 arch/arm/boot/dts/pxa27x-lp8x4x.dts
 create mode 100644 arch/arm/configs/lp8x4x_defconfig
 create mode 100644 arch/arm/mach-pxa/pxa27x-dt.c

diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index d57c1a6..c4752ff 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -206,6 +206,7 @@ dtb-$(CONFIG_ARCH_OMAP2PLUS) += omap2420-h4.dtb \
 	dra7-evm.dtb
 dtb-$(CONFIG_ARCH_ORION5X) += orion5x-lacie-ethernet-disk-mini-v2.dtb
 dtb-$(CONFIG_ARCH_PRIMA2) += prima2-evb.dtb
+dtb-$(CONFIG_MACH_PXA27X_DT) += pxa27x-lp8x4x.dtb
 dtb-$(CONFIG_ARCH_U8500) += ste-snowball.dtb \
 	ste-hrefprev60-stuib.dtb \
 	ste-hrefprev60-tvk.dtb \
diff --git a/arch/arm/boot/dts/pxa27x-lp8x4x.dts b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
new file mode 100644
index 0000000..6a780fe
--- /dev/null
+++ b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
@@ -0,0 +1,153 @@
+/* Device tree for ICP DAS LP-8x4x */
+/dts-v1/;
+
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include "pxa27x.dtsi"
+
+/ {
+	model = "ICP DAS LP-8x4x programmable automation controller";
+	compatible = "marvell,lp8x4x", "marvell,pxa270";
+
+	aliases {
+		ethernet0 = &eth0;
+		ethernet1 = &eth1;
+	};
+
+	memory {
+		reg = <0xa0000000 0x08000000>;
+	};
+
+	regulators {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		vmmc: regulator@0 {
+			compatible = "regulator-fixed";
+			reg = <0>;
+			regulator-name = "vmmc";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-always-on;
+		};
+	};
+
+	pxabus {
+		pxairq: interrupt-controller@40d00000 {
+			marvell,intc-priority;
+			marvell,intc-nr-irqs = <34>;
+		};
+
+		uart@40100000 {
+			status = "okay";
+		};
+
+		uart@40200000 {
+			status = "okay";
+		};
+
+		uart@40700000 {
+			status = "okay";
+		};
+
+		mmc@41100000 {
+			status = "okay";
+			vmmc-supply = <&vmmc>;
+		};
+
+		ohci@4c000000 {
+			status = "okay";
+			marvell,port-mode = <3>;
+			marvell,oc-mode-perport;
+			marvell,enable-port1;
+		};
+
+		leds {
+			compatible = "gpio-leds";
+
+			status {
+				gpios = <&gpio 84 1>;
+				linux,default-trigger = "heartbeat";
+			};
+		};
+
+		i2c: i2c-gpio {
+			compatible = "i2c-gpio";
+			gpios = <&gpio 22 0 /* sda */
+				 &gpio 12 0 /* scl */>;
+			i2c-gpio,delay-us = <1>;
+			i2c-gpio,timeout-ms = <1>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			eeprom@50 {
+				compatible = "atmel,24c128";
+				reg = <0x50>;
+				pagesize = <64>;
+			};
+		};
+
+		w1: w1-gpio {
+			compatible = "w1-gpio";
+			gpios = <&gpio 83 0>;
+		};
+	};
+
+	extbus {
+		flash@0 {
+			compatible = "cfi-flash";
+			reg = <0 0 0x02000000>;
+			bank-width = <4>;
+			device-width = <2>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			fs@0 {
+				label = "u-boot";
+				reg = <0 0x40000>;
+			};
+			fs@40000 {
+				label = "settings";
+				reg = <0x40000 0x40000>;
+			};
+			fs@80000 {
+				label = "kernel";
+				reg = <0x80000 0x280000>;
+			};
+			fs@300000 {
+				label = "root_fs";
+				reg = <0x300000 0x1d00000>;
+			};
+		};
+
+		flash@1 {
+			compatible = "cfi-flash";
+			reg = <1 0x0 0x01000000>;
+			bank-width = <2>;
+			device-width = <1>;
+		};
+
+		netio@3 {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0 3 0 0x02000000>;
+			interrupt-parent = <&gpio>;
+
+			eth0: eth@0 {
+				compatible = "davicom,dm9000";
+				reg = <0x0 0x2
+				       0x4000 0x2>;
+				interrupts = <9 IRQ_TYPE_EDGE_RISING>;
+				status = "okay";
+			};
+
+			eth1: eth@1000000 {
+				compatible = "davicom,dm9000";
+				reg = <0x1000000 0x2
+				       0x1004000 0x2>;
+				interrupts = <82 IRQ_TYPE_EDGE_RISING>;
+				status = "okay";
+			};
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/pxa27x.dtsi b/arch/arm/boot/dts/pxa27x.dtsi
index c2a90c5..29d878d 100644
--- a/arch/arm/boot/dts/pxa27x.dtsi
+++ b/arch/arm/boot/dts/pxa27x.dtsi
@@ -31,4 +31,21 @@
 			dma-names = "rx", "tx";
 		};
 	};
+
+	extbus {
+		/*
+		 * PXA27x synchrous, static and
+		 * variable-latency IO interfaces
+		 */
+	        compatible = "simple-bus";
+
+		#address-cells = <2>; /* first cell is nCS, second is address */
+		#size-cells = <1>;
+		ranges = <0 0 0 0x04000000
+			  1 0 0x04000000 0x04000000
+			  2 0 0x08000000 0x04000000
+			  3 0 0x0c000000 0x04000000
+			  4 0 0x10000000 0x04000000
+			  5 0 0x14000000 0x04000000>;
+	};
 };
diff --git a/arch/arm/configs/lp8x4x_defconfig b/arch/arm/configs/lp8x4x_defconfig
new file mode 100644
index 0000000..9f1efb6
--- /dev/null
+++ b/arch/arm/configs/lp8x4x_defconfig
@@ -0,0 +1,168 @@
+# CONFIG_LOCALVERSION_AUTO is not set
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_RCU_BOOST=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_NS is not set
+# CONFIG_IPC_NS is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+# CONFIG_UID16 is not set
+# CONFIG_SHMEM is not set
+CONFIG_EMBEDDED=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_SLOB=y
+CONFIG_JUMP_LABEL=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+# CONFIG_LBDAF is not set
+CONFIG_BLK_CMDLINE_PARSER=y
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_ARCH_PXA=y
+CONFIG_MACH_PXA27X_DT=y
+# CONFIG_ARM_THUMB is not set
+CONFIG_PREEMPT=y
+CONFIG_AEABI=y
+# CONFIG_COMPACTION is not set
+# CONFIG_CROSS_MEMORY_ATTACH is not set
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="init=/sbin/init root=/dev/mmcblk0p1 rw rootfstype=ext4 console=ttyS0,115200 mem=128M rootwait"
+# CONFIG_SUSPEND is not set
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_BRIDGE=m
+CONFIG_BRIDGE_VLAN_FILTERING=y
+CONFIG_VLAN_8021Q=m
+CONFIG_VLAN_8021Q_GVRP=y
+CONFIG_VLAN_8021Q_MVRP=y
+# CONFIG_WIRELESS is not set
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+# CONFIG_FW_LOADER is not set
+CONFIG_MTD=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_CFI_GEOMETRY=y
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_PHYSMAP_OF=y
+CONFIG_PROC_DEVICETREE=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_LOOP_MIN_COUNT=2
+CONFIG_EEPROM_AT24=m
+CONFIG_SCSI=y
+# CONFIG_SCSI_PROC_FS is not set
+CONFIG_BLK_DEV_SD=y
+# CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_NETDEVICES=y
+CONFIG_BONDING=m
+CONFIG_MACVLAN=m
+CONFIG_MACVTAP=m
+CONFIG_TUN=m
+# CONFIG_NET_VENDOR_ARC is not set
+# CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_CIRRUS is not set
+CONFIG_DM9000=y
+CONFIG_DM9000_FORCE_SIMPLE_PHY_POLL=y
+# CONFIG_NET_VENDOR_FARADAY is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+CONFIG_PPP=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPPOE=m
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_SLIP=m
+CONFIG_SLIP_COMPRESSED=y
+# CONFIG_WLAN is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=800
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=600
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_SERIO is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_8250=y
+# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=40
+CONFIG_SERIAL_8250_RUNTIME_UARTS=40
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_PXA=y
+CONFIG_HW_RANDOM=y
+CONFIG_I2C=m
+# CONFIG_I2C_COMPAT is not set
+CONFIG_I2C_GPIO=m
+CONFIG_W1=m
+CONFIG_W1_MASTER_GPIO=m
+CONFIG_W1_SLAVE_SMEM=m
+# CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_SA1100_WATCHDOG=m
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_FB=y
+CONFIG_FB_PXA=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_LOGO=y
+CONFIG_USB=m
+CONFIG_USB_OHCI_HCD=m
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+CONFIG_USB_STORAGE=m
+CONFIG_USB_SERIAL=m
+CONFIG_MMC=y
+CONFIG_MMC_PXA=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_PXA=m
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_EXT2_FS=m
+CONFIG_EXT3_FS=y
+CONFIG_EXT4_FS=y
+CONFIG_REISERFS_FS=m
+CONFIG_ISO9660_FS=m
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_NTFS_FS=m
+CONFIG_NTFS_RW=y
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V4=y
+CONFIG_ROOT_NFS=y
+CONFIG_CIFS=m
+CONFIG_CIFS_STATS=y
+CONFIG_CODA_FS=m
+CONFIG_NLS_DEFAULT="cp855"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_855=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_UTF8=y
+CONFIG_PRINTK_TIME=y
diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig
index 96100db..df3a79d 100644
--- a/arch/arm/mach-pxa/Kconfig
+++ b/arch/arm/mach-pxa/Kconfig
@@ -4,6 +4,21 @@ menu "Intel PXA2xx/PXA3xx Implementations"
 
 comment "Intel/Marvell Dev Platforms (sorted by hardware release time)"
 
+config MACH_PXA27X_DT
+	bool "Support PXA27x platforms from device tree"
+	select PXA27x
+	select USE_OF
+	help
+	  Include support for Marvell PXA27x based platforms using
+	  the device tree.
+
+	  While MACH_PXA27X_DT when enabled should boot any PXA27x
+	  compatible machine, it still makes sense to select specific
+	  machines. Those options will select required features and
+	  provide per-machine errata workarounds.
+
+	  If unsure, say Y.
+
 config MACH_PXA3XX_DT
 	bool "Support PXA3xx platforms from device tree"
 	select CPU_PXA300
diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile
index 648867a..adaa72a 100644
--- a/arch/arm/mach-pxa/Makefile
+++ b/arch/arm/mach-pxa/Makefile
@@ -20,6 +20,7 @@ obj-$(CONFIG_CPU_PXA930)	+= pxa930.o
 # NOTE: keep the order of boards in accordance to their order in Kconfig
 
 # Device Tree support
+obj-$(CONFIG_MACH_PXA27X_DT)	+= pxa27x-dt.o
 obj-$(CONFIG_MACH_PXA3XX_DT)	+= pxa-dt.o
 
 # Intel/Marvell Dev Platforms
diff --git a/arch/arm/mach-pxa/pxa27x-dt.c b/arch/arm/mach-pxa/pxa27x-dt.c
new file mode 100644
index 0000000..865cf46
--- /dev/null
+++ b/arch/arm/mach-pxa/pxa27x-dt.c
@@ -0,0 +1,64 @@
+/*
+ *  linux/arch/arm/mach-pxa/pxa27x-dt.c
+ *
+ *  Copyright (C) 2013 Sergei Ianovich
+ *
+ *  based mostly on linux/arch/arm/mach-pxa/pxa-dt.c by Daniel Mack
+ *
+ *  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
+ *  publishhed by the Free Software Foundation.
+ */
+
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <asm/io.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <mach/irqs.h>
+#include <mach/pxa27x.h>
+
+#include "generic.h"
+
+#ifdef CONFIG_PXA27x
+static const struct of_dev_auxdata pxa27x_auxdata_lookup[] __initconst = {
+	OF_DEV_AUXDATA("mrvl,pxa-uart",	    0x40100000, "pxa2xx-uart.0", NULL),
+	OF_DEV_AUXDATA("mrvl,pxa-uart",	    0x40200000, "pxa2xx-uart.1", NULL),
+	OF_DEV_AUXDATA("mrvl,pxa-uart",	    0x40700000, "pxa2xx-uart.2", NULL),
+	OF_DEV_AUXDATA("mrvl,pxa-uart",	    0x41600000, "pxa2xx-uart.3", NULL),
+	OF_DEV_AUXDATA("marvell,pxa-mmc",   0x41100000, "pxa2xx-mci.0", NULL),
+	OF_DEV_AUXDATA("intel,pxa27x-gpio", 0x40e00000, "pxa27x-gpio", NULL),
+	OF_DEV_AUXDATA("marvell,pxa-ohci",  0x4c000000, "pxa27x-ohci", NULL),
+	OF_DEV_AUXDATA("mrvl,pxa-i2c",	    0x40301680, "pxa2xx-i2c.0", NULL),
+	{}
+};
+
+static void __init pxa27x_dt_init(void)
+{
+	of_platform_populate(NULL, of_default_bus_match_table,
+			     pxa27x_auxdata_lookup, NULL);
+}
+
+static const char * const pxa27x_dt_board_compat[] __initconst = {
+	"marvell,pxa270",
+	"marvell,pxa271",
+	"marvell,pxa272",
+	NULL,
+};
+
+#endif
+
+#ifdef CONFIG_PXA27x
+DT_MACHINE_START(PXA27X_DT, "Marvell PXA27x (Device Tree Support)")
+	.map_io		= pxa27x_map_io,
+	.init_irq	= pxa27x_dt_init_irq,
+	.handle_irq	= pxa27x_handle_irq,
+	.init_time	= pxa_timer_init,
+	.restart	= pxa_restart,
+	.init_machine	= pxa27x_dt_init,
+	.dt_compat	= pxa27x_dt_board_compat,
+MACHINE_END
+
+#endif
-- 
1.8.4.2


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

* [PATCH v3 08/21] ARM: pxa27x: device tree support ICP DAS LP-8x4x
@ 2013-12-17 19:37             ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-17 19:37 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Daniel Mack, Arnd Bergmann, Rob Herring,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala, Russell King,
	Eric Miao, Haojian Zhuang, open list:OPEN FIRMWARE AND...

ICP DAS calls LP-8x4x 'programmable automation controller'. It is
an industrial computer based on PXA270 SoC. They ship it with a 2.6.19
kernel and proprietary kernel module and userspace library to access
its industrial IO.

This patch allows to boot the device with a modern kernel with device
tree. It adds support for:
* MMC card interface on PXA270
* USB 1.1 port on PXA270
* 2 NOR flash devices
* 2 onboard ethernet Davicom DM9000 devices
* 3 serial UART ports on PXA270
* front panel red LED
* 64bit 1-wire system ID chip
* 16 kiB EEPROM (reading)

Support for these devices will be added in separate patches, since
they are not currently supported by the kernel:
* DS1302 RTC
* 512kiB SRAM
* FPGA irq chip
* 3 built-in 16550A serial UART ports
* industrial IO parallel bus
* 10 position rotary switch
* 8 pin DIP switch
* 16 kiB EEPROM (writing)
* serial interface for digital and analog industrial IO modules on
  parallel bus (all I-87... modules)
* digital and analog industrial IO modules for parallel bus:
  ** I-8024 4 port analog output
  ** I-8041 32 port digital output
  ** I-8042 16 port digital output/16 port digital input

Not supported for now:
* VGA interface on PXA270 for lack of dts binding
* the rest of parallel bus (I-8...) modules for lack of hardware
* GPIO reset for lack of relevance (watchdog reset is working)

NOTE: USB support requires U-Boot patch series which setups GPIO.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Daniel Mack <zonque@gmail.com>
CC: Arnd Bergmann <arnd@arndb.de>
---
   v2..v3
   * added extbus which maps synchronous, static, and variable-latency
     I/O (VLIO) interfaces of PXA27x SoC as suggested by Arnd Bergmann
   * map is placed into platform include
   * configured existing kernel drivers to support:
     - front panel LED using gpio-leds
     - 64bit 1-wire system ID chip using w1-gpio
     - 16 kiB EEPROM using at24 over i2c-gpio
   * number change (06/16 -> 08/21)

   v1..v2
   * drop left-over extern declaration
   * use of_have_populated_dt() instead of a static variable
   * drop wildcards in compatible
   * drop machine-special machine description
   * number changed from 9 to 6 (dropped patches)

 arch/arm/boot/dts/Makefile          |   1 +
 arch/arm/boot/dts/pxa27x-lp8x4x.dts | 153 ++++++++++++++++++++++++++++++++
 arch/arm/boot/dts/pxa27x.dtsi       |  17 ++++
 arch/arm/configs/lp8x4x_defconfig   | 168 ++++++++++++++++++++++++++++++++++++
 arch/arm/mach-pxa/Kconfig           |  15 ++++
 arch/arm/mach-pxa/Makefile          |   1 +
 arch/arm/mach-pxa/pxa27x-dt.c       |  64 ++++++++++++++
 7 files changed, 419 insertions(+)
 create mode 100644 arch/arm/boot/dts/pxa27x-lp8x4x.dts
 create mode 100644 arch/arm/configs/lp8x4x_defconfig
 create mode 100644 arch/arm/mach-pxa/pxa27x-dt.c

diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index d57c1a6..c4752ff 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -206,6 +206,7 @@ dtb-$(CONFIG_ARCH_OMAP2PLUS) += omap2420-h4.dtb \
 	dra7-evm.dtb
 dtb-$(CONFIG_ARCH_ORION5X) += orion5x-lacie-ethernet-disk-mini-v2.dtb
 dtb-$(CONFIG_ARCH_PRIMA2) += prima2-evb.dtb
+dtb-$(CONFIG_MACH_PXA27X_DT) += pxa27x-lp8x4x.dtb
 dtb-$(CONFIG_ARCH_U8500) += ste-snowball.dtb \
 	ste-hrefprev60-stuib.dtb \
 	ste-hrefprev60-tvk.dtb \
diff --git a/arch/arm/boot/dts/pxa27x-lp8x4x.dts b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
new file mode 100644
index 0000000..6a780fe
--- /dev/null
+++ b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
@@ -0,0 +1,153 @@
+/* Device tree for ICP DAS LP-8x4x */
+/dts-v1/;
+
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include "pxa27x.dtsi"
+
+/ {
+	model = "ICP DAS LP-8x4x programmable automation controller";
+	compatible = "marvell,lp8x4x", "marvell,pxa270";
+
+	aliases {
+		ethernet0 = &eth0;
+		ethernet1 = &eth1;
+	};
+
+	memory {
+		reg = <0xa0000000 0x08000000>;
+	};
+
+	regulators {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		vmmc: regulator@0 {
+			compatible = "regulator-fixed";
+			reg = <0>;
+			regulator-name = "vmmc";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-always-on;
+		};
+	};
+
+	pxabus {
+		pxairq: interrupt-controller@40d00000 {
+			marvell,intc-priority;
+			marvell,intc-nr-irqs = <34>;
+		};
+
+		uart@40100000 {
+			status = "okay";
+		};
+
+		uart@40200000 {
+			status = "okay";
+		};
+
+		uart@40700000 {
+			status = "okay";
+		};
+
+		mmc@41100000 {
+			status = "okay";
+			vmmc-supply = <&vmmc>;
+		};
+
+		ohci@4c000000 {
+			status = "okay";
+			marvell,port-mode = <3>;
+			marvell,oc-mode-perport;
+			marvell,enable-port1;
+		};
+
+		leds {
+			compatible = "gpio-leds";
+
+			status {
+				gpios = <&gpio 84 1>;
+				linux,default-trigger = "heartbeat";
+			};
+		};
+
+		i2c: i2c-gpio {
+			compatible = "i2c-gpio";
+			gpios = <&gpio 22 0 /* sda */
+				 &gpio 12 0 /* scl */>;
+			i2c-gpio,delay-us = <1>;
+			i2c-gpio,timeout-ms = <1>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			eeprom@50 {
+				compatible = "atmel,24c128";
+				reg = <0x50>;
+				pagesize = <64>;
+			};
+		};
+
+		w1: w1-gpio {
+			compatible = "w1-gpio";
+			gpios = <&gpio 83 0>;
+		};
+	};
+
+	extbus {
+		flash@0 {
+			compatible = "cfi-flash";
+			reg = <0 0 0x02000000>;
+			bank-width = <4>;
+			device-width = <2>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			fs@0 {
+				label = "u-boot";
+				reg = <0 0x40000>;
+			};
+			fs@40000 {
+				label = "settings";
+				reg = <0x40000 0x40000>;
+			};
+			fs@80000 {
+				label = "kernel";
+				reg = <0x80000 0x280000>;
+			};
+			fs@300000 {
+				label = "root_fs";
+				reg = <0x300000 0x1d00000>;
+			};
+		};
+
+		flash@1 {
+			compatible = "cfi-flash";
+			reg = <1 0x0 0x01000000>;
+			bank-width = <2>;
+			device-width = <1>;
+		};
+
+		netio@3 {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0 3 0 0x02000000>;
+			interrupt-parent = <&gpio>;
+
+			eth0: eth@0 {
+				compatible = "davicom,dm9000";
+				reg = <0x0 0x2
+				       0x4000 0x2>;
+				interrupts = <9 IRQ_TYPE_EDGE_RISING>;
+				status = "okay";
+			};
+
+			eth1: eth@1000000 {
+				compatible = "davicom,dm9000";
+				reg = <0x1000000 0x2
+				       0x1004000 0x2>;
+				interrupts = <82 IRQ_TYPE_EDGE_RISING>;
+				status = "okay";
+			};
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/pxa27x.dtsi b/arch/arm/boot/dts/pxa27x.dtsi
index c2a90c5..29d878d 100644
--- a/arch/arm/boot/dts/pxa27x.dtsi
+++ b/arch/arm/boot/dts/pxa27x.dtsi
@@ -31,4 +31,21 @@
 			dma-names = "rx", "tx";
 		};
 	};
+
+	extbus {
+		/*
+		 * PXA27x synchrous, static and
+		 * variable-latency IO interfaces
+		 */
+	        compatible = "simple-bus";
+
+		#address-cells = <2>; /* first cell is nCS, second is address */
+		#size-cells = <1>;
+		ranges = <0 0 0 0x04000000
+			  1 0 0x04000000 0x04000000
+			  2 0 0x08000000 0x04000000
+			  3 0 0x0c000000 0x04000000
+			  4 0 0x10000000 0x04000000
+			  5 0 0x14000000 0x04000000>;
+	};
 };
diff --git a/arch/arm/configs/lp8x4x_defconfig b/arch/arm/configs/lp8x4x_defconfig
new file mode 100644
index 0000000..9f1efb6
--- /dev/null
+++ b/arch/arm/configs/lp8x4x_defconfig
@@ -0,0 +1,168 @@
+# CONFIG_LOCALVERSION_AUTO is not set
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_RCU_BOOST=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_NS is not set
+# CONFIG_IPC_NS is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+# CONFIG_UID16 is not set
+# CONFIG_SHMEM is not set
+CONFIG_EMBEDDED=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_SLOB=y
+CONFIG_JUMP_LABEL=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+# CONFIG_LBDAF is not set
+CONFIG_BLK_CMDLINE_PARSER=y
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_ARCH_PXA=y
+CONFIG_MACH_PXA27X_DT=y
+# CONFIG_ARM_THUMB is not set
+CONFIG_PREEMPT=y
+CONFIG_AEABI=y
+# CONFIG_COMPACTION is not set
+# CONFIG_CROSS_MEMORY_ATTACH is not set
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="init=/sbin/init root=/dev/mmcblk0p1 rw rootfstype=ext4 console=ttyS0,115200 mem=128M rootwait"
+# CONFIG_SUSPEND is not set
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_BRIDGE=m
+CONFIG_BRIDGE_VLAN_FILTERING=y
+CONFIG_VLAN_8021Q=m
+CONFIG_VLAN_8021Q_GVRP=y
+CONFIG_VLAN_8021Q_MVRP=y
+# CONFIG_WIRELESS is not set
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+# CONFIG_FW_LOADER is not set
+CONFIG_MTD=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_CFI_GEOMETRY=y
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_PHYSMAP_OF=y
+CONFIG_PROC_DEVICETREE=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_LOOP_MIN_COUNT=2
+CONFIG_EEPROM_AT24=m
+CONFIG_SCSI=y
+# CONFIG_SCSI_PROC_FS is not set
+CONFIG_BLK_DEV_SD=y
+# CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_NETDEVICES=y
+CONFIG_BONDING=m
+CONFIG_MACVLAN=m
+CONFIG_MACVTAP=m
+CONFIG_TUN=m
+# CONFIG_NET_VENDOR_ARC is not set
+# CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_CIRRUS is not set
+CONFIG_DM9000=y
+CONFIG_DM9000_FORCE_SIMPLE_PHY_POLL=y
+# CONFIG_NET_VENDOR_FARADAY is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+CONFIG_PPP=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPPOE=m
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_SLIP=m
+CONFIG_SLIP_COMPRESSED=y
+# CONFIG_WLAN is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=800
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=600
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_SERIO is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_8250=y
+# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=40
+CONFIG_SERIAL_8250_RUNTIME_UARTS=40
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_PXA=y
+CONFIG_HW_RANDOM=y
+CONFIG_I2C=m
+# CONFIG_I2C_COMPAT is not set
+CONFIG_I2C_GPIO=m
+CONFIG_W1=m
+CONFIG_W1_MASTER_GPIO=m
+CONFIG_W1_SLAVE_SMEM=m
+# CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_SA1100_WATCHDOG=m
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_FB=y
+CONFIG_FB_PXA=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_LOGO=y
+CONFIG_USB=m
+CONFIG_USB_OHCI_HCD=m
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+CONFIG_USB_STORAGE=m
+CONFIG_USB_SERIAL=m
+CONFIG_MMC=y
+CONFIG_MMC_PXA=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_PXA=m
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_EXT2_FS=m
+CONFIG_EXT3_FS=y
+CONFIG_EXT4_FS=y
+CONFIG_REISERFS_FS=m
+CONFIG_ISO9660_FS=m
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_NTFS_FS=m
+CONFIG_NTFS_RW=y
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V4=y
+CONFIG_ROOT_NFS=y
+CONFIG_CIFS=m
+CONFIG_CIFS_STATS=y
+CONFIG_CODA_FS=m
+CONFIG_NLS_DEFAULT="cp855"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_855=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_UTF8=y
+CONFIG_PRINTK_TIME=y
diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig
index 96100db..df3a79d 100644
--- a/arch/arm/mach-pxa/Kconfig
+++ b/arch/arm/mach-pxa/Kconfig
@@ -4,6 +4,21 @@ menu "Intel PXA2xx/PXA3xx Implementations"
 
 comment "Intel/Marvell Dev Platforms (sorted by hardware release time)"
 
+config MACH_PXA27X_DT
+	bool "Support PXA27x platforms from device tree"
+	select PXA27x
+	select USE_OF
+	help
+	  Include support for Marvell PXA27x based platforms using
+	  the device tree.
+
+	  While MACH_PXA27X_DT when enabled should boot any PXA27x
+	  compatible machine, it still makes sense to select specific
+	  machines. Those options will select required features and
+	  provide per-machine errata workarounds.
+
+	  If unsure, say Y.
+
 config MACH_PXA3XX_DT
 	bool "Support PXA3xx platforms from device tree"
 	select CPU_PXA300
diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile
index 648867a..adaa72a 100644
--- a/arch/arm/mach-pxa/Makefile
+++ b/arch/arm/mach-pxa/Makefile
@@ -20,6 +20,7 @@ obj-$(CONFIG_CPU_PXA930)	+= pxa930.o
 # NOTE: keep the order of boards in accordance to their order in Kconfig
 
 # Device Tree support
+obj-$(CONFIG_MACH_PXA27X_DT)	+= pxa27x-dt.o
 obj-$(CONFIG_MACH_PXA3XX_DT)	+= pxa-dt.o
 
 # Intel/Marvell Dev Platforms
diff --git a/arch/arm/mach-pxa/pxa27x-dt.c b/arch/arm/mach-pxa/pxa27x-dt.c
new file mode 100644
index 0000000..865cf46
--- /dev/null
+++ b/arch/arm/mach-pxa/pxa27x-dt.c
@@ -0,0 +1,64 @@
+/*
+ *  linux/arch/arm/mach-pxa/pxa27x-dt.c
+ *
+ *  Copyright (C) 2013 Sergei Ianovich
+ *
+ *  based mostly on linux/arch/arm/mach-pxa/pxa-dt.c by Daniel Mack
+ *
+ *  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
+ *  publishhed by the Free Software Foundation.
+ */
+
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <asm/io.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <mach/irqs.h>
+#include <mach/pxa27x.h>
+
+#include "generic.h"
+
+#ifdef CONFIG_PXA27x
+static const struct of_dev_auxdata pxa27x_auxdata_lookup[] __initconst = {
+	OF_DEV_AUXDATA("mrvl,pxa-uart",	    0x40100000, "pxa2xx-uart.0", NULL),
+	OF_DEV_AUXDATA("mrvl,pxa-uart",	    0x40200000, "pxa2xx-uart.1", NULL),
+	OF_DEV_AUXDATA("mrvl,pxa-uart",	    0x40700000, "pxa2xx-uart.2", NULL),
+	OF_DEV_AUXDATA("mrvl,pxa-uart",	    0x41600000, "pxa2xx-uart.3", NULL),
+	OF_DEV_AUXDATA("marvell,pxa-mmc",   0x41100000, "pxa2xx-mci.0", NULL),
+	OF_DEV_AUXDATA("intel,pxa27x-gpio", 0x40e00000, "pxa27x-gpio", NULL),
+	OF_DEV_AUXDATA("marvell,pxa-ohci",  0x4c000000, "pxa27x-ohci", NULL),
+	OF_DEV_AUXDATA("mrvl,pxa-i2c",	    0x40301680, "pxa2xx-i2c.0", NULL),
+	{}
+};
+
+static void __init pxa27x_dt_init(void)
+{
+	of_platform_populate(NULL, of_default_bus_match_table,
+			     pxa27x_auxdata_lookup, NULL);
+}
+
+static const char * const pxa27x_dt_board_compat[] __initconst = {
+	"marvell,pxa270",
+	"marvell,pxa271",
+	"marvell,pxa272",
+	NULL,
+};
+
+#endif
+
+#ifdef CONFIG_PXA27x
+DT_MACHINE_START(PXA27X_DT, "Marvell PXA27x (Device Tree Support)")
+	.map_io		= pxa27x_map_io,
+	.init_irq	= pxa27x_dt_init_irq,
+	.handle_irq	= pxa27x_handle_irq,
+	.init_time	= pxa_timer_init,
+	.restart	= pxa_restart,
+	.init_machine	= pxa27x_dt_init,
+	.dt_compat	= pxa27x_dt_board_compat,
+MACHINE_END
+
+#endif
-- 
1.8.4.2

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

* [PATCH v3 08/21] ARM: pxa27x: device tree support ICP DAS LP-8x4x
@ 2013-12-17 19:37             ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-17 19:37 UTC (permalink / raw)
  To: linux-arm-kernel

ICP DAS calls LP-8x4x 'programmable automation controller'. It is
an industrial computer based on PXA270 SoC. They ship it with a 2.6.19
kernel and proprietary kernel module and userspace library to access
its industrial IO.

This patch allows to boot the device with a modern kernel with device
tree. It adds support for:
* MMC card interface on PXA270
* USB 1.1 port on PXA270
* 2 NOR flash devices
* 2 onboard ethernet Davicom DM9000 devices
* 3 serial UART ports on PXA270
* front panel red LED
* 64bit 1-wire system ID chip
* 16 kiB EEPROM (reading)

Support for these devices will be added in separate patches, since
they are not currently supported by the kernel:
* DS1302 RTC
* 512kiB SRAM
* FPGA irq chip
* 3 built-in 16550A serial UART ports
* industrial IO parallel bus
* 10 position rotary switch
* 8 pin DIP switch
* 16 kiB EEPROM (writing)
* serial interface for digital and analog industrial IO modules on
  parallel bus (all I-87... modules)
* digital and analog industrial IO modules for parallel bus:
  ** I-8024 4 port analog output
  ** I-8041 32 port digital output
  ** I-8042 16 port digital output/16 port digital input

Not supported for now:
* VGA interface on PXA270 for lack of dts binding
* the rest of parallel bus (I-8...) modules for lack of hardware
* GPIO reset for lack of relevance (watchdog reset is working)

NOTE: USB support requires U-Boot patch series which setups GPIO.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Daniel Mack <zonque@gmail.com>
CC: Arnd Bergmann <arnd@arndb.de>
---
   v2..v3
   * added extbus which maps synchronous, static, and variable-latency
     I/O (VLIO) interfaces of PXA27x SoC as suggested by Arnd Bergmann
   * map is placed into platform include
   * configured existing kernel drivers to support:
     - front panel LED using gpio-leds
     - 64bit 1-wire system ID chip using w1-gpio
     - 16 kiB EEPROM using at24 over i2c-gpio
   * number change (06/16 -> 08/21)

   v1..v2
   * drop left-over extern declaration
   * use of_have_populated_dt() instead of a static variable
   * drop wildcards in compatible
   * drop machine-special machine description
   * number changed from 9 to 6 (dropped patches)

 arch/arm/boot/dts/Makefile          |   1 +
 arch/arm/boot/dts/pxa27x-lp8x4x.dts | 153 ++++++++++++++++++++++++++++++++
 arch/arm/boot/dts/pxa27x.dtsi       |  17 ++++
 arch/arm/configs/lp8x4x_defconfig   | 168 ++++++++++++++++++++++++++++++++++++
 arch/arm/mach-pxa/Kconfig           |  15 ++++
 arch/arm/mach-pxa/Makefile          |   1 +
 arch/arm/mach-pxa/pxa27x-dt.c       |  64 ++++++++++++++
 7 files changed, 419 insertions(+)
 create mode 100644 arch/arm/boot/dts/pxa27x-lp8x4x.dts
 create mode 100644 arch/arm/configs/lp8x4x_defconfig
 create mode 100644 arch/arm/mach-pxa/pxa27x-dt.c

diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index d57c1a6..c4752ff 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -206,6 +206,7 @@ dtb-$(CONFIG_ARCH_OMAP2PLUS) += omap2420-h4.dtb \
 	dra7-evm.dtb
 dtb-$(CONFIG_ARCH_ORION5X) += orion5x-lacie-ethernet-disk-mini-v2.dtb
 dtb-$(CONFIG_ARCH_PRIMA2) += prima2-evb.dtb
+dtb-$(CONFIG_MACH_PXA27X_DT) += pxa27x-lp8x4x.dtb
 dtb-$(CONFIG_ARCH_U8500) += ste-snowball.dtb \
 	ste-hrefprev60-stuib.dtb \
 	ste-hrefprev60-tvk.dtb \
diff --git a/arch/arm/boot/dts/pxa27x-lp8x4x.dts b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
new file mode 100644
index 0000000..6a780fe
--- /dev/null
+++ b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
@@ -0,0 +1,153 @@
+/* Device tree for ICP DAS LP-8x4x */
+/dts-v1/;
+
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include "pxa27x.dtsi"
+
+/ {
+	model = "ICP DAS LP-8x4x programmable automation controller";
+	compatible = "marvell,lp8x4x", "marvell,pxa270";
+
+	aliases {
+		ethernet0 = &eth0;
+		ethernet1 = &eth1;
+	};
+
+	memory {
+		reg = <0xa0000000 0x08000000>;
+	};
+
+	regulators {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		vmmc: regulator at 0 {
+			compatible = "regulator-fixed";
+			reg = <0>;
+			regulator-name = "vmmc";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-always-on;
+		};
+	};
+
+	pxabus {
+		pxairq: interrupt-controller at 40d00000 {
+			marvell,intc-priority;
+			marvell,intc-nr-irqs = <34>;
+		};
+
+		uart at 40100000 {
+			status = "okay";
+		};
+
+		uart at 40200000 {
+			status = "okay";
+		};
+
+		uart at 40700000 {
+			status = "okay";
+		};
+
+		mmc at 41100000 {
+			status = "okay";
+			vmmc-supply = <&vmmc>;
+		};
+
+		ohci at 4c000000 {
+			status = "okay";
+			marvell,port-mode = <3>;
+			marvell,oc-mode-perport;
+			marvell,enable-port1;
+		};
+
+		leds {
+			compatible = "gpio-leds";
+
+			status {
+				gpios = <&gpio 84 1>;
+				linux,default-trigger = "heartbeat";
+			};
+		};
+
+		i2c: i2c-gpio {
+			compatible = "i2c-gpio";
+			gpios = <&gpio 22 0 /* sda */
+				 &gpio 12 0 /* scl */>;
+			i2c-gpio,delay-us = <1>;
+			i2c-gpio,timeout-ms = <1>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			eeprom at 50 {
+				compatible = "atmel,24c128";
+				reg = <0x50>;
+				pagesize = <64>;
+			};
+		};
+
+		w1: w1-gpio {
+			compatible = "w1-gpio";
+			gpios = <&gpio 83 0>;
+		};
+	};
+
+	extbus {
+		flash at 0 {
+			compatible = "cfi-flash";
+			reg = <0 0 0x02000000>;
+			bank-width = <4>;
+			device-width = <2>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			fs at 0 {
+				label = "u-boot";
+				reg = <0 0x40000>;
+			};
+			fs at 40000 {
+				label = "settings";
+				reg = <0x40000 0x40000>;
+			};
+			fs at 80000 {
+				label = "kernel";
+				reg = <0x80000 0x280000>;
+			};
+			fs at 300000 {
+				label = "root_fs";
+				reg = <0x300000 0x1d00000>;
+			};
+		};
+
+		flash at 1 {
+			compatible = "cfi-flash";
+			reg = <1 0x0 0x01000000>;
+			bank-width = <2>;
+			device-width = <1>;
+		};
+
+		netio at 3 {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0 3 0 0x02000000>;
+			interrupt-parent = <&gpio>;
+
+			eth0: eth at 0 {
+				compatible = "davicom,dm9000";
+				reg = <0x0 0x2
+				       0x4000 0x2>;
+				interrupts = <9 IRQ_TYPE_EDGE_RISING>;
+				status = "okay";
+			};
+
+			eth1: eth at 1000000 {
+				compatible = "davicom,dm9000";
+				reg = <0x1000000 0x2
+				       0x1004000 0x2>;
+				interrupts = <82 IRQ_TYPE_EDGE_RISING>;
+				status = "okay";
+			};
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/pxa27x.dtsi b/arch/arm/boot/dts/pxa27x.dtsi
index c2a90c5..29d878d 100644
--- a/arch/arm/boot/dts/pxa27x.dtsi
+++ b/arch/arm/boot/dts/pxa27x.dtsi
@@ -31,4 +31,21 @@
 			dma-names = "rx", "tx";
 		};
 	};
+
+	extbus {
+		/*
+		 * PXA27x synchrous, static and
+		 * variable-latency IO interfaces
+		 */
+	        compatible = "simple-bus";
+
+		#address-cells = <2>; /* first cell is nCS, second is address */
+		#size-cells = <1>;
+		ranges = <0 0 0 0x04000000
+			  1 0 0x04000000 0x04000000
+			  2 0 0x08000000 0x04000000
+			  3 0 0x0c000000 0x04000000
+			  4 0 0x10000000 0x04000000
+			  5 0 0x14000000 0x04000000>;
+	};
 };
diff --git a/arch/arm/configs/lp8x4x_defconfig b/arch/arm/configs/lp8x4x_defconfig
new file mode 100644
index 0000000..9f1efb6
--- /dev/null
+++ b/arch/arm/configs/lp8x4x_defconfig
@@ -0,0 +1,168 @@
+# CONFIG_LOCALVERSION_AUTO is not set
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_RCU_BOOST=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_NS is not set
+# CONFIG_IPC_NS is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+# CONFIG_UID16 is not set
+# CONFIG_SHMEM is not set
+CONFIG_EMBEDDED=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_SLOB=y
+CONFIG_JUMP_LABEL=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+# CONFIG_LBDAF is not set
+CONFIG_BLK_CMDLINE_PARSER=y
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_ARCH_PXA=y
+CONFIG_MACH_PXA27X_DT=y
+# CONFIG_ARM_THUMB is not set
+CONFIG_PREEMPT=y
+CONFIG_AEABI=y
+# CONFIG_COMPACTION is not set
+# CONFIG_CROSS_MEMORY_ATTACH is not set
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="init=/sbin/init root=/dev/mmcblk0p1 rw rootfstype=ext4 console=ttyS0,115200 mem=128M rootwait"
+# CONFIG_SUSPEND is not set
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_BRIDGE=m
+CONFIG_BRIDGE_VLAN_FILTERING=y
+CONFIG_VLAN_8021Q=m
+CONFIG_VLAN_8021Q_GVRP=y
+CONFIG_VLAN_8021Q_MVRP=y
+# CONFIG_WIRELESS is not set
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+# CONFIG_FW_LOADER is not set
+CONFIG_MTD=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_CFI_GEOMETRY=y
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_PHYSMAP_OF=y
+CONFIG_PROC_DEVICETREE=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_LOOP_MIN_COUNT=2
+CONFIG_EEPROM_AT24=m
+CONFIG_SCSI=y
+# CONFIG_SCSI_PROC_FS is not set
+CONFIG_BLK_DEV_SD=y
+# CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_NETDEVICES=y
+CONFIG_BONDING=m
+CONFIG_MACVLAN=m
+CONFIG_MACVTAP=m
+CONFIG_TUN=m
+# CONFIG_NET_VENDOR_ARC is not set
+# CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_CIRRUS is not set
+CONFIG_DM9000=y
+CONFIG_DM9000_FORCE_SIMPLE_PHY_POLL=y
+# CONFIG_NET_VENDOR_FARADAY is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+CONFIG_PPP=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPPOE=m
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_SLIP=m
+CONFIG_SLIP_COMPRESSED=y
+# CONFIG_WLAN is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=800
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=600
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_SERIO is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_8250=y
+# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=40
+CONFIG_SERIAL_8250_RUNTIME_UARTS=40
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_PXA=y
+CONFIG_HW_RANDOM=y
+CONFIG_I2C=m
+# CONFIG_I2C_COMPAT is not set
+CONFIG_I2C_GPIO=m
+CONFIG_W1=m
+CONFIG_W1_MASTER_GPIO=m
+CONFIG_W1_SLAVE_SMEM=m
+# CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_SA1100_WATCHDOG=m
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_FB=y
+CONFIG_FB_PXA=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_LOGO=y
+CONFIG_USB=m
+CONFIG_USB_OHCI_HCD=m
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+CONFIG_USB_STORAGE=m
+CONFIG_USB_SERIAL=m
+CONFIG_MMC=y
+CONFIG_MMC_PXA=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_PXA=m
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_EXT2_FS=m
+CONFIG_EXT3_FS=y
+CONFIG_EXT4_FS=y
+CONFIG_REISERFS_FS=m
+CONFIG_ISO9660_FS=m
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_NTFS_FS=m
+CONFIG_NTFS_RW=y
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V4=y
+CONFIG_ROOT_NFS=y
+CONFIG_CIFS=m
+CONFIG_CIFS_STATS=y
+CONFIG_CODA_FS=m
+CONFIG_NLS_DEFAULT="cp855"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_855=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_UTF8=y
+CONFIG_PRINTK_TIME=y
diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig
index 96100db..df3a79d 100644
--- a/arch/arm/mach-pxa/Kconfig
+++ b/arch/arm/mach-pxa/Kconfig
@@ -4,6 +4,21 @@ menu "Intel PXA2xx/PXA3xx Implementations"
 
 comment "Intel/Marvell Dev Platforms (sorted by hardware release time)"
 
+config MACH_PXA27X_DT
+	bool "Support PXA27x platforms from device tree"
+	select PXA27x
+	select USE_OF
+	help
+	  Include support for Marvell PXA27x based platforms using
+	  the device tree.
+
+	  While MACH_PXA27X_DT when enabled should boot any PXA27x
+	  compatible machine, it still makes sense to select specific
+	  machines. Those options will select required features and
+	  provide per-machine errata workarounds.
+
+	  If unsure, say Y.
+
 config MACH_PXA3XX_DT
 	bool "Support PXA3xx platforms from device tree"
 	select CPU_PXA300
diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile
index 648867a..adaa72a 100644
--- a/arch/arm/mach-pxa/Makefile
+++ b/arch/arm/mach-pxa/Makefile
@@ -20,6 +20,7 @@ obj-$(CONFIG_CPU_PXA930)	+= pxa930.o
 # NOTE: keep the order of boards in accordance to their order in Kconfig
 
 # Device Tree support
+obj-$(CONFIG_MACH_PXA27X_DT)	+= pxa27x-dt.o
 obj-$(CONFIG_MACH_PXA3XX_DT)	+= pxa-dt.o
 
 # Intel/Marvell Dev Platforms
diff --git a/arch/arm/mach-pxa/pxa27x-dt.c b/arch/arm/mach-pxa/pxa27x-dt.c
new file mode 100644
index 0000000..865cf46
--- /dev/null
+++ b/arch/arm/mach-pxa/pxa27x-dt.c
@@ -0,0 +1,64 @@
+/*
+ *  linux/arch/arm/mach-pxa/pxa27x-dt.c
+ *
+ *  Copyright (C) 2013 Sergei Ianovich
+ *
+ *  based mostly on linux/arch/arm/mach-pxa/pxa-dt.c by Daniel Mack
+ *
+ *  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
+ *  publishhed by the Free Software Foundation.
+ */
+
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <asm/io.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <mach/irqs.h>
+#include <mach/pxa27x.h>
+
+#include "generic.h"
+
+#ifdef CONFIG_PXA27x
+static const struct of_dev_auxdata pxa27x_auxdata_lookup[] __initconst = {
+	OF_DEV_AUXDATA("mrvl,pxa-uart",	    0x40100000, "pxa2xx-uart.0", NULL),
+	OF_DEV_AUXDATA("mrvl,pxa-uart",	    0x40200000, "pxa2xx-uart.1", NULL),
+	OF_DEV_AUXDATA("mrvl,pxa-uart",	    0x40700000, "pxa2xx-uart.2", NULL),
+	OF_DEV_AUXDATA("mrvl,pxa-uart",	    0x41600000, "pxa2xx-uart.3", NULL),
+	OF_DEV_AUXDATA("marvell,pxa-mmc",   0x41100000, "pxa2xx-mci.0", NULL),
+	OF_DEV_AUXDATA("intel,pxa27x-gpio", 0x40e00000, "pxa27x-gpio", NULL),
+	OF_DEV_AUXDATA("marvell,pxa-ohci",  0x4c000000, "pxa27x-ohci", NULL),
+	OF_DEV_AUXDATA("mrvl,pxa-i2c",	    0x40301680, "pxa2xx-i2c.0", NULL),
+	{}
+};
+
+static void __init pxa27x_dt_init(void)
+{
+	of_platform_populate(NULL, of_default_bus_match_table,
+			     pxa27x_auxdata_lookup, NULL);
+}
+
+static const char * const pxa27x_dt_board_compat[] __initconst = {
+	"marvell,pxa270",
+	"marvell,pxa271",
+	"marvell,pxa272",
+	NULL,
+};
+
+#endif
+
+#ifdef CONFIG_PXA27x
+DT_MACHINE_START(PXA27X_DT, "Marvell PXA27x (Device Tree Support)")
+	.map_io		= pxa27x_map_io,
+	.init_irq	= pxa27x_dt_init_irq,
+	.handle_irq	= pxa27x_handle_irq,
+	.init_time	= pxa_timer_init,
+	.restart	= pxa_restart,
+	.init_machine	= pxa27x_dt_init,
+	.dt_compat	= pxa27x_dt_board_compat,
+MACHINE_END
+
+#endif
-- 
1.8.4.2

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

* [PATCH v3 09/21] rtc: support DS1302 RTC on ICP DAS LP-8x4x
  2013-12-17 19:37           ` Sergei Ianovich
  (?)
@ 2013-12-17 19:37             ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-17 19:37 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Rob Landley, Russell King,
	Alessandro Zummo, Grant Likely, open list:OPEN FIRMWARE AND...,
	open list:DOCUMENTATION, rtc-linux

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
   v2..v3
   * use usleep_range instead of custom nsleep
   * number change (07/16 -> 09/21)

   v0..v2
   * use device tree
   * use devm helpers where possible

 .../devicetree/bindings/rtc/rtc-ds1302.txt         |  14 +++
 arch/arm/boot/dts/pxa27x-lp8x4x.dts                |  13 +++
 arch/arm/configs/lp8x4x_defconfig                  |   1 +
 drivers/rtc/Kconfig                                |   2 +-
 drivers/rtc/rtc-ds1302.c                           | 100 ++++++++++++++++++++-
 5 files changed, 127 insertions(+), 3 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/rtc/rtc-ds1302.txt

diff --git a/Documentation/devicetree/bindings/rtc/rtc-ds1302.txt b/Documentation/devicetree/bindings/rtc/rtc-ds1302.txt
new file mode 100644
index 0000000..876297c
--- /dev/null
+++ b/Documentation/devicetree/bindings/rtc/rtc-ds1302.txt
@@ -0,0 +1,14 @@
+* Dallas Semiconductor DS-1302 RTC
+
+Simple device which could be used to store date/time between reboots.
+
+Required properties:
+- compatible : Should be "ds,rtc-ds1302"
+- reg : Should be address and size of IO memory region
+
+Examples:
+
+rtc@40900000 {
+	compatible = "ds,rtc-ds1302";
+	reg = <0x1700901c 0x1>;
+};
diff --git a/arch/arm/boot/dts/pxa27x-lp8x4x.dts b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
index 6a780fe..872c386 100644
--- a/arch/arm/boot/dts/pxa27x-lp8x4x.dts
+++ b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
@@ -149,5 +149,18 @@
 				status = "okay";
 			};
 		};
+
+		fpga@5 {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0 5 0x3000000 0x10000>;
+
+			rtc@901c {
+				compatible = "ds,rtc-ds1302";
+				reg = <0x901c 0x1>;
+				status = "okay";
+			};
+		};
 	};
 };
diff --git a/arch/arm/configs/lp8x4x_defconfig b/arch/arm/configs/lp8x4x_defconfig
index 9f1efb6..d60e37a 100644
--- a/arch/arm/configs/lp8x4x_defconfig
+++ b/arch/arm/configs/lp8x4x_defconfig
@@ -141,6 +141,7 @@ CONFIG_LEDS_GPIO=y
 CONFIG_LEDS_TRIGGERS=y
 CONFIG_LEDS_TRIGGER_HEARTBEAT=y
 CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_DS1302=y
 CONFIG_RTC_DRV_PXA=m
 # CONFIG_IOMMU_SUPPORT is not set
 CONFIG_EXT2_FS=m
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 0077302..501055f 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -676,7 +676,7 @@ config RTC_DRV_DS1286
 
 config RTC_DRV_DS1302
 	tristate "Dallas DS1302"
-	depends on SH_SECUREEDGE5410
+	depends on SH_SECUREEDGE5410 || (ARCH_PXA && HIGH_RES_TIMERS)
 	help
 	  If you say yes here you get support for the Dallas DS1302 RTC chips.
 
diff --git a/drivers/rtc/rtc-ds1302.c b/drivers/rtc/rtc-ds1302.c
index 07e8d79..24a75d8 100644
--- a/drivers/rtc/rtc-ds1302.c
+++ b/drivers/rtc/rtc-ds1302.c
@@ -50,7 +50,7 @@
 #define ds1302_set_tx()
 #define ds1302_set_rx()
 
-static inline int ds1302_hw_init(void)
+static inline int ds1302_hw_init(struct platform_device *pdev)
 {
 	return 0;
 }
@@ -86,6 +86,101 @@ static inline int ds1302_rxbit(void)
 	return !!(get_dp() & RTC_IODATA);
 }
 
+#elif defined(CONFIG_ARCH_PXA) && defined(CONFIG_HIGH_RES_TIMERS)
+
+#include <linux/delay.h>
+#include <linux/of.h>
+
+#define	RTC_CE		0x01
+#define	RTC_CLK		0x02
+#define	RTC_nWE		0x04
+#define	RTC_IODATA	0x08
+
+static unsigned long ds1302_state;
+
+static void *mem;
+
+static inline int ds1302_hw_init(struct platform_device *pdev)
+{
+	struct resource *r;
+
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!r)
+		return -ENODEV;
+
+	mem = devm_ioremap_resource(&pdev->dev, r);
+	if (!mem)
+		return -EFAULT;
+
+	return 0;
+}
+
+static inline void ds1302_reset(void)
+{
+	ds1302_state = 0;
+	iowrite8(ds1302_state, mem);
+	usleep_range(4, 5);
+}
+
+static inline void ds1302_clock(void)
+{
+	usleep_range(1, 2);
+	ds1302_state |= RTC_CLK;
+	iowrite8(ds1302_state, mem);
+	usleep_range(1, 2);
+	ds1302_state &= ~RTC_CLK;
+	iowrite8(ds1302_state, mem);
+}
+
+static inline void ds1302_start(void)
+{
+	ds1302_state &= ~RTC_CLK;
+	ds1302_state |= RTC_CE;
+	iowrite8(ds1302_state, mem);
+	usleep_range(3, 4);
+}
+
+static inline void ds1302_stop(void)
+{
+	ds1302_state &= ~RTC_CE;
+	iowrite8(ds1302_state, mem);
+}
+
+static inline void ds1302_set_tx(void)
+{
+	ds1302_state &= ~RTC_nWE;
+	iowrite8(ds1302_state, mem);
+}
+
+static inline void ds1302_set_rx(void)
+{
+	ds1302_state |= RTC_nWE;
+	iowrite8(ds1302_state, mem);
+}
+
+static inline void ds1302_txbit(int bit)
+{
+	if (bit)
+		ds1302_state |= RTC_IODATA;
+	else
+		ds1302_state &= ~RTC_IODATA;
+	iowrite8(ds1302_state, mem);
+}
+
+static inline int ds1302_rxbit(void)
+{
+	return ioread8(mem) & 0x1;
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id ds1302_dt_ids[] = {
+	{ .compatible = "ds,rtc-ds1302" },
+	{ }
+};
+
+MODULE_DEVICE_TABLE(of, ds1302_dt_ids);
+#endif
+
 #else
 #error "Add support for your platform"
 #endif
@@ -216,7 +311,7 @@ static int __init ds1302_rtc_probe(struct platform_device *pdev)
 {
 	struct rtc_device *rtc;
 
-	if (ds1302_hw_init()) {
+	if (ds1302_hw_init(pdev)) {
 		dev_err(&pdev->dev, "Failed to init communication channel");
 		return -EINVAL;
 	}
@@ -245,6 +340,7 @@ static struct platform_driver ds1302_platform_driver = {
 	.driver		= {
 		.name	= DRV_NAME,
 		.owner	= THIS_MODULE,
+		.of_match_table = of_match_ptr(ds1302_dt_ids),
 	},
 };
 
-- 
1.8.4.2


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

* [PATCH v3 09/21] rtc: support DS1302 RTC on ICP DAS LP-8x4x
@ 2013-12-17 19:37             ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-17 19:37 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Rob Landley, Russell King,
	Alessandro Zummo, Grant Likely, open list:OPEN FIRMWARE AND...,
	open list:DOCUMENTATION, rtc-linux

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
   v2..v3
   * use usleep_range instead of custom nsleep
   * number change (07/16 -> 09/21)

   v0..v2
   * use device tree
   * use devm helpers where possible

 .../devicetree/bindings/rtc/rtc-ds1302.txt         |  14 +++
 arch/arm/boot/dts/pxa27x-lp8x4x.dts                |  13 +++
 arch/arm/configs/lp8x4x_defconfig                  |   1 +
 drivers/rtc/Kconfig                                |   2 +-
 drivers/rtc/rtc-ds1302.c                           | 100 ++++++++++++++++++++-
 5 files changed, 127 insertions(+), 3 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/rtc/rtc-ds1302.txt

diff --git a/Documentation/devicetree/bindings/rtc/rtc-ds1302.txt b/Documentation/devicetree/bindings/rtc/rtc-ds1302.txt
new file mode 100644
index 0000000..876297c
--- /dev/null
+++ b/Documentation/devicetree/bindings/rtc/rtc-ds1302.txt
@@ -0,0 +1,14 @@
+* Dallas Semiconductor DS-1302 RTC
+
+Simple device which could be used to store date/time between reboots.
+
+Required properties:
+- compatible : Should be "ds,rtc-ds1302"
+- reg : Should be address and size of IO memory region
+
+Examples:
+
+rtc@40900000 {
+	compatible = "ds,rtc-ds1302";
+	reg = <0x1700901c 0x1>;
+};
diff --git a/arch/arm/boot/dts/pxa27x-lp8x4x.dts b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
index 6a780fe..872c386 100644
--- a/arch/arm/boot/dts/pxa27x-lp8x4x.dts
+++ b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
@@ -149,5 +149,18 @@
 				status = "okay";
 			};
 		};
+
+		fpga@5 {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0 5 0x3000000 0x10000>;
+
+			rtc@901c {
+				compatible = "ds,rtc-ds1302";
+				reg = <0x901c 0x1>;
+				status = "okay";
+			};
+		};
 	};
 };
diff --git a/arch/arm/configs/lp8x4x_defconfig b/arch/arm/configs/lp8x4x_defconfig
index 9f1efb6..d60e37a 100644
--- a/arch/arm/configs/lp8x4x_defconfig
+++ b/arch/arm/configs/lp8x4x_defconfig
@@ -141,6 +141,7 @@ CONFIG_LEDS_GPIO=y
 CONFIG_LEDS_TRIGGERS=y
 CONFIG_LEDS_TRIGGER_HEARTBEAT=y
 CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_DS1302=y
 CONFIG_RTC_DRV_PXA=m
 # CONFIG_IOMMU_SUPPORT is not set
 CONFIG_EXT2_FS=m
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 0077302..501055f 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -676,7 +676,7 @@ config RTC_DRV_DS1286
 
 config RTC_DRV_DS1302
 	tristate "Dallas DS1302"
-	depends on SH_SECUREEDGE5410
+	depends on SH_SECUREEDGE5410 || (ARCH_PXA && HIGH_RES_TIMERS)
 	help
 	  If you say yes here you get support for the Dallas DS1302 RTC chips.
 
diff --git a/drivers/rtc/rtc-ds1302.c b/drivers/rtc/rtc-ds1302.c
index 07e8d79..24a75d8 100644
--- a/drivers/rtc/rtc-ds1302.c
+++ b/drivers/rtc/rtc-ds1302.c
@@ -50,7 +50,7 @@
 #define ds1302_set_tx()
 #define ds1302_set_rx()
 
-static inline int ds1302_hw_init(void)
+static inline int ds1302_hw_init(struct platform_device *pdev)
 {
 	return 0;
 }
@@ -86,6 +86,101 @@ static inline int ds1302_rxbit(void)
 	return !!(get_dp() & RTC_IODATA);
 }
 
+#elif defined(CONFIG_ARCH_PXA) && defined(CONFIG_HIGH_RES_TIMERS)
+
+#include <linux/delay.h>
+#include <linux/of.h>
+
+#define	RTC_CE		0x01
+#define	RTC_CLK		0x02
+#define	RTC_nWE		0x04
+#define	RTC_IODATA	0x08
+
+static unsigned long ds1302_state;
+
+static void *mem;
+
+static inline int ds1302_hw_init(struct platform_device *pdev)
+{
+	struct resource *r;
+
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!r)
+		return -ENODEV;
+
+	mem = devm_ioremap_resource(&pdev->dev, r);
+	if (!mem)
+		return -EFAULT;
+
+	return 0;
+}
+
+static inline void ds1302_reset(void)
+{
+	ds1302_state = 0;
+	iowrite8(ds1302_state, mem);
+	usleep_range(4, 5);
+}
+
+static inline void ds1302_clock(void)
+{
+	usleep_range(1, 2);
+	ds1302_state |= RTC_CLK;
+	iowrite8(ds1302_state, mem);
+	usleep_range(1, 2);
+	ds1302_state &= ~RTC_CLK;
+	iowrite8(ds1302_state, mem);
+}
+
+static inline void ds1302_start(void)
+{
+	ds1302_state &= ~RTC_CLK;
+	ds1302_state |= RTC_CE;
+	iowrite8(ds1302_state, mem);
+	usleep_range(3, 4);
+}
+
+static inline void ds1302_stop(void)
+{
+	ds1302_state &= ~RTC_CE;
+	iowrite8(ds1302_state, mem);
+}
+
+static inline void ds1302_set_tx(void)
+{
+	ds1302_state &= ~RTC_nWE;
+	iowrite8(ds1302_state, mem);
+}
+
+static inline void ds1302_set_rx(void)
+{
+	ds1302_state |= RTC_nWE;
+	iowrite8(ds1302_state, mem);
+}
+
+static inline void ds1302_txbit(int bit)
+{
+	if (bit)
+		ds1302_state |= RTC_IODATA;
+	else
+		ds1302_state &= ~RTC_IODATA;
+	iowrite8(ds1302_state, mem);
+}
+
+static inline int ds1302_rxbit(void)
+{
+	return ioread8(mem) & 0x1;
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id ds1302_dt_ids[] = {
+	{ .compatible = "ds,rtc-ds1302" },
+	{ }
+};
+
+MODULE_DEVICE_TABLE(of, ds1302_dt_ids);
+#endif
+
 #else
 #error "Add support for your platform"
 #endif
@@ -216,7 +311,7 @@ static int __init ds1302_rtc_probe(struct platform_device *pdev)
 {
 	struct rtc_device *rtc;
 
-	if (ds1302_hw_init()) {
+	if (ds1302_hw_init(pdev)) {
 		dev_err(&pdev->dev, "Failed to init communication channel");
 		return -EINVAL;
 	}
@@ -245,6 +340,7 @@ static struct platform_driver ds1302_platform_driver = {
 	.driver		= {
 		.name	= DRV_NAME,
 		.owner	= THIS_MODULE,
+		.of_match_table = of_match_ptr(ds1302_dt_ids),
 	},
 };
 
-- 
1.8.4.2

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

* [PATCH v3 09/21] rtc: support DS1302 RTC on ICP DAS LP-8x4x
@ 2013-12-17 19:37             ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-17 19:37 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
   v2..v3
   * use usleep_range instead of custom nsleep
   * number change (07/16 -> 09/21)

   v0..v2
   * use device tree
   * use devm helpers where possible

 .../devicetree/bindings/rtc/rtc-ds1302.txt         |  14 +++
 arch/arm/boot/dts/pxa27x-lp8x4x.dts                |  13 +++
 arch/arm/configs/lp8x4x_defconfig                  |   1 +
 drivers/rtc/Kconfig                                |   2 +-
 drivers/rtc/rtc-ds1302.c                           | 100 ++++++++++++++++++++-
 5 files changed, 127 insertions(+), 3 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/rtc/rtc-ds1302.txt

diff --git a/Documentation/devicetree/bindings/rtc/rtc-ds1302.txt b/Documentation/devicetree/bindings/rtc/rtc-ds1302.txt
new file mode 100644
index 0000000..876297c
--- /dev/null
+++ b/Documentation/devicetree/bindings/rtc/rtc-ds1302.txt
@@ -0,0 +1,14 @@
+* Dallas Semiconductor DS-1302 RTC
+
+Simple device which could be used to store date/time between reboots.
+
+Required properties:
+- compatible : Should be "ds,rtc-ds1302"
+- reg : Should be address and size of IO memory region
+
+Examples:
+
+rtc at 40900000 {
+	compatible = "ds,rtc-ds1302";
+	reg = <0x1700901c 0x1>;
+};
diff --git a/arch/arm/boot/dts/pxa27x-lp8x4x.dts b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
index 6a780fe..872c386 100644
--- a/arch/arm/boot/dts/pxa27x-lp8x4x.dts
+++ b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
@@ -149,5 +149,18 @@
 				status = "okay";
 			};
 		};
+
+		fpga at 5 {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0 5 0x3000000 0x10000>;
+
+			rtc at 901c {
+				compatible = "ds,rtc-ds1302";
+				reg = <0x901c 0x1>;
+				status = "okay";
+			};
+		};
 	};
 };
diff --git a/arch/arm/configs/lp8x4x_defconfig b/arch/arm/configs/lp8x4x_defconfig
index 9f1efb6..d60e37a 100644
--- a/arch/arm/configs/lp8x4x_defconfig
+++ b/arch/arm/configs/lp8x4x_defconfig
@@ -141,6 +141,7 @@ CONFIG_LEDS_GPIO=y
 CONFIG_LEDS_TRIGGERS=y
 CONFIG_LEDS_TRIGGER_HEARTBEAT=y
 CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_DS1302=y
 CONFIG_RTC_DRV_PXA=m
 # CONFIG_IOMMU_SUPPORT is not set
 CONFIG_EXT2_FS=m
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 0077302..501055f 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -676,7 +676,7 @@ config RTC_DRV_DS1286
 
 config RTC_DRV_DS1302
 	tristate "Dallas DS1302"
-	depends on SH_SECUREEDGE5410
+	depends on SH_SECUREEDGE5410 || (ARCH_PXA && HIGH_RES_TIMERS)
 	help
 	  If you say yes here you get support for the Dallas DS1302 RTC chips.
 
diff --git a/drivers/rtc/rtc-ds1302.c b/drivers/rtc/rtc-ds1302.c
index 07e8d79..24a75d8 100644
--- a/drivers/rtc/rtc-ds1302.c
+++ b/drivers/rtc/rtc-ds1302.c
@@ -50,7 +50,7 @@
 #define ds1302_set_tx()
 #define ds1302_set_rx()
 
-static inline int ds1302_hw_init(void)
+static inline int ds1302_hw_init(struct platform_device *pdev)
 {
 	return 0;
 }
@@ -86,6 +86,101 @@ static inline int ds1302_rxbit(void)
 	return !!(get_dp() & RTC_IODATA);
 }
 
+#elif defined(CONFIG_ARCH_PXA) && defined(CONFIG_HIGH_RES_TIMERS)
+
+#include <linux/delay.h>
+#include <linux/of.h>
+
+#define	RTC_CE		0x01
+#define	RTC_CLK		0x02
+#define	RTC_nWE		0x04
+#define	RTC_IODATA	0x08
+
+static unsigned long ds1302_state;
+
+static void *mem;
+
+static inline int ds1302_hw_init(struct platform_device *pdev)
+{
+	struct resource *r;
+
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!r)
+		return -ENODEV;
+
+	mem = devm_ioremap_resource(&pdev->dev, r);
+	if (!mem)
+		return -EFAULT;
+
+	return 0;
+}
+
+static inline void ds1302_reset(void)
+{
+	ds1302_state = 0;
+	iowrite8(ds1302_state, mem);
+	usleep_range(4, 5);
+}
+
+static inline void ds1302_clock(void)
+{
+	usleep_range(1, 2);
+	ds1302_state |= RTC_CLK;
+	iowrite8(ds1302_state, mem);
+	usleep_range(1, 2);
+	ds1302_state &= ~RTC_CLK;
+	iowrite8(ds1302_state, mem);
+}
+
+static inline void ds1302_start(void)
+{
+	ds1302_state &= ~RTC_CLK;
+	ds1302_state |= RTC_CE;
+	iowrite8(ds1302_state, mem);
+	usleep_range(3, 4);
+}
+
+static inline void ds1302_stop(void)
+{
+	ds1302_state &= ~RTC_CE;
+	iowrite8(ds1302_state, mem);
+}
+
+static inline void ds1302_set_tx(void)
+{
+	ds1302_state &= ~RTC_nWE;
+	iowrite8(ds1302_state, mem);
+}
+
+static inline void ds1302_set_rx(void)
+{
+	ds1302_state |= RTC_nWE;
+	iowrite8(ds1302_state, mem);
+}
+
+static inline void ds1302_txbit(int bit)
+{
+	if (bit)
+		ds1302_state |= RTC_IODATA;
+	else
+		ds1302_state &= ~RTC_IODATA;
+	iowrite8(ds1302_state, mem);
+}
+
+static inline int ds1302_rxbit(void)
+{
+	return ioread8(mem) & 0x1;
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id ds1302_dt_ids[] = {
+	{ .compatible = "ds,rtc-ds1302" },
+	{ }
+};
+
+MODULE_DEVICE_TABLE(of, ds1302_dt_ids);
+#endif
+
 #else
 #error "Add support for your platform"
 #endif
@@ -216,7 +311,7 @@ static int __init ds1302_rtc_probe(struct platform_device *pdev)
 {
 	struct rtc_device *rtc;
 
-	if (ds1302_hw_init()) {
+	if (ds1302_hw_init(pdev)) {
 		dev_err(&pdev->dev, "Failed to init communication channel");
 		return -EINVAL;
 	}
@@ -245,6 +340,7 @@ static struct platform_driver ds1302_platform_driver = {
 	.driver		= {
 		.name	= DRV_NAME,
 		.owner	= THIS_MODULE,
+		.of_match_table = of_match_ptr(ds1302_dt_ids),
 	},
 };
 
-- 
1.8.4.2

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

* [PATCH v3 10/21] mtd: support BB SRAM on ICP DAS LP-8x4x
  2013-12-17 19:37           ` Sergei Ianovich
  (?)
  (?)
@ 2013-12-17 19:37             ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-17 19:37 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Russell King, David Woodhouse,
	Grant Likely, Artem Bityutskiy, Robert Jarzmik, Kees Cook,
	Randy Dunlap, Philip Avinash, open list:OPEN FIRMWARE AND...,
	open list:MEMORY TECHNOLOGY...

This provides an MTD device driver for 512kB of battery backed up SRAM
on ICPDAS LP-8X4X programmable automation controllers.

SRAM chip is connected via FPGA and is not accessible without a driver,
unlike flash memory which is wired to CPU MMU.

This SRAM becomes an excellent persisent storage of volatile process
data like counter values and sensor statuses. Storing those data in
flash or mmc card is not a viable solution.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
   v2..v3
   * no changes (except number 08/16 -> 10/21)

   v0..v2
   * use device tree
   * use devm helpers where possible

 arch/arm/boot/dts/pxa27x-lp8x4x.dts |   6 +
 arch/arm/configs/lp8x4x_defconfig   |   1 +
 drivers/mtd/devices/Kconfig         |  14 +++
 drivers/mtd/devices/Makefile        |   1 +
 drivers/mtd/devices/sram_lp8x4x.c   | 227 ++++++++++++++++++++++++++++++++++++
 5 files changed, 249 insertions(+)
 create mode 100644 drivers/mtd/devices/sram_lp8x4x.c

diff --git a/arch/arm/boot/dts/pxa27x-lp8x4x.dts b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
index 872c386..07856e0 100644
--- a/arch/arm/boot/dts/pxa27x-lp8x4x.dts
+++ b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
@@ -161,6 +161,12 @@
 				reg = <0x901c 0x1>;
 				status = "okay";
 			};
+
+			sram@a000 {
+				compatible = "icpdas,sram-lp8x4x";
+				reg = <0xa000 0x1000
+				       0x901e 0x1>;
+			};
 		};
 	};
 };
diff --git a/arch/arm/configs/lp8x4x_defconfig b/arch/arm/configs/lp8x4x_defconfig
index d60e37a..17a4e6f 100644
--- a/arch/arm/configs/lp8x4x_defconfig
+++ b/arch/arm/configs/lp8x4x_defconfig
@@ -57,6 +57,7 @@ CONFIG_MTD_CFI_ADV_OPTIONS=y
 CONFIG_MTD_CFI_GEOMETRY=y
 CONFIG_MTD_CFI_INTELEXT=y
 CONFIG_MTD_PHYSMAP_OF=y
+CONFIG_MTD_SRAM_LP8X4X=y
 CONFIG_PROC_DEVICETREE=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_LOOP_MIN_COUNT=2
diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig
index 0128138..95f2075 100644
--- a/drivers/mtd/devices/Kconfig
+++ b/drivers/mtd/devices/Kconfig
@@ -217,4 +217,18 @@ config BCH_CONST_T
 	default 4
 endif
 
+config MTD_SRAM_LP8X4X
+	tristate "SRAM on ICPDAS LP-8X4X"
+	depends on OF && ARCH_PXA
+       ---help---
+	 This provides an MTD device driver for 512kiB of battery backed up SRAM
+	 on ICPDAS LP-8X4X programmable automation controllers.
+
+	 SRAM chip is connected via FPGA and is not accessible without a driver,
+	 unlike flash memory which is wired to CPU MMU.
+
+	 Say N, unless you plan to run this kernel on LP-8X4X.
+
+	 If you say M, the module will be called sram_lp8x4x.
+
 endmenu
diff --git a/drivers/mtd/devices/Makefile b/drivers/mtd/devices/Makefile
index d83bd73..56a74c9 100644
--- a/drivers/mtd/devices/Makefile
+++ b/drivers/mtd/devices/Makefile
@@ -16,6 +16,7 @@ obj-$(CONFIG_MTD_NAND_OMAP_BCH)	+= elm.o
 obj-$(CONFIG_MTD_SPEAR_SMI)	+= spear_smi.o
 obj-$(CONFIG_MTD_SST25L)	+= sst25l.o
 obj-$(CONFIG_MTD_BCM47XXSFLASH)	+= bcm47xxsflash.o
+obj-$(CONFIG_MTD_SRAM_LP8X4X)	+= sram_lp8x4x.o
 
 
 CFLAGS_docg3.o			+= -I$(src)
diff --git a/drivers/mtd/devices/sram_lp8x4x.c b/drivers/mtd/devices/sram_lp8x4x.c
new file mode 100644
index 0000000..9dc7149
--- /dev/null
+++ b/drivers/mtd/devices/sram_lp8x4x.c
@@ -0,0 +1,227 @@
+/*
+ *  linux/drivers/mtd/devices/lp8x4x_sram.c
+ *
+ *  MTD Driver for SRAM on ICPDAS LP-8x4x
+ *  Copyright (C) 2013 Sergei Ianovich <ynvich@gmail.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation or any later version.
+ */
+
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mtd/map.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/platform_device.h>
+#include <linux/of_device.h>
+#include <linux/slab.h>
+#include <linux/string_helpers.h>
+#include <linux/types.h>
+
+#include <asm/mach/flash.h>
+
+struct lp8x4x_sram_info {
+	void __iomem	*bank;
+	void __iomem	*virt;
+	struct mutex	lock;
+	unsigned	active_bank;
+	struct mtd_info	mtd;
+};
+
+static int
+lp8x4x_sram_erase(struct mtd_info *mtd, struct erase_info *instr)
+{
+	struct lp8x4x_sram_info *info = mtd->priv;
+	unsigned bank = instr->addr >> 11;
+	unsigned offset = (instr->addr & 0x7ff) << 1;
+	loff_t i;
+
+	mutex_lock(&info->lock);
+	if (unlikely(bank != info->active_bank)) {
+		info->active_bank = bank;
+		iowrite8(bank, info->bank);
+	}
+	for (i = 0; i < instr->len; i++) {
+		iowrite8(0xff, info->virt + offset);
+		offset += 2;
+		if (unlikely(offset == 0)) {
+			info->active_bank++;
+			iowrite8(info->active_bank, info->bank);
+		}
+	}
+	mutex_unlock(&info->lock);
+	instr->state = MTD_ERASE_DONE;
+	mtd_erase_callback(instr);
+
+	return 0;
+}
+
+static int
+lp8x4x_sram_write(struct mtd_info *mtd, loff_t to, size_t len,
+		size_t *retlen, const u_char *b)
+{
+	struct lp8x4x_sram_info *info = mtd->priv;
+	unsigned bank = to >> 11;
+	unsigned offset = (to & 0x7ff) << 1;
+	loff_t i;
+
+	mutex_lock(&info->lock);
+	if (unlikely(bank != info->active_bank)) {
+		info->active_bank = bank;
+		iowrite8(bank, info->bank);
+	}
+	for (i = 0; i < len; i++) {
+		iowrite8(b[i], info->virt + offset);
+		offset += 2;
+		if (unlikely(offset == 0)) {
+			info->active_bank++;
+			iowrite8(info->active_bank, info->bank);
+		}
+	}
+	mutex_unlock(&info->lock);
+	*retlen = len;
+	return 0;
+}
+
+static int
+lp8x4x_sram_read(struct mtd_info *mtd, loff_t from, size_t len,
+		size_t *retlen, u_char *b)
+{
+	struct lp8x4x_sram_info *info = mtd->priv;
+	unsigned bank = from >> 11;
+	unsigned offset = (from & 0x7ff) << 1;
+	loff_t i;
+
+	mutex_lock(&info->lock);
+	if (unlikely(bank != info->active_bank)) {
+		info->active_bank = bank;
+		iowrite8(bank, info->bank);
+	}
+	for (i = 0; i < len; i++) {
+		b[i] = ioread8(info->virt + offset);
+		offset += 2;
+		if (unlikely(offset == 0)) {
+			info->active_bank++;
+			iowrite8(info->active_bank, info->bank);
+		}
+	}
+	mutex_unlock(&info->lock);
+	*retlen = len;
+	return 0;
+}
+
+static void
+lp8x4x_sram_sync(struct mtd_info *mtd)
+{
+}
+
+static struct of_device_id of_flash_match[] = {
+	{
+		.compatible	= "icpdas,sram-lp8x4x",
+	},
+	{ },
+};
+MODULE_DEVICE_TABLE(of, of_flash_match);
+
+static const char * const probe_types[] = {
+	"cmdlinepart", "RedBoot", "ofpart", "ofoldpart", NULL };
+
+static int
+lp8x4x_sram_probe(struct platform_device *pdev)
+{
+	const struct of_device_id *match;
+	struct lp8x4x_sram_info *info;
+	struct resource *r1, *r2;
+	char sz_str[16];
+	struct mtd_part_parser_data ppdata;
+	int err = 0;
+
+	match = of_match_device(of_flash_match, &pdev->dev);
+	if (!match)
+		return -EINVAL;
+
+	r1 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	r2 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	if (!r1 || !r2)
+		return -ENODEV;
+
+	info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
+	if (!info)
+		return -ENOMEM;
+
+	info->virt =  devm_ioremap_resource(&pdev->dev, r1);
+	if (!info->virt) {
+		dev_err(&pdev->dev, "Failed to ioremap %p\n",
+		       info->virt);
+		return -EFAULT;
+	}
+
+	info->bank = devm_ioremap_resource(&pdev->dev, r2);
+	if (!info->bank) {
+		dev_err(&pdev->dev, "Failed to ioremap %p\n",
+		       info->bank);
+		return -EFAULT;
+	}
+
+	info->mtd.priv = info;
+	info->mtd.name = "SRAM";
+	info->mtd.type = MTD_RAM;
+	info->mtd.flags = MTD_CAP_RAM;
+	info->mtd.size = resource_size(r1) << 7;
+	info->mtd.erasesize = 512;
+	info->mtd.writesize = 4;
+	info->mtd._erase = lp8x4x_sram_erase;
+	info->mtd._write = lp8x4x_sram_write;
+	info->mtd._read = lp8x4x_sram_read;
+	info->mtd._sync = lp8x4x_sram_sync;
+	info->mtd.owner = THIS_MODULE;
+
+	mutex_init(&info->lock);
+	iowrite8(info->active_bank, info->bank);
+	platform_set_drvdata(pdev, info);
+
+	ppdata.of_node = pdev->dev.of_node;
+	err = mtd_device_parse_register(&info->mtd, probe_types, &ppdata,
+			NULL, 0);
+
+	if (err < 0) {
+		dev_err(&pdev->dev, "Failed to register platform device\n");
+		return err;
+	}
+
+	string_get_size(info->mtd.size, STRING_UNITS_2, sz_str,
+			sizeof(sz_str));
+	dev_info(&pdev->dev, "using %s SRAM on LP-8X4X as %s\n", sz_str,
+			dev_name(&info->mtd.dev));
+	return 0;
+}
+
+static int
+lp8x4x_sram_remove(struct platform_device *dev)
+{
+	struct lp8x4x_sram_info *info = platform_get_drvdata(dev);
+
+	mtd_device_unregister(&info->mtd);
+	platform_set_drvdata(dev, NULL);
+	return 0;
+}
+
+static struct platform_driver lp8x4x_sram_driver = {
+	.driver = {
+		.name		= "sram-lp8x4x",
+		.owner		= THIS_MODULE,
+		.of_match_table = of_flash_match,
+	},
+	.probe		= lp8x4x_sram_probe,
+	.remove		= lp8x4x_sram_remove,
+};
+
+module_platform_driver(lp8x4x_sram_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Sergei Ianovich <ynvich@gmail.com>");
+MODULE_DESCRIPTION("MTD driver for SRAM on ICPDAS LP-8x4x");
-- 
1.8.4.2


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

* [PATCH v3 10/21] mtd: support BB SRAM on ICP DAS LP-8x4x
@ 2013-12-17 19:37             ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-17 19:37 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Russell King, David Woodhouse,
	Grant Likely, Artem Bityutskiy, Robert Jarzmik, Kees Cook,
	Randy Dunlap, Philip Avinash, open list:OPEN FIRMWARE AND...,
	open list:MEMORY TECHNOLOGY...

This provides an MTD device driver for 512kB of battery backed up SRAM
on ICPDAS LP-8X4X programmable automation controllers.

SRAM chip is connected via FPGA and is not accessible without a driver,
unlike flash memory which is wired to CPU MMU.

This SRAM becomes an excellent persisent storage of volatile process
data like counter values and sensor statuses. Storing those data in
flash or mmc card is not a viable solution.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
   v2..v3
   * no changes (except number 08/16 -> 10/21)

   v0..v2
   * use device tree
   * use devm helpers where possible

 arch/arm/boot/dts/pxa27x-lp8x4x.dts |   6 +
 arch/arm/configs/lp8x4x_defconfig   |   1 +
 drivers/mtd/devices/Kconfig         |  14 +++
 drivers/mtd/devices/Makefile        |   1 +
 drivers/mtd/devices/sram_lp8x4x.c   | 227 ++++++++++++++++++++++++++++++++++++
 5 files changed, 249 insertions(+)
 create mode 100644 drivers/mtd/devices/sram_lp8x4x.c

diff --git a/arch/arm/boot/dts/pxa27x-lp8x4x.dts b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
index 872c386..07856e0 100644
--- a/arch/arm/boot/dts/pxa27x-lp8x4x.dts
+++ b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
@@ -161,6 +161,12 @@
 				reg = <0x901c 0x1>;
 				status = "okay";
 			};
+
+			sram@a000 {
+				compatible = "icpdas,sram-lp8x4x";
+				reg = <0xa000 0x1000
+				       0x901e 0x1>;
+			};
 		};
 	};
 };
diff --git a/arch/arm/configs/lp8x4x_defconfig b/arch/arm/configs/lp8x4x_defconfig
index d60e37a..17a4e6f 100644
--- a/arch/arm/configs/lp8x4x_defconfig
+++ b/arch/arm/configs/lp8x4x_defconfig
@@ -57,6 +57,7 @@ CONFIG_MTD_CFI_ADV_OPTIONS=y
 CONFIG_MTD_CFI_GEOMETRY=y
 CONFIG_MTD_CFI_INTELEXT=y
 CONFIG_MTD_PHYSMAP_OF=y
+CONFIG_MTD_SRAM_LP8X4X=y
 CONFIG_PROC_DEVICETREE=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_LOOP_MIN_COUNT=2
diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig
index 0128138..95f2075 100644
--- a/drivers/mtd/devices/Kconfig
+++ b/drivers/mtd/devices/Kconfig
@@ -217,4 +217,18 @@ config BCH_CONST_T
 	default 4
 endif
 
+config MTD_SRAM_LP8X4X
+	tristate "SRAM on ICPDAS LP-8X4X"
+	depends on OF && ARCH_PXA
+       ---help---
+	 This provides an MTD device driver for 512kiB of battery backed up SRAM
+	 on ICPDAS LP-8X4X programmable automation controllers.
+
+	 SRAM chip is connected via FPGA and is not accessible without a driver,
+	 unlike flash memory which is wired to CPU MMU.
+
+	 Say N, unless you plan to run this kernel on LP-8X4X.
+
+	 If you say M, the module will be called sram_lp8x4x.
+
 endmenu
diff --git a/drivers/mtd/devices/Makefile b/drivers/mtd/devices/Makefile
index d83bd73..56a74c9 100644
--- a/drivers/mtd/devices/Makefile
+++ b/drivers/mtd/devices/Makefile
@@ -16,6 +16,7 @@ obj-$(CONFIG_MTD_NAND_OMAP_BCH)	+= elm.o
 obj-$(CONFIG_MTD_SPEAR_SMI)	+= spear_smi.o
 obj-$(CONFIG_MTD_SST25L)	+= sst25l.o
 obj-$(CONFIG_MTD_BCM47XXSFLASH)	+= bcm47xxsflash.o
+obj-$(CONFIG_MTD_SRAM_LP8X4X)	+= sram_lp8x4x.o
 
 
 CFLAGS_docg3.o			+= -I$(src)
diff --git a/drivers/mtd/devices/sram_lp8x4x.c b/drivers/mtd/devices/sram_lp8x4x.c
new file mode 100644
index 0000000..9dc7149
--- /dev/null
+++ b/drivers/mtd/devices/sram_lp8x4x.c
@@ -0,0 +1,227 @@
+/*
+ *  linux/drivers/mtd/devices/lp8x4x_sram.c
+ *
+ *  MTD Driver for SRAM on ICPDAS LP-8x4x
+ *  Copyright (C) 2013 Sergei Ianovich <ynvich@gmail.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation or any later version.
+ */
+
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mtd/map.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/platform_device.h>
+#include <linux/of_device.h>
+#include <linux/slab.h>
+#include <linux/string_helpers.h>
+#include <linux/types.h>
+
+#include <asm/mach/flash.h>
+
+struct lp8x4x_sram_info {
+	void __iomem	*bank;
+	void __iomem	*virt;
+	struct mutex	lock;
+	unsigned	active_bank;
+	struct mtd_info	mtd;
+};
+
+static int
+lp8x4x_sram_erase(struct mtd_info *mtd, struct erase_info *instr)
+{
+	struct lp8x4x_sram_info *info = mtd->priv;
+	unsigned bank = instr->addr >> 11;
+	unsigned offset = (instr->addr & 0x7ff) << 1;
+	loff_t i;
+
+	mutex_lock(&info->lock);
+	if (unlikely(bank != info->active_bank)) {
+		info->active_bank = bank;
+		iowrite8(bank, info->bank);
+	}
+	for (i = 0; i < instr->len; i++) {
+		iowrite8(0xff, info->virt + offset);
+		offset += 2;
+		if (unlikely(offset == 0)) {
+			info->active_bank++;
+			iowrite8(info->active_bank, info->bank);
+		}
+	}
+	mutex_unlock(&info->lock);
+	instr->state = MTD_ERASE_DONE;
+	mtd_erase_callback(instr);
+
+	return 0;
+}
+
+static int
+lp8x4x_sram_write(struct mtd_info *mtd, loff_t to, size_t len,
+		size_t *retlen, const u_char *b)
+{
+	struct lp8x4x_sram_info *info = mtd->priv;
+	unsigned bank = to >> 11;
+	unsigned offset = (to & 0x7ff) << 1;
+	loff_t i;
+
+	mutex_lock(&info->lock);
+	if (unlikely(bank != info->active_bank)) {
+		info->active_bank = bank;
+		iowrite8(bank, info->bank);
+	}
+	for (i = 0; i < len; i++) {
+		iowrite8(b[i], info->virt + offset);
+		offset += 2;
+		if (unlikely(offset == 0)) {
+			info->active_bank++;
+			iowrite8(info->active_bank, info->bank);
+		}
+	}
+	mutex_unlock(&info->lock);
+	*retlen = len;
+	return 0;
+}
+
+static int
+lp8x4x_sram_read(struct mtd_info *mtd, loff_t from, size_t len,
+		size_t *retlen, u_char *b)
+{
+	struct lp8x4x_sram_info *info = mtd->priv;
+	unsigned bank = from >> 11;
+	unsigned offset = (from & 0x7ff) << 1;
+	loff_t i;
+
+	mutex_lock(&info->lock);
+	if (unlikely(bank != info->active_bank)) {
+		info->active_bank = bank;
+		iowrite8(bank, info->bank);
+	}
+	for (i = 0; i < len; i++) {
+		b[i] = ioread8(info->virt + offset);
+		offset += 2;
+		if (unlikely(offset == 0)) {
+			info->active_bank++;
+			iowrite8(info->active_bank, info->bank);
+		}
+	}
+	mutex_unlock(&info->lock);
+	*retlen = len;
+	return 0;
+}
+
+static void
+lp8x4x_sram_sync(struct mtd_info *mtd)
+{
+}
+
+static struct of_device_id of_flash_match[] = {
+	{
+		.compatible	= "icpdas,sram-lp8x4x",
+	},
+	{ },
+};
+MODULE_DEVICE_TABLE(of, of_flash_match);
+
+static const char * const probe_types[] = {
+	"cmdlinepart", "RedBoot", "ofpart", "ofoldpart", NULL };
+
+static int
+lp8x4x_sram_probe(struct platform_device *pdev)
+{
+	const struct of_device_id *match;
+	struct lp8x4x_sram_info *info;
+	struct resource *r1, *r2;
+	char sz_str[16];
+	struct mtd_part_parser_data ppdata;
+	int err = 0;
+
+	match = of_match_device(of_flash_match, &pdev->dev);
+	if (!match)
+		return -EINVAL;
+
+	r1 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	r2 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	if (!r1 || !r2)
+		return -ENODEV;
+
+	info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
+	if (!info)
+		return -ENOMEM;
+
+	info->virt =  devm_ioremap_resource(&pdev->dev, r1);
+	if (!info->virt) {
+		dev_err(&pdev->dev, "Failed to ioremap %p\n",
+		       info->virt);
+		return -EFAULT;
+	}
+
+	info->bank = devm_ioremap_resource(&pdev->dev, r2);
+	if (!info->bank) {
+		dev_err(&pdev->dev, "Failed to ioremap %p\n",
+		       info->bank);
+		return -EFAULT;
+	}
+
+	info->mtd.priv = info;
+	info->mtd.name = "SRAM";
+	info->mtd.type = MTD_RAM;
+	info->mtd.flags = MTD_CAP_RAM;
+	info->mtd.size = resource_size(r1) << 7;
+	info->mtd.erasesize = 512;
+	info->mtd.writesize = 4;
+	info->mtd._erase = lp8x4x_sram_erase;
+	info->mtd._write = lp8x4x_sram_write;
+	info->mtd._read = lp8x4x_sram_read;
+	info->mtd._sync = lp8x4x_sram_sync;
+	info->mtd.owner = THIS_MODULE;
+
+	mutex_init(&info->lock);
+	iowrite8(info->active_bank, info->bank);
+	platform_set_drvdata(pdev, info);
+
+	ppdata.of_node = pdev->dev.of_node;
+	err = mtd_device_parse_register(&info->mtd, probe_types, &ppdata,
+			NULL, 0);
+
+	if (err < 0) {
+		dev_err(&pdev->dev, "Failed to register platform device\n");
+		return err;
+	}
+
+	string_get_size(info->mtd.size, STRING_UNITS_2, sz_str,
+			sizeof(sz_str));
+	dev_info(&pdev->dev, "using %s SRAM on LP-8X4X as %s\n", sz_str,
+			dev_name(&info->mtd.dev));
+	return 0;
+}
+
+static int
+lp8x4x_sram_remove(struct platform_device *dev)
+{
+	struct lp8x4x_sram_info *info = platform_get_drvdata(dev);
+
+	mtd_device_unregister(&info->mtd);
+	platform_set_drvdata(dev, NULL);
+	return 0;
+}
+
+static struct platform_driver lp8x4x_sram_driver = {
+	.driver = {
+		.name		= "sram-lp8x4x",
+		.owner		= THIS_MODULE,
+		.of_match_table = of_flash_match,
+	},
+	.probe		= lp8x4x_sram_probe,
+	.remove		= lp8x4x_sram_remove,
+};
+
+module_platform_driver(lp8x4x_sram_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Sergei Ianovich <ynvich@gmail.com>");
+MODULE_DESCRIPTION("MTD driver for SRAM on ICPDAS LP-8x4x");
-- 
1.8.4.2

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

* [PATCH v3 10/21] mtd: support BB SRAM on ICP DAS LP-8x4x
@ 2013-12-17 19:37             ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-17 19:37 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Mark Rutland, open list:OPEN FIRMWARE AND...,
	Russell King, Kees Cook, Pawel Moll, Ian Campbell,
	Artem Bityutskiy, Robert Jarzmik, Randy Dunlap, Rob Herring,
	Sergei Ianovich, Philip Avinash, Kumar Gala, Grant Likely,
	open list:MEMORY TECHNOLOGY...,
	David Woodhouse

This provides an MTD device driver for 512kB of battery backed up SRAM
on ICPDAS LP-8X4X programmable automation controllers.

SRAM chip is connected via FPGA and is not accessible without a driver,
unlike flash memory which is wired to CPU MMU.

This SRAM becomes an excellent persisent storage of volatile process
data like counter values and sensor statuses. Storing those data in
flash or mmc card is not a viable solution.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
   v2..v3
   * no changes (except number 08/16 -> 10/21)

   v0..v2
   * use device tree
   * use devm helpers where possible

 arch/arm/boot/dts/pxa27x-lp8x4x.dts |   6 +
 arch/arm/configs/lp8x4x_defconfig   |   1 +
 drivers/mtd/devices/Kconfig         |  14 +++
 drivers/mtd/devices/Makefile        |   1 +
 drivers/mtd/devices/sram_lp8x4x.c   | 227 ++++++++++++++++++++++++++++++++++++
 5 files changed, 249 insertions(+)
 create mode 100644 drivers/mtd/devices/sram_lp8x4x.c

diff --git a/arch/arm/boot/dts/pxa27x-lp8x4x.dts b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
index 872c386..07856e0 100644
--- a/arch/arm/boot/dts/pxa27x-lp8x4x.dts
+++ b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
@@ -161,6 +161,12 @@
 				reg = <0x901c 0x1>;
 				status = "okay";
 			};
+
+			sram@a000 {
+				compatible = "icpdas,sram-lp8x4x";
+				reg = <0xa000 0x1000
+				       0x901e 0x1>;
+			};
 		};
 	};
 };
diff --git a/arch/arm/configs/lp8x4x_defconfig b/arch/arm/configs/lp8x4x_defconfig
index d60e37a..17a4e6f 100644
--- a/arch/arm/configs/lp8x4x_defconfig
+++ b/arch/arm/configs/lp8x4x_defconfig
@@ -57,6 +57,7 @@ CONFIG_MTD_CFI_ADV_OPTIONS=y
 CONFIG_MTD_CFI_GEOMETRY=y
 CONFIG_MTD_CFI_INTELEXT=y
 CONFIG_MTD_PHYSMAP_OF=y
+CONFIG_MTD_SRAM_LP8X4X=y
 CONFIG_PROC_DEVICETREE=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_LOOP_MIN_COUNT=2
diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig
index 0128138..95f2075 100644
--- a/drivers/mtd/devices/Kconfig
+++ b/drivers/mtd/devices/Kconfig
@@ -217,4 +217,18 @@ config BCH_CONST_T
 	default 4
 endif
 
+config MTD_SRAM_LP8X4X
+	tristate "SRAM on ICPDAS LP-8X4X"
+	depends on OF && ARCH_PXA
+       ---help---
+	 This provides an MTD device driver for 512kiB of battery backed up SRAM
+	 on ICPDAS LP-8X4X programmable automation controllers.
+
+	 SRAM chip is connected via FPGA and is not accessible without a driver,
+	 unlike flash memory which is wired to CPU MMU.
+
+	 Say N, unless you plan to run this kernel on LP-8X4X.
+
+	 If you say M, the module will be called sram_lp8x4x.
+
 endmenu
diff --git a/drivers/mtd/devices/Makefile b/drivers/mtd/devices/Makefile
index d83bd73..56a74c9 100644
--- a/drivers/mtd/devices/Makefile
+++ b/drivers/mtd/devices/Makefile
@@ -16,6 +16,7 @@ obj-$(CONFIG_MTD_NAND_OMAP_BCH)	+= elm.o
 obj-$(CONFIG_MTD_SPEAR_SMI)	+= spear_smi.o
 obj-$(CONFIG_MTD_SST25L)	+= sst25l.o
 obj-$(CONFIG_MTD_BCM47XXSFLASH)	+= bcm47xxsflash.o
+obj-$(CONFIG_MTD_SRAM_LP8X4X)	+= sram_lp8x4x.o
 
 
 CFLAGS_docg3.o			+= -I$(src)
diff --git a/drivers/mtd/devices/sram_lp8x4x.c b/drivers/mtd/devices/sram_lp8x4x.c
new file mode 100644
index 0000000..9dc7149
--- /dev/null
+++ b/drivers/mtd/devices/sram_lp8x4x.c
@@ -0,0 +1,227 @@
+/*
+ *  linux/drivers/mtd/devices/lp8x4x_sram.c
+ *
+ *  MTD Driver for SRAM on ICPDAS LP-8x4x
+ *  Copyright (C) 2013 Sergei Ianovich <ynvich@gmail.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation or any later version.
+ */
+
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mtd/map.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/platform_device.h>
+#include <linux/of_device.h>
+#include <linux/slab.h>
+#include <linux/string_helpers.h>
+#include <linux/types.h>
+
+#include <asm/mach/flash.h>
+
+struct lp8x4x_sram_info {
+	void __iomem	*bank;
+	void __iomem	*virt;
+	struct mutex	lock;
+	unsigned	active_bank;
+	struct mtd_info	mtd;
+};
+
+static int
+lp8x4x_sram_erase(struct mtd_info *mtd, struct erase_info *instr)
+{
+	struct lp8x4x_sram_info *info = mtd->priv;
+	unsigned bank = instr->addr >> 11;
+	unsigned offset = (instr->addr & 0x7ff) << 1;
+	loff_t i;
+
+	mutex_lock(&info->lock);
+	if (unlikely(bank != info->active_bank)) {
+		info->active_bank = bank;
+		iowrite8(bank, info->bank);
+	}
+	for (i = 0; i < instr->len; i++) {
+		iowrite8(0xff, info->virt + offset);
+		offset += 2;
+		if (unlikely(offset == 0)) {
+			info->active_bank++;
+			iowrite8(info->active_bank, info->bank);
+		}
+	}
+	mutex_unlock(&info->lock);
+	instr->state = MTD_ERASE_DONE;
+	mtd_erase_callback(instr);
+
+	return 0;
+}
+
+static int
+lp8x4x_sram_write(struct mtd_info *mtd, loff_t to, size_t len,
+		size_t *retlen, const u_char *b)
+{
+	struct lp8x4x_sram_info *info = mtd->priv;
+	unsigned bank = to >> 11;
+	unsigned offset = (to & 0x7ff) << 1;
+	loff_t i;
+
+	mutex_lock(&info->lock);
+	if (unlikely(bank != info->active_bank)) {
+		info->active_bank = bank;
+		iowrite8(bank, info->bank);
+	}
+	for (i = 0; i < len; i++) {
+		iowrite8(b[i], info->virt + offset);
+		offset += 2;
+		if (unlikely(offset == 0)) {
+			info->active_bank++;
+			iowrite8(info->active_bank, info->bank);
+		}
+	}
+	mutex_unlock(&info->lock);
+	*retlen = len;
+	return 0;
+}
+
+static int
+lp8x4x_sram_read(struct mtd_info *mtd, loff_t from, size_t len,
+		size_t *retlen, u_char *b)
+{
+	struct lp8x4x_sram_info *info = mtd->priv;
+	unsigned bank = from >> 11;
+	unsigned offset = (from & 0x7ff) << 1;
+	loff_t i;
+
+	mutex_lock(&info->lock);
+	if (unlikely(bank != info->active_bank)) {
+		info->active_bank = bank;
+		iowrite8(bank, info->bank);
+	}
+	for (i = 0; i < len; i++) {
+		b[i] = ioread8(info->virt + offset);
+		offset += 2;
+		if (unlikely(offset == 0)) {
+			info->active_bank++;
+			iowrite8(info->active_bank, info->bank);
+		}
+	}
+	mutex_unlock(&info->lock);
+	*retlen = len;
+	return 0;
+}
+
+static void
+lp8x4x_sram_sync(struct mtd_info *mtd)
+{
+}
+
+static struct of_device_id of_flash_match[] = {
+	{
+		.compatible	= "icpdas,sram-lp8x4x",
+	},
+	{ },
+};
+MODULE_DEVICE_TABLE(of, of_flash_match);
+
+static const char * const probe_types[] = {
+	"cmdlinepart", "RedBoot", "ofpart", "ofoldpart", NULL };
+
+static int
+lp8x4x_sram_probe(struct platform_device *pdev)
+{
+	const struct of_device_id *match;
+	struct lp8x4x_sram_info *info;
+	struct resource *r1, *r2;
+	char sz_str[16];
+	struct mtd_part_parser_data ppdata;
+	int err = 0;
+
+	match = of_match_device(of_flash_match, &pdev->dev);
+	if (!match)
+		return -EINVAL;
+
+	r1 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	r2 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	if (!r1 || !r2)
+		return -ENODEV;
+
+	info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
+	if (!info)
+		return -ENOMEM;
+
+	info->virt =  devm_ioremap_resource(&pdev->dev, r1);
+	if (!info->virt) {
+		dev_err(&pdev->dev, "Failed to ioremap %p\n",
+		       info->virt);
+		return -EFAULT;
+	}
+
+	info->bank = devm_ioremap_resource(&pdev->dev, r2);
+	if (!info->bank) {
+		dev_err(&pdev->dev, "Failed to ioremap %p\n",
+		       info->bank);
+		return -EFAULT;
+	}
+
+	info->mtd.priv = info;
+	info->mtd.name = "SRAM";
+	info->mtd.type = MTD_RAM;
+	info->mtd.flags = MTD_CAP_RAM;
+	info->mtd.size = resource_size(r1) << 7;
+	info->mtd.erasesize = 512;
+	info->mtd.writesize = 4;
+	info->mtd._erase = lp8x4x_sram_erase;
+	info->mtd._write = lp8x4x_sram_write;
+	info->mtd._read = lp8x4x_sram_read;
+	info->mtd._sync = lp8x4x_sram_sync;
+	info->mtd.owner = THIS_MODULE;
+
+	mutex_init(&info->lock);
+	iowrite8(info->active_bank, info->bank);
+	platform_set_drvdata(pdev, info);
+
+	ppdata.of_node = pdev->dev.of_node;
+	err = mtd_device_parse_register(&info->mtd, probe_types, &ppdata,
+			NULL, 0);
+
+	if (err < 0) {
+		dev_err(&pdev->dev, "Failed to register platform device\n");
+		return err;
+	}
+
+	string_get_size(info->mtd.size, STRING_UNITS_2, sz_str,
+			sizeof(sz_str));
+	dev_info(&pdev->dev, "using %s SRAM on LP-8X4X as %s\n", sz_str,
+			dev_name(&info->mtd.dev));
+	return 0;
+}
+
+static int
+lp8x4x_sram_remove(struct platform_device *dev)
+{
+	struct lp8x4x_sram_info *info = platform_get_drvdata(dev);
+
+	mtd_device_unregister(&info->mtd);
+	platform_set_drvdata(dev, NULL);
+	return 0;
+}
+
+static struct platform_driver lp8x4x_sram_driver = {
+	.driver = {
+		.name		= "sram-lp8x4x",
+		.owner		= THIS_MODULE,
+		.of_match_table = of_flash_match,
+	},
+	.probe		= lp8x4x_sram_probe,
+	.remove		= lp8x4x_sram_remove,
+};
+
+module_platform_driver(lp8x4x_sram_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Sergei Ianovich <ynvich@gmail.com>");
+MODULE_DESCRIPTION("MTD driver for SRAM on ICPDAS LP-8x4x");
-- 
1.8.4.2

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

* [PATCH v3 10/21] mtd: support BB SRAM on ICP DAS LP-8x4x
@ 2013-12-17 19:37             ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-17 19:37 UTC (permalink / raw)
  To: linux-arm-kernel

This provides an MTD device driver for 512kB of battery backed up SRAM
on ICPDAS LP-8X4X programmable automation controllers.

SRAM chip is connected via FPGA and is not accessible without a driver,
unlike flash memory which is wired to CPU MMU.

This SRAM becomes an excellent persisent storage of volatile process
data like counter values and sensor statuses. Storing those data in
flash or mmc card is not a viable solution.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
   v2..v3
   * no changes (except number 08/16 -> 10/21)

   v0..v2
   * use device tree
   * use devm helpers where possible

 arch/arm/boot/dts/pxa27x-lp8x4x.dts |   6 +
 arch/arm/configs/lp8x4x_defconfig   |   1 +
 drivers/mtd/devices/Kconfig         |  14 +++
 drivers/mtd/devices/Makefile        |   1 +
 drivers/mtd/devices/sram_lp8x4x.c   | 227 ++++++++++++++++++++++++++++++++++++
 5 files changed, 249 insertions(+)
 create mode 100644 drivers/mtd/devices/sram_lp8x4x.c

diff --git a/arch/arm/boot/dts/pxa27x-lp8x4x.dts b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
index 872c386..07856e0 100644
--- a/arch/arm/boot/dts/pxa27x-lp8x4x.dts
+++ b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
@@ -161,6 +161,12 @@
 				reg = <0x901c 0x1>;
 				status = "okay";
 			};
+
+			sram at a000 {
+				compatible = "icpdas,sram-lp8x4x";
+				reg = <0xa000 0x1000
+				       0x901e 0x1>;
+			};
 		};
 	};
 };
diff --git a/arch/arm/configs/lp8x4x_defconfig b/arch/arm/configs/lp8x4x_defconfig
index d60e37a..17a4e6f 100644
--- a/arch/arm/configs/lp8x4x_defconfig
+++ b/arch/arm/configs/lp8x4x_defconfig
@@ -57,6 +57,7 @@ CONFIG_MTD_CFI_ADV_OPTIONS=y
 CONFIG_MTD_CFI_GEOMETRY=y
 CONFIG_MTD_CFI_INTELEXT=y
 CONFIG_MTD_PHYSMAP_OF=y
+CONFIG_MTD_SRAM_LP8X4X=y
 CONFIG_PROC_DEVICETREE=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_LOOP_MIN_COUNT=2
diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig
index 0128138..95f2075 100644
--- a/drivers/mtd/devices/Kconfig
+++ b/drivers/mtd/devices/Kconfig
@@ -217,4 +217,18 @@ config BCH_CONST_T
 	default 4
 endif
 
+config MTD_SRAM_LP8X4X
+	tristate "SRAM on ICPDAS LP-8X4X"
+	depends on OF && ARCH_PXA
+       ---help---
+	 This provides an MTD device driver for 512kiB of battery backed up SRAM
+	 on ICPDAS LP-8X4X programmable automation controllers.
+
+	 SRAM chip is connected via FPGA and is not accessible without a driver,
+	 unlike flash memory which is wired to CPU MMU.
+
+	 Say N, unless you plan to run this kernel on LP-8X4X.
+
+	 If you say M, the module will be called sram_lp8x4x.
+
 endmenu
diff --git a/drivers/mtd/devices/Makefile b/drivers/mtd/devices/Makefile
index d83bd73..56a74c9 100644
--- a/drivers/mtd/devices/Makefile
+++ b/drivers/mtd/devices/Makefile
@@ -16,6 +16,7 @@ obj-$(CONFIG_MTD_NAND_OMAP_BCH)	+= elm.o
 obj-$(CONFIG_MTD_SPEAR_SMI)	+= spear_smi.o
 obj-$(CONFIG_MTD_SST25L)	+= sst25l.o
 obj-$(CONFIG_MTD_BCM47XXSFLASH)	+= bcm47xxsflash.o
+obj-$(CONFIG_MTD_SRAM_LP8X4X)	+= sram_lp8x4x.o
 
 
 CFLAGS_docg3.o			+= -I$(src)
diff --git a/drivers/mtd/devices/sram_lp8x4x.c b/drivers/mtd/devices/sram_lp8x4x.c
new file mode 100644
index 0000000..9dc7149
--- /dev/null
+++ b/drivers/mtd/devices/sram_lp8x4x.c
@@ -0,0 +1,227 @@
+/*
+ *  linux/drivers/mtd/devices/lp8x4x_sram.c
+ *
+ *  MTD Driver for SRAM on ICPDAS LP-8x4x
+ *  Copyright (C) 2013 Sergei Ianovich <ynvich@gmail.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation or any later version.
+ */
+
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mtd/map.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/platform_device.h>
+#include <linux/of_device.h>
+#include <linux/slab.h>
+#include <linux/string_helpers.h>
+#include <linux/types.h>
+
+#include <asm/mach/flash.h>
+
+struct lp8x4x_sram_info {
+	void __iomem	*bank;
+	void __iomem	*virt;
+	struct mutex	lock;
+	unsigned	active_bank;
+	struct mtd_info	mtd;
+};
+
+static int
+lp8x4x_sram_erase(struct mtd_info *mtd, struct erase_info *instr)
+{
+	struct lp8x4x_sram_info *info = mtd->priv;
+	unsigned bank = instr->addr >> 11;
+	unsigned offset = (instr->addr & 0x7ff) << 1;
+	loff_t i;
+
+	mutex_lock(&info->lock);
+	if (unlikely(bank != info->active_bank)) {
+		info->active_bank = bank;
+		iowrite8(bank, info->bank);
+	}
+	for (i = 0; i < instr->len; i++) {
+		iowrite8(0xff, info->virt + offset);
+		offset += 2;
+		if (unlikely(offset == 0)) {
+			info->active_bank++;
+			iowrite8(info->active_bank, info->bank);
+		}
+	}
+	mutex_unlock(&info->lock);
+	instr->state = MTD_ERASE_DONE;
+	mtd_erase_callback(instr);
+
+	return 0;
+}
+
+static int
+lp8x4x_sram_write(struct mtd_info *mtd, loff_t to, size_t len,
+		size_t *retlen, const u_char *b)
+{
+	struct lp8x4x_sram_info *info = mtd->priv;
+	unsigned bank = to >> 11;
+	unsigned offset = (to & 0x7ff) << 1;
+	loff_t i;
+
+	mutex_lock(&info->lock);
+	if (unlikely(bank != info->active_bank)) {
+		info->active_bank = bank;
+		iowrite8(bank, info->bank);
+	}
+	for (i = 0; i < len; i++) {
+		iowrite8(b[i], info->virt + offset);
+		offset += 2;
+		if (unlikely(offset == 0)) {
+			info->active_bank++;
+			iowrite8(info->active_bank, info->bank);
+		}
+	}
+	mutex_unlock(&info->lock);
+	*retlen = len;
+	return 0;
+}
+
+static int
+lp8x4x_sram_read(struct mtd_info *mtd, loff_t from, size_t len,
+		size_t *retlen, u_char *b)
+{
+	struct lp8x4x_sram_info *info = mtd->priv;
+	unsigned bank = from >> 11;
+	unsigned offset = (from & 0x7ff) << 1;
+	loff_t i;
+
+	mutex_lock(&info->lock);
+	if (unlikely(bank != info->active_bank)) {
+		info->active_bank = bank;
+		iowrite8(bank, info->bank);
+	}
+	for (i = 0; i < len; i++) {
+		b[i] = ioread8(info->virt + offset);
+		offset += 2;
+		if (unlikely(offset == 0)) {
+			info->active_bank++;
+			iowrite8(info->active_bank, info->bank);
+		}
+	}
+	mutex_unlock(&info->lock);
+	*retlen = len;
+	return 0;
+}
+
+static void
+lp8x4x_sram_sync(struct mtd_info *mtd)
+{
+}
+
+static struct of_device_id of_flash_match[] = {
+	{
+		.compatible	= "icpdas,sram-lp8x4x",
+	},
+	{ },
+};
+MODULE_DEVICE_TABLE(of, of_flash_match);
+
+static const char * const probe_types[] = {
+	"cmdlinepart", "RedBoot", "ofpart", "ofoldpart", NULL };
+
+static int
+lp8x4x_sram_probe(struct platform_device *pdev)
+{
+	const struct of_device_id *match;
+	struct lp8x4x_sram_info *info;
+	struct resource *r1, *r2;
+	char sz_str[16];
+	struct mtd_part_parser_data ppdata;
+	int err = 0;
+
+	match = of_match_device(of_flash_match, &pdev->dev);
+	if (!match)
+		return -EINVAL;
+
+	r1 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	r2 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	if (!r1 || !r2)
+		return -ENODEV;
+
+	info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
+	if (!info)
+		return -ENOMEM;
+
+	info->virt =  devm_ioremap_resource(&pdev->dev, r1);
+	if (!info->virt) {
+		dev_err(&pdev->dev, "Failed to ioremap %p\n",
+		       info->virt);
+		return -EFAULT;
+	}
+
+	info->bank = devm_ioremap_resource(&pdev->dev, r2);
+	if (!info->bank) {
+		dev_err(&pdev->dev, "Failed to ioremap %p\n",
+		       info->bank);
+		return -EFAULT;
+	}
+
+	info->mtd.priv = info;
+	info->mtd.name = "SRAM";
+	info->mtd.type = MTD_RAM;
+	info->mtd.flags = MTD_CAP_RAM;
+	info->mtd.size = resource_size(r1) << 7;
+	info->mtd.erasesize = 512;
+	info->mtd.writesize = 4;
+	info->mtd._erase = lp8x4x_sram_erase;
+	info->mtd._write = lp8x4x_sram_write;
+	info->mtd._read = lp8x4x_sram_read;
+	info->mtd._sync = lp8x4x_sram_sync;
+	info->mtd.owner = THIS_MODULE;
+
+	mutex_init(&info->lock);
+	iowrite8(info->active_bank, info->bank);
+	platform_set_drvdata(pdev, info);
+
+	ppdata.of_node = pdev->dev.of_node;
+	err = mtd_device_parse_register(&info->mtd, probe_types, &ppdata,
+			NULL, 0);
+
+	if (err < 0) {
+		dev_err(&pdev->dev, "Failed to register platform device\n");
+		return err;
+	}
+
+	string_get_size(info->mtd.size, STRING_UNITS_2, sz_str,
+			sizeof(sz_str));
+	dev_info(&pdev->dev, "using %s SRAM on LP-8X4X as %s\n", sz_str,
+			dev_name(&info->mtd.dev));
+	return 0;
+}
+
+static int
+lp8x4x_sram_remove(struct platform_device *dev)
+{
+	struct lp8x4x_sram_info *info = platform_get_drvdata(dev);
+
+	mtd_device_unregister(&info->mtd);
+	platform_set_drvdata(dev, NULL);
+	return 0;
+}
+
+static struct platform_driver lp8x4x_sram_driver = {
+	.driver = {
+		.name		= "sram-lp8x4x",
+		.owner		= THIS_MODULE,
+		.of_match_table = of_flash_match,
+	},
+	.probe		= lp8x4x_sram_probe,
+	.remove		= lp8x4x_sram_remove,
+};
+
+module_platform_driver(lp8x4x_sram_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Sergei Ianovich <ynvich@gmail.com>");
+MODULE_DESCRIPTION("MTD driver for SRAM on ICPDAS LP-8x4x");
-- 
1.8.4.2

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

* [PATCH v3 11/21] ARM: pxa: support ICP DAS LP-8x4x FPGA irq
  2013-12-17 19:37           ` Sergei Ianovich
  (?)
@ 2013-12-17 19:37             ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-17 19:37 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Arnd Bergmann, Linus Walleij, Rob Herring,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala, Rob Landley,
	Russell King, Thomas Gleixner, Grant Likely,
	open list:OPEN FIRMWARE AND...,
	open list:DOCUMENTATION

ICP DAS LP-8x4x contains FPGA chip. The chip functions as a interrupt
source providing 16 additional interrupts among other things. The
interrupt lines are muxed to a GPIO pin. GPIO pins are in turn muxed
to a CPU interrupt line.

Until pxa is completely converted to device tree, it is impossible
to use IRQCHIP_DECLARE() and the irqdomain needs to added manually.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Arnd Bergmann <arnd@arndb.de>
CC: Linus Walleij <linus.walleij@linaro.org>
---
   v2..v3
   * no changes (except number 09/16 -> 10/21)

   v0..v2
   * extract irqchip and move to drivers/irqchip/
   * use device tree
   * use devm helpers where possible

 .../bindings/interrupt-controller/irq-lp8x4x.txt   |  49 +++++
 arch/arm/boot/dts/pxa27x-lp8x4x.dts                |  10 +
 drivers/irqchip/Kconfig                            |   5 +
 drivers/irqchip/Makefile                           |   1 +
 drivers/irqchip/irq-lp8x4x.c                       | 205 +++++++++++++++++++++
 5 files changed, 270 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/interrupt-controller/irq-lp8x4x.txt
 create mode 100644 drivers/irqchip/irq-lp8x4x.c

diff --git a/Documentation/devicetree/bindings/interrupt-controller/irq-lp8x4x.txt b/Documentation/devicetree/bindings/interrupt-controller/irq-lp8x4x.txt
new file mode 100644
index 0000000..c8940d2
--- /dev/null
+++ b/Documentation/devicetree/bindings/interrupt-controller/irq-lp8x4x.txt
@@ -0,0 +1,49 @@
+ICP DAS LP-8x4x FPGA Interrupt Controller
+
+ICP DAS LP-8x4x contains FPGA chip. The chip functions as a interrupt
+source providing 16 additional interrupts among other things.
+
+Required properties:
+- compatible : should be "icpdas,irq-lp8x4x"
+
+- reg: physical base address of the controller and length of memory mapped
+  region.
+
+- interrupt-controller : identifies the node as an interrupt controller
+
+- #interrupt-cells : should be 1
+
+- interrupts : should provide interrupt
+
+- interrupt-parent : should provide a link to interrupt controller either
+		     explicitly and implicitly from a parent node
+
+Example:
+
+	fpga: fpga@17000006 {
+		compatible = "icpdas,irq-lp8x4x";
+		reg = <0x17000006 0x16>;
+		interrupt-parent = <&gpio>;
+		interrupts = <3 IRQ_TYPE_EDGE_RISING>;
+		#interrupt-cells = <1>;
+		interrupt-controller;
+		status = "okay";
+	};
+
+	uart@17009050 {
+		compatible = "icpdas,uart-lp8x4x";
+		reg = <0x17009050 0x10
+		       0x17009030 0x02>;
+		interrupt-parent = <&fpga>;
+		interrupts = <13>;
+		status = "okay";
+	};
+
+	uart@17009060 {
+		compatible = "icpdas,uart-lp8x4x";
+		reg = <0x17009060 0x10
+		       0x17009032 0x02>;
+		interrupt-parent = <&fpga>;
+		interrupts = <14>;
+		status = "okay";
+	};
diff --git a/arch/arm/boot/dts/pxa27x-lp8x4x.dts b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
index 07856e0..78dfd2e 100644
--- a/arch/arm/boot/dts/pxa27x-lp8x4x.dts
+++ b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
@@ -167,6 +167,16 @@
 				reg = <0xa000 0x1000
 				       0x901e 0x1>;
 			};
+
+			fpgairq: irq@9006 {
+				compatible = "icpdas,irq-lp8x4x";
+				reg = <0x9006 0x16>;
+				interrupt-parent = <&gpio>;
+				interrupts = <3 IRQ_TYPE_EDGE_FALLING>;
+				#interrupt-cells = <1>;
+				interrupt-controller;
+				status = "okay";
+			};
 		};
 	};
 };
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index 3792a1a..7e22729 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -35,6 +35,11 @@ config IMGPDC_IRQ
 	select GENERIC_IRQ_CHIP
 	select IRQ_DOMAIN
 
+config LP8X4X_IRQ
+	bool
+	depends on OF
+	select IRQ_DOMAIN
+
 config ORION_IRQCHIP
 	bool
 	select IRQ_DOMAIN
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index c60b901..8a28927 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -22,3 +22,4 @@ obj-$(CONFIG_RENESAS_IRQC)		+= irq-renesas-irqc.o
 obj-$(CONFIG_VERSATILE_FPGA_IRQ)	+= irq-versatile-fpga.o
 obj-$(CONFIG_ARCH_VT8500)		+= irq-vt8500.o
 obj-$(CONFIG_TB10X_IRQC)		+= irq-tb10x.o
+obj-$(CONFIG_LP8X4X_IRQ)		+= irq-lp8x4x.o
diff --git a/drivers/irqchip/irq-lp8x4x.c b/drivers/irqchip/irq-lp8x4x.c
new file mode 100644
index 0000000..5d44880b
--- /dev/null
+++ b/drivers/irqchip/irq-lp8x4x.c
@@ -0,0 +1,205 @@
+/*
+ *  linux/drivers/irqchip/irq-lp8x4x.c
+ *
+ *  Support for ICP DAS LP-8x4x FPGA irq
+ *  Copyright (C) 2013 Sergei Ianovich <ynvich@gmail.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation or any later version.
+ */
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/irqchip/chained_irq.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+#define EOI			0x00000000
+#define INSINT			0x00000002
+#define ENSYSINT		0x00000004
+#define PRIMINT			0x00000006
+#define SECOINT			0x00000008
+#define ENRISEINT		0x0000000A
+#define CLRRISEINT		0x0000000C
+#define ENHILVINT		0x0000000E
+#define CLRHILVINT		0x00000010
+#define ENFALLINT		0x00000012
+#define CLRFALLINT		0x00000014
+#define LP8X4X_IRQ_MEM_SIZE	0x00000016
+
+static unsigned char irq_sys_enabled;
+static unsigned char irq_high_enabled;
+static void *base;
+static int irq_base;
+static int num_irq = 16;
+
+static void lp8x4x_mask_irq(struct irq_data *d)
+{
+	unsigned mask;
+	int irq = d->irq - irq_base;
+
+	if (irq < 0 || irq > 15) {
+		pr_err("lp8x4x: wrong irq handler for irq %i\n", d->irq);
+		return;
+	}
+
+	if (irq < 8) {
+		irq_high_enabled &= ~(1 << irq);
+
+		mask = ioread8(base + ENHILVINT);
+		mask &= ~(1 << irq);
+		iowrite8(mask, base + ENHILVINT);
+	} else {
+		irq -= 8;
+		irq_sys_enabled &= ~(1 << irq);
+
+		mask = ioread8(base + ENSYSINT);
+		mask &= ~(1 << irq);
+		iowrite8(mask, base + ENSYSINT);
+	}
+}
+
+static void lp8x4x_unmask_irq(struct irq_data *d)
+{
+	unsigned mask;
+	int irq = d->irq - irq_base;
+
+	if (irq < 0 || irq > 15) {
+		pr_err("wrong irq handler for irq %i\n", d->irq);
+		return;
+	}
+
+	if (irq < 8) {
+		irq_high_enabled |= 1 << irq;
+		mask = ioread8(base + CLRHILVINT);
+		mask |= 1 << irq;
+		iowrite8(mask, base + CLRHILVINT);
+
+		mask = ioread8(base + ENHILVINT);
+		mask |= 1 << irq;
+		iowrite8(mask, base + ENHILVINT);
+	} else {
+		irq -= 8;
+		irq_sys_enabled |= 1 << irq;
+
+		mask = ioread8(base + SECOINT);
+		mask |= 1 << irq;
+		iowrite8(mask, base + SECOINT);
+
+		mask = ioread8(base + ENSYSINT);
+		mask |= 1 << irq;
+		iowrite8(mask, base + ENSYSINT);
+	}
+}
+
+static struct irq_chip lp8x4x_irq_chip = {
+	.name			= "FPGA",
+	.irq_ack		= lp8x4x_mask_irq,
+	.irq_mask		= lp8x4x_mask_irq,
+	.irq_mask_ack		= lp8x4x_mask_irq,
+	.irq_unmask		= lp8x4x_unmask_irq,
+};
+
+static void lp8x4x_irq_handler(unsigned int irq, struct irq_desc *desc)
+{
+	int loop, n;
+	unsigned long mask;
+	struct irq_chip *chip = irq_desc_get_chip(desc);
+
+	chained_irq_enter(chip, desc);
+
+	do {
+		loop = 0;
+		mask = ioread8(base + CLRHILVINT) & 0xff;
+		mask |= (ioread8(base + SECOINT) & 0x1f) << 8;
+		mask |= (ioread8(base + PRIMINT) & 0xe0) << 8;
+		mask &= (irq_high_enabled | (irq_sys_enabled << 8));
+		for_each_set_bit(n, &mask, BITS_PER_LONG) {
+			loop = 1;
+
+			generic_handle_irq(irq_base + n);
+		}
+	} while (loop);
+
+	iowrite8(0, base + EOI);
+	chained_irq_exit(chip, desc);
+}
+
+static int lp8x4x_irq_domain_map(struct irq_domain *d, unsigned int irq,
+				 irq_hw_number_t hw)
+{
+	irq_set_chip_and_handler(irq, &lp8x4x_irq_chip,
+				 handle_level_irq);
+	set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+	return 0;
+}
+
+const struct irq_domain_ops lp8x4x_irq_domain_ops = {
+	.map	= lp8x4x_irq_domain_map,
+	.xlate	= irq_domain_xlate_onecell,
+};
+
+static struct of_device_id lp8x4x_irq_dt_ids[] = {
+	{ .compatible = "icpdas,irq-lp8x4x", },
+	{}
+};
+
+static int lp8x4x_irq_probe(struct platform_device *pdev)
+{
+	struct resource *rm, *ri;
+	struct device_node *np = pdev->dev.of_node;
+	struct irq_domain *domain;
+
+	rm = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	ri = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!rm || !ri || resource_size(rm) < LP8X4X_IRQ_MEM_SIZE)
+		return -ENODEV;
+
+	base = devm_ioremap_resource(&pdev->dev, rm);
+	if (!base) {
+		dev_err(&pdev->dev, "Failed to ioremap %p\n", base);
+		return -EFAULT;
+	}
+
+	irq_base = irq_alloc_descs(-1, 0, num_irq, 0);
+	if (irq_base < 0) {
+		dev_err(&pdev->dev, "Failed to allocate IRQ numbers\n");
+		return irq_base;
+	}
+
+	domain = irq_domain_add_legacy(np, num_irq, irq_base, 0,
+				       &lp8x4x_irq_domain_ops, NULL);
+	if (!domain) {
+		dev_err(&pdev->dev, "Failed to add IRQ domain\n");
+		return -ENOMEM;
+	}
+
+	iowrite8(0, base + CLRRISEINT);
+	iowrite8(0, base + ENRISEINT);
+	iowrite8(0, base + CLRFALLINT);
+	iowrite8(0, base + ENFALLINT);
+	iowrite8(0, base + CLRHILVINT);
+	iowrite8(0, base + ENHILVINT);
+	iowrite8(0, base + ENSYSINT);
+	iowrite8(0, base + SECOINT);
+
+	irq_set_chained_handler(ri->start, lp8x4x_irq_handler);
+
+	return 0;
+}
+
+static struct platform_driver lp8x4x_irq_driver = {
+	.probe		= lp8x4x_irq_probe,
+	.driver		= {
+		.name	= "irq-lp8x4x",
+		.of_match_table = lp8x4x_irq_dt_ids,
+	},
+};
+
+static int __init lp8x4x_irq_init(void)
+{
+	return platform_driver_register(&lp8x4x_irq_driver);
+}
+postcore_initcall(lp8x4x_irq_init);
-- 
1.8.4.2


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

* [PATCH v3 11/21] ARM: pxa: support ICP DAS LP-8x4x FPGA irq
@ 2013-12-17 19:37             ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-17 19:37 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Arnd Bergmann, Linus Walleij, Rob Herring,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala, Rob Landley,
	Russell King, Thomas Gleixner, Grant Likely,
	open list:OPEN FIRMWARE AND...,
	open list:DOCUMENTATION

ICP DAS LP-8x4x contains FPGA chip. The chip functions as a interrupt
source providing 16 additional interrupts among other things. The
interrupt lines are muxed to a GPIO pin. GPIO pins are in turn muxed
to a CPU interrupt line.

Until pxa is completely converted to device tree, it is impossible
to use IRQCHIP_DECLARE() and the irqdomain needs to added manually.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Arnd Bergmann <arnd@arndb.de>
CC: Linus Walleij <linus.walleij@linaro.org>
---
   v2..v3
   * no changes (except number 09/16 -> 10/21)

   v0..v2
   * extract irqchip and move to drivers/irqchip/
   * use device tree
   * use devm helpers where possible

 .../bindings/interrupt-controller/irq-lp8x4x.txt   |  49 +++++
 arch/arm/boot/dts/pxa27x-lp8x4x.dts                |  10 +
 drivers/irqchip/Kconfig                            |   5 +
 drivers/irqchip/Makefile                           |   1 +
 drivers/irqchip/irq-lp8x4x.c                       | 205 +++++++++++++++++++++
 5 files changed, 270 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/interrupt-controller/irq-lp8x4x.txt
 create mode 100644 drivers/irqchip/irq-lp8x4x.c

diff --git a/Documentation/devicetree/bindings/interrupt-controller/irq-lp8x4x.txt b/Documentation/devicetree/bindings/interrupt-controller/irq-lp8x4x.txt
new file mode 100644
index 0000000..c8940d2
--- /dev/null
+++ b/Documentation/devicetree/bindings/interrupt-controller/irq-lp8x4x.txt
@@ -0,0 +1,49 @@
+ICP DAS LP-8x4x FPGA Interrupt Controller
+
+ICP DAS LP-8x4x contains FPGA chip. The chip functions as a interrupt
+source providing 16 additional interrupts among other things.
+
+Required properties:
+- compatible : should be "icpdas,irq-lp8x4x"
+
+- reg: physical base address of the controller and length of memory mapped
+  region.
+
+- interrupt-controller : identifies the node as an interrupt controller
+
+- #interrupt-cells : should be 1
+
+- interrupts : should provide interrupt
+
+- interrupt-parent : should provide a link to interrupt controller either
+		     explicitly and implicitly from a parent node
+
+Example:
+
+	fpga: fpga@17000006 {
+		compatible = "icpdas,irq-lp8x4x";
+		reg = <0x17000006 0x16>;
+		interrupt-parent = <&gpio>;
+		interrupts = <3 IRQ_TYPE_EDGE_RISING>;
+		#interrupt-cells = <1>;
+		interrupt-controller;
+		status = "okay";
+	};
+
+	uart@17009050 {
+		compatible = "icpdas,uart-lp8x4x";
+		reg = <0x17009050 0x10
+		       0x17009030 0x02>;
+		interrupt-parent = <&fpga>;
+		interrupts = <13>;
+		status = "okay";
+	};
+
+	uart@17009060 {
+		compatible = "icpdas,uart-lp8x4x";
+		reg = <0x17009060 0x10
+		       0x17009032 0x02>;
+		interrupt-parent = <&fpga>;
+		interrupts = <14>;
+		status = "okay";
+	};
diff --git a/arch/arm/boot/dts/pxa27x-lp8x4x.dts b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
index 07856e0..78dfd2e 100644
--- a/arch/arm/boot/dts/pxa27x-lp8x4x.dts
+++ b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
@@ -167,6 +167,16 @@
 				reg = <0xa000 0x1000
 				       0x901e 0x1>;
 			};
+
+			fpgairq: irq@9006 {
+				compatible = "icpdas,irq-lp8x4x";
+				reg = <0x9006 0x16>;
+				interrupt-parent = <&gpio>;
+				interrupts = <3 IRQ_TYPE_EDGE_FALLING>;
+				#interrupt-cells = <1>;
+				interrupt-controller;
+				status = "okay";
+			};
 		};
 	};
 };
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index 3792a1a..7e22729 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -35,6 +35,11 @@ config IMGPDC_IRQ
 	select GENERIC_IRQ_CHIP
 	select IRQ_DOMAIN
 
+config LP8X4X_IRQ
+	bool
+	depends on OF
+	select IRQ_DOMAIN
+
 config ORION_IRQCHIP
 	bool
 	select IRQ_DOMAIN
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index c60b901..8a28927 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -22,3 +22,4 @@ obj-$(CONFIG_RENESAS_IRQC)		+= irq-renesas-irqc.o
 obj-$(CONFIG_VERSATILE_FPGA_IRQ)	+= irq-versatile-fpga.o
 obj-$(CONFIG_ARCH_VT8500)		+= irq-vt8500.o
 obj-$(CONFIG_TB10X_IRQC)		+= irq-tb10x.o
+obj-$(CONFIG_LP8X4X_IRQ)		+= irq-lp8x4x.o
diff --git a/drivers/irqchip/irq-lp8x4x.c b/drivers/irqchip/irq-lp8x4x.c
new file mode 100644
index 0000000..5d44880b
--- /dev/null
+++ b/drivers/irqchip/irq-lp8x4x.c
@@ -0,0 +1,205 @@
+/*
+ *  linux/drivers/irqchip/irq-lp8x4x.c
+ *
+ *  Support for ICP DAS LP-8x4x FPGA irq
+ *  Copyright (C) 2013 Sergei Ianovich <ynvich@gmail.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation or any later version.
+ */
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/irqchip/chained_irq.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+#define EOI			0x00000000
+#define INSINT			0x00000002
+#define ENSYSINT		0x00000004
+#define PRIMINT			0x00000006
+#define SECOINT			0x00000008
+#define ENRISEINT		0x0000000A
+#define CLRRISEINT		0x0000000C
+#define ENHILVINT		0x0000000E
+#define CLRHILVINT		0x00000010
+#define ENFALLINT		0x00000012
+#define CLRFALLINT		0x00000014
+#define LP8X4X_IRQ_MEM_SIZE	0x00000016
+
+static unsigned char irq_sys_enabled;
+static unsigned char irq_high_enabled;
+static void *base;
+static int irq_base;
+static int num_irq = 16;
+
+static void lp8x4x_mask_irq(struct irq_data *d)
+{
+	unsigned mask;
+	int irq = d->irq - irq_base;
+
+	if (irq < 0 || irq > 15) {
+		pr_err("lp8x4x: wrong irq handler for irq %i\n", d->irq);
+		return;
+	}
+
+	if (irq < 8) {
+		irq_high_enabled &= ~(1 << irq);
+
+		mask = ioread8(base + ENHILVINT);
+		mask &= ~(1 << irq);
+		iowrite8(mask, base + ENHILVINT);
+	} else {
+		irq -= 8;
+		irq_sys_enabled &= ~(1 << irq);
+
+		mask = ioread8(base + ENSYSINT);
+		mask &= ~(1 << irq);
+		iowrite8(mask, base + ENSYSINT);
+	}
+}
+
+static void lp8x4x_unmask_irq(struct irq_data *d)
+{
+	unsigned mask;
+	int irq = d->irq - irq_base;
+
+	if (irq < 0 || irq > 15) {
+		pr_err("wrong irq handler for irq %i\n", d->irq);
+		return;
+	}
+
+	if (irq < 8) {
+		irq_high_enabled |= 1 << irq;
+		mask = ioread8(base + CLRHILVINT);
+		mask |= 1 << irq;
+		iowrite8(mask, base + CLRHILVINT);
+
+		mask = ioread8(base + ENHILVINT);
+		mask |= 1 << irq;
+		iowrite8(mask, base + ENHILVINT);
+	} else {
+		irq -= 8;
+		irq_sys_enabled |= 1 << irq;
+
+		mask = ioread8(base + SECOINT);
+		mask |= 1 << irq;
+		iowrite8(mask, base + SECOINT);
+
+		mask = ioread8(base + ENSYSINT);
+		mask |= 1 << irq;
+		iowrite8(mask, base + ENSYSINT);
+	}
+}
+
+static struct irq_chip lp8x4x_irq_chip = {
+	.name			= "FPGA",
+	.irq_ack		= lp8x4x_mask_irq,
+	.irq_mask		= lp8x4x_mask_irq,
+	.irq_mask_ack		= lp8x4x_mask_irq,
+	.irq_unmask		= lp8x4x_unmask_irq,
+};
+
+static void lp8x4x_irq_handler(unsigned int irq, struct irq_desc *desc)
+{
+	int loop, n;
+	unsigned long mask;
+	struct irq_chip *chip = irq_desc_get_chip(desc);
+
+	chained_irq_enter(chip, desc);
+
+	do {
+		loop = 0;
+		mask = ioread8(base + CLRHILVINT) & 0xff;
+		mask |= (ioread8(base + SECOINT) & 0x1f) << 8;
+		mask |= (ioread8(base + PRIMINT) & 0xe0) << 8;
+		mask &= (irq_high_enabled | (irq_sys_enabled << 8));
+		for_each_set_bit(n, &mask, BITS_PER_LONG) {
+			loop = 1;
+
+			generic_handle_irq(irq_base + n);
+		}
+	} while (loop);
+
+	iowrite8(0, base + EOI);
+	chained_irq_exit(chip, desc);
+}
+
+static int lp8x4x_irq_domain_map(struct irq_domain *d, unsigned int irq,
+				 irq_hw_number_t hw)
+{
+	irq_set_chip_and_handler(irq, &lp8x4x_irq_chip,
+				 handle_level_irq);
+	set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+	return 0;
+}
+
+const struct irq_domain_ops lp8x4x_irq_domain_ops = {
+	.map	= lp8x4x_irq_domain_map,
+	.xlate	= irq_domain_xlate_onecell,
+};
+
+static struct of_device_id lp8x4x_irq_dt_ids[] = {
+	{ .compatible = "icpdas,irq-lp8x4x", },
+	{}
+};
+
+static int lp8x4x_irq_probe(struct platform_device *pdev)
+{
+	struct resource *rm, *ri;
+	struct device_node *np = pdev->dev.of_node;
+	struct irq_domain *domain;
+
+	rm = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	ri = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!rm || !ri || resource_size(rm) < LP8X4X_IRQ_MEM_SIZE)
+		return -ENODEV;
+
+	base = devm_ioremap_resource(&pdev->dev, rm);
+	if (!base) {
+		dev_err(&pdev->dev, "Failed to ioremap %p\n", base);
+		return -EFAULT;
+	}
+
+	irq_base = irq_alloc_descs(-1, 0, num_irq, 0);
+	if (irq_base < 0) {
+		dev_err(&pdev->dev, "Failed to allocate IRQ numbers\n");
+		return irq_base;
+	}
+
+	domain = irq_domain_add_legacy(np, num_irq, irq_base, 0,
+				       &lp8x4x_irq_domain_ops, NULL);
+	if (!domain) {
+		dev_err(&pdev->dev, "Failed to add IRQ domain\n");
+		return -ENOMEM;
+	}
+
+	iowrite8(0, base + CLRRISEINT);
+	iowrite8(0, base + ENRISEINT);
+	iowrite8(0, base + CLRFALLINT);
+	iowrite8(0, base + ENFALLINT);
+	iowrite8(0, base + CLRHILVINT);
+	iowrite8(0, base + ENHILVINT);
+	iowrite8(0, base + ENSYSINT);
+	iowrite8(0, base + SECOINT);
+
+	irq_set_chained_handler(ri->start, lp8x4x_irq_handler);
+
+	return 0;
+}
+
+static struct platform_driver lp8x4x_irq_driver = {
+	.probe		= lp8x4x_irq_probe,
+	.driver		= {
+		.name	= "irq-lp8x4x",
+		.of_match_table = lp8x4x_irq_dt_ids,
+	},
+};
+
+static int __init lp8x4x_irq_init(void)
+{
+	return platform_driver_register(&lp8x4x_irq_driver);
+}
+postcore_initcall(lp8x4x_irq_init);
-- 
1.8.4.2

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

* [PATCH v3 11/21] ARM: pxa: support ICP DAS LP-8x4x FPGA irq
@ 2013-12-17 19:37             ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-17 19:37 UTC (permalink / raw)
  To: linux-arm-kernel

ICP DAS LP-8x4x contains FPGA chip. The chip functions as a interrupt
source providing 16 additional interrupts among other things. The
interrupt lines are muxed to a GPIO pin. GPIO pins are in turn muxed
to a CPU interrupt line.

Until pxa is completely converted to device tree, it is impossible
to use IRQCHIP_DECLARE() and the irqdomain needs to added manually.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Arnd Bergmann <arnd@arndb.de>
CC: Linus Walleij <linus.walleij@linaro.org>
---
   v2..v3
   * no changes (except number 09/16 -> 10/21)

   v0..v2
   * extract irqchip and move to drivers/irqchip/
   * use device tree
   * use devm helpers where possible

 .../bindings/interrupt-controller/irq-lp8x4x.txt   |  49 +++++
 arch/arm/boot/dts/pxa27x-lp8x4x.dts                |  10 +
 drivers/irqchip/Kconfig                            |   5 +
 drivers/irqchip/Makefile                           |   1 +
 drivers/irqchip/irq-lp8x4x.c                       | 205 +++++++++++++++++++++
 5 files changed, 270 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/interrupt-controller/irq-lp8x4x.txt
 create mode 100644 drivers/irqchip/irq-lp8x4x.c

diff --git a/Documentation/devicetree/bindings/interrupt-controller/irq-lp8x4x.txt b/Documentation/devicetree/bindings/interrupt-controller/irq-lp8x4x.txt
new file mode 100644
index 0000000..c8940d2
--- /dev/null
+++ b/Documentation/devicetree/bindings/interrupt-controller/irq-lp8x4x.txt
@@ -0,0 +1,49 @@
+ICP DAS LP-8x4x FPGA Interrupt Controller
+
+ICP DAS LP-8x4x contains FPGA chip. The chip functions as a interrupt
+source providing 16 additional interrupts among other things.
+
+Required properties:
+- compatible : should be "icpdas,irq-lp8x4x"
+
+- reg: physical base address of the controller and length of memory mapped
+  region.
+
+- interrupt-controller : identifies the node as an interrupt controller
+
+- #interrupt-cells : should be 1
+
+- interrupts : should provide interrupt
+
+- interrupt-parent : should provide a link to interrupt controller either
+		     explicitly and implicitly from a parent node
+
+Example:
+
+	fpga: fpga at 17000006 {
+		compatible = "icpdas,irq-lp8x4x";
+		reg = <0x17000006 0x16>;
+		interrupt-parent = <&gpio>;
+		interrupts = <3 IRQ_TYPE_EDGE_RISING>;
+		#interrupt-cells = <1>;
+		interrupt-controller;
+		status = "okay";
+	};
+
+	uart at 17009050 {
+		compatible = "icpdas,uart-lp8x4x";
+		reg = <0x17009050 0x10
+		       0x17009030 0x02>;
+		interrupt-parent = <&fpga>;
+		interrupts = <13>;
+		status = "okay";
+	};
+
+	uart at 17009060 {
+		compatible = "icpdas,uart-lp8x4x";
+		reg = <0x17009060 0x10
+		       0x17009032 0x02>;
+		interrupt-parent = <&fpga>;
+		interrupts = <14>;
+		status = "okay";
+	};
diff --git a/arch/arm/boot/dts/pxa27x-lp8x4x.dts b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
index 07856e0..78dfd2e 100644
--- a/arch/arm/boot/dts/pxa27x-lp8x4x.dts
+++ b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
@@ -167,6 +167,16 @@
 				reg = <0xa000 0x1000
 				       0x901e 0x1>;
 			};
+
+			fpgairq: irq at 9006 {
+				compatible = "icpdas,irq-lp8x4x";
+				reg = <0x9006 0x16>;
+				interrupt-parent = <&gpio>;
+				interrupts = <3 IRQ_TYPE_EDGE_FALLING>;
+				#interrupt-cells = <1>;
+				interrupt-controller;
+				status = "okay";
+			};
 		};
 	};
 };
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index 3792a1a..7e22729 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -35,6 +35,11 @@ config IMGPDC_IRQ
 	select GENERIC_IRQ_CHIP
 	select IRQ_DOMAIN
 
+config LP8X4X_IRQ
+	bool
+	depends on OF
+	select IRQ_DOMAIN
+
 config ORION_IRQCHIP
 	bool
 	select IRQ_DOMAIN
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index c60b901..8a28927 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -22,3 +22,4 @@ obj-$(CONFIG_RENESAS_IRQC)		+= irq-renesas-irqc.o
 obj-$(CONFIG_VERSATILE_FPGA_IRQ)	+= irq-versatile-fpga.o
 obj-$(CONFIG_ARCH_VT8500)		+= irq-vt8500.o
 obj-$(CONFIG_TB10X_IRQC)		+= irq-tb10x.o
+obj-$(CONFIG_LP8X4X_IRQ)		+= irq-lp8x4x.o
diff --git a/drivers/irqchip/irq-lp8x4x.c b/drivers/irqchip/irq-lp8x4x.c
new file mode 100644
index 0000000..5d44880b
--- /dev/null
+++ b/drivers/irqchip/irq-lp8x4x.c
@@ -0,0 +1,205 @@
+/*
+ *  linux/drivers/irqchip/irq-lp8x4x.c
+ *
+ *  Support for ICP DAS LP-8x4x FPGA irq
+ *  Copyright (C) 2013 Sergei Ianovich <ynvich@gmail.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation or any later version.
+ */
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/irqchip/chained_irq.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+#define EOI			0x00000000
+#define INSINT			0x00000002
+#define ENSYSINT		0x00000004
+#define PRIMINT			0x00000006
+#define SECOINT			0x00000008
+#define ENRISEINT		0x0000000A
+#define CLRRISEINT		0x0000000C
+#define ENHILVINT		0x0000000E
+#define CLRHILVINT		0x00000010
+#define ENFALLINT		0x00000012
+#define CLRFALLINT		0x00000014
+#define LP8X4X_IRQ_MEM_SIZE	0x00000016
+
+static unsigned char irq_sys_enabled;
+static unsigned char irq_high_enabled;
+static void *base;
+static int irq_base;
+static int num_irq = 16;
+
+static void lp8x4x_mask_irq(struct irq_data *d)
+{
+	unsigned mask;
+	int irq = d->irq - irq_base;
+
+	if (irq < 0 || irq > 15) {
+		pr_err("lp8x4x: wrong irq handler for irq %i\n", d->irq);
+		return;
+	}
+
+	if (irq < 8) {
+		irq_high_enabled &= ~(1 << irq);
+
+		mask = ioread8(base + ENHILVINT);
+		mask &= ~(1 << irq);
+		iowrite8(mask, base + ENHILVINT);
+	} else {
+		irq -= 8;
+		irq_sys_enabled &= ~(1 << irq);
+
+		mask = ioread8(base + ENSYSINT);
+		mask &= ~(1 << irq);
+		iowrite8(mask, base + ENSYSINT);
+	}
+}
+
+static void lp8x4x_unmask_irq(struct irq_data *d)
+{
+	unsigned mask;
+	int irq = d->irq - irq_base;
+
+	if (irq < 0 || irq > 15) {
+		pr_err("wrong irq handler for irq %i\n", d->irq);
+		return;
+	}
+
+	if (irq < 8) {
+		irq_high_enabled |= 1 << irq;
+		mask = ioread8(base + CLRHILVINT);
+		mask |= 1 << irq;
+		iowrite8(mask, base + CLRHILVINT);
+
+		mask = ioread8(base + ENHILVINT);
+		mask |= 1 << irq;
+		iowrite8(mask, base + ENHILVINT);
+	} else {
+		irq -= 8;
+		irq_sys_enabled |= 1 << irq;
+
+		mask = ioread8(base + SECOINT);
+		mask |= 1 << irq;
+		iowrite8(mask, base + SECOINT);
+
+		mask = ioread8(base + ENSYSINT);
+		mask |= 1 << irq;
+		iowrite8(mask, base + ENSYSINT);
+	}
+}
+
+static struct irq_chip lp8x4x_irq_chip = {
+	.name			= "FPGA",
+	.irq_ack		= lp8x4x_mask_irq,
+	.irq_mask		= lp8x4x_mask_irq,
+	.irq_mask_ack		= lp8x4x_mask_irq,
+	.irq_unmask		= lp8x4x_unmask_irq,
+};
+
+static void lp8x4x_irq_handler(unsigned int irq, struct irq_desc *desc)
+{
+	int loop, n;
+	unsigned long mask;
+	struct irq_chip *chip = irq_desc_get_chip(desc);
+
+	chained_irq_enter(chip, desc);
+
+	do {
+		loop = 0;
+		mask = ioread8(base + CLRHILVINT) & 0xff;
+		mask |= (ioread8(base + SECOINT) & 0x1f) << 8;
+		mask |= (ioread8(base + PRIMINT) & 0xe0) << 8;
+		mask &= (irq_high_enabled | (irq_sys_enabled << 8));
+		for_each_set_bit(n, &mask, BITS_PER_LONG) {
+			loop = 1;
+
+			generic_handle_irq(irq_base + n);
+		}
+	} while (loop);
+
+	iowrite8(0, base + EOI);
+	chained_irq_exit(chip, desc);
+}
+
+static int lp8x4x_irq_domain_map(struct irq_domain *d, unsigned int irq,
+				 irq_hw_number_t hw)
+{
+	irq_set_chip_and_handler(irq, &lp8x4x_irq_chip,
+				 handle_level_irq);
+	set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+	return 0;
+}
+
+const struct irq_domain_ops lp8x4x_irq_domain_ops = {
+	.map	= lp8x4x_irq_domain_map,
+	.xlate	= irq_domain_xlate_onecell,
+};
+
+static struct of_device_id lp8x4x_irq_dt_ids[] = {
+	{ .compatible = "icpdas,irq-lp8x4x", },
+	{}
+};
+
+static int lp8x4x_irq_probe(struct platform_device *pdev)
+{
+	struct resource *rm, *ri;
+	struct device_node *np = pdev->dev.of_node;
+	struct irq_domain *domain;
+
+	rm = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	ri = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!rm || !ri || resource_size(rm) < LP8X4X_IRQ_MEM_SIZE)
+		return -ENODEV;
+
+	base = devm_ioremap_resource(&pdev->dev, rm);
+	if (!base) {
+		dev_err(&pdev->dev, "Failed to ioremap %p\n", base);
+		return -EFAULT;
+	}
+
+	irq_base = irq_alloc_descs(-1, 0, num_irq, 0);
+	if (irq_base < 0) {
+		dev_err(&pdev->dev, "Failed to allocate IRQ numbers\n");
+		return irq_base;
+	}
+
+	domain = irq_domain_add_legacy(np, num_irq, irq_base, 0,
+				       &lp8x4x_irq_domain_ops, NULL);
+	if (!domain) {
+		dev_err(&pdev->dev, "Failed to add IRQ domain\n");
+		return -ENOMEM;
+	}
+
+	iowrite8(0, base + CLRRISEINT);
+	iowrite8(0, base + ENRISEINT);
+	iowrite8(0, base + CLRFALLINT);
+	iowrite8(0, base + ENFALLINT);
+	iowrite8(0, base + CLRHILVINT);
+	iowrite8(0, base + ENHILVINT);
+	iowrite8(0, base + ENSYSINT);
+	iowrite8(0, base + SECOINT);
+
+	irq_set_chained_handler(ri->start, lp8x4x_irq_handler);
+
+	return 0;
+}
+
+static struct platform_driver lp8x4x_irq_driver = {
+	.probe		= lp8x4x_irq_probe,
+	.driver		= {
+		.name	= "irq-lp8x4x",
+		.of_match_table = lp8x4x_irq_dt_ids,
+	},
+};
+
+static int __init lp8x4x_irq_init(void)
+{
+	return platform_driver_register(&lp8x4x_irq_driver);
+}
+postcore_initcall(lp8x4x_irq_init);
-- 
1.8.4.2

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

* [PATCH v3 12/21] serial: support for 16550A serial ports on LP-8x4x
  2013-12-17 19:37           ` Sergei Ianovich
  (?)
@ 2013-12-17 19:37             ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-17 19:37 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Heikki Krogerus, Rob Herring, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala, Rob Landley,
	Russell King, Greg Kroah-Hartman, Jiri Slaby, Grant Likely,
	Randy Dunlap, Arnd Bergmann, James Cameron,
	open list:OPEN FIRMWARE AND...,
	open list:DOCUMENTATION, open list:SERIAL DRIVERS

The patch adds support for 3 additional LP-8x4x built-in serial
ports.

The device can also host up to 8 extension cards with 4 serial ports
on each card for a total of 35 ports. However, I don't have
the hardware to test extension cards, so they are not supported, yet.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Heikki Krogerus <heikki.krogerus@linux.intel.com>
---
   v2..v3
   * no changes (except number 10/16 -> 12/21)

   v0..v2
   * register platform driver instead of platform device
   * use device tree
   * use devm helpers where possible

 .../devicetree/bindings/serial/lp8x4x-serial.txt   |  35 +++++
 arch/arm/boot/dts/pxa27x-lp8x4x.dts                |  25 ++++
 arch/arm/configs/lp8x4x_defconfig                  |   1 +
 drivers/tty/serial/8250/8250_lp8x4x.c              | 162 +++++++++++++++++++++
 drivers/tty/serial/8250/Kconfig                    |  12 ++
 drivers/tty/serial/8250/Makefile                   |   1 +
 6 files changed, 236 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/serial/lp8x4x-serial.txt
 create mode 100644 drivers/tty/serial/8250/8250_lp8x4x.c

diff --git a/Documentation/devicetree/bindings/serial/lp8x4x-serial.txt b/Documentation/devicetree/bindings/serial/lp8x4x-serial.txt
new file mode 100644
index 0000000..eed4ffc
--- /dev/null
+++ b/Documentation/devicetree/bindings/serial/lp8x4x-serial.txt
@@ -0,0 +1,35 @@
+UART ports on ICP DAS LP-8x4x
+
+ICP DAS LP-8x4x contains three additional serial ports interfaced via
+Analog Devices ADM213EA chips in addition to 3 serial ports on PXA CPU.
+
+Required properties:
+- compatible : should be "icpdas,uart-lp8x4x"
+
+- reg : should provide 16 byte man IO memory region and 1 byte region for
+	termios
+
+- interrupts : should provide interrupt
+
+- interrupt-parent : should provide a link to interrupt controller either
+		     explicitly and implicitly from a parent node
+
+Examples (from pxa27x-lp8x4x.dts):
+
+		uart@17009050 {
+			compatible = "icpdas,uart-lp8x4x";
+			reg = <0x17009050 0x10
+			       0x17009030 0x02>;
+			interrupt-parent = <&fpga>;
+			interrupts = <13>;
+			status = "okay";
+		};
+
+		uart@17009060 {
+			compatible = "icpdas,uart-lp8x4x";
+			reg = <0x17009060 0x10
+			       0x17009032 0x02>;
+			interrupt-parent = <&fpga>;
+			interrupts = <14>;
+			status = "okay";
+		};
diff --git a/arch/arm/boot/dts/pxa27x-lp8x4x.dts b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
index 78dfd2e..ee0d8b7 100644
--- a/arch/arm/boot/dts/pxa27x-lp8x4x.dts
+++ b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
@@ -155,6 +155,7 @@
 			#address-cells = <1>;
 			#size-cells = <1>;
 			ranges = <0 5 0x3000000 0x10000>;
+			interrupt-parent = <&fpgairq>;
 
 			rtc@901c {
 				compatible = "ds,rtc-ds1302";
@@ -177,6 +178,30 @@
 				interrupt-controller;
 				status = "okay";
 			};
+
+			uart@9050 {
+				compatible = "icpdas,uart-lp8x4x";
+				reg = <0x9050 0x10
+				       0x9030 0x02>;
+				interrupts = <13>;
+				status = "okay";
+			};
+
+			uart@9060 {
+				compatible = "icpdas,uart-lp8x4x";
+				reg = <0x9060 0x10
+				       0x9032 0x02>;
+				interrupts = <14>;
+				status = "okay";
+			};
+
+			uart@9070 {
+				compatible = "icpdas,uart-lp8x4x";
+				reg = <0x9070 0x10
+				       0x9034 0x02>;
+				interrupts = <15>;
+				status = "okay";
+			};
 		};
 	};
 };
diff --git a/arch/arm/configs/lp8x4x_defconfig b/arch/arm/configs/lp8x4x_defconfig
index 17a4e6f..9116ce1 100644
--- a/arch/arm/configs/lp8x4x_defconfig
+++ b/arch/arm/configs/lp8x4x_defconfig
@@ -112,6 +112,7 @@ CONFIG_SERIAL_8250_EXTENDED=y
 CONFIG_SERIAL_8250_MANY_PORTS=y
 CONFIG_SERIAL_8250_SHARE_IRQ=y
 CONFIG_SERIAL_PXA=y
+CONFIG_SERIAL_8250_LP8X4X=m
 CONFIG_HW_RANDOM=y
 CONFIG_I2C=m
 # CONFIG_I2C_COMPAT is not set
diff --git a/drivers/tty/serial/8250/8250_lp8x4x.c b/drivers/tty/serial/8250/8250_lp8x4x.c
new file mode 100644
index 0000000..ec2f215
--- /dev/null
+++ b/drivers/tty/serial/8250/8250_lp8x4x.c
@@ -0,0 +1,162 @@
+/*  linux/drivers/tty/serial/8250/8250_lp8x4x.c
+ *
+ *  Support for 16550A serial ports on ICP DAS LP-8x4x
+ *
+ *  Copyright (C) 2013 Sergei Ianovich <ynvich@gmail.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/module.h>
+#include <linux/serial_8250.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+struct lp8x4x_serial_data {
+	int			line;
+	void			*ios_mem;
+};
+
+static void lp8x4x_serial_set_termios(struct uart_port *port,
+		struct ktermios *termios, struct ktermios *old)
+{
+	unsigned int len;
+	unsigned int baud;
+	struct lp8x4x_serial_data *data = port->private_data;
+
+	switch (termios->c_cflag & CSIZE) {
+	case CS5:
+		len = 7;
+		break;
+	case CS6:
+		len = 8;
+		break;
+	case CS7:
+		len = 9;
+		break;
+	default:
+	case CS8:
+		len = 10;
+		break;
+	}
+
+	if (termios->c_cflag & CSTOPB)
+		len++;
+	if (termios->c_cflag & PARENB)
+		len++;
+	if (!(termios->c_cflag & PARODD))
+		len++;
+#ifdef CMSPAR
+	if (termios->c_cflag & CMSPAR)
+		len++;
+#endif
+
+	len -= 9;
+	len &= 3;
+	len <<= 3;
+	/*
+	 * Ask the core to calculate the divisor for us.
+	 */
+	baud = uart_get_baud_rate(port, termios, old,
+				  port->uartclk / 16 / 0xffff,
+				  port->uartclk / 16);
+	switch (baud) {
+	case 2400:
+		len |= 1;
+	case 4800:
+		len |= 2;
+	case 19200:
+		len |= 4;
+	case 38400:
+		len |= 5;
+	case 57600:
+		len |= 6;
+	case 115200:
+		len |= 7;
+	case 9600:
+	default:
+		len |= 3;
+	};
+	iowrite8(len, data->ios_mem);
+
+	serial8250_do_set_termios(port, termios, old);
+}
+
+static struct of_device_id lp8x4x_serial_dt_ids[] = {
+	{ .compatible = "icpdas,uart-lp8x4x", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, lp8x4x_serial_dt_ids);
+
+static int lp8x4x_serial_probe(struct platform_device *pdev)
+{
+	struct uart_8250_port uart = {};
+	struct lp8x4x_serial_data *data;
+	struct resource *mmres, *mires, *irqres;
+	int ret;
+
+	mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	mires = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	irqres = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!mmres || !mires || !irqres)
+		return -ENODEV;
+
+	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->ios_mem = devm_ioremap_resource(&pdev->dev, mires);
+	if (!data->ios_mem)
+		return -EFAULT;
+
+	uart.port.iotype = UPIO_MEM;
+	uart.port.mapbase = mmres->start;
+	uart.port.iobase = mmres->start;
+	uart.port.regshift = 1;
+	uart.port.irq = irqres->start;
+	uart.port.flags = UPF_IOREMAP;
+	uart.port.dev = &pdev->dev;
+	uart.port.uartclk = 14745600;
+	uart.port.set_termios = lp8x4x_serial_set_termios;
+	uart.port.private_data = data;
+
+	ret = serial8250_register_8250_port(&uart);
+	if (ret < 0)
+		return ret;
+
+	data->line = ret;
+
+	platform_set_drvdata(pdev, data);
+
+	return 0;
+}
+
+static int lp8x4x_serial_remove(struct platform_device *pdev)
+{
+	struct lp8x4x_serial_data *data = platform_get_drvdata(pdev);
+
+	serial8250_unregister_port(data->line);
+
+	return 0;
+}
+
+static struct platform_driver lp8x4x_serial_driver = {
+	.probe          = lp8x4x_serial_probe,
+	.remove         = lp8x4x_serial_remove,
+
+	.driver		= {
+		.name	= "uart-lp8x4x",
+		.owner	= THIS_MODULE,
+		.of_match_table = lp8x4x_serial_dt_ids,
+	},
+};
+
+module_platform_driver(lp8x4x_serial_driver);
+
+MODULE_AUTHOR("Sergei Ianovich");
+MODULE_DESCRIPTION("8250 serial port module for LP-8x4x");
+MODULE_LICENSE("GPL");
diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
index 81bd7c9..9fb0fbb 100644
--- a/drivers/tty/serial/8250/Kconfig
+++ b/drivers/tty/serial/8250/Kconfig
@@ -311,3 +311,15 @@ config SERIAL_PXA
 	  can enable its onboard serial ports by enabling this option.
 
 	  If you choose M here, the module name will be 8250_pxa.
+
+config SERIAL_8250_LP8X4X
+	tristate "Support 16550A ports on ICP DAS LP-8x4x"
+	depends on OF && SERIAL_8250 && SERIAL_8250_MANY_PORTS && ARCH_PXA
+	select LP8X4X_IRQ
+	help
+	  In addition to serial ports on PXA270 SoC, LP-8x4x has 1 dual
+	  RS232/RS485 port, 1 RS485 port and 1 RS232 port.
+
+	  Say N here, unless you plan to run this kernel on a LP-8x4x system.
+
+	  If you choose M here, the module name will be 8250_lp8x4x.
diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile
index b7d1b61..7370bfb 100644
--- a/drivers/tty/serial/8250/Makefile
+++ b/drivers/tty/serial/8250/Makefile
@@ -17,6 +17,7 @@ obj-$(CONFIG_SERIAL_8250_ACCENT)	+= 8250_accent.o
 obj-$(CONFIG_SERIAL_8250_BOCA)		+= 8250_boca.o
 obj-$(CONFIG_SERIAL_8250_EXAR_ST16C554)	+= 8250_exar_st16c554.o
 obj-$(CONFIG_SERIAL_8250_HUB6)		+= 8250_hub6.o
+obj-$(CONFIG_SERIAL_8250_LP8X4X)	+= 8250_lp8x4x.o
 obj-$(CONFIG_SERIAL_8250_FSL)		+= 8250_fsl.o
 obj-$(CONFIG_SERIAL_8250_DW)		+= 8250_dw.o
 obj-$(CONFIG_SERIAL_8250_EM)		+= 8250_em.o
-- 
1.8.4.2


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

* [PATCH v3 12/21] serial: support for 16550A serial ports on LP-8x4x
@ 2013-12-17 19:37             ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-17 19:37 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Heikki Krogerus, Rob Herring, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala, Rob Landley,
	Russell King, Greg Kroah-Hartman, Jiri Slaby, Grant Likely,
	Randy Dunlap, Arnd Bergmann, James Cameron,
	open list:OPEN FIRMWARE AND...,
	open list:DOCUMENTATION, open list:SERIAL DRIVERS

The patch adds support for 3 additional LP-8x4x built-in serial
ports.

The device can also host up to 8 extension cards with 4 serial ports
on each card for a total of 35 ports. However, I don't have
the hardware to test extension cards, so they are not supported, yet.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Heikki Krogerus <heikki.krogerus@linux.intel.com>
---
   v2..v3
   * no changes (except number 10/16 -> 12/21)

   v0..v2
   * register platform driver instead of platform device
   * use device tree
   * use devm helpers where possible

 .../devicetree/bindings/serial/lp8x4x-serial.txt   |  35 +++++
 arch/arm/boot/dts/pxa27x-lp8x4x.dts                |  25 ++++
 arch/arm/configs/lp8x4x_defconfig                  |   1 +
 drivers/tty/serial/8250/8250_lp8x4x.c              | 162 +++++++++++++++++++++
 drivers/tty/serial/8250/Kconfig                    |  12 ++
 drivers/tty/serial/8250/Makefile                   |   1 +
 6 files changed, 236 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/serial/lp8x4x-serial.txt
 create mode 100644 drivers/tty/serial/8250/8250_lp8x4x.c

diff --git a/Documentation/devicetree/bindings/serial/lp8x4x-serial.txt b/Documentation/devicetree/bindings/serial/lp8x4x-serial.txt
new file mode 100644
index 0000000..eed4ffc
--- /dev/null
+++ b/Documentation/devicetree/bindings/serial/lp8x4x-serial.txt
@@ -0,0 +1,35 @@
+UART ports on ICP DAS LP-8x4x
+
+ICP DAS LP-8x4x contains three additional serial ports interfaced via
+Analog Devices ADM213EA chips in addition to 3 serial ports on PXA CPU.
+
+Required properties:
+- compatible : should be "icpdas,uart-lp8x4x"
+
+- reg : should provide 16 byte man IO memory region and 1 byte region for
+	termios
+
+- interrupts : should provide interrupt
+
+- interrupt-parent : should provide a link to interrupt controller either
+		     explicitly and implicitly from a parent node
+
+Examples (from pxa27x-lp8x4x.dts):
+
+		uart@17009050 {
+			compatible = "icpdas,uart-lp8x4x";
+			reg = <0x17009050 0x10
+			       0x17009030 0x02>;
+			interrupt-parent = <&fpga>;
+			interrupts = <13>;
+			status = "okay";
+		};
+
+		uart@17009060 {
+			compatible = "icpdas,uart-lp8x4x";
+			reg = <0x17009060 0x10
+			       0x17009032 0x02>;
+			interrupt-parent = <&fpga>;
+			interrupts = <14>;
+			status = "okay";
+		};
diff --git a/arch/arm/boot/dts/pxa27x-lp8x4x.dts b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
index 78dfd2e..ee0d8b7 100644
--- a/arch/arm/boot/dts/pxa27x-lp8x4x.dts
+++ b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
@@ -155,6 +155,7 @@
 			#address-cells = <1>;
 			#size-cells = <1>;
 			ranges = <0 5 0x3000000 0x10000>;
+			interrupt-parent = <&fpgairq>;
 
 			rtc@901c {
 				compatible = "ds,rtc-ds1302";
@@ -177,6 +178,30 @@
 				interrupt-controller;
 				status = "okay";
 			};
+
+			uart@9050 {
+				compatible = "icpdas,uart-lp8x4x";
+				reg = <0x9050 0x10
+				       0x9030 0x02>;
+				interrupts = <13>;
+				status = "okay";
+			};
+
+			uart@9060 {
+				compatible = "icpdas,uart-lp8x4x";
+				reg = <0x9060 0x10
+				       0x9032 0x02>;
+				interrupts = <14>;
+				status = "okay";
+			};
+
+			uart@9070 {
+				compatible = "icpdas,uart-lp8x4x";
+				reg = <0x9070 0x10
+				       0x9034 0x02>;
+				interrupts = <15>;
+				status = "okay";
+			};
 		};
 	};
 };
diff --git a/arch/arm/configs/lp8x4x_defconfig b/arch/arm/configs/lp8x4x_defconfig
index 17a4e6f..9116ce1 100644
--- a/arch/arm/configs/lp8x4x_defconfig
+++ b/arch/arm/configs/lp8x4x_defconfig
@@ -112,6 +112,7 @@ CONFIG_SERIAL_8250_EXTENDED=y
 CONFIG_SERIAL_8250_MANY_PORTS=y
 CONFIG_SERIAL_8250_SHARE_IRQ=y
 CONFIG_SERIAL_PXA=y
+CONFIG_SERIAL_8250_LP8X4X=m
 CONFIG_HW_RANDOM=y
 CONFIG_I2C=m
 # CONFIG_I2C_COMPAT is not set
diff --git a/drivers/tty/serial/8250/8250_lp8x4x.c b/drivers/tty/serial/8250/8250_lp8x4x.c
new file mode 100644
index 0000000..ec2f215
--- /dev/null
+++ b/drivers/tty/serial/8250/8250_lp8x4x.c
@@ -0,0 +1,162 @@
+/*  linux/drivers/tty/serial/8250/8250_lp8x4x.c
+ *
+ *  Support for 16550A serial ports on ICP DAS LP-8x4x
+ *
+ *  Copyright (C) 2013 Sergei Ianovich <ynvich@gmail.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/module.h>
+#include <linux/serial_8250.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+struct lp8x4x_serial_data {
+	int			line;
+	void			*ios_mem;
+};
+
+static void lp8x4x_serial_set_termios(struct uart_port *port,
+		struct ktermios *termios, struct ktermios *old)
+{
+	unsigned int len;
+	unsigned int baud;
+	struct lp8x4x_serial_data *data = port->private_data;
+
+	switch (termios->c_cflag & CSIZE) {
+	case CS5:
+		len = 7;
+		break;
+	case CS6:
+		len = 8;
+		break;
+	case CS7:
+		len = 9;
+		break;
+	default:
+	case CS8:
+		len = 10;
+		break;
+	}
+
+	if (termios->c_cflag & CSTOPB)
+		len++;
+	if (termios->c_cflag & PARENB)
+		len++;
+	if (!(termios->c_cflag & PARODD))
+		len++;
+#ifdef CMSPAR
+	if (termios->c_cflag & CMSPAR)
+		len++;
+#endif
+
+	len -= 9;
+	len &= 3;
+	len <<= 3;
+	/*
+	 * Ask the core to calculate the divisor for us.
+	 */
+	baud = uart_get_baud_rate(port, termios, old,
+				  port->uartclk / 16 / 0xffff,
+				  port->uartclk / 16);
+	switch (baud) {
+	case 2400:
+		len |= 1;
+	case 4800:
+		len |= 2;
+	case 19200:
+		len |= 4;
+	case 38400:
+		len |= 5;
+	case 57600:
+		len |= 6;
+	case 115200:
+		len |= 7;
+	case 9600:
+	default:
+		len |= 3;
+	};
+	iowrite8(len, data->ios_mem);
+
+	serial8250_do_set_termios(port, termios, old);
+}
+
+static struct of_device_id lp8x4x_serial_dt_ids[] = {
+	{ .compatible = "icpdas,uart-lp8x4x", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, lp8x4x_serial_dt_ids);
+
+static int lp8x4x_serial_probe(struct platform_device *pdev)
+{
+	struct uart_8250_port uart = {};
+	struct lp8x4x_serial_data *data;
+	struct resource *mmres, *mires, *irqres;
+	int ret;
+
+	mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	mires = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	irqres = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!mmres || !mires || !irqres)
+		return -ENODEV;
+
+	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->ios_mem = devm_ioremap_resource(&pdev->dev, mires);
+	if (!data->ios_mem)
+		return -EFAULT;
+
+	uart.port.iotype = UPIO_MEM;
+	uart.port.mapbase = mmres->start;
+	uart.port.iobase = mmres->start;
+	uart.port.regshift = 1;
+	uart.port.irq = irqres->start;
+	uart.port.flags = UPF_IOREMAP;
+	uart.port.dev = &pdev->dev;
+	uart.port.uartclk = 14745600;
+	uart.port.set_termios = lp8x4x_serial_set_termios;
+	uart.port.private_data = data;
+
+	ret = serial8250_register_8250_port(&uart);
+	if (ret < 0)
+		return ret;
+
+	data->line = ret;
+
+	platform_set_drvdata(pdev, data);
+
+	return 0;
+}
+
+static int lp8x4x_serial_remove(struct platform_device *pdev)
+{
+	struct lp8x4x_serial_data *data = platform_get_drvdata(pdev);
+
+	serial8250_unregister_port(data->line);
+
+	return 0;
+}
+
+static struct platform_driver lp8x4x_serial_driver = {
+	.probe          = lp8x4x_serial_probe,
+	.remove         = lp8x4x_serial_remove,
+
+	.driver		= {
+		.name	= "uart-lp8x4x",
+		.owner	= THIS_MODULE,
+		.of_match_table = lp8x4x_serial_dt_ids,
+	},
+};
+
+module_platform_driver(lp8x4x_serial_driver);
+
+MODULE_AUTHOR("Sergei Ianovich");
+MODULE_DESCRIPTION("8250 serial port module for LP-8x4x");
+MODULE_LICENSE("GPL");
diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
index 81bd7c9..9fb0fbb 100644
--- a/drivers/tty/serial/8250/Kconfig
+++ b/drivers/tty/serial/8250/Kconfig
@@ -311,3 +311,15 @@ config SERIAL_PXA
 	  can enable its onboard serial ports by enabling this option.
 
 	  If you choose M here, the module name will be 8250_pxa.
+
+config SERIAL_8250_LP8X4X
+	tristate "Support 16550A ports on ICP DAS LP-8x4x"
+	depends on OF && SERIAL_8250 && SERIAL_8250_MANY_PORTS && ARCH_PXA
+	select LP8X4X_IRQ
+	help
+	  In addition to serial ports on PXA270 SoC, LP-8x4x has 1 dual
+	  RS232/RS485 port, 1 RS485 port and 1 RS232 port.
+
+	  Say N here, unless you plan to run this kernel on a LP-8x4x system.
+
+	  If you choose M here, the module name will be 8250_lp8x4x.
diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile
index b7d1b61..7370bfb 100644
--- a/drivers/tty/serial/8250/Makefile
+++ b/drivers/tty/serial/8250/Makefile
@@ -17,6 +17,7 @@ obj-$(CONFIG_SERIAL_8250_ACCENT)	+= 8250_accent.o
 obj-$(CONFIG_SERIAL_8250_BOCA)		+= 8250_boca.o
 obj-$(CONFIG_SERIAL_8250_EXAR_ST16C554)	+= 8250_exar_st16c554.o
 obj-$(CONFIG_SERIAL_8250_HUB6)		+= 8250_hub6.o
+obj-$(CONFIG_SERIAL_8250_LP8X4X)	+= 8250_lp8x4x.o
 obj-$(CONFIG_SERIAL_8250_FSL)		+= 8250_fsl.o
 obj-$(CONFIG_SERIAL_8250_DW)		+= 8250_dw.o
 obj-$(CONFIG_SERIAL_8250_EM)		+= 8250_em.o
-- 
1.8.4.2

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

* [PATCH v3 12/21] serial: support for 16550A serial ports on LP-8x4x
@ 2013-12-17 19:37             ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-17 19:37 UTC (permalink / raw)
  To: linux-arm-kernel

The patch adds support for 3 additional LP-8x4x built-in serial
ports.

The device can also host up to 8 extension cards with 4 serial ports
on each card for a total of 35 ports. However, I don't have
the hardware to test extension cards, so they are not supported, yet.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Heikki Krogerus <heikki.krogerus@linux.intel.com>
---
   v2..v3
   * no changes (except number 10/16 -> 12/21)

   v0..v2
   * register platform driver instead of platform device
   * use device tree
   * use devm helpers where possible

 .../devicetree/bindings/serial/lp8x4x-serial.txt   |  35 +++++
 arch/arm/boot/dts/pxa27x-lp8x4x.dts                |  25 ++++
 arch/arm/configs/lp8x4x_defconfig                  |   1 +
 drivers/tty/serial/8250/8250_lp8x4x.c              | 162 +++++++++++++++++++++
 drivers/tty/serial/8250/Kconfig                    |  12 ++
 drivers/tty/serial/8250/Makefile                   |   1 +
 6 files changed, 236 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/serial/lp8x4x-serial.txt
 create mode 100644 drivers/tty/serial/8250/8250_lp8x4x.c

diff --git a/Documentation/devicetree/bindings/serial/lp8x4x-serial.txt b/Documentation/devicetree/bindings/serial/lp8x4x-serial.txt
new file mode 100644
index 0000000..eed4ffc
--- /dev/null
+++ b/Documentation/devicetree/bindings/serial/lp8x4x-serial.txt
@@ -0,0 +1,35 @@
+UART ports on ICP DAS LP-8x4x
+
+ICP DAS LP-8x4x contains three additional serial ports interfaced via
+Analog Devices ADM213EA chips in addition to 3 serial ports on PXA CPU.
+
+Required properties:
+- compatible : should be "icpdas,uart-lp8x4x"
+
+- reg : should provide 16 byte man IO memory region and 1 byte region for
+	termios
+
+- interrupts : should provide interrupt
+
+- interrupt-parent : should provide a link to interrupt controller either
+		     explicitly and implicitly from a parent node
+
+Examples (from pxa27x-lp8x4x.dts):
+
+		uart at 17009050 {
+			compatible = "icpdas,uart-lp8x4x";
+			reg = <0x17009050 0x10
+			       0x17009030 0x02>;
+			interrupt-parent = <&fpga>;
+			interrupts = <13>;
+			status = "okay";
+		};
+
+		uart at 17009060 {
+			compatible = "icpdas,uart-lp8x4x";
+			reg = <0x17009060 0x10
+			       0x17009032 0x02>;
+			interrupt-parent = <&fpga>;
+			interrupts = <14>;
+			status = "okay";
+		};
diff --git a/arch/arm/boot/dts/pxa27x-lp8x4x.dts b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
index 78dfd2e..ee0d8b7 100644
--- a/arch/arm/boot/dts/pxa27x-lp8x4x.dts
+++ b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
@@ -155,6 +155,7 @@
 			#address-cells = <1>;
 			#size-cells = <1>;
 			ranges = <0 5 0x3000000 0x10000>;
+			interrupt-parent = <&fpgairq>;
 
 			rtc at 901c {
 				compatible = "ds,rtc-ds1302";
@@ -177,6 +178,30 @@
 				interrupt-controller;
 				status = "okay";
 			};
+
+			uart at 9050 {
+				compatible = "icpdas,uart-lp8x4x";
+				reg = <0x9050 0x10
+				       0x9030 0x02>;
+				interrupts = <13>;
+				status = "okay";
+			};
+
+			uart at 9060 {
+				compatible = "icpdas,uart-lp8x4x";
+				reg = <0x9060 0x10
+				       0x9032 0x02>;
+				interrupts = <14>;
+				status = "okay";
+			};
+
+			uart at 9070 {
+				compatible = "icpdas,uart-lp8x4x";
+				reg = <0x9070 0x10
+				       0x9034 0x02>;
+				interrupts = <15>;
+				status = "okay";
+			};
 		};
 	};
 };
diff --git a/arch/arm/configs/lp8x4x_defconfig b/arch/arm/configs/lp8x4x_defconfig
index 17a4e6f..9116ce1 100644
--- a/arch/arm/configs/lp8x4x_defconfig
+++ b/arch/arm/configs/lp8x4x_defconfig
@@ -112,6 +112,7 @@ CONFIG_SERIAL_8250_EXTENDED=y
 CONFIG_SERIAL_8250_MANY_PORTS=y
 CONFIG_SERIAL_8250_SHARE_IRQ=y
 CONFIG_SERIAL_PXA=y
+CONFIG_SERIAL_8250_LP8X4X=m
 CONFIG_HW_RANDOM=y
 CONFIG_I2C=m
 # CONFIG_I2C_COMPAT is not set
diff --git a/drivers/tty/serial/8250/8250_lp8x4x.c b/drivers/tty/serial/8250/8250_lp8x4x.c
new file mode 100644
index 0000000..ec2f215
--- /dev/null
+++ b/drivers/tty/serial/8250/8250_lp8x4x.c
@@ -0,0 +1,162 @@
+/*  linux/drivers/tty/serial/8250/8250_lp8x4x.c
+ *
+ *  Support for 16550A serial ports on ICP DAS LP-8x4x
+ *
+ *  Copyright (C) 2013 Sergei Ianovich <ynvich@gmail.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/module.h>
+#include <linux/serial_8250.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+struct lp8x4x_serial_data {
+	int			line;
+	void			*ios_mem;
+};
+
+static void lp8x4x_serial_set_termios(struct uart_port *port,
+		struct ktermios *termios, struct ktermios *old)
+{
+	unsigned int len;
+	unsigned int baud;
+	struct lp8x4x_serial_data *data = port->private_data;
+
+	switch (termios->c_cflag & CSIZE) {
+	case CS5:
+		len = 7;
+		break;
+	case CS6:
+		len = 8;
+		break;
+	case CS7:
+		len = 9;
+		break;
+	default:
+	case CS8:
+		len = 10;
+		break;
+	}
+
+	if (termios->c_cflag & CSTOPB)
+		len++;
+	if (termios->c_cflag & PARENB)
+		len++;
+	if (!(termios->c_cflag & PARODD))
+		len++;
+#ifdef CMSPAR
+	if (termios->c_cflag & CMSPAR)
+		len++;
+#endif
+
+	len -= 9;
+	len &= 3;
+	len <<= 3;
+	/*
+	 * Ask the core to calculate the divisor for us.
+	 */
+	baud = uart_get_baud_rate(port, termios, old,
+				  port->uartclk / 16 / 0xffff,
+				  port->uartclk / 16);
+	switch (baud) {
+	case 2400:
+		len |= 1;
+	case 4800:
+		len |= 2;
+	case 19200:
+		len |= 4;
+	case 38400:
+		len |= 5;
+	case 57600:
+		len |= 6;
+	case 115200:
+		len |= 7;
+	case 9600:
+	default:
+		len |= 3;
+	};
+	iowrite8(len, data->ios_mem);
+
+	serial8250_do_set_termios(port, termios, old);
+}
+
+static struct of_device_id lp8x4x_serial_dt_ids[] = {
+	{ .compatible = "icpdas,uart-lp8x4x", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, lp8x4x_serial_dt_ids);
+
+static int lp8x4x_serial_probe(struct platform_device *pdev)
+{
+	struct uart_8250_port uart = {};
+	struct lp8x4x_serial_data *data;
+	struct resource *mmres, *mires, *irqres;
+	int ret;
+
+	mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	mires = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	irqres = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!mmres || !mires || !irqres)
+		return -ENODEV;
+
+	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->ios_mem = devm_ioremap_resource(&pdev->dev, mires);
+	if (!data->ios_mem)
+		return -EFAULT;
+
+	uart.port.iotype = UPIO_MEM;
+	uart.port.mapbase = mmres->start;
+	uart.port.iobase = mmres->start;
+	uart.port.regshift = 1;
+	uart.port.irq = irqres->start;
+	uart.port.flags = UPF_IOREMAP;
+	uart.port.dev = &pdev->dev;
+	uart.port.uartclk = 14745600;
+	uart.port.set_termios = lp8x4x_serial_set_termios;
+	uart.port.private_data = data;
+
+	ret = serial8250_register_8250_port(&uart);
+	if (ret < 0)
+		return ret;
+
+	data->line = ret;
+
+	platform_set_drvdata(pdev, data);
+
+	return 0;
+}
+
+static int lp8x4x_serial_remove(struct platform_device *pdev)
+{
+	struct lp8x4x_serial_data *data = platform_get_drvdata(pdev);
+
+	serial8250_unregister_port(data->line);
+
+	return 0;
+}
+
+static struct platform_driver lp8x4x_serial_driver = {
+	.probe          = lp8x4x_serial_probe,
+	.remove         = lp8x4x_serial_remove,
+
+	.driver		= {
+		.name	= "uart-lp8x4x",
+		.owner	= THIS_MODULE,
+		.of_match_table = lp8x4x_serial_dt_ids,
+	},
+};
+
+module_platform_driver(lp8x4x_serial_driver);
+
+MODULE_AUTHOR("Sergei Ianovich");
+MODULE_DESCRIPTION("8250 serial port module for LP-8x4x");
+MODULE_LICENSE("GPL");
diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
index 81bd7c9..9fb0fbb 100644
--- a/drivers/tty/serial/8250/Kconfig
+++ b/drivers/tty/serial/8250/Kconfig
@@ -311,3 +311,15 @@ config SERIAL_PXA
 	  can enable its onboard serial ports by enabling this option.
 
 	  If you choose M here, the module name will be 8250_pxa.
+
+config SERIAL_8250_LP8X4X
+	tristate "Support 16550A ports on ICP DAS LP-8x4x"
+	depends on OF && SERIAL_8250 && SERIAL_8250_MANY_PORTS && ARCH_PXA
+	select LP8X4X_IRQ
+	help
+	  In addition to serial ports on PXA270 SoC, LP-8x4x has 1 dual
+	  RS232/RS485 port, 1 RS485 port and 1 RS232 port.
+
+	  Say N here, unless you plan to run this kernel on a LP-8x4x system.
+
+	  If you choose M here, the module name will be 8250_lp8x4x.
diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile
index b7d1b61..7370bfb 100644
--- a/drivers/tty/serial/8250/Makefile
+++ b/drivers/tty/serial/8250/Makefile
@@ -17,6 +17,7 @@ obj-$(CONFIG_SERIAL_8250_ACCENT)	+= 8250_accent.o
 obj-$(CONFIG_SERIAL_8250_BOCA)		+= 8250_boca.o
 obj-$(CONFIG_SERIAL_8250_EXAR_ST16C554)	+= 8250_exar_st16c554.o
 obj-$(CONFIG_SERIAL_8250_HUB6)		+= 8250_hub6.o
+obj-$(CONFIG_SERIAL_8250_LP8X4X)	+= 8250_lp8x4x.o
 obj-$(CONFIG_SERIAL_8250_FSL)		+= 8250_fsl.o
 obj-$(CONFIG_SERIAL_8250_DW)		+= 8250_dw.o
 obj-$(CONFIG_SERIAL_8250_EM)		+= 8250_em.o
-- 
1.8.4.2

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

* [PATCH v3 13/21] misc: support for LP-8x4x custom parallel bus
  2013-12-17 19:37           ` Sergei Ianovich
  (?)
@ 2013-12-17 19:37             ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-17 19:37 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Rob Landley, Russell King,
	Arnd Bergmann, Greg Kroah-Hartman, Grant Likely,
	open list:OPEN FIRMWARE AND...,
	open list:DOCUMENTATION

This patch implements probing for the bus and reporting the number
of available expansion slots.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
   v2..v3
   * fixed goto after bus_register
   * number change (11/16 -> 13/21)

   v0..v2
   * use device tree
   * use devm helpers where possible

 .../devicetree/bindings/misc/lp8x4x-bus.txt        |  16 ++
 Documentation/misc-devices/lp8x4x_bus.txt          |  30 ++++
 arch/arm/boot/dts/pxa27x-lp8x4x.dts                |   5 +
 arch/arm/configs/lp8x4x_defconfig                  |   1 +
 drivers/misc/Kconfig                               |  13 ++
 drivers/misc/Makefile                              |   1 +
 drivers/misc/lp8x4x_bus.c                          | 167 +++++++++++++++++++++
 7 files changed, 233 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
 create mode 100644 Documentation/misc-devices/lp8x4x_bus.txt
 create mode 100644 drivers/misc/lp8x4x_bus.c

diff --git a/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt b/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
new file mode 100644
index 0000000..1c87a29
--- /dev/null
+++ b/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
@@ -0,0 +1,16 @@
+Custom parallel bus on ICP DAS LP-8x4x industrial computers
+
+See Documentation/misc-devices/lp8x4x_bus.txt for details.
+
+Required properties:
+- compatible : should be "icpdas,backplane-lp8x4x"
+
+- reg: physical base address of the slot count register and the length
+       of the memory mapped region.
+
+Example:
+
+	backplane {
+		compatible = "icpdas,backplane-lp8x4x";
+		reg = <0x17009046 0x2>;
+	};
diff --git a/Documentation/misc-devices/lp8x4x_bus.txt b/Documentation/misc-devices/lp8x4x_bus.txt
new file mode 100644
index 0000000..f5392b3
--- /dev/null
+++ b/Documentation/misc-devices/lp8x4x_bus.txt
@@ -0,0 +1,30 @@
+Kernel driver lpx8x4x_bus
+======================
+
+Supported hardare:
+Custom parallel bus on ICP DAS LP-8x4x industrial computers
+
+Data sheet:
+Not freely available
+
+Author:
+Sergei Ianovich <ynvich@gmail.com>
+
+Description
+-----------
+
+http://www.icpdas.com/root/product/solutions/pac/linpac/lp-8x4x_hardware.html
+
+LP-8x4x is an ARM-based industrial computer with a custom parallel bus to
+connect expansion modules with digital input/output, analog input/output,
+serial, CAN and other types of ports.
+
+The bus is implemented by a FPGA.
+
+SYSFS
+-----
+
+/sys/bus/icpdas/devices/backplane:
+
+slot_count
+	RO - shows total number of expansion slots on the device
diff --git a/arch/arm/boot/dts/pxa27x-lp8x4x.dts b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
index ee0d8b7..4ea566c 100644
--- a/arch/arm/boot/dts/pxa27x-lp8x4x.dts
+++ b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
@@ -202,6 +202,11 @@
 				interrupts = <15>;
 				status = "okay";
 			};
+
+			backplane {
+				compatible = "icpdas,backplane-lp8x4x";
+				reg = <0x9046 0x2>;
+			};
 		};
 	};
 };
diff --git a/arch/arm/configs/lp8x4x_defconfig b/arch/arm/configs/lp8x4x_defconfig
index 9116ce1..c34eb2a 100644
--- a/arch/arm/configs/lp8x4x_defconfig
+++ b/arch/arm/configs/lp8x4x_defconfig
@@ -62,6 +62,7 @@ CONFIG_PROC_DEVICETREE=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_LOOP_MIN_COUNT=2
 CONFIG_EEPROM_AT24=m
+CONFIG_LP8X4X_BUS=m
 CONFIG_SCSI=y
 # CONFIG_SCSI_PROC_FS is not set
 CONFIG_BLK_DEV_SD=y
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index a3e291d..e4d52da 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -515,6 +515,19 @@ config SRAM
 	  the genalloc API. It is supposed to be used for small on-chip SRAM
 	  areas found on many SoCs.
 
+config LP8X4X_BUS
+	tristate "ICP DAS LP-8x4x industrial IO bus"
+	depends on OF && ARCH_PXA
+	select SYSFS
+	---help---
+	  This is a driver for ICP DAS LP-8x4x programmable automation
+	  controller. It exposes a custom parallel bus. The bus services
+	  data acquisition and control modules.
+
+	  Say N, unless you plan to run this kernel on a LP-8x4x system.
+
+	  If you say M here, the module will be called lp8x4x_bus.
+
 source "drivers/misc/c2port/Kconfig"
 source "drivers/misc/eeprom/Kconfig"
 source "drivers/misc/cb710/Kconfig"
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index f45473e..7578cff 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -53,3 +53,4 @@ obj-$(CONFIG_VMWARE_VMCI)	+= vmw_vmci/
 obj-$(CONFIG_LATTICE_ECP3_CONFIG)	+= lattice-ecp3-config.o
 obj-$(CONFIG_SRAM)		+= sram.o
 obj-y				+= mic/
+obj-$(CONFIG_LP8X4X_BUS)	+= lp8x4x_bus.o
diff --git a/drivers/misc/lp8x4x_bus.c b/drivers/misc/lp8x4x_bus.c
new file mode 100644
index 0000000..7aa55cf
--- /dev/null
+++ b/drivers/misc/lp8x4x_bus.c
@@ -0,0 +1,167 @@
+/*
+ *  linux/misc/lp8x4x_bus.c
+ *
+ *  Support for ICP DAS LP-8x4x programmable automation controller bus
+ *  Copyright (C) 2013 Sergei Ianovich <ynvich@gmail.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation or any later version.
+ */
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#define MODULE_NAME	"lp8x4x-bus"
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Sergei Ianovich <ynvich@gmail.com>");
+MODULE_DESCRIPTION("ICP DAS LP-8x4x parallel bus driver");
+
+struct lp8x4x_master {
+	unsigned int		slot_count;
+	void			*count_addr;
+	struct device		dev;
+};
+
+static int lp8x4x_match(struct device *dev, struct device_driver *drv)
+{
+	return 1;
+}
+
+static struct bus_type lp8x4x_bus_type = {
+	.name		= "icpdas",
+	.match		= lp8x4x_match,
+};
+
+static void lp8x4x_master_release(struct device *dev)
+{
+	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
+	WARN_ON(!dev);
+
+	kfree(m);
+}
+
+static ssize_t slot_count_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
+
+	return sprintf(buf, "%u\n", m->slot_count);
+}
+
+static DEVICE_ATTR_RO(slot_count);
+
+static struct attribute *master_dev_attrs[] = {
+	&dev_attr_slot_count.attr,
+	NULL,
+};
+ATTRIBUTE_GROUPS(master_dev);
+
+
+static void devm_lp8x4x_bus_release(struct device *dev, void *res)
+{
+	struct lp8x4x_master *m = *(struct lp8x4x_master **)res;
+
+	dev_dbg(dev, "releasing devices\n");
+	device_unregister(&m->dev);
+	bus_unregister(&lp8x4x_bus_type);
+}
+
+static int __init lp8x4x_bus_probe(struct platform_device *pdev)
+{
+	struct lp8x4x_master *m, **p;
+	struct resource *res;
+	int err = 0;
+
+	m = kzalloc(sizeof(*m), GFP_KERNEL);
+	if (!m)
+		return -ENOMEM;
+
+	p = devres_alloc(devm_lp8x4x_bus_release, sizeof(*p), GFP_KERNEL);
+	if (!p) {
+		err = -ENOMEM;
+		goto err1;
+	}
+	*p = m;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "could not get slot count address\n");
+		err = -ENODEV;
+		goto err2;
+	}
+
+	m->count_addr = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(m->count_addr)) {
+		dev_err(&pdev->dev, "Failed to ioremap slot count address\n");
+		err = PTR_ERR(m->count_addr);
+		goto err2;
+	}
+
+	m->slot_count = ioread8(m->count_addr);
+	switch (m->slot_count) {
+	case 1:
+	case 4:
+		break;
+	case 7:
+		m->slot_count = 8;
+		break;
+	default:
+		dev_err(&pdev->dev, "unexpected slot number(%u)",
+				m->slot_count);
+		err = -ENODEV;
+		goto err2;
+	};
+
+	dev_info(&pdev->dev, "found bus with up to %u slots\n", m->slot_count);
+
+	err = bus_register(&lp8x4x_bus_type);
+	if (err < 0) {
+		dev_err(&pdev->dev, "failed to register bus type\n");
+		goto err2;
+	}
+
+	m->dev.bus = &lp8x4x_bus_type;
+	dev_set_name(&m->dev, "backplane");
+	m->dev.parent = &pdev->dev;
+	m->dev.release = lp8x4x_master_release;
+	m->dev.groups = master_dev_groups;
+
+	err = device_register(&m->dev);
+	if (err < 0) {
+		dev_err(&pdev->dev, "failed to register backplane device\n");
+		goto err3;
+	}
+
+	devres_add(&pdev->dev, p);
+	return 0;
+
+err3:
+	bus_unregister(&lp8x4x_bus_type);
+err2:
+	devres_free(p);
+err1:
+	kfree(m);
+	return err;
+}
+
+static const struct of_device_id lp8x4x_bus_dt_ids[] = {
+	{ .compatible = "icpdas,backplane-lp8x4x" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, lp8x4x_bus_dt_ids);
+
+static struct platform_driver lp8x4x_bus_driver = {
+	.driver		= {
+		.name	= MODULE_NAME,
+		.owner	= THIS_MODULE,
+		.of_match_table = lp8x4x_bus_dt_ids,
+	},
+};
+
+module_platform_driver_probe(lp8x4x_bus_driver, lp8x4x_bus_probe);
-- 
1.8.4.2


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

* [PATCH v3 13/21] misc: support for LP-8x4x custom parallel bus
@ 2013-12-17 19:37             ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-17 19:37 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Rob Landley, Russell King,
	Arnd Bergmann, Greg Kroah-Hartman, Grant Likely,
	open list:OPEN FIRMWARE AND...,
	open list:DOCUMENTATION

This patch implements probing for the bus and reporting the number
of available expansion slots.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
   v2..v3
   * fixed goto after bus_register
   * number change (11/16 -> 13/21)

   v0..v2
   * use device tree
   * use devm helpers where possible

 .../devicetree/bindings/misc/lp8x4x-bus.txt        |  16 ++
 Documentation/misc-devices/lp8x4x_bus.txt          |  30 ++++
 arch/arm/boot/dts/pxa27x-lp8x4x.dts                |   5 +
 arch/arm/configs/lp8x4x_defconfig                  |   1 +
 drivers/misc/Kconfig                               |  13 ++
 drivers/misc/Makefile                              |   1 +
 drivers/misc/lp8x4x_bus.c                          | 167 +++++++++++++++++++++
 7 files changed, 233 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
 create mode 100644 Documentation/misc-devices/lp8x4x_bus.txt
 create mode 100644 drivers/misc/lp8x4x_bus.c

diff --git a/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt b/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
new file mode 100644
index 0000000..1c87a29
--- /dev/null
+++ b/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
@@ -0,0 +1,16 @@
+Custom parallel bus on ICP DAS LP-8x4x industrial computers
+
+See Documentation/misc-devices/lp8x4x_bus.txt for details.
+
+Required properties:
+- compatible : should be "icpdas,backplane-lp8x4x"
+
+- reg: physical base address of the slot count register and the length
+       of the memory mapped region.
+
+Example:
+
+	backplane {
+		compatible = "icpdas,backplane-lp8x4x";
+		reg = <0x17009046 0x2>;
+	};
diff --git a/Documentation/misc-devices/lp8x4x_bus.txt b/Documentation/misc-devices/lp8x4x_bus.txt
new file mode 100644
index 0000000..f5392b3
--- /dev/null
+++ b/Documentation/misc-devices/lp8x4x_bus.txt
@@ -0,0 +1,30 @@
+Kernel driver lpx8x4x_bus
+======================
+
+Supported hardare:
+Custom parallel bus on ICP DAS LP-8x4x industrial computers
+
+Data sheet:
+Not freely available
+
+Author:
+Sergei Ianovich <ynvich@gmail.com>
+
+Description
+-----------
+
+http://www.icpdas.com/root/product/solutions/pac/linpac/lp-8x4x_hardware.html
+
+LP-8x4x is an ARM-based industrial computer with a custom parallel bus to
+connect expansion modules with digital input/output, analog input/output,
+serial, CAN and other types of ports.
+
+The bus is implemented by a FPGA.
+
+SYSFS
+-----
+
+/sys/bus/icpdas/devices/backplane:
+
+slot_count
+	RO - shows total number of expansion slots on the device
diff --git a/arch/arm/boot/dts/pxa27x-lp8x4x.dts b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
index ee0d8b7..4ea566c 100644
--- a/arch/arm/boot/dts/pxa27x-lp8x4x.dts
+++ b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
@@ -202,6 +202,11 @@
 				interrupts = <15>;
 				status = "okay";
 			};
+
+			backplane {
+				compatible = "icpdas,backplane-lp8x4x";
+				reg = <0x9046 0x2>;
+			};
 		};
 	};
 };
diff --git a/arch/arm/configs/lp8x4x_defconfig b/arch/arm/configs/lp8x4x_defconfig
index 9116ce1..c34eb2a 100644
--- a/arch/arm/configs/lp8x4x_defconfig
+++ b/arch/arm/configs/lp8x4x_defconfig
@@ -62,6 +62,7 @@ CONFIG_PROC_DEVICETREE=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_LOOP_MIN_COUNT=2
 CONFIG_EEPROM_AT24=m
+CONFIG_LP8X4X_BUS=m
 CONFIG_SCSI=y
 # CONFIG_SCSI_PROC_FS is not set
 CONFIG_BLK_DEV_SD=y
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index a3e291d..e4d52da 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -515,6 +515,19 @@ config SRAM
 	  the genalloc API. It is supposed to be used for small on-chip SRAM
 	  areas found on many SoCs.
 
+config LP8X4X_BUS
+	tristate "ICP DAS LP-8x4x industrial IO bus"
+	depends on OF && ARCH_PXA
+	select SYSFS
+	---help---
+	  This is a driver for ICP DAS LP-8x4x programmable automation
+	  controller. It exposes a custom parallel bus. The bus services
+	  data acquisition and control modules.
+
+	  Say N, unless you plan to run this kernel on a LP-8x4x system.
+
+	  If you say M here, the module will be called lp8x4x_bus.
+
 source "drivers/misc/c2port/Kconfig"
 source "drivers/misc/eeprom/Kconfig"
 source "drivers/misc/cb710/Kconfig"
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index f45473e..7578cff 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -53,3 +53,4 @@ obj-$(CONFIG_VMWARE_VMCI)	+= vmw_vmci/
 obj-$(CONFIG_LATTICE_ECP3_CONFIG)	+= lattice-ecp3-config.o
 obj-$(CONFIG_SRAM)		+= sram.o
 obj-y				+= mic/
+obj-$(CONFIG_LP8X4X_BUS)	+= lp8x4x_bus.o
diff --git a/drivers/misc/lp8x4x_bus.c b/drivers/misc/lp8x4x_bus.c
new file mode 100644
index 0000000..7aa55cf
--- /dev/null
+++ b/drivers/misc/lp8x4x_bus.c
@@ -0,0 +1,167 @@
+/*
+ *  linux/misc/lp8x4x_bus.c
+ *
+ *  Support for ICP DAS LP-8x4x programmable automation controller bus
+ *  Copyright (C) 2013 Sergei Ianovich <ynvich@gmail.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation or any later version.
+ */
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#define MODULE_NAME	"lp8x4x-bus"
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Sergei Ianovich <ynvich@gmail.com>");
+MODULE_DESCRIPTION("ICP DAS LP-8x4x parallel bus driver");
+
+struct lp8x4x_master {
+	unsigned int		slot_count;
+	void			*count_addr;
+	struct device		dev;
+};
+
+static int lp8x4x_match(struct device *dev, struct device_driver *drv)
+{
+	return 1;
+}
+
+static struct bus_type lp8x4x_bus_type = {
+	.name		= "icpdas",
+	.match		= lp8x4x_match,
+};
+
+static void lp8x4x_master_release(struct device *dev)
+{
+	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
+	WARN_ON(!dev);
+
+	kfree(m);
+}
+
+static ssize_t slot_count_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
+
+	return sprintf(buf, "%u\n", m->slot_count);
+}
+
+static DEVICE_ATTR_RO(slot_count);
+
+static struct attribute *master_dev_attrs[] = {
+	&dev_attr_slot_count.attr,
+	NULL,
+};
+ATTRIBUTE_GROUPS(master_dev);
+
+
+static void devm_lp8x4x_bus_release(struct device *dev, void *res)
+{
+	struct lp8x4x_master *m = *(struct lp8x4x_master **)res;
+
+	dev_dbg(dev, "releasing devices\n");
+	device_unregister(&m->dev);
+	bus_unregister(&lp8x4x_bus_type);
+}
+
+static int __init lp8x4x_bus_probe(struct platform_device *pdev)
+{
+	struct lp8x4x_master *m, **p;
+	struct resource *res;
+	int err = 0;
+
+	m = kzalloc(sizeof(*m), GFP_KERNEL);
+	if (!m)
+		return -ENOMEM;
+
+	p = devres_alloc(devm_lp8x4x_bus_release, sizeof(*p), GFP_KERNEL);
+	if (!p) {
+		err = -ENOMEM;
+		goto err1;
+	}
+	*p = m;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "could not get slot count address\n");
+		err = -ENODEV;
+		goto err2;
+	}
+
+	m->count_addr = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(m->count_addr)) {
+		dev_err(&pdev->dev, "Failed to ioremap slot count address\n");
+		err = PTR_ERR(m->count_addr);
+		goto err2;
+	}
+
+	m->slot_count = ioread8(m->count_addr);
+	switch (m->slot_count) {
+	case 1:
+	case 4:
+		break;
+	case 7:
+		m->slot_count = 8;
+		break;
+	default:
+		dev_err(&pdev->dev, "unexpected slot number(%u)",
+				m->slot_count);
+		err = -ENODEV;
+		goto err2;
+	};
+
+	dev_info(&pdev->dev, "found bus with up to %u slots\n", m->slot_count);
+
+	err = bus_register(&lp8x4x_bus_type);
+	if (err < 0) {
+		dev_err(&pdev->dev, "failed to register bus type\n");
+		goto err2;
+	}
+
+	m->dev.bus = &lp8x4x_bus_type;
+	dev_set_name(&m->dev, "backplane");
+	m->dev.parent = &pdev->dev;
+	m->dev.release = lp8x4x_master_release;
+	m->dev.groups = master_dev_groups;
+
+	err = device_register(&m->dev);
+	if (err < 0) {
+		dev_err(&pdev->dev, "failed to register backplane device\n");
+		goto err3;
+	}
+
+	devres_add(&pdev->dev, p);
+	return 0;
+
+err3:
+	bus_unregister(&lp8x4x_bus_type);
+err2:
+	devres_free(p);
+err1:
+	kfree(m);
+	return err;
+}
+
+static const struct of_device_id lp8x4x_bus_dt_ids[] = {
+	{ .compatible = "icpdas,backplane-lp8x4x" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, lp8x4x_bus_dt_ids);
+
+static struct platform_driver lp8x4x_bus_driver = {
+	.driver		= {
+		.name	= MODULE_NAME,
+		.owner	= THIS_MODULE,
+		.of_match_table = lp8x4x_bus_dt_ids,
+	},
+};
+
+module_platform_driver_probe(lp8x4x_bus_driver, lp8x4x_bus_probe);
-- 
1.8.4.2


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

* [PATCH v3 13/21] misc: support for LP-8x4x custom parallel bus
@ 2013-12-17 19:37             ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-17 19:37 UTC (permalink / raw)
  To: linux-arm-kernel

This patch implements probing for the bus and reporting the number
of available expansion slots.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
   v2..v3
   * fixed goto after bus_register
   * number change (11/16 -> 13/21)

   v0..v2
   * use device tree
   * use devm helpers where possible

 .../devicetree/bindings/misc/lp8x4x-bus.txt        |  16 ++
 Documentation/misc-devices/lp8x4x_bus.txt          |  30 ++++
 arch/arm/boot/dts/pxa27x-lp8x4x.dts                |   5 +
 arch/arm/configs/lp8x4x_defconfig                  |   1 +
 drivers/misc/Kconfig                               |  13 ++
 drivers/misc/Makefile                              |   1 +
 drivers/misc/lp8x4x_bus.c                          | 167 +++++++++++++++++++++
 7 files changed, 233 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
 create mode 100644 Documentation/misc-devices/lp8x4x_bus.txt
 create mode 100644 drivers/misc/lp8x4x_bus.c

diff --git a/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt b/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
new file mode 100644
index 0000000..1c87a29
--- /dev/null
+++ b/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
@@ -0,0 +1,16 @@
+Custom parallel bus on ICP DAS LP-8x4x industrial computers
+
+See Documentation/misc-devices/lp8x4x_bus.txt for details.
+
+Required properties:
+- compatible : should be "icpdas,backplane-lp8x4x"
+
+- reg: physical base address of the slot count register and the length
+       of the memory mapped region.
+
+Example:
+
+	backplane {
+		compatible = "icpdas,backplane-lp8x4x";
+		reg = <0x17009046 0x2>;
+	};
diff --git a/Documentation/misc-devices/lp8x4x_bus.txt b/Documentation/misc-devices/lp8x4x_bus.txt
new file mode 100644
index 0000000..f5392b3
--- /dev/null
+++ b/Documentation/misc-devices/lp8x4x_bus.txt
@@ -0,0 +1,30 @@
+Kernel driver lpx8x4x_bus
+======================
+
+Supported hardare:
+Custom parallel bus on ICP DAS LP-8x4x industrial computers
+
+Data sheet:
+Not freely available
+
+Author:
+Sergei Ianovich <ynvich@gmail.com>
+
+Description
+-----------
+
+http://www.icpdas.com/root/product/solutions/pac/linpac/lp-8x4x_hardware.html
+
+LP-8x4x is an ARM-based industrial computer with a custom parallel bus to
+connect expansion modules with digital input/output, analog input/output,
+serial, CAN and other types of ports.
+
+The bus is implemented by a FPGA.
+
+SYSFS
+-----
+
+/sys/bus/icpdas/devices/backplane:
+
+slot_count
+	RO - shows total number of expansion slots on the device
diff --git a/arch/arm/boot/dts/pxa27x-lp8x4x.dts b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
index ee0d8b7..4ea566c 100644
--- a/arch/arm/boot/dts/pxa27x-lp8x4x.dts
+++ b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
@@ -202,6 +202,11 @@
 				interrupts = <15>;
 				status = "okay";
 			};
+
+			backplane {
+				compatible = "icpdas,backplane-lp8x4x";
+				reg = <0x9046 0x2>;
+			};
 		};
 	};
 };
diff --git a/arch/arm/configs/lp8x4x_defconfig b/arch/arm/configs/lp8x4x_defconfig
index 9116ce1..c34eb2a 100644
--- a/arch/arm/configs/lp8x4x_defconfig
+++ b/arch/arm/configs/lp8x4x_defconfig
@@ -62,6 +62,7 @@ CONFIG_PROC_DEVICETREE=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_LOOP_MIN_COUNT=2
 CONFIG_EEPROM_AT24=m
+CONFIG_LP8X4X_BUS=m
 CONFIG_SCSI=y
 # CONFIG_SCSI_PROC_FS is not set
 CONFIG_BLK_DEV_SD=y
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index a3e291d..e4d52da 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -515,6 +515,19 @@ config SRAM
 	  the genalloc API. It is supposed to be used for small on-chip SRAM
 	  areas found on many SoCs.
 
+config LP8X4X_BUS
+	tristate "ICP DAS LP-8x4x industrial IO bus"
+	depends on OF && ARCH_PXA
+	select SYSFS
+	---help---
+	  This is a driver for ICP DAS LP-8x4x programmable automation
+	  controller. It exposes a custom parallel bus. The bus services
+	  data acquisition and control modules.
+
+	  Say N, unless you plan to run this kernel on a LP-8x4x system.
+
+	  If you say M here, the module will be called lp8x4x_bus.
+
 source "drivers/misc/c2port/Kconfig"
 source "drivers/misc/eeprom/Kconfig"
 source "drivers/misc/cb710/Kconfig"
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index f45473e..7578cff 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -53,3 +53,4 @@ obj-$(CONFIG_VMWARE_VMCI)	+= vmw_vmci/
 obj-$(CONFIG_LATTICE_ECP3_CONFIG)	+= lattice-ecp3-config.o
 obj-$(CONFIG_SRAM)		+= sram.o
 obj-y				+= mic/
+obj-$(CONFIG_LP8X4X_BUS)	+= lp8x4x_bus.o
diff --git a/drivers/misc/lp8x4x_bus.c b/drivers/misc/lp8x4x_bus.c
new file mode 100644
index 0000000..7aa55cf
--- /dev/null
+++ b/drivers/misc/lp8x4x_bus.c
@@ -0,0 +1,167 @@
+/*
+ *  linux/misc/lp8x4x_bus.c
+ *
+ *  Support for ICP DAS LP-8x4x programmable automation controller bus
+ *  Copyright (C) 2013 Sergei Ianovich <ynvich@gmail.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation or any later version.
+ */
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#define MODULE_NAME	"lp8x4x-bus"
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Sergei Ianovich <ynvich@gmail.com>");
+MODULE_DESCRIPTION("ICP DAS LP-8x4x parallel bus driver");
+
+struct lp8x4x_master {
+	unsigned int		slot_count;
+	void			*count_addr;
+	struct device		dev;
+};
+
+static int lp8x4x_match(struct device *dev, struct device_driver *drv)
+{
+	return 1;
+}
+
+static struct bus_type lp8x4x_bus_type = {
+	.name		= "icpdas",
+	.match		= lp8x4x_match,
+};
+
+static void lp8x4x_master_release(struct device *dev)
+{
+	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
+	WARN_ON(!dev);
+
+	kfree(m);
+}
+
+static ssize_t slot_count_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
+
+	return sprintf(buf, "%u\n", m->slot_count);
+}
+
+static DEVICE_ATTR_RO(slot_count);
+
+static struct attribute *master_dev_attrs[] = {
+	&dev_attr_slot_count.attr,
+	NULL,
+};
+ATTRIBUTE_GROUPS(master_dev);
+
+
+static void devm_lp8x4x_bus_release(struct device *dev, void *res)
+{
+	struct lp8x4x_master *m = *(struct lp8x4x_master **)res;
+
+	dev_dbg(dev, "releasing devices\n");
+	device_unregister(&m->dev);
+	bus_unregister(&lp8x4x_bus_type);
+}
+
+static int __init lp8x4x_bus_probe(struct platform_device *pdev)
+{
+	struct lp8x4x_master *m, **p;
+	struct resource *res;
+	int err = 0;
+
+	m = kzalloc(sizeof(*m), GFP_KERNEL);
+	if (!m)
+		return -ENOMEM;
+
+	p = devres_alloc(devm_lp8x4x_bus_release, sizeof(*p), GFP_KERNEL);
+	if (!p) {
+		err = -ENOMEM;
+		goto err1;
+	}
+	*p = m;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "could not get slot count address\n");
+		err = -ENODEV;
+		goto err2;
+	}
+
+	m->count_addr = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(m->count_addr)) {
+		dev_err(&pdev->dev, "Failed to ioremap slot count address\n");
+		err = PTR_ERR(m->count_addr);
+		goto err2;
+	}
+
+	m->slot_count = ioread8(m->count_addr);
+	switch (m->slot_count) {
+	case 1:
+	case 4:
+		break;
+	case 7:
+		m->slot_count = 8;
+		break;
+	default:
+		dev_err(&pdev->dev, "unexpected slot number(%u)",
+				m->slot_count);
+		err = -ENODEV;
+		goto err2;
+	};
+
+	dev_info(&pdev->dev, "found bus with up to %u slots\n", m->slot_count);
+
+	err = bus_register(&lp8x4x_bus_type);
+	if (err < 0) {
+		dev_err(&pdev->dev, "failed to register bus type\n");
+		goto err2;
+	}
+
+	m->dev.bus = &lp8x4x_bus_type;
+	dev_set_name(&m->dev, "backplane");
+	m->dev.parent = &pdev->dev;
+	m->dev.release = lp8x4x_master_release;
+	m->dev.groups = master_dev_groups;
+
+	err = device_register(&m->dev);
+	if (err < 0) {
+		dev_err(&pdev->dev, "failed to register backplane device\n");
+		goto err3;
+	}
+
+	devres_add(&pdev->dev, p);
+	return 0;
+
+err3:
+	bus_unregister(&lp8x4x_bus_type);
+err2:
+	devres_free(p);
+err1:
+	kfree(m);
+	return err;
+}
+
+static const struct of_device_id lp8x4x_bus_dt_ids[] = {
+	{ .compatible = "icpdas,backplane-lp8x4x" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, lp8x4x_bus_dt_ids);
+
+static struct platform_driver lp8x4x_bus_driver = {
+	.driver		= {
+		.name	= MODULE_NAME,
+		.owner	= THIS_MODULE,
+		.of_match_table = lp8x4x_bus_dt_ids,
+	},
+};
+
+module_platform_driver_probe(lp8x4x_bus_driver, lp8x4x_bus_probe);
-- 
1.8.4.2

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

* [PATCH v3 14/21] misc: support for LP-8x4x rotary switch
  2013-12-17 19:37           ` Sergei Ianovich
  (?)
@ 2013-12-17 19:37             ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-17 19:37 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Rob Landley, Russell King,
	Arnd Bergmann, Greg Kroah-Hartman, open list:OPEN FIRMWARE AND...,
	open list:DOCUMENTATION

Reorder backplane resources by start address.

Reorder backplane attributes alphabetically.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
   v2..v3
   * new patch

 .../devicetree/bindings/misc/lp8x4x-bus.txt        |  8 ++--
 Documentation/misc-devices/lp8x4x_bus.txt          |  3 ++
 arch/arm/boot/dts/pxa27x-lp8x4x.dts                |  3 +-
 drivers/misc/lp8x4x_bus.c                          | 43 ++++++++++++++++++----
 4 files changed, 45 insertions(+), 12 deletions(-)

diff --git a/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt b/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
index 1c87a29..8a55020 100644
--- a/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
+++ b/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
@@ -5,12 +5,14 @@ See Documentation/misc-devices/lp8x4x_bus.txt for details.
 Required properties:
 - compatible : should be "icpdas,backplane-lp8x4x"
 
-- reg: physical base address of the slot count register and the length
-       of the memory mapped region.
+- reg: physical base addresses and region lengths of
+       * the rotary switch
+       * the slot count register
 
 Example:
 
 	backplane {
 		compatible = "icpdas,backplane-lp8x4x";
-		reg = <0x17009046 0x2>;
+		reg = <0x0 0x2
+		       0x9046 0x2>;
 	};
diff --git a/Documentation/misc-devices/lp8x4x_bus.txt b/Documentation/misc-devices/lp8x4x_bus.txt
index f5392b3..bea435b 100644
--- a/Documentation/misc-devices/lp8x4x_bus.txt
+++ b/Documentation/misc-devices/lp8x4x_bus.txt
@@ -26,5 +26,8 @@ SYSFS
 
 /sys/bus/icpdas/devices/backplane:
 
+rotary
+	RO - shows position of LP-8x4x rotary switch (0-9)
+
 slot_count
 	RO - shows total number of expansion slots on the device
diff --git a/arch/arm/boot/dts/pxa27x-lp8x4x.dts b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
index 4ea566c..b50ce43 100644
--- a/arch/arm/boot/dts/pxa27x-lp8x4x.dts
+++ b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
@@ -205,7 +205,8 @@
 
 			backplane {
 				compatible = "icpdas,backplane-lp8x4x";
-				reg = <0x9046 0x2>;
+				reg = <0x0 0x2
+				       0x9046 0x2>;
 			};
 		};
 	};
diff --git a/drivers/misc/lp8x4x_bus.c b/drivers/misc/lp8x4x_bus.c
index 7aa55cf..18ca8f8 100644
--- a/drivers/misc/lp8x4x_bus.c
+++ b/drivers/misc/lp8x4x_bus.c
@@ -25,6 +25,7 @@ MODULE_DESCRIPTION("ICP DAS LP-8x4x parallel bus driver");
 struct lp8x4x_master {
 	unsigned int		slot_count;
 	void			*count_addr;
+	void			*rotary_addr;
 	struct device		dev;
 };
 
@@ -56,8 +57,19 @@ static ssize_t slot_count_show(struct device *dev,
 
 static DEVICE_ATTR_RO(slot_count);
 
+static ssize_t rotary_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
+
+	return sprintf(buf, "%u\n", (ioread8(m->rotary_addr) ^ 0xf) & 0xf);
+}
+
+static DEVICE_ATTR_RO(rotary);
+
 static struct attribute *master_dev_attrs[] = {
 	&dev_attr_slot_count.attr,
+	&dev_attr_rotary.attr,
 	NULL,
 };
 ATTRIBUTE_GROUPS(master_dev);
@@ -76,6 +88,7 @@ static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 {
 	struct lp8x4x_master *m, **p;
 	struct resource *res;
+	int r = 0;
 	int err = 0;
 
 	m = kzalloc(sizeof(*m), GFP_KERNEL);
@@ -89,18 +102,32 @@ static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 	}
 	*p = m;
 
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	res = platform_get_resource(pdev, IORESOURCE_MEM, r++);
+	if (!res) {
+		dev_err(&pdev->dev, "Failed to get rotary address\n");
+		err = -ENODEV;
+		goto err_free;
+	}
+
+	m->rotary_addr = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(m->rotary_addr)) {
+		dev_err(&pdev->dev, "Failed to ioremap rotary address\n");
+		err = PTR_ERR(m->rotary_addr);
+		goto err_free;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, r++);
 	if (!res) {
 		dev_err(&pdev->dev, "could not get slot count address\n");
 		err = -ENODEV;
-		goto err2;
+		goto err_free;
 	}
 
 	m->count_addr = devm_ioremap_resource(&pdev->dev, res);
 	if (IS_ERR(m->count_addr)) {
 		dev_err(&pdev->dev, "Failed to ioremap slot count address\n");
 		err = PTR_ERR(m->count_addr);
-		goto err2;
+		goto err_free;
 	}
 
 	m->slot_count = ioread8(m->count_addr);
@@ -115,7 +142,7 @@ static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 		dev_err(&pdev->dev, "unexpected slot number(%u)",
 				m->slot_count);
 		err = -ENODEV;
-		goto err2;
+		goto err_free;
 	};
 
 	dev_info(&pdev->dev, "found bus with up to %u slots\n", m->slot_count);
@@ -123,7 +150,7 @@ static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 	err = bus_register(&lp8x4x_bus_type);
 	if (err < 0) {
 		dev_err(&pdev->dev, "failed to register bus type\n");
-		goto err2;
+		goto err_free;
 	}
 
 	m->dev.bus = &lp8x4x_bus_type;
@@ -135,15 +162,15 @@ static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 	err = device_register(&m->dev);
 	if (err < 0) {
 		dev_err(&pdev->dev, "failed to register backplane device\n");
-		goto err3;
+		goto err_bus;
 	}
 
 	devres_add(&pdev->dev, p);
 	return 0;
 
-err3:
+err_bus:
 	bus_unregister(&lp8x4x_bus_type);
-err2:
+err_free:
 	devres_free(p);
 err1:
 	kfree(m);
-- 
1.8.4.2


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

* [PATCH v3 14/21] misc: support for LP-8x4x rotary switch
@ 2013-12-17 19:37             ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-17 19:37 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Rob Landley, Russell King,
	Arnd Bergmann, Greg Kroah-Hartman, open list:OPEN FIRMWARE AND...,
	open list:DOCUMENTATION

Reorder backplane resources by start address.

Reorder backplane attributes alphabetically.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
   v2..v3
   * new patch

 .../devicetree/bindings/misc/lp8x4x-bus.txt        |  8 ++--
 Documentation/misc-devices/lp8x4x_bus.txt          |  3 ++
 arch/arm/boot/dts/pxa27x-lp8x4x.dts                |  3 +-
 drivers/misc/lp8x4x_bus.c                          | 43 ++++++++++++++++++----
 4 files changed, 45 insertions(+), 12 deletions(-)

diff --git a/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt b/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
index 1c87a29..8a55020 100644
--- a/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
+++ b/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
@@ -5,12 +5,14 @@ See Documentation/misc-devices/lp8x4x_bus.txt for details.
 Required properties:
 - compatible : should be "icpdas,backplane-lp8x4x"
 
-- reg: physical base address of the slot count register and the length
-       of the memory mapped region.
+- reg: physical base addresses and region lengths of
+       * the rotary switch
+       * the slot count register
 
 Example:
 
 	backplane {
 		compatible = "icpdas,backplane-lp8x4x";
-		reg = <0x17009046 0x2>;
+		reg = <0x0 0x2
+		       0x9046 0x2>;
 	};
diff --git a/Documentation/misc-devices/lp8x4x_bus.txt b/Documentation/misc-devices/lp8x4x_bus.txt
index f5392b3..bea435b 100644
--- a/Documentation/misc-devices/lp8x4x_bus.txt
+++ b/Documentation/misc-devices/lp8x4x_bus.txt
@@ -26,5 +26,8 @@ SYSFS
 
 /sys/bus/icpdas/devices/backplane:
 
+rotary
+	RO - shows position of LP-8x4x rotary switch (0-9)
+
 slot_count
 	RO - shows total number of expansion slots on the device
diff --git a/arch/arm/boot/dts/pxa27x-lp8x4x.dts b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
index 4ea566c..b50ce43 100644
--- a/arch/arm/boot/dts/pxa27x-lp8x4x.dts
+++ b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
@@ -205,7 +205,8 @@
 
 			backplane {
 				compatible = "icpdas,backplane-lp8x4x";
-				reg = <0x9046 0x2>;
+				reg = <0x0 0x2
+				       0x9046 0x2>;
 			};
 		};
 	};
diff --git a/drivers/misc/lp8x4x_bus.c b/drivers/misc/lp8x4x_bus.c
index 7aa55cf..18ca8f8 100644
--- a/drivers/misc/lp8x4x_bus.c
+++ b/drivers/misc/lp8x4x_bus.c
@@ -25,6 +25,7 @@ MODULE_DESCRIPTION("ICP DAS LP-8x4x parallel bus driver");
 struct lp8x4x_master {
 	unsigned int		slot_count;
 	void			*count_addr;
+	void			*rotary_addr;
 	struct device		dev;
 };
 
@@ -56,8 +57,19 @@ static ssize_t slot_count_show(struct device *dev,
 
 static DEVICE_ATTR_RO(slot_count);
 
+static ssize_t rotary_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
+
+	return sprintf(buf, "%u\n", (ioread8(m->rotary_addr) ^ 0xf) & 0xf);
+}
+
+static DEVICE_ATTR_RO(rotary);
+
 static struct attribute *master_dev_attrs[] = {
 	&dev_attr_slot_count.attr,
+	&dev_attr_rotary.attr,
 	NULL,
 };
 ATTRIBUTE_GROUPS(master_dev);
@@ -76,6 +88,7 @@ static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 {
 	struct lp8x4x_master *m, **p;
 	struct resource *res;
+	int r = 0;
 	int err = 0;
 
 	m = kzalloc(sizeof(*m), GFP_KERNEL);
@@ -89,18 +102,32 @@ static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 	}
 	*p = m;
 
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	res = platform_get_resource(pdev, IORESOURCE_MEM, r++);
+	if (!res) {
+		dev_err(&pdev->dev, "Failed to get rotary address\n");
+		err = -ENODEV;
+		goto err_free;
+	}
+
+	m->rotary_addr = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(m->rotary_addr)) {
+		dev_err(&pdev->dev, "Failed to ioremap rotary address\n");
+		err = PTR_ERR(m->rotary_addr);
+		goto err_free;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, r++);
 	if (!res) {
 		dev_err(&pdev->dev, "could not get slot count address\n");
 		err = -ENODEV;
-		goto err2;
+		goto err_free;
 	}
 
 	m->count_addr = devm_ioremap_resource(&pdev->dev, res);
 	if (IS_ERR(m->count_addr)) {
 		dev_err(&pdev->dev, "Failed to ioremap slot count address\n");
 		err = PTR_ERR(m->count_addr);
-		goto err2;
+		goto err_free;
 	}
 
 	m->slot_count = ioread8(m->count_addr);
@@ -115,7 +142,7 @@ static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 		dev_err(&pdev->dev, "unexpected slot number(%u)",
 				m->slot_count);
 		err = -ENODEV;
-		goto err2;
+		goto err_free;
 	};
 
 	dev_info(&pdev->dev, "found bus with up to %u slots\n", m->slot_count);
@@ -123,7 +150,7 @@ static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 	err = bus_register(&lp8x4x_bus_type);
 	if (err < 0) {
 		dev_err(&pdev->dev, "failed to register bus type\n");
-		goto err2;
+		goto err_free;
 	}
 
 	m->dev.bus = &lp8x4x_bus_type;
@@ -135,15 +162,15 @@ static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 	err = device_register(&m->dev);
 	if (err < 0) {
 		dev_err(&pdev->dev, "failed to register backplane device\n");
-		goto err3;
+		goto err_bus;
 	}
 
 	devres_add(&pdev->dev, p);
 	return 0;
 
-err3:
+err_bus:
 	bus_unregister(&lp8x4x_bus_type);
-err2:
+err_free:
 	devres_free(p);
 err1:
 	kfree(m);
-- 
1.8.4.2

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

* [PATCH v3 14/21] misc: support for LP-8x4x rotary switch
@ 2013-12-17 19:37             ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-17 19:37 UTC (permalink / raw)
  To: linux-arm-kernel

Reorder backplane resources by start address.

Reorder backplane attributes alphabetically.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
   v2..v3
   * new patch

 .../devicetree/bindings/misc/lp8x4x-bus.txt        |  8 ++--
 Documentation/misc-devices/lp8x4x_bus.txt          |  3 ++
 arch/arm/boot/dts/pxa27x-lp8x4x.dts                |  3 +-
 drivers/misc/lp8x4x_bus.c                          | 43 ++++++++++++++++++----
 4 files changed, 45 insertions(+), 12 deletions(-)

diff --git a/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt b/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
index 1c87a29..8a55020 100644
--- a/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
+++ b/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
@@ -5,12 +5,14 @@ See Documentation/misc-devices/lp8x4x_bus.txt for details.
 Required properties:
 - compatible : should be "icpdas,backplane-lp8x4x"
 
-- reg: physical base address of the slot count register and the length
-       of the memory mapped region.
+- reg: physical base addresses and region lengths of
+       * the rotary switch
+       * the slot count register
 
 Example:
 
 	backplane {
 		compatible = "icpdas,backplane-lp8x4x";
-		reg = <0x17009046 0x2>;
+		reg = <0x0 0x2
+		       0x9046 0x2>;
 	};
diff --git a/Documentation/misc-devices/lp8x4x_bus.txt b/Documentation/misc-devices/lp8x4x_bus.txt
index f5392b3..bea435b 100644
--- a/Documentation/misc-devices/lp8x4x_bus.txt
+++ b/Documentation/misc-devices/lp8x4x_bus.txt
@@ -26,5 +26,8 @@ SYSFS
 
 /sys/bus/icpdas/devices/backplane:
 
+rotary
+	RO - shows position of LP-8x4x rotary switch (0-9)
+
 slot_count
 	RO - shows total number of expansion slots on the device
diff --git a/arch/arm/boot/dts/pxa27x-lp8x4x.dts b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
index 4ea566c..b50ce43 100644
--- a/arch/arm/boot/dts/pxa27x-lp8x4x.dts
+++ b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
@@ -205,7 +205,8 @@
 
 			backplane {
 				compatible = "icpdas,backplane-lp8x4x";
-				reg = <0x9046 0x2>;
+				reg = <0x0 0x2
+				       0x9046 0x2>;
 			};
 		};
 	};
diff --git a/drivers/misc/lp8x4x_bus.c b/drivers/misc/lp8x4x_bus.c
index 7aa55cf..18ca8f8 100644
--- a/drivers/misc/lp8x4x_bus.c
+++ b/drivers/misc/lp8x4x_bus.c
@@ -25,6 +25,7 @@ MODULE_DESCRIPTION("ICP DAS LP-8x4x parallel bus driver");
 struct lp8x4x_master {
 	unsigned int		slot_count;
 	void			*count_addr;
+	void			*rotary_addr;
 	struct device		dev;
 };
 
@@ -56,8 +57,19 @@ static ssize_t slot_count_show(struct device *dev,
 
 static DEVICE_ATTR_RO(slot_count);
 
+static ssize_t rotary_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
+
+	return sprintf(buf, "%u\n", (ioread8(m->rotary_addr) ^ 0xf) & 0xf);
+}
+
+static DEVICE_ATTR_RO(rotary);
+
 static struct attribute *master_dev_attrs[] = {
 	&dev_attr_slot_count.attr,
+	&dev_attr_rotary.attr,
 	NULL,
 };
 ATTRIBUTE_GROUPS(master_dev);
@@ -76,6 +88,7 @@ static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 {
 	struct lp8x4x_master *m, **p;
 	struct resource *res;
+	int r = 0;
 	int err = 0;
 
 	m = kzalloc(sizeof(*m), GFP_KERNEL);
@@ -89,18 +102,32 @@ static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 	}
 	*p = m;
 
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	res = platform_get_resource(pdev, IORESOURCE_MEM, r++);
+	if (!res) {
+		dev_err(&pdev->dev, "Failed to get rotary address\n");
+		err = -ENODEV;
+		goto err_free;
+	}
+
+	m->rotary_addr = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(m->rotary_addr)) {
+		dev_err(&pdev->dev, "Failed to ioremap rotary address\n");
+		err = PTR_ERR(m->rotary_addr);
+		goto err_free;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, r++);
 	if (!res) {
 		dev_err(&pdev->dev, "could not get slot count address\n");
 		err = -ENODEV;
-		goto err2;
+		goto err_free;
 	}
 
 	m->count_addr = devm_ioremap_resource(&pdev->dev, res);
 	if (IS_ERR(m->count_addr)) {
 		dev_err(&pdev->dev, "Failed to ioremap slot count address\n");
 		err = PTR_ERR(m->count_addr);
-		goto err2;
+		goto err_free;
 	}
 
 	m->slot_count = ioread8(m->count_addr);
@@ -115,7 +142,7 @@ static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 		dev_err(&pdev->dev, "unexpected slot number(%u)",
 				m->slot_count);
 		err = -ENODEV;
-		goto err2;
+		goto err_free;
 	};
 
 	dev_info(&pdev->dev, "found bus with up to %u slots\n", m->slot_count);
@@ -123,7 +150,7 @@ static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 	err = bus_register(&lp8x4x_bus_type);
 	if (err < 0) {
 		dev_err(&pdev->dev, "failed to register bus type\n");
-		goto err2;
+		goto err_free;
 	}
 
 	m->dev.bus = &lp8x4x_bus_type;
@@ -135,15 +162,15 @@ static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 	err = device_register(&m->dev);
 	if (err < 0) {
 		dev_err(&pdev->dev, "failed to register backplane device\n");
-		goto err3;
+		goto err_bus;
 	}
 
 	devres_add(&pdev->dev, p);
 	return 0;
 
-err3:
+err_bus:
 	bus_unregister(&lp8x4x_bus_type);
-err2:
+err_free:
 	devres_free(p);
 err1:
 	kfree(m);
-- 
1.8.4.2

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

* [PATCH v3 15/21] misc: support for LP-8x4x DIP switch
  2013-12-17 19:37           ` Sergei Ianovich
  (?)
@ 2013-12-17 19:37             ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-17 19:37 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Rob Landley, Russell King,
	Arnd Bergmann, Greg Kroah-Hartman, open list:OPEN FIRMWARE AND...,
	open list:DOCUMENTATION

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
   v2..v3
   * new patch

 .../devicetree/bindings/misc/lp8x4x-bus.txt        |  2 ++
 Documentation/misc-devices/lp8x4x_bus.txt          |  3 +++
 arch/arm/boot/dts/pxa27x-lp8x4x.dts                |  1 +
 drivers/misc/lp8x4x_bus.c                          | 26 ++++++++++++++++++++++
 4 files changed, 32 insertions(+)

diff --git a/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt b/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
index 8a55020..1b1776a 100644
--- a/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
+++ b/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
@@ -7,6 +7,7 @@ Required properties:
 
 - reg: physical base addresses and region lengths of
        * the rotary switch
+       * the 8bit DIP switch
        * the slot count register
 
 Example:
@@ -14,5 +15,6 @@ Example:
 	backplane {
 		compatible = "icpdas,backplane-lp8x4x";
 		reg = <0x0 0x2
+		       0x9002 0x2
 		       0x9046 0x2>;
 	};
diff --git a/Documentation/misc-devices/lp8x4x_bus.txt b/Documentation/misc-devices/lp8x4x_bus.txt
index bea435b..829781b 100644
--- a/Documentation/misc-devices/lp8x4x_bus.txt
+++ b/Documentation/misc-devices/lp8x4x_bus.txt
@@ -26,6 +26,9 @@ SYSFS
 
 /sys/bus/icpdas/devices/backplane:
 
+dip
+	RO - shows status of LP-8x4x 8bit DIP switch
+
 rotary
 	RO - shows position of LP-8x4x rotary switch (0-9)
 
diff --git a/arch/arm/boot/dts/pxa27x-lp8x4x.dts b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
index b50ce43..09a6bc9 100644
--- a/arch/arm/boot/dts/pxa27x-lp8x4x.dts
+++ b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
@@ -206,6 +206,7 @@
 			backplane {
 				compatible = "icpdas,backplane-lp8x4x";
 				reg = <0x0 0x2
+				       0x9002 0x2
 				       0x9046 0x2>;
 			};
 		};
diff --git a/drivers/misc/lp8x4x_bus.c b/drivers/misc/lp8x4x_bus.c
index 18ca8f8..dfbc8c4 100644
--- a/drivers/misc/lp8x4x_bus.c
+++ b/drivers/misc/lp8x4x_bus.c
@@ -26,6 +26,7 @@ struct lp8x4x_master {
 	unsigned int		slot_count;
 	void			*count_addr;
 	void			*rotary_addr;
+	void			*dip_addr;
 	struct device		dev;
 };
 
@@ -67,9 +68,20 @@ static ssize_t rotary_show(struct device *dev,
 
 static DEVICE_ATTR_RO(rotary);
 
+static ssize_t dip_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
+
+	return sprintf(buf, "0x%02x\n", ioread8(m->dip_addr) ^ 0xff);
+}
+
+static DEVICE_ATTR_RO(dip);
+
 static struct attribute *master_dev_attrs[] = {
 	&dev_attr_slot_count.attr,
 	&dev_attr_rotary.attr,
+	&dev_attr_dip.attr,
 	NULL,
 };
 ATTRIBUTE_GROUPS(master_dev);
@@ -118,6 +130,20 @@ static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, r++);
 	if (!res) {
+		dev_err(&pdev->dev, "Failed to get DIP switch address\n");
+		err = -ENODEV;
+		goto err_free;
+	}
+
+	m->dip_addr = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(m->dip_addr)) {
+		dev_err(&pdev->dev, "Failed to ioremap DIP switch address\n");
+		err = PTR_ERR(m->dip_addr);
+		goto err_free;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, r++);
+	if (!res) {
 		dev_err(&pdev->dev, "could not get slot count address\n");
 		err = -ENODEV;
 		goto err_free;
-- 
1.8.4.2


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

* [PATCH v3 15/21] misc: support for LP-8x4x DIP switch
@ 2013-12-17 19:37             ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-17 19:37 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Rob Landley, Russell King,
	Arnd Bergmann, Greg Kroah-Hartman, open list:OPEN FIRMWARE AND...,
	open list:DOCUMENTATION

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
   v2..v3
   * new patch

 .../devicetree/bindings/misc/lp8x4x-bus.txt        |  2 ++
 Documentation/misc-devices/lp8x4x_bus.txt          |  3 +++
 arch/arm/boot/dts/pxa27x-lp8x4x.dts                |  1 +
 drivers/misc/lp8x4x_bus.c                          | 26 ++++++++++++++++++++++
 4 files changed, 32 insertions(+)

diff --git a/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt b/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
index 8a55020..1b1776a 100644
--- a/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
+++ b/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
@@ -7,6 +7,7 @@ Required properties:
 
 - reg: physical base addresses and region lengths of
        * the rotary switch
+       * the 8bit DIP switch
        * the slot count register
 
 Example:
@@ -14,5 +15,6 @@ Example:
 	backplane {
 		compatible = "icpdas,backplane-lp8x4x";
 		reg = <0x0 0x2
+		       0x9002 0x2
 		       0x9046 0x2>;
 	};
diff --git a/Documentation/misc-devices/lp8x4x_bus.txt b/Documentation/misc-devices/lp8x4x_bus.txt
index bea435b..829781b 100644
--- a/Documentation/misc-devices/lp8x4x_bus.txt
+++ b/Documentation/misc-devices/lp8x4x_bus.txt
@@ -26,6 +26,9 @@ SYSFS
 
 /sys/bus/icpdas/devices/backplane:
 
+dip
+	RO - shows status of LP-8x4x 8bit DIP switch
+
 rotary
 	RO - shows position of LP-8x4x rotary switch (0-9)
 
diff --git a/arch/arm/boot/dts/pxa27x-lp8x4x.dts b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
index b50ce43..09a6bc9 100644
--- a/arch/arm/boot/dts/pxa27x-lp8x4x.dts
+++ b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
@@ -206,6 +206,7 @@
 			backplane {
 				compatible = "icpdas,backplane-lp8x4x";
 				reg = <0x0 0x2
+				       0x9002 0x2
 				       0x9046 0x2>;
 			};
 		};
diff --git a/drivers/misc/lp8x4x_bus.c b/drivers/misc/lp8x4x_bus.c
index 18ca8f8..dfbc8c4 100644
--- a/drivers/misc/lp8x4x_bus.c
+++ b/drivers/misc/lp8x4x_bus.c
@@ -26,6 +26,7 @@ struct lp8x4x_master {
 	unsigned int		slot_count;
 	void			*count_addr;
 	void			*rotary_addr;
+	void			*dip_addr;
 	struct device		dev;
 };
 
@@ -67,9 +68,20 @@ static ssize_t rotary_show(struct device *dev,
 
 static DEVICE_ATTR_RO(rotary);
 
+static ssize_t dip_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
+
+	return sprintf(buf, "0x%02x\n", ioread8(m->dip_addr) ^ 0xff);
+}
+
+static DEVICE_ATTR_RO(dip);
+
 static struct attribute *master_dev_attrs[] = {
 	&dev_attr_slot_count.attr,
 	&dev_attr_rotary.attr,
+	&dev_attr_dip.attr,
 	NULL,
 };
 ATTRIBUTE_GROUPS(master_dev);
@@ -118,6 +130,20 @@ static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, r++);
 	if (!res) {
+		dev_err(&pdev->dev, "Failed to get DIP switch address\n");
+		err = -ENODEV;
+		goto err_free;
+	}
+
+	m->dip_addr = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(m->dip_addr)) {
+		dev_err(&pdev->dev, "Failed to ioremap DIP switch address\n");
+		err = PTR_ERR(m->dip_addr);
+		goto err_free;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, r++);
+	if (!res) {
 		dev_err(&pdev->dev, "could not get slot count address\n");
 		err = -ENODEV;
 		goto err_free;
-- 
1.8.4.2

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

* [PATCH v3 15/21] misc: support for LP-8x4x DIP switch
@ 2013-12-17 19:37             ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-17 19:37 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
   v2..v3
   * new patch

 .../devicetree/bindings/misc/lp8x4x-bus.txt        |  2 ++
 Documentation/misc-devices/lp8x4x_bus.txt          |  3 +++
 arch/arm/boot/dts/pxa27x-lp8x4x.dts                |  1 +
 drivers/misc/lp8x4x_bus.c                          | 26 ++++++++++++++++++++++
 4 files changed, 32 insertions(+)

diff --git a/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt b/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
index 8a55020..1b1776a 100644
--- a/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
+++ b/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
@@ -7,6 +7,7 @@ Required properties:
 
 - reg: physical base addresses and region lengths of
        * the rotary switch
+       * the 8bit DIP switch
        * the slot count register
 
 Example:
@@ -14,5 +15,6 @@ Example:
 	backplane {
 		compatible = "icpdas,backplane-lp8x4x";
 		reg = <0x0 0x2
+		       0x9002 0x2
 		       0x9046 0x2>;
 	};
diff --git a/Documentation/misc-devices/lp8x4x_bus.txt b/Documentation/misc-devices/lp8x4x_bus.txt
index bea435b..829781b 100644
--- a/Documentation/misc-devices/lp8x4x_bus.txt
+++ b/Documentation/misc-devices/lp8x4x_bus.txt
@@ -26,6 +26,9 @@ SYSFS
 
 /sys/bus/icpdas/devices/backplane:
 
+dip
+	RO - shows status of LP-8x4x 8bit DIP switch
+
 rotary
 	RO - shows position of LP-8x4x rotary switch (0-9)
 
diff --git a/arch/arm/boot/dts/pxa27x-lp8x4x.dts b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
index b50ce43..09a6bc9 100644
--- a/arch/arm/boot/dts/pxa27x-lp8x4x.dts
+++ b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
@@ -206,6 +206,7 @@
 			backplane {
 				compatible = "icpdas,backplane-lp8x4x";
 				reg = <0x0 0x2
+				       0x9002 0x2
 				       0x9046 0x2>;
 			};
 		};
diff --git a/drivers/misc/lp8x4x_bus.c b/drivers/misc/lp8x4x_bus.c
index 18ca8f8..dfbc8c4 100644
--- a/drivers/misc/lp8x4x_bus.c
+++ b/drivers/misc/lp8x4x_bus.c
@@ -26,6 +26,7 @@ struct lp8x4x_master {
 	unsigned int		slot_count;
 	void			*count_addr;
 	void			*rotary_addr;
+	void			*dip_addr;
 	struct device		dev;
 };
 
@@ -67,9 +68,20 @@ static ssize_t rotary_show(struct device *dev,
 
 static DEVICE_ATTR_RO(rotary);
 
+static ssize_t dip_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
+
+	return sprintf(buf, "0x%02x\n", ioread8(m->dip_addr) ^ 0xff);
+}
+
+static DEVICE_ATTR_RO(dip);
+
 static struct attribute *master_dev_attrs[] = {
 	&dev_attr_slot_count.attr,
 	&dev_attr_rotary.attr,
+	&dev_attr_dip.attr,
 	NULL,
 };
 ATTRIBUTE_GROUPS(master_dev);
@@ -118,6 +130,20 @@ static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, r++);
 	if (!res) {
+		dev_err(&pdev->dev, "Failed to get DIP switch address\n");
+		err = -ENODEV;
+		goto err_free;
+	}
+
+	m->dip_addr = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(m->dip_addr)) {
+		dev_err(&pdev->dev, "Failed to ioremap DIP switch address\n");
+		err = PTR_ERR(m->dip_addr);
+		goto err_free;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, r++);
+	if (!res) {
 		dev_err(&pdev->dev, "could not get slot count address\n");
 		err = -ENODEV;
 		goto err_free;
-- 
1.8.4.2

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

* [PATCH v3 16/21] misc: support for writing to LP-8x4x EEPROM
  2013-12-17 19:37           ` Sergei Ianovich
  (?)
@ 2013-12-17 19:37             ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-17 19:37 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Rob Landley, Russell King,
	Arnd Bergmann, Greg Kroah-Hartman, open list:OPEN FIRMWARE AND...,
	open list:DOCUMENTATION

at24c128 write protection is implemented by a separate GPIO line.
EEPROM driver doesn't provide this option, so we implement it
in the board-specific device.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
   v2..v3
   * new patch

 .../devicetree/bindings/misc/lp8x4x-bus.txt        |  3 ++
 Documentation/misc-devices/lp8x4x_bus.txt          |  3 ++
 arch/arm/boot/dts/pxa27x-lp8x4x.dts                |  1 +
 drivers/misc/lp8x4x_bus.c                          | 50 ++++++++++++++++++++++
 4 files changed, 57 insertions(+)

diff --git a/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt b/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
index 1b1776a..b0fb145 100644
--- a/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
+++ b/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
@@ -10,6 +10,8 @@ Required properties:
        * the 8bit DIP switch
        * the slot count register
 
+- eeprom-gpios : should point to active-low write enable GPIO
+
 Example:
 
 	backplane {
@@ -17,4 +19,5 @@ Example:
 		reg = <0x0 0x2
 		       0x9002 0x2
 		       0x9046 0x2>;
+		eeprom-gpios = <&gpio 4 0>;
 	};
diff --git a/Documentation/misc-devices/lp8x4x_bus.txt b/Documentation/misc-devices/lp8x4x_bus.txt
index 829781b..78ea0a89 100644
--- a/Documentation/misc-devices/lp8x4x_bus.txt
+++ b/Documentation/misc-devices/lp8x4x_bus.txt
@@ -29,6 +29,9 @@ SYSFS
 dip
 	RO - shows status of LP-8x4x 8bit DIP switch
 
+eeprom_write_enable
+	RW - controls write access to board's EEPROM (1 - enable)
+
 rotary
 	RO - shows position of LP-8x4x rotary switch (0-9)
 
diff --git a/arch/arm/boot/dts/pxa27x-lp8x4x.dts b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
index 09a6bc9..52f0036 100644
--- a/arch/arm/boot/dts/pxa27x-lp8x4x.dts
+++ b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
@@ -208,6 +208,7 @@
 				reg = <0x0 0x2
 				       0x9002 0x2
 				       0x9046 0x2>;
+				eeprom-gpios = <&gpio 4 0>;
 			};
 		};
 	};
diff --git a/drivers/misc/lp8x4x_bus.c b/drivers/misc/lp8x4x_bus.c
index dfbc8c4..567fe078 100644
--- a/drivers/misc/lp8x4x_bus.c
+++ b/drivers/misc/lp8x4x_bus.c
@@ -9,6 +9,7 @@
  *  published by the Free Software Foundation or any later version.
  */
 #include <linux/err.h>
+#include <linux/gpio/consumer.h>
 #include <linux/init.h>
 #include <linux/io.h>
 #include <linux/list.h>
@@ -27,6 +28,7 @@ struct lp8x4x_master {
 	void			*count_addr;
 	void			*rotary_addr;
 	void			*dip_addr;
+	struct gpio_desc        *eeprom_nWE;
 	struct device		dev;
 };
 
@@ -68,6 +70,40 @@ static ssize_t rotary_show(struct device *dev,
 
 static DEVICE_ATTR_RO(rotary);
 
+static ssize_t eeprom_write_enable_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
+
+	return sprintf(buf, "%u\n", !gpiod_get_value(m->eeprom_nWE));
+}
+
+static ssize_t eeprom_write_enable_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
+	unsigned int val = 0;
+	int err;
+
+	if (!buf)
+		return count;
+
+	if (0 == count)
+		return count;
+
+	err = kstrtouint(buf, 10, &val);
+	if (err != 0) {
+		dev_err(dev, "Bad input %s\n", buf);
+		return count;
+	}
+
+	gpiod_set_value(m->eeprom_nWE, !val);
+
+	return count;
+}
+
+static DEVICE_ATTR_RW(eeprom_write_enable);
+
 static ssize_t dip_show(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
@@ -81,6 +117,7 @@ static DEVICE_ATTR_RO(dip);
 static struct attribute *master_dev_attrs[] = {
 	&dev_attr_slot_count.attr,
 	&dev_attr_rotary.attr,
+	&dev_attr_eeprom_write_enable.attr,
 	&dev_attr_dip.attr,
 	NULL,
 };
@@ -156,6 +193,19 @@ static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 		goto err_free;
 	}
 
+	m->eeprom_nWE = devm_gpiod_get(&pdev->dev, "eeprom");
+	if (IS_ERR(m->eeprom_nWE)) {
+		err = PTR_ERR(m->eeprom_nWE);
+		dev_err(&pdev->dev, "Failed to get eeprom GPIO\n");
+		goto err_free;
+	}
+
+	err = gpiod_direction_output(m->eeprom_nWE, 1);
+	if (err < 0) {
+		dev_err(&pdev->dev, "Failed to set eeprom GPIO output\n");
+		goto err_free;
+	}
+
 	m->slot_count = ioread8(m->count_addr);
 	switch (m->slot_count) {
 	case 1:
-- 
1.8.4.2


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

* [PATCH v3 16/21] misc: support for writing to LP-8x4x EEPROM
@ 2013-12-17 19:37             ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-17 19:37 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Rob Landley, Russell King,
	Arnd Bergmann, Greg Kroah-Hartman, open list:OPEN FIRMWARE AND...,
	open list:DOCUMENTATION

at24c128 write protection is implemented by a separate GPIO line.
EEPROM driver doesn't provide this option, so we implement it
in the board-specific device.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
   v2..v3
   * new patch

 .../devicetree/bindings/misc/lp8x4x-bus.txt        |  3 ++
 Documentation/misc-devices/lp8x4x_bus.txt          |  3 ++
 arch/arm/boot/dts/pxa27x-lp8x4x.dts                |  1 +
 drivers/misc/lp8x4x_bus.c                          | 50 ++++++++++++++++++++++
 4 files changed, 57 insertions(+)

diff --git a/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt b/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
index 1b1776a..b0fb145 100644
--- a/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
+++ b/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
@@ -10,6 +10,8 @@ Required properties:
        * the 8bit DIP switch
        * the slot count register
 
+- eeprom-gpios : should point to active-low write enable GPIO
+
 Example:
 
 	backplane {
@@ -17,4 +19,5 @@ Example:
 		reg = <0x0 0x2
 		       0x9002 0x2
 		       0x9046 0x2>;
+		eeprom-gpios = <&gpio 4 0>;
 	};
diff --git a/Documentation/misc-devices/lp8x4x_bus.txt b/Documentation/misc-devices/lp8x4x_bus.txt
index 829781b..78ea0a89 100644
--- a/Documentation/misc-devices/lp8x4x_bus.txt
+++ b/Documentation/misc-devices/lp8x4x_bus.txt
@@ -29,6 +29,9 @@ SYSFS
 dip
 	RO - shows status of LP-8x4x 8bit DIP switch
 
+eeprom_write_enable
+	RW - controls write access to board's EEPROM (1 - enable)
+
 rotary
 	RO - shows position of LP-8x4x rotary switch (0-9)
 
diff --git a/arch/arm/boot/dts/pxa27x-lp8x4x.dts b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
index 09a6bc9..52f0036 100644
--- a/arch/arm/boot/dts/pxa27x-lp8x4x.dts
+++ b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
@@ -208,6 +208,7 @@
 				reg = <0x0 0x2
 				       0x9002 0x2
 				       0x9046 0x2>;
+				eeprom-gpios = <&gpio 4 0>;
 			};
 		};
 	};
diff --git a/drivers/misc/lp8x4x_bus.c b/drivers/misc/lp8x4x_bus.c
index dfbc8c4..567fe078 100644
--- a/drivers/misc/lp8x4x_bus.c
+++ b/drivers/misc/lp8x4x_bus.c
@@ -9,6 +9,7 @@
  *  published by the Free Software Foundation or any later version.
  */
 #include <linux/err.h>
+#include <linux/gpio/consumer.h>
 #include <linux/init.h>
 #include <linux/io.h>
 #include <linux/list.h>
@@ -27,6 +28,7 @@ struct lp8x4x_master {
 	void			*count_addr;
 	void			*rotary_addr;
 	void			*dip_addr;
+	struct gpio_desc        *eeprom_nWE;
 	struct device		dev;
 };
 
@@ -68,6 +70,40 @@ static ssize_t rotary_show(struct device *dev,
 
 static DEVICE_ATTR_RO(rotary);
 
+static ssize_t eeprom_write_enable_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
+
+	return sprintf(buf, "%u\n", !gpiod_get_value(m->eeprom_nWE));
+}
+
+static ssize_t eeprom_write_enable_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
+	unsigned int val = 0;
+	int err;
+
+	if (!buf)
+		return count;
+
+	if (0 == count)
+		return count;
+
+	err = kstrtouint(buf, 10, &val);
+	if (err != 0) {
+		dev_err(dev, "Bad input %s\n", buf);
+		return count;
+	}
+
+	gpiod_set_value(m->eeprom_nWE, !val);
+
+	return count;
+}
+
+static DEVICE_ATTR_RW(eeprom_write_enable);
+
 static ssize_t dip_show(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
@@ -81,6 +117,7 @@ static DEVICE_ATTR_RO(dip);
 static struct attribute *master_dev_attrs[] = {
 	&dev_attr_slot_count.attr,
 	&dev_attr_rotary.attr,
+	&dev_attr_eeprom_write_enable.attr,
 	&dev_attr_dip.attr,
 	NULL,
 };
@@ -156,6 +193,19 @@ static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 		goto err_free;
 	}
 
+	m->eeprom_nWE = devm_gpiod_get(&pdev->dev, "eeprom");
+	if (IS_ERR(m->eeprom_nWE)) {
+		err = PTR_ERR(m->eeprom_nWE);
+		dev_err(&pdev->dev, "Failed to get eeprom GPIO\n");
+		goto err_free;
+	}
+
+	err = gpiod_direction_output(m->eeprom_nWE, 1);
+	if (err < 0) {
+		dev_err(&pdev->dev, "Failed to set eeprom GPIO output\n");
+		goto err_free;
+	}
+
 	m->slot_count = ioread8(m->count_addr);
 	switch (m->slot_count) {
 	case 1:
-- 
1.8.4.2

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

* [PATCH v3 16/21] misc: support for writing to LP-8x4x EEPROM
@ 2013-12-17 19:37             ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-17 19:37 UTC (permalink / raw)
  To: linux-arm-kernel

at24c128 write protection is implemented by a separate GPIO line.
EEPROM driver doesn't provide this option, so we implement it
in the board-specific device.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
   v2..v3
   * new patch

 .../devicetree/bindings/misc/lp8x4x-bus.txt        |  3 ++
 Documentation/misc-devices/lp8x4x_bus.txt          |  3 ++
 arch/arm/boot/dts/pxa27x-lp8x4x.dts                |  1 +
 drivers/misc/lp8x4x_bus.c                          | 50 ++++++++++++++++++++++
 4 files changed, 57 insertions(+)

diff --git a/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt b/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
index 1b1776a..b0fb145 100644
--- a/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
+++ b/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
@@ -10,6 +10,8 @@ Required properties:
        * the 8bit DIP switch
        * the slot count register
 
+- eeprom-gpios : should point to active-low write enable GPIO
+
 Example:
 
 	backplane {
@@ -17,4 +19,5 @@ Example:
 		reg = <0x0 0x2
 		       0x9002 0x2
 		       0x9046 0x2>;
+		eeprom-gpios = <&gpio 4 0>;
 	};
diff --git a/Documentation/misc-devices/lp8x4x_bus.txt b/Documentation/misc-devices/lp8x4x_bus.txt
index 829781b..78ea0a89 100644
--- a/Documentation/misc-devices/lp8x4x_bus.txt
+++ b/Documentation/misc-devices/lp8x4x_bus.txt
@@ -29,6 +29,9 @@ SYSFS
 dip
 	RO - shows status of LP-8x4x 8bit DIP switch
 
+eeprom_write_enable
+	RW - controls write access to board's EEPROM (1 - enable)
+
 rotary
 	RO - shows position of LP-8x4x rotary switch (0-9)
 
diff --git a/arch/arm/boot/dts/pxa27x-lp8x4x.dts b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
index 09a6bc9..52f0036 100644
--- a/arch/arm/boot/dts/pxa27x-lp8x4x.dts
+++ b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
@@ -208,6 +208,7 @@
 				reg = <0x0 0x2
 				       0x9002 0x2
 				       0x9046 0x2>;
+				eeprom-gpios = <&gpio 4 0>;
 			};
 		};
 	};
diff --git a/drivers/misc/lp8x4x_bus.c b/drivers/misc/lp8x4x_bus.c
index dfbc8c4..567fe078 100644
--- a/drivers/misc/lp8x4x_bus.c
+++ b/drivers/misc/lp8x4x_bus.c
@@ -9,6 +9,7 @@
  *  published by the Free Software Foundation or any later version.
  */
 #include <linux/err.h>
+#include <linux/gpio/consumer.h>
 #include <linux/init.h>
 #include <linux/io.h>
 #include <linux/list.h>
@@ -27,6 +28,7 @@ struct lp8x4x_master {
 	void			*count_addr;
 	void			*rotary_addr;
 	void			*dip_addr;
+	struct gpio_desc        *eeprom_nWE;
 	struct device		dev;
 };
 
@@ -68,6 +70,40 @@ static ssize_t rotary_show(struct device *dev,
 
 static DEVICE_ATTR_RO(rotary);
 
+static ssize_t eeprom_write_enable_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
+
+	return sprintf(buf, "%u\n", !gpiod_get_value(m->eeprom_nWE));
+}
+
+static ssize_t eeprom_write_enable_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
+	unsigned int val = 0;
+	int err;
+
+	if (!buf)
+		return count;
+
+	if (0 == count)
+		return count;
+
+	err = kstrtouint(buf, 10, &val);
+	if (err != 0) {
+		dev_err(dev, "Bad input %s\n", buf);
+		return count;
+	}
+
+	gpiod_set_value(m->eeprom_nWE, !val);
+
+	return count;
+}
+
+static DEVICE_ATTR_RW(eeprom_write_enable);
+
 static ssize_t dip_show(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
@@ -81,6 +117,7 @@ static DEVICE_ATTR_RO(dip);
 static struct attribute *master_dev_attrs[] = {
 	&dev_attr_slot_count.attr,
 	&dev_attr_rotary.attr,
+	&dev_attr_eeprom_write_enable.attr,
 	&dev_attr_dip.attr,
 	NULL,
 };
@@ -156,6 +193,19 @@ static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 		goto err_free;
 	}
 
+	m->eeprom_nWE = devm_gpiod_get(&pdev->dev, "eeprom");
+	if (IS_ERR(m->eeprom_nWE)) {
+		err = PTR_ERR(m->eeprom_nWE);
+		dev_err(&pdev->dev, "Failed to get eeprom GPIO\n");
+		goto err_free;
+	}
+
+	err = gpiod_direction_output(m->eeprom_nWE, 1);
+	if (err < 0) {
+		dev_err(&pdev->dev, "Failed to set eeprom GPIO output\n");
+		goto err_free;
+	}
+
 	m->slot_count = ioread8(m->count_addr);
 	switch (m->slot_count) {
 	case 1:
-- 
1.8.4.2

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

* [PATCH v3 17/21] misc: support for serial slots in LP-8x4x
  2013-12-17 19:37           ` Sergei Ianovich
  (?)
@ 2013-12-17 19:37             ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-17 19:37 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Rob Landley, Russell King,
	Arnd Bergmann, Greg Kroah-Hartman, open list:OPEN FIRMWARE AND...,
	open list:DOCUMENTATION

Serial modules (I-870xxW series) implement DCON protocol which
allows one-master-many-slaves configuration over RS-485. When
these modules are installed into the device, they could be
accessed using the 2nd PXA built-in UART port (/dev/ttyS1).
However, it seems that addresses are not processed by the modules.
So the parallel bus needs to select which slot is connected.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
   v2..v3
   * no changes (except number 12/16 -> 17/21)

   v0..v2
   * use device tree
   * use devm helpers where possible

 .../devicetree/bindings/misc/lp8x4x-bus.txt        |  2 +
 Documentation/misc-devices/lp8x4x_bus.txt          | 15 +++++-
 arch/arm/boot/dts/pxa27x-lp8x4x.dts                |  1 +
 drivers/misc/lp8x4x_bus.c                          | 63 ++++++++++++++++++++++
 4 files changed, 80 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt b/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
index b0fb145..24a8c62 100644
--- a/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
+++ b/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
@@ -8,6 +8,7 @@ Required properties:
 - reg: physical base addresses and region lengths of
        * the rotary switch
        * the 8bit DIP switch
+       * the serial slot select register
        * the slot count register
 
 - eeprom-gpios : should point to active-low write enable GPIO
@@ -18,6 +19,7 @@ Example:
 		compatible = "icpdas,backplane-lp8x4x";
 		reg = <0x0 0x2
 		       0x9002 0x2
+		       0x9004 0x2
 		       0x9046 0x2>;
 		eeprom-gpios = <&gpio 4 0>;
 	};
diff --git a/Documentation/misc-devices/lp8x4x_bus.txt b/Documentation/misc-devices/lp8x4x_bus.txt
index 78ea0a89..7b86797 100644
--- a/Documentation/misc-devices/lp8x4x_bus.txt
+++ b/Documentation/misc-devices/lp8x4x_bus.txt
@@ -19,13 +19,26 @@ LP-8x4x is an ARM-based industrial computer with a custom parallel bus to
 connect expansion modules with digital input/output, analog input/output,
 serial, CAN and other types of ports.
 
-The bus is implemented by a FPGA.
+The bus is implemented by a FPGA. There are two major groups of expansion
+modules: serial and parallel.
+
+Serial modules (I-870xxW series) implement DCON protocol which allows one-
+master-many-slaves configuration over RS-485. When these modules are installed
+into the device, they could be accessed using the 2nd PXA built-in UART port
+(/dev/ttyS1). However, it seems that addresses are not processed by
+the modules. So the parallel bus needs to select which slot is connected.
 
 SYSFS
 -----
 
 /sys/bus/icpdas/devices/backplane:
 
+active_slot
+	RW - connects the select slot for serial communications. If there
+	     is a parallel module in the selected slot, it simply ignores
+	     incoming packets. So it is safe to activate any available
+	     slot.
+
 dip
 	RO - shows status of LP-8x4x 8bit DIP switch
 
diff --git a/arch/arm/boot/dts/pxa27x-lp8x4x.dts b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
index 52f0036..a6adf45 100644
--- a/arch/arm/boot/dts/pxa27x-lp8x4x.dts
+++ b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
@@ -207,6 +207,7 @@
 				compatible = "icpdas,backplane-lp8x4x";
 				reg = <0x0 0x2
 				       0x9002 0x2
+				       0x9004 0x2
 				       0x9046 0x2>;
 				eeprom-gpios = <&gpio 4 0>;
 			};
diff --git a/drivers/misc/lp8x4x_bus.c b/drivers/misc/lp8x4x_bus.c
index 567fe078..e805640 100644
--- a/drivers/misc/lp8x4x_bus.c
+++ b/drivers/misc/lp8x4x_bus.c
@@ -29,6 +29,8 @@ struct lp8x4x_master {
 	void			*rotary_addr;
 	void			*dip_addr;
 	struct gpio_desc        *eeprom_nWE;
+	unsigned int		active_slot;
+	void			*switch_addr;
 	struct device		dev;
 };
 
@@ -47,6 +49,9 @@ static void lp8x4x_master_release(struct device *dev)
 	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
 	WARN_ON(!dev);
 
+	/* Disable serial communications */
+	iowrite8(0xff, m->switch_addr);
+
 	kfree(m);
 }
 
@@ -114,11 +119,52 @@ static ssize_t dip_show(struct device *dev,
 
 static DEVICE_ATTR_RO(dip);
 
+static ssize_t active_slot_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
+
+	return sprintf(buf, "%u\n", m->active_slot);
+}
+
+static ssize_t active_slot_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
+	unsigned int active_slot = 0;
+	int err;
+
+	if (!buf)
+		return count;
+	if (0 == count)
+		return count;
+
+	err = kstrtouint(buf, 10, &active_slot);
+	if (err != 0 || active_slot > m->slot_count) {
+		dev_err(dev, "slot number is out of range 1..%u\n",
+				m->slot_count);
+		return count;
+	}
+
+	if (!active_slot) {
+		m->active_slot = 0;
+		iowrite8(0xff, m->switch_addr);
+		return count;
+	}
+
+	m->active_slot = active_slot;
+	iowrite8((1 << (m->active_slot - 1)) ^ 0xff, m->switch_addr);
+	return count;
+}
+
+static DEVICE_ATTR_RW(active_slot);
+
 static struct attribute *master_dev_attrs[] = {
 	&dev_attr_slot_count.attr,
 	&dev_attr_rotary.attr,
 	&dev_attr_eeprom_write_enable.attr,
 	&dev_attr_dip.attr,
+	&dev_attr_active_slot.attr,
 	NULL,
 };
 ATTRIBUTE_GROUPS(master_dev);
@@ -181,6 +227,20 @@ static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, r++);
 	if (!res) {
+		dev_err(&pdev->dev, "Failed to get slot switch address\n");
+		err = -ENODEV;
+		goto err_free;
+	}
+
+	m->switch_addr = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(m->switch_addr)) {
+		dev_err(&pdev->dev, "Failed to ioremap switch address\n");
+		err = PTR_ERR(m->switch_addr);
+		goto err_free;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, r++);
+	if (!res) {
 		dev_err(&pdev->dev, "could not get slot count address\n");
 		err = -ENODEV;
 		goto err_free;
@@ -223,6 +283,9 @@ static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 
 	dev_info(&pdev->dev, "found bus with up to %u slots\n", m->slot_count);
 
+	/* Disable serial communications until explicitly enabled */
+	iowrite8(0xff, m->switch_addr);
+
 	err = bus_register(&lp8x4x_bus_type);
 	if (err < 0) {
 		dev_err(&pdev->dev, "failed to register bus type\n");
-- 
1.8.4.2


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

* [PATCH v3 17/21] misc: support for serial slots in LP-8x4x
@ 2013-12-17 19:37             ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-17 19:37 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Rob Landley, Russell King,
	Arnd Bergmann, Greg Kroah-Hartman, open list:OPEN FIRMWARE AND...,
	open list:DOCUMENTATION

Serial modules (I-870xxW series) implement DCON protocol which
allows one-master-many-slaves configuration over RS-485. When
these modules are installed into the device, they could be
accessed using the 2nd PXA built-in UART port (/dev/ttyS1).
However, it seems that addresses are not processed by the modules.
So the parallel bus needs to select which slot is connected.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
   v2..v3
   * no changes (except number 12/16 -> 17/21)

   v0..v2
   * use device tree
   * use devm helpers where possible

 .../devicetree/bindings/misc/lp8x4x-bus.txt        |  2 +
 Documentation/misc-devices/lp8x4x_bus.txt          | 15 +++++-
 arch/arm/boot/dts/pxa27x-lp8x4x.dts                |  1 +
 drivers/misc/lp8x4x_bus.c                          | 63 ++++++++++++++++++++++
 4 files changed, 80 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt b/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
index b0fb145..24a8c62 100644
--- a/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
+++ b/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
@@ -8,6 +8,7 @@ Required properties:
 - reg: physical base addresses and region lengths of
        * the rotary switch
        * the 8bit DIP switch
+       * the serial slot select register
        * the slot count register
 
 - eeprom-gpios : should point to active-low write enable GPIO
@@ -18,6 +19,7 @@ Example:
 		compatible = "icpdas,backplane-lp8x4x";
 		reg = <0x0 0x2
 		       0x9002 0x2
+		       0x9004 0x2
 		       0x9046 0x2>;
 		eeprom-gpios = <&gpio 4 0>;
 	};
diff --git a/Documentation/misc-devices/lp8x4x_bus.txt b/Documentation/misc-devices/lp8x4x_bus.txt
index 78ea0a89..7b86797 100644
--- a/Documentation/misc-devices/lp8x4x_bus.txt
+++ b/Documentation/misc-devices/lp8x4x_bus.txt
@@ -19,13 +19,26 @@ LP-8x4x is an ARM-based industrial computer with a custom parallel bus to
 connect expansion modules with digital input/output, analog input/output,
 serial, CAN and other types of ports.
 
-The bus is implemented by a FPGA.
+The bus is implemented by a FPGA. There are two major groups of expansion
+modules: serial and parallel.
+
+Serial modules (I-870xxW series) implement DCON protocol which allows one-
+master-many-slaves configuration over RS-485. When these modules are installed
+into the device, they could be accessed using the 2nd PXA built-in UART port
+(/dev/ttyS1). However, it seems that addresses are not processed by
+the modules. So the parallel bus needs to select which slot is connected.
 
 SYSFS
 -----
 
 /sys/bus/icpdas/devices/backplane:
 
+active_slot
+	RW - connects the select slot for serial communications. If there
+	     is a parallel module in the selected slot, it simply ignores
+	     incoming packets. So it is safe to activate any available
+	     slot.
+
 dip
 	RO - shows status of LP-8x4x 8bit DIP switch
 
diff --git a/arch/arm/boot/dts/pxa27x-lp8x4x.dts b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
index 52f0036..a6adf45 100644
--- a/arch/arm/boot/dts/pxa27x-lp8x4x.dts
+++ b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
@@ -207,6 +207,7 @@
 				compatible = "icpdas,backplane-lp8x4x";
 				reg = <0x0 0x2
 				       0x9002 0x2
+				       0x9004 0x2
 				       0x9046 0x2>;
 				eeprom-gpios = <&gpio 4 0>;
 			};
diff --git a/drivers/misc/lp8x4x_bus.c b/drivers/misc/lp8x4x_bus.c
index 567fe078..e805640 100644
--- a/drivers/misc/lp8x4x_bus.c
+++ b/drivers/misc/lp8x4x_bus.c
@@ -29,6 +29,8 @@ struct lp8x4x_master {
 	void			*rotary_addr;
 	void			*dip_addr;
 	struct gpio_desc        *eeprom_nWE;
+	unsigned int		active_slot;
+	void			*switch_addr;
 	struct device		dev;
 };
 
@@ -47,6 +49,9 @@ static void lp8x4x_master_release(struct device *dev)
 	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
 	WARN_ON(!dev);
 
+	/* Disable serial communications */
+	iowrite8(0xff, m->switch_addr);
+
 	kfree(m);
 }
 
@@ -114,11 +119,52 @@ static ssize_t dip_show(struct device *dev,
 
 static DEVICE_ATTR_RO(dip);
 
+static ssize_t active_slot_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
+
+	return sprintf(buf, "%u\n", m->active_slot);
+}
+
+static ssize_t active_slot_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
+	unsigned int active_slot = 0;
+	int err;
+
+	if (!buf)
+		return count;
+	if (0 == count)
+		return count;
+
+	err = kstrtouint(buf, 10, &active_slot);
+	if (err != 0 || active_slot > m->slot_count) {
+		dev_err(dev, "slot number is out of range 1..%u\n",
+				m->slot_count);
+		return count;
+	}
+
+	if (!active_slot) {
+		m->active_slot = 0;
+		iowrite8(0xff, m->switch_addr);
+		return count;
+	}
+
+	m->active_slot = active_slot;
+	iowrite8((1 << (m->active_slot - 1)) ^ 0xff, m->switch_addr);
+	return count;
+}
+
+static DEVICE_ATTR_RW(active_slot);
+
 static struct attribute *master_dev_attrs[] = {
 	&dev_attr_slot_count.attr,
 	&dev_attr_rotary.attr,
 	&dev_attr_eeprom_write_enable.attr,
 	&dev_attr_dip.attr,
+	&dev_attr_active_slot.attr,
 	NULL,
 };
 ATTRIBUTE_GROUPS(master_dev);
@@ -181,6 +227,20 @@ static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, r++);
 	if (!res) {
+		dev_err(&pdev->dev, "Failed to get slot switch address\n");
+		err = -ENODEV;
+		goto err_free;
+	}
+
+	m->switch_addr = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(m->switch_addr)) {
+		dev_err(&pdev->dev, "Failed to ioremap switch address\n");
+		err = PTR_ERR(m->switch_addr);
+		goto err_free;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, r++);
+	if (!res) {
 		dev_err(&pdev->dev, "could not get slot count address\n");
 		err = -ENODEV;
 		goto err_free;
@@ -223,6 +283,9 @@ static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 
 	dev_info(&pdev->dev, "found bus with up to %u slots\n", m->slot_count);
 
+	/* Disable serial communications until explicitly enabled */
+	iowrite8(0xff, m->switch_addr);
+
 	err = bus_register(&lp8x4x_bus_type);
 	if (err < 0) {
 		dev_err(&pdev->dev, "failed to register bus type\n");
-- 
1.8.4.2

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

* [PATCH v3 17/21] misc: support for serial slots in LP-8x4x
@ 2013-12-17 19:37             ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-17 19:37 UTC (permalink / raw)
  To: linux-arm-kernel

Serial modules (I-870xxW series) implement DCON protocol which
allows one-master-many-slaves configuration over RS-485. When
these modules are installed into the device, they could be
accessed using the 2nd PXA built-in UART port (/dev/ttyS1).
However, it seems that addresses are not processed by the modules.
So the parallel bus needs to select which slot is connected.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
   v2..v3
   * no changes (except number 12/16 -> 17/21)

   v0..v2
   * use device tree
   * use devm helpers where possible

 .../devicetree/bindings/misc/lp8x4x-bus.txt        |  2 +
 Documentation/misc-devices/lp8x4x_bus.txt          | 15 +++++-
 arch/arm/boot/dts/pxa27x-lp8x4x.dts                |  1 +
 drivers/misc/lp8x4x_bus.c                          | 63 ++++++++++++++++++++++
 4 files changed, 80 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt b/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
index b0fb145..24a8c62 100644
--- a/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
+++ b/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
@@ -8,6 +8,7 @@ Required properties:
 - reg: physical base addresses and region lengths of
        * the rotary switch
        * the 8bit DIP switch
+       * the serial slot select register
        * the slot count register
 
 - eeprom-gpios : should point to active-low write enable GPIO
@@ -18,6 +19,7 @@ Example:
 		compatible = "icpdas,backplane-lp8x4x";
 		reg = <0x0 0x2
 		       0x9002 0x2
+		       0x9004 0x2
 		       0x9046 0x2>;
 		eeprom-gpios = <&gpio 4 0>;
 	};
diff --git a/Documentation/misc-devices/lp8x4x_bus.txt b/Documentation/misc-devices/lp8x4x_bus.txt
index 78ea0a89..7b86797 100644
--- a/Documentation/misc-devices/lp8x4x_bus.txt
+++ b/Documentation/misc-devices/lp8x4x_bus.txt
@@ -19,13 +19,26 @@ LP-8x4x is an ARM-based industrial computer with a custom parallel bus to
 connect expansion modules with digital input/output, analog input/output,
 serial, CAN and other types of ports.
 
-The bus is implemented by a FPGA.
+The bus is implemented by a FPGA. There are two major groups of expansion
+modules: serial and parallel.
+
+Serial modules (I-870xxW series) implement DCON protocol which allows one-
+master-many-slaves configuration over RS-485. When these modules are installed
+into the device, they could be accessed using the 2nd PXA built-in UART port
+(/dev/ttyS1). However, it seems that addresses are not processed by
+the modules. So the parallel bus needs to select which slot is connected.
 
 SYSFS
 -----
 
 /sys/bus/icpdas/devices/backplane:
 
+active_slot
+	RW - connects the select slot for serial communications. If there
+	     is a parallel module in the selected slot, it simply ignores
+	     incoming packets. So it is safe to activate any available
+	     slot.
+
 dip
 	RO - shows status of LP-8x4x 8bit DIP switch
 
diff --git a/arch/arm/boot/dts/pxa27x-lp8x4x.dts b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
index 52f0036..a6adf45 100644
--- a/arch/arm/boot/dts/pxa27x-lp8x4x.dts
+++ b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
@@ -207,6 +207,7 @@
 				compatible = "icpdas,backplane-lp8x4x";
 				reg = <0x0 0x2
 				       0x9002 0x2
+				       0x9004 0x2
 				       0x9046 0x2>;
 				eeprom-gpios = <&gpio 4 0>;
 			};
diff --git a/drivers/misc/lp8x4x_bus.c b/drivers/misc/lp8x4x_bus.c
index 567fe078..e805640 100644
--- a/drivers/misc/lp8x4x_bus.c
+++ b/drivers/misc/lp8x4x_bus.c
@@ -29,6 +29,8 @@ struct lp8x4x_master {
 	void			*rotary_addr;
 	void			*dip_addr;
 	struct gpio_desc        *eeprom_nWE;
+	unsigned int		active_slot;
+	void			*switch_addr;
 	struct device		dev;
 };
 
@@ -47,6 +49,9 @@ static void lp8x4x_master_release(struct device *dev)
 	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
 	WARN_ON(!dev);
 
+	/* Disable serial communications */
+	iowrite8(0xff, m->switch_addr);
+
 	kfree(m);
 }
 
@@ -114,11 +119,52 @@ static ssize_t dip_show(struct device *dev,
 
 static DEVICE_ATTR_RO(dip);
 
+static ssize_t active_slot_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
+
+	return sprintf(buf, "%u\n", m->active_slot);
+}
+
+static ssize_t active_slot_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
+	unsigned int active_slot = 0;
+	int err;
+
+	if (!buf)
+		return count;
+	if (0 == count)
+		return count;
+
+	err = kstrtouint(buf, 10, &active_slot);
+	if (err != 0 || active_slot > m->slot_count) {
+		dev_err(dev, "slot number is out of range 1..%u\n",
+				m->slot_count);
+		return count;
+	}
+
+	if (!active_slot) {
+		m->active_slot = 0;
+		iowrite8(0xff, m->switch_addr);
+		return count;
+	}
+
+	m->active_slot = active_slot;
+	iowrite8((1 << (m->active_slot - 1)) ^ 0xff, m->switch_addr);
+	return count;
+}
+
+static DEVICE_ATTR_RW(active_slot);
+
 static struct attribute *master_dev_attrs[] = {
 	&dev_attr_slot_count.attr,
 	&dev_attr_rotary.attr,
 	&dev_attr_eeprom_write_enable.attr,
 	&dev_attr_dip.attr,
+	&dev_attr_active_slot.attr,
 	NULL,
 };
 ATTRIBUTE_GROUPS(master_dev);
@@ -181,6 +227,20 @@ static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, r++);
 	if (!res) {
+		dev_err(&pdev->dev, "Failed to get slot switch address\n");
+		err = -ENODEV;
+		goto err_free;
+	}
+
+	m->switch_addr = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(m->switch_addr)) {
+		dev_err(&pdev->dev, "Failed to ioremap switch address\n");
+		err = PTR_ERR(m->switch_addr);
+		goto err_free;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, r++);
+	if (!res) {
 		dev_err(&pdev->dev, "could not get slot count address\n");
 		err = -ENODEV;
 		goto err_free;
@@ -223,6 +283,9 @@ static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 
 	dev_info(&pdev->dev, "found bus with up to %u slots\n", m->slot_count);
 
+	/* Disable serial communications until explicitly enabled */
+	iowrite8(0xff, m->switch_addr);
+
 	err = bus_register(&lp8x4x_bus_type);
 	if (err < 0) {
 		dev_err(&pdev->dev, "failed to register bus type\n");
-- 
1.8.4.2

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

* [PATCH v3 18/21] misc: support for parallel slots in LP-8x4x
  2013-12-17 19:37           ` Sergei Ianovich
  (?)
@ 2013-12-17 19:37             ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-17 19:37 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Rob Landley, Russell King,
	Arnd Bergmann, Greg Kroah-Hartman, open list:OPEN FIRMWARE AND...,
	open list:DOCUMENTATION

This patch enumerates parallel modules in expansion slots and exposes
model numbers via sysfs.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
   v2..v3
   * no changes (except number 13/16 -> 18/21)

   v0..v2
   * use device tree
   * use devm helpers where possible

 .../devicetree/bindings/misc/lp8x4x-bus.txt        |   9 ++
 Documentation/misc-devices/lp8x4x_bus.txt          |   8 ++
 arch/arm/boot/dts/pxa27x-lp8x4x.dts                |   8 ++
 drivers/misc/lp8x4x_bus.c                          | 119 +++++++++++++++++++++
 4 files changed, 144 insertions(+)

diff --git a/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt b/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
index 24a8c62..75ac3b2 100644
--- a/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
+++ b/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
@@ -7,6 +7,7 @@ Required properties:
 
 - reg: physical base addresses and region lengths of
        * the rotary switch
+       * 8 plugable industrial IO slots
        * the 8bit DIP switch
        * the serial slot select register
        * the slot count register
@@ -18,6 +19,14 @@ Example:
 	backplane {
 		compatible = "icpdas,backplane-lp8x4x";
 		reg = <0x0 0x2
+		       0x1000 0x10
+		       0x2000 0x10
+		       0x3000 0x10
+		       0x4000 0x10
+		       0x5000 0x10
+		       0x6000 0x10
+		       0x7000 0x10
+		       0x8000 0x10
 		       0x9002 0x2
 		       0x9004 0x2
 		       0x9046 0x2>;
diff --git a/Documentation/misc-devices/lp8x4x_bus.txt b/Documentation/misc-devices/lp8x4x_bus.txt
index 7b86797..09380fd 100644
--- a/Documentation/misc-devices/lp8x4x_bus.txt
+++ b/Documentation/misc-devices/lp8x4x_bus.txt
@@ -28,6 +28,9 @@ into the device, they could be accessed using the 2nd PXA built-in UART port
 (/dev/ttyS1). However, it seems that addresses are not processed by
 the modules. So the parallel bus needs to select which slot is connected.
 
+Parallel modules allow much faster communication. There are accessed using
+IO memory through the FPGA. Their ports are exposed via sysfs.
+
 SYSFS
 -----
 
@@ -50,3 +53,8 @@ rotary
 
 slot_count
 	RO - shows total number of expansion slots on the device
+
+/sys/bus/icpdas/devices/slot%02i:
+
+model
+	RO - shows expansion module model number
diff --git a/arch/arm/boot/dts/pxa27x-lp8x4x.dts b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
index a6adf45..f13b276 100644
--- a/arch/arm/boot/dts/pxa27x-lp8x4x.dts
+++ b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
@@ -206,6 +206,14 @@
 			backplane {
 				compatible = "icpdas,backplane-lp8x4x";
 				reg = <0x0 0x2
+				       0x1000 0x10
+				       0x2000 0x10
+				       0x3000 0x10
+				       0x4000 0x10
+				       0x5000 0x10
+				       0x6000 0x10
+				       0x7000 0x10
+				       0x8000 0x10
 				       0x9002 0x2
 				       0x9004 0x2
 				       0x9046 0x2>;
diff --git a/drivers/misc/lp8x4x_bus.c b/drivers/misc/lp8x4x_bus.c
index e805640..59dc767 100644
--- a/drivers/misc/lp8x4x_bus.c
+++ b/drivers/misc/lp8x4x_bus.c
@@ -23,6 +23,13 @@ MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Sergei Ianovich <ynvich@gmail.com>");
 MODULE_DESCRIPTION("ICP DAS LP-8x4x parallel bus driver");
 
+struct lp8x4x_slot {
+	void			*data_addr;
+	unsigned int		model;
+	struct device		dev;
+};
+
+#define LP8X4X_MAX_SLOT_COUNT	8
 struct lp8x4x_master {
 	unsigned int		slot_count;
 	void			*count_addr;
@@ -31,9 +38,45 @@ struct lp8x4x_master {
 	struct gpio_desc        *eeprom_nWE;
 	unsigned int		active_slot;
 	void			*switch_addr;
+	struct lp8x4x_slot	slot[LP8X4X_MAX_SLOT_COUNT];
 	struct device		dev;
 };
 
+static unsigned char lp8x4x_model[256] = {
+	   0,    0,    0, 0x11,    0, 0x18, 0x13, 0x11,
+	0x0e, 0x11,    0,    0,    0, 0x5a, 0x5b, 0x5c,
+	0x3c, 0x44, 0x34, 0x3a, 0x39, 0x36, 0x37, 0x33,
+	0x35, 0x40, 0x41, 0x42, 0x38, 0x3f, 0x32, 0x45,
+	0xac, 0x70, 0x8e, 0x8e, 0x1e, 0x72, 0x90, 0x29,
+	0x4a, 0x22, 0xd3, 0xd2, 0x28, 0x25, 0x2a, 0x29,
+	0x48, 0x49, 0x5d, 0x1f, 0x20, 0x23, 0x24, 0x4d,
+	0x3d, 0x3e,    0,    0,    0,    0,    0,    0,
+	   0, 0x78, 0x72, 0x2b, 0x5e, 0x5e, 0x36, 0xae,
+	0x30,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0, 0x5c, 0x5e,    0, 0x5e,    0,    0,
+	   0, 0x3b,    0,    0,    0,    0,    0,    0,
+	   0, 0x50, 0x2e,    0, 0x58,    0,    0, 0x43,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0, 0x54,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0
+};
+
 static int lp8x4x_match(struct device *dev, struct device_driver *drv)
 {
 	return 1;
@@ -44,6 +87,26 @@ static struct bus_type lp8x4x_bus_type = {
 	.match		= lp8x4x_match,
 };
 
+static void lp8x4x_slot_release(struct device *dev)
+{
+}
+
+static ssize_t model_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct lp8x4x_slot *s = container_of(dev, struct lp8x4x_slot, dev);
+
+	return sprintf(buf, "%u\n", s->model + 8000);
+}
+
+static DEVICE_ATTR_RO(model);
+
+static struct attribute *slot_dev_attrs[] = {
+	&dev_attr_model.attr,
+	NULL,
+};
+ATTRIBUTE_GROUPS(slot_dev);
+
 static void lp8x4x_master_release(struct device *dev)
 {
 	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
@@ -173,18 +236,50 @@ ATTRIBUTE_GROUPS(master_dev);
 static void devm_lp8x4x_bus_release(struct device *dev, void *res)
 {
 	struct lp8x4x_master *m = *(struct lp8x4x_master **)res;
+	struct lp8x4x_slot *s;
+	int i;
 
 	dev_dbg(dev, "releasing devices\n");
+	for (i = 0; i < LP8X4X_MAX_SLOT_COUNT; i++) {
+		s = &m->slot[i];
+		if (s->model)
+			device_unregister(&s->dev);
+	}
 	device_unregister(&m->dev);
 	bus_unregister(&lp8x4x_bus_type);
 }
 
+static void __init lp8x4x_bus_probe_slot(struct lp8x4x_master *m, int i,
+		unsigned char model)
+{
+	struct lp8x4x_slot *s = &m->slot[i];
+	int err;
+
+	dev_info(&m->dev, "found %u in slot %i\n", 8000 + model, i + 1);
+
+	s->dev.bus = &lp8x4x_bus_type;
+	dev_set_name(&s->dev, "slot%02i", i + 1);
+	s->dev.parent = &m->dev;
+	s->dev.release = lp8x4x_slot_release;
+	s->dev.groups = slot_dev_groups;
+	s->model = model;
+
+	err = device_register(&s->dev);
+	if (err < 0) {
+		dev_err(&s->dev, "failed to register device\n");
+		s->model = 0;
+		return;
+	}
+}
+
 static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 {
 	struct lp8x4x_master *m, **p;
 	struct resource *res;
 	int r = 0;
+	int i;
 	int err = 0;
+	unsigned int model;
 
 	m = kzalloc(sizeof(*m), GFP_KERNEL);
 	if (!m)
@@ -211,6 +306,23 @@ static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 		goto err_free;
 	}
 
+	for (i = 0; i < LP8X4X_MAX_SLOT_COUNT; i++) {
+		res = platform_get_resource(pdev, IORESOURCE_MEM, r++);
+		if (!res) {
+			dev_err(&pdev->dev, "Failed to get slot %i address\n",
+					i);
+			err = -ENODEV;
+			goto err_free;
+		}
+
+		m->slot[i].data_addr = devm_ioremap_resource(&pdev->dev, res);
+		if (IS_ERR(m->slot[i].data_addr)) {
+			dev_err(&pdev->dev, "Failed to ioremap slot %i\n", i);
+			err = PTR_ERR(m->slot[i].data_addr);
+			goto err_free;
+		}
+	}
+
 	res = platform_get_resource(pdev, IORESOURCE_MEM, r++);
 	if (!res) {
 		dev_err(&pdev->dev, "Failed to get DIP switch address\n");
@@ -305,6 +417,13 @@ static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 	}
 
 	devres_add(&pdev->dev, p);
+	for (i = 0; i < LP8X4X_MAX_SLOT_COUNT; i++) {
+		model = lp8x4x_model[ioread8(m->slot[i].data_addr)];
+		if (!model)
+			continue;
+
+		lp8x4x_bus_probe_slot(m, i, model);
+	}
 	return 0;
 
 err_bus:
-- 
1.8.4.2


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

* [PATCH v3 18/21] misc: support for parallel slots in LP-8x4x
@ 2013-12-17 19:37             ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-17 19:37 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Rob Landley, Russell King,
	Arnd Bergmann, Greg Kroah-Hartman, open list:OPEN FIRMWARE AND...,
	open list:DOCUMENTATION

This patch enumerates parallel modules in expansion slots and exposes
model numbers via sysfs.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
   v2..v3
   * no changes (except number 13/16 -> 18/21)

   v0..v2
   * use device tree
   * use devm helpers where possible

 .../devicetree/bindings/misc/lp8x4x-bus.txt        |   9 ++
 Documentation/misc-devices/lp8x4x_bus.txt          |   8 ++
 arch/arm/boot/dts/pxa27x-lp8x4x.dts                |   8 ++
 drivers/misc/lp8x4x_bus.c                          | 119 +++++++++++++++++++++
 4 files changed, 144 insertions(+)

diff --git a/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt b/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
index 24a8c62..75ac3b2 100644
--- a/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
+++ b/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
@@ -7,6 +7,7 @@ Required properties:
 
 - reg: physical base addresses and region lengths of
        * the rotary switch
+       * 8 plugable industrial IO slots
        * the 8bit DIP switch
        * the serial slot select register
        * the slot count register
@@ -18,6 +19,14 @@ Example:
 	backplane {
 		compatible = "icpdas,backplane-lp8x4x";
 		reg = <0x0 0x2
+		       0x1000 0x10
+		       0x2000 0x10
+		       0x3000 0x10
+		       0x4000 0x10
+		       0x5000 0x10
+		       0x6000 0x10
+		       0x7000 0x10
+		       0x8000 0x10
 		       0x9002 0x2
 		       0x9004 0x2
 		       0x9046 0x2>;
diff --git a/Documentation/misc-devices/lp8x4x_bus.txt b/Documentation/misc-devices/lp8x4x_bus.txt
index 7b86797..09380fd 100644
--- a/Documentation/misc-devices/lp8x4x_bus.txt
+++ b/Documentation/misc-devices/lp8x4x_bus.txt
@@ -28,6 +28,9 @@ into the device, they could be accessed using the 2nd PXA built-in UART port
 (/dev/ttyS1). However, it seems that addresses are not processed by
 the modules. So the parallel bus needs to select which slot is connected.
 
+Parallel modules allow much faster communication. There are accessed using
+IO memory through the FPGA. Their ports are exposed via sysfs.
+
 SYSFS
 -----
 
@@ -50,3 +53,8 @@ rotary
 
 slot_count
 	RO - shows total number of expansion slots on the device
+
+/sys/bus/icpdas/devices/slot%02i:
+
+model
+	RO - shows expansion module model number
diff --git a/arch/arm/boot/dts/pxa27x-lp8x4x.dts b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
index a6adf45..f13b276 100644
--- a/arch/arm/boot/dts/pxa27x-lp8x4x.dts
+++ b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
@@ -206,6 +206,14 @@
 			backplane {
 				compatible = "icpdas,backplane-lp8x4x";
 				reg = <0x0 0x2
+				       0x1000 0x10
+				       0x2000 0x10
+				       0x3000 0x10
+				       0x4000 0x10
+				       0x5000 0x10
+				       0x6000 0x10
+				       0x7000 0x10
+				       0x8000 0x10
 				       0x9002 0x2
 				       0x9004 0x2
 				       0x9046 0x2>;
diff --git a/drivers/misc/lp8x4x_bus.c b/drivers/misc/lp8x4x_bus.c
index e805640..59dc767 100644
--- a/drivers/misc/lp8x4x_bus.c
+++ b/drivers/misc/lp8x4x_bus.c
@@ -23,6 +23,13 @@ MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Sergei Ianovich <ynvich@gmail.com>");
 MODULE_DESCRIPTION("ICP DAS LP-8x4x parallel bus driver");
 
+struct lp8x4x_slot {
+	void			*data_addr;
+	unsigned int		model;
+	struct device		dev;
+};
+
+#define LP8X4X_MAX_SLOT_COUNT	8
 struct lp8x4x_master {
 	unsigned int		slot_count;
 	void			*count_addr;
@@ -31,9 +38,45 @@ struct lp8x4x_master {
 	struct gpio_desc        *eeprom_nWE;
 	unsigned int		active_slot;
 	void			*switch_addr;
+	struct lp8x4x_slot	slot[LP8X4X_MAX_SLOT_COUNT];
 	struct device		dev;
 };
 
+static unsigned char lp8x4x_model[256] = {
+	   0,    0,    0, 0x11,    0, 0x18, 0x13, 0x11,
+	0x0e, 0x11,    0,    0,    0, 0x5a, 0x5b, 0x5c,
+	0x3c, 0x44, 0x34, 0x3a, 0x39, 0x36, 0x37, 0x33,
+	0x35, 0x40, 0x41, 0x42, 0x38, 0x3f, 0x32, 0x45,
+	0xac, 0x70, 0x8e, 0x8e, 0x1e, 0x72, 0x90, 0x29,
+	0x4a, 0x22, 0xd3, 0xd2, 0x28, 0x25, 0x2a, 0x29,
+	0x48, 0x49, 0x5d, 0x1f, 0x20, 0x23, 0x24, 0x4d,
+	0x3d, 0x3e,    0,    0,    0,    0,    0,    0,
+	   0, 0x78, 0x72, 0x2b, 0x5e, 0x5e, 0x36, 0xae,
+	0x30,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0, 0x5c, 0x5e,    0, 0x5e,    0,    0,
+	   0, 0x3b,    0,    0,    0,    0,    0,    0,
+	   0, 0x50, 0x2e,    0, 0x58,    0,    0, 0x43,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0, 0x54,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0
+};
+
 static int lp8x4x_match(struct device *dev, struct device_driver *drv)
 {
 	return 1;
@@ -44,6 +87,26 @@ static struct bus_type lp8x4x_bus_type = {
 	.match		= lp8x4x_match,
 };
 
+static void lp8x4x_slot_release(struct device *dev)
+{
+}
+
+static ssize_t model_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct lp8x4x_slot *s = container_of(dev, struct lp8x4x_slot, dev);
+
+	return sprintf(buf, "%u\n", s->model + 8000);
+}
+
+static DEVICE_ATTR_RO(model);
+
+static struct attribute *slot_dev_attrs[] = {
+	&dev_attr_model.attr,
+	NULL,
+};
+ATTRIBUTE_GROUPS(slot_dev);
+
 static void lp8x4x_master_release(struct device *dev)
 {
 	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
@@ -173,18 +236,50 @@ ATTRIBUTE_GROUPS(master_dev);
 static void devm_lp8x4x_bus_release(struct device *dev, void *res)
 {
 	struct lp8x4x_master *m = *(struct lp8x4x_master **)res;
+	struct lp8x4x_slot *s;
+	int i;
 
 	dev_dbg(dev, "releasing devices\n");
+	for (i = 0; i < LP8X4X_MAX_SLOT_COUNT; i++) {
+		s = &m->slot[i];
+		if (s->model)
+			device_unregister(&s->dev);
+	}
 	device_unregister(&m->dev);
 	bus_unregister(&lp8x4x_bus_type);
 }
 
+static void __init lp8x4x_bus_probe_slot(struct lp8x4x_master *m, int i,
+		unsigned char model)
+{
+	struct lp8x4x_slot *s = &m->slot[i];
+	int err;
+
+	dev_info(&m->dev, "found %u in slot %i\n", 8000 + model, i + 1);
+
+	s->dev.bus = &lp8x4x_bus_type;
+	dev_set_name(&s->dev, "slot%02i", i + 1);
+	s->dev.parent = &m->dev;
+	s->dev.release = lp8x4x_slot_release;
+	s->dev.groups = slot_dev_groups;
+	s->model = model;
+
+	err = device_register(&s->dev);
+	if (err < 0) {
+		dev_err(&s->dev, "failed to register device\n");
+		s->model = 0;
+		return;
+	}
+}
+
 static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 {
 	struct lp8x4x_master *m, **p;
 	struct resource *res;
 	int r = 0;
+	int i;
 	int err = 0;
+	unsigned int model;
 
 	m = kzalloc(sizeof(*m), GFP_KERNEL);
 	if (!m)
@@ -211,6 +306,23 @@ static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 		goto err_free;
 	}
 
+	for (i = 0; i < LP8X4X_MAX_SLOT_COUNT; i++) {
+		res = platform_get_resource(pdev, IORESOURCE_MEM, r++);
+		if (!res) {
+			dev_err(&pdev->dev, "Failed to get slot %i address\n",
+					i);
+			err = -ENODEV;
+			goto err_free;
+		}
+
+		m->slot[i].data_addr = devm_ioremap_resource(&pdev->dev, res);
+		if (IS_ERR(m->slot[i].data_addr)) {
+			dev_err(&pdev->dev, "Failed to ioremap slot %i\n", i);
+			err = PTR_ERR(m->slot[i].data_addr);
+			goto err_free;
+		}
+	}
+
 	res = platform_get_resource(pdev, IORESOURCE_MEM, r++);
 	if (!res) {
 		dev_err(&pdev->dev, "Failed to get DIP switch address\n");
@@ -305,6 +417,13 @@ static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 	}
 
 	devres_add(&pdev->dev, p);
+	for (i = 0; i < LP8X4X_MAX_SLOT_COUNT; i++) {
+		model = lp8x4x_model[ioread8(m->slot[i].data_addr)];
+		if (!model)
+			continue;
+
+		lp8x4x_bus_probe_slot(m, i, model);
+	}
 	return 0;
 
 err_bus:
-- 
1.8.4.2

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

* [PATCH v3 18/21] misc: support for parallel slots in LP-8x4x
@ 2013-12-17 19:37             ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-17 19:37 UTC (permalink / raw)
  To: linux-arm-kernel

This patch enumerates parallel modules in expansion slots and exposes
model numbers via sysfs.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
   v2..v3
   * no changes (except number 13/16 -> 18/21)

   v0..v2
   * use device tree
   * use devm helpers where possible

 .../devicetree/bindings/misc/lp8x4x-bus.txt        |   9 ++
 Documentation/misc-devices/lp8x4x_bus.txt          |   8 ++
 arch/arm/boot/dts/pxa27x-lp8x4x.dts                |   8 ++
 drivers/misc/lp8x4x_bus.c                          | 119 +++++++++++++++++++++
 4 files changed, 144 insertions(+)

diff --git a/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt b/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
index 24a8c62..75ac3b2 100644
--- a/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
+++ b/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
@@ -7,6 +7,7 @@ Required properties:
 
 - reg: physical base addresses and region lengths of
        * the rotary switch
+       * 8 plugable industrial IO slots
        * the 8bit DIP switch
        * the serial slot select register
        * the slot count register
@@ -18,6 +19,14 @@ Example:
 	backplane {
 		compatible = "icpdas,backplane-lp8x4x";
 		reg = <0x0 0x2
+		       0x1000 0x10
+		       0x2000 0x10
+		       0x3000 0x10
+		       0x4000 0x10
+		       0x5000 0x10
+		       0x6000 0x10
+		       0x7000 0x10
+		       0x8000 0x10
 		       0x9002 0x2
 		       0x9004 0x2
 		       0x9046 0x2>;
diff --git a/Documentation/misc-devices/lp8x4x_bus.txt b/Documentation/misc-devices/lp8x4x_bus.txt
index 7b86797..09380fd 100644
--- a/Documentation/misc-devices/lp8x4x_bus.txt
+++ b/Documentation/misc-devices/lp8x4x_bus.txt
@@ -28,6 +28,9 @@ into the device, they could be accessed using the 2nd PXA built-in UART port
 (/dev/ttyS1). However, it seems that addresses are not processed by
 the modules. So the parallel bus needs to select which slot is connected.
 
+Parallel modules allow much faster communication. There are accessed using
+IO memory through the FPGA. Their ports are exposed via sysfs.
+
 SYSFS
 -----
 
@@ -50,3 +53,8 @@ rotary
 
 slot_count
 	RO - shows total number of expansion slots on the device
+
+/sys/bus/icpdas/devices/slot%02i:
+
+model
+	RO - shows expansion module model number
diff --git a/arch/arm/boot/dts/pxa27x-lp8x4x.dts b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
index a6adf45..f13b276 100644
--- a/arch/arm/boot/dts/pxa27x-lp8x4x.dts
+++ b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
@@ -206,6 +206,14 @@
 			backplane {
 				compatible = "icpdas,backplane-lp8x4x";
 				reg = <0x0 0x2
+				       0x1000 0x10
+				       0x2000 0x10
+				       0x3000 0x10
+				       0x4000 0x10
+				       0x5000 0x10
+				       0x6000 0x10
+				       0x7000 0x10
+				       0x8000 0x10
 				       0x9002 0x2
 				       0x9004 0x2
 				       0x9046 0x2>;
diff --git a/drivers/misc/lp8x4x_bus.c b/drivers/misc/lp8x4x_bus.c
index e805640..59dc767 100644
--- a/drivers/misc/lp8x4x_bus.c
+++ b/drivers/misc/lp8x4x_bus.c
@@ -23,6 +23,13 @@ MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Sergei Ianovich <ynvich@gmail.com>");
 MODULE_DESCRIPTION("ICP DAS LP-8x4x parallel bus driver");
 
+struct lp8x4x_slot {
+	void			*data_addr;
+	unsigned int		model;
+	struct device		dev;
+};
+
+#define LP8X4X_MAX_SLOT_COUNT	8
 struct lp8x4x_master {
 	unsigned int		slot_count;
 	void			*count_addr;
@@ -31,9 +38,45 @@ struct lp8x4x_master {
 	struct gpio_desc        *eeprom_nWE;
 	unsigned int		active_slot;
 	void			*switch_addr;
+	struct lp8x4x_slot	slot[LP8X4X_MAX_SLOT_COUNT];
 	struct device		dev;
 };
 
+static unsigned char lp8x4x_model[256] = {
+	   0,    0,    0, 0x11,    0, 0x18, 0x13, 0x11,
+	0x0e, 0x11,    0,    0,    0, 0x5a, 0x5b, 0x5c,
+	0x3c, 0x44, 0x34, 0x3a, 0x39, 0x36, 0x37, 0x33,
+	0x35, 0x40, 0x41, 0x42, 0x38, 0x3f, 0x32, 0x45,
+	0xac, 0x70, 0x8e, 0x8e, 0x1e, 0x72, 0x90, 0x29,
+	0x4a, 0x22, 0xd3, 0xd2, 0x28, 0x25, 0x2a, 0x29,
+	0x48, 0x49, 0x5d, 0x1f, 0x20, 0x23, 0x24, 0x4d,
+	0x3d, 0x3e,    0,    0,    0,    0,    0,    0,
+	   0, 0x78, 0x72, 0x2b, 0x5e, 0x5e, 0x36, 0xae,
+	0x30,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0, 0x5c, 0x5e,    0, 0x5e,    0,    0,
+	   0, 0x3b,    0,    0,    0,    0,    0,    0,
+	   0, 0x50, 0x2e,    0, 0x58,    0,    0, 0x43,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0, 0x54,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0
+};
+
 static int lp8x4x_match(struct device *dev, struct device_driver *drv)
 {
 	return 1;
@@ -44,6 +87,26 @@ static struct bus_type lp8x4x_bus_type = {
 	.match		= lp8x4x_match,
 };
 
+static void lp8x4x_slot_release(struct device *dev)
+{
+}
+
+static ssize_t model_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct lp8x4x_slot *s = container_of(dev, struct lp8x4x_slot, dev);
+
+	return sprintf(buf, "%u\n", s->model + 8000);
+}
+
+static DEVICE_ATTR_RO(model);
+
+static struct attribute *slot_dev_attrs[] = {
+	&dev_attr_model.attr,
+	NULL,
+};
+ATTRIBUTE_GROUPS(slot_dev);
+
 static void lp8x4x_master_release(struct device *dev)
 {
 	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
@@ -173,18 +236,50 @@ ATTRIBUTE_GROUPS(master_dev);
 static void devm_lp8x4x_bus_release(struct device *dev, void *res)
 {
 	struct lp8x4x_master *m = *(struct lp8x4x_master **)res;
+	struct lp8x4x_slot *s;
+	int i;
 
 	dev_dbg(dev, "releasing devices\n");
+	for (i = 0; i < LP8X4X_MAX_SLOT_COUNT; i++) {
+		s = &m->slot[i];
+		if (s->model)
+			device_unregister(&s->dev);
+	}
 	device_unregister(&m->dev);
 	bus_unregister(&lp8x4x_bus_type);
 }
 
+static void __init lp8x4x_bus_probe_slot(struct lp8x4x_master *m, int i,
+		unsigned char model)
+{
+	struct lp8x4x_slot *s = &m->slot[i];
+	int err;
+
+	dev_info(&m->dev, "found %u in slot %i\n", 8000 + model, i + 1);
+
+	s->dev.bus = &lp8x4x_bus_type;
+	dev_set_name(&s->dev, "slot%02i", i + 1);
+	s->dev.parent = &m->dev;
+	s->dev.release = lp8x4x_slot_release;
+	s->dev.groups = slot_dev_groups;
+	s->model = model;
+
+	err = device_register(&s->dev);
+	if (err < 0) {
+		dev_err(&s->dev, "failed to register device\n");
+		s->model = 0;
+		return;
+	}
+}
+
 static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 {
 	struct lp8x4x_master *m, **p;
 	struct resource *res;
 	int r = 0;
+	int i;
 	int err = 0;
+	unsigned int model;
 
 	m = kzalloc(sizeof(*m), GFP_KERNEL);
 	if (!m)
@@ -211,6 +306,23 @@ static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 		goto err_free;
 	}
 
+	for (i = 0; i < LP8X4X_MAX_SLOT_COUNT; i++) {
+		res = platform_get_resource(pdev, IORESOURCE_MEM, r++);
+		if (!res) {
+			dev_err(&pdev->dev, "Failed to get slot %i address\n",
+					i);
+			err = -ENODEV;
+			goto err_free;
+		}
+
+		m->slot[i].data_addr = devm_ioremap_resource(&pdev->dev, res);
+		if (IS_ERR(m->slot[i].data_addr)) {
+			dev_err(&pdev->dev, "Failed to ioremap slot %i\n", i);
+			err = PTR_ERR(m->slot[i].data_addr);
+			goto err_free;
+		}
+	}
+
 	res = platform_get_resource(pdev, IORESOURCE_MEM, r++);
 	if (!res) {
 		dev_err(&pdev->dev, "Failed to get DIP switch address\n");
@@ -305,6 +417,13 @@ static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 	}
 
 	devres_add(&pdev->dev, p);
+	for (i = 0; i < LP8X4X_MAX_SLOT_COUNT; i++) {
+		model = lp8x4x_model[ioread8(m->slot[i].data_addr)];
+		if (!model)
+			continue;
+
+		lp8x4x_bus_probe_slot(m, i, model);
+	}
 	return 0;
 
 err_bus:
-- 
1.8.4.2

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

* [PATCH v3 19/21] misc: support for I-8041 in LP-8x4x
  2013-12-17 19:37           ` Sergei Ianovich
@ 2013-12-17 19:37             ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-17 19:37 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Rob Landley, Arnd Bergmann, Greg Kroah-Hartman,
	open list:DOCUMENTATION

Status of I-8041 32 digital output channels can be managed via
sysfs now.

http://www.icpdas.com/products/Remote_IO/i-8ke/i-8041w.htm

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
   v2..v3
   v0..v2
   * no changes (except number 14/16 -> 19/21)

 Documentation/misc-devices/lp8x4x_bus.txt |  4 ++
 drivers/misc/lp8x4x_bus.c                 | 67 ++++++++++++++++++++++++++++++-
 2 files changed, 69 insertions(+), 2 deletions(-)

diff --git a/Documentation/misc-devices/lp8x4x_bus.txt b/Documentation/misc-devices/lp8x4x_bus.txt
index 09380fd..68fefde 100644
--- a/Documentation/misc-devices/lp8x4x_bus.txt
+++ b/Documentation/misc-devices/lp8x4x_bus.txt
@@ -58,3 +58,7 @@ slot_count
 
 model
 	RO - shows expansion module model number
+
+output_status
+	RW - set status of digital output channels on the module in
+	     the expansion slot. Value can be read back.
diff --git a/drivers/misc/lp8x4x_bus.c b/drivers/misc/lp8x4x_bus.c
index 59dc767..5af788d 100644
--- a/drivers/misc/lp8x4x_bus.c
+++ b/drivers/misc/lp8x4x_bus.c
@@ -26,6 +26,9 @@ MODULE_DESCRIPTION("ICP DAS LP-8x4x parallel bus driver");
 struct lp8x4x_slot {
 	void			*data_addr;
 	unsigned int		model;
+	struct mutex		lock;
+	unsigned int		DO_len;
+	u32			DO;
 	struct device		dev;
 };
 
@@ -91,6 +94,45 @@ static void lp8x4x_slot_release(struct device *dev)
 {
 }
 
+static void lp8x4x_slot_set_DO(struct lp8x4x_slot *s)
+{
+	int i;
+	mutex_lock(&s->lock);
+	for (i = 0; i < s->DO_len; i++)
+		iowrite8((s->DO >> (i * 8)) & 0xff, s->data_addr + 2 * i);
+	mutex_unlock(&s->lock);
+}
+
+static ssize_t output_status_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct lp8x4x_slot *s = container_of(dev, struct lp8x4x_slot, dev);
+
+	return sprintf(buf, "0x%08x\n", s->DO);
+}
+
+static ssize_t output_status_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct lp8x4x_slot *s = container_of(dev, struct lp8x4x_slot, dev);
+
+	if (!buf)
+		return count;
+	if (0 == count)
+		return count;
+
+	if (kstrtouint(buf, 16, &s->DO) != 0) {
+		dev_err(dev, "bad input\n");
+		return count;
+	}
+
+	lp8x4x_slot_set_DO(s);
+
+	return count;
+}
+
+static DEVICE_ATTR_RW(output_status);
+
 static ssize_t model_show(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
@@ -107,6 +149,13 @@ static struct attribute *slot_dev_attrs[] = {
 };
 ATTRIBUTE_GROUPS(slot_dev);
 
+static struct attribute *do_slot_dev_attrs[] = {
+	&dev_attr_model.attr,
+	&dev_attr_output_status.attr,
+	NULL,
+};
+ATTRIBUTE_GROUPS(do_slot_dev);
+
 static void lp8x4x_master_release(struct device *dev)
 {
 	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
@@ -242,8 +291,10 @@ static void devm_lp8x4x_bus_release(struct device *dev, void *res)
 	dev_dbg(dev, "releasing devices\n");
 	for (i = 0; i < LP8X4X_MAX_SLOT_COUNT; i++) {
 		s = &m->slot[i];
-		if (s->model)
+		if (s->model) {
 			device_unregister(&s->dev);
+			mutex_destroy(&s->lock);
+		}
 	}
 	device_unregister(&m->dev);
 	bus_unregister(&lp8x4x_bus_type);
@@ -261,13 +312,25 @@ static void __init lp8x4x_bus_probe_slot(struct lp8x4x_master *m, int i,
 	dev_set_name(&s->dev, "slot%02i", i + 1);
 	s->dev.parent = &m->dev;
 	s->dev.release = lp8x4x_slot_release;
-	s->dev.groups = slot_dev_groups;
 	s->model = model;
+	mutex_init(&s->lock);
+
+	switch (model) {
+	case 41:
+		s->DO_len = 4;
+		lp8x4x_slot_set_DO(s);
+		s->dev.groups = do_slot_dev_groups;
+		break;
+	default:
+		s->dev.groups = slot_dev_groups;
+		break;
+	};
 
 	err = device_register(&s->dev);
 	if (err < 0) {
 		dev_err(&s->dev, "failed to register device\n");
 		s->model = 0;
+		mutex_destroy(&s->lock);
 		return;
 	}
 }
-- 
1.8.4.2


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

* [PATCH v3 19/21] misc: support for I-8041 in LP-8x4x
@ 2013-12-17 19:37             ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-17 19:37 UTC (permalink / raw)
  To: linux-arm-kernel

Status of I-8041 32 digital output channels can be managed via
sysfs now.

http://www.icpdas.com/products/Remote_IO/i-8ke/i-8041w.htm

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
   v2..v3
   v0..v2
   * no changes (except number 14/16 -> 19/21)

 Documentation/misc-devices/lp8x4x_bus.txt |  4 ++
 drivers/misc/lp8x4x_bus.c                 | 67 ++++++++++++++++++++++++++++++-
 2 files changed, 69 insertions(+), 2 deletions(-)

diff --git a/Documentation/misc-devices/lp8x4x_bus.txt b/Documentation/misc-devices/lp8x4x_bus.txt
index 09380fd..68fefde 100644
--- a/Documentation/misc-devices/lp8x4x_bus.txt
+++ b/Documentation/misc-devices/lp8x4x_bus.txt
@@ -58,3 +58,7 @@ slot_count
 
 model
 	RO - shows expansion module model number
+
+output_status
+	RW - set status of digital output channels on the module in
+	     the expansion slot. Value can be read back.
diff --git a/drivers/misc/lp8x4x_bus.c b/drivers/misc/lp8x4x_bus.c
index 59dc767..5af788d 100644
--- a/drivers/misc/lp8x4x_bus.c
+++ b/drivers/misc/lp8x4x_bus.c
@@ -26,6 +26,9 @@ MODULE_DESCRIPTION("ICP DAS LP-8x4x parallel bus driver");
 struct lp8x4x_slot {
 	void			*data_addr;
 	unsigned int		model;
+	struct mutex		lock;
+	unsigned int		DO_len;
+	u32			DO;
 	struct device		dev;
 };
 
@@ -91,6 +94,45 @@ static void lp8x4x_slot_release(struct device *dev)
 {
 }
 
+static void lp8x4x_slot_set_DO(struct lp8x4x_slot *s)
+{
+	int i;
+	mutex_lock(&s->lock);
+	for (i = 0; i < s->DO_len; i++)
+		iowrite8((s->DO >> (i * 8)) & 0xff, s->data_addr + 2 * i);
+	mutex_unlock(&s->lock);
+}
+
+static ssize_t output_status_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct lp8x4x_slot *s = container_of(dev, struct lp8x4x_slot, dev);
+
+	return sprintf(buf, "0x%08x\n", s->DO);
+}
+
+static ssize_t output_status_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct lp8x4x_slot *s = container_of(dev, struct lp8x4x_slot, dev);
+
+	if (!buf)
+		return count;
+	if (0 == count)
+		return count;
+
+	if (kstrtouint(buf, 16, &s->DO) != 0) {
+		dev_err(dev, "bad input\n");
+		return count;
+	}
+
+	lp8x4x_slot_set_DO(s);
+
+	return count;
+}
+
+static DEVICE_ATTR_RW(output_status);
+
 static ssize_t model_show(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
@@ -107,6 +149,13 @@ static struct attribute *slot_dev_attrs[] = {
 };
 ATTRIBUTE_GROUPS(slot_dev);
 
+static struct attribute *do_slot_dev_attrs[] = {
+	&dev_attr_model.attr,
+	&dev_attr_output_status.attr,
+	NULL,
+};
+ATTRIBUTE_GROUPS(do_slot_dev);
+
 static void lp8x4x_master_release(struct device *dev)
 {
 	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
@@ -242,8 +291,10 @@ static void devm_lp8x4x_bus_release(struct device *dev, void *res)
 	dev_dbg(dev, "releasing devices\n");
 	for (i = 0; i < LP8X4X_MAX_SLOT_COUNT; i++) {
 		s = &m->slot[i];
-		if (s->model)
+		if (s->model) {
 			device_unregister(&s->dev);
+			mutex_destroy(&s->lock);
+		}
 	}
 	device_unregister(&m->dev);
 	bus_unregister(&lp8x4x_bus_type);
@@ -261,13 +312,25 @@ static void __init lp8x4x_bus_probe_slot(struct lp8x4x_master *m, int i,
 	dev_set_name(&s->dev, "slot%02i", i + 1);
 	s->dev.parent = &m->dev;
 	s->dev.release = lp8x4x_slot_release;
-	s->dev.groups = slot_dev_groups;
 	s->model = model;
+	mutex_init(&s->lock);
+
+	switch (model) {
+	case 41:
+		s->DO_len = 4;
+		lp8x4x_slot_set_DO(s);
+		s->dev.groups = do_slot_dev_groups;
+		break;
+	default:
+		s->dev.groups = slot_dev_groups;
+		break;
+	};
 
 	err = device_register(&s->dev);
 	if (err < 0) {
 		dev_err(&s->dev, "failed to register device\n");
 		s->model = 0;
+		mutex_destroy(&s->lock);
 		return;
 	}
 }
-- 
1.8.4.2

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

* [PATCH v3 20/21] misc: support for I-8042 in LP-8x4x
  2013-12-17 19:37           ` Sergei Ianovich
@ 2013-12-17 19:37             ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-17 19:37 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Rob Landley, Arnd Bergmann, Greg Kroah-Hartman,
	open list:DOCUMENTATION

Status of I-8042 16 digital output channels can be managed via
sysfs.

Status of I-8042 16 digital input channels can be read via sysfs.

http://www.icpdas.com/products/Remote_IO/i-8ke/i-8042w.htm

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
   v2..v3
   v0..v2
   * no changes (except number 15/16 -> 20/21)

 Documentation/misc-devices/lp8x4x_bus.txt |  4 ++
 drivers/misc/lp8x4x_bus.c                 | 76 ++++++++++++++++++++++++++++++-
 2 files changed, 78 insertions(+), 2 deletions(-)

diff --git a/Documentation/misc-devices/lp8x4x_bus.txt b/Documentation/misc-devices/lp8x4x_bus.txt
index 68fefde..3ea257d 100644
--- a/Documentation/misc-devices/lp8x4x_bus.txt
+++ b/Documentation/misc-devices/lp8x4x_bus.txt
@@ -59,6 +59,10 @@ slot_count
 model
 	RO - shows expansion module model number
 
+input_status
+	RO - get status of digital input channels on the module in
+	     the expansion slot.
+
 output_status
 	RW - set status of digital output channels on the module in
 	     the expansion slot. Value can be read back.
diff --git a/drivers/misc/lp8x4x_bus.c b/drivers/misc/lp8x4x_bus.c
index 5af788d..3fb227d 100644
--- a/drivers/misc/lp8x4x_bus.c
+++ b/drivers/misc/lp8x4x_bus.c
@@ -29,6 +29,8 @@ struct lp8x4x_slot {
 	struct mutex		lock;
 	unsigned int		DO_len;
 	u32			DO;
+	unsigned int		DI_len;
+	u32			DI;
 	struct device		dev;
 };
 
@@ -94,6 +96,21 @@ static void lp8x4x_slot_release(struct device *dev)
 {
 }
 
+static void lp8x4x_slot_get_DI(struct lp8x4x_slot *s)
+{
+	int i;
+	u32 b;
+
+	mutex_lock(&s->lock);
+	s->DI = 0;
+	for (i = 0; i < s->DI_len; i++) {
+		b = ioread8(s->data_addr + 2 * (i + 1));
+		b ^= 0xff;
+		s->DI += b << (i * 8);
+	}
+	mutex_unlock(&s->lock);
+}
+
 static void lp8x4x_slot_set_DO(struct lp8x4x_slot *s)
 {
 	int i;
@@ -103,29 +120,70 @@ static void lp8x4x_slot_set_DO(struct lp8x4x_slot *s)
 	mutex_unlock(&s->lock);
 }
 
+static ssize_t input_status_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct lp8x4x_slot *s = container_of(dev, struct lp8x4x_slot, dev);
+
+	lp8x4x_slot_get_DI(s);
+	switch (s->DI_len) {
+	case 4:
+		return sprintf(buf, "0x%08x\n", s->DI);
+	case 2:
+		return sprintf(buf, "0x%04x\n", s->DI);
+	case 1:
+		return sprintf(buf, "0x%02x\n", s->DI);
+	default:
+		break;
+	}
+	return sprintf(buf, "0x%x\n", s->DI);
+}
+
+static DEVICE_ATTR_RO(input_status);
+
 static ssize_t output_status_show(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
 	struct lp8x4x_slot *s = container_of(dev, struct lp8x4x_slot, dev);
 
-	return sprintf(buf, "0x%08x\n", s->DO);
+	switch (s->DO_len) {
+	case 4:
+		return sprintf(buf, "0x%08x\n", s->DO);
+	case 2:
+		return sprintf(buf, "0x%04x\n", s->DO);
+	case 1:
+		return sprintf(buf, "0x%02x\n", s->DO);
+	default:
+		break;
+	}
+	return sprintf(buf, "0x%x\n", s->DO);
 }
 
 static ssize_t output_status_store(struct device *dev,
 		struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct lp8x4x_slot *s = container_of(dev, struct lp8x4x_slot, dev);
+	u32 DO;
+	u8 *b = (void *) &DO;
+	int i;
 
 	if (!buf)
 		return count;
 	if (0 == count)
 		return count;
 
-	if (kstrtouint(buf, 16, &s->DO) != 0) {
+	if (kstrtouint(buf, 16, &DO) != 0) {
 		dev_err(dev, "bad input\n");
 		return count;
 	}
 
+	for (i = 4; i > s->DO_len; i--)
+		if (b[i - 1] != 0) {
+			dev_err(dev, "bad input\n");
+			return count;
+		}
+
+	s->DO = DO;
 	lp8x4x_slot_set_DO(s);
 
 	return count;
@@ -156,6 +214,14 @@ static struct attribute *do_slot_dev_attrs[] = {
 };
 ATTRIBUTE_GROUPS(do_slot_dev);
 
+static struct attribute *dio_slot_dev_attrs[] = {
+	&dev_attr_model.attr,
+	&dev_attr_output_status.attr,
+	&dev_attr_input_status.attr,
+	NULL,
+};
+ATTRIBUTE_GROUPS(dio_slot_dev);
+
 static void lp8x4x_master_release(struct device *dev)
 {
 	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
@@ -321,6 +387,12 @@ static void __init lp8x4x_bus_probe_slot(struct lp8x4x_master *m, int i,
 		lp8x4x_slot_set_DO(s);
 		s->dev.groups = do_slot_dev_groups;
 		break;
+	case 42:
+		s->DI_len = 2;
+		s->DO_len = 2;
+		lp8x4x_slot_set_DO(s);
+		s->dev.groups = dio_slot_dev_groups;
+		break;
 	default:
 		s->dev.groups = slot_dev_groups;
 		break;
-- 
1.8.4.2


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

* [PATCH v3 20/21] misc: support for I-8042 in LP-8x4x
@ 2013-12-17 19:37             ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-17 19:37 UTC (permalink / raw)
  To: linux-arm-kernel

Status of I-8042 16 digital output channels can be managed via
sysfs.

Status of I-8042 16 digital input channels can be read via sysfs.

http://www.icpdas.com/products/Remote_IO/i-8ke/i-8042w.htm

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
   v2..v3
   v0..v2
   * no changes (except number 15/16 -> 20/21)

 Documentation/misc-devices/lp8x4x_bus.txt |  4 ++
 drivers/misc/lp8x4x_bus.c                 | 76 ++++++++++++++++++++++++++++++-
 2 files changed, 78 insertions(+), 2 deletions(-)

diff --git a/Documentation/misc-devices/lp8x4x_bus.txt b/Documentation/misc-devices/lp8x4x_bus.txt
index 68fefde..3ea257d 100644
--- a/Documentation/misc-devices/lp8x4x_bus.txt
+++ b/Documentation/misc-devices/lp8x4x_bus.txt
@@ -59,6 +59,10 @@ slot_count
 model
 	RO - shows expansion module model number
 
+input_status
+	RO - get status of digital input channels on the module in
+	     the expansion slot.
+
 output_status
 	RW - set status of digital output channels on the module in
 	     the expansion slot. Value can be read back.
diff --git a/drivers/misc/lp8x4x_bus.c b/drivers/misc/lp8x4x_bus.c
index 5af788d..3fb227d 100644
--- a/drivers/misc/lp8x4x_bus.c
+++ b/drivers/misc/lp8x4x_bus.c
@@ -29,6 +29,8 @@ struct lp8x4x_slot {
 	struct mutex		lock;
 	unsigned int		DO_len;
 	u32			DO;
+	unsigned int		DI_len;
+	u32			DI;
 	struct device		dev;
 };
 
@@ -94,6 +96,21 @@ static void lp8x4x_slot_release(struct device *dev)
 {
 }
 
+static void lp8x4x_slot_get_DI(struct lp8x4x_slot *s)
+{
+	int i;
+	u32 b;
+
+	mutex_lock(&s->lock);
+	s->DI = 0;
+	for (i = 0; i < s->DI_len; i++) {
+		b = ioread8(s->data_addr + 2 * (i + 1));
+		b ^= 0xff;
+		s->DI += b << (i * 8);
+	}
+	mutex_unlock(&s->lock);
+}
+
 static void lp8x4x_slot_set_DO(struct lp8x4x_slot *s)
 {
 	int i;
@@ -103,29 +120,70 @@ static void lp8x4x_slot_set_DO(struct lp8x4x_slot *s)
 	mutex_unlock(&s->lock);
 }
 
+static ssize_t input_status_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct lp8x4x_slot *s = container_of(dev, struct lp8x4x_slot, dev);
+
+	lp8x4x_slot_get_DI(s);
+	switch (s->DI_len) {
+	case 4:
+		return sprintf(buf, "0x%08x\n", s->DI);
+	case 2:
+		return sprintf(buf, "0x%04x\n", s->DI);
+	case 1:
+		return sprintf(buf, "0x%02x\n", s->DI);
+	default:
+		break;
+	}
+	return sprintf(buf, "0x%x\n", s->DI);
+}
+
+static DEVICE_ATTR_RO(input_status);
+
 static ssize_t output_status_show(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
 	struct lp8x4x_slot *s = container_of(dev, struct lp8x4x_slot, dev);
 
-	return sprintf(buf, "0x%08x\n", s->DO);
+	switch (s->DO_len) {
+	case 4:
+		return sprintf(buf, "0x%08x\n", s->DO);
+	case 2:
+		return sprintf(buf, "0x%04x\n", s->DO);
+	case 1:
+		return sprintf(buf, "0x%02x\n", s->DO);
+	default:
+		break;
+	}
+	return sprintf(buf, "0x%x\n", s->DO);
 }
 
 static ssize_t output_status_store(struct device *dev,
 		struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct lp8x4x_slot *s = container_of(dev, struct lp8x4x_slot, dev);
+	u32 DO;
+	u8 *b = (void *) &DO;
+	int i;
 
 	if (!buf)
 		return count;
 	if (0 == count)
 		return count;
 
-	if (kstrtouint(buf, 16, &s->DO) != 0) {
+	if (kstrtouint(buf, 16, &DO) != 0) {
 		dev_err(dev, "bad input\n");
 		return count;
 	}
 
+	for (i = 4; i > s->DO_len; i--)
+		if (b[i - 1] != 0) {
+			dev_err(dev, "bad input\n");
+			return count;
+		}
+
+	s->DO = DO;
 	lp8x4x_slot_set_DO(s);
 
 	return count;
@@ -156,6 +214,14 @@ static struct attribute *do_slot_dev_attrs[] = {
 };
 ATTRIBUTE_GROUPS(do_slot_dev);
 
+static struct attribute *dio_slot_dev_attrs[] = {
+	&dev_attr_model.attr,
+	&dev_attr_output_status.attr,
+	&dev_attr_input_status.attr,
+	NULL,
+};
+ATTRIBUTE_GROUPS(dio_slot_dev);
+
 static void lp8x4x_master_release(struct device *dev)
 {
 	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
@@ -321,6 +387,12 @@ static void __init lp8x4x_bus_probe_slot(struct lp8x4x_master *m, int i,
 		lp8x4x_slot_set_DO(s);
 		s->dev.groups = do_slot_dev_groups;
 		break;
+	case 42:
+		s->DI_len = 2;
+		s->DO_len = 2;
+		lp8x4x_slot_set_DO(s);
+		s->dev.groups = dio_slot_dev_groups;
+		break;
 	default:
 		s->dev.groups = slot_dev_groups;
 		break;
-- 
1.8.4.2

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

* [PATCH v3 21/21] misc: support for I-8024 in LP-8x4x
  2013-12-17 19:37           ` Sergei Ianovich
@ 2013-12-17 19:37             ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-17 19:37 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Rob Landley, Arnd Bergmann, Greg Kroah-Hartman,
	open list:DOCUMENTATION

Status of I-8042 4 analog output channels can be managed via
sysfs.

http://www.icpdas.com/root/product/solutions/remote_io/rs-485/i-8k_i-87k/i-8024w.html

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
   v2..v3
   * use usleep_range instead of custom nsleep
   * number change (16/16 -> 21/21)

   v0..v2
   * no changes

 Documentation/misc-devices/lp8x4x_bus.txt | 15 ++++++
 drivers/misc/lp8x4x_bus.c                 | 78 +++++++++++++++++++++++++++++++
 2 files changed, 93 insertions(+)

diff --git a/Documentation/misc-devices/lp8x4x_bus.txt b/Documentation/misc-devices/lp8x4x_bus.txt
index 3ea257d..6076e01 100644
--- a/Documentation/misc-devices/lp8x4x_bus.txt
+++ b/Documentation/misc-devices/lp8x4x_bus.txt
@@ -66,3 +66,18 @@ input_status
 output_status
 	RW - set status of digital output channels on the module in
 	     the expansion slot. Value can be read back.
+
+analog_output
+	RW - set status of analog output channels on the module in
+	     the expansion slot. Tested with voltage output. Bits 0-13:
+	     0x00c0 is -10.0V
+	     0x2000 is   0.0V
+	     0x3f40 is +10.0V
+
+	     So 1 unit of output is 1.25 mV.
+
+	     Bits 15 and 14 determine which channel to apply the value:
+	     0x0000 is channel 1
+	     0x4000 is channel 2
+	     0x8000 is channel 3
+	     0xc000 is channel 4
diff --git a/drivers/misc/lp8x4x_bus.c b/drivers/misc/lp8x4x_bus.c
index 3fb227d..72cd0b2 100644
--- a/drivers/misc/lp8x4x_bus.c
+++ b/drivers/misc/lp8x4x_bus.c
@@ -8,6 +8,7 @@
  *  it under the terms of the GNU General Public License version 2 as
  *  published by the Free Software Foundation or any later version.
  */
+#include <linux/delay.h>
 #include <linux/err.h>
 #include <linux/gpio/consumer.h>
 #include <linux/init.h>
@@ -23,6 +24,7 @@ MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Sergei Ianovich <ynvich@gmail.com>");
 MODULE_DESCRIPTION("ICP DAS LP-8x4x parallel bus driver");
 
+#define LP8X4X_MAX_AO_CHANNELS	4
 struct lp8x4x_slot {
 	void			*data_addr;
 	unsigned int		model;
@@ -31,6 +33,8 @@ struct lp8x4x_slot {
 	u32			DO;
 	unsigned int		DI_len;
 	u32			DI;
+	unsigned int		AO_len;
+	u32			AO[LP8X4X_MAX_AO_CHANNELS];
 	struct device		dev;
 };
 
@@ -120,6 +124,26 @@ static void lp8x4x_slot_set_DO(struct lp8x4x_slot *s)
 	mutex_unlock(&s->lock);
 }
 
+static void lp8x4x_slot_reset_AO(struct lp8x4x_slot *s)
+{
+	int i;
+	mutex_lock(&s->lock);
+	for (i = 0; i < s->AO_len; i++)
+		s->AO[i] = 0x2000;
+	iowrite8(0x00, s->data_addr);
+	usleep_range(1, 2);
+	iowrite8(0xff, s->data_addr);
+	mutex_unlock(&s->lock);
+}
+
+static void lp8x4x_slot_set_AO(struct lp8x4x_slot *s, u32 val)
+{
+	mutex_lock(&s->lock);
+	iowrite8(val & 0xff, s->data_addr + 2);
+	iowrite8((val >> 8) & 0xff, s->data_addr + 4);
+	mutex_unlock(&s->lock);
+}
+
 static ssize_t input_status_show(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
@@ -191,6 +215,48 @@ static ssize_t output_status_store(struct device *dev,
 
 static DEVICE_ATTR_RW(output_status);
 
+static ssize_t analog_output_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct lp8x4x_slot *s = container_of(dev, struct lp8x4x_slot, dev);
+	int i, c = 0;
+
+	for (i = 0; i < s->AO_len; i++)
+		c += sprintf(&buf[c], "0x%04x\n", s->AO[i]);
+	return c;
+}
+
+static ssize_t analog_output_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct lp8x4x_slot *s = container_of(dev, struct lp8x4x_slot, dev);
+	u32 AO;
+	int i;
+
+	if (!buf)
+		return count;
+	if (0 == count)
+		return count;
+
+	if (kstrtouint(buf, 16, &AO) != 0) {
+		dev_err(dev, "bad input\n");
+		return count;
+	}
+
+	if (AO & 0xffff0000) {
+		dev_err(dev, "bad input\n");
+		return count;
+	}
+
+	i = AO >> 14;
+	s->AO[i] = AO & 0x3fff;
+	lp8x4x_slot_set_AO(s, AO);
+
+	return count;
+}
+
+static DEVICE_ATTR_RW(analog_output);
+
 static ssize_t model_show(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
@@ -222,6 +288,13 @@ static struct attribute *dio_slot_dev_attrs[] = {
 };
 ATTRIBUTE_GROUPS(dio_slot_dev);
 
+static struct attribute *ao_slot_dev_attrs[] = {
+	&dev_attr_model.attr,
+	&dev_attr_analog_output.attr,
+	NULL,
+};
+ATTRIBUTE_GROUPS(ao_slot_dev);
+
 static void lp8x4x_master_release(struct device *dev)
 {
 	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
@@ -382,6 +455,11 @@ static void __init lp8x4x_bus_probe_slot(struct lp8x4x_master *m, int i,
 	mutex_init(&s->lock);
 
 	switch (model) {
+	case 24:
+		s->AO_len = 4;
+		lp8x4x_slot_reset_AO(s);
+		s->dev.groups = ao_slot_dev_groups;
+		break;
 	case 41:
 		s->DO_len = 4;
 		lp8x4x_slot_set_DO(s);
-- 
1.8.4.2


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

* [PATCH v3 21/21] misc: support for I-8024 in LP-8x4x
@ 2013-12-17 19:37             ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-17 19:37 UTC (permalink / raw)
  To: linux-arm-kernel

Status of I-8042 4 analog output channels can be managed via
sysfs.

http://www.icpdas.com/root/product/solutions/remote_io/rs-485/i-8k_i-87k/i-8024w.html

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
   v2..v3
   * use usleep_range instead of custom nsleep
   * number change (16/16 -> 21/21)

   v0..v2
   * no changes

 Documentation/misc-devices/lp8x4x_bus.txt | 15 ++++++
 drivers/misc/lp8x4x_bus.c                 | 78 +++++++++++++++++++++++++++++++
 2 files changed, 93 insertions(+)

diff --git a/Documentation/misc-devices/lp8x4x_bus.txt b/Documentation/misc-devices/lp8x4x_bus.txt
index 3ea257d..6076e01 100644
--- a/Documentation/misc-devices/lp8x4x_bus.txt
+++ b/Documentation/misc-devices/lp8x4x_bus.txt
@@ -66,3 +66,18 @@ input_status
 output_status
 	RW - set status of digital output channels on the module in
 	     the expansion slot. Value can be read back.
+
+analog_output
+	RW - set status of analog output channels on the module in
+	     the expansion slot. Tested with voltage output. Bits 0-13:
+	     0x00c0 is -10.0V
+	     0x2000 is   0.0V
+	     0x3f40 is +10.0V
+
+	     So 1 unit of output is 1.25 mV.
+
+	     Bits 15 and 14 determine which channel to apply the value:
+	     0x0000 is channel 1
+	     0x4000 is channel 2
+	     0x8000 is channel 3
+	     0xc000 is channel 4
diff --git a/drivers/misc/lp8x4x_bus.c b/drivers/misc/lp8x4x_bus.c
index 3fb227d..72cd0b2 100644
--- a/drivers/misc/lp8x4x_bus.c
+++ b/drivers/misc/lp8x4x_bus.c
@@ -8,6 +8,7 @@
  *  it under the terms of the GNU General Public License version 2 as
  *  published by the Free Software Foundation or any later version.
  */
+#include <linux/delay.h>
 #include <linux/err.h>
 #include <linux/gpio/consumer.h>
 #include <linux/init.h>
@@ -23,6 +24,7 @@ MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Sergei Ianovich <ynvich@gmail.com>");
 MODULE_DESCRIPTION("ICP DAS LP-8x4x parallel bus driver");
 
+#define LP8X4X_MAX_AO_CHANNELS	4
 struct lp8x4x_slot {
 	void			*data_addr;
 	unsigned int		model;
@@ -31,6 +33,8 @@ struct lp8x4x_slot {
 	u32			DO;
 	unsigned int		DI_len;
 	u32			DI;
+	unsigned int		AO_len;
+	u32			AO[LP8X4X_MAX_AO_CHANNELS];
 	struct device		dev;
 };
 
@@ -120,6 +124,26 @@ static void lp8x4x_slot_set_DO(struct lp8x4x_slot *s)
 	mutex_unlock(&s->lock);
 }
 
+static void lp8x4x_slot_reset_AO(struct lp8x4x_slot *s)
+{
+	int i;
+	mutex_lock(&s->lock);
+	for (i = 0; i < s->AO_len; i++)
+		s->AO[i] = 0x2000;
+	iowrite8(0x00, s->data_addr);
+	usleep_range(1, 2);
+	iowrite8(0xff, s->data_addr);
+	mutex_unlock(&s->lock);
+}
+
+static void lp8x4x_slot_set_AO(struct lp8x4x_slot *s, u32 val)
+{
+	mutex_lock(&s->lock);
+	iowrite8(val & 0xff, s->data_addr + 2);
+	iowrite8((val >> 8) & 0xff, s->data_addr + 4);
+	mutex_unlock(&s->lock);
+}
+
 static ssize_t input_status_show(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
@@ -191,6 +215,48 @@ static ssize_t output_status_store(struct device *dev,
 
 static DEVICE_ATTR_RW(output_status);
 
+static ssize_t analog_output_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct lp8x4x_slot *s = container_of(dev, struct lp8x4x_slot, dev);
+	int i, c = 0;
+
+	for (i = 0; i < s->AO_len; i++)
+		c += sprintf(&buf[c], "0x%04x\n", s->AO[i]);
+	return c;
+}
+
+static ssize_t analog_output_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct lp8x4x_slot *s = container_of(dev, struct lp8x4x_slot, dev);
+	u32 AO;
+	int i;
+
+	if (!buf)
+		return count;
+	if (0 == count)
+		return count;
+
+	if (kstrtouint(buf, 16, &AO) != 0) {
+		dev_err(dev, "bad input\n");
+		return count;
+	}
+
+	if (AO & 0xffff0000) {
+		dev_err(dev, "bad input\n");
+		return count;
+	}
+
+	i = AO >> 14;
+	s->AO[i] = AO & 0x3fff;
+	lp8x4x_slot_set_AO(s, AO);
+
+	return count;
+}
+
+static DEVICE_ATTR_RW(analog_output);
+
 static ssize_t model_show(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
@@ -222,6 +288,13 @@ static struct attribute *dio_slot_dev_attrs[] = {
 };
 ATTRIBUTE_GROUPS(dio_slot_dev);
 
+static struct attribute *ao_slot_dev_attrs[] = {
+	&dev_attr_model.attr,
+	&dev_attr_analog_output.attr,
+	NULL,
+};
+ATTRIBUTE_GROUPS(ao_slot_dev);
+
 static void lp8x4x_master_release(struct device *dev)
 {
 	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
@@ -382,6 +455,11 @@ static void __init lp8x4x_bus_probe_slot(struct lp8x4x_master *m, int i,
 	mutex_init(&s->lock);
 
 	switch (model) {
+	case 24:
+		s->AO_len = 4;
+		lp8x4x_slot_reset_AO(s);
+		s->dev.groups = ao_slot_dev_groups;
+		break;
 	case 41:
 		s->DO_len = 4;
 		lp8x4x_slot_set_DO(s);
-- 
1.8.4.2

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

* Re: [PATCH v2 00/16] ARM: support for ICP DAS LP-8x4x (with dts)
  2013-12-16 20:38                         ` Sergei Ianovich
@ 2013-12-18 20:50                           ` Arnd Bergmann
  -1 siblings, 0 replies; 700+ messages in thread
From: Arnd Bergmann @ 2013-12-18 20:50 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: linux-kernel, linux-arm-kernel, Daniel Mack, Haojian Zhuang

On Monday 16 December 2013, Sergei Ianovich wrote:
> On Mon, 2013-12-16 at 18:56 +0100, Arnd Bergmann wrote:
> > Ok, I see. This sounds like some of the other platforms we have with
> > external memory buses. If there is a chance that Linux ever has to
> > program the per-CS settings into the bus controller, I would suggest
> > to represent that as well as a separate node, like this
> 
> This is a platform-specific bus (PXA27x). Should it go into pxa27x.dtsi
> rather than machine dts?

Yes, that was the idea.

> > In case there is a driver for the extbus node, I would not make it
> > "simple-bus" but instead add a separate compatible string to match
> > the driver, and let that driver call of_platform_populate
> > to probe the children after the bus is set up.
> 
> There seems to be none at the moment. However, some machines need to
> setup these partitions as a part of their initialization. So complete
> migration to DT will require this driver.
> 
> In LP-8x4x case everything is setup by the bootloader. So "simple-bus"
> works for me.

Hmm, this is a bit tricky then. I think it would be best to not
use "simple-bus" then, to allow migrating the other platforms later,
but that will be a little more work. Maybe you can register a trivial
driver in the platform code that only calls of_platform_populate on
the device for now?

	Arnd

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

* [PATCH v2 00/16] ARM: support for ICP DAS LP-8x4x (with dts)
@ 2013-12-18 20:50                           ` Arnd Bergmann
  0 siblings, 0 replies; 700+ messages in thread
From: Arnd Bergmann @ 2013-12-18 20:50 UTC (permalink / raw)
  To: linux-arm-kernel

On Monday 16 December 2013, Sergei Ianovich wrote:
> On Mon, 2013-12-16 at 18:56 +0100, Arnd Bergmann wrote:
> > Ok, I see. This sounds like some of the other platforms we have with
> > external memory buses. If there is a chance that Linux ever has to
> > program the per-CS settings into the bus controller, I would suggest
> > to represent that as well as a separate node, like this
> 
> This is a platform-specific bus (PXA27x). Should it go into pxa27x.dtsi
> rather than machine dts?

Yes, that was the idea.

> > In case there is a driver for the extbus node, I would not make it
> > "simple-bus" but instead add a separate compatible string to match
> > the driver, and let that driver call of_platform_populate
> > to probe the children after the bus is set up.
> 
> There seems to be none at the moment. However, some machines need to
> setup these partitions as a part of their initialization. So complete
> migration to DT will require this driver.
> 
> In LP-8x4x case everything is setup by the bootloader. So "simple-bus"
> works for me.

Hmm, this is a bit tricky then. I think it would be best to not
use "simple-bus" then, to allow migrating the other platforms later,
but that will be a little more work. Maybe you can register a trivial
driver in the platform code that only calls of_platform_populate on
the device for now?

	Arnd

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

* Re: [PATCH v2 00/16] ARM: support for ICP DAS LP-8x4x (with dts)
  2013-12-18 20:50                           ` Arnd Bergmann
@ 2013-12-18 20:56                             ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-18 20:56 UTC (permalink / raw)
  To: Arnd Bergmann; +Cc: linux-kernel, linux-arm-kernel, Daniel Mack, Haojian Zhuang

On Wed, 2013-12-18 at 21:50 +0100, Arnd Bergmann wrote:
> > This is a platform-specific bus (PXA27x). Should it go into pxa27x.dtsi
> > rather than machine dts?
> 
> Yes, that was the idea.

Great.

> > There seems to be none at the moment. However, some machines need to
> > setup these partitions as a part of their initialization. So complete
> > migration to DT will require this driver.
> > 
> > In LP-8x4x case everything is setup by the bootloader. So "simple-bus"
> > works for me.
> 
> Hmm, this is a bit tricky then. I think it would be best to not
> use "simple-bus" then, to allow migrating the other platforms later,
> but that will be a little more work. Maybe you can register a trivial
> driver in the platform code that only calls of_platform_populate on
> the device for now?

Could we postpone this until someone needs this functionality?



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

* [PATCH v2 00/16] ARM: support for ICP DAS LP-8x4x (with dts)
@ 2013-12-18 20:56                             ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-18 20:56 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, 2013-12-18 at 21:50 +0100, Arnd Bergmann wrote:
> > This is a platform-specific bus (PXA27x). Should it go into pxa27x.dtsi
> > rather than machine dts?
> 
> Yes, that was the idea.

Great.

> > There seems to be none at the moment. However, some machines need to
> > setup these partitions as a part of their initialization. So complete
> > migration to DT will require this driver.
> > 
> > In LP-8x4x case everything is setup by the bootloader. So "simple-bus"
> > works for me.
> 
> Hmm, this is a bit tricky then. I think it would be best to not
> use "simple-bus" then, to allow migrating the other platforms later,
> but that will be a little more work. Maybe you can register a trivial
> driver in the platform code that only calls of_platform_populate on
> the device for now?

Could we postpone this until someone needs this functionality?

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

* Re: [PATCH v2 00/16] ARM: support for ICP DAS LP-8x4x (with dts)
  2013-12-18 20:56                             ` Sergei Ianovich
@ 2013-12-18 21:10                               ` Arnd Bergmann
  -1 siblings, 0 replies; 700+ messages in thread
From: Arnd Bergmann @ 2013-12-18 21:10 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: linux-kernel, linux-arm-kernel, Daniel Mack, Haojian Zhuang

On Wednesday 18 December 2013, Sergei Ianovich wrote:
> > Hmm, this is a bit tricky then. I think it would be best to not
> > use "simple-bus" then, to allow migrating the other platforms later,
> > but that will be a little more work. Maybe you can register a trivial
> > driver in the platform code that only calls of_platform_populate on
> > the device for now?
> 
> Could we postpone this until someone needs this functionality?

We have to be sure that any device tree files you write now can remain
compatible with future kernels if we add it later. My reasoning at first
was that this wouldn't work if we had to change the "compatible" string
for the bus node, but after re-thinking it now I believe that it's fine.

You would still be able to boot a kernel with an old dts file on a new
kernel if it just contains a "simple-bus" node here, as long as it doesn't
need any boot-time setup at the bus controller. We can change the dts
file later if we need to add this functionality, which would break booting
old kernels with the new dts files, which isn't much of a problem in
general.

	Arnd

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

* [PATCH v2 00/16] ARM: support for ICP DAS LP-8x4x (with dts)
@ 2013-12-18 21:10                               ` Arnd Bergmann
  0 siblings, 0 replies; 700+ messages in thread
From: Arnd Bergmann @ 2013-12-18 21:10 UTC (permalink / raw)
  To: linux-arm-kernel

On Wednesday 18 December 2013, Sergei Ianovich wrote:
> > Hmm, this is a bit tricky then. I think it would be best to not
> > use "simple-bus" then, to allow migrating the other platforms later,
> > but that will be a little more work. Maybe you can register a trivial
> > driver in the platform code that only calls of_platform_populate on
> > the device for now?
> 
> Could we postpone this until someone needs this functionality?

We have to be sure that any device tree files you write now can remain
compatible with future kernels if we add it later. My reasoning at first
was that this wouldn't work if we had to change the "compatible" string
for the bus node, but after re-thinking it now I believe that it's fine.

You would still be able to boot a kernel with an old dts file on a new
kernel if it just contains a "simple-bus" node here, as long as it doesn't
need any boot-time setup at the bus controller. We can change the dts
file later if we need to add this functionality, which would break booting
old kernels with the new dts files, which isn't much of a problem in
general.

	Arnd

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

* Re: [PATCH v2 00/16] ARM: support for ICP DAS LP-8x4x (with dts)
  2013-12-18 21:10                               ` Arnd Bergmann
@ 2013-12-18 21:20                                 ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-18 21:20 UTC (permalink / raw)
  To: Arnd Bergmann; +Cc: linux-kernel, linux-arm-kernel, Daniel Mack, Haojian Zhuang

On Wed, 2013-12-18 at 22:10 +0100, Arnd Bergmann wrote:
> On Wednesday 18 December 2013, Sergei Ianovich wrote:
> > Could we postpone this until someone needs this functionality?
> 
> We have to be sure that any device tree files you write now can remain
> compatible with future kernels if we add it later. My reasoning at first
> was that this wouldn't work if we had to change the "compatible" string
> for the bus node, but after re-thinking it now I believe that it's fine.

Great.

> You would still be able to boot a kernel with an old dts file on a new
> kernel if it just contains a "simple-bus" node here, as long as it doesn't
> need any boot-time setup at the bus controller. We can change the dts
> file later if we need to add this functionality, which would break booting
> old kernels with the new dts files, which isn't much of a problem in
> general.

It should actually only break old kernels which require new
functionally. Otherwise, dts can have

compatible = "marvell,pxa-extbus", "simple-bus";

and an older kernel will be happy with "simple-bus". Please correct me
if I'm wrong.



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

* [PATCH v2 00/16] ARM: support for ICP DAS LP-8x4x (with dts)
@ 2013-12-18 21:20                                 ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-18 21:20 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, 2013-12-18 at 22:10 +0100, Arnd Bergmann wrote:
> On Wednesday 18 December 2013, Sergei Ianovich wrote:
> > Could we postpone this until someone needs this functionality?
> 
> We have to be sure that any device tree files you write now can remain
> compatible with future kernels if we add it later. My reasoning at first
> was that this wouldn't work if we had to change the "compatible" string
> for the bus node, but after re-thinking it now I believe that it's fine.

Great.

> You would still be able to boot a kernel with an old dts file on a new
> kernel if it just contains a "simple-bus" node here, as long as it doesn't
> need any boot-time setup at the bus controller. We can change the dts
> file later if we need to add this functionality, which would break booting
> old kernels with the new dts files, which isn't much of a problem in
> general.

It should actually only break old kernels which require new
functionally. Otherwise, dts can have

compatible = "marvell,pxa-extbus", "simple-bus";

and an older kernel will be happy with "simple-bus". Please correct me
if I'm wrong.

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

* Re: [PATCH v3 01/21 resend] serial: rewrite pxa2xx-uart to use 8250_core
  2013-12-17 19:37             ` Sergei Ianovich
@ 2013-12-18 23:55               ` Greg Kroah-Hartman
  -1 siblings, 0 replies; 700+ messages in thread
From: Greg Kroah-Hartman @ 2013-12-18 23:55 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: linux-kernel, linux-arm-kernel, Russell King, Jiri Slaby,
	Grant Likely, Rob Herring, Heikki Krogerus, James Cameron,
	Zhou Zhu, Haojian Zhuang, Arnd Bergmann,
	open list:SERIAL DRIVERS, open list:OPEN FIRMWARE AND...

On Tue, Dec 17, 2013 at 11:37:31PM +0400, Sergei Ianovich wrote:
> pxa2xx-uart was a separate uart platform driver. It was declaring
> the same device names and numbers as 8250 driver. As a result,
> it was impossible to use 8250 driver on PXA SoCs.
> 
> Upon closer examination pxa2xx-uart turned out to be a clone of
> 8250_core driver.
> 
> Workaround for Erratum #19 according to Marvel(R) PXA270M Processor
> Specification Update (April 19, 2010) is dropped. 8250_core reads
> from FIFO immediately after checking DR bit in LSR.
> 
> Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
> Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
> Reviewed-by: James Cameron <quozl@laptop.org>
> CC: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

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

* [PATCH v3 01/21 resend] serial: rewrite pxa2xx-uart to use 8250_core
@ 2013-12-18 23:55               ` Greg Kroah-Hartman
  0 siblings, 0 replies; 700+ messages in thread
From: Greg Kroah-Hartman @ 2013-12-18 23:55 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Dec 17, 2013 at 11:37:31PM +0400, Sergei Ianovich wrote:
> pxa2xx-uart was a separate uart platform driver. It was declaring
> the same device names and numbers as 8250 driver. As a result,
> it was impossible to use 8250 driver on PXA SoCs.
> 
> Upon closer examination pxa2xx-uart turned out to be a clone of
> 8250_core driver.
> 
> Workaround for Erratum #19 according to Marvel(R) PXA270M Processor
> Specification Update (April 19, 2010) is dropped. 8250_core reads
> from FIFO immediately after checking DR bit in LSR.
> 
> Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
> Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
> Reviewed-by: James Cameron <quozl@laptop.org>
> CC: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

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

* Re: [PATCH v3 07/21] ARM: dts: parse DMA config in pxamci
  2013-12-17 19:37             ` Sergei Ianovich
@ 2013-12-19  0:50               ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-19  0:50 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-arm-kernel, Daniel Mack, Arnd Bergmann, Chris Ball,
	Mark Brown, Ulf Hansson, Jingoo Han, Adrian Hunter, linux-mmc

Daniel,

On Tue, 2013-12-17 at 23:37 +0400, Sergei Ianovich wrote:
> The existing PXA MMC driver cannot get DMA channels in a proper
> way from the respective device tree binding.
> 
> This patch provides temporary workaround which allows using the
> existing driver in DT machines by pointing to the proper
> dmaengine-based "marvell,pdma-1.0" DMA.
> 
> Even though the new DMA provider is not present we can parse device node
> attributes manually and use channel numbers to acquire DMA channel
> from the existing non-dmaengine provider.
> 
> When Daniel's DMA series is merged there will be no need to manually
> parse for "dmas" and this patch can be safely reverted.
> 
> Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
> CC: Daniel Mack <zonque@gmail.com>
> CC: Arnd Bergmann <arnd@arndb.de>
> ---
>    v2..v3
>    * split into good (PATCH 07/21) and temporary (this one) parts
> 
>    v1..v2
>    * add binding for next-gen dma controller
>    * use correct dma declararion
>    * number changed from 5 to 3

Could you please comment on this solution for PXA DMA?

There may appear new, but it remains the last open review comment for
the series at the moment.


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

* [PATCH v3 07/21] ARM: dts: parse DMA config in pxamci
@ 2013-12-19  0:50               ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-19  0:50 UTC (permalink / raw)
  To: linux-arm-kernel

Daniel,

On Tue, 2013-12-17 at 23:37 +0400, Sergei Ianovich wrote:
> The existing PXA MMC driver cannot get DMA channels in a proper
> way from the respective device tree binding.
> 
> This patch provides temporary workaround which allows using the
> existing driver in DT machines by pointing to the proper
> dmaengine-based "marvell,pdma-1.0" DMA.
> 
> Even though the new DMA provider is not present we can parse device node
> attributes manually and use channel numbers to acquire DMA channel
> from the existing non-dmaengine provider.
> 
> When Daniel's DMA series is merged there will be no need to manually
> parse for "dmas" and this patch can be safely reverted.
> 
> Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
> CC: Daniel Mack <zonque@gmail.com>
> CC: Arnd Bergmann <arnd@arndb.de>
> ---
>    v2..v3
>    * split into good (PATCH 07/21) and temporary (this one) parts
> 
>    v1..v2
>    * add binding for next-gen dma controller
>    * use correct dma declararion
>    * number changed from 5 to 3

Could you please comment on this solution for PXA DMA?

There may appear new, but it remains the last open review comment for
the series at the moment.

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

* Re: [PATCH v2 00/16] ARM: support for ICP DAS LP-8x4x (with dts)
  2013-12-18 21:20                                 ` Sergei Ianovich
@ 2013-12-19  5:30                                   ` Arnd Bergmann
  -1 siblings, 0 replies; 700+ messages in thread
From: Arnd Bergmann @ 2013-12-19  5:30 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: linux-kernel, linux-arm-kernel, Daniel Mack, Haojian Zhuang

On Wednesday 18 December 2013, Sergei Ianovich wrote:
> > You would still be able to boot a kernel with an old dts file on a new
> > kernel if it just contains a "simple-bus" node here, as long as it doesn't
> > need any boot-time setup at the bus controller. We can change the dts
> > file later if we need to add this functionality, which would break booting
> > old kernels with the new dts files, which isn't much of a problem in
> > general.
> 
> It should actually only break old kernels which require new
> functionally. Otherwise, dts can have
> 
> compatible = "marvell,pxa-extbus", "simple-bus";
> 
> and an older kernel will be happy with "simple-bus". Please correct me
> if I'm wrong.

This would work only if we can probe the devices behind the external
bus controller before the controller itsef has been set up, since
the initialization order can depend on a number of things but not
the bus hierarchy. It will also work if the code setting up the
bus controller can be guaranteed to run before we call
of_platform_populate for the regular devices, which is probably
the best solution here.

	Arnd

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

* [PATCH v2 00/16] ARM: support for ICP DAS LP-8x4x (with dts)
@ 2013-12-19  5:30                                   ` Arnd Bergmann
  0 siblings, 0 replies; 700+ messages in thread
From: Arnd Bergmann @ 2013-12-19  5:30 UTC (permalink / raw)
  To: linux-arm-kernel

On Wednesday 18 December 2013, Sergei Ianovich wrote:
> > You would still be able to boot a kernel with an old dts file on a new
> > kernel if it just contains a "simple-bus" node here, as long as it doesn't
> > need any boot-time setup at the bus controller. We can change the dts
> > file later if we need to add this functionality, which would break booting
> > old kernels with the new dts files, which isn't much of a problem in
> > general.
> 
> It should actually only break old kernels which require new
> functionally. Otherwise, dts can have
> 
> compatible = "marvell,pxa-extbus", "simple-bus";
> 
> and an older kernel will be happy with "simple-bus". Please correct me
> if I'm wrong.

This would work only if we can probe the devices behind the external
bus controller before the controller itsef has been set up, since
the initialization order can depend on a number of things but not
the bus hierarchy. It will also work if the code setting up the
bus controller can be guaranteed to run before we call
of_platform_populate for the regular devices, which is probably
the best solution here.

	Arnd

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

* Re: [PATCH v3 01/21 resend] serial: rewrite pxa2xx-uart to use 8250_core
  2013-12-17 19:37             ` Sergei Ianovich
@ 2013-12-19  8:51               ` Heikki Krogerus
  -1 siblings, 0 replies; 700+ messages in thread
From: Heikki Krogerus @ 2013-12-19  8:51 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: linux-kernel, linux-arm-kernel, Greg Kroah-Hartman, Russell King,
	Jiri Slaby, Grant Likely, Rob Herring, James Cameron, Zhou Zhu,
	Haojian Zhuang, Arnd Bergmann, open list:SERIAL DRIVERS,
	open list:OPEN FIRMWARE AND...

Hi Sergei,

I noticed one more thing. I'm sorry about commenting this late.

On Tue, Dec 17, 2013 at 11:37:31PM +0400, Sergei Ianovich wrote:
> +static int serial_pxa_probe(struct platform_device *pdev)
> +{
> +	struct uart_8250_port uart = {};
> +	struct pxa8250_data *data;
> +	struct resource *mmres, *irqres;
> +	int ret;
> +
> +	mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	irqres = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
> +	if (!mmres || !irqres)
> +		return -ENODEV;
> +
> +	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
> +	if (!data)
> +		return -ENOMEM;
> +
> +	data->clk = devm_clk_get(&pdev->dev, NULL);
> +	if (IS_ERR(data->clk))
> +		return PTR_ERR(data->clk);
> +
> +	ret = clk_prepare(data->clk);
> +	if (ret)
> +		return ret;
> +
> +	uart.port.type = PORT_XSCALE;
> +	uart.port.iotype = UPIO_MEM32;
> +	uart.port.mapbase = mmres->start;
> +	uart.port.regshift = 2;
> +	uart.port.irq = irqres->start;
> +	uart.port.fifosize = 64;
> +	uart.port.flags = UPF_IOREMAP | UPF_SKIP_TEST;

Since you set the type PORT_XSCALE, don's you want to use
UPF_FIXED_TYPE flag instead of the UPF_SKIP_TEST here? Otherwise the
type will just get overridden and autoconfig() will be executed.

I'm guessing you also want to prevent things like the irq and the
uartclk from being changed by anybody by using the flag
UPF_FIXED_PORT, right?

> +	uart.port.dev = &pdev->dev;
> +	uart.port.uartclk = clk_get_rate(data->clk);
> +	uart.port.pm = serial_pxa_pm;
> +	uart.port.private_data = data;
> +	uart.dl_write = serial_pxa_dl_write;
> +
> +	ret = serial8250_register_8250_port(&uart);
> +	if (ret < 0)
> +		goto err_clk;
> +
> +	data->line = ret;
> +
> +	platform_set_drvdata(pdev, data);
> +
> +	return 0;
> +
> + err_clk:
> +	clk_unprepare(data->clk);
> +	return ret;
> +}

-- 
heikki

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

* [PATCH v3 01/21 resend] serial: rewrite pxa2xx-uart to use 8250_core
@ 2013-12-19  8:51               ` Heikki Krogerus
  0 siblings, 0 replies; 700+ messages in thread
From: Heikki Krogerus @ 2013-12-19  8:51 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Sergei,

I noticed one more thing. I'm sorry about commenting this late.

On Tue, Dec 17, 2013 at 11:37:31PM +0400, Sergei Ianovich wrote:
> +static int serial_pxa_probe(struct platform_device *pdev)
> +{
> +	struct uart_8250_port uart = {};
> +	struct pxa8250_data *data;
> +	struct resource *mmres, *irqres;
> +	int ret;
> +
> +	mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	irqres = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
> +	if (!mmres || !irqres)
> +		return -ENODEV;
> +
> +	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
> +	if (!data)
> +		return -ENOMEM;
> +
> +	data->clk = devm_clk_get(&pdev->dev, NULL);
> +	if (IS_ERR(data->clk))
> +		return PTR_ERR(data->clk);
> +
> +	ret = clk_prepare(data->clk);
> +	if (ret)
> +		return ret;
> +
> +	uart.port.type = PORT_XSCALE;
> +	uart.port.iotype = UPIO_MEM32;
> +	uart.port.mapbase = mmres->start;
> +	uart.port.regshift = 2;
> +	uart.port.irq = irqres->start;
> +	uart.port.fifosize = 64;
> +	uart.port.flags = UPF_IOREMAP | UPF_SKIP_TEST;

Since you set the type PORT_XSCALE, don's you want to use
UPF_FIXED_TYPE flag instead of the UPF_SKIP_TEST here? Otherwise the
type will just get overridden and autoconfig() will be executed.

I'm guessing you also want to prevent things like the irq and the
uartclk from being changed by anybody by using the flag
UPF_FIXED_PORT, right?

> +	uart.port.dev = &pdev->dev;
> +	uart.port.uartclk = clk_get_rate(data->clk);
> +	uart.port.pm = serial_pxa_pm;
> +	uart.port.private_data = data;
> +	uart.dl_write = serial_pxa_dl_write;
> +
> +	ret = serial8250_register_8250_port(&uart);
> +	if (ret < 0)
> +		goto err_clk;
> +
> +	data->line = ret;
> +
> +	platform_set_drvdata(pdev, data);
> +
> +	return 0;
> +
> + err_clk:
> +	clk_unprepare(data->clk);
> +	return ret;
> +}

-- 
heikki

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

* Re: [PATCH v3 01/21 resend] serial: rewrite pxa2xx-uart to use 8250_core
  2013-12-19  8:51               ` Heikki Krogerus
@ 2013-12-19  9:35                 ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-19  9:35 UTC (permalink / raw)
  To: Heikki Krogerus
  Cc: linux-kernel, linux-arm-kernel, Greg Kroah-Hartman, Russell King,
	Jiri Slaby, Grant Likely, Rob Herring, James Cameron, Zhou Zhu,
	Haojian Zhuang, Arnd Bergmann, open list:SERIAL DRIVERS,
	open list:OPEN FIRMWARE AND...

Hi Heikki,

On Thu, 2013-12-19 at 10:51 +0200, Heikki Krogerus wrote:
> I noticed one more thing. I'm sorry about commenting this late.
> 
> Since you set the type PORT_XSCALE, don's you want to use
> UPF_FIXED_TYPE flag instead of the UPF_SKIP_TEST here? Otherwise the
> type will just get overridden and autoconfig() will be executed.

UPF_FIXED_PORT was my first guess. However, it didn't work.

I've also tried to do ioremap in serial_pxa_probe instead of using
UPF_IOREMAP. This didn't work as well.

I've left this

uart.port.type = PORT_XSCALE;

as an indicator that 8250_pxa depends on this port type, and anyone
changing its specific code paths should test with 8250_pxa. This line
could be safely removed or commented out, if you feel strongly about
that.

> I'm guessing you also want to prevent things like the irq and the
> uartclk from being changed by anybody by using the flag
> UPF_FIXED_PORT, right?

IIRC, autoprobing doesn't change irq or uartclk.


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

* [PATCH v3 01/21 resend] serial: rewrite pxa2xx-uart to use 8250_core
@ 2013-12-19  9:35                 ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-19  9:35 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Heikki,

On Thu, 2013-12-19 at 10:51 +0200, Heikki Krogerus wrote:
> I noticed one more thing. I'm sorry about commenting this late.
> 
> Since you set the type PORT_XSCALE, don's you want to use
> UPF_FIXED_TYPE flag instead of the UPF_SKIP_TEST here? Otherwise the
> type will just get overridden and autoconfig() will be executed.

UPF_FIXED_PORT was my first guess. However, it didn't work.

I've also tried to do ioremap in serial_pxa_probe instead of using
UPF_IOREMAP. This didn't work as well.

I've left this

uart.port.type = PORT_XSCALE;

as an indicator that 8250_pxa depends on this port type, and anyone
changing its specific code paths should test with 8250_pxa. This line
could be safely removed or commented out, if you feel strongly about
that.

> I'm guessing you also want to prevent things like the irq and the
> uartclk from being changed by anybody by using the flag
> UPF_FIXED_PORT, right?

IIRC, autoprobing doesn't change irq or uartclk.

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

* Re: [PATCH v3 01/21 resend] serial: rewrite pxa2xx-uart to use 8250_core
  2013-12-19  9:35                 ` Sergei Ianovich
@ 2013-12-19 10:01                   ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-19 10:01 UTC (permalink / raw)
  To: Heikki Krogerus
  Cc: linux-kernel, linux-arm-kernel, Greg Kroah-Hartman, Russell King,
	Jiri Slaby, Grant Likely, Rob Herring, James Cameron, Zhou Zhu,
	Haojian Zhuang, Arnd Bergmann, open list:SERIAL DRIVERS,
	open list:OPEN FIRMWARE AND...

On Thu, 2013-12-19 at 13:35 +0400, Sergei Ianovich wrote:
> Hi Heikki,
> 
> On Thu, 2013-12-19 at 10:51 +0200, Heikki Krogerus wrote:
> > I noticed one more thing. I'm sorry about commenting this late.
> > 
> > Since you set the type PORT_XSCALE, don's you want to use
> > UPF_FIXED_TYPE flag instead of the UPF_SKIP_TEST here? Otherwise the
> > type will just get overridden and autoconfig() will be executed.
> 
> UPF_FIXED_PORT was my first guess. However, it didn't work.
> 
> I've also tried to do ioremap in serial_pxa_probe instead of using
> UPF_IOREMAP. This didn't work as well.

I didn't clarify properly.

UPF_SKIP_TEST skips only the loopback test. This test could work on PXA,
but requires PXA-specific pre-initialization. There are more test after
the loopback one, which will fail if we are not on PXA. So I decided
that skipping it is easier than tricky rewriting of autoconfig().


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

* [PATCH v3 01/21 resend] serial: rewrite pxa2xx-uart to use 8250_core
@ 2013-12-19 10:01                   ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2013-12-19 10:01 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, 2013-12-19 at 13:35 +0400, Sergei Ianovich wrote:
> Hi Heikki,
> 
> On Thu, 2013-12-19 at 10:51 +0200, Heikki Krogerus wrote:
> > I noticed one more thing. I'm sorry about commenting this late.
> > 
> > Since you set the type PORT_XSCALE, don's you want to use
> > UPF_FIXED_TYPE flag instead of the UPF_SKIP_TEST here? Otherwise the
> > type will just get overridden and autoconfig() will be executed.
> 
> UPF_FIXED_PORT was my first guess. However, it didn't work.
> 
> I've also tried to do ioremap in serial_pxa_probe instead of using
> UPF_IOREMAP. This didn't work as well.

I didn't clarify properly.

UPF_SKIP_TEST skips only the loopback test. This test could work on PXA,
but requires PXA-specific pre-initialization. There are more test after
the loopback one, which will fail if we are not on PXA. So I decided
that skipping it is easier than tricky rewriting of autoconfig().

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

* Re: [PATCH v3 01/21 resend] serial: rewrite pxa2xx-uart to use 8250_core
  2013-12-19 10:01                   ` Sergei Ianovich
@ 2013-12-19 11:05                     ` Heikki Krogerus
  -1 siblings, 0 replies; 700+ messages in thread
From: Heikki Krogerus @ 2013-12-19 11:05 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: linux-kernel, linux-arm-kernel, Greg Kroah-Hartman, Russell King,
	Jiri Slaby, Grant Likely, Rob Herring, James Cameron, Zhou Zhu,
	Haojian Zhuang, Arnd Bergmann, open list:SERIAL DRIVERS,
	open list:OPEN FIRMWARE AND...

On Thu, Dec 19, 2013 at 02:01:36PM +0400, Sergei Ianovich wrote:
> On Thu, 2013-12-19 at 13:35 +0400, Sergei Ianovich wrote:
> > On Thu, 2013-12-19 at 10:51 +0200, Heikki Krogerus wrote:
> > > I noticed one more thing. I'm sorry about commenting this late.
> > > 
> > > Since you set the type PORT_XSCALE, don's you want to use
> > > UPF_FIXED_TYPE flag instead of the UPF_SKIP_TEST here? Otherwise the
> > > type will just get overridden and autoconfig() will be executed.
> > 
> > UPF_FIXED_PORT was my first guess. However, it didn't work.
> > 
> > I've also tried to do ioremap in serial_pxa_probe instead of using
> > UPF_IOREMAP. This didn't work as well.
> 
> I didn't clarify properly.
> 
> UPF_SKIP_TEST skips only the loopback test. This test could work on PXA,
> but requires PXA-specific pre-initialization. There are more test after
> the loopback one, which will fail if we are not on PXA. So I decided
> that skipping it is easier than tricky rewriting of autoconfig().

OK. So there is no problem here. Sorry about the noise.

Thanks,

-- 
heikki

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

* [PATCH v3 01/21 resend] serial: rewrite pxa2xx-uart to use 8250_core
@ 2013-12-19 11:05                     ` Heikki Krogerus
  0 siblings, 0 replies; 700+ messages in thread
From: Heikki Krogerus @ 2013-12-19 11:05 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Dec 19, 2013 at 02:01:36PM +0400, Sergei Ianovich wrote:
> On Thu, 2013-12-19 at 13:35 +0400, Sergei Ianovich wrote:
> > On Thu, 2013-12-19 at 10:51 +0200, Heikki Krogerus wrote:
> > > I noticed one more thing. I'm sorry about commenting this late.
> > > 
> > > Since you set the type PORT_XSCALE, don's you want to use
> > > UPF_FIXED_TYPE flag instead of the UPF_SKIP_TEST here? Otherwise the
> > > type will just get overridden and autoconfig() will be executed.
> > 
> > UPF_FIXED_PORT was my first guess. However, it didn't work.
> > 
> > I've also tried to do ioremap in serial_pxa_probe instead of using
> > UPF_IOREMAP. This didn't work as well.
> 
> I didn't clarify properly.
> 
> UPF_SKIP_TEST skips only the loopback test. This test could work on PXA,
> but requires PXA-specific pre-initialization. There are more test after
> the loopback one, which will fail if we are not on PXA. So I decided
> that skipping it is easier than tricky rewriting of autoconfig().

OK. So there is no problem here. Sorry about the noise.

Thanks,

-- 
heikki

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

* Re: [PATCH v3 12/21] serial: support for 16550A serial ports on LP-8x4x
  2013-12-17 19:37             ` Sergei Ianovich
@ 2013-12-19 11:18               ` Heikki Krogerus
  -1 siblings, 0 replies; 700+ messages in thread
From: Heikki Krogerus @ 2013-12-19 11:18 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: linux-kernel, linux-arm-kernel, Rob Herring, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala, Rob Landley,
	Russell King, Greg Kroah-Hartman, Jiri Slaby, Grant Likely,
	Randy Dunlap, Arnd Bergmann, James Cameron,
	open list:OPEN FIRMWARE AND...,
	open list:DOCUMENTATION, open list:SERIAL DRIVERS

Hi,

On Tue, Dec 17, 2013 at 11:37:42PM +0400, Sergei Ianovich wrote:
> The patch adds support for 3 additional LP-8x4x built-in serial
> ports.
> 
> The device can also host up to 8 extension cards with 4 serial ports
> on each card for a total of 35 ports. However, I don't have
> the hardware to test extension cards, so they are not supported, yet.
> 
> Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
> CC: Heikki Krogerus <heikki.krogerus@linux.intel.com>

Looks OK to me, though normally I would prefer the arch code and the
driver to be handled in separate patches. FWIW...

Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>


Thanks,

-- 
heikki

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

* [PATCH v3 12/21] serial: support for 16550A serial ports on LP-8x4x
@ 2013-12-19 11:18               ` Heikki Krogerus
  0 siblings, 0 replies; 700+ messages in thread
From: Heikki Krogerus @ 2013-12-19 11:18 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

On Tue, Dec 17, 2013 at 11:37:42PM +0400, Sergei Ianovich wrote:
> The patch adds support for 3 additional LP-8x4x built-in serial
> ports.
> 
> The device can also host up to 8 extension cards with 4 serial ports
> on each card for a total of 35 ports. However, I don't have
> the hardware to test extension cards, so they are not supported, yet.
> 
> Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
> CC: Heikki Krogerus <heikki.krogerus@linux.intel.com>

Looks OK to me, though normally I would prefer the arch code and the
driver to be handled in separate patches. FWIW...

Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>


Thanks,

-- 
heikki

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

* Re: [PATCH v3 11/21] ARM: pxa: support ICP DAS LP-8x4x FPGA irq
  2013-12-17 19:37             ` Sergei Ianovich
  (?)
@ 2014-01-02 12:32               ` Linus Walleij
  -1 siblings, 0 replies; 700+ messages in thread
From: Linus Walleij @ 2014-01-02 12:32 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: linux-kernel, linux-arm-kernel, Arnd Bergmann, Rob Herring,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala, Rob Landley,
	Russell King, Thomas Gleixner, Grant Likely,
	open list:OPEN FIRMWARE AND...,
	open list:DOCUMENTATION

On Tue, Dec 17, 2013 at 8:37 PM, Sergei Ianovich <ynvich@gmail.com> wrote:

> ICP DAS LP-8x4x contains FPGA chip. The chip functions as a interrupt
> source providing 16 additional interrupts among other things. The
> interrupt lines are muxed to a GPIO pin. GPIO pins are in turn muxed
> to a CPU interrupt line.
>
> Until pxa is completely converted to device tree, it is impossible
> to use IRQCHIP_DECLARE() and the irqdomain needs to added manually.
>
> Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
> CC: Arnd Bergmann <arnd@arndb.de>
> CC: Linus Walleij <linus.walleij@linaro.org>

(...)
> +++ b/drivers/irqchip/irq-lp8x4x.c

Usually combined GPIO+IRQ controllers are put into drivers/gpio but
this is a bit special as it seems to handle also non-GPIO-related IRQs
so let's get some input on this.

> +static unsigned char irq_sys_enabled;
> +static unsigned char irq_high_enabled;
> +static void *base;
> +static int irq_base;
> +static int num_irq = 16;

Please use the state container design pattern and get rid of these
global variables.

This documentation patch describes this pattern and has been
merged for v3.14, so please read this:
http://marc.info/?l=linux-kernel&m=138615980524966&w=2

> +static void lp8x4x_mask_irq(struct irq_data *d)
> +{
> +       unsigned mask;
> +       int irq = d->irq - irq_base;

Don't calculate hardware IRQ numbers from offsets. Use
irqdomain, which is done for exactly this purpose.

> +       if (irq < 8) {
> +               irq_high_enabled &= ~(1 << irq);

I usually use the BIT() macro for this, like:

#include <linux/bitops.h>

irq_high_enabled &= ~BIT(irq);

> +static struct irq_chip lp8x4x_irq_chip = {
> +       .name                   = "FPGA",
> +       .irq_ack                = lp8x4x_mask_irq,
> +       .irq_mask               = lp8x4x_mask_irq,
> +       .irq_mask_ack           = lp8x4x_mask_irq,
> +       .irq_unmask             = lp8x4x_unmask_irq,
> +};

After you have added your state container you will have
a handle to your struct gpio_chip in the cookie passed to
as irqdata.

Then you need to mark the GPIO lines used for IRQs by
doing something similar to this patch in your startup()
and shutdown() callbacks:
http://marc.info/?l=linux-gpio&m=138547223832167&w=2

> +static void lp8x4x_irq_handler(unsigned int irq, struct irq_desc *desc)
> +{> +static void lp8x4x_unmask_irq(struct irq_data *d)
> +{
> +       unsigned mask;
> +       int irq = d->irq - irq_base;

Use the irqdomain.

> +       int loop, n;
> +       unsigned long mask;
> +       struct irq_chip *chip = irq_desc_get_chip(desc);
> +
> +       chained_irq_enter(chip, desc);
> +
> +       do {
> +               loop = 0;
> +               mask = ioread8(base + CLRHILVINT) & 0xff;
> +               mask |= (ioread8(base + SECOINT) & 0x1f) << 8;
> +               mask |= (ioread8(base + PRIMINT) & 0xe0) << 8;

#define these magic constants so we know what they mean.
0x1f, 0xe0...

> +               mask &= (irq_high_enabled | (irq_sys_enabled << 8));
> +               for_each_set_bit(n, &mask, BITS_PER_LONG) {
> +                       loop = 1;
> +
> +                       generic_handle_irq(irq_base + n);
> +               }
> +       } while (loop);

If you're going to do it like this then have "loop" be a bool variable.

However I don't quite like this construction, an eternal for() loop
with a break; statement works too, but try to just use the mask and
get rid of the "loop" helper variable.

> +       iowrite8(0, base + EOI);

This looks dangerous, what are you doing here?

> +static int lp8x4x_irq_probe(struct platform_device *pdev)
> +{
> +       struct resource *rm, *ri;

Explain these names. Usually we call them "res" or something
simple like this.

> +       irq_base = irq_alloc_descs(-1, 0, num_irq, 0);
> +       if (irq_base < 0) {
> +               dev_err(&pdev->dev, "Failed to allocate IRQ numbers\n");
> +               return irq_base;
> +       }

Instead of doing this, create the descriptors by calling
irq_create_mapping() on all the hardware lines after adding
the irq domain.

> +       domain = irq_domain_add_legacy(np, num_irq, irq_base, 0,
> +                                      &lp8x4x_irq_domain_ops, NULL);
> +       if (!domain) {
> +               dev_err(&pdev->dev, "Failed to add IRQ domain\n");
> +               return -ENOMEM;
> +       }

Why are you using a legacy irqdomain? You're not dependent
on any specific base so use a linear domain.

> +       iowrite8(0, base + CLRRISEINT);
> +       iowrite8(0, base + ENRISEINT);
> +       iowrite8(0, base + CLRFALLINT);
> +       iowrite8(0, base + ENFALLINT);
> +       iowrite8(0, base + CLRHILVINT);
> +       iowrite8(0, base + ENHILVINT);
> +       iowrite8(0, base + ENSYSINT);
> +       iowrite8(0, base + SECOINT);

Add a comment explaining what you're doing here.

> +static int __init lp8x4x_irq_init(void)
> +{
> +       return platform_driver_register(&lp8x4x_irq_driver);
> +}
> +postcore_initcall(lp8x4x_irq_init);

Do you *have* to do it this early? I guess if it's used for
the UARTs then yes, but make a case for it...

Yours,
Linus Walleij

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

* Re: [PATCH v3 11/21] ARM: pxa: support ICP DAS LP-8x4x FPGA irq
@ 2014-01-02 12:32               ` Linus Walleij
  0 siblings, 0 replies; 700+ messages in thread
From: Linus Walleij @ 2014-01-02 12:32 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: linux-kernel, linux-arm-kernel, Arnd Bergmann, Rob Herring,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala, Rob Landley,
	Russell King, Thomas Gleixner, Grant Likely,
	open list:OPEN FIRMWARE AND...,
	open list:DOCUMENTATION

On Tue, Dec 17, 2013 at 8:37 PM, Sergei Ianovich <ynvich@gmail.com> wrote:

> ICP DAS LP-8x4x contains FPGA chip. The chip functions as a interrupt
> source providing 16 additional interrupts among other things. The
> interrupt lines are muxed to a GPIO pin. GPIO pins are in turn muxed
> to a CPU interrupt line.
>
> Until pxa is completely converted to device tree, it is impossible
> to use IRQCHIP_DECLARE() and the irqdomain needs to added manually.
>
> Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
> CC: Arnd Bergmann <arnd@arndb.de>
> CC: Linus Walleij <linus.walleij@linaro.org>

(...)
> +++ b/drivers/irqchip/irq-lp8x4x.c

Usually combined GPIO+IRQ controllers are put into drivers/gpio but
this is a bit special as it seems to handle also non-GPIO-related IRQs
so let's get some input on this.

> +static unsigned char irq_sys_enabled;
> +static unsigned char irq_high_enabled;
> +static void *base;
> +static int irq_base;
> +static int num_irq = 16;

Please use the state container design pattern and get rid of these
global variables.

This documentation patch describes this pattern and has been
merged for v3.14, so please read this:
http://marc.info/?l=linux-kernel&m=138615980524966&w=2

> +static void lp8x4x_mask_irq(struct irq_data *d)
> +{
> +       unsigned mask;
> +       int irq = d->irq - irq_base;

Don't calculate hardware IRQ numbers from offsets. Use
irqdomain, which is done for exactly this purpose.

> +       if (irq < 8) {
> +               irq_high_enabled &= ~(1 << irq);

I usually use the BIT() macro for this, like:

#include <linux/bitops.h>

irq_high_enabled &= ~BIT(irq);

> +static struct irq_chip lp8x4x_irq_chip = {
> +       .name                   = "FPGA",
> +       .irq_ack                = lp8x4x_mask_irq,
> +       .irq_mask               = lp8x4x_mask_irq,
> +       .irq_mask_ack           = lp8x4x_mask_irq,
> +       .irq_unmask             = lp8x4x_unmask_irq,
> +};

After you have added your state container you will have
a handle to your struct gpio_chip in the cookie passed to
as irqdata.

Then you need to mark the GPIO lines used for IRQs by
doing something similar to this patch in your startup()
and shutdown() callbacks:
http://marc.info/?l=linux-gpio&m=138547223832167&w=2

> +static void lp8x4x_irq_handler(unsigned int irq, struct irq_desc *desc)
> +{> +static void lp8x4x_unmask_irq(struct irq_data *d)
> +{
> +       unsigned mask;
> +       int irq = d->irq - irq_base;

Use the irqdomain.

> +       int loop, n;
> +       unsigned long mask;
> +       struct irq_chip *chip = irq_desc_get_chip(desc);
> +
> +       chained_irq_enter(chip, desc);
> +
> +       do {
> +               loop = 0;
> +               mask = ioread8(base + CLRHILVINT) & 0xff;
> +               mask |= (ioread8(base + SECOINT) & 0x1f) << 8;
> +               mask |= (ioread8(base + PRIMINT) & 0xe0) << 8;

#define these magic constants so we know what they mean.
0x1f, 0xe0...

> +               mask &= (irq_high_enabled | (irq_sys_enabled << 8));
> +               for_each_set_bit(n, &mask, BITS_PER_LONG) {
> +                       loop = 1;
> +
> +                       generic_handle_irq(irq_base + n);
> +               }
> +       } while (loop);

If you're going to do it like this then have "loop" be a bool variable.

However I don't quite like this construction, an eternal for() loop
with a break; statement works too, but try to just use the mask and
get rid of the "loop" helper variable.

> +       iowrite8(0, base + EOI);

This looks dangerous, what are you doing here?

> +static int lp8x4x_irq_probe(struct platform_device *pdev)
> +{
> +       struct resource *rm, *ri;

Explain these names. Usually we call them "res" or something
simple like this.

> +       irq_base = irq_alloc_descs(-1, 0, num_irq, 0);
> +       if (irq_base < 0) {
> +               dev_err(&pdev->dev, "Failed to allocate IRQ numbers\n");
> +               return irq_base;
> +       }

Instead of doing this, create the descriptors by calling
irq_create_mapping() on all the hardware lines after adding
the irq domain.

> +       domain = irq_domain_add_legacy(np, num_irq, irq_base, 0,
> +                                      &lp8x4x_irq_domain_ops, NULL);
> +       if (!domain) {
> +               dev_err(&pdev->dev, "Failed to add IRQ domain\n");
> +               return -ENOMEM;
> +       }

Why are you using a legacy irqdomain? You're not dependent
on any specific base so use a linear domain.

> +       iowrite8(0, base + CLRRISEINT);
> +       iowrite8(0, base + ENRISEINT);
> +       iowrite8(0, base + CLRFALLINT);
> +       iowrite8(0, base + ENFALLINT);
> +       iowrite8(0, base + CLRHILVINT);
> +       iowrite8(0, base + ENHILVINT);
> +       iowrite8(0, base + ENSYSINT);
> +       iowrite8(0, base + SECOINT);

Add a comment explaining what you're doing here.

> +static int __init lp8x4x_irq_init(void)
> +{
> +       return platform_driver_register(&lp8x4x_irq_driver);
> +}
> +postcore_initcall(lp8x4x_irq_init);

Do you *have* to do it this early? I guess if it's used for
the UARTs then yes, but make a case for it...

Yours,
Linus Walleij

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

* [PATCH v3 11/21] ARM: pxa: support ICP DAS LP-8x4x FPGA irq
@ 2014-01-02 12:32               ` Linus Walleij
  0 siblings, 0 replies; 700+ messages in thread
From: Linus Walleij @ 2014-01-02 12:32 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Dec 17, 2013 at 8:37 PM, Sergei Ianovich <ynvich@gmail.com> wrote:

> ICP DAS LP-8x4x contains FPGA chip. The chip functions as a interrupt
> source providing 16 additional interrupts among other things. The
> interrupt lines are muxed to a GPIO pin. GPIO pins are in turn muxed
> to a CPU interrupt line.
>
> Until pxa is completely converted to device tree, it is impossible
> to use IRQCHIP_DECLARE() and the irqdomain needs to added manually.
>
> Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
> CC: Arnd Bergmann <arnd@arndb.de>
> CC: Linus Walleij <linus.walleij@linaro.org>

(...)
> +++ b/drivers/irqchip/irq-lp8x4x.c

Usually combined GPIO+IRQ controllers are put into drivers/gpio but
this is a bit special as it seems to handle also non-GPIO-related IRQs
so let's get some input on this.

> +static unsigned char irq_sys_enabled;
> +static unsigned char irq_high_enabled;
> +static void *base;
> +static int irq_base;
> +static int num_irq = 16;

Please use the state container design pattern and get rid of these
global variables.

This documentation patch describes this pattern and has been
merged for v3.14, so please read this:
http://marc.info/?l=linux-kernel&m=138615980524966&w=2

> +static void lp8x4x_mask_irq(struct irq_data *d)
> +{
> +       unsigned mask;
> +       int irq = d->irq - irq_base;

Don't calculate hardware IRQ numbers from offsets. Use
irqdomain, which is done for exactly this purpose.

> +       if (irq < 8) {
> +               irq_high_enabled &= ~(1 << irq);

I usually use the BIT() macro for this, like:

#include <linux/bitops.h>

irq_high_enabled &= ~BIT(irq);

> +static struct irq_chip lp8x4x_irq_chip = {
> +       .name                   = "FPGA",
> +       .irq_ack                = lp8x4x_mask_irq,
> +       .irq_mask               = lp8x4x_mask_irq,
> +       .irq_mask_ack           = lp8x4x_mask_irq,
> +       .irq_unmask             = lp8x4x_unmask_irq,
> +};

After you have added your state container you will have
a handle to your struct gpio_chip in the cookie passed to
as irqdata.

Then you need to mark the GPIO lines used for IRQs by
doing something similar to this patch in your startup()
and shutdown() callbacks:
http://marc.info/?l=linux-gpio&m=138547223832167&w=2

> +static void lp8x4x_irq_handler(unsigned int irq, struct irq_desc *desc)
> +{> +static void lp8x4x_unmask_irq(struct irq_data *d)
> +{
> +       unsigned mask;
> +       int irq = d->irq - irq_base;

Use the irqdomain.

> +       int loop, n;
> +       unsigned long mask;
> +       struct irq_chip *chip = irq_desc_get_chip(desc);
> +
> +       chained_irq_enter(chip, desc);
> +
> +       do {
> +               loop = 0;
> +               mask = ioread8(base + CLRHILVINT) & 0xff;
> +               mask |= (ioread8(base + SECOINT) & 0x1f) << 8;
> +               mask |= (ioread8(base + PRIMINT) & 0xe0) << 8;

#define these magic constants so we know what they mean.
0x1f, 0xe0...

> +               mask &= (irq_high_enabled | (irq_sys_enabled << 8));
> +               for_each_set_bit(n, &mask, BITS_PER_LONG) {
> +                       loop = 1;
> +
> +                       generic_handle_irq(irq_base + n);
> +               }
> +       } while (loop);

If you're going to do it like this then have "loop" be a bool variable.

However I don't quite like this construction, an eternal for() loop
with a break; statement works too, but try to just use the mask and
get rid of the "loop" helper variable.

> +       iowrite8(0, base + EOI);

This looks dangerous, what are you doing here?

> +static int lp8x4x_irq_probe(struct platform_device *pdev)
> +{
> +       struct resource *rm, *ri;

Explain these names. Usually we call them "res" or something
simple like this.

> +       irq_base = irq_alloc_descs(-1, 0, num_irq, 0);
> +       if (irq_base < 0) {
> +               dev_err(&pdev->dev, "Failed to allocate IRQ numbers\n");
> +               return irq_base;
> +       }

Instead of doing this, create the descriptors by calling
irq_create_mapping() on all the hardware lines after adding
the irq domain.

> +       domain = irq_domain_add_legacy(np, num_irq, irq_base, 0,
> +                                      &lp8x4x_irq_domain_ops, NULL);
> +       if (!domain) {
> +               dev_err(&pdev->dev, "Failed to add IRQ domain\n");
> +               return -ENOMEM;
> +       }

Why are you using a legacy irqdomain? You're not dependent
on any specific base so use a linear domain.

> +       iowrite8(0, base + CLRRISEINT);
> +       iowrite8(0, base + ENRISEINT);
> +       iowrite8(0, base + CLRFALLINT);
> +       iowrite8(0, base + ENFALLINT);
> +       iowrite8(0, base + CLRHILVINT);
> +       iowrite8(0, base + ENHILVINT);
> +       iowrite8(0, base + ENSYSINT);
> +       iowrite8(0, base + SECOINT);

Add a comment explaining what you're doing here.

> +static int __init lp8x4x_irq_init(void)
> +{
> +       return platform_driver_register(&lp8x4x_irq_driver);
> +}
> +postcore_initcall(lp8x4x_irq_init);

Do you *have* to do it this early? I guess if it's used for
the UARTs then yes, but make a case for it...

Yours,
Linus Walleij

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

* Re: [PATCH v3 11/21] ARM: pxa: support ICP DAS LP-8x4x FPGA irq
  2014-01-02 12:32               ` Linus Walleij
  (?)
@ 2014-01-08 19:01                 ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2014-01-08 19:01 UTC (permalink / raw)
  To: Linus Walleij
  Cc: linux-kernel, linux-arm-kernel, Arnd Bergmann, Rob Herring,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala, Rob Landley,
	Russell King, Thomas Gleixner, Grant Likely,
	open list:OPEN FIRMWARE AND...,
	open list:DOCUMENTATION

On Thu, 2014-01-02 at 13:32 +0100, Linus Walleij wrote:
> On Tue, Dec 17, 2013 at 8:37 PM, Sergei Ianovich <ynvich@gmail.com> wrote:
> Usually combined GPIO+IRQ controllers are put into drivers/gpio but
> this is a bit special as it seems to handle also non-GPIO-related IRQs
> so let's get some input on this.

This one is a plain IRQ controller. It has simple input lines, not GPIO
pins. The chip reports its status to upper level interrupt controller.
The upper level controller is PXA GPIO in this case.

(...)

> > +static struct irq_chip lp8x4x_irq_chip = {
> > +       .name                   = "FPGA",
> > +       .irq_ack                = lp8x4x_mask_irq,
> > +       .irq_mask               = lp8x4x_mask_irq,
> > +       .irq_mask_ack           = lp8x4x_mask_irq,
> > +       .irq_unmask             = lp8x4x_unmask_irq,
> > +};
> 
> After you have added your state container you will have
> a handle to your struct gpio_chip in the cookie passed to
> as irqdata.
> 
> Then you need to mark the GPIO lines used for IRQs by
> doing something similar to this patch in your startup()
> and shutdown() callbacks:
> http://marc.info/?l=linux-gpio&m=138547223832167&w=2

The chip requires no GPIO initialization. 

(...)

> > +       iowrite8(0, base + EOI);
> 
> This looks dangerous, what are you doing here?

This is done in kernel source which comes with the device. The
controller won't work without this line.

I cannot know for sure, as I don't have board datasheets or drawings. I
suspect, this clears GPIO line which reports interrupts to the upper
level controller.

(...)

> > +static int __init lp8x4x_irq_init(void)
> > +{
> > +       return platform_driver_register(&lp8x4x_irq_driver);
> > +}
> > +postcore_initcall(lp8x4x_irq_init);
> 
> Do you *have* to do it this early? I guess if it's used for
> the UARTs then yes, but make a case for it...

PXA isn't DT-only at the moment. As a result, it is impossible
to use IRQCHIP_DECLARE(). So drivers for the on-CPU IRQs and GPIO-IRQs
are loaded using postcore_initcall(). We need to have all irq domain
drivers loaded prior to DT parsing in order to allow normal
initialization of IRQ resources with DT. I'll update the commit message.

The rest of review comment are implemented. The changes don't affect any
other patches in the series. Should I repost the whole series?

Or only this patch?

Thanks.


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

* Re: [PATCH v3 11/21] ARM: pxa: support ICP DAS LP-8x4x FPGA irq
@ 2014-01-08 19:01                 ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2014-01-08 19:01 UTC (permalink / raw)
  To: Linus Walleij
  Cc: linux-kernel, linux-arm-kernel, Arnd Bergmann, Rob Herring,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala, Rob Landley,
	Russell King, Thomas Gleixner, Grant Likely,
	open list:OPEN FIRMWARE AND...,
	open list:DOCUMENTATION

On Thu, 2014-01-02 at 13:32 +0100, Linus Walleij wrote:
> On Tue, Dec 17, 2013 at 8:37 PM, Sergei Ianovich <ynvich@gmail.com> wrote:
> Usually combined GPIO+IRQ controllers are put into drivers/gpio but
> this is a bit special as it seems to handle also non-GPIO-related IRQs
> so let's get some input on this.

This one is a plain IRQ controller. It has simple input lines, not GPIO
pins. The chip reports its status to upper level interrupt controller.
The upper level controller is PXA GPIO in this case.

(...)

> > +static struct irq_chip lp8x4x_irq_chip = {
> > +       .name                   = "FPGA",
> > +       .irq_ack                = lp8x4x_mask_irq,
> > +       .irq_mask               = lp8x4x_mask_irq,
> > +       .irq_mask_ack           = lp8x4x_mask_irq,
> > +       .irq_unmask             = lp8x4x_unmask_irq,
> > +};
> 
> After you have added your state container you will have
> a handle to your struct gpio_chip in the cookie passed to
> as irqdata.
> 
> Then you need to mark the GPIO lines used for IRQs by
> doing something similar to this patch in your startup()
> and shutdown() callbacks:
> http://marc.info/?l=linux-gpio&m=138547223832167&w=2

The chip requires no GPIO initialization. 

(...)

> > +       iowrite8(0, base + EOI);
> 
> This looks dangerous, what are you doing here?

This is done in kernel source which comes with the device. The
controller won't work without this line.

I cannot know for sure, as I don't have board datasheets or drawings. I
suspect, this clears GPIO line which reports interrupts to the upper
level controller.

(...)

> > +static int __init lp8x4x_irq_init(void)
> > +{
> > +       return platform_driver_register(&lp8x4x_irq_driver);
> > +}
> > +postcore_initcall(lp8x4x_irq_init);
> 
> Do you *have* to do it this early? I guess if it's used for
> the UARTs then yes, but make a case for it...

PXA isn't DT-only at the moment. As a result, it is impossible
to use IRQCHIP_DECLARE(). So drivers for the on-CPU IRQs and GPIO-IRQs
are loaded using postcore_initcall(). We need to have all irq domain
drivers loaded prior to DT parsing in order to allow normal
initialization of IRQ resources with DT. I'll update the commit message.

The rest of review comment are implemented. The changes don't affect any
other patches in the series. Should I repost the whole series?

Or only this patch?

Thanks.


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

* [PATCH v3 11/21] ARM: pxa: support ICP DAS LP-8x4x FPGA irq
@ 2014-01-08 19:01                 ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2014-01-08 19:01 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, 2014-01-02 at 13:32 +0100, Linus Walleij wrote:
> On Tue, Dec 17, 2013 at 8:37 PM, Sergei Ianovich <ynvich@gmail.com> wrote:
> Usually combined GPIO+IRQ controllers are put into drivers/gpio but
> this is a bit special as it seems to handle also non-GPIO-related IRQs
> so let's get some input on this.

This one is a plain IRQ controller. It has simple input lines, not GPIO
pins. The chip reports its status to upper level interrupt controller.
The upper level controller is PXA GPIO in this case.

(...)

> > +static struct irq_chip lp8x4x_irq_chip = {
> > +       .name                   = "FPGA",
> > +       .irq_ack                = lp8x4x_mask_irq,
> > +       .irq_mask               = lp8x4x_mask_irq,
> > +       .irq_mask_ack           = lp8x4x_mask_irq,
> > +       .irq_unmask             = lp8x4x_unmask_irq,
> > +};
> 
> After you have added your state container you will have
> a handle to your struct gpio_chip in the cookie passed to
> as irqdata.
> 
> Then you need to mark the GPIO lines used for IRQs by
> doing something similar to this patch in your startup()
> and shutdown() callbacks:
> http://marc.info/?l=linux-gpio&m=138547223832167&w=2

The chip requires no GPIO initialization. 

(...)

> > +       iowrite8(0, base + EOI);
> 
> This looks dangerous, what are you doing here?

This is done in kernel source which comes with the device. The
controller won't work without this line.

I cannot know for sure, as I don't have board datasheets or drawings. I
suspect, this clears GPIO line which reports interrupts to the upper
level controller.

(...)

> > +static int __init lp8x4x_irq_init(void)
> > +{
> > +       return platform_driver_register(&lp8x4x_irq_driver);
> > +}
> > +postcore_initcall(lp8x4x_irq_init);
> 
> Do you *have* to do it this early? I guess if it's used for
> the UARTs then yes, but make a case for it...

PXA isn't DT-only at the moment. As a result, it is impossible
to use IRQCHIP_DECLARE(). So drivers for the on-CPU IRQs and GPIO-IRQs
are loaded using postcore_initcall(). We need to have all irq domain
drivers loaded prior to DT parsing in order to allow normal
initialization of IRQ resources with DT. I'll update the commit message.

The rest of review comment are implemented. The changes don't affect any
other patches in the series. Should I repost the whole series?

Or only this patch?

Thanks.

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

* [PATCH v3.1 11/21] ARM: pxa: support ICP DAS LP-8x4x FPGA irq
@ 2014-01-09 23:07               ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2014-01-09 23:07 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Arnd Bergmann, Linus Walleij, Rob Herring,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala, Rob Landley,
	Russell King, Thomas Gleixner, Grant Likely,
	open list:OPEN FIRMWARE AND...,
	open list:DOCUMENTATION

ICP DAS LP-8x4x contains FPGA chip. The chip functions as an interrupt
source providing 16 additional interrupts among other things. The
interrupt lines are muxed to a GPIO pin of a 2nd level PXA-GPIO
interrupt controller. GPIO pins of the 2nd level controller are in turn
muxed to a CPU interrupt line.

Until pxa is completely converted to device tree, it is impossible
to use IRQCHIP_DECLARE() and the irqdomain needs to added manually.
Drivers for the on-CPU IRQs and GPIO-IRQs are loaded using
postcore_initcall(). We need to have all irq domain drivers loaded prior
to DT parsing in order to allow normal initialization of IRQ resources
with DT.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Arnd Bergmann <arnd@arndb.de>
CC: Linus Walleij <linus.walleij@linaro.org>
---
   v3..v3.1
   fixes according to Linus Walleij review comments:
   * update commit message
   * use state container instead of global variables
   * get hardware irq nums from irq_data, don't calculate them
   * use BIT() macro
   * add defines for system irq register masks
   * replace cycle control variable with break
   * use better names for resource variables
   * add a linear domain instead of a legacy one
   * use irq_create_mapping() instead of irq_alloc_desc()

   v2..v3
   * no changes (except number 09/16 -> 11/21)

   v0..v2
   * extract irqchip and move to drivers/irqchip/
   * use device tree
   * use devm helpers where possible

 .../bindings/interrupt-controller/irq-lp8x4x.txt   |  49 +++++
 arch/arm/boot/dts/pxa27x-lp8x4x.dts                |  10 +
 drivers/irqchip/Kconfig                            |   5 +
 drivers/irqchip/Makefile                           |   1 +
 drivers/irqchip/irq-lp8x4x.c                       | 238 +++++++++++++++++++++
 5 files changed, 303 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/interrupt-controller/irq-lp8x4x.txt
 create mode 100644 drivers/irqchip/irq-lp8x4x.c

diff --git a/Documentation/devicetree/bindings/interrupt-controller/irq-lp8x4x.txt b/Documentation/devicetree/bindings/interrupt-controller/irq-lp8x4x.txt
new file mode 100644
index 0000000..c8940d2
--- /dev/null
+++ b/Documentation/devicetree/bindings/interrupt-controller/irq-lp8x4x.txt
@@ -0,0 +1,49 @@
+ICP DAS LP-8x4x FPGA Interrupt Controller
+
+ICP DAS LP-8x4x contains FPGA chip. The chip functions as a interrupt
+source providing 16 additional interrupts among other things.
+
+Required properties:
+- compatible : should be "icpdas,irq-lp8x4x"
+
+- reg: physical base address of the controller and length of memory mapped
+  region.
+
+- interrupt-controller : identifies the node as an interrupt controller
+
+- #interrupt-cells : should be 1
+
+- interrupts : should provide interrupt
+
+- interrupt-parent : should provide a link to interrupt controller either
+		     explicitly and implicitly from a parent node
+
+Example:
+
+	fpga: fpga@17000006 {
+		compatible = "icpdas,irq-lp8x4x";
+		reg = <0x17000006 0x16>;
+		interrupt-parent = <&gpio>;
+		interrupts = <3 IRQ_TYPE_EDGE_RISING>;
+		#interrupt-cells = <1>;
+		interrupt-controller;
+		status = "okay";
+	};
+
+	uart@17009050 {
+		compatible = "icpdas,uart-lp8x4x";
+		reg = <0x17009050 0x10
+		       0x17009030 0x02>;
+		interrupt-parent = <&fpga>;
+		interrupts = <13>;
+		status = "okay";
+	};
+
+	uart@17009060 {
+		compatible = "icpdas,uart-lp8x4x";
+		reg = <0x17009060 0x10
+		       0x17009032 0x02>;
+		interrupt-parent = <&fpga>;
+		interrupts = <14>;
+		status = "okay";
+	};
diff --git a/arch/arm/boot/dts/pxa27x-lp8x4x.dts b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
index 07856e0..78dfd2e 100644
--- a/arch/arm/boot/dts/pxa27x-lp8x4x.dts
+++ b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
@@ -167,6 +167,16 @@
 				reg = <0xa000 0x1000
 				       0x901e 0x1>;
 			};
+
+			fpgairq: irq@9006 {
+				compatible = "icpdas,irq-lp8x4x";
+				reg = <0x9006 0x16>;
+				interrupt-parent = <&gpio>;
+				interrupts = <3 IRQ_TYPE_EDGE_FALLING>;
+				#interrupt-cells = <1>;
+				interrupt-controller;
+				status = "okay";
+			};
 		};
 	};
 };
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index 3792a1a..7e22729 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -35,6 +35,11 @@ config IMGPDC_IRQ
 	select GENERIC_IRQ_CHIP
 	select IRQ_DOMAIN
 
+config LP8X4X_IRQ
+	bool
+	depends on OF
+	select IRQ_DOMAIN
+
 config ORION_IRQCHIP
 	bool
 	select IRQ_DOMAIN
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index c60b901..8a28927 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -22,3 +22,4 @@ obj-$(CONFIG_RENESAS_IRQC)		+= irq-renesas-irqc.o
 obj-$(CONFIG_VERSATILE_FPGA_IRQ)	+= irq-versatile-fpga.o
 obj-$(CONFIG_ARCH_VT8500)		+= irq-vt8500.o
 obj-$(CONFIG_TB10X_IRQC)		+= irq-tb10x.o
+obj-$(CONFIG_LP8X4X_IRQ)		+= irq-lp8x4x.o
diff --git a/drivers/irqchip/irq-lp8x4x.c b/drivers/irqchip/irq-lp8x4x.c
new file mode 100644
index 0000000..61dfbed
--- /dev/null
+++ b/drivers/irqchip/irq-lp8x4x.c
@@ -0,0 +1,238 @@
+/*
+ *  linux/drivers/irqchip/irq-lp8x4x.c
+ *
+ *  Support for ICP DAS LP-8x4x FPGA irq
+ *  Copyright (C) 2013 Sergei Ianovich <ynvich@gmail.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation or any later version.
+ */
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/irqchip/chained_irq.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+#define EOI			0x00000000
+#define INSINT			0x00000002
+#define ENSYSINT		0x00000004
+#define PRIMINT			0x00000006
+#define PRIMINT_MASK		0xe0
+#define SECOINT			0x00000008
+#define SECOINT_MASK		0x1f
+#define ENRISEINT		0x0000000A
+#define CLRRISEINT		0x0000000C
+#define ENHILVINT		0x0000000E
+#define CLRHILVINT		0x00000010
+#define ENFALLINT		0x00000012
+#define CLRFALLINT		0x00000014
+#define IRQ_MEM_SIZE		0x00000016
+#define LP8X4X_NUM_IRQ_DEFAULT	16
+
+struct lp8x4x_irq_data {
+	void			*base;
+	struct irq_domain	*domain;
+	unsigned long		num_irq;
+	unsigned char		irq_sys_enabled;
+	unsigned char		irq_high_enabled;
+};
+
+static void lp8x4x_mask_irq(struct irq_data *d)
+{
+	unsigned mask;
+	unsigned long irq = d->hwirq;
+	struct lp8x4x_irq_data *host = irq_data_get_irq_chip_data(d);
+
+	if (!host) {
+		pr_err("lp8x4x: missing host data for irq %i\n", d->irq);
+		return;
+	}
+
+	if (irq >= host->num_irq) {
+		pr_err("lp8x4x: wrong irq handler for irq %i\n", d->irq);
+		return;
+	}
+
+	if (irq < 8) {
+		host->irq_high_enabled &= ~BIT(irq);
+
+		mask = ioread8(host->base + ENHILVINT);
+		mask &= ~BIT(irq);
+		iowrite8(mask, host->base + ENHILVINT);
+	} else {
+		irq -= 8;
+		host->irq_sys_enabled &= ~BIT(irq);
+
+		mask = ioread8(host->base + ENSYSINT);
+		mask &= ~BIT(irq);
+		iowrite8(mask, host->base + ENSYSINT);
+	}
+}
+
+static void lp8x4x_unmask_irq(struct irq_data *d)
+{
+	unsigned mask;
+	unsigned long irq = d->hwirq;
+	struct lp8x4x_irq_data *host = irq_data_get_irq_chip_data(d);
+
+	if (!host) {
+		pr_err("lp8x4x: missing host data for irq %i\n", d->irq);
+		return;
+	}
+
+	if (irq >= host->num_irq) {
+		pr_err("lp8x4x: wrong irq handler for irq %i\n", d->irq);
+		return;
+	}
+
+	if (irq < 8) {
+		host->irq_high_enabled |= BIT(irq);
+		mask = ioread8(host->base + CLRHILVINT);
+		mask |= BIT(irq);
+		iowrite8(mask, host->base + CLRHILVINT);
+
+		mask = ioread8(host->base + ENHILVINT);
+		mask |= BIT(irq);
+		iowrite8(mask, host->base + ENHILVINT);
+	} else {
+		irq -= 8;
+		host->irq_sys_enabled |= BIT(irq);
+
+		mask = ioread8(host->base + SECOINT);
+		mask |= BIT(irq);
+		iowrite8(mask, host->base + SECOINT);
+
+		mask = ioread8(host->base + ENSYSINT);
+		mask |= BIT(irq);
+		iowrite8(mask, host->base + ENSYSINT);
+	}
+}
+
+static struct irq_chip lp8x4x_irq_chip = {
+	.name			= "FPGA",
+	.irq_ack		= lp8x4x_mask_irq,
+	.irq_mask		= lp8x4x_mask_irq,
+	.irq_mask_ack		= lp8x4x_mask_irq,
+	.irq_unmask		= lp8x4x_unmask_irq,
+};
+
+static void lp8x4x_irq_handler(unsigned int irq, struct irq_desc *desc)
+{
+	int n;
+	unsigned long mask;
+	struct irq_chip *chip = irq_desc_get_chip(desc);
+	struct lp8x4x_irq_data *host = irq_desc_get_handler_data(desc);
+
+	if (!host)
+		return;
+
+	chained_irq_enter(chip, desc);
+
+	for (;;) {
+		mask = ioread8(host->base + CLRHILVINT) & 0xff;
+		mask |= (ioread8(host->base + SECOINT) & SECOINT_MASK) << 8;
+		mask |= (ioread8(host->base + PRIMINT) & PRIMINT_MASK) << 8;
+		mask &= host->irq_high_enabled | (host->irq_sys_enabled << 8);
+		if (mask == 0)
+			break;
+		for_each_set_bit(n, &mask, BITS_PER_LONG)
+			generic_handle_irq(irq_find_mapping(host->domain, n));
+	}
+
+	iowrite8(0, host->base + EOI);
+	chained_irq_exit(chip, desc);
+}
+
+static int lp8x4x_irq_domain_map(struct irq_domain *d, unsigned int irq,
+				 irq_hw_number_t hw)
+{
+	struct lp8x4x_irq_data *host = d->host_data;
+	int err;
+
+	err = irq_set_chip_data(irq, host);
+	if (err < 0)
+		return err;
+
+	irq_set_chip_and_handler(irq, &lp8x4x_irq_chip, handle_level_irq);
+	set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+	return 0;
+}
+
+const struct irq_domain_ops lp8x4x_irq_domain_ops = {
+	.map	= lp8x4x_irq_domain_map,
+	.xlate	= irq_domain_xlate_onecell,
+};
+
+static struct of_device_id lp8x4x_irq_dt_ids[] = {
+	{ .compatible = "icpdas,irq-lp8x4x", },
+	{}
+};
+
+static int lp8x4x_irq_probe(struct platform_device *pdev)
+{
+	struct resource *res_mem, *res_irq;
+	struct device_node *np = pdev->dev.of_node;
+	struct lp8x4x_irq_data *host;
+	int i, err;
+
+	res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!res_mem || !res_irq || resource_size(res_mem) < IRQ_MEM_SIZE)
+		return -ENODEV;
+
+	host = devm_kzalloc(&pdev->dev, sizeof(*host), GFP_KERNEL);
+	if (!host)
+		return -ENODEV;
+
+	host->num_irq = LP8X4X_NUM_IRQ_DEFAULT;
+	host->base = devm_ioremap_resource(&pdev->dev, res_mem);
+	if (!host->base) {
+		dev_err(&pdev->dev, "Failed to ioremap %p\n", host->base);
+		return -EFAULT;
+	}
+
+	host->domain = irq_domain_add_linear(np, host->num_irq,
+				       &lp8x4x_irq_domain_ops, host);
+	if (!host->domain) {
+		dev_err(&pdev->dev, "Failed to add IRQ domain\n");
+		return -ENOMEM;
+	}
+
+	for (i = 0; i < host->num_irq; i++) {
+		err = irq_create_mapping(host->domain, i);
+		if (err < 0)
+			dev_err(&pdev->dev, "Failed to map IRQ %i\n", i);
+	}
+
+	/* Initialize chip registers */
+	iowrite8(0, host->base + CLRRISEINT);
+	iowrite8(0, host->base + ENRISEINT);
+	iowrite8(0, host->base + CLRFALLINT);
+	iowrite8(0, host->base + ENFALLINT);
+	iowrite8(0, host->base + CLRHILVINT);
+	iowrite8(0, host->base + ENHILVINT);
+	iowrite8(0, host->base + ENSYSINT);
+	iowrite8(0, host->base + SECOINT);
+
+	irq_set_handler_data(res_irq->start, host);
+	irq_set_chained_handler(res_irq->start, lp8x4x_irq_handler);
+
+	return 0;
+}
+
+static struct platform_driver lp8x4x_irq_driver = {
+	.probe		= lp8x4x_irq_probe,
+	.driver		= {
+		.name	= "irq-lp8x4x",
+		.of_match_table = lp8x4x_irq_dt_ids,
+	},
+};
+
+static int __init lp8x4x_irq_init(void)
+{
+	return platform_driver_register(&lp8x4x_irq_driver);
+}
+postcore_initcall(lp8x4x_irq_init);
-- 
1.8.4.2


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

* [PATCH v3.1 11/21] ARM: pxa: support ICP DAS LP-8x4x FPGA irq
@ 2014-01-09 23:07               ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2014-01-09 23:07 UTC (permalink / raw)
  To: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
  Cc: Sergei Ianovich, Arnd Bergmann, Linus Walleij, Rob Herring,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala, Rob Landley,
	Russell King, Thomas Gleixner, Grant Likely,
	open list:OPEN FIRMWARE AND...,
	open list:DOCUMENTATION

ICP DAS LP-8x4x contains FPGA chip. The chip functions as an interrupt
source providing 16 additional interrupts among other things. The
interrupt lines are muxed to a GPIO pin of a 2nd level PXA-GPIO
interrupt controller. GPIO pins of the 2nd level controller are in turn
muxed to a CPU interrupt line.

Until pxa is completely converted to device tree, it is impossible
to use IRQCHIP_DECLARE() and the irqdomain needs to added manually.
Drivers for the on-CPU IRQs and GPIO-IRQs are loaded using
postcore_initcall(). We need to have all irq domain drivers loaded prior
to DT parsing in order to allow normal initialization of IRQ resources
with DT.

Signed-off-by: Sergei Ianovich <ynvich-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
CC: Arnd Bergmann <arnd-r2nGTMty4D4@public.gmane.org>
CC: Linus Walleij <linus.walleij-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
---
   v3..v3.1
   fixes according to Linus Walleij review comments:
   * update commit message
   * use state container instead of global variables
   * get hardware irq nums from irq_data, don't calculate them
   * use BIT() macro
   * add defines for system irq register masks
   * replace cycle control variable with break
   * use better names for resource variables
   * add a linear domain instead of a legacy one
   * use irq_create_mapping() instead of irq_alloc_desc()

   v2..v3
   * no changes (except number 09/16 -> 11/21)

   v0..v2
   * extract irqchip and move to drivers/irqchip/
   * use device tree
   * use devm helpers where possible

 .../bindings/interrupt-controller/irq-lp8x4x.txt   |  49 +++++
 arch/arm/boot/dts/pxa27x-lp8x4x.dts                |  10 +
 drivers/irqchip/Kconfig                            |   5 +
 drivers/irqchip/Makefile                           |   1 +
 drivers/irqchip/irq-lp8x4x.c                       | 238 +++++++++++++++++++++
 5 files changed, 303 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/interrupt-controller/irq-lp8x4x.txt
 create mode 100644 drivers/irqchip/irq-lp8x4x.c

diff --git a/Documentation/devicetree/bindings/interrupt-controller/irq-lp8x4x.txt b/Documentation/devicetree/bindings/interrupt-controller/irq-lp8x4x.txt
new file mode 100644
index 0000000..c8940d2
--- /dev/null
+++ b/Documentation/devicetree/bindings/interrupt-controller/irq-lp8x4x.txt
@@ -0,0 +1,49 @@
+ICP DAS LP-8x4x FPGA Interrupt Controller
+
+ICP DAS LP-8x4x contains FPGA chip. The chip functions as a interrupt
+source providing 16 additional interrupts among other things.
+
+Required properties:
+- compatible : should be "icpdas,irq-lp8x4x"
+
+- reg: physical base address of the controller and length of memory mapped
+  region.
+
+- interrupt-controller : identifies the node as an interrupt controller
+
+- #interrupt-cells : should be 1
+
+- interrupts : should provide interrupt
+
+- interrupt-parent : should provide a link to interrupt controller either
+		     explicitly and implicitly from a parent node
+
+Example:
+
+	fpga: fpga@17000006 {
+		compatible = "icpdas,irq-lp8x4x";
+		reg = <0x17000006 0x16>;
+		interrupt-parent = <&gpio>;
+		interrupts = <3 IRQ_TYPE_EDGE_RISING>;
+		#interrupt-cells = <1>;
+		interrupt-controller;
+		status = "okay";
+	};
+
+	uart@17009050 {
+		compatible = "icpdas,uart-lp8x4x";
+		reg = <0x17009050 0x10
+		       0x17009030 0x02>;
+		interrupt-parent = <&fpga>;
+		interrupts = <13>;
+		status = "okay";
+	};
+
+	uart@17009060 {
+		compatible = "icpdas,uart-lp8x4x";
+		reg = <0x17009060 0x10
+		       0x17009032 0x02>;
+		interrupt-parent = <&fpga>;
+		interrupts = <14>;
+		status = "okay";
+	};
diff --git a/arch/arm/boot/dts/pxa27x-lp8x4x.dts b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
index 07856e0..78dfd2e 100644
--- a/arch/arm/boot/dts/pxa27x-lp8x4x.dts
+++ b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
@@ -167,6 +167,16 @@
 				reg = <0xa000 0x1000
 				       0x901e 0x1>;
 			};
+
+			fpgairq: irq@9006 {
+				compatible = "icpdas,irq-lp8x4x";
+				reg = <0x9006 0x16>;
+				interrupt-parent = <&gpio>;
+				interrupts = <3 IRQ_TYPE_EDGE_FALLING>;
+				#interrupt-cells = <1>;
+				interrupt-controller;
+				status = "okay";
+			};
 		};
 	};
 };
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index 3792a1a..7e22729 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -35,6 +35,11 @@ config IMGPDC_IRQ
 	select GENERIC_IRQ_CHIP
 	select IRQ_DOMAIN
 
+config LP8X4X_IRQ
+	bool
+	depends on OF
+	select IRQ_DOMAIN
+
 config ORION_IRQCHIP
 	bool
 	select IRQ_DOMAIN
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index c60b901..8a28927 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -22,3 +22,4 @@ obj-$(CONFIG_RENESAS_IRQC)		+= irq-renesas-irqc.o
 obj-$(CONFIG_VERSATILE_FPGA_IRQ)	+= irq-versatile-fpga.o
 obj-$(CONFIG_ARCH_VT8500)		+= irq-vt8500.o
 obj-$(CONFIG_TB10X_IRQC)		+= irq-tb10x.o
+obj-$(CONFIG_LP8X4X_IRQ)		+= irq-lp8x4x.o
diff --git a/drivers/irqchip/irq-lp8x4x.c b/drivers/irqchip/irq-lp8x4x.c
new file mode 100644
index 0000000..61dfbed
--- /dev/null
+++ b/drivers/irqchip/irq-lp8x4x.c
@@ -0,0 +1,238 @@
+/*
+ *  linux/drivers/irqchip/irq-lp8x4x.c
+ *
+ *  Support for ICP DAS LP-8x4x FPGA irq
+ *  Copyright (C) 2013 Sergei Ianovich <ynvich-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation or any later version.
+ */
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/irqchip/chained_irq.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+#define EOI			0x00000000
+#define INSINT			0x00000002
+#define ENSYSINT		0x00000004
+#define PRIMINT			0x00000006
+#define PRIMINT_MASK		0xe0
+#define SECOINT			0x00000008
+#define SECOINT_MASK		0x1f
+#define ENRISEINT		0x0000000A
+#define CLRRISEINT		0x0000000C
+#define ENHILVINT		0x0000000E
+#define CLRHILVINT		0x00000010
+#define ENFALLINT		0x00000012
+#define CLRFALLINT		0x00000014
+#define IRQ_MEM_SIZE		0x00000016
+#define LP8X4X_NUM_IRQ_DEFAULT	16
+
+struct lp8x4x_irq_data {
+	void			*base;
+	struct irq_domain	*domain;
+	unsigned long		num_irq;
+	unsigned char		irq_sys_enabled;
+	unsigned char		irq_high_enabled;
+};
+
+static void lp8x4x_mask_irq(struct irq_data *d)
+{
+	unsigned mask;
+	unsigned long irq = d->hwirq;
+	struct lp8x4x_irq_data *host = irq_data_get_irq_chip_data(d);
+
+	if (!host) {
+		pr_err("lp8x4x: missing host data for irq %i\n", d->irq);
+		return;
+	}
+
+	if (irq >= host->num_irq) {
+		pr_err("lp8x4x: wrong irq handler for irq %i\n", d->irq);
+		return;
+	}
+
+	if (irq < 8) {
+		host->irq_high_enabled &= ~BIT(irq);
+
+		mask = ioread8(host->base + ENHILVINT);
+		mask &= ~BIT(irq);
+		iowrite8(mask, host->base + ENHILVINT);
+	} else {
+		irq -= 8;
+		host->irq_sys_enabled &= ~BIT(irq);
+
+		mask = ioread8(host->base + ENSYSINT);
+		mask &= ~BIT(irq);
+		iowrite8(mask, host->base + ENSYSINT);
+	}
+}
+
+static void lp8x4x_unmask_irq(struct irq_data *d)
+{
+	unsigned mask;
+	unsigned long irq = d->hwirq;
+	struct lp8x4x_irq_data *host = irq_data_get_irq_chip_data(d);
+
+	if (!host) {
+		pr_err("lp8x4x: missing host data for irq %i\n", d->irq);
+		return;
+	}
+
+	if (irq >= host->num_irq) {
+		pr_err("lp8x4x: wrong irq handler for irq %i\n", d->irq);
+		return;
+	}
+
+	if (irq < 8) {
+		host->irq_high_enabled |= BIT(irq);
+		mask = ioread8(host->base + CLRHILVINT);
+		mask |= BIT(irq);
+		iowrite8(mask, host->base + CLRHILVINT);
+
+		mask = ioread8(host->base + ENHILVINT);
+		mask |= BIT(irq);
+		iowrite8(mask, host->base + ENHILVINT);
+	} else {
+		irq -= 8;
+		host->irq_sys_enabled |= BIT(irq);
+
+		mask = ioread8(host->base + SECOINT);
+		mask |= BIT(irq);
+		iowrite8(mask, host->base + SECOINT);
+
+		mask = ioread8(host->base + ENSYSINT);
+		mask |= BIT(irq);
+		iowrite8(mask, host->base + ENSYSINT);
+	}
+}
+
+static struct irq_chip lp8x4x_irq_chip = {
+	.name			= "FPGA",
+	.irq_ack		= lp8x4x_mask_irq,
+	.irq_mask		= lp8x4x_mask_irq,
+	.irq_mask_ack		= lp8x4x_mask_irq,
+	.irq_unmask		= lp8x4x_unmask_irq,
+};
+
+static void lp8x4x_irq_handler(unsigned int irq, struct irq_desc *desc)
+{
+	int n;
+	unsigned long mask;
+	struct irq_chip *chip = irq_desc_get_chip(desc);
+	struct lp8x4x_irq_data *host = irq_desc_get_handler_data(desc);
+
+	if (!host)
+		return;
+
+	chained_irq_enter(chip, desc);
+
+	for (;;) {
+		mask = ioread8(host->base + CLRHILVINT) & 0xff;
+		mask |= (ioread8(host->base + SECOINT) & SECOINT_MASK) << 8;
+		mask |= (ioread8(host->base + PRIMINT) & PRIMINT_MASK) << 8;
+		mask &= host->irq_high_enabled | (host->irq_sys_enabled << 8);
+		if (mask == 0)
+			break;
+		for_each_set_bit(n, &mask, BITS_PER_LONG)
+			generic_handle_irq(irq_find_mapping(host->domain, n));
+	}
+
+	iowrite8(0, host->base + EOI);
+	chained_irq_exit(chip, desc);
+}
+
+static int lp8x4x_irq_domain_map(struct irq_domain *d, unsigned int irq,
+				 irq_hw_number_t hw)
+{
+	struct lp8x4x_irq_data *host = d->host_data;
+	int err;
+
+	err = irq_set_chip_data(irq, host);
+	if (err < 0)
+		return err;
+
+	irq_set_chip_and_handler(irq, &lp8x4x_irq_chip, handle_level_irq);
+	set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+	return 0;
+}
+
+const struct irq_domain_ops lp8x4x_irq_domain_ops = {
+	.map	= lp8x4x_irq_domain_map,
+	.xlate	= irq_domain_xlate_onecell,
+};
+
+static struct of_device_id lp8x4x_irq_dt_ids[] = {
+	{ .compatible = "icpdas,irq-lp8x4x", },
+	{}
+};
+
+static int lp8x4x_irq_probe(struct platform_device *pdev)
+{
+	struct resource *res_mem, *res_irq;
+	struct device_node *np = pdev->dev.of_node;
+	struct lp8x4x_irq_data *host;
+	int i, err;
+
+	res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!res_mem || !res_irq || resource_size(res_mem) < IRQ_MEM_SIZE)
+		return -ENODEV;
+
+	host = devm_kzalloc(&pdev->dev, sizeof(*host), GFP_KERNEL);
+	if (!host)
+		return -ENODEV;
+
+	host->num_irq = LP8X4X_NUM_IRQ_DEFAULT;
+	host->base = devm_ioremap_resource(&pdev->dev, res_mem);
+	if (!host->base) {
+		dev_err(&pdev->dev, "Failed to ioremap %p\n", host->base);
+		return -EFAULT;
+	}
+
+	host->domain = irq_domain_add_linear(np, host->num_irq,
+				       &lp8x4x_irq_domain_ops, host);
+	if (!host->domain) {
+		dev_err(&pdev->dev, "Failed to add IRQ domain\n");
+		return -ENOMEM;
+	}
+
+	for (i = 0; i < host->num_irq; i++) {
+		err = irq_create_mapping(host->domain, i);
+		if (err < 0)
+			dev_err(&pdev->dev, "Failed to map IRQ %i\n", i);
+	}
+
+	/* Initialize chip registers */
+	iowrite8(0, host->base + CLRRISEINT);
+	iowrite8(0, host->base + ENRISEINT);
+	iowrite8(0, host->base + CLRFALLINT);
+	iowrite8(0, host->base + ENFALLINT);
+	iowrite8(0, host->base + CLRHILVINT);
+	iowrite8(0, host->base + ENHILVINT);
+	iowrite8(0, host->base + ENSYSINT);
+	iowrite8(0, host->base + SECOINT);
+
+	irq_set_handler_data(res_irq->start, host);
+	irq_set_chained_handler(res_irq->start, lp8x4x_irq_handler);
+
+	return 0;
+}
+
+static struct platform_driver lp8x4x_irq_driver = {
+	.probe		= lp8x4x_irq_probe,
+	.driver		= {
+		.name	= "irq-lp8x4x",
+		.of_match_table = lp8x4x_irq_dt_ids,
+	},
+};
+
+static int __init lp8x4x_irq_init(void)
+{
+	return platform_driver_register(&lp8x4x_irq_driver);
+}
+postcore_initcall(lp8x4x_irq_init);
-- 
1.8.4.2

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH v3.1 11/21] ARM: pxa: support ICP DAS LP-8x4x FPGA irq
@ 2014-01-09 23:07               ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2014-01-09 23:07 UTC (permalink / raw)
  To: linux-arm-kernel

ICP DAS LP-8x4x contains FPGA chip. The chip functions as an interrupt
source providing 16 additional interrupts among other things. The
interrupt lines are muxed to a GPIO pin of a 2nd level PXA-GPIO
interrupt controller. GPIO pins of the 2nd level controller are in turn
muxed to a CPU interrupt line.

Until pxa is completely converted to device tree, it is impossible
to use IRQCHIP_DECLARE() and the irqdomain needs to added manually.
Drivers for the on-CPU IRQs and GPIO-IRQs are loaded using
postcore_initcall(). We need to have all irq domain drivers loaded prior
to DT parsing in order to allow normal initialization of IRQ resources
with DT.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Arnd Bergmann <arnd@arndb.de>
CC: Linus Walleij <linus.walleij@linaro.org>
---
   v3..v3.1
   fixes according to Linus Walleij review comments:
   * update commit message
   * use state container instead of global variables
   * get hardware irq nums from irq_data, don't calculate them
   * use BIT() macro
   * add defines for system irq register masks
   * replace cycle control variable with break
   * use better names for resource variables
   * add a linear domain instead of a legacy one
   * use irq_create_mapping() instead of irq_alloc_desc()

   v2..v3
   * no changes (except number 09/16 -> 11/21)

   v0..v2
   * extract irqchip and move to drivers/irqchip/
   * use device tree
   * use devm helpers where possible

 .../bindings/interrupt-controller/irq-lp8x4x.txt   |  49 +++++
 arch/arm/boot/dts/pxa27x-lp8x4x.dts                |  10 +
 drivers/irqchip/Kconfig                            |   5 +
 drivers/irqchip/Makefile                           |   1 +
 drivers/irqchip/irq-lp8x4x.c                       | 238 +++++++++++++++++++++
 5 files changed, 303 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/interrupt-controller/irq-lp8x4x.txt
 create mode 100644 drivers/irqchip/irq-lp8x4x.c

diff --git a/Documentation/devicetree/bindings/interrupt-controller/irq-lp8x4x.txt b/Documentation/devicetree/bindings/interrupt-controller/irq-lp8x4x.txt
new file mode 100644
index 0000000..c8940d2
--- /dev/null
+++ b/Documentation/devicetree/bindings/interrupt-controller/irq-lp8x4x.txt
@@ -0,0 +1,49 @@
+ICP DAS LP-8x4x FPGA Interrupt Controller
+
+ICP DAS LP-8x4x contains FPGA chip. The chip functions as a interrupt
+source providing 16 additional interrupts among other things.
+
+Required properties:
+- compatible : should be "icpdas,irq-lp8x4x"
+
+- reg: physical base address of the controller and length of memory mapped
+  region.
+
+- interrupt-controller : identifies the node as an interrupt controller
+
+- #interrupt-cells : should be 1
+
+- interrupts : should provide interrupt
+
+- interrupt-parent : should provide a link to interrupt controller either
+		     explicitly and implicitly from a parent node
+
+Example:
+
+	fpga: fpga at 17000006 {
+		compatible = "icpdas,irq-lp8x4x";
+		reg = <0x17000006 0x16>;
+		interrupt-parent = <&gpio>;
+		interrupts = <3 IRQ_TYPE_EDGE_RISING>;
+		#interrupt-cells = <1>;
+		interrupt-controller;
+		status = "okay";
+	};
+
+	uart at 17009050 {
+		compatible = "icpdas,uart-lp8x4x";
+		reg = <0x17009050 0x10
+		       0x17009030 0x02>;
+		interrupt-parent = <&fpga>;
+		interrupts = <13>;
+		status = "okay";
+	};
+
+	uart at 17009060 {
+		compatible = "icpdas,uart-lp8x4x";
+		reg = <0x17009060 0x10
+		       0x17009032 0x02>;
+		interrupt-parent = <&fpga>;
+		interrupts = <14>;
+		status = "okay";
+	};
diff --git a/arch/arm/boot/dts/pxa27x-lp8x4x.dts b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
index 07856e0..78dfd2e 100644
--- a/arch/arm/boot/dts/pxa27x-lp8x4x.dts
+++ b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
@@ -167,6 +167,16 @@
 				reg = <0xa000 0x1000
 				       0x901e 0x1>;
 			};
+
+			fpgairq: irq at 9006 {
+				compatible = "icpdas,irq-lp8x4x";
+				reg = <0x9006 0x16>;
+				interrupt-parent = <&gpio>;
+				interrupts = <3 IRQ_TYPE_EDGE_FALLING>;
+				#interrupt-cells = <1>;
+				interrupt-controller;
+				status = "okay";
+			};
 		};
 	};
 };
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index 3792a1a..7e22729 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -35,6 +35,11 @@ config IMGPDC_IRQ
 	select GENERIC_IRQ_CHIP
 	select IRQ_DOMAIN
 
+config LP8X4X_IRQ
+	bool
+	depends on OF
+	select IRQ_DOMAIN
+
 config ORION_IRQCHIP
 	bool
 	select IRQ_DOMAIN
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index c60b901..8a28927 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -22,3 +22,4 @@ obj-$(CONFIG_RENESAS_IRQC)		+= irq-renesas-irqc.o
 obj-$(CONFIG_VERSATILE_FPGA_IRQ)	+= irq-versatile-fpga.o
 obj-$(CONFIG_ARCH_VT8500)		+= irq-vt8500.o
 obj-$(CONFIG_TB10X_IRQC)		+= irq-tb10x.o
+obj-$(CONFIG_LP8X4X_IRQ)		+= irq-lp8x4x.o
diff --git a/drivers/irqchip/irq-lp8x4x.c b/drivers/irqchip/irq-lp8x4x.c
new file mode 100644
index 0000000..61dfbed
--- /dev/null
+++ b/drivers/irqchip/irq-lp8x4x.c
@@ -0,0 +1,238 @@
+/*
+ *  linux/drivers/irqchip/irq-lp8x4x.c
+ *
+ *  Support for ICP DAS LP-8x4x FPGA irq
+ *  Copyright (C) 2013 Sergei Ianovich <ynvich@gmail.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation or any later version.
+ */
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/irqchip/chained_irq.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+#define EOI			0x00000000
+#define INSINT			0x00000002
+#define ENSYSINT		0x00000004
+#define PRIMINT			0x00000006
+#define PRIMINT_MASK		0xe0
+#define SECOINT			0x00000008
+#define SECOINT_MASK		0x1f
+#define ENRISEINT		0x0000000A
+#define CLRRISEINT		0x0000000C
+#define ENHILVINT		0x0000000E
+#define CLRHILVINT		0x00000010
+#define ENFALLINT		0x00000012
+#define CLRFALLINT		0x00000014
+#define IRQ_MEM_SIZE		0x00000016
+#define LP8X4X_NUM_IRQ_DEFAULT	16
+
+struct lp8x4x_irq_data {
+	void			*base;
+	struct irq_domain	*domain;
+	unsigned long		num_irq;
+	unsigned char		irq_sys_enabled;
+	unsigned char		irq_high_enabled;
+};
+
+static void lp8x4x_mask_irq(struct irq_data *d)
+{
+	unsigned mask;
+	unsigned long irq = d->hwirq;
+	struct lp8x4x_irq_data *host = irq_data_get_irq_chip_data(d);
+
+	if (!host) {
+		pr_err("lp8x4x: missing host data for irq %i\n", d->irq);
+		return;
+	}
+
+	if (irq >= host->num_irq) {
+		pr_err("lp8x4x: wrong irq handler for irq %i\n", d->irq);
+		return;
+	}
+
+	if (irq < 8) {
+		host->irq_high_enabled &= ~BIT(irq);
+
+		mask = ioread8(host->base + ENHILVINT);
+		mask &= ~BIT(irq);
+		iowrite8(mask, host->base + ENHILVINT);
+	} else {
+		irq -= 8;
+		host->irq_sys_enabled &= ~BIT(irq);
+
+		mask = ioread8(host->base + ENSYSINT);
+		mask &= ~BIT(irq);
+		iowrite8(mask, host->base + ENSYSINT);
+	}
+}
+
+static void lp8x4x_unmask_irq(struct irq_data *d)
+{
+	unsigned mask;
+	unsigned long irq = d->hwirq;
+	struct lp8x4x_irq_data *host = irq_data_get_irq_chip_data(d);
+
+	if (!host) {
+		pr_err("lp8x4x: missing host data for irq %i\n", d->irq);
+		return;
+	}
+
+	if (irq >= host->num_irq) {
+		pr_err("lp8x4x: wrong irq handler for irq %i\n", d->irq);
+		return;
+	}
+
+	if (irq < 8) {
+		host->irq_high_enabled |= BIT(irq);
+		mask = ioread8(host->base + CLRHILVINT);
+		mask |= BIT(irq);
+		iowrite8(mask, host->base + CLRHILVINT);
+
+		mask = ioread8(host->base + ENHILVINT);
+		mask |= BIT(irq);
+		iowrite8(mask, host->base + ENHILVINT);
+	} else {
+		irq -= 8;
+		host->irq_sys_enabled |= BIT(irq);
+
+		mask = ioread8(host->base + SECOINT);
+		mask |= BIT(irq);
+		iowrite8(mask, host->base + SECOINT);
+
+		mask = ioread8(host->base + ENSYSINT);
+		mask |= BIT(irq);
+		iowrite8(mask, host->base + ENSYSINT);
+	}
+}
+
+static struct irq_chip lp8x4x_irq_chip = {
+	.name			= "FPGA",
+	.irq_ack		= lp8x4x_mask_irq,
+	.irq_mask		= lp8x4x_mask_irq,
+	.irq_mask_ack		= lp8x4x_mask_irq,
+	.irq_unmask		= lp8x4x_unmask_irq,
+};
+
+static void lp8x4x_irq_handler(unsigned int irq, struct irq_desc *desc)
+{
+	int n;
+	unsigned long mask;
+	struct irq_chip *chip = irq_desc_get_chip(desc);
+	struct lp8x4x_irq_data *host = irq_desc_get_handler_data(desc);
+
+	if (!host)
+		return;
+
+	chained_irq_enter(chip, desc);
+
+	for (;;) {
+		mask = ioread8(host->base + CLRHILVINT) & 0xff;
+		mask |= (ioread8(host->base + SECOINT) & SECOINT_MASK) << 8;
+		mask |= (ioread8(host->base + PRIMINT) & PRIMINT_MASK) << 8;
+		mask &= host->irq_high_enabled | (host->irq_sys_enabled << 8);
+		if (mask == 0)
+			break;
+		for_each_set_bit(n, &mask, BITS_PER_LONG)
+			generic_handle_irq(irq_find_mapping(host->domain, n));
+	}
+
+	iowrite8(0, host->base + EOI);
+	chained_irq_exit(chip, desc);
+}
+
+static int lp8x4x_irq_domain_map(struct irq_domain *d, unsigned int irq,
+				 irq_hw_number_t hw)
+{
+	struct lp8x4x_irq_data *host = d->host_data;
+	int err;
+
+	err = irq_set_chip_data(irq, host);
+	if (err < 0)
+		return err;
+
+	irq_set_chip_and_handler(irq, &lp8x4x_irq_chip, handle_level_irq);
+	set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+	return 0;
+}
+
+const struct irq_domain_ops lp8x4x_irq_domain_ops = {
+	.map	= lp8x4x_irq_domain_map,
+	.xlate	= irq_domain_xlate_onecell,
+};
+
+static struct of_device_id lp8x4x_irq_dt_ids[] = {
+	{ .compatible = "icpdas,irq-lp8x4x", },
+	{}
+};
+
+static int lp8x4x_irq_probe(struct platform_device *pdev)
+{
+	struct resource *res_mem, *res_irq;
+	struct device_node *np = pdev->dev.of_node;
+	struct lp8x4x_irq_data *host;
+	int i, err;
+
+	res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!res_mem || !res_irq || resource_size(res_mem) < IRQ_MEM_SIZE)
+		return -ENODEV;
+
+	host = devm_kzalloc(&pdev->dev, sizeof(*host), GFP_KERNEL);
+	if (!host)
+		return -ENODEV;
+
+	host->num_irq = LP8X4X_NUM_IRQ_DEFAULT;
+	host->base = devm_ioremap_resource(&pdev->dev, res_mem);
+	if (!host->base) {
+		dev_err(&pdev->dev, "Failed to ioremap %p\n", host->base);
+		return -EFAULT;
+	}
+
+	host->domain = irq_domain_add_linear(np, host->num_irq,
+				       &lp8x4x_irq_domain_ops, host);
+	if (!host->domain) {
+		dev_err(&pdev->dev, "Failed to add IRQ domain\n");
+		return -ENOMEM;
+	}
+
+	for (i = 0; i < host->num_irq; i++) {
+		err = irq_create_mapping(host->domain, i);
+		if (err < 0)
+			dev_err(&pdev->dev, "Failed to map IRQ %i\n", i);
+	}
+
+	/* Initialize chip registers */
+	iowrite8(0, host->base + CLRRISEINT);
+	iowrite8(0, host->base + ENRISEINT);
+	iowrite8(0, host->base + CLRFALLINT);
+	iowrite8(0, host->base + ENFALLINT);
+	iowrite8(0, host->base + CLRHILVINT);
+	iowrite8(0, host->base + ENHILVINT);
+	iowrite8(0, host->base + ENSYSINT);
+	iowrite8(0, host->base + SECOINT);
+
+	irq_set_handler_data(res_irq->start, host);
+	irq_set_chained_handler(res_irq->start, lp8x4x_irq_handler);
+
+	return 0;
+}
+
+static struct platform_driver lp8x4x_irq_driver = {
+	.probe		= lp8x4x_irq_probe,
+	.driver		= {
+		.name	= "irq-lp8x4x",
+		.of_match_table = lp8x4x_irq_dt_ids,
+	},
+};
+
+static int __init lp8x4x_irq_init(void)
+{
+	return platform_driver_register(&lp8x4x_irq_driver);
+}
+postcore_initcall(lp8x4x_irq_init);
-- 
1.8.4.2

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

* Re: [PATCH v2 00/16] ARM: support for ICP DAS LP-8x4x (with dts)
  2013-12-19  5:30                                   ` Arnd Bergmann
@ 2014-01-09 23:12                                     ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2014-01-09 23:12 UTC (permalink / raw)
  To: Arnd Bergmann; +Cc: linux-kernel, linux-arm-kernel, Daniel Mack, Haojian Zhuang

On Thu, 2013-12-19 at 06:30 +0100, Arnd Bergmann wrote:
> This would work only if we can probe the devices behind the external
> bus controller before the controller itsef has been set up, since
> the initialization order can depend on a number of things but not
> the bus hierarchy. It will also work if the code setting up the
> bus controller can be guaranteed to run before we call
> of_platform_populate for the regular devices, which is probably
> the best solution here.

There has been no activity for 3 weeks. Could we resume the series?



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

* [PATCH v2 00/16] ARM: support for ICP DAS LP-8x4x (with dts)
@ 2014-01-09 23:12                                     ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2014-01-09 23:12 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, 2013-12-19 at 06:30 +0100, Arnd Bergmann wrote:
> This would work only if we can probe the devices behind the external
> bus controller before the controller itsef has been set up, since
> the initialization order can depend on a number of things but not
> the bus hierarchy. It will also work if the code setting up the
> bus controller can be guaranteed to run before we call
> of_platform_populate for the regular devices, which is probably
> the best solution here.

There has been no activity for 3 weeks. Could we resume the series?

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

* Re: [PATCH v3 11/21] ARM: pxa: support ICP DAS LP-8x4x FPGA irq
  2014-01-08 19:01                 ` Sergei Ianovich
  (?)
@ 2014-01-15  7:39                   ` Linus Walleij
  -1 siblings, 0 replies; 700+ messages in thread
From: Linus Walleij @ 2014-01-15  7:39 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: linux-kernel, linux-arm-kernel, Arnd Bergmann, Rob Herring,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala, Rob Landley,
	Russell King, Thomas Gleixner, Grant Likely,
	open list:OPEN FIRMWARE AND...,
	open list:DOCUMENTATION

On Wed, Jan 8, 2014 at 8:01 PM, Sergei Ianovich <ynvich@gmail.com> wrote:
> On Thu, 2014-01-02 at 13:32 +0100, Linus Walleij wrote:
>> On Tue, Dec 17, 2013 at 8:37 PM, Sergei Ianovich <ynvich@gmail.com> wrote:
>> Usually combined GPIO+IRQ controllers are put into drivers/gpio but
>> this is a bit special as it seems to handle also non-GPIO-related IRQs
>> so let's get some input on this.
>
> This one is a plain IRQ controller. It has simple input lines, not GPIO
> pins. The chip reports its status to upper level interrupt controller.
> The upper level controller is PXA GPIO in this case.

Hm I don't know why I was deluded into thinking this had something to
do with GPIO. I must have been soft in the head. Sorry about all those
comments ...

I'll re-read the irqchip driver v3.1.

Yours,
Linus Walleij

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

* Re: [PATCH v3 11/21] ARM: pxa: support ICP DAS LP-8x4x FPGA irq
@ 2014-01-15  7:39                   ` Linus Walleij
  0 siblings, 0 replies; 700+ messages in thread
From: Linus Walleij @ 2014-01-15  7:39 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: linux-kernel, linux-arm-kernel, Arnd Bergmann, Rob Herring,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala, Rob Landley,
	Russell King, Thomas Gleixner, Grant Likely,
	open list:OPEN FIRMWARE AND...,
	open list:DOCUMENTATION

On Wed, Jan 8, 2014 at 8:01 PM, Sergei Ianovich <ynvich@gmail.com> wrote:
> On Thu, 2014-01-02 at 13:32 +0100, Linus Walleij wrote:
>> On Tue, Dec 17, 2013 at 8:37 PM, Sergei Ianovich <ynvich@gmail.com> wrote:
>> Usually combined GPIO+IRQ controllers are put into drivers/gpio but
>> this is a bit special as it seems to handle also non-GPIO-related IRQs
>> so let's get some input on this.
>
> This one is a plain IRQ controller. It has simple input lines, not GPIO
> pins. The chip reports its status to upper level interrupt controller.
> The upper level controller is PXA GPIO in this case.

Hm I don't know why I was deluded into thinking this had something to
do with GPIO. I must have been soft in the head. Sorry about all those
comments ...

I'll re-read the irqchip driver v3.1.

Yours,
Linus Walleij

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

* [PATCH v3 11/21] ARM: pxa: support ICP DAS LP-8x4x FPGA irq
@ 2014-01-15  7:39                   ` Linus Walleij
  0 siblings, 0 replies; 700+ messages in thread
From: Linus Walleij @ 2014-01-15  7:39 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Jan 8, 2014 at 8:01 PM, Sergei Ianovich <ynvich@gmail.com> wrote:
> On Thu, 2014-01-02 at 13:32 +0100, Linus Walleij wrote:
>> On Tue, Dec 17, 2013 at 8:37 PM, Sergei Ianovich <ynvich@gmail.com> wrote:
>> Usually combined GPIO+IRQ controllers are put into drivers/gpio but
>> this is a bit special as it seems to handle also non-GPIO-related IRQs
>> so let's get some input on this.
>
> This one is a plain IRQ controller. It has simple input lines, not GPIO
> pins. The chip reports its status to upper level interrupt controller.
> The upper level controller is PXA GPIO in this case.

Hm I don't know why I was deluded into thinking this had something to
do with GPIO. I must have been soft in the head. Sorry about all those
comments ...

I'll re-read the irqchip driver v3.1.

Yours,
Linus Walleij

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

* Re: [PATCH v3.1 11/21] ARM: pxa: support ICP DAS LP-8x4x FPGA irq
  2014-01-09 23:07               ` Sergei Ianovich
  (?)
@ 2014-01-15  7:46                 ` Linus Walleij
  -1 siblings, 0 replies; 700+ messages in thread
From: Linus Walleij @ 2014-01-15  7:46 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: linux-kernel, linux-arm-kernel, Arnd Bergmann, Rob Herring,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala, Rob Landley,
	Russell King, Thomas Gleixner, Grant Likely,
	open list:OPEN FIRMWARE AND...,
	open list:DOCUMENTATION

This is looking much better!

On Fri, Jan 10, 2014 at 12:07 AM, Sergei Ianovich <ynvich@gmail.com> wrote:

> +++ b/drivers/irqchip/irq-lp8x4x.c
(...)

You could add some kerneldoc to this following struct (OK nitpick, but
still nice, especially for the last two variables).

> +struct lp8x4x_irq_data {
> +       void                    *base;
> +       struct irq_domain       *domain;
> +       unsigned long           num_irq;
> +       unsigned char           irq_sys_enabled;
> +       unsigned char           irq_high_enabled;
> +};
> +
> +static void lp8x4x_mask_irq(struct irq_data *d)
> +{
> +       unsigned mask;
> +       unsigned long irq = d->hwirq;

Name the local variable hwirq too so we know what it is.

> +       struct lp8x4x_irq_data *host = irq_data_get_irq_chip_data(d);
> +
> +       if (!host) {
> +               pr_err("lp8x4x: missing host data for irq %i\n", d->irq);
> +               return;
> +       }
> +
> +       if (irq >= host->num_irq) {
> +               pr_err("lp8x4x: wrong irq handler for irq %i\n", d->irq);
> +               return;
> +       }

This is on the hotpath. Do you *really* need these two checks?

(...)
> +static void lp8x4x_unmask_irq(struct irq_data *d)
> +{
> +       unsigned mask;
> +       unsigned long irq = d->hwirq;

Name the variable "hwirq".

> +       struct lp8x4x_irq_data *host = irq_data_get_irq_chip_data(d);
> +
> +       if (!host) {
> +               pr_err("lp8x4x: missing host data for irq %i\n", d->irq);
> +               return;
> +       }
> +
> +       if (irq >= host->num_irq) {
> +               pr_err("lp8x4x: wrong irq handler for irq %i\n", d->irq);
> +               return;
> +       }

Again overzealous error checks.

(...)
> +static void lp8x4x_irq_handler(unsigned int irq, struct irq_desc *desc)
> +{
> +       int n;
> +       unsigned long mask;
> +       struct irq_chip *chip = irq_desc_get_chip(desc);
> +       struct lp8x4x_irq_data *host = irq_desc_get_handler_data(desc);
> +
> +       if (!host)
> +               return;

I don't think this happens either?

> +       chained_irq_enter(chip, desc);
> +
> +       for (;;) {
> +               mask = ioread8(host->base + CLRHILVINT) & 0xff;
> +               mask |= (ioread8(host->base + SECOINT) & SECOINT_MASK) << 8;
> +               mask |= (ioread8(host->base + PRIMINT) & PRIMINT_MASK) << 8;
> +               mask &= host->irq_high_enabled | (host->irq_sys_enabled << 8);
> +               if (mask == 0)
> +                       break;
> +               for_each_set_bit(n, &mask, BITS_PER_LONG)
> +                       generic_handle_irq(irq_find_mapping(host->domain, n));
> +       }

I like the looks of this.

If you fix this:
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>

Yours,
Linus Walleij

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

* Re: [PATCH v3.1 11/21] ARM: pxa: support ICP DAS LP-8x4x FPGA irq
@ 2014-01-15  7:46                 ` Linus Walleij
  0 siblings, 0 replies; 700+ messages in thread
From: Linus Walleij @ 2014-01-15  7:46 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: linux-kernel, linux-arm-kernel, Arnd Bergmann, Rob Herring,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala, Rob Landley,
	Russell King, Thomas Gleixner, Grant Likely,
	open list:OPEN FIRMWARE AND...,
	open list:DOCUMENTATION

This is looking much better!

On Fri, Jan 10, 2014 at 12:07 AM, Sergei Ianovich <ynvich@gmail.com> wrote:

> +++ b/drivers/irqchip/irq-lp8x4x.c
(...)

You could add some kerneldoc to this following struct (OK nitpick, but
still nice, especially for the last two variables).

> +struct lp8x4x_irq_data {
> +       void                    *base;
> +       struct irq_domain       *domain;
> +       unsigned long           num_irq;
> +       unsigned char           irq_sys_enabled;
> +       unsigned char           irq_high_enabled;
> +};
> +
> +static void lp8x4x_mask_irq(struct irq_data *d)
> +{
> +       unsigned mask;
> +       unsigned long irq = d->hwirq;

Name the local variable hwirq too so we know what it is.

> +       struct lp8x4x_irq_data *host = irq_data_get_irq_chip_data(d);
> +
> +       if (!host) {
> +               pr_err("lp8x4x: missing host data for irq %i\n", d->irq);
> +               return;
> +       }
> +
> +       if (irq >= host->num_irq) {
> +               pr_err("lp8x4x: wrong irq handler for irq %i\n", d->irq);
> +               return;
> +       }

This is on the hotpath. Do you *really* need these two checks?

(...)
> +static void lp8x4x_unmask_irq(struct irq_data *d)
> +{
> +       unsigned mask;
> +       unsigned long irq = d->hwirq;

Name the variable "hwirq".

> +       struct lp8x4x_irq_data *host = irq_data_get_irq_chip_data(d);
> +
> +       if (!host) {
> +               pr_err("lp8x4x: missing host data for irq %i\n", d->irq);
> +               return;
> +       }
> +
> +       if (irq >= host->num_irq) {
> +               pr_err("lp8x4x: wrong irq handler for irq %i\n", d->irq);
> +               return;
> +       }

Again overzealous error checks.

(...)
> +static void lp8x4x_irq_handler(unsigned int irq, struct irq_desc *desc)
> +{
> +       int n;
> +       unsigned long mask;
> +       struct irq_chip *chip = irq_desc_get_chip(desc);
> +       struct lp8x4x_irq_data *host = irq_desc_get_handler_data(desc);
> +
> +       if (!host)
> +               return;

I don't think this happens either?

> +       chained_irq_enter(chip, desc);
> +
> +       for (;;) {
> +               mask = ioread8(host->base + CLRHILVINT) & 0xff;
> +               mask |= (ioread8(host->base + SECOINT) & SECOINT_MASK) << 8;
> +               mask |= (ioread8(host->base + PRIMINT) & PRIMINT_MASK) << 8;
> +               mask &= host->irq_high_enabled | (host->irq_sys_enabled << 8);
> +               if (mask == 0)
> +                       break;
> +               for_each_set_bit(n, &mask, BITS_PER_LONG)
> +                       generic_handle_irq(irq_find_mapping(host->domain, n));
> +       }

I like the looks of this.

If you fix this:
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>

Yours,
Linus Walleij

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

* [PATCH v3.1 11/21] ARM: pxa: support ICP DAS LP-8x4x FPGA irq
@ 2014-01-15  7:46                 ` Linus Walleij
  0 siblings, 0 replies; 700+ messages in thread
From: Linus Walleij @ 2014-01-15  7:46 UTC (permalink / raw)
  To: linux-arm-kernel

This is looking much better!

On Fri, Jan 10, 2014 at 12:07 AM, Sergei Ianovich <ynvich@gmail.com> wrote:

> +++ b/drivers/irqchip/irq-lp8x4x.c
(...)

You could add some kerneldoc to this following struct (OK nitpick, but
still nice, especially for the last two variables).

> +struct lp8x4x_irq_data {
> +       void                    *base;
> +       struct irq_domain       *domain;
> +       unsigned long           num_irq;
> +       unsigned char           irq_sys_enabled;
> +       unsigned char           irq_high_enabled;
> +};
> +
> +static void lp8x4x_mask_irq(struct irq_data *d)
> +{
> +       unsigned mask;
> +       unsigned long irq = d->hwirq;

Name the local variable hwirq too so we know what it is.

> +       struct lp8x4x_irq_data *host = irq_data_get_irq_chip_data(d);
> +
> +       if (!host) {
> +               pr_err("lp8x4x: missing host data for irq %i\n", d->irq);
> +               return;
> +       }
> +
> +       if (irq >= host->num_irq) {
> +               pr_err("lp8x4x: wrong irq handler for irq %i\n", d->irq);
> +               return;
> +       }

This is on the hotpath. Do you *really* need these two checks?

(...)
> +static void lp8x4x_unmask_irq(struct irq_data *d)
> +{
> +       unsigned mask;
> +       unsigned long irq = d->hwirq;

Name the variable "hwirq".

> +       struct lp8x4x_irq_data *host = irq_data_get_irq_chip_data(d);
> +
> +       if (!host) {
> +               pr_err("lp8x4x: missing host data for irq %i\n", d->irq);
> +               return;
> +       }
> +
> +       if (irq >= host->num_irq) {
> +               pr_err("lp8x4x: wrong irq handler for irq %i\n", d->irq);
> +               return;
> +       }

Again overzealous error checks.

(...)
> +static void lp8x4x_irq_handler(unsigned int irq, struct irq_desc *desc)
> +{
> +       int n;
> +       unsigned long mask;
> +       struct irq_chip *chip = irq_desc_get_chip(desc);
> +       struct lp8x4x_irq_data *host = irq_desc_get_handler_data(desc);
> +
> +       if (!host)
> +               return;

I don't think this happens either?

> +       chained_irq_enter(chip, desc);
> +
> +       for (;;) {
> +               mask = ioread8(host->base + CLRHILVINT) & 0xff;
> +               mask |= (ioread8(host->base + SECOINT) & SECOINT_MASK) << 8;
> +               mask |= (ioread8(host->base + PRIMINT) & PRIMINT_MASK) << 8;
> +               mask &= host->irq_high_enabled | (host->irq_sys_enabled << 8);
> +               if (mask == 0)
> +                       break;
> +               for_each_set_bit(n, &mask, BITS_PER_LONG)
> +                       generic_handle_irq(irq_find_mapping(host->domain, n));
> +       }

I like the looks of this.

If you fix this:
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>

Yours,
Linus Walleij

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

* [PATCH v3.2 11/21] ARM: pxa: support ICP DAS LP-8x4x FPGA irq
  2014-01-09 23:07               ` Sergei Ianovich
  (?)
@ 2014-01-15 13:12                 ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2014-01-15 13:12 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Linus Walleij, Sergei Ianovich, Arnd Bergmann, Rob Herring,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala, Rob Landley,
	Russell King, Thomas Gleixner, Grant Likely,
	open list:OPEN FIRMWARE AND...,
	open list:DOCUMENTATION

ICP DAS LP-8x4x contains FPGA chip. The chip functions as an interrupt
source providing 16 additional interrupts among other things. The
interrupt lines are muxed to a GPIO pin of a 2nd level PXA-GPIO
interrupt controller. GPIO pins of the 2nd level controller are in turn
muxed to a CPU interrupt line.

Until pxa is completely converted to device tree, it is impossible
to use IRQCHIP_DECLARE() and the irqdomain needs to added manually.
Drivers for the on-CPU IRQs and GPIO-IRQs are loaded using
postcore_initcall(). We need to have all irq domain drivers loaded prior
to DT parsing in order to allow normal initialization of IRQ resources
with DT.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
CC: Arnd Bergmann <arnd@arndb.de>
---
   v3.1..v3.2
   fixes to apply Linus Walleij's "Reviewed-by":
   * add kerneldoc comment for state container struct
   * rename irq -> hwirq for clarity
   * drop overzealous error checks from the hotpaths

   v3..v3.1
   fixes according to Linus Walleij review comments:
   * update commit message
   * use state container instead of global variables
   * get hardware irq nums from irq_data, don't calculate them
   * use BIT() macro
   * add defines for system irq register masks
   * replace cycle control variable with break
   * use better names for resource variables
   * add a linear domain instead of a legacy one
   * use irq_create_mapping() instead of irq_alloc_desc()

   v2..v3
   * no changes (except number 09/16 -> 11/21)

   v0..v2
   * extract irqchip and move to drivers/irqchip/
   * use device tree
   * use devm helpers where possible

 .../bindings/interrupt-controller/irq-lp8x4x.txt   |  49 +++++
 arch/arm/boot/dts/pxa27x-lp8x4x.dts                |  10 +
 drivers/irqchip/Kconfig                            |   5 +
 drivers/irqchip/Makefile                           |   1 +
 drivers/irqchip/irq-lp8x4x.c                       | 227 +++++++++++++++++++++
 5 files changed, 292 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/interrupt-controller/irq-lp8x4x.txt
 create mode 100644 drivers/irqchip/irq-lp8x4x.c

diff --git a/Documentation/devicetree/bindings/interrupt-controller/irq-lp8x4x.txt b/Documentation/devicetree/bindings/interrupt-controller/irq-lp8x4x.txt
new file mode 100644
index 0000000..c8940d2
--- /dev/null
+++ b/Documentation/devicetree/bindings/interrupt-controller/irq-lp8x4x.txt
@@ -0,0 +1,49 @@
+ICP DAS LP-8x4x FPGA Interrupt Controller
+
+ICP DAS LP-8x4x contains FPGA chip. The chip functions as a interrupt
+source providing 16 additional interrupts among other things.
+
+Required properties:
+- compatible : should be "icpdas,irq-lp8x4x"
+
+- reg: physical base address of the controller and length of memory mapped
+  region.
+
+- interrupt-controller : identifies the node as an interrupt controller
+
+- #interrupt-cells : should be 1
+
+- interrupts : should provide interrupt
+
+- interrupt-parent : should provide a link to interrupt controller either
+		     explicitly and implicitly from a parent node
+
+Example:
+
+	fpga: fpga@17000006 {
+		compatible = "icpdas,irq-lp8x4x";
+		reg = <0x17000006 0x16>;
+		interrupt-parent = <&gpio>;
+		interrupts = <3 IRQ_TYPE_EDGE_RISING>;
+		#interrupt-cells = <1>;
+		interrupt-controller;
+		status = "okay";
+	};
+
+	uart@17009050 {
+		compatible = "icpdas,uart-lp8x4x";
+		reg = <0x17009050 0x10
+		       0x17009030 0x02>;
+		interrupt-parent = <&fpga>;
+		interrupts = <13>;
+		status = "okay";
+	};
+
+	uart@17009060 {
+		compatible = "icpdas,uart-lp8x4x";
+		reg = <0x17009060 0x10
+		       0x17009032 0x02>;
+		interrupt-parent = <&fpga>;
+		interrupts = <14>;
+		status = "okay";
+	};
diff --git a/arch/arm/boot/dts/pxa27x-lp8x4x.dts b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
index 07856e0..78dfd2e 100644
--- a/arch/arm/boot/dts/pxa27x-lp8x4x.dts
+++ b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
@@ -167,6 +167,16 @@
 				reg = <0xa000 0x1000
 				       0x901e 0x1>;
 			};
+
+			fpgairq: irq@9006 {
+				compatible = "icpdas,irq-lp8x4x";
+				reg = <0x9006 0x16>;
+				interrupt-parent = <&gpio>;
+				interrupts = <3 IRQ_TYPE_EDGE_FALLING>;
+				#interrupt-cells = <1>;
+				interrupt-controller;
+				status = "okay";
+			};
 		};
 	};
 };
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index 3792a1a..7e22729 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -35,6 +35,11 @@ config IMGPDC_IRQ
 	select GENERIC_IRQ_CHIP
 	select IRQ_DOMAIN
 
+config LP8X4X_IRQ
+	bool
+	depends on OF
+	select IRQ_DOMAIN
+
 config ORION_IRQCHIP
 	bool
 	select IRQ_DOMAIN
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index c60b901..8a28927 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -22,3 +22,4 @@ obj-$(CONFIG_RENESAS_IRQC)		+= irq-renesas-irqc.o
 obj-$(CONFIG_VERSATILE_FPGA_IRQ)	+= irq-versatile-fpga.o
 obj-$(CONFIG_ARCH_VT8500)		+= irq-vt8500.o
 obj-$(CONFIG_TB10X_IRQC)		+= irq-tb10x.o
+obj-$(CONFIG_LP8X4X_IRQ)		+= irq-lp8x4x.o
diff --git a/drivers/irqchip/irq-lp8x4x.c b/drivers/irqchip/irq-lp8x4x.c
new file mode 100644
index 0000000..12ccbb03
--- /dev/null
+++ b/drivers/irqchip/irq-lp8x4x.c
@@ -0,0 +1,227 @@
+/*
+ *  linux/drivers/irqchip/irq-lp8x4x.c
+ *
+ *  Support for ICP DAS LP-8x4x FPGA irq
+ *  Copyright (C) 2013 Sergei Ianovich <ynvich@gmail.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation or any later version.
+ */
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/irqchip/chained_irq.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+#define EOI			0x00000000
+#define INSINT			0x00000002
+#define ENSYSINT		0x00000004
+#define PRIMINT			0x00000006
+#define PRIMINT_MASK		0xe0
+#define SECOINT			0x00000008
+#define SECOINT_MASK		0x1f
+#define ENRISEINT		0x0000000A
+#define CLRRISEINT		0x0000000C
+#define ENHILVINT		0x0000000E
+#define CLRHILVINT		0x00000010
+#define ENFALLINT		0x00000012
+#define CLRFALLINT		0x00000014
+#define IRQ_MEM_SIZE		0x00000016
+#define LP8X4X_NUM_IRQ_DEFAULT	16
+
+/**
+ * struct lp8x4x_irq_data - LP8X4X custom irq controller state container
+ * @base:               base IO memory address
+ * @irq_domain:         Interrupt translation domain; responsible for mapping
+ *                      between hwirq number and linux irq number
+ * @irq_sys_enabled:    mask keeping track of interrupts enabled in the
+ *                      register which vendor calls 'system'
+ * @irq_high_enabled:   mask keeping track of interrupts enabled in the
+ *                      register which vendor calls 'high'
+ *
+ * The structure implements State Container from
+ * Documentation/driver-model/design-patterns.txt
+ */
+
+struct lp8x4x_irq_data {
+	void			*base;
+	struct irq_domain	*domain;
+	unsigned char		irq_sys_enabled;
+	unsigned char		irq_high_enabled;
+};
+
+static void lp8x4x_mask_irq(struct irq_data *d)
+{
+	unsigned mask;
+	unsigned long hwirq = d->hwirq;
+	struct lp8x4x_irq_data *host = irq_data_get_irq_chip_data(d);
+
+	if (hwirq < 8) {
+		host->irq_high_enabled &= ~BIT(hwirq);
+
+		mask = ioread8(host->base + ENHILVINT);
+		mask &= ~BIT(hwirq);
+		iowrite8(mask, host->base + ENHILVINT);
+	} else {
+		hwirq -= 8;
+		host->irq_sys_enabled &= ~BIT(hwirq);
+
+		mask = ioread8(host->base + ENSYSINT);
+		mask &= ~BIT(hwirq);
+		iowrite8(mask, host->base + ENSYSINT);
+	}
+}
+
+static void lp8x4x_unmask_irq(struct irq_data *d)
+{
+	unsigned mask;
+	unsigned long hwirq = d->hwirq;
+	struct lp8x4x_irq_data *host = irq_data_get_irq_chip_data(d);
+
+	if (hwirq < 8) {
+		host->irq_high_enabled |= BIT(hwirq);
+		mask = ioread8(host->base + CLRHILVINT);
+		mask |= BIT(hwirq);
+		iowrite8(mask, host->base + CLRHILVINT);
+
+		mask = ioread8(host->base + ENHILVINT);
+		mask |= BIT(hwirq);
+		iowrite8(mask, host->base + ENHILVINT);
+	} else {
+		hwirq -= 8;
+		host->irq_sys_enabled |= BIT(hwirq);
+
+		mask = ioread8(host->base + SECOINT);
+		mask |= BIT(hwirq);
+		iowrite8(mask, host->base + SECOINT);
+
+		mask = ioread8(host->base + ENSYSINT);
+		mask |= BIT(hwirq);
+		iowrite8(mask, host->base + ENSYSINT);
+	}
+}
+
+static struct irq_chip lp8x4x_irq_chip = {
+	.name			= "FPGA",
+	.irq_ack		= lp8x4x_mask_irq,
+	.irq_mask		= lp8x4x_mask_irq,
+	.irq_mask_ack		= lp8x4x_mask_irq,
+	.irq_unmask		= lp8x4x_unmask_irq,
+};
+
+static void lp8x4x_irq_handler(unsigned int irq, struct irq_desc *desc)
+{
+	int n;
+	unsigned long mask;
+	struct irq_chip *chip = irq_desc_get_chip(desc);
+	struct lp8x4x_irq_data *host = irq_desc_get_handler_data(desc);
+
+	chained_irq_enter(chip, desc);
+
+	for (;;) {
+		mask = ioread8(host->base + CLRHILVINT) & 0xff;
+		mask |= (ioread8(host->base + SECOINT) & SECOINT_MASK) << 8;
+		mask |= (ioread8(host->base + PRIMINT) & PRIMINT_MASK) << 8;
+		mask &= host->irq_high_enabled | (host->irq_sys_enabled << 8);
+		if (mask == 0)
+			break;
+		for_each_set_bit(n, &mask, BITS_PER_LONG)
+			generic_handle_irq(irq_find_mapping(host->domain, n));
+	}
+
+	iowrite8(0, host->base + EOI);
+	chained_irq_exit(chip, desc);
+}
+
+static int lp8x4x_irq_domain_map(struct irq_domain *d, unsigned int irq,
+				 irq_hw_number_t hw)
+{
+	struct lp8x4x_irq_data *host = d->host_data;
+	int err;
+
+	err = irq_set_chip_data(irq, host);
+	if (err < 0)
+		return err;
+
+	irq_set_chip_and_handler(irq, &lp8x4x_irq_chip, handle_level_irq);
+	set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+	return 0;
+}
+
+const struct irq_domain_ops lp8x4x_irq_domain_ops = {
+	.map	= lp8x4x_irq_domain_map,
+	.xlate	= irq_domain_xlate_onecell,
+};
+
+static struct of_device_id lp8x4x_irq_dt_ids[] = {
+	{ .compatible = "icpdas,irq-lp8x4x", },
+	{}
+};
+
+static int lp8x4x_irq_probe(struct platform_device *pdev)
+{
+	struct resource *res_mem, *res_irq;
+	struct device_node *np = pdev->dev.of_node;
+	struct lp8x4x_irq_data *host;
+	int i, err;
+
+	res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!res_mem || !res_irq || resource_size(res_mem) < IRQ_MEM_SIZE)
+		return -ENODEV;
+
+	host = devm_kzalloc(&pdev->dev, sizeof(*host), GFP_KERNEL);
+	if (!host)
+		return -ENODEV;
+
+	host->base = devm_ioremap_resource(&pdev->dev, res_mem);
+	if (!host->base) {
+		dev_err(&pdev->dev, "Failed to ioremap %p\n", host->base);
+		return -EFAULT;
+	}
+
+	host->domain = irq_domain_add_linear(np, LP8X4X_NUM_IRQ_DEFAULT,
+				       &lp8x4x_irq_domain_ops, host);
+	if (!host->domain) {
+		dev_err(&pdev->dev, "Failed to add IRQ domain\n");
+		return -ENOMEM;
+	}
+
+	for (i = 0; i < LP8X4X_NUM_IRQ_DEFAULT; i++) {
+		err = irq_create_mapping(host->domain, i);
+		if (err < 0)
+			dev_err(&pdev->dev, "Failed to map IRQ %i\n", i);
+	}
+
+	/* Initialize chip registers */
+	iowrite8(0, host->base + CLRRISEINT);
+	iowrite8(0, host->base + ENRISEINT);
+	iowrite8(0, host->base + CLRFALLINT);
+	iowrite8(0, host->base + ENFALLINT);
+	iowrite8(0, host->base + CLRHILVINT);
+	iowrite8(0, host->base + ENHILVINT);
+	iowrite8(0, host->base + ENSYSINT);
+	iowrite8(0, host->base + SECOINT);
+
+	irq_set_handler_data(res_irq->start, host);
+	irq_set_chained_handler(res_irq->start, lp8x4x_irq_handler);
+
+	return 0;
+}
+
+static struct platform_driver lp8x4x_irq_driver = {
+	.probe		= lp8x4x_irq_probe,
+	.driver		= {
+		.name	= "irq-lp8x4x",
+		.of_match_table = lp8x4x_irq_dt_ids,
+	},
+};
+
+static int __init lp8x4x_irq_init(void)
+{
+	return platform_driver_register(&lp8x4x_irq_driver);
+}
+postcore_initcall(lp8x4x_irq_init);
-- 
1.8.4.2


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

* [PATCH v3.2 11/21] ARM: pxa: support ICP DAS LP-8x4x FPGA irq
@ 2014-01-15 13:12                 ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2014-01-15 13:12 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Linus Walleij, Sergei Ianovich, Arnd Bergmann, Rob Herring,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala, Rob Landley,
	Russell King, Thomas Gleixner, Grant Likely,
	open list:OPEN FIRMWARE AND...,
	open list:DOCUMENTATION

ICP DAS LP-8x4x contains FPGA chip. The chip functions as an interrupt
source providing 16 additional interrupts among other things. The
interrupt lines are muxed to a GPIO pin of a 2nd level PXA-GPIO
interrupt controller. GPIO pins of the 2nd level controller are in turn
muxed to a CPU interrupt line.

Until pxa is completely converted to device tree, it is impossible
to use IRQCHIP_DECLARE() and the irqdomain needs to added manually.
Drivers for the on-CPU IRQs and GPIO-IRQs are loaded using
postcore_initcall(). We need to have all irq domain drivers loaded prior
to DT parsing in order to allow normal initialization of IRQ resources
with DT.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
CC: Arnd Bergmann <arnd@arndb.de>
---
   v3.1..v3.2
   fixes to apply Linus Walleij's "Reviewed-by":
   * add kerneldoc comment for state container struct
   * rename irq -> hwirq for clarity
   * drop overzealous error checks from the hotpaths

   v3..v3.1
   fixes according to Linus Walleij review comments:
   * update commit message
   * use state container instead of global variables
   * get hardware irq nums from irq_data, don't calculate them
   * use BIT() macro
   * add defines for system irq register masks
   * replace cycle control variable with break
   * use better names for resource variables
   * add a linear domain instead of a legacy one
   * use irq_create_mapping() instead of irq_alloc_desc()

   v2..v3
   * no changes (except number 09/16 -> 11/21)

   v0..v2
   * extract irqchip and move to drivers/irqchip/
   * use device tree
   * use devm helpers where possible

 .../bindings/interrupt-controller/irq-lp8x4x.txt   |  49 +++++
 arch/arm/boot/dts/pxa27x-lp8x4x.dts                |  10 +
 drivers/irqchip/Kconfig                            |   5 +
 drivers/irqchip/Makefile                           |   1 +
 drivers/irqchip/irq-lp8x4x.c                       | 227 +++++++++++++++++++++
 5 files changed, 292 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/interrupt-controller/irq-lp8x4x.txt
 create mode 100644 drivers/irqchip/irq-lp8x4x.c

diff --git a/Documentation/devicetree/bindings/interrupt-controller/irq-lp8x4x.txt b/Documentation/devicetree/bindings/interrupt-controller/irq-lp8x4x.txt
new file mode 100644
index 0000000..c8940d2
--- /dev/null
+++ b/Documentation/devicetree/bindings/interrupt-controller/irq-lp8x4x.txt
@@ -0,0 +1,49 @@
+ICP DAS LP-8x4x FPGA Interrupt Controller
+
+ICP DAS LP-8x4x contains FPGA chip. The chip functions as a interrupt
+source providing 16 additional interrupts among other things.
+
+Required properties:
+- compatible : should be "icpdas,irq-lp8x4x"
+
+- reg: physical base address of the controller and length of memory mapped
+  region.
+
+- interrupt-controller : identifies the node as an interrupt controller
+
+- #interrupt-cells : should be 1
+
+- interrupts : should provide interrupt
+
+- interrupt-parent : should provide a link to interrupt controller either
+		     explicitly and implicitly from a parent node
+
+Example:
+
+	fpga: fpga@17000006 {
+		compatible = "icpdas,irq-lp8x4x";
+		reg = <0x17000006 0x16>;
+		interrupt-parent = <&gpio>;
+		interrupts = <3 IRQ_TYPE_EDGE_RISING>;
+		#interrupt-cells = <1>;
+		interrupt-controller;
+		status = "okay";
+	};
+
+	uart@17009050 {
+		compatible = "icpdas,uart-lp8x4x";
+		reg = <0x17009050 0x10
+		       0x17009030 0x02>;
+		interrupt-parent = <&fpga>;
+		interrupts = <13>;
+		status = "okay";
+	};
+
+	uart@17009060 {
+		compatible = "icpdas,uart-lp8x4x";
+		reg = <0x17009060 0x10
+		       0x17009032 0x02>;
+		interrupt-parent = <&fpga>;
+		interrupts = <14>;
+		status = "okay";
+	};
diff --git a/arch/arm/boot/dts/pxa27x-lp8x4x.dts b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
index 07856e0..78dfd2e 100644
--- a/arch/arm/boot/dts/pxa27x-lp8x4x.dts
+++ b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
@@ -167,6 +167,16 @@
 				reg = <0xa000 0x1000
 				       0x901e 0x1>;
 			};
+
+			fpgairq: irq@9006 {
+				compatible = "icpdas,irq-lp8x4x";
+				reg = <0x9006 0x16>;
+				interrupt-parent = <&gpio>;
+				interrupts = <3 IRQ_TYPE_EDGE_FALLING>;
+				#interrupt-cells = <1>;
+				interrupt-controller;
+				status = "okay";
+			};
 		};
 	};
 };
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index 3792a1a..7e22729 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -35,6 +35,11 @@ config IMGPDC_IRQ
 	select GENERIC_IRQ_CHIP
 	select IRQ_DOMAIN
 
+config LP8X4X_IRQ
+	bool
+	depends on OF
+	select IRQ_DOMAIN
+
 config ORION_IRQCHIP
 	bool
 	select IRQ_DOMAIN
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index c60b901..8a28927 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -22,3 +22,4 @@ obj-$(CONFIG_RENESAS_IRQC)		+= irq-renesas-irqc.o
 obj-$(CONFIG_VERSATILE_FPGA_IRQ)	+= irq-versatile-fpga.o
 obj-$(CONFIG_ARCH_VT8500)		+= irq-vt8500.o
 obj-$(CONFIG_TB10X_IRQC)		+= irq-tb10x.o
+obj-$(CONFIG_LP8X4X_IRQ)		+= irq-lp8x4x.o
diff --git a/drivers/irqchip/irq-lp8x4x.c b/drivers/irqchip/irq-lp8x4x.c
new file mode 100644
index 0000000..12ccbb03
--- /dev/null
+++ b/drivers/irqchip/irq-lp8x4x.c
@@ -0,0 +1,227 @@
+/*
+ *  linux/drivers/irqchip/irq-lp8x4x.c
+ *
+ *  Support for ICP DAS LP-8x4x FPGA irq
+ *  Copyright (C) 2013 Sergei Ianovich <ynvich@gmail.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation or any later version.
+ */
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/irqchip/chained_irq.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+#define EOI			0x00000000
+#define INSINT			0x00000002
+#define ENSYSINT		0x00000004
+#define PRIMINT			0x00000006
+#define PRIMINT_MASK		0xe0
+#define SECOINT			0x00000008
+#define SECOINT_MASK		0x1f
+#define ENRISEINT		0x0000000A
+#define CLRRISEINT		0x0000000C
+#define ENHILVINT		0x0000000E
+#define CLRHILVINT		0x00000010
+#define ENFALLINT		0x00000012
+#define CLRFALLINT		0x00000014
+#define IRQ_MEM_SIZE		0x00000016
+#define LP8X4X_NUM_IRQ_DEFAULT	16
+
+/**
+ * struct lp8x4x_irq_data - LP8X4X custom irq controller state container
+ * @base:               base IO memory address
+ * @irq_domain:         Interrupt translation domain; responsible for mapping
+ *                      between hwirq number and linux irq number
+ * @irq_sys_enabled:    mask keeping track of interrupts enabled in the
+ *                      register which vendor calls 'system'
+ * @irq_high_enabled:   mask keeping track of interrupts enabled in the
+ *                      register which vendor calls 'high'
+ *
+ * The structure implements State Container from
+ * Documentation/driver-model/design-patterns.txt
+ */
+
+struct lp8x4x_irq_data {
+	void			*base;
+	struct irq_domain	*domain;
+	unsigned char		irq_sys_enabled;
+	unsigned char		irq_high_enabled;
+};
+
+static void lp8x4x_mask_irq(struct irq_data *d)
+{
+	unsigned mask;
+	unsigned long hwirq = d->hwirq;
+	struct lp8x4x_irq_data *host = irq_data_get_irq_chip_data(d);
+
+	if (hwirq < 8) {
+		host->irq_high_enabled &= ~BIT(hwirq);
+
+		mask = ioread8(host->base + ENHILVINT);
+		mask &= ~BIT(hwirq);
+		iowrite8(mask, host->base + ENHILVINT);
+	} else {
+		hwirq -= 8;
+		host->irq_sys_enabled &= ~BIT(hwirq);
+
+		mask = ioread8(host->base + ENSYSINT);
+		mask &= ~BIT(hwirq);
+		iowrite8(mask, host->base + ENSYSINT);
+	}
+}
+
+static void lp8x4x_unmask_irq(struct irq_data *d)
+{
+	unsigned mask;
+	unsigned long hwirq = d->hwirq;
+	struct lp8x4x_irq_data *host = irq_data_get_irq_chip_data(d);
+
+	if (hwirq < 8) {
+		host->irq_high_enabled |= BIT(hwirq);
+		mask = ioread8(host->base + CLRHILVINT);
+		mask |= BIT(hwirq);
+		iowrite8(mask, host->base + CLRHILVINT);
+
+		mask = ioread8(host->base + ENHILVINT);
+		mask |= BIT(hwirq);
+		iowrite8(mask, host->base + ENHILVINT);
+	} else {
+		hwirq -= 8;
+		host->irq_sys_enabled |= BIT(hwirq);
+
+		mask = ioread8(host->base + SECOINT);
+		mask |= BIT(hwirq);
+		iowrite8(mask, host->base + SECOINT);
+
+		mask = ioread8(host->base + ENSYSINT);
+		mask |= BIT(hwirq);
+		iowrite8(mask, host->base + ENSYSINT);
+	}
+}
+
+static struct irq_chip lp8x4x_irq_chip = {
+	.name			= "FPGA",
+	.irq_ack		= lp8x4x_mask_irq,
+	.irq_mask		= lp8x4x_mask_irq,
+	.irq_mask_ack		= lp8x4x_mask_irq,
+	.irq_unmask		= lp8x4x_unmask_irq,
+};
+
+static void lp8x4x_irq_handler(unsigned int irq, struct irq_desc *desc)
+{
+	int n;
+	unsigned long mask;
+	struct irq_chip *chip = irq_desc_get_chip(desc);
+	struct lp8x4x_irq_data *host = irq_desc_get_handler_data(desc);
+
+	chained_irq_enter(chip, desc);
+
+	for (;;) {
+		mask = ioread8(host->base + CLRHILVINT) & 0xff;
+		mask |= (ioread8(host->base + SECOINT) & SECOINT_MASK) << 8;
+		mask |= (ioread8(host->base + PRIMINT) & PRIMINT_MASK) << 8;
+		mask &= host->irq_high_enabled | (host->irq_sys_enabled << 8);
+		if (mask == 0)
+			break;
+		for_each_set_bit(n, &mask, BITS_PER_LONG)
+			generic_handle_irq(irq_find_mapping(host->domain, n));
+	}
+
+	iowrite8(0, host->base + EOI);
+	chained_irq_exit(chip, desc);
+}
+
+static int lp8x4x_irq_domain_map(struct irq_domain *d, unsigned int irq,
+				 irq_hw_number_t hw)
+{
+	struct lp8x4x_irq_data *host = d->host_data;
+	int err;
+
+	err = irq_set_chip_data(irq, host);
+	if (err < 0)
+		return err;
+
+	irq_set_chip_and_handler(irq, &lp8x4x_irq_chip, handle_level_irq);
+	set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+	return 0;
+}
+
+const struct irq_domain_ops lp8x4x_irq_domain_ops = {
+	.map	= lp8x4x_irq_domain_map,
+	.xlate	= irq_domain_xlate_onecell,
+};
+
+static struct of_device_id lp8x4x_irq_dt_ids[] = {
+	{ .compatible = "icpdas,irq-lp8x4x", },
+	{}
+};
+
+static int lp8x4x_irq_probe(struct platform_device *pdev)
+{
+	struct resource *res_mem, *res_irq;
+	struct device_node *np = pdev->dev.of_node;
+	struct lp8x4x_irq_data *host;
+	int i, err;
+
+	res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!res_mem || !res_irq || resource_size(res_mem) < IRQ_MEM_SIZE)
+		return -ENODEV;
+
+	host = devm_kzalloc(&pdev->dev, sizeof(*host), GFP_KERNEL);
+	if (!host)
+		return -ENODEV;
+
+	host->base = devm_ioremap_resource(&pdev->dev, res_mem);
+	if (!host->base) {
+		dev_err(&pdev->dev, "Failed to ioremap %p\n", host->base);
+		return -EFAULT;
+	}
+
+	host->domain = irq_domain_add_linear(np, LP8X4X_NUM_IRQ_DEFAULT,
+				       &lp8x4x_irq_domain_ops, host);
+	if (!host->domain) {
+		dev_err(&pdev->dev, "Failed to add IRQ domain\n");
+		return -ENOMEM;
+	}
+
+	for (i = 0; i < LP8X4X_NUM_IRQ_DEFAULT; i++) {
+		err = irq_create_mapping(host->domain, i);
+		if (err < 0)
+			dev_err(&pdev->dev, "Failed to map IRQ %i\n", i);
+	}
+
+	/* Initialize chip registers */
+	iowrite8(0, host->base + CLRRISEINT);
+	iowrite8(0, host->base + ENRISEINT);
+	iowrite8(0, host->base + CLRFALLINT);
+	iowrite8(0, host->base + ENFALLINT);
+	iowrite8(0, host->base + CLRHILVINT);
+	iowrite8(0, host->base + ENHILVINT);
+	iowrite8(0, host->base + ENSYSINT);
+	iowrite8(0, host->base + SECOINT);
+
+	irq_set_handler_data(res_irq->start, host);
+	irq_set_chained_handler(res_irq->start, lp8x4x_irq_handler);
+
+	return 0;
+}
+
+static struct platform_driver lp8x4x_irq_driver = {
+	.probe		= lp8x4x_irq_probe,
+	.driver		= {
+		.name	= "irq-lp8x4x",
+		.of_match_table = lp8x4x_irq_dt_ids,
+	},
+};
+
+static int __init lp8x4x_irq_init(void)
+{
+	return platform_driver_register(&lp8x4x_irq_driver);
+}
+postcore_initcall(lp8x4x_irq_init);
-- 
1.8.4.2


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

* [PATCH v3.2 11/21] ARM: pxa: support ICP DAS LP-8x4x FPGA irq
@ 2014-01-15 13:12                 ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2014-01-15 13:12 UTC (permalink / raw)
  To: linux-arm-kernel

ICP DAS LP-8x4x contains FPGA chip. The chip functions as an interrupt
source providing 16 additional interrupts among other things. The
interrupt lines are muxed to a GPIO pin of a 2nd level PXA-GPIO
interrupt controller. GPIO pins of the 2nd level controller are in turn
muxed to a CPU interrupt line.

Until pxa is completely converted to device tree, it is impossible
to use IRQCHIP_DECLARE() and the irqdomain needs to added manually.
Drivers for the on-CPU IRQs and GPIO-IRQs are loaded using
postcore_initcall(). We need to have all irq domain drivers loaded prior
to DT parsing in order to allow normal initialization of IRQ resources
with DT.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
CC: Arnd Bergmann <arnd@arndb.de>
---
   v3.1..v3.2
   fixes to apply Linus Walleij's "Reviewed-by":
   * add kerneldoc comment for state container struct
   * rename irq -> hwirq for clarity
   * drop overzealous error checks from the hotpaths

   v3..v3.1
   fixes according to Linus Walleij review comments:
   * update commit message
   * use state container instead of global variables
   * get hardware irq nums from irq_data, don't calculate them
   * use BIT() macro
   * add defines for system irq register masks
   * replace cycle control variable with break
   * use better names for resource variables
   * add a linear domain instead of a legacy one
   * use irq_create_mapping() instead of irq_alloc_desc()

   v2..v3
   * no changes (except number 09/16 -> 11/21)

   v0..v2
   * extract irqchip and move to drivers/irqchip/
   * use device tree
   * use devm helpers where possible

 .../bindings/interrupt-controller/irq-lp8x4x.txt   |  49 +++++
 arch/arm/boot/dts/pxa27x-lp8x4x.dts                |  10 +
 drivers/irqchip/Kconfig                            |   5 +
 drivers/irqchip/Makefile                           |   1 +
 drivers/irqchip/irq-lp8x4x.c                       | 227 +++++++++++++++++++++
 5 files changed, 292 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/interrupt-controller/irq-lp8x4x.txt
 create mode 100644 drivers/irqchip/irq-lp8x4x.c

diff --git a/Documentation/devicetree/bindings/interrupt-controller/irq-lp8x4x.txt b/Documentation/devicetree/bindings/interrupt-controller/irq-lp8x4x.txt
new file mode 100644
index 0000000..c8940d2
--- /dev/null
+++ b/Documentation/devicetree/bindings/interrupt-controller/irq-lp8x4x.txt
@@ -0,0 +1,49 @@
+ICP DAS LP-8x4x FPGA Interrupt Controller
+
+ICP DAS LP-8x4x contains FPGA chip. The chip functions as a interrupt
+source providing 16 additional interrupts among other things.
+
+Required properties:
+- compatible : should be "icpdas,irq-lp8x4x"
+
+- reg: physical base address of the controller and length of memory mapped
+  region.
+
+- interrupt-controller : identifies the node as an interrupt controller
+
+- #interrupt-cells : should be 1
+
+- interrupts : should provide interrupt
+
+- interrupt-parent : should provide a link to interrupt controller either
+		     explicitly and implicitly from a parent node
+
+Example:
+
+	fpga: fpga at 17000006 {
+		compatible = "icpdas,irq-lp8x4x";
+		reg = <0x17000006 0x16>;
+		interrupt-parent = <&gpio>;
+		interrupts = <3 IRQ_TYPE_EDGE_RISING>;
+		#interrupt-cells = <1>;
+		interrupt-controller;
+		status = "okay";
+	};
+
+	uart at 17009050 {
+		compatible = "icpdas,uart-lp8x4x";
+		reg = <0x17009050 0x10
+		       0x17009030 0x02>;
+		interrupt-parent = <&fpga>;
+		interrupts = <13>;
+		status = "okay";
+	};
+
+	uart at 17009060 {
+		compatible = "icpdas,uart-lp8x4x";
+		reg = <0x17009060 0x10
+		       0x17009032 0x02>;
+		interrupt-parent = <&fpga>;
+		interrupts = <14>;
+		status = "okay";
+	};
diff --git a/arch/arm/boot/dts/pxa27x-lp8x4x.dts b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
index 07856e0..78dfd2e 100644
--- a/arch/arm/boot/dts/pxa27x-lp8x4x.dts
+++ b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
@@ -167,6 +167,16 @@
 				reg = <0xa000 0x1000
 				       0x901e 0x1>;
 			};
+
+			fpgairq: irq at 9006 {
+				compatible = "icpdas,irq-lp8x4x";
+				reg = <0x9006 0x16>;
+				interrupt-parent = <&gpio>;
+				interrupts = <3 IRQ_TYPE_EDGE_FALLING>;
+				#interrupt-cells = <1>;
+				interrupt-controller;
+				status = "okay";
+			};
 		};
 	};
 };
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index 3792a1a..7e22729 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -35,6 +35,11 @@ config IMGPDC_IRQ
 	select GENERIC_IRQ_CHIP
 	select IRQ_DOMAIN
 
+config LP8X4X_IRQ
+	bool
+	depends on OF
+	select IRQ_DOMAIN
+
 config ORION_IRQCHIP
 	bool
 	select IRQ_DOMAIN
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index c60b901..8a28927 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -22,3 +22,4 @@ obj-$(CONFIG_RENESAS_IRQC)		+= irq-renesas-irqc.o
 obj-$(CONFIG_VERSATILE_FPGA_IRQ)	+= irq-versatile-fpga.o
 obj-$(CONFIG_ARCH_VT8500)		+= irq-vt8500.o
 obj-$(CONFIG_TB10X_IRQC)		+= irq-tb10x.o
+obj-$(CONFIG_LP8X4X_IRQ)		+= irq-lp8x4x.o
diff --git a/drivers/irqchip/irq-lp8x4x.c b/drivers/irqchip/irq-lp8x4x.c
new file mode 100644
index 0000000..12ccbb03
--- /dev/null
+++ b/drivers/irqchip/irq-lp8x4x.c
@@ -0,0 +1,227 @@
+/*
+ *  linux/drivers/irqchip/irq-lp8x4x.c
+ *
+ *  Support for ICP DAS LP-8x4x FPGA irq
+ *  Copyright (C) 2013 Sergei Ianovich <ynvich@gmail.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation or any later version.
+ */
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/irqchip/chained_irq.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+#define EOI			0x00000000
+#define INSINT			0x00000002
+#define ENSYSINT		0x00000004
+#define PRIMINT			0x00000006
+#define PRIMINT_MASK		0xe0
+#define SECOINT			0x00000008
+#define SECOINT_MASK		0x1f
+#define ENRISEINT		0x0000000A
+#define CLRRISEINT		0x0000000C
+#define ENHILVINT		0x0000000E
+#define CLRHILVINT		0x00000010
+#define ENFALLINT		0x00000012
+#define CLRFALLINT		0x00000014
+#define IRQ_MEM_SIZE		0x00000016
+#define LP8X4X_NUM_IRQ_DEFAULT	16
+
+/**
+ * struct lp8x4x_irq_data - LP8X4X custom irq controller state container
+ * @base:               base IO memory address
+ * @irq_domain:         Interrupt translation domain; responsible for mapping
+ *                      between hwirq number and linux irq number
+ * @irq_sys_enabled:    mask keeping track of interrupts enabled in the
+ *                      register which vendor calls 'system'
+ * @irq_high_enabled:   mask keeping track of interrupts enabled in the
+ *                      register which vendor calls 'high'
+ *
+ * The structure implements State Container from
+ * Documentation/driver-model/design-patterns.txt
+ */
+
+struct lp8x4x_irq_data {
+	void			*base;
+	struct irq_domain	*domain;
+	unsigned char		irq_sys_enabled;
+	unsigned char		irq_high_enabled;
+};
+
+static void lp8x4x_mask_irq(struct irq_data *d)
+{
+	unsigned mask;
+	unsigned long hwirq = d->hwirq;
+	struct lp8x4x_irq_data *host = irq_data_get_irq_chip_data(d);
+
+	if (hwirq < 8) {
+		host->irq_high_enabled &= ~BIT(hwirq);
+
+		mask = ioread8(host->base + ENHILVINT);
+		mask &= ~BIT(hwirq);
+		iowrite8(mask, host->base + ENHILVINT);
+	} else {
+		hwirq -= 8;
+		host->irq_sys_enabled &= ~BIT(hwirq);
+
+		mask = ioread8(host->base + ENSYSINT);
+		mask &= ~BIT(hwirq);
+		iowrite8(mask, host->base + ENSYSINT);
+	}
+}
+
+static void lp8x4x_unmask_irq(struct irq_data *d)
+{
+	unsigned mask;
+	unsigned long hwirq = d->hwirq;
+	struct lp8x4x_irq_data *host = irq_data_get_irq_chip_data(d);
+
+	if (hwirq < 8) {
+		host->irq_high_enabled |= BIT(hwirq);
+		mask = ioread8(host->base + CLRHILVINT);
+		mask |= BIT(hwirq);
+		iowrite8(mask, host->base + CLRHILVINT);
+
+		mask = ioread8(host->base + ENHILVINT);
+		mask |= BIT(hwirq);
+		iowrite8(mask, host->base + ENHILVINT);
+	} else {
+		hwirq -= 8;
+		host->irq_sys_enabled |= BIT(hwirq);
+
+		mask = ioread8(host->base + SECOINT);
+		mask |= BIT(hwirq);
+		iowrite8(mask, host->base + SECOINT);
+
+		mask = ioread8(host->base + ENSYSINT);
+		mask |= BIT(hwirq);
+		iowrite8(mask, host->base + ENSYSINT);
+	}
+}
+
+static struct irq_chip lp8x4x_irq_chip = {
+	.name			= "FPGA",
+	.irq_ack		= lp8x4x_mask_irq,
+	.irq_mask		= lp8x4x_mask_irq,
+	.irq_mask_ack		= lp8x4x_mask_irq,
+	.irq_unmask		= lp8x4x_unmask_irq,
+};
+
+static void lp8x4x_irq_handler(unsigned int irq, struct irq_desc *desc)
+{
+	int n;
+	unsigned long mask;
+	struct irq_chip *chip = irq_desc_get_chip(desc);
+	struct lp8x4x_irq_data *host = irq_desc_get_handler_data(desc);
+
+	chained_irq_enter(chip, desc);
+
+	for (;;) {
+		mask = ioread8(host->base + CLRHILVINT) & 0xff;
+		mask |= (ioread8(host->base + SECOINT) & SECOINT_MASK) << 8;
+		mask |= (ioread8(host->base + PRIMINT) & PRIMINT_MASK) << 8;
+		mask &= host->irq_high_enabled | (host->irq_sys_enabled << 8);
+		if (mask == 0)
+			break;
+		for_each_set_bit(n, &mask, BITS_PER_LONG)
+			generic_handle_irq(irq_find_mapping(host->domain, n));
+	}
+
+	iowrite8(0, host->base + EOI);
+	chained_irq_exit(chip, desc);
+}
+
+static int lp8x4x_irq_domain_map(struct irq_domain *d, unsigned int irq,
+				 irq_hw_number_t hw)
+{
+	struct lp8x4x_irq_data *host = d->host_data;
+	int err;
+
+	err = irq_set_chip_data(irq, host);
+	if (err < 0)
+		return err;
+
+	irq_set_chip_and_handler(irq, &lp8x4x_irq_chip, handle_level_irq);
+	set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+	return 0;
+}
+
+const struct irq_domain_ops lp8x4x_irq_domain_ops = {
+	.map	= lp8x4x_irq_domain_map,
+	.xlate	= irq_domain_xlate_onecell,
+};
+
+static struct of_device_id lp8x4x_irq_dt_ids[] = {
+	{ .compatible = "icpdas,irq-lp8x4x", },
+	{}
+};
+
+static int lp8x4x_irq_probe(struct platform_device *pdev)
+{
+	struct resource *res_mem, *res_irq;
+	struct device_node *np = pdev->dev.of_node;
+	struct lp8x4x_irq_data *host;
+	int i, err;
+
+	res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!res_mem || !res_irq || resource_size(res_mem) < IRQ_MEM_SIZE)
+		return -ENODEV;
+
+	host = devm_kzalloc(&pdev->dev, sizeof(*host), GFP_KERNEL);
+	if (!host)
+		return -ENODEV;
+
+	host->base = devm_ioremap_resource(&pdev->dev, res_mem);
+	if (!host->base) {
+		dev_err(&pdev->dev, "Failed to ioremap %p\n", host->base);
+		return -EFAULT;
+	}
+
+	host->domain = irq_domain_add_linear(np, LP8X4X_NUM_IRQ_DEFAULT,
+				       &lp8x4x_irq_domain_ops, host);
+	if (!host->domain) {
+		dev_err(&pdev->dev, "Failed to add IRQ domain\n");
+		return -ENOMEM;
+	}
+
+	for (i = 0; i < LP8X4X_NUM_IRQ_DEFAULT; i++) {
+		err = irq_create_mapping(host->domain, i);
+		if (err < 0)
+			dev_err(&pdev->dev, "Failed to map IRQ %i\n", i);
+	}
+
+	/* Initialize chip registers */
+	iowrite8(0, host->base + CLRRISEINT);
+	iowrite8(0, host->base + ENRISEINT);
+	iowrite8(0, host->base + CLRFALLINT);
+	iowrite8(0, host->base + ENFALLINT);
+	iowrite8(0, host->base + CLRHILVINT);
+	iowrite8(0, host->base + ENHILVINT);
+	iowrite8(0, host->base + ENSYSINT);
+	iowrite8(0, host->base + SECOINT);
+
+	irq_set_handler_data(res_irq->start, host);
+	irq_set_chained_handler(res_irq->start, lp8x4x_irq_handler);
+
+	return 0;
+}
+
+static struct platform_driver lp8x4x_irq_driver = {
+	.probe		= lp8x4x_irq_probe,
+	.driver		= {
+		.name	= "irq-lp8x4x",
+		.of_match_table = lp8x4x_irq_dt_ids,
+	},
+};
+
+static int __init lp8x4x_irq_init(void)
+{
+	return platform_driver_register(&lp8x4x_irq_driver);
+}
+postcore_initcall(lp8x4x_irq_init);
-- 
1.8.4.2

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

* Re: [PATCH v3 11/21] ARM: pxa: support ICP DAS LP-8x4x FPGA irq
  2014-01-15  7:39                   ` Linus Walleij
  (?)
@ 2014-01-15 13:17                     ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2014-01-15 13:17 UTC (permalink / raw)
  To: Linus Walleij
  Cc: linux-kernel, linux-arm-kernel, Arnd Bergmann, Rob Herring,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala, Rob Landley,
	Russell King, Thomas Gleixner, Grant Likely,
	open list:OPEN FIRMWARE AND...,
	open list:DOCUMENTATION

On Wed, 2014-01-15 at 08:39 +0100, Linus Walleij wrote:
> On Wed, Jan 8, 2014 at 8:01 PM, Sergei Ianovich <ynvich@gmail.com> wrote:
> Hm I don't know why I was deluded into thinking this had something to
> do with GPIO. I must have been soft in the head. Sorry about all those
> comments ...

It's not your fault for sure. My commit message wasn't clear enough and
needed clarifications. It is better now.

Thanks for constructive reviewing.


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

* Re: [PATCH v3 11/21] ARM: pxa: support ICP DAS LP-8x4x FPGA irq
@ 2014-01-15 13:17                     ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2014-01-15 13:17 UTC (permalink / raw)
  To: Linus Walleij
  Cc: linux-kernel, linux-arm-kernel, Arnd Bergmann, Rob Herring,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala, Rob Landley,
	Russell King, Thomas Gleixner, Grant Likely,
	open list:OPEN FIRMWARE AND...,
	open list:DOCUMENTATION

On Wed, 2014-01-15 at 08:39 +0100, Linus Walleij wrote:
> On Wed, Jan 8, 2014 at 8:01 PM, Sergei Ianovich <ynvich@gmail.com> wrote:
> Hm I don't know why I was deluded into thinking this had something to
> do with GPIO. I must have been soft in the head. Sorry about all those
> comments ...

It's not your fault for sure. My commit message wasn't clear enough and
needed clarifications. It is better now.

Thanks for constructive reviewing.


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

* [PATCH v3 11/21] ARM: pxa: support ICP DAS LP-8x4x FPGA irq
@ 2014-01-15 13:17                     ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2014-01-15 13:17 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, 2014-01-15 at 08:39 +0100, Linus Walleij wrote:
> On Wed, Jan 8, 2014 at 8:01 PM, Sergei Ianovich <ynvich@gmail.com> wrote:
> Hm I don't know why I was deluded into thinking this had something to
> do with GPIO. I must have been soft in the head. Sorry about all those
> comments ...

It's not your fault for sure. My commit message wasn't clear enough and
needed clarifications. It is better now.

Thanks for constructive reviewing.

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

* Re: [PATCH v2 00/16] ARM: support for ICP DAS LP-8x4x (with dts)
  2014-01-09 23:12                                     ` Sergei Ianovich
@ 2014-01-20 16:08                                       ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2014-01-20 16:08 UTC (permalink / raw)
  To: Arnd Bergmann; +Cc: linux-kernel, linux-arm-kernel, Daniel Mack, Haojian Zhuang

On Fri, 2014-01-10 at 03:12 +0400, Sergei Ianovich wrote:
> On Thu, 2013-12-19 at 06:30 +0100, Arnd Bergmann wrote:
> > This would work only if we can probe the devices behind the external
> > bus controller before the controller itsef has been set up, since
> > the initialization order can depend on a number of things but not
> > the bus hierarchy. It will also work if the code setting up the
> > bus controller can be guaranteed to run before we call
> > of_platform_populate for the regular devices, which is probably
> > the best solution here.
> 
> There has been no activity for 3 weeks. Could we resume the series?

It's over a month now. Is anything wrong?


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

* [PATCH v2 00/16] ARM: support for ICP DAS LP-8x4x (with dts)
@ 2014-01-20 16:08                                       ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2014-01-20 16:08 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, 2014-01-10 at 03:12 +0400, Sergei Ianovich wrote:
> On Thu, 2013-12-19 at 06:30 +0100, Arnd Bergmann wrote:
> > This would work only if we can probe the devices behind the external
> > bus controller before the controller itsef has been set up, since
> > the initialization order can depend on a number of things but not
> > the bus hierarchy. It will also work if the code setting up the
> > bus controller can be guaranteed to run before we call
> > of_platform_populate for the regular devices, which is probably
> > the best solution here.
> 
> There has been no activity for 3 weeks. Could we resume the series?

It's over a month now. Is anything wrong?

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

* Re: [PATCH v2 00/16] ARM: support for ICP DAS LP-8x4x (with dts)
  2014-01-20 16:08                                       ` Sergei Ianovich
@ 2014-01-20 16:20                                         ` Daniel Mack
  -1 siblings, 0 replies; 700+ messages in thread
From: Daniel Mack @ 2014-01-20 16:20 UTC (permalink / raw)
  To: Sergei Ianovich, Arnd Bergmann
  Cc: linux-kernel, linux-arm-kernel, Haojian Zhuang

On 01/20/2014 05:08 PM, Sergei Ianovich wrote:
> On Fri, 2014-01-10 at 03:12 +0400, Sergei Ianovich wrote:
>> On Thu, 2013-12-19 at 06:30 +0100, Arnd Bergmann wrote:
>>> This would work only if we can probe the devices behind the external
>>> bus controller before the controller itsef has been set up, since
>>> the initialization order can depend on a number of things but not
>>> the bus hierarchy. It will also work if the code setting up the
>>> bus controller can be guaranteed to run before we call
>>> of_platform_populate for the regular devices, which is probably
>>> the best solution here.
>>
>> There has been no activity for 3 weeks. Could we resume the series?
> 
> It's over a month now. Is anything wrong?
> 

No, I'm busy, that's all.

That said, the current situation is

a) we need someone to have a look at the performance regression of the
MMC file system layer that you reported. I couldn't find a PXA-based
board yet with a MMC slot soldered on it. But as you apparently have
such hardware, I'd really appreciate your help here. Could you do some
measurements and see whether you see major differences in packet size or
timings?

b) Marek Vasut thankfully reported back to me and signaled success with
his pxa-pata driver. So we're most probably good in that area.

c) Robert Jarzmik is still in the process of converting the camera
driver. Here as well, I lack hardware, I can't even compile-test
anything here.


So please, if you have any spare time, have a look at the MMC
regressions and see if you can contribute anything. I'll hope to find
some time to rebase my patches on top of 3.13 very soon, so we have a
new base to work on.


Thanks,
Daniel


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

* [PATCH v2 00/16] ARM: support for ICP DAS LP-8x4x (with dts)
@ 2014-01-20 16:20                                         ` Daniel Mack
  0 siblings, 0 replies; 700+ messages in thread
From: Daniel Mack @ 2014-01-20 16:20 UTC (permalink / raw)
  To: linux-arm-kernel

On 01/20/2014 05:08 PM, Sergei Ianovich wrote:
> On Fri, 2014-01-10 at 03:12 +0400, Sergei Ianovich wrote:
>> On Thu, 2013-12-19 at 06:30 +0100, Arnd Bergmann wrote:
>>> This would work only if we can probe the devices behind the external
>>> bus controller before the controller itsef has been set up, since
>>> the initialization order can depend on a number of things but not
>>> the bus hierarchy. It will also work if the code setting up the
>>> bus controller can be guaranteed to run before we call
>>> of_platform_populate for the regular devices, which is probably
>>> the best solution here.
>>
>> There has been no activity for 3 weeks. Could we resume the series?
> 
> It's over a month now. Is anything wrong?
> 

No, I'm busy, that's all.

That said, the current situation is

a) we need someone to have a look at the performance regression of the
MMC file system layer that you reported. I couldn't find a PXA-based
board yet with a MMC slot soldered on it. But as you apparently have
such hardware, I'd really appreciate your help here. Could you do some
measurements and see whether you see major differences in packet size or
timings?

b) Marek Vasut thankfully reported back to me and signaled success with
his pxa-pata driver. So we're most probably good in that area.

c) Robert Jarzmik is still in the process of converting the camera
driver. Here as well, I lack hardware, I can't even compile-test
anything here.


So please, if you have any spare time, have a look at the MMC
regressions and see if you can contribute anything. I'll hope to find
some time to rebase my patches on top of 3.13 very soon, so we have a
new base to work on.


Thanks,
Daniel

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

* Re: [PATCH v2 00/16] ARM: support for ICP DAS LP-8x4x (with dts)
  2014-01-20 16:20                                         ` Daniel Mack
@ 2014-01-20 16:52                                           ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2014-01-20 16:52 UTC (permalink / raw)
  To: Daniel Mack; +Cc: Arnd Bergmann, linux-kernel, linux-arm-kernel, Haojian Zhuang

On Mon, 2014-01-20 at 17:20 +0100, Daniel Mack wrote:
> On 01/20/2014 05:08 PM, Sergei Ianovich wrote:
> > It's over a month now. Is anything wrong?
> No, I'm busy, that's all.

Thanks for reply.

> That said, the current situation is
> 
> a) we need someone to have a look at the performance regression of the
> MMC file system layer that you reported. I couldn't find a PXA-based
> board yet with a MMC slot soldered on it. But as you apparently have
> such hardware, I'd really appreciate your help here. Could you do some
> measurements and see whether you see major differences in packet size or
> timings?

I have the hardware with MMC, but none of the other devices. Could you
give some pointer where to start? How would you do measurements?

(...)

> So please, if you have any spare time, have a look at the MMC
> regressions and see if you can contribute anything. I'll hope to find
> some time to rebase my patches on top of 3.13 very soon, so we have a
> new base to work on.

It would be nice to have updated patches. Most interesting is whether
the new DMA still works as expected for other devices.

Apart from that, would mind if my series is landed with a workaround
(Patch v3 7/21). I hope you understand it doesn't feel good to depend on
something with no development activity.


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

* [PATCH v2 00/16] ARM: support for ICP DAS LP-8x4x (with dts)
@ 2014-01-20 16:52                                           ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2014-01-20 16:52 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, 2014-01-20 at 17:20 +0100, Daniel Mack wrote:
> On 01/20/2014 05:08 PM, Sergei Ianovich wrote:
> > It's over a month now. Is anything wrong?
> No, I'm busy, that's all.

Thanks for reply.

> That said, the current situation is
> 
> a) we need someone to have a look at the performance regression of the
> MMC file system layer that you reported. I couldn't find a PXA-based
> board yet with a MMC slot soldered on it. But as you apparently have
> such hardware, I'd really appreciate your help here. Could you do some
> measurements and see whether you see major differences in packet size or
> timings?

I have the hardware with MMC, but none of the other devices. Could you
give some pointer where to start? How would you do measurements?

(...)

> So please, if you have any spare time, have a look at the MMC
> regressions and see if you can contribute anything. I'll hope to find
> some time to rebase my patches on top of 3.13 very soon, so we have a
> new base to work on.

It would be nice to have updated patches. Most interesting is whether
the new DMA still works as expected for other devices.

Apart from that, would mind if my series is landed with a workaround
(Patch v3 7/21). I hope you understand it doesn't feel good to depend on
something with no development activity.

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

* Re: [PATCH v2 00/16] ARM: support for ICP DAS LP-8x4x (with dts)
  2014-01-20 16:52                                           ` Sergei Ianovich
@ 2014-01-20 16:58                                             ` Daniel Mack
  -1 siblings, 0 replies; 700+ messages in thread
From: Daniel Mack @ 2014-01-20 16:58 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: Arnd Bergmann, linux-kernel, linux-arm-kernel, Haojian Zhuang

On 01/20/2014 05:52 PM, Sergei Ianovich wrote:
> On Mon, 2014-01-20 at 17:20 +0100, Daniel Mack wrote:
>> On 01/20/2014 05:08 PM, Sergei Ianovich wrote:
>>> It's over a month now. Is anything wrong?
>> No, I'm busy, that's all.
> 
> Thanks for reply.
> 
>> That said, the current situation is
>>
>> a) we need someone to have a look at the performance regression of the
>> MMC file system layer that you reported. I couldn't find a PXA-based
>> board yet with a MMC slot soldered on it. But as you apparently have
>> such hardware, I'd really appreciate your help here. Could you do some
>> measurements and see whether you see major differences in packet size or
>> timings?
> 
> I have the hardware with MMC, but none of the other devices. Could you
> give some pointer where to start? How would you do measurements?

Please check whether the DMA engine transfers data in chunks of
comparable size in both cases. Also, take time stamps when the packet is
submitted, and calculate the delta when the transfer returns. See if any
significant time gap contributes to the regression you see.

After all, it's still quite possible that the DMA driver has performance
bottlenecks. We need to find the code where so much more time is spent
with the new implementation.

> It would be nice to have updated patches. Most interesting is whether
> the new DMA still works as expected for other devices.

I'll allocate a time slot for that :)

> Apart from that, would mind if my series is landed with a workaround
> (Patch v3 7/21). I hope you understand it doesn't feel good to depend on
> something with no development activity.

I understand, but that shouldn't keep you you from maintaining a patch
stack out-of-tree until things are in shape enough to go mainline.


Thanks for you help,
Daniel


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

* [PATCH v2 00/16] ARM: support for ICP DAS LP-8x4x (with dts)
@ 2014-01-20 16:58                                             ` Daniel Mack
  0 siblings, 0 replies; 700+ messages in thread
From: Daniel Mack @ 2014-01-20 16:58 UTC (permalink / raw)
  To: linux-arm-kernel

On 01/20/2014 05:52 PM, Sergei Ianovich wrote:
> On Mon, 2014-01-20 at 17:20 +0100, Daniel Mack wrote:
>> On 01/20/2014 05:08 PM, Sergei Ianovich wrote:
>>> It's over a month now. Is anything wrong?
>> No, I'm busy, that's all.
> 
> Thanks for reply.
> 
>> That said, the current situation is
>>
>> a) we need someone to have a look at the performance regression of the
>> MMC file system layer that you reported. I couldn't find a PXA-based
>> board yet with a MMC slot soldered on it. But as you apparently have
>> such hardware, I'd really appreciate your help here. Could you do some
>> measurements and see whether you see major differences in packet size or
>> timings?
> 
> I have the hardware with MMC, but none of the other devices. Could you
> give some pointer where to start? How would you do measurements?

Please check whether the DMA engine transfers data in chunks of
comparable size in both cases. Also, take time stamps when the packet is
submitted, and calculate the delta when the transfer returns. See if any
significant time gap contributes to the regression you see.

After all, it's still quite possible that the DMA driver has performance
bottlenecks. We need to find the code where so much more time is spent
with the new implementation.

> It would be nice to have updated patches. Most interesting is whether
> the new DMA still works as expected for other devices.

I'll allocate a time slot for that :)

> Apart from that, would mind if my series is landed with a workaround
> (Patch v3 7/21). I hope you understand it doesn't feel good to depend on
> something with no development activity.

I understand, but that shouldn't keep you you from maintaining a patch
stack out-of-tree until things are in shape enough to go mainline.


Thanks for you help,
Daniel

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

* Re: [PATCH 01/11] resolve PXA<->8250 serial device address conflict
  2013-12-01  6:26   ` Sergei Ianovich
@ 2014-01-28 14:14     ` Pavel Machek
  -1 siblings, 0 replies; 700+ messages in thread
From: Pavel Machek @ 2014-01-28 14:14 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: linux-kernel, linux-arm-kernel, Greg Kroah-Hartman, Jiri Slaby,
	open list:SERIAL DRIVERS

Hi!

> PXA serial ports have "standard" UART names (ttyS[0-3]), major
> device number (4) and first minor device number (64) by default.
> 
> If the system has extra 8250 serial port hardware in addition
> to onboard PXA serial ports, default settings produce a device
> allocation conflict.
> 
> The patch provides a configuration option which can move onboard
> ports out of the way of 8250_core by assigning a different (204)
> major number and corresponding device names (ttySA[0-3]).

Yes, please. I was hitting the same issue with Sharp Zaurus and bluetooth
CF card... Bluetooth card had 8250 inside...


-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

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

* [PATCH 01/11] resolve PXA<->8250 serial device address conflict
@ 2014-01-28 14:14     ` Pavel Machek
  0 siblings, 0 replies; 700+ messages in thread
From: Pavel Machek @ 2014-01-28 14:14 UTC (permalink / raw)
  To: linux-arm-kernel

Hi!

> PXA serial ports have "standard" UART names (ttyS[0-3]), major
> device number (4) and first minor device number (64) by default.
> 
> If the system has extra 8250 serial port hardware in addition
> to onboard PXA serial ports, default settings produce a device
> allocation conflict.
> 
> The patch provides a configuration option which can move onboard
> ports out of the way of 8250_core by assigning a different (204)
> major number and corresponding device names (ttySA[0-3]).

Yes, please. I was hitting the same issue with Sharp Zaurus and bluetooth
CF card... Bluetooth card had 8250 inside...


-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

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

* Re: [PATCH 01/11] resolve PXA<->8250 serial device address conflict
  2014-01-28 14:14     ` Pavel Machek
@ 2014-01-28 14:20       ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2014-01-28 14:20 UTC (permalink / raw)
  To: Pavel Machek
  Cc: linux-kernel, linux-arm-kernel, Greg Kroah-Hartman, Jiri Slaby,
	open list:SERIAL DRIVERS

On Tue, 2014-01-28 at 15:14 +0100, Pavel Machek wrote:
> Yes, please. I was hitting the same issue with Sharp Zaurus and bluetooth
> CF card... Bluetooth card had 8250 inside...

A better implementation is posted as v3 of the patch.

http://linux-kernel.2935.n7.nabble.com/PATCH-00-11-ARM-support-for-ICP-DAS-LP-8x4x-tp761919p773485.html

It would be great if you could test that patch add post back the
results.


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

* [PATCH 01/11] resolve PXA<->8250 serial device address conflict
@ 2014-01-28 14:20       ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2014-01-28 14:20 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, 2014-01-28 at 15:14 +0100, Pavel Machek wrote:
> Yes, please. I was hitting the same issue with Sharp Zaurus and bluetooth
> CF card... Bluetooth card had 8250 inside...

A better implementation is posted as v3 of the patch.

http://linux-kernel.2935.n7.nabble.com/PATCH-00-11-ARM-support-for-ICP-DAS-LP-8x4x-tp761919p773485.html

It would be great if you could test that patch add post back the
results.

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

* Re: [PATCH v3 10/21] mtd: support BB SRAM on ICP DAS LP-8x4x
  2013-12-17 19:37             ` Sergei Ianovich
  (?)
@ 2014-04-16  5:04               ` Brian Norris
  -1 siblings, 0 replies; 700+ messages in thread
From: Brian Norris @ 2014-04-16  5:04 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: linux-kernel, linux-arm-kernel, Rob Herring, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala, Russell King,
	David Woodhouse, Grant Likely, Artem Bityutskiy, Robert Jarzmik,
	Kees Cook, Randy Dunlap, Philip Avinash,
	open list:OPEN FIRMWARE AND..., open list:MEMORY TECHNOLOGY...

Hi Sergei,

On Tue, Dec 17, 2013 at 11:37:40PM +0400, Sergei Ianovich wrote:
> This provides an MTD device driver for 512kB of battery backed up SRAM
> on ICPDAS LP-8X4X programmable automation controllers.
> 
> SRAM chip is connected via FPGA and is not accessible without a driver,
> unlike flash memory which is wired to CPU MMU.
> 
> This SRAM becomes an excellent persisent storage of volatile process
> data like counter values and sensor statuses. Storing those data in
> flash or mmc card is not a viable solution.
> 
> Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
> ---
>    v2..v3
>    * no changes (except number 08/16 -> 10/21)
> 
>    v0..v2
>    * use device tree
>    * use devm helpers where possible

What's the status of this series? Is the rest of this platform support
going in via other trees yet? I have a few trivial comments, but this
driver mostly looks good as-is.

>  arch/arm/boot/dts/pxa27x-lp8x4x.dts |   6 +
>  arch/arm/configs/lp8x4x_defconfig   |   1 +
>  drivers/mtd/devices/Kconfig         |  14 +++
>  drivers/mtd/devices/Makefile        |   1 +
>  drivers/mtd/devices/sram_lp8x4x.c   | 227 ++++++++++++++++++++++++++++++++++++
>  5 files changed, 249 insertions(+)
>  create mode 100644 drivers/mtd/devices/sram_lp8x4x.c
> 
> diff --git a/arch/arm/boot/dts/pxa27x-lp8x4x.dts b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
> index 872c386..07856e0 100644
> --- a/arch/arm/boot/dts/pxa27x-lp8x4x.dts
> +++ b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
> @@ -161,6 +161,12 @@
>  				reg = <0x901c 0x1>;
>  				status = "okay";
>  			};
> +
> +			sram@a000 {
> +				compatible = "icpdas,sram-lp8x4x";
> +				reg = <0xa000 0x1000
> +				       0x901e 0x1>;
> +			};

You'll need a (trivial) DT binding doc in
Documentation/devicetree/bindings/ to go with this. You might also need
to split the arch/arm/boot/dts/ stuff out to a separate patch, so the
MTD driver can go in the MTD tree separate from the ARM tree bits.

>  		};
>  	};
>  };
> diff --git a/arch/arm/configs/lp8x4x_defconfig b/arch/arm/configs/lp8x4x_defconfig
> index d60e37a..17a4e6f 100644
> --- a/arch/arm/configs/lp8x4x_defconfig
> +++ b/arch/arm/configs/lp8x4x_defconfig
> @@ -57,6 +57,7 @@ CONFIG_MTD_CFI_ADV_OPTIONS=y
>  CONFIG_MTD_CFI_GEOMETRY=y
>  CONFIG_MTD_CFI_INTELEXT=y
>  CONFIG_MTD_PHYSMAP_OF=y
> +CONFIG_MTD_SRAM_LP8X4X=y
>  CONFIG_PROC_DEVICETREE=y
>  CONFIG_BLK_DEV_LOOP=y
>  CONFIG_BLK_DEV_LOOP_MIN_COUNT=2
> diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig
> index 0128138..95f2075 100644
> --- a/drivers/mtd/devices/Kconfig
> +++ b/drivers/mtd/devices/Kconfig
> @@ -217,4 +217,18 @@ config BCH_CONST_T
>  	default 4
>  endif
>  
> +config MTD_SRAM_LP8X4X
> +	tristate "SRAM on ICPDAS LP-8X4X"
> +	depends on OF && ARCH_PXA
> +       ---help---
> +	 This provides an MTD device driver for 512kiB of battery backed up SRAM
> +	 on ICPDAS LP-8X4X programmable automation controllers.
> +
> +	 SRAM chip is connected via FPGA and is not accessible without a driver,
> +	 unlike flash memory which is wired to CPU MMU.
> +
> +	 Say N, unless you plan to run this kernel on LP-8X4X.
> +
> +	 If you say M, the module will be called sram_lp8x4x.
> +
>  endmenu
> diff --git a/drivers/mtd/devices/Makefile b/drivers/mtd/devices/Makefile
> index d83bd73..56a74c9 100644
> --- a/drivers/mtd/devices/Makefile
> +++ b/drivers/mtd/devices/Makefile
> @@ -16,6 +16,7 @@ obj-$(CONFIG_MTD_NAND_OMAP_BCH)	+= elm.o
>  obj-$(CONFIG_MTD_SPEAR_SMI)	+= spear_smi.o
>  obj-$(CONFIG_MTD_SST25L)	+= sst25l.o
>  obj-$(CONFIG_MTD_BCM47XXSFLASH)	+= bcm47xxsflash.o
> +obj-$(CONFIG_MTD_SRAM_LP8X4X)	+= sram_lp8x4x.o
>  
>  
>  CFLAGS_docg3.o			+= -I$(src)
> diff --git a/drivers/mtd/devices/sram_lp8x4x.c b/drivers/mtd/devices/sram_lp8x4x.c
> new file mode 100644
> index 0000000..9dc7149
> --- /dev/null
> +++ b/drivers/mtd/devices/sram_lp8x4x.c
> @@ -0,0 +1,227 @@
> +/*
> + *  linux/drivers/mtd/devices/lp8x4x_sram.c
> + *
> + *  MTD Driver for SRAM on ICPDAS LP-8x4x
> + *  Copyright (C) 2013 Sergei Ianovich <ynvich@gmail.com>
> + *
> + *  This program is free software; you can redistribute it and/or modify
> + *  it under the terms of the GNU General Public License version 2 as
> + *  published by the Free Software Foundation or any later version.
> + */
> +
> +#include <linux/init.h>
> +#include <linux/io.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/mtd/map.h>
> +#include <linux/mtd/mtd.h>
> +#include <linux/mtd/partitions.h>
> +#include <linux/platform_device.h>
> +#include <linux/of_device.h>
> +#include <linux/slab.h>
> +#include <linux/string_helpers.h>
> +#include <linux/types.h>
> +
> +#include <asm/mach/flash.h>

Do you need this? It looks unused.

> +
> +struct lp8x4x_sram_info {
> +	void __iomem	*bank;
> +	void __iomem	*virt;
> +	struct mutex	lock;
> +	unsigned	active_bank;
> +	struct mtd_info	mtd;
> +};
> +
> +static int
> +lp8x4x_sram_erase(struct mtd_info *mtd, struct erase_info *instr)
> +{
> +	struct lp8x4x_sram_info *info = mtd->priv;
> +	unsigned bank = instr->addr >> 11;
> +	unsigned offset = (instr->addr & 0x7ff) << 1;
> +	loff_t i;
> +
> +	mutex_lock(&info->lock);
> +	if (unlikely(bank != info->active_bank)) {
> +		info->active_bank = bank;
> +		iowrite8(bank, info->bank);
> +	}
> +	for (i = 0; i < instr->len; i++) {
> +		iowrite8(0xff, info->virt + offset);
> +		offset += 2;
> +		if (unlikely(offset == 0)) {
> +			info->active_bank++;
> +			iowrite8(info->active_bank, info->bank);
> +		}
> +	}
> +	mutex_unlock(&info->lock);
> +	instr->state = MTD_ERASE_DONE;
> +	mtd_erase_callback(instr);
> +
> +	return 0;
> +}
> +
> +static int
> +lp8x4x_sram_write(struct mtd_info *mtd, loff_t to, size_t len,
> +		size_t *retlen, const u_char *b)
> +{
> +	struct lp8x4x_sram_info *info = mtd->priv;
> +	unsigned bank = to >> 11;
> +	unsigned offset = (to & 0x7ff) << 1;
> +	loff_t i;
> +
> +	mutex_lock(&info->lock);
> +	if (unlikely(bank != info->active_bank)) {
> +		info->active_bank = bank;
> +		iowrite8(bank, info->bank);
> +	}
> +	for (i = 0; i < len; i++) {
> +		iowrite8(b[i], info->virt + offset);
> +		offset += 2;
> +		if (unlikely(offset == 0)) {
> +			info->active_bank++;
> +			iowrite8(info->active_bank, info->bank);
> +		}
> +	}
> +	mutex_unlock(&info->lock);
> +	*retlen = len;
> +	return 0;
> +}
> +
> +static int
> +lp8x4x_sram_read(struct mtd_info *mtd, loff_t from, size_t len,
> +		size_t *retlen, u_char *b)
> +{
> +	struct lp8x4x_sram_info *info = mtd->priv;
> +	unsigned bank = from >> 11;
> +	unsigned offset = (from & 0x7ff) << 1;
> +	loff_t i;
> +
> +	mutex_lock(&info->lock);
> +	if (unlikely(bank != info->active_bank)) {
> +		info->active_bank = bank;
> +		iowrite8(bank, info->bank);
> +	}
> +	for (i = 0; i < len; i++) {
> +		b[i] = ioread8(info->virt + offset);
> +		offset += 2;
> +		if (unlikely(offset == 0)) {
> +			info->active_bank++;
> +			iowrite8(info->active_bank, info->bank);
> +		}
> +	}
> +	mutex_unlock(&info->lock);
> +	*retlen = len;
> +	return 0;
> +}
> +
> +static void
> +lp8x4x_sram_sync(struct mtd_info *mtd)
> +{
> +}

You don't need the empty call-back. See mtd_sync(), which only calls the
_sync callback if it's filled in.

> +
> +static struct of_device_id of_flash_match[] = {
> +	{
> +		.compatible	= "icpdas,sram-lp8x4x",
> +	},
> +	{ },
> +};
> +MODULE_DEVICE_TABLE(of, of_flash_match);
> +
> +static const char * const probe_types[] = {
> +	"cmdlinepart", "RedBoot", "ofpart", "ofoldpart", NULL };

Please drop 'ofoldpart'; it is obsolte. And do you really want
'RedBoot'?

> +
> +static int
> +lp8x4x_sram_probe(struct platform_device *pdev)
> +{
> +	const struct of_device_id *match;
> +	struct lp8x4x_sram_info *info;
> +	struct resource *r1, *r2;
> +	char sz_str[16];
> +	struct mtd_part_parser_data ppdata;
> +	int err = 0;
> +
> +	match = of_match_device(of_flash_match, &pdev->dev);
> +	if (!match)
> +		return -EINVAL;
> +
> +	r1 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	r2 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
> +	if (!r1 || !r2)
> +		return -ENODEV;

Move these next to the devm_ioremap_resource(), and then remove the
	if (!r1 || !r2)
checks, since devm_ioremap_resource() does them for you. (See
lib/devres.c.)

> +
> +	info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
> +	if (!info)
> +		return -ENOMEM;
> +
> +	info->virt =  devm_ioremap_resource(&pdev->dev, r1);
> +	if (!info->virt) {
> +		dev_err(&pdev->dev, "Failed to ioremap %p\n",
> +		       info->virt);

You don't need the print message. devm_ioremap_resource() handles this
for you.

> +		return -EFAULT;
> +	}
> +
> +	info->bank = devm_ioremap_resource(&pdev->dev, r2);
> +	if (!info->bank) {
> +		dev_err(&pdev->dev, "Failed to ioremap %p\n",
> +		       info->bank);

Ditto.

> +		return -EFAULT;
> +	}
> +
> +	info->mtd.priv = info;
> +	info->mtd.name = "SRAM";
> +	info->mtd.type = MTD_RAM;
> +	info->mtd.flags = MTD_CAP_RAM;
> +	info->mtd.size = resource_size(r1) << 7;
> +	info->mtd.erasesize = 512;
> +	info->mtd.writesize = 4;
> +	info->mtd._erase = lp8x4x_sram_erase;
> +	info->mtd._write = lp8x4x_sram_write;
> +	info->mtd._read = lp8x4x_sram_read;
> +	info->mtd._sync = lp8x4x_sram_sync;
> +	info->mtd.owner = THIS_MODULE;
> +
> +	mutex_init(&info->lock);
> +	iowrite8(info->active_bank, info->bank);
> +	platform_set_drvdata(pdev, info);
> +
> +	ppdata.of_node = pdev->dev.of_node;
> +	err = mtd_device_parse_register(&info->mtd, probe_types, &ppdata,
> +			NULL, 0);

If you don't need the other partition types (commented above), then you
can just use the defaults (drivers/mtd/mtdpart.c,
default_mtd_part_types) by dropping your 'probe_types' and making the
second argument NULL.

> +
> +	if (err < 0) {
> +		dev_err(&pdev->dev, "Failed to register platform device\n");

How about "failed to register MTD"?

> +		return err;
> +	}
> +
> +	string_get_size(info->mtd.size, STRING_UNITS_2, sz_str,
> +			sizeof(sz_str));
> +	dev_info(&pdev->dev, "using %s SRAM on LP-8X4X as %s\n", sz_str,
> +			dev_name(&info->mtd.dev));
> +	return 0;
> +}
> +
> +static int
> +lp8x4x_sram_remove(struct platform_device *dev)
> +{
> +	struct lp8x4x_sram_info *info = platform_get_drvdata(dev);
> +
> +	mtd_device_unregister(&info->mtd);

Please check the return code.

> +	platform_set_drvdata(dev, NULL);

I don't think you need to do this any more. The driver core takes care
of this on removal.

> +	return 0;

(So just: return mtd_device_unregister(&info->mtd);)

> +}
> +
> +static struct platform_driver lp8x4x_sram_driver = {
> +	.driver = {
> +		.name		= "sram-lp8x4x",
> +		.owner		= THIS_MODULE,
> +		.of_match_table = of_flash_match,
> +	},
> +	.probe		= lp8x4x_sram_probe,
> +	.remove		= lp8x4x_sram_remove,
> +};
> +
> +module_platform_driver(lp8x4x_sram_driver);
> +
> +MODULE_LICENSE("GPL");
> +MODULE_AUTHOR("Sergei Ianovich <ynvich@gmail.com>");
> +MODULE_DESCRIPTION("MTD driver for SRAM on ICPDAS LP-8x4x");

With that, you have my:

	Reviewed-by: Brian Norris <computersforpeace@gmail.com>

and I can merge this to the MTD tree if/when you'd like.

Brian

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

* Re: [PATCH v3 10/21] mtd: support BB SRAM on ICP DAS LP-8x4x
@ 2014-04-16  5:04               ` Brian Norris
  0 siblings, 0 replies; 700+ messages in thread
From: Brian Norris @ 2014-04-16  5:04 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: Mark Rutland, open list:OPEN FIRMWARE AND...,
	Russell King, Kees Cook, Pawel Moll, Ian Campbell,
	Artem Bityutskiy, Robert Jarzmik, Randy Dunlap, linux-kernel,
	Rob Herring, Philip Avinash, Kumar Gala, Grant Likely,
	open list:MEMORY TECHNOLOGY...,
	David Woodhouse, linux-arm-kernel

Hi Sergei,

On Tue, Dec 17, 2013 at 11:37:40PM +0400, Sergei Ianovich wrote:
> This provides an MTD device driver for 512kB of battery backed up SRAM
> on ICPDAS LP-8X4X programmable automation controllers.
> 
> SRAM chip is connected via FPGA and is not accessible without a driver,
> unlike flash memory which is wired to CPU MMU.
> 
> This SRAM becomes an excellent persisent storage of volatile process
> data like counter values and sensor statuses. Storing those data in
> flash or mmc card is not a viable solution.
> 
> Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
> ---
>    v2..v3
>    * no changes (except number 08/16 -> 10/21)
> 
>    v0..v2
>    * use device tree
>    * use devm helpers where possible

What's the status of this series? Is the rest of this platform support
going in via other trees yet? I have a few trivial comments, but this
driver mostly looks good as-is.

>  arch/arm/boot/dts/pxa27x-lp8x4x.dts |   6 +
>  arch/arm/configs/lp8x4x_defconfig   |   1 +
>  drivers/mtd/devices/Kconfig         |  14 +++
>  drivers/mtd/devices/Makefile        |   1 +
>  drivers/mtd/devices/sram_lp8x4x.c   | 227 ++++++++++++++++++++++++++++++++++++
>  5 files changed, 249 insertions(+)
>  create mode 100644 drivers/mtd/devices/sram_lp8x4x.c
> 
> diff --git a/arch/arm/boot/dts/pxa27x-lp8x4x.dts b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
> index 872c386..07856e0 100644
> --- a/arch/arm/boot/dts/pxa27x-lp8x4x.dts
> +++ b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
> @@ -161,6 +161,12 @@
>  				reg = <0x901c 0x1>;
>  				status = "okay";
>  			};
> +
> +			sram@a000 {
> +				compatible = "icpdas,sram-lp8x4x";
> +				reg = <0xa000 0x1000
> +				       0x901e 0x1>;
> +			};

You'll need a (trivial) DT binding doc in
Documentation/devicetree/bindings/ to go with this. You might also need
to split the arch/arm/boot/dts/ stuff out to a separate patch, so the
MTD driver can go in the MTD tree separate from the ARM tree bits.

>  		};
>  	};
>  };
> diff --git a/arch/arm/configs/lp8x4x_defconfig b/arch/arm/configs/lp8x4x_defconfig
> index d60e37a..17a4e6f 100644
> --- a/arch/arm/configs/lp8x4x_defconfig
> +++ b/arch/arm/configs/lp8x4x_defconfig
> @@ -57,6 +57,7 @@ CONFIG_MTD_CFI_ADV_OPTIONS=y
>  CONFIG_MTD_CFI_GEOMETRY=y
>  CONFIG_MTD_CFI_INTELEXT=y
>  CONFIG_MTD_PHYSMAP_OF=y
> +CONFIG_MTD_SRAM_LP8X4X=y
>  CONFIG_PROC_DEVICETREE=y
>  CONFIG_BLK_DEV_LOOP=y
>  CONFIG_BLK_DEV_LOOP_MIN_COUNT=2
> diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig
> index 0128138..95f2075 100644
> --- a/drivers/mtd/devices/Kconfig
> +++ b/drivers/mtd/devices/Kconfig
> @@ -217,4 +217,18 @@ config BCH_CONST_T
>  	default 4
>  endif
>  
> +config MTD_SRAM_LP8X4X
> +	tristate "SRAM on ICPDAS LP-8X4X"
> +	depends on OF && ARCH_PXA
> +       ---help---
> +	 This provides an MTD device driver for 512kiB of battery backed up SRAM
> +	 on ICPDAS LP-8X4X programmable automation controllers.
> +
> +	 SRAM chip is connected via FPGA and is not accessible without a driver,
> +	 unlike flash memory which is wired to CPU MMU.
> +
> +	 Say N, unless you plan to run this kernel on LP-8X4X.
> +
> +	 If you say M, the module will be called sram_lp8x4x.
> +
>  endmenu
> diff --git a/drivers/mtd/devices/Makefile b/drivers/mtd/devices/Makefile
> index d83bd73..56a74c9 100644
> --- a/drivers/mtd/devices/Makefile
> +++ b/drivers/mtd/devices/Makefile
> @@ -16,6 +16,7 @@ obj-$(CONFIG_MTD_NAND_OMAP_BCH)	+= elm.o
>  obj-$(CONFIG_MTD_SPEAR_SMI)	+= spear_smi.o
>  obj-$(CONFIG_MTD_SST25L)	+= sst25l.o
>  obj-$(CONFIG_MTD_BCM47XXSFLASH)	+= bcm47xxsflash.o
> +obj-$(CONFIG_MTD_SRAM_LP8X4X)	+= sram_lp8x4x.o
>  
>  
>  CFLAGS_docg3.o			+= -I$(src)
> diff --git a/drivers/mtd/devices/sram_lp8x4x.c b/drivers/mtd/devices/sram_lp8x4x.c
> new file mode 100644
> index 0000000..9dc7149
> --- /dev/null
> +++ b/drivers/mtd/devices/sram_lp8x4x.c
> @@ -0,0 +1,227 @@
> +/*
> + *  linux/drivers/mtd/devices/lp8x4x_sram.c
> + *
> + *  MTD Driver for SRAM on ICPDAS LP-8x4x
> + *  Copyright (C) 2013 Sergei Ianovich <ynvich@gmail.com>
> + *
> + *  This program is free software; you can redistribute it and/or modify
> + *  it under the terms of the GNU General Public License version 2 as
> + *  published by the Free Software Foundation or any later version.
> + */
> +
> +#include <linux/init.h>
> +#include <linux/io.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/mtd/map.h>
> +#include <linux/mtd/mtd.h>
> +#include <linux/mtd/partitions.h>
> +#include <linux/platform_device.h>
> +#include <linux/of_device.h>
> +#include <linux/slab.h>
> +#include <linux/string_helpers.h>
> +#include <linux/types.h>
> +
> +#include <asm/mach/flash.h>

Do you need this? It looks unused.

> +
> +struct lp8x4x_sram_info {
> +	void __iomem	*bank;
> +	void __iomem	*virt;
> +	struct mutex	lock;
> +	unsigned	active_bank;
> +	struct mtd_info	mtd;
> +};
> +
> +static int
> +lp8x4x_sram_erase(struct mtd_info *mtd, struct erase_info *instr)
> +{
> +	struct lp8x4x_sram_info *info = mtd->priv;
> +	unsigned bank = instr->addr >> 11;
> +	unsigned offset = (instr->addr & 0x7ff) << 1;
> +	loff_t i;
> +
> +	mutex_lock(&info->lock);
> +	if (unlikely(bank != info->active_bank)) {
> +		info->active_bank = bank;
> +		iowrite8(bank, info->bank);
> +	}
> +	for (i = 0; i < instr->len; i++) {
> +		iowrite8(0xff, info->virt + offset);
> +		offset += 2;
> +		if (unlikely(offset == 0)) {
> +			info->active_bank++;
> +			iowrite8(info->active_bank, info->bank);
> +		}
> +	}
> +	mutex_unlock(&info->lock);
> +	instr->state = MTD_ERASE_DONE;
> +	mtd_erase_callback(instr);
> +
> +	return 0;
> +}
> +
> +static int
> +lp8x4x_sram_write(struct mtd_info *mtd, loff_t to, size_t len,
> +		size_t *retlen, const u_char *b)
> +{
> +	struct lp8x4x_sram_info *info = mtd->priv;
> +	unsigned bank = to >> 11;
> +	unsigned offset = (to & 0x7ff) << 1;
> +	loff_t i;
> +
> +	mutex_lock(&info->lock);
> +	if (unlikely(bank != info->active_bank)) {
> +		info->active_bank = bank;
> +		iowrite8(bank, info->bank);
> +	}
> +	for (i = 0; i < len; i++) {
> +		iowrite8(b[i], info->virt + offset);
> +		offset += 2;
> +		if (unlikely(offset == 0)) {
> +			info->active_bank++;
> +			iowrite8(info->active_bank, info->bank);
> +		}
> +	}
> +	mutex_unlock(&info->lock);
> +	*retlen = len;
> +	return 0;
> +}
> +
> +static int
> +lp8x4x_sram_read(struct mtd_info *mtd, loff_t from, size_t len,
> +		size_t *retlen, u_char *b)
> +{
> +	struct lp8x4x_sram_info *info = mtd->priv;
> +	unsigned bank = from >> 11;
> +	unsigned offset = (from & 0x7ff) << 1;
> +	loff_t i;
> +
> +	mutex_lock(&info->lock);
> +	if (unlikely(bank != info->active_bank)) {
> +		info->active_bank = bank;
> +		iowrite8(bank, info->bank);
> +	}
> +	for (i = 0; i < len; i++) {
> +		b[i] = ioread8(info->virt + offset);
> +		offset += 2;
> +		if (unlikely(offset == 0)) {
> +			info->active_bank++;
> +			iowrite8(info->active_bank, info->bank);
> +		}
> +	}
> +	mutex_unlock(&info->lock);
> +	*retlen = len;
> +	return 0;
> +}
> +
> +static void
> +lp8x4x_sram_sync(struct mtd_info *mtd)
> +{
> +}

You don't need the empty call-back. See mtd_sync(), which only calls the
_sync callback if it's filled in.

> +
> +static struct of_device_id of_flash_match[] = {
> +	{
> +		.compatible	= "icpdas,sram-lp8x4x",
> +	},
> +	{ },
> +};
> +MODULE_DEVICE_TABLE(of, of_flash_match);
> +
> +static const char * const probe_types[] = {
> +	"cmdlinepart", "RedBoot", "ofpart", "ofoldpart", NULL };

Please drop 'ofoldpart'; it is obsolte. And do you really want
'RedBoot'?

> +
> +static int
> +lp8x4x_sram_probe(struct platform_device *pdev)
> +{
> +	const struct of_device_id *match;
> +	struct lp8x4x_sram_info *info;
> +	struct resource *r1, *r2;
> +	char sz_str[16];
> +	struct mtd_part_parser_data ppdata;
> +	int err = 0;
> +
> +	match = of_match_device(of_flash_match, &pdev->dev);
> +	if (!match)
> +		return -EINVAL;
> +
> +	r1 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	r2 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
> +	if (!r1 || !r2)
> +		return -ENODEV;

Move these next to the devm_ioremap_resource(), and then remove the
	if (!r1 || !r2)
checks, since devm_ioremap_resource() does them for you. (See
lib/devres.c.)

> +
> +	info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
> +	if (!info)
> +		return -ENOMEM;
> +
> +	info->virt =  devm_ioremap_resource(&pdev->dev, r1);
> +	if (!info->virt) {
> +		dev_err(&pdev->dev, "Failed to ioremap %p\n",
> +		       info->virt);

You don't need the print message. devm_ioremap_resource() handles this
for you.

> +		return -EFAULT;
> +	}
> +
> +	info->bank = devm_ioremap_resource(&pdev->dev, r2);
> +	if (!info->bank) {
> +		dev_err(&pdev->dev, "Failed to ioremap %p\n",
> +		       info->bank);

Ditto.

> +		return -EFAULT;
> +	}
> +
> +	info->mtd.priv = info;
> +	info->mtd.name = "SRAM";
> +	info->mtd.type = MTD_RAM;
> +	info->mtd.flags = MTD_CAP_RAM;
> +	info->mtd.size = resource_size(r1) << 7;
> +	info->mtd.erasesize = 512;
> +	info->mtd.writesize = 4;
> +	info->mtd._erase = lp8x4x_sram_erase;
> +	info->mtd._write = lp8x4x_sram_write;
> +	info->mtd._read = lp8x4x_sram_read;
> +	info->mtd._sync = lp8x4x_sram_sync;
> +	info->mtd.owner = THIS_MODULE;
> +
> +	mutex_init(&info->lock);
> +	iowrite8(info->active_bank, info->bank);
> +	platform_set_drvdata(pdev, info);
> +
> +	ppdata.of_node = pdev->dev.of_node;
> +	err = mtd_device_parse_register(&info->mtd, probe_types, &ppdata,
> +			NULL, 0);

If you don't need the other partition types (commented above), then you
can just use the defaults (drivers/mtd/mtdpart.c,
default_mtd_part_types) by dropping your 'probe_types' and making the
second argument NULL.

> +
> +	if (err < 0) {
> +		dev_err(&pdev->dev, "Failed to register platform device\n");

How about "failed to register MTD"?

> +		return err;
> +	}
> +
> +	string_get_size(info->mtd.size, STRING_UNITS_2, sz_str,
> +			sizeof(sz_str));
> +	dev_info(&pdev->dev, "using %s SRAM on LP-8X4X as %s\n", sz_str,
> +			dev_name(&info->mtd.dev));
> +	return 0;
> +}
> +
> +static int
> +lp8x4x_sram_remove(struct platform_device *dev)
> +{
> +	struct lp8x4x_sram_info *info = platform_get_drvdata(dev);
> +
> +	mtd_device_unregister(&info->mtd);

Please check the return code.

> +	platform_set_drvdata(dev, NULL);

I don't think you need to do this any more. The driver core takes care
of this on removal.

> +	return 0;

(So just: return mtd_device_unregister(&info->mtd);)

> +}
> +
> +static struct platform_driver lp8x4x_sram_driver = {
> +	.driver = {
> +		.name		= "sram-lp8x4x",
> +		.owner		= THIS_MODULE,
> +		.of_match_table = of_flash_match,
> +	},
> +	.probe		= lp8x4x_sram_probe,
> +	.remove		= lp8x4x_sram_remove,
> +};
> +
> +module_platform_driver(lp8x4x_sram_driver);
> +
> +MODULE_LICENSE("GPL");
> +MODULE_AUTHOR("Sergei Ianovich <ynvich@gmail.com>");
> +MODULE_DESCRIPTION("MTD driver for SRAM on ICPDAS LP-8x4x");

With that, you have my:

	Reviewed-by: Brian Norris <computersforpeace@gmail.com>

and I can merge this to the MTD tree if/when you'd like.

Brian

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

* [PATCH v3 10/21] mtd: support BB SRAM on ICP DAS LP-8x4x
@ 2014-04-16  5:04               ` Brian Norris
  0 siblings, 0 replies; 700+ messages in thread
From: Brian Norris @ 2014-04-16  5:04 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Sergei,

On Tue, Dec 17, 2013 at 11:37:40PM +0400, Sergei Ianovich wrote:
> This provides an MTD device driver for 512kB of battery backed up SRAM
> on ICPDAS LP-8X4X programmable automation controllers.
> 
> SRAM chip is connected via FPGA and is not accessible without a driver,
> unlike flash memory which is wired to CPU MMU.
> 
> This SRAM becomes an excellent persisent storage of volatile process
> data like counter values and sensor statuses. Storing those data in
> flash or mmc card is not a viable solution.
> 
> Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
> ---
>    v2..v3
>    * no changes (except number 08/16 -> 10/21)
> 
>    v0..v2
>    * use device tree
>    * use devm helpers where possible

What's the status of this series? Is the rest of this platform support
going in via other trees yet? I have a few trivial comments, but this
driver mostly looks good as-is.

>  arch/arm/boot/dts/pxa27x-lp8x4x.dts |   6 +
>  arch/arm/configs/lp8x4x_defconfig   |   1 +
>  drivers/mtd/devices/Kconfig         |  14 +++
>  drivers/mtd/devices/Makefile        |   1 +
>  drivers/mtd/devices/sram_lp8x4x.c   | 227 ++++++++++++++++++++++++++++++++++++
>  5 files changed, 249 insertions(+)
>  create mode 100644 drivers/mtd/devices/sram_lp8x4x.c
> 
> diff --git a/arch/arm/boot/dts/pxa27x-lp8x4x.dts b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
> index 872c386..07856e0 100644
> --- a/arch/arm/boot/dts/pxa27x-lp8x4x.dts
> +++ b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
> @@ -161,6 +161,12 @@
>  				reg = <0x901c 0x1>;
>  				status = "okay";
>  			};
> +
> +			sram at a000 {
> +				compatible = "icpdas,sram-lp8x4x";
> +				reg = <0xa000 0x1000
> +				       0x901e 0x1>;
> +			};

You'll need a (trivial) DT binding doc in
Documentation/devicetree/bindings/ to go with this. You might also need
to split the arch/arm/boot/dts/ stuff out to a separate patch, so the
MTD driver can go in the MTD tree separate from the ARM tree bits.

>  		};
>  	};
>  };
> diff --git a/arch/arm/configs/lp8x4x_defconfig b/arch/arm/configs/lp8x4x_defconfig
> index d60e37a..17a4e6f 100644
> --- a/arch/arm/configs/lp8x4x_defconfig
> +++ b/arch/arm/configs/lp8x4x_defconfig
> @@ -57,6 +57,7 @@ CONFIG_MTD_CFI_ADV_OPTIONS=y
>  CONFIG_MTD_CFI_GEOMETRY=y
>  CONFIG_MTD_CFI_INTELEXT=y
>  CONFIG_MTD_PHYSMAP_OF=y
> +CONFIG_MTD_SRAM_LP8X4X=y
>  CONFIG_PROC_DEVICETREE=y
>  CONFIG_BLK_DEV_LOOP=y
>  CONFIG_BLK_DEV_LOOP_MIN_COUNT=2
> diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig
> index 0128138..95f2075 100644
> --- a/drivers/mtd/devices/Kconfig
> +++ b/drivers/mtd/devices/Kconfig
> @@ -217,4 +217,18 @@ config BCH_CONST_T
>  	default 4
>  endif
>  
> +config MTD_SRAM_LP8X4X
> +	tristate "SRAM on ICPDAS LP-8X4X"
> +	depends on OF && ARCH_PXA
> +       ---help---
> +	 This provides an MTD device driver for 512kiB of battery backed up SRAM
> +	 on ICPDAS LP-8X4X programmable automation controllers.
> +
> +	 SRAM chip is connected via FPGA and is not accessible without a driver,
> +	 unlike flash memory which is wired to CPU MMU.
> +
> +	 Say N, unless you plan to run this kernel on LP-8X4X.
> +
> +	 If you say M, the module will be called sram_lp8x4x.
> +
>  endmenu
> diff --git a/drivers/mtd/devices/Makefile b/drivers/mtd/devices/Makefile
> index d83bd73..56a74c9 100644
> --- a/drivers/mtd/devices/Makefile
> +++ b/drivers/mtd/devices/Makefile
> @@ -16,6 +16,7 @@ obj-$(CONFIG_MTD_NAND_OMAP_BCH)	+= elm.o
>  obj-$(CONFIG_MTD_SPEAR_SMI)	+= spear_smi.o
>  obj-$(CONFIG_MTD_SST25L)	+= sst25l.o
>  obj-$(CONFIG_MTD_BCM47XXSFLASH)	+= bcm47xxsflash.o
> +obj-$(CONFIG_MTD_SRAM_LP8X4X)	+= sram_lp8x4x.o
>  
>  
>  CFLAGS_docg3.o			+= -I$(src)
> diff --git a/drivers/mtd/devices/sram_lp8x4x.c b/drivers/mtd/devices/sram_lp8x4x.c
> new file mode 100644
> index 0000000..9dc7149
> --- /dev/null
> +++ b/drivers/mtd/devices/sram_lp8x4x.c
> @@ -0,0 +1,227 @@
> +/*
> + *  linux/drivers/mtd/devices/lp8x4x_sram.c
> + *
> + *  MTD Driver for SRAM on ICPDAS LP-8x4x
> + *  Copyright (C) 2013 Sergei Ianovich <ynvich@gmail.com>
> + *
> + *  This program is free software; you can redistribute it and/or modify
> + *  it under the terms of the GNU General Public License version 2 as
> + *  published by the Free Software Foundation or any later version.
> + */
> +
> +#include <linux/init.h>
> +#include <linux/io.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/mtd/map.h>
> +#include <linux/mtd/mtd.h>
> +#include <linux/mtd/partitions.h>
> +#include <linux/platform_device.h>
> +#include <linux/of_device.h>
> +#include <linux/slab.h>
> +#include <linux/string_helpers.h>
> +#include <linux/types.h>
> +
> +#include <asm/mach/flash.h>

Do you need this? It looks unused.

> +
> +struct lp8x4x_sram_info {
> +	void __iomem	*bank;
> +	void __iomem	*virt;
> +	struct mutex	lock;
> +	unsigned	active_bank;
> +	struct mtd_info	mtd;
> +};
> +
> +static int
> +lp8x4x_sram_erase(struct mtd_info *mtd, struct erase_info *instr)
> +{
> +	struct lp8x4x_sram_info *info = mtd->priv;
> +	unsigned bank = instr->addr >> 11;
> +	unsigned offset = (instr->addr & 0x7ff) << 1;
> +	loff_t i;
> +
> +	mutex_lock(&info->lock);
> +	if (unlikely(bank != info->active_bank)) {
> +		info->active_bank = bank;
> +		iowrite8(bank, info->bank);
> +	}
> +	for (i = 0; i < instr->len; i++) {
> +		iowrite8(0xff, info->virt + offset);
> +		offset += 2;
> +		if (unlikely(offset == 0)) {
> +			info->active_bank++;
> +			iowrite8(info->active_bank, info->bank);
> +		}
> +	}
> +	mutex_unlock(&info->lock);
> +	instr->state = MTD_ERASE_DONE;
> +	mtd_erase_callback(instr);
> +
> +	return 0;
> +}
> +
> +static int
> +lp8x4x_sram_write(struct mtd_info *mtd, loff_t to, size_t len,
> +		size_t *retlen, const u_char *b)
> +{
> +	struct lp8x4x_sram_info *info = mtd->priv;
> +	unsigned bank = to >> 11;
> +	unsigned offset = (to & 0x7ff) << 1;
> +	loff_t i;
> +
> +	mutex_lock(&info->lock);
> +	if (unlikely(bank != info->active_bank)) {
> +		info->active_bank = bank;
> +		iowrite8(bank, info->bank);
> +	}
> +	for (i = 0; i < len; i++) {
> +		iowrite8(b[i], info->virt + offset);
> +		offset += 2;
> +		if (unlikely(offset == 0)) {
> +			info->active_bank++;
> +			iowrite8(info->active_bank, info->bank);
> +		}
> +	}
> +	mutex_unlock(&info->lock);
> +	*retlen = len;
> +	return 0;
> +}
> +
> +static int
> +lp8x4x_sram_read(struct mtd_info *mtd, loff_t from, size_t len,
> +		size_t *retlen, u_char *b)
> +{
> +	struct lp8x4x_sram_info *info = mtd->priv;
> +	unsigned bank = from >> 11;
> +	unsigned offset = (from & 0x7ff) << 1;
> +	loff_t i;
> +
> +	mutex_lock(&info->lock);
> +	if (unlikely(bank != info->active_bank)) {
> +		info->active_bank = bank;
> +		iowrite8(bank, info->bank);
> +	}
> +	for (i = 0; i < len; i++) {
> +		b[i] = ioread8(info->virt + offset);
> +		offset += 2;
> +		if (unlikely(offset == 0)) {
> +			info->active_bank++;
> +			iowrite8(info->active_bank, info->bank);
> +		}
> +	}
> +	mutex_unlock(&info->lock);
> +	*retlen = len;
> +	return 0;
> +}
> +
> +static void
> +lp8x4x_sram_sync(struct mtd_info *mtd)
> +{
> +}

You don't need the empty call-back. See mtd_sync(), which only calls the
_sync callback if it's filled in.

> +
> +static struct of_device_id of_flash_match[] = {
> +	{
> +		.compatible	= "icpdas,sram-lp8x4x",
> +	},
> +	{ },
> +};
> +MODULE_DEVICE_TABLE(of, of_flash_match);
> +
> +static const char * const probe_types[] = {
> +	"cmdlinepart", "RedBoot", "ofpart", "ofoldpart", NULL };

Please drop 'ofoldpart'; it is obsolte. And do you really want
'RedBoot'?

> +
> +static int
> +lp8x4x_sram_probe(struct platform_device *pdev)
> +{
> +	const struct of_device_id *match;
> +	struct lp8x4x_sram_info *info;
> +	struct resource *r1, *r2;
> +	char sz_str[16];
> +	struct mtd_part_parser_data ppdata;
> +	int err = 0;
> +
> +	match = of_match_device(of_flash_match, &pdev->dev);
> +	if (!match)
> +		return -EINVAL;
> +
> +	r1 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	r2 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
> +	if (!r1 || !r2)
> +		return -ENODEV;

Move these next to the devm_ioremap_resource(), and then remove the
	if (!r1 || !r2)
checks, since devm_ioremap_resource() does them for you. (See
lib/devres.c.)

> +
> +	info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
> +	if (!info)
> +		return -ENOMEM;
> +
> +	info->virt =  devm_ioremap_resource(&pdev->dev, r1);
> +	if (!info->virt) {
> +		dev_err(&pdev->dev, "Failed to ioremap %p\n",
> +		       info->virt);

You don't need the print message. devm_ioremap_resource() handles this
for you.

> +		return -EFAULT;
> +	}
> +
> +	info->bank = devm_ioremap_resource(&pdev->dev, r2);
> +	if (!info->bank) {
> +		dev_err(&pdev->dev, "Failed to ioremap %p\n",
> +		       info->bank);

Ditto.

> +		return -EFAULT;
> +	}
> +
> +	info->mtd.priv = info;
> +	info->mtd.name = "SRAM";
> +	info->mtd.type = MTD_RAM;
> +	info->mtd.flags = MTD_CAP_RAM;
> +	info->mtd.size = resource_size(r1) << 7;
> +	info->mtd.erasesize = 512;
> +	info->mtd.writesize = 4;
> +	info->mtd._erase = lp8x4x_sram_erase;
> +	info->mtd._write = lp8x4x_sram_write;
> +	info->mtd._read = lp8x4x_sram_read;
> +	info->mtd._sync = lp8x4x_sram_sync;
> +	info->mtd.owner = THIS_MODULE;
> +
> +	mutex_init(&info->lock);
> +	iowrite8(info->active_bank, info->bank);
> +	platform_set_drvdata(pdev, info);
> +
> +	ppdata.of_node = pdev->dev.of_node;
> +	err = mtd_device_parse_register(&info->mtd, probe_types, &ppdata,
> +			NULL, 0);

If you don't need the other partition types (commented above), then you
can just use the defaults (drivers/mtd/mtdpart.c,
default_mtd_part_types) by dropping your 'probe_types' and making the
second argument NULL.

> +
> +	if (err < 0) {
> +		dev_err(&pdev->dev, "Failed to register platform device\n");

How about "failed to register MTD"?

> +		return err;
> +	}
> +
> +	string_get_size(info->mtd.size, STRING_UNITS_2, sz_str,
> +			sizeof(sz_str));
> +	dev_info(&pdev->dev, "using %s SRAM on LP-8X4X as %s\n", sz_str,
> +			dev_name(&info->mtd.dev));
> +	return 0;
> +}
> +
> +static int
> +lp8x4x_sram_remove(struct platform_device *dev)
> +{
> +	struct lp8x4x_sram_info *info = platform_get_drvdata(dev);
> +
> +	mtd_device_unregister(&info->mtd);

Please check the return code.

> +	platform_set_drvdata(dev, NULL);

I don't think you need to do this any more. The driver core takes care
of this on removal.

> +	return 0;

(So just: return mtd_device_unregister(&info->mtd);)

> +}
> +
> +static struct platform_driver lp8x4x_sram_driver = {
> +	.driver = {
> +		.name		= "sram-lp8x4x",
> +		.owner		= THIS_MODULE,
> +		.of_match_table = of_flash_match,
> +	},
> +	.probe		= lp8x4x_sram_probe,
> +	.remove		= lp8x4x_sram_remove,
> +};
> +
> +module_platform_driver(lp8x4x_sram_driver);
> +
> +MODULE_LICENSE("GPL");
> +MODULE_AUTHOR("Sergei Ianovich <ynvich@gmail.com>");
> +MODULE_DESCRIPTION("MTD driver for SRAM on ICPDAS LP-8x4x");

With that, you have my:

	Reviewed-by: Brian Norris <computersforpeace@gmail.com>

and I can merge this to the MTD tree if/when you'd like.

Brian

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

* Re: [PATCH v3 10/21] mtd: support BB SRAM on ICP DAS LP-8x4x
  2014-04-16  5:04               ` Brian Norris
  (?)
@ 2014-04-16  5:21                 ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2014-04-16  5:21 UTC (permalink / raw)
  To: Brian Norris
  Cc: linux-kernel, linux-arm-kernel, Rob Herring, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala, Russell King,
	David Woodhouse, Grant Likely, Artem Bityutskiy, Robert Jarzmik,
	Kees Cook, Randy Dunlap, Philip Avinash,
	open list:OPEN FIRMWARE AND..., open list:MEMORY TECHNOLOGY...

On Tue, 2014-04-15 at 22:04 -0700, Brian Norris wrote:
> Hi Sergei,
> 
> On Tue, Dec 17, 2013 at 11:37:40PM +0400, Sergei Ianovich wrote:
> > This provides an MTD device driver for 512kB of battery backed up SRAM
> > on ICPDAS LP-8X4X programmable automation controllers.
> > 
> > SRAM chip is connected via FPGA and is not accessible without a driver,
> > unlike flash memory which is wired to CPU MMU.
> > 
> > This SRAM becomes an excellent persisent storage of volatile process
> > data like counter values and sensor statuses. Storing those data in
> > flash or mmc card is not a viable solution.
> > 
> > Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
> > ---
> >    v2..v3
> >    * no changes (except number 08/16 -> 10/21)
> > 
> >    v0..v2
> >    * use device tree
> >    * use devm helpers where possible
> 
> What's the status of this series? Is the rest of this platform support
> going in via other trees yet? I have a few trivial comments, but this
> driver mostly looks good as-is.

(...)

> You'll need a (trivial) DT binding doc in
> Documentation/devicetree/bindings/ to go with this. You might also need
> to split the arch/arm/boot/dts/ stuff out to a separate patch, so the
> MTD driver can go in the MTD tree separate from the ARM tree bits.

(...)

> With that, you have my:
> 
> 	Reviewed-by: Brian Norris <computersforpeace@gmail.com>
> 
> and I can merge this to the MTD tree if/when you'd like.

Thanks for response, the rest of the series is stuck on a DMA driver
with no development activity. I'll fix the comments, separate ARM staff
and refile the patch.


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

* Re: [PATCH v3 10/21] mtd: support BB SRAM on ICP DAS LP-8x4x
@ 2014-04-16  5:21                 ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2014-04-16  5:21 UTC (permalink / raw)
  To: Brian Norris
  Cc: Mark Rutland, open list:OPEN FIRMWARE AND...,
	Russell King, Kees Cook, Pawel Moll, Ian Campbell,
	Artem Bityutskiy, Robert Jarzmik, Randy Dunlap, linux-kernel,
	Rob Herring, Philip Avinash, Kumar Gala, Grant Likely,
	open list:MEMORY TECHNOLOGY...,
	David Woodhouse, linux-arm-kernel

On Tue, 2014-04-15 at 22:04 -0700, Brian Norris wrote:
> Hi Sergei,
> 
> On Tue, Dec 17, 2013 at 11:37:40PM +0400, Sergei Ianovich wrote:
> > This provides an MTD device driver for 512kB of battery backed up SRAM
> > on ICPDAS LP-8X4X programmable automation controllers.
> > 
> > SRAM chip is connected via FPGA and is not accessible without a driver,
> > unlike flash memory which is wired to CPU MMU.
> > 
> > This SRAM becomes an excellent persisent storage of volatile process
> > data like counter values and sensor statuses. Storing those data in
> > flash or mmc card is not a viable solution.
> > 
> > Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
> > ---
> >    v2..v3
> >    * no changes (except number 08/16 -> 10/21)
> > 
> >    v0..v2
> >    * use device tree
> >    * use devm helpers where possible
> 
> What's the status of this series? Is the rest of this platform support
> going in via other trees yet? I have a few trivial comments, but this
> driver mostly looks good as-is.

(...)

> You'll need a (trivial) DT binding doc in
> Documentation/devicetree/bindings/ to go with this. You might also need
> to split the arch/arm/boot/dts/ stuff out to a separate patch, so the
> MTD driver can go in the MTD tree separate from the ARM tree bits.

(...)

> With that, you have my:
> 
> 	Reviewed-by: Brian Norris <computersforpeace@gmail.com>
> 
> and I can merge this to the MTD tree if/when you'd like.

Thanks for response, the rest of the series is stuck on a DMA driver
with no development activity. I'll fix the comments, separate ARM staff
and refile the patch.

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

* [PATCH v3 10/21] mtd: support BB SRAM on ICP DAS LP-8x4x
@ 2014-04-16  5:21                 ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2014-04-16  5:21 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, 2014-04-15 at 22:04 -0700, Brian Norris wrote:
> Hi Sergei,
> 
> On Tue, Dec 17, 2013 at 11:37:40PM +0400, Sergei Ianovich wrote:
> > This provides an MTD device driver for 512kB of battery backed up SRAM
> > on ICPDAS LP-8X4X programmable automation controllers.
> > 
> > SRAM chip is connected via FPGA and is not accessible without a driver,
> > unlike flash memory which is wired to CPU MMU.
> > 
> > This SRAM becomes an excellent persisent storage of volatile process
> > data like counter values and sensor statuses. Storing those data in
> > flash or mmc card is not a viable solution.
> > 
> > Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
> > ---
> >    v2..v3
> >    * no changes (except number 08/16 -> 10/21)
> > 
> >    v0..v2
> >    * use device tree
> >    * use devm helpers where possible
> 
> What's the status of this series? Is the rest of this platform support
> going in via other trees yet? I have a few trivial comments, but this
> driver mostly looks good as-is.

(...)

> You'll need a (trivial) DT binding doc in
> Documentation/devicetree/bindings/ to go with this. You might also need
> to split the arch/arm/boot/dts/ stuff out to a separate patch, so the
> MTD driver can go in the MTD tree separate from the ARM tree bits.

(...)

> With that, you have my:
> 
> 	Reviewed-by: Brian Norris <computersforpeace@gmail.com>
> 
> and I can merge this to the MTD tree if/when you'd like.

Thanks for response, the rest of the series is stuck on a DMA driver
with no development activity. I'll fix the comments, separate ARM staff
and refile the patch.

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

* [PATCH v4 00/21] ARM: support for ICP DAS LP-8x4x (with dts)
  2013-12-17 19:37           ` Sergei Ianovich
@ 2014-04-16 17:13             ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2014-04-16 17:13 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Daniel Mack, Arnd Bergmann, Haojian Zhuang

Hi Arnd,

We had an intensive discussion of the series in the beginning of
December 2013 [1]. The discussion resulted in 3 versions of the series
in less than 3 weeks. Then there was a decision to block this series
until Daniel Mack's DMA-engine-for-PXA series is ready.

Unfortunately Daniel neigther agrees to review my trivial temporary
solution to the DMA-in-device-tree (patch 7 of 21), nor he is active
in DMA series development. There is no progress for 3 months.

As with any big out of tree series, its support is painful. It requires
extensive merging when doing bisects, on each step.

It would great if the decision to block could be reconsidered, and we could
move forward.

Best,

Sergei Ianovich

1. http://linux-kernel.2935.n7.nabble.com/PATCH-00-11-ARM-support-for-ICP-DAS-LP-8x4x-td761919.html

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

* [PATCH v4 00/21] ARM: support for ICP DAS LP-8x4x (with dts)
@ 2014-04-16 17:13             ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2014-04-16 17:13 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Arnd,

We had an intensive discussion of the series in the beginning of
December 2013 [1]. The discussion resulted in 3 versions of the series
in less than 3 weeks. Then there was a decision to block this series
until Daniel Mack's DMA-engine-for-PXA series is ready.

Unfortunately Daniel neigther agrees to review my trivial temporary
solution to the DMA-in-device-tree (patch 7 of 21), nor he is active
in DMA series development. There is no progress for 3 months.

As with any big out of tree series, its support is painful. It requires
extensive merging when doing bisects, on each step.

It would great if the decision to block could be reconsidered, and we could
move forward.

Best,

Sergei Ianovich

1. http://linux-kernel.2935.n7.nabble.com/PATCH-00-11-ARM-support-for-ICP-DAS-LP-8x4x-td761919.html

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

* [PATCH v4 01/21] serial: rewrite pxa2xx-uart to use 8250_core
  2014-04-16 17:13             ` Sergei Ianovich
  (?)
@ 2014-04-16 17:13               ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2014-04-16 17:13 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Russell King, Greg Kroah-Hartman, Jiri Slaby,
	Grant Likely, Rob Herring, James Cameron, Heikki Krogerus,
	Paul Bolle, Arnd Bergmann, Randy Dunlap, Stefan Seyfried,
	open list:SERIAL DRIVERS, open list:OPEN FIRMWARE AND...

pxa2xx-uart was a separate uart platform driver. It was declaring
the same device names and numbers as 8250 driver. As a result,
it was impossible to use 8250 driver on PXA SoCs.

Upon closer examination pxa2xx-uart turned out to be a clone of
8250_core driver.

Workaround for Erratum #19 according to Marvel(R) PXA270M Processor
Specification Update (April 19, 2010) is dropped. 8250_core reads
from FIFO immediately after checking DR bit in LSR.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Reviewed-by: James Cameron <quozl@laptop.org>
Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 Resenging together with the rest of the series as the series
 breaks without this one at [PATCH 12/21]

 no changes v3..v4

 changes v2..v3
 * remove devm_free/put as suggested by Heikki Krogerus
 * use SET_SYSTEM_SLEEP_PM_OPS macro to set pm ops as suggested
   by Heikki Krogerus

 changes v1..v2
 * actually implement workaround for E74 in dl_write as spooted
   by James Cameron
 * added comment about E19 in commit message

 arch/arm/configs/am200epdkit_defconfig    |   3 +-
 arch/arm/configs/cm_x2xx_defconfig        |   3 +-
 arch/arm/configs/cm_x300_defconfig        |   3 +-
 arch/arm/configs/colibri_pxa270_defconfig |   3 +-
 arch/arm/configs/colibri_pxa300_defconfig |   3 +-
 arch/arm/configs/corgi_defconfig          |   4 +-
 arch/arm/configs/em_x270_defconfig        |   3 +-
 arch/arm/configs/ezx_defconfig            |   3 +-
 arch/arm/configs/h5000_defconfig          |   3 +-
 arch/arm/configs/imote2_defconfig         |   3 +-
 arch/arm/configs/lpd270_defconfig         |   3 +-
 arch/arm/configs/lubbock_defconfig        |   3 +-
 arch/arm/configs/mainstone_defconfig      |   3 +-
 arch/arm/configs/mmp2_defconfig           |   3 +-
 arch/arm/configs/pcm027_defconfig         |   3 +-
 arch/arm/configs/pxa168_defconfig         |   3 +-
 arch/arm/configs/pxa255-idp_defconfig     |   3 +-
 arch/arm/configs/pxa3xx_defconfig         |   3 +-
 arch/arm/configs/pxa910_defconfig         |   3 +-
 arch/arm/configs/raumfeld_defconfig       |   3 +-
 arch/arm/configs/spitz_defconfig          |   4 +-
 arch/arm/configs/trizeps4_defconfig       |   3 +-
 arch/arm/configs/viper_defconfig          |   4 +-
 arch/arm/configs/xcep_defconfig           |   3 +-
 drivers/tty/serial/8250/8250_pxa.c        | 178 ++++++
 drivers/tty/serial/8250/Kconfig           |   9 +
 drivers/tty/serial/8250/Makefile          |   1 +
 drivers/tty/serial/Kconfig                |  23 -
 drivers/tty/serial/Makefile               |   1 -
 drivers/tty/serial/pxa.c                  | 971 ------------------------------
 30 files changed, 236 insertions(+), 1022 deletions(-)
 create mode 100644 drivers/tty/serial/8250/8250_pxa.c
 delete mode 100644 drivers/tty/serial/pxa.c

diff --git a/arch/arm/configs/am200epdkit_defconfig b/arch/arm/configs/am200epdkit_defconfig
index f0dea52..0cde234 100644
--- a/arch/arm/configs/am200epdkit_defconfig
+++ b/arch/arm/configs/am200epdkit_defconfig
@@ -60,8 +60,9 @@ CONFIG_BLK_DEV_IDECS=m
 CONFIG_NETDEVICES=y
 CONFIG_NET_ETHERNET=y
 CONFIG_SMC91X=m
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 # CONFIG_HWMON is not set
diff --git a/arch/arm/configs/cm_x2xx_defconfig b/arch/arm/configs/cm_x2xx_defconfig
index a93ff8d..b9fbe65 100644
--- a/arch/arm/configs/cm_x2xx_defconfig
+++ b/arch/arm/configs/cm_x2xx_defconfig
@@ -96,8 +96,9 @@ CONFIG_KEYBOARD_PXA27x=m
 CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_TOUCHSCREEN_UCB1400=m
 # CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_LEGACY_PTY_COUNT=16
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/cm_x300_defconfig b/arch/arm/configs/cm_x300_defconfig
index f4b7672..53a82ae 100644
--- a/arch/arm/configs/cm_x300_defconfig
+++ b/arch/arm/configs/cm_x300_defconfig
@@ -80,8 +80,9 @@ CONFIG_TOUCHSCREEN_WM97XX=m
 # CONFIG_TOUCHSCREEN_WM9713 is not set
 # CONFIG_SERIO is not set
 # CONFIG_LEGACY_PTYS is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
 CONFIG_I2C_PXA=y
diff --git a/arch/arm/configs/colibri_pxa270_defconfig b/arch/arm/configs/colibri_pxa270_defconfig
index 2ef2c5e..1ce0409 100644
--- a/arch/arm/configs/colibri_pxa270_defconfig
+++ b/arch/arm/configs/colibri_pxa270_defconfig
@@ -103,8 +103,9 @@ CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=m
 CONFIG_SERIO_LIBPS2=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_HW_RANDOM=y
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
diff --git a/arch/arm/configs/colibri_pxa300_defconfig b/arch/arm/configs/colibri_pxa300_defconfig
index b985334..f96bda0 100644
--- a/arch/arm/configs/colibri_pxa300_defconfig
+++ b/arch/arm/configs/colibri_pxa300_defconfig
@@ -31,8 +31,9 @@ CONFIG_INPUT_EVDEV=y
 # CONFIG_INPUT_MOUSE is not set
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_GPIO_ROTARY_ENCODER=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_HW_RANDOM=y
 CONFIG_DEBUG_GPIO=y
 # CONFIG_HWMON is not set
diff --git a/arch/arm/configs/corgi_defconfig b/arch/arm/configs/corgi_defconfig
index 1fd1d1d..bb4842d 100644
--- a/arch/arm/configs/corgi_defconfig
+++ b/arch/arm/configs/corgi_defconfig
@@ -131,10 +131,10 @@ CONFIG_TOUCHSCREEN_ADS7846=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=m
 # CONFIG_SERIO is not set
-CONFIG_SERIAL_8250=m
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_CS=m
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 CONFIG_I2C=y
 CONFIG_I2C_PXA=y
diff --git a/arch/arm/configs/em_x270_defconfig b/arch/arm/configs/em_x270_defconfig
index 60a21e0..ec0ec54 100644
--- a/arch/arm/configs/em_x270_defconfig
+++ b/arch/arm/configs/em_x270_defconfig
@@ -90,8 +90,9 @@ CONFIG_TOUCHSCREEN_WM97XX=m
 # CONFIG_TOUCHSCREEN_WM9705 is not set
 # CONFIG_TOUCHSCREEN_WM9713 is not set
 # CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_LEGACY_PTY_COUNT=16
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/ezx_defconfig b/arch/arm/configs/ezx_defconfig
index d95763d..631e2ec 100644
--- a/arch/arm/configs/ezx_defconfig
+++ b/arch/arm/configs/ezx_defconfig
@@ -215,8 +215,9 @@ CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=y
 CONFIG_INPUT_PCAP=y
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_LEGACY_PTY_COUNT=8
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/h5000_defconfig b/arch/arm/configs/h5000_defconfig
index 37903e3..655b735 100644
--- a/arch/arm/configs/h5000_defconfig
+++ b/arch/arm/configs/h5000_defconfig
@@ -47,8 +47,9 @@ CONFIG_MTD_PHYSMAP=y
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_LEGACY_PTY_COUNT=32
 # CONFIG_HW_RANDOM is not set
 # CONFIG_HWMON is not set
diff --git a/arch/arm/configs/imote2_defconfig b/arch/arm/configs/imote2_defconfig
index fd996bb..49d45e9 100644
--- a/arch/arm/configs/imote2_defconfig
+++ b/arch/arm/configs/imote2_defconfig
@@ -193,8 +193,9 @@ CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=y
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_LEGACY_PTY_COUNT=8
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/lpd270_defconfig b/arch/arm/configs/lpd270_defconfig
index 1c8c9ee..c3927b6 100644
--- a/arch/arm/configs/lpd270_defconfig
+++ b/arch/arm/configs/lpd270_defconfig
@@ -38,8 +38,9 @@ CONFIG_SMC91X=y
 CONFIG_INPUT_EVDEV=y
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_HW_RANDOM is not set
 CONFIG_FB=y
 CONFIG_FB_PXA=y
diff --git a/arch/arm/configs/lubbock_defconfig b/arch/arm/configs/lubbock_defconfig
index c4ba274..c8b0436 100644
--- a/arch/arm/configs/lubbock_defconfig
+++ b/arch/arm/configs/lubbock_defconfig
@@ -37,8 +37,9 @@ CONFIG_PCMCIA_PCNET=y
 CONFIG_INPUT_EVDEV=y
 # CONFIG_SERIO_SERPORT is not set
 CONFIG_SERIO_SA1111=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_USB_GADGET=y
 CONFIG_USB_G_SERIAL=m
diff --git a/arch/arm/configs/mainstone_defconfig b/arch/arm/configs/mainstone_defconfig
index 04efa1b..768892c 100644
--- a/arch/arm/configs/mainstone_defconfig
+++ b/arch/arm/configs/mainstone_defconfig
@@ -34,8 +34,9 @@ CONFIG_SMC91X=y
 CONFIG_INPUT_EVDEV=y
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_FB=y
 CONFIG_FB_PXA=y
 # CONFIG_VGA_CONSOLE is not set
diff --git a/arch/arm/configs/mmp2_defconfig b/arch/arm/configs/mmp2_defconfig
index f1cb95e..1ced9df 100644
--- a/arch/arm/configs/mmp2_defconfig
+++ b/arch/arm/configs/mmp2_defconfig
@@ -44,8 +44,9 @@ CONFIG_SMC91X=y
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/pcm027_defconfig b/arch/arm/configs/pcm027_defconfig
index 2f136c3..1280128 100644
--- a/arch/arm/configs/pcm027_defconfig
+++ b/arch/arm/configs/pcm027_defconfig
@@ -60,8 +60,9 @@ CONFIG_SMC91X=y
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/pxa168_defconfig b/arch/arm/configs/pxa168_defconfig
index 74d7e01..1668dac 100644
--- a/arch/arm/configs/pxa168_defconfig
+++ b/arch/arm/configs/pxa168_defconfig
@@ -40,8 +40,9 @@ CONFIG_SMC91X=y
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 # CONFIG_HWMON is not set
diff --git a/arch/arm/configs/pxa255-idp_defconfig b/arch/arm/configs/pxa255-idp_defconfig
index 917a070..399a706 100644
--- a/arch/arm/configs/pxa255-idp_defconfig
+++ b/arch/arm/configs/pxa255-idp_defconfig
@@ -35,8 +35,9 @@ CONFIG_SMC91X=y
 CONFIG_INPUT_EVDEV=y
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_FB=y
 CONFIG_FB_PXA=y
 # CONFIG_VGA_CONSOLE is not set
diff --git a/arch/arm/configs/pxa3xx_defconfig b/arch/arm/configs/pxa3xx_defconfig
index 60e3138..7c3e052 100644
--- a/arch/arm/configs/pxa3xx_defconfig
+++ b/arch/arm/configs/pxa3xx_defconfig
@@ -56,8 +56,9 @@ CONFIG_KEYBOARD_PXA27x=y
 CONFIG_KEYBOARD_PXA930_ROTARY=y
 CONFIG_MOUSE_PXA930_TRKBALL=y
 CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/pxa910_defconfig b/arch/arm/configs/pxa910_defconfig
index 3bb7771..cdacfcb 100644
--- a/arch/arm/configs/pxa910_defconfig
+++ b/arch/arm/configs/pxa910_defconfig
@@ -40,8 +40,9 @@ CONFIG_SMC91X=y
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_SPI=y
 CONFIG_FB=y
 CONFIG_MMP_DISP=y
diff --git a/arch/arm/configs/raumfeld_defconfig b/arch/arm/configs/raumfeld_defconfig
index f7caa90..f1e16f2 100644
--- a/arch/arm/configs/raumfeld_defconfig
+++ b/arch/arm/configs/raumfeld_defconfig
@@ -67,8 +67,9 @@ CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_TOUCHSCREEN_EETI=m
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_GPIO_ROTARY_ENCODER=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_HW_RANDOM=y
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
diff --git a/arch/arm/configs/spitz_defconfig b/arch/arm/configs/spitz_defconfig
index 2e0419d..b6efcf5 100644
--- a/arch/arm/configs/spitz_defconfig
+++ b/arch/arm/configs/spitz_defconfig
@@ -128,10 +128,10 @@ CONFIG_TOUCHSCREEN_ADS7846=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=m
 # CONFIG_SERIO is not set
-CONFIG_SERIAL_8250=m
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_CS=m
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 CONFIG_SPI=y
 CONFIG_SPI_PXA2XX=y
diff --git a/arch/arm/configs/trizeps4_defconfig b/arch/arm/configs/trizeps4_defconfig
index 3162173..453c79c 100644
--- a/arch/arm/configs/trizeps4_defconfig
+++ b/arch/arm/configs/trizeps4_defconfig
@@ -132,8 +132,9 @@ CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=m
 CONFIG_SERIO_LIBPS2=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_HW_RANDOM=y
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
diff --git a/arch/arm/configs/viper_defconfig b/arch/arm/configs/viper_defconfig
index d36e0d3..4efac06 100644
--- a/arch/arm/configs/viper_defconfig
+++ b/arch/arm/configs/viper_defconfig
@@ -101,11 +101,11 @@ CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=m
 # CONFIG_CONSOLE_TRANSLATIONS is not set
 # CONFIG_VT_CONSOLE is not set
-CONFIG_SERIAL_8250=m
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_NR_UARTS=5
 CONFIG_SERIAL_8250_RUNTIME_UARTS=5
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
diff --git a/arch/arm/configs/xcep_defconfig b/arch/arm/configs/xcep_defconfig
index 721832f..b67aeaf 100644
--- a/arch/arm/configs/xcep_defconfig
+++ b/arch/arm/configs/xcep_defconfig
@@ -60,8 +60,9 @@ CONFIG_NET_ETHERNET=y
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
 # CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=m
diff --git a/drivers/tty/serial/8250/8250_pxa.c b/drivers/tty/serial/8250/8250_pxa.c
new file mode 100644
index 0000000..0da0d40
--- /dev/null
+++ b/drivers/tty/serial/8250/8250_pxa.c
@@ -0,0 +1,178 @@
+/*
+ *  drivers/tty/serial/8250/8250_pxa.c -- driver for PXA on-board UARTS
+ *  Copyright:	(C) 2013 Sergei Ianovich <ynvich@gmail.com>
+ *
+ *  replaces drivers/serial/pxa.c by Nicolas Pitre
+ *  Created:	Feb 20, 2003
+ *  Copyright:	(C) 2003 Monta Vista Software, Inc.
+ *
+ *  Based on drivers/serial/8250.c by Russell King.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/serial_8250.h>
+#include <linux/serial_core.h>
+#include <linux/serial_reg.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
+#include <linux/pm_runtime.h>
+
+#include "8250.h"
+
+struct pxa8250_data {
+	int			line;
+	struct clk		*clk;
+};
+
+#ifdef CONFIG_PM
+static int serial_pxa_suspend(struct device *dev)
+{
+	struct pxa8250_data *data = dev_get_drvdata(dev);
+
+	serial8250_suspend_port(data->line);
+
+	return 0;
+}
+
+static int serial_pxa_resume(struct device *dev)
+{
+	struct pxa8250_data *data = dev_get_drvdata(dev);
+
+	serial8250_resume_port(data->line);
+
+	return 0;
+}
+#endif
+
+static const struct dev_pm_ops serial_pxa_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(serial_pxa_suspend, serial_pxa_resume)
+};
+
+static struct of_device_id serial_pxa_dt_ids[] = {
+	{ .compatible = "mrvl,pxa-uart", },
+	{ .compatible = "mrvl,mmp-uart", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, serial_pxa_dt_ids);
+
+/* Uart divisor latch write */
+static void serial_pxa_dl_write(struct uart_8250_port *up, int value)
+{
+	unsigned int dll;
+
+	serial_out(up, UART_DLL, value & 0xff);
+	/*
+	 * work around Erratum #74 according to Marvel(R) PXA270M Processor
+	 * Specification Update (April 19, 2010)
+	 */
+	dll = serial_in(up, UART_DLL);
+	WARN_ON(dll != (value & 0xff));
+
+	serial_out(up, UART_DLM, value >> 8 & 0xff);
+}
+
+
+static void serial_pxa_pm(struct uart_port *port, unsigned int state,
+	      unsigned int oldstate)
+{
+	struct pxa8250_data *data = port->private_data;
+
+	if (!state)
+		clk_prepare_enable(data->clk);
+	else
+		clk_disable_unprepare(data->clk);
+}
+
+static int serial_pxa_probe(struct platform_device *pdev)
+{
+	struct uart_8250_port uart = {};
+	struct pxa8250_data *data;
+	struct resource *mmres, *irqres;
+	int ret;
+
+	mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	irqres = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!mmres || !irqres)
+		return -ENODEV;
+
+	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(data->clk))
+		return PTR_ERR(data->clk);
+
+	ret = clk_prepare(data->clk);
+	if (ret)
+		return ret;
+
+	uart.port.type = PORT_XSCALE;
+	uart.port.iotype = UPIO_MEM32;
+	uart.port.mapbase = mmres->start;
+	uart.port.regshift = 2;
+	uart.port.irq = irqres->start;
+	uart.port.fifosize = 64;
+	uart.port.flags = UPF_IOREMAP | UPF_SKIP_TEST;
+	uart.port.dev = &pdev->dev;
+	uart.port.uartclk = clk_get_rate(data->clk);
+	uart.port.pm = serial_pxa_pm;
+	uart.port.private_data = data;
+	uart.dl_write = serial_pxa_dl_write;
+
+	ret = serial8250_register_8250_port(&uart);
+	if (ret < 0)
+		goto err_clk;
+
+	data->line = ret;
+
+	platform_set_drvdata(pdev, data);
+
+	return 0;
+
+ err_clk:
+	clk_unprepare(data->clk);
+	return ret;
+}
+
+static int serial_pxa_remove(struct platform_device *pdev)
+{
+	struct pxa8250_data *data = platform_get_drvdata(pdev);
+
+	serial8250_unregister_port(data->line);
+
+	clk_unprepare(data->clk);
+
+	return 0;
+}
+
+static struct platform_driver serial_pxa_driver = {
+	.probe          = serial_pxa_probe,
+	.remove         = serial_pxa_remove,
+
+	.driver		= {
+		.name	= "pxa2xx-uart",
+		.owner	= THIS_MODULE,
+		.pm	= &serial_pxa_pm_ops,
+		.of_match_table = serial_pxa_dt_ids,
+	},
+};
+
+module_platform_driver(serial_pxa_driver);
+
+MODULE_AUTHOR("Sergei Ianovich");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:pxa2xx-uart");
diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
index 2332991..81bd7c9 100644
--- a/drivers/tty/serial/8250/Kconfig
+++ b/drivers/tty/serial/8250/Kconfig
@@ -302,3 +302,12 @@ config SERIAL_8250_RT288X
 	  If you have a Ralink RT288x/RT305x SoC based board and want to use the
 	  serial port, say Y to this option. The driver can handle up to 2 serial
 	  ports. If unsure, say N.
+
+config SERIAL_PXA
+	tristate "PXA serial port support"
+	depends on SERIAL_8250 && (ARCH_PXA || ARCH_MMP)
+	help
+	  If you have a machine based on an Intel XScale PXA2xx CPU you
+	  can enable its onboard serial ports by enabling this option.
+
+	  If you choose M here, the module name will be 8250_pxa.
diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile
index 36d68d0..b7d1b61 100644
--- a/drivers/tty/serial/8250/Makefile
+++ b/drivers/tty/serial/8250/Makefile
@@ -20,3 +20,4 @@ obj-$(CONFIG_SERIAL_8250_HUB6)		+= 8250_hub6.o
 obj-$(CONFIG_SERIAL_8250_FSL)		+= 8250_fsl.o
 obj-$(CONFIG_SERIAL_8250_DW)		+= 8250_dw.o
 obj-$(CONFIG_SERIAL_8250_EM)		+= 8250_em.o
+obj-$(CONFIG_SERIAL_PXA)		+= 8250_pxa.o
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index 2e6d8dd..da46e31 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -395,29 +395,6 @@ config SERIAL_MPSC_CONSOLE
 	help
 	  Say Y here if you want to support a serial console on a Marvell MPSC.
 
-config SERIAL_PXA
-	bool "PXA serial port support"
-	depends on ARCH_PXA || ARCH_MMP
-	select SERIAL_CORE
-	help
-	  If you have a machine based on an Intel XScale PXA2xx CPU you
-	  can enable its onboard serial ports by enabling this option.
-
-config SERIAL_PXA_CONSOLE
-	bool "Console on PXA serial port"
-	depends on SERIAL_PXA
-	select SERIAL_CORE_CONSOLE
-	help
-	  If you have enabled the serial port on the Intel XScale PXA
-	  CPU you can make it the console by answering Y to this option.
-
-	  Even if you say Y here, the currently visible virtual console
-	  (/dev/tty0) will still be used as the system console by default, but
-	  you can alter that using a kernel command line option such as
-	  "console=ttySA0". (Try "man bootparam" or see the documentation of
-	  your boot loader (lilo or loadlin) about how to pass options to the
-	  kernel at boot time.)
-
 config SERIAL_SA1100
 	bool "SA1100 serial port support"
 	depends on ARCH_SA1100
diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile
index 3680854..fd71d3f 100644
--- a/drivers/tty/serial/Makefile
+++ b/drivers/tty/serial/Makefile
@@ -20,7 +20,6 @@ obj-$(CONFIG_SERIAL_8250) += 8250/
 obj-$(CONFIG_SERIAL_AMBA_PL010) += amba-pl010.o
 obj-$(CONFIG_SERIAL_AMBA_PL011) += amba-pl011.o
 obj-$(CONFIG_SERIAL_CLPS711X) += clps711x.o
-obj-$(CONFIG_SERIAL_PXA) += pxa.o
 obj-$(CONFIG_SERIAL_PNX8XXX) += pnx8xxx_uart.o
 obj-$(CONFIG_SERIAL_SA1100) += sa1100.o
 obj-$(CONFIG_SERIAL_BCM63XX) += bcm63xx_uart.o
diff --git a/drivers/tty/serial/pxa.c b/drivers/tty/serial/pxa.c
deleted file mode 100644
index f9f20f3..0000000
--- a/drivers/tty/serial/pxa.c
+++ /dev/null
@@ -1,971 +0,0 @@
-/*
- *  Based on drivers/serial/8250.c by Russell King.
- *
- *  Author:	Nicolas Pitre
- *  Created:	Feb 20, 2003
- *  Copyright:	(C) 2003 Monta Vista Software, Inc.
- *
- * 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.
- *
- * Note 1: This driver is made separate from the already too overloaded
- * 8250.c because it needs some kirks of its own and that'll make it
- * easier to add DMA support.
- *
- * Note 2: I'm too sick of device allocation policies for serial ports.
- * If someone else wants to request an "official" allocation of major/minor
- * for this driver please be my guest.  And don't forget that new hardware
- * to come from Intel might have more than 3 or 4 of those UARTs.  Let's
- * hope for a better port registration and dynamic device allocation scheme
- * with the serial core maintainer satisfaction to appear soon.
- */
-
-
-#if defined(CONFIG_SERIAL_PXA_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-#define SUPPORT_SYSRQ
-#endif
-
-#include <linux/module.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-#include <linux/console.h>
-#include <linux/sysrq.h>
-#include <linux/serial_reg.h>
-#include <linux/circ_buf.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/of.h>
-#include <linux/platform_device.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/serial_core.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-
-#define PXA_NAME_LEN		8
-
-struct uart_pxa_port {
-	struct uart_port        port;
-	unsigned char           ier;
-	unsigned char           lcr;
-	unsigned char           mcr;
-	unsigned int            lsr_break_flag;
-	struct clk		*clk;
-	char			name[PXA_NAME_LEN];
-};
-
-static inline unsigned int serial_in(struct uart_pxa_port *up, int offset)
-{
-	offset <<= 2;
-	return readl(up->port.membase + offset);
-}
-
-static inline void serial_out(struct uart_pxa_port *up, int offset, int value)
-{
-	offset <<= 2;
-	writel(value, up->port.membase + offset);
-}
-
-static void serial_pxa_enable_ms(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	up->ier |= UART_IER_MSI;
-	serial_out(up, UART_IER, up->ier);
-}
-
-static void serial_pxa_stop_tx(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	if (up->ier & UART_IER_THRI) {
-		up->ier &= ~UART_IER_THRI;
-		serial_out(up, UART_IER, up->ier);
-	}
-}
-
-static void serial_pxa_stop_rx(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	up->ier &= ~UART_IER_RLSI;
-	up->port.read_status_mask &= ~UART_LSR_DR;
-	serial_out(up, UART_IER, up->ier);
-}
-
-static inline void receive_chars(struct uart_pxa_port *up, int *status)
-{
-	unsigned int ch, flag;
-	int max_count = 256;
-
-	do {
-		/* work around Errata #20 according to
-		 * Intel(R) PXA27x Processor Family
-		 * Specification Update (May 2005)
-		 *
-		 * Step 2
-		 * Disable the Reciever Time Out Interrupt via IER[RTOEI]
-		 */
-		up->ier &= ~UART_IER_RTOIE;
-		serial_out(up, UART_IER, up->ier);
-
-		ch = serial_in(up, UART_RX);
-		flag = TTY_NORMAL;
-		up->port.icount.rx++;
-
-		if (unlikely(*status & (UART_LSR_BI | UART_LSR_PE |
-				       UART_LSR_FE | UART_LSR_OE))) {
-			/*
-			 * For statistics only
-			 */
-			if (*status & UART_LSR_BI) {
-				*status &= ~(UART_LSR_FE | UART_LSR_PE);
-				up->port.icount.brk++;
-				/*
-				 * We do the SysRQ and SAK checking
-				 * here because otherwise the break
-				 * may get masked by ignore_status_mask
-				 * or read_status_mask.
-				 */
-				if (uart_handle_break(&up->port))
-					goto ignore_char;
-			} else if (*status & UART_LSR_PE)
-				up->port.icount.parity++;
-			else if (*status & UART_LSR_FE)
-				up->port.icount.frame++;
-			if (*status & UART_LSR_OE)
-				up->port.icount.overrun++;
-
-			/*
-			 * Mask off conditions which should be ignored.
-			 */
-			*status &= up->port.read_status_mask;
-
-#ifdef CONFIG_SERIAL_PXA_CONSOLE
-			if (up->port.line == up->port.cons->index) {
-				/* Recover the break flag from console xmit */
-				*status |= up->lsr_break_flag;
-				up->lsr_break_flag = 0;
-			}
-#endif
-			if (*status & UART_LSR_BI) {
-				flag = TTY_BREAK;
-			} else if (*status & UART_LSR_PE)
-				flag = TTY_PARITY;
-			else if (*status & UART_LSR_FE)
-				flag = TTY_FRAME;
-		}
-
-		if (uart_handle_sysrq_char(&up->port, ch))
-			goto ignore_char;
-
-		uart_insert_char(&up->port, *status, UART_LSR_OE, ch, flag);
-
-	ignore_char:
-		*status = serial_in(up, UART_LSR);
-	} while ((*status & UART_LSR_DR) && (max_count-- > 0));
-	tty_flip_buffer_push(&up->port.state->port);
-
-	/* work around Errata #20 according to
-	 * Intel(R) PXA27x Processor Family
-	 * Specification Update (May 2005)
-	 *
-	 * Step 6:
-	 * No more data in FIFO: Re-enable RTO interrupt via IER[RTOIE]
-	 */
-	up->ier |= UART_IER_RTOIE;
-	serial_out(up, UART_IER, up->ier);
-}
-
-static void transmit_chars(struct uart_pxa_port *up)
-{
-	struct circ_buf *xmit = &up->port.state->xmit;
-	int count;
-
-	if (up->port.x_char) {
-		serial_out(up, UART_TX, up->port.x_char);
-		up->port.icount.tx++;
-		up->port.x_char = 0;
-		return;
-	}
-	if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) {
-		serial_pxa_stop_tx(&up->port);
-		return;
-	}
-
-	count = up->port.fifosize / 2;
-	do {
-		serial_out(up, UART_TX, xmit->buf[xmit->tail]);
-		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
-		up->port.icount.tx++;
-		if (uart_circ_empty(xmit))
-			break;
-	} while (--count > 0);
-
-	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
-		uart_write_wakeup(&up->port);
-
-
-	if (uart_circ_empty(xmit))
-		serial_pxa_stop_tx(&up->port);
-}
-
-static void serial_pxa_start_tx(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	if (!(up->ier & UART_IER_THRI)) {
-		up->ier |= UART_IER_THRI;
-		serial_out(up, UART_IER, up->ier);
-	}
-}
-
-static inline void check_modem_status(struct uart_pxa_port *up)
-{
-	int status;
-
-	status = serial_in(up, UART_MSR);
-
-	if ((status & UART_MSR_ANY_DELTA) == 0)
-		return;
-
-	if (status & UART_MSR_TERI)
-		up->port.icount.rng++;
-	if (status & UART_MSR_DDSR)
-		up->port.icount.dsr++;
-	if (status & UART_MSR_DDCD)
-		uart_handle_dcd_change(&up->port, status & UART_MSR_DCD);
-	if (status & UART_MSR_DCTS)
-		uart_handle_cts_change(&up->port, status & UART_MSR_CTS);
-
-	wake_up_interruptible(&up->port.state->port.delta_msr_wait);
-}
-
-/*
- * This handles the interrupt from one port.
- */
-static inline irqreturn_t serial_pxa_irq(int irq, void *dev_id)
-{
-	struct uart_pxa_port *up = dev_id;
-	unsigned int iir, lsr;
-
-	iir = serial_in(up, UART_IIR);
-	if (iir & UART_IIR_NO_INT)
-		return IRQ_NONE;
-	lsr = serial_in(up, UART_LSR);
-	if (lsr & UART_LSR_DR)
-		receive_chars(up, &lsr);
-	check_modem_status(up);
-	if (lsr & UART_LSR_THRE)
-		transmit_chars(up);
-	return IRQ_HANDLED;
-}
-
-static unsigned int serial_pxa_tx_empty(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned long flags;
-	unsigned int ret;
-
-	spin_lock_irqsave(&up->port.lock, flags);
-	ret = serial_in(up, UART_LSR) & UART_LSR_TEMT ? TIOCSER_TEMT : 0;
-	spin_unlock_irqrestore(&up->port.lock, flags);
-
-	return ret;
-}
-
-static unsigned int serial_pxa_get_mctrl(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned char status;
-	unsigned int ret;
-
-	status = serial_in(up, UART_MSR);
-
-	ret = 0;
-	if (status & UART_MSR_DCD)
-		ret |= TIOCM_CAR;
-	if (status & UART_MSR_RI)
-		ret |= TIOCM_RNG;
-	if (status & UART_MSR_DSR)
-		ret |= TIOCM_DSR;
-	if (status & UART_MSR_CTS)
-		ret |= TIOCM_CTS;
-	return ret;
-}
-
-static void serial_pxa_set_mctrl(struct uart_port *port, unsigned int mctrl)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned char mcr = 0;
-
-	if (mctrl & TIOCM_RTS)
-		mcr |= UART_MCR_RTS;
-	if (mctrl & TIOCM_DTR)
-		mcr |= UART_MCR_DTR;
-	if (mctrl & TIOCM_OUT1)
-		mcr |= UART_MCR_OUT1;
-	if (mctrl & TIOCM_OUT2)
-		mcr |= UART_MCR_OUT2;
-	if (mctrl & TIOCM_LOOP)
-		mcr |= UART_MCR_LOOP;
-
-	mcr |= up->mcr;
-
-	serial_out(up, UART_MCR, mcr);
-}
-
-static void serial_pxa_break_ctl(struct uart_port *port, int break_state)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned long flags;
-
-	spin_lock_irqsave(&up->port.lock, flags);
-	if (break_state == -1)
-		up->lcr |= UART_LCR_SBC;
-	else
-		up->lcr &= ~UART_LCR_SBC;
-	serial_out(up, UART_LCR, up->lcr);
-	spin_unlock_irqrestore(&up->port.lock, flags);
-}
-
-static int serial_pxa_startup(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned long flags;
-	int retval;
-
-	if (port->line == 3) /* HWUART */
-		up->mcr |= UART_MCR_AFE;
-	else
-		up->mcr = 0;
-
-	up->port.uartclk = clk_get_rate(up->clk);
-
-	/*
-	 * Allocate the IRQ
-	 */
-	retval = request_irq(up->port.irq, serial_pxa_irq, 0, up->name, up);
-	if (retval)
-		return retval;
-
-	/*
-	 * Clear the FIFO buffers and disable them.
-	 * (they will be reenabled in set_termios())
-	 */
-	serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO);
-	serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO |
-			UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
-	serial_out(up, UART_FCR, 0);
-
-	/*
-	 * Clear the interrupt registers.
-	 */
-	(void) serial_in(up, UART_LSR);
-	(void) serial_in(up, UART_RX);
-	(void) serial_in(up, UART_IIR);
-	(void) serial_in(up, UART_MSR);
-
-	/*
-	 * Now, initialize the UART
-	 */
-	serial_out(up, UART_LCR, UART_LCR_WLEN8);
-
-	spin_lock_irqsave(&up->port.lock, flags);
-	up->port.mctrl |= TIOCM_OUT2;
-	serial_pxa_set_mctrl(&up->port, up->port.mctrl);
-	spin_unlock_irqrestore(&up->port.lock, flags);
-
-	/*
-	 * Finally, enable interrupts.  Note: Modem status interrupts
-	 * are set via set_termios(), which will be occurring imminently
-	 * anyway, so we don't enable them here.
-	 */
-	up->ier = UART_IER_RLSI | UART_IER_RDI | UART_IER_RTOIE | UART_IER_UUE;
-	serial_out(up, UART_IER, up->ier);
-
-	/*
-	 * And clear the interrupt registers again for luck.
-	 */
-	(void) serial_in(up, UART_LSR);
-	(void) serial_in(up, UART_RX);
-	(void) serial_in(up, UART_IIR);
-	(void) serial_in(up, UART_MSR);
-
-	return 0;
-}
-
-static void serial_pxa_shutdown(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned long flags;
-
-	free_irq(up->port.irq, up);
-
-	/*
-	 * Disable interrupts from this port
-	 */
-	up->ier = 0;
-	serial_out(up, UART_IER, 0);
-
-	spin_lock_irqsave(&up->port.lock, flags);
-	up->port.mctrl &= ~TIOCM_OUT2;
-	serial_pxa_set_mctrl(&up->port, up->port.mctrl);
-	spin_unlock_irqrestore(&up->port.lock, flags);
-
-	/*
-	 * Disable break condition and FIFOs
-	 */
-	serial_out(up, UART_LCR, serial_in(up, UART_LCR) & ~UART_LCR_SBC);
-	serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO |
-				  UART_FCR_CLEAR_RCVR |
-				  UART_FCR_CLEAR_XMIT);
-	serial_out(up, UART_FCR, 0);
-}
-
-static void
-serial_pxa_set_termios(struct uart_port *port, struct ktermios *termios,
-		       struct ktermios *old)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned char cval, fcr = 0;
-	unsigned long flags;
-	unsigned int baud, quot;
-	unsigned int dll;
-
-	switch (termios->c_cflag & CSIZE) {
-	case CS5:
-		cval = UART_LCR_WLEN5;
-		break;
-	case CS6:
-		cval = UART_LCR_WLEN6;
-		break;
-	case CS7:
-		cval = UART_LCR_WLEN7;
-		break;
-	default:
-	case CS8:
-		cval = UART_LCR_WLEN8;
-		break;
-	}
-
-	if (termios->c_cflag & CSTOPB)
-		cval |= UART_LCR_STOP;
-	if (termios->c_cflag & PARENB)
-		cval |= UART_LCR_PARITY;
-	if (!(termios->c_cflag & PARODD))
-		cval |= UART_LCR_EPAR;
-
-	/*
-	 * Ask the core to calculate the divisor for us.
-	 */
-	baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
-	quot = uart_get_divisor(port, baud);
-
-	if ((up->port.uartclk / quot) < (2400 * 16))
-		fcr = UART_FCR_ENABLE_FIFO | UART_FCR_PXAR1;
-	else if ((up->port.uartclk / quot) < (230400 * 16))
-		fcr = UART_FCR_ENABLE_FIFO | UART_FCR_PXAR8;
-	else
-		fcr = UART_FCR_ENABLE_FIFO | UART_FCR_PXAR32;
-
-	/*
-	 * Ok, we're now changing the port state.  Do it with
-	 * interrupts disabled.
-	 */
-	spin_lock_irqsave(&up->port.lock, flags);
-
-	/*
-	 * Ensure the port will be enabled.
-	 * This is required especially for serial console.
-	 */
-	up->ier |= UART_IER_UUE;
-
-	/*
-	 * Update the per-port timeout.
-	 */
-	uart_update_timeout(port, termios->c_cflag, baud);
-
-	up->port.read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;
-	if (termios->c_iflag & INPCK)
-		up->port.read_status_mask |= UART_LSR_FE | UART_LSR_PE;
-	if (termios->c_iflag & (BRKINT | PARMRK))
-		up->port.read_status_mask |= UART_LSR_BI;
-
-	/*
-	 * Characters to ignore
-	 */
-	up->port.ignore_status_mask = 0;
-	if (termios->c_iflag & IGNPAR)
-		up->port.ignore_status_mask |= UART_LSR_PE | UART_LSR_FE;
-	if (termios->c_iflag & IGNBRK) {
-		up->port.ignore_status_mask |= UART_LSR_BI;
-		/*
-		 * If we're ignoring parity and break indicators,
-		 * ignore overruns too (for real raw support).
-		 */
-		if (termios->c_iflag & IGNPAR)
-			up->port.ignore_status_mask |= UART_LSR_OE;
-	}
-
-	/*
-	 * ignore all characters if CREAD is not set
-	 */
-	if ((termios->c_cflag & CREAD) == 0)
-		up->port.ignore_status_mask |= UART_LSR_DR;
-
-	/*
-	 * CTS flow control flag and modem status interrupts
-	 */
-	up->ier &= ~UART_IER_MSI;
-	if (UART_ENABLE_MS(&up->port, termios->c_cflag))
-		up->ier |= UART_IER_MSI;
-
-	serial_out(up, UART_IER, up->ier);
-
-	if (termios->c_cflag & CRTSCTS)
-		up->mcr |= UART_MCR_AFE;
-	else
-		up->mcr &= ~UART_MCR_AFE;
-
-	serial_out(up, UART_LCR, cval | UART_LCR_DLAB);	/* set DLAB */
-	serial_out(up, UART_DLL, quot & 0xff);		/* LS of divisor */
-
-	/*
-	 * work around Errata #75 according to Intel(R) PXA27x Processor Family
-	 * Specification Update (Nov 2005)
-	 */
-	dll = serial_in(up, UART_DLL);
-	WARN_ON(dll != (quot & 0xff));
-
-	serial_out(up, UART_DLM, quot >> 8);		/* MS of divisor */
-	serial_out(up, UART_LCR, cval);			/* reset DLAB */
-	up->lcr = cval;					/* Save LCR */
-	serial_pxa_set_mctrl(&up->port, up->port.mctrl);
-	serial_out(up, UART_FCR, fcr);
-	spin_unlock_irqrestore(&up->port.lock, flags);
-}
-
-static void
-serial_pxa_pm(struct uart_port *port, unsigned int state,
-	      unsigned int oldstate)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	if (!state)
-		clk_prepare_enable(up->clk);
-	else
-		clk_disable_unprepare(up->clk);
-}
-
-static void serial_pxa_release_port(struct uart_port *port)
-{
-}
-
-static int serial_pxa_request_port(struct uart_port *port)
-{
-	return 0;
-}
-
-static void serial_pxa_config_port(struct uart_port *port, int flags)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	up->port.type = PORT_PXA;
-}
-
-static int
-serial_pxa_verify_port(struct uart_port *port, struct serial_struct *ser)
-{
-	/* we don't want the core code to modify any port params */
-	return -EINVAL;
-}
-
-static const char *
-serial_pxa_type(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	return up->name;
-}
-
-static struct uart_pxa_port *serial_pxa_ports[4];
-static struct uart_driver serial_pxa_reg;
-
-#ifdef CONFIG_SERIAL_PXA_CONSOLE
-
-#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
-
-/*
- *	Wait for transmitter & holding register to empty
- */
-static inline void wait_for_xmitr(struct uart_pxa_port *up)
-{
-	unsigned int status, tmout = 10000;
-
-	/* Wait up to 10ms for the character(s) to be sent. */
-	do {
-		status = serial_in(up, UART_LSR);
-
-		if (status & UART_LSR_BI)
-			up->lsr_break_flag = UART_LSR_BI;
-
-		if (--tmout == 0)
-			break;
-		udelay(1);
-	} while ((status & BOTH_EMPTY) != BOTH_EMPTY);
-
-	/* Wait up to 1s for flow control if necessary */
-	if (up->port.flags & UPF_CONS_FLOW) {
-		tmout = 1000000;
-		while (--tmout &&
-		       ((serial_in(up, UART_MSR) & UART_MSR_CTS) == 0))
-			udelay(1);
-	}
-}
-
-static void serial_pxa_console_putchar(struct uart_port *port, int ch)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	wait_for_xmitr(up);
-	serial_out(up, UART_TX, ch);
-}
-
-/*
- * Print a string to the serial port trying not to disturb
- * any possible real use of the port...
- *
- *	The console_lock must be held when we get here.
- */
-static void
-serial_pxa_console_write(struct console *co, const char *s, unsigned int count)
-{
-	struct uart_pxa_port *up = serial_pxa_ports[co->index];
-	unsigned int ier;
-	unsigned long flags;
-	int locked = 1;
-
-	clk_enable(up->clk);
-	local_irq_save(flags);
-	if (up->port.sysrq)
-		locked = 0;
-	else if (oops_in_progress)
-		locked = spin_trylock(&up->port.lock);
-	else
-		spin_lock(&up->port.lock);
-
-	/*
-	 *	First save the IER then disable the interrupts
-	 */
-	ier = serial_in(up, UART_IER);
-	serial_out(up, UART_IER, UART_IER_UUE);
-
-	uart_console_write(&up->port, s, count, serial_pxa_console_putchar);
-
-	/*
-	 *	Finally, wait for transmitter to become empty
-	 *	and restore the IER
-	 */
-	wait_for_xmitr(up);
-	serial_out(up, UART_IER, ier);
-
-	if (locked)
-		spin_unlock(&up->port.lock);
-	local_irq_restore(flags);
-	clk_disable(up->clk);
-
-}
-
-#ifdef CONFIG_CONSOLE_POLL
-/*
- * Console polling routines for writing and reading from the uart while
- * in an interrupt or debug context.
- */
-
-static int serial_pxa_get_poll_char(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned char lsr = serial_in(up, UART_LSR);
-
-	while (!(lsr & UART_LSR_DR))
-		lsr = serial_in(up, UART_LSR);
-
-	return serial_in(up, UART_RX);
-}
-
-
-static void serial_pxa_put_poll_char(struct uart_port *port,
-			 unsigned char c)
-{
-	unsigned int ier;
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	/*
-	 *	First save the IER then disable the interrupts
-	 */
-	ier = serial_in(up, UART_IER);
-	serial_out(up, UART_IER, UART_IER_UUE);
-
-	wait_for_xmitr(up);
-	/*
-	 *	Send the character out.
-	 *	If a LF, also do CR...
-	 */
-	serial_out(up, UART_TX, c);
-	if (c == 10) {
-		wait_for_xmitr(up);
-		serial_out(up, UART_TX, 13);
-	}
-
-	/*
-	 *	Finally, wait for transmitter to become empty
-	 *	and restore the IER
-	 */
-	wait_for_xmitr(up);
-	serial_out(up, UART_IER, ier);
-}
-
-#endif /* CONFIG_CONSOLE_POLL */
-
-static int __init
-serial_pxa_console_setup(struct console *co, char *options)
-{
-	struct uart_pxa_port *up;
-	int baud = 9600;
-	int bits = 8;
-	int parity = 'n';
-	int flow = 'n';
-
-	if (co->index == -1 || co->index >= serial_pxa_reg.nr)
-		co->index = 0;
-	up = serial_pxa_ports[co->index];
-	if (!up)
-		return -ENODEV;
-
-	if (options)
-		uart_parse_options(options, &baud, &parity, &bits, &flow);
-
-	return uart_set_options(&up->port, co, baud, parity, bits, flow);
-}
-
-static struct console serial_pxa_console = {
-	.name		= "ttyS",
-	.write		= serial_pxa_console_write,
-	.device		= uart_console_device,
-	.setup		= serial_pxa_console_setup,
-	.flags		= CON_PRINTBUFFER,
-	.index		= -1,
-	.data		= &serial_pxa_reg,
-};
-
-#define PXA_CONSOLE	&serial_pxa_console
-#else
-#define PXA_CONSOLE	NULL
-#endif
-
-static struct uart_ops serial_pxa_pops = {
-	.tx_empty	= serial_pxa_tx_empty,
-	.set_mctrl	= serial_pxa_set_mctrl,
-	.get_mctrl	= serial_pxa_get_mctrl,
-	.stop_tx	= serial_pxa_stop_tx,
-	.start_tx	= serial_pxa_start_tx,
-	.stop_rx	= serial_pxa_stop_rx,
-	.enable_ms	= serial_pxa_enable_ms,
-	.break_ctl	= serial_pxa_break_ctl,
-	.startup	= serial_pxa_startup,
-	.shutdown	= serial_pxa_shutdown,
-	.set_termios	= serial_pxa_set_termios,
-	.pm		= serial_pxa_pm,
-	.type		= serial_pxa_type,
-	.release_port	= serial_pxa_release_port,
-	.request_port	= serial_pxa_request_port,
-	.config_port	= serial_pxa_config_port,
-	.verify_port	= serial_pxa_verify_port,
-#ifdef CONFIG_CONSOLE_POLL
-	.poll_get_char = serial_pxa_get_poll_char,
-	.poll_put_char = serial_pxa_put_poll_char,
-#endif
-};
-
-static struct uart_driver serial_pxa_reg = {
-	.owner		= THIS_MODULE,
-	.driver_name	= "PXA serial",
-	.dev_name	= "ttyS",
-	.major		= TTY_MAJOR,
-	.minor		= 64,
-	.nr		= 4,
-	.cons		= PXA_CONSOLE,
-};
-
-#ifdef CONFIG_PM
-static int serial_pxa_suspend(struct device *dev)
-{
-        struct uart_pxa_port *sport = dev_get_drvdata(dev);
-
-        if (sport)
-                uart_suspend_port(&serial_pxa_reg, &sport->port);
-
-        return 0;
-}
-
-static int serial_pxa_resume(struct device *dev)
-{
-        struct uart_pxa_port *sport = dev_get_drvdata(dev);
-
-        if (sport)
-                uart_resume_port(&serial_pxa_reg, &sport->port);
-
-        return 0;
-}
-
-static const struct dev_pm_ops serial_pxa_pm_ops = {
-	.suspend	= serial_pxa_suspend,
-	.resume		= serial_pxa_resume,
-};
-#endif
-
-static struct of_device_id serial_pxa_dt_ids[] = {
-	{ .compatible = "mrvl,pxa-uart", },
-	{ .compatible = "mrvl,mmp-uart", },
-	{}
-};
-MODULE_DEVICE_TABLE(of, serial_pxa_dt_ids);
-
-static int serial_pxa_probe_dt(struct platform_device *pdev,
-			       struct uart_pxa_port *sport)
-{
-	struct device_node *np = pdev->dev.of_node;
-	int ret;
-
-	if (!np)
-		return 1;
-
-	ret = of_alias_get_id(np, "serial");
-	if (ret < 0) {
-		dev_err(&pdev->dev, "failed to get alias id, errno %d\n", ret);
-		return ret;
-	}
-	sport->port.line = ret;
-	return 0;
-}
-
-static int serial_pxa_probe(struct platform_device *dev)
-{
-	struct uart_pxa_port *sport;
-	struct resource *mmres, *irqres;
-	int ret;
-
-	mmres = platform_get_resource(dev, IORESOURCE_MEM, 0);
-	irqres = platform_get_resource(dev, IORESOURCE_IRQ, 0);
-	if (!mmres || !irqres)
-		return -ENODEV;
-
-	sport = kzalloc(sizeof(struct uart_pxa_port), GFP_KERNEL);
-	if (!sport)
-		return -ENOMEM;
-
-	sport->clk = clk_get(&dev->dev, NULL);
-	if (IS_ERR(sport->clk)) {
-		ret = PTR_ERR(sport->clk);
-		goto err_free;
-	}
-
-	ret = clk_prepare(sport->clk);
-	if (ret) {
-		clk_put(sport->clk);
-		goto err_free;
-	}
-
-	sport->port.type = PORT_PXA;
-	sport->port.iotype = UPIO_MEM;
-	sport->port.mapbase = mmres->start;
-	sport->port.irq = irqres->start;
-	sport->port.fifosize = 64;
-	sport->port.ops = &serial_pxa_pops;
-	sport->port.dev = &dev->dev;
-	sport->port.flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF;
-	sport->port.uartclk = clk_get_rate(sport->clk);
-
-	ret = serial_pxa_probe_dt(dev, sport);
-	if (ret > 0)
-		sport->port.line = dev->id;
-	else if (ret < 0)
-		goto err_clk;
-	snprintf(sport->name, PXA_NAME_LEN - 1, "UART%d", sport->port.line + 1);
-
-	sport->port.membase = ioremap(mmres->start, resource_size(mmres));
-	if (!sport->port.membase) {
-		ret = -ENOMEM;
-		goto err_clk;
-	}
-
-	serial_pxa_ports[sport->port.line] = sport;
-
-	uart_add_one_port(&serial_pxa_reg, &sport->port);
-	platform_set_drvdata(dev, sport);
-
-	return 0;
-
- err_clk:
-	clk_unprepare(sport->clk);
-	clk_put(sport->clk);
- err_free:
-	kfree(sport);
-	return ret;
-}
-
-static int serial_pxa_remove(struct platform_device *dev)
-{
-	struct uart_pxa_port *sport = platform_get_drvdata(dev);
-
-	uart_remove_one_port(&serial_pxa_reg, &sport->port);
-
-	clk_unprepare(sport->clk);
-	clk_put(sport->clk);
-	kfree(sport);
-
-	return 0;
-}
-
-static struct platform_driver serial_pxa_driver = {
-        .probe          = serial_pxa_probe,
-        .remove         = serial_pxa_remove,
-
-	.driver		= {
-	        .name	= "pxa2xx-uart",
-		.owner	= THIS_MODULE,
-#ifdef CONFIG_PM
-		.pm	= &serial_pxa_pm_ops,
-#endif
-		.of_match_table = serial_pxa_dt_ids,
-	},
-};
-
-static int __init serial_pxa_init(void)
-{
-	int ret;
-
-	ret = uart_register_driver(&serial_pxa_reg);
-	if (ret != 0)
-		return ret;
-
-	ret = platform_driver_register(&serial_pxa_driver);
-	if (ret != 0)
-		uart_unregister_driver(&serial_pxa_reg);
-
-	return ret;
-}
-
-static void __exit serial_pxa_exit(void)
-{
-	platform_driver_unregister(&serial_pxa_driver);
-	uart_unregister_driver(&serial_pxa_reg);
-}
-
-module_init(serial_pxa_init);
-module_exit(serial_pxa_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:pxa2xx-uart");
-- 
1.8.4.2


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

* [PATCH v4 01/21] serial: rewrite pxa2xx-uart to use 8250_core
@ 2014-04-16 17:13               ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2014-04-16 17:13 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Russell King, Greg Kroah-Hartman, Jiri Slaby,
	Grant Likely, Rob Herring, James Cameron, Heikki Krogerus,
	Paul Bolle, Arnd Bergmann, Randy Dunlap, Stefan Seyfried,
	open list:SERIAL DRIVERS, open list:OPEN FIRMWARE AND...

pxa2xx-uart was a separate uart platform driver. It was declaring
the same device names and numbers as 8250 driver. As a result,
it was impossible to use 8250 driver on PXA SoCs.

Upon closer examination pxa2xx-uart turned out to be a clone of
8250_core driver.

Workaround for Erratum #19 according to Marvel(R) PXA270M Processor
Specification Update (April 19, 2010) is dropped. 8250_core reads
from FIFO immediately after checking DR bit in LSR.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Reviewed-by: James Cameron <quozl@laptop.org>
Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 Resenging together with the rest of the series as the series
 breaks without this one at [PATCH 12/21]

 no changes v3..v4

 changes v2..v3
 * remove devm_free/put as suggested by Heikki Krogerus
 * use SET_SYSTEM_SLEEP_PM_OPS macro to set pm ops as suggested
   by Heikki Krogerus

 changes v1..v2
 * actually implement workaround for E74 in dl_write as spooted
   by James Cameron
 * added comment about E19 in commit message

 arch/arm/configs/am200epdkit_defconfig    |   3 +-
 arch/arm/configs/cm_x2xx_defconfig        |   3 +-
 arch/arm/configs/cm_x300_defconfig        |   3 +-
 arch/arm/configs/colibri_pxa270_defconfig |   3 +-
 arch/arm/configs/colibri_pxa300_defconfig |   3 +-
 arch/arm/configs/corgi_defconfig          |   4 +-
 arch/arm/configs/em_x270_defconfig        |   3 +-
 arch/arm/configs/ezx_defconfig            |   3 +-
 arch/arm/configs/h5000_defconfig          |   3 +-
 arch/arm/configs/imote2_defconfig         |   3 +-
 arch/arm/configs/lpd270_defconfig         |   3 +-
 arch/arm/configs/lubbock_defconfig        |   3 +-
 arch/arm/configs/mainstone_defconfig      |   3 +-
 arch/arm/configs/mmp2_defconfig           |   3 +-
 arch/arm/configs/pcm027_defconfig         |   3 +-
 arch/arm/configs/pxa168_defconfig         |   3 +-
 arch/arm/configs/pxa255-idp_defconfig     |   3 +-
 arch/arm/configs/pxa3xx_defconfig         |   3 +-
 arch/arm/configs/pxa910_defconfig         |   3 +-
 arch/arm/configs/raumfeld_defconfig       |   3 +-
 arch/arm/configs/spitz_defconfig          |   4 +-
 arch/arm/configs/trizeps4_defconfig       |   3 +-
 arch/arm/configs/viper_defconfig          |   4 +-
 arch/arm/configs/xcep_defconfig           |   3 +-
 drivers/tty/serial/8250/8250_pxa.c        | 178 ++++++
 drivers/tty/serial/8250/Kconfig           |   9 +
 drivers/tty/serial/8250/Makefile          |   1 +
 drivers/tty/serial/Kconfig                |  23 -
 drivers/tty/serial/Makefile               |   1 -
 drivers/tty/serial/pxa.c                  | 971 ------------------------------
 30 files changed, 236 insertions(+), 1022 deletions(-)
 create mode 100644 drivers/tty/serial/8250/8250_pxa.c
 delete mode 100644 drivers/tty/serial/pxa.c

diff --git a/arch/arm/configs/am200epdkit_defconfig b/arch/arm/configs/am200epdkit_defconfig
index f0dea52..0cde234 100644
--- a/arch/arm/configs/am200epdkit_defconfig
+++ b/arch/arm/configs/am200epdkit_defconfig
@@ -60,8 +60,9 @@ CONFIG_BLK_DEV_IDECS=m
 CONFIG_NETDEVICES=y
 CONFIG_NET_ETHERNET=y
 CONFIG_SMC91X=m
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 # CONFIG_HWMON is not set
diff --git a/arch/arm/configs/cm_x2xx_defconfig b/arch/arm/configs/cm_x2xx_defconfig
index a93ff8d..b9fbe65 100644
--- a/arch/arm/configs/cm_x2xx_defconfig
+++ b/arch/arm/configs/cm_x2xx_defconfig
@@ -96,8 +96,9 @@ CONFIG_KEYBOARD_PXA27x=m
 CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_TOUCHSCREEN_UCB1400=m
 # CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_LEGACY_PTY_COUNT=16
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/cm_x300_defconfig b/arch/arm/configs/cm_x300_defconfig
index f4b7672..53a82ae 100644
--- a/arch/arm/configs/cm_x300_defconfig
+++ b/arch/arm/configs/cm_x300_defconfig
@@ -80,8 +80,9 @@ CONFIG_TOUCHSCREEN_WM97XX=m
 # CONFIG_TOUCHSCREEN_WM9713 is not set
 # CONFIG_SERIO is not set
 # CONFIG_LEGACY_PTYS is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
 CONFIG_I2C_PXA=y
diff --git a/arch/arm/configs/colibri_pxa270_defconfig b/arch/arm/configs/colibri_pxa270_defconfig
index 2ef2c5e..1ce0409 100644
--- a/arch/arm/configs/colibri_pxa270_defconfig
+++ b/arch/arm/configs/colibri_pxa270_defconfig
@@ -103,8 +103,9 @@ CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=m
 CONFIG_SERIO_LIBPS2=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_HW_RANDOM=y
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
diff --git a/arch/arm/configs/colibri_pxa300_defconfig b/arch/arm/configs/colibri_pxa300_defconfig
index b985334..f96bda0 100644
--- a/arch/arm/configs/colibri_pxa300_defconfig
+++ b/arch/arm/configs/colibri_pxa300_defconfig
@@ -31,8 +31,9 @@ CONFIG_INPUT_EVDEV=y
 # CONFIG_INPUT_MOUSE is not set
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_GPIO_ROTARY_ENCODER=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_HW_RANDOM=y
 CONFIG_DEBUG_GPIO=y
 # CONFIG_HWMON is not set
diff --git a/arch/arm/configs/corgi_defconfig b/arch/arm/configs/corgi_defconfig
index 1fd1d1d..bb4842d 100644
--- a/arch/arm/configs/corgi_defconfig
+++ b/arch/arm/configs/corgi_defconfig
@@ -131,10 +131,10 @@ CONFIG_TOUCHSCREEN_ADS7846=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=m
 # CONFIG_SERIO is not set
-CONFIG_SERIAL_8250=m
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_CS=m
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 CONFIG_I2C=y
 CONFIG_I2C_PXA=y
diff --git a/arch/arm/configs/em_x270_defconfig b/arch/arm/configs/em_x270_defconfig
index 60a21e0..ec0ec54 100644
--- a/arch/arm/configs/em_x270_defconfig
+++ b/arch/arm/configs/em_x270_defconfig
@@ -90,8 +90,9 @@ CONFIG_TOUCHSCREEN_WM97XX=m
 # CONFIG_TOUCHSCREEN_WM9705 is not set
 # CONFIG_TOUCHSCREEN_WM9713 is not set
 # CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_LEGACY_PTY_COUNT=16
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/ezx_defconfig b/arch/arm/configs/ezx_defconfig
index d95763d..631e2ec 100644
--- a/arch/arm/configs/ezx_defconfig
+++ b/arch/arm/configs/ezx_defconfig
@@ -215,8 +215,9 @@ CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=y
 CONFIG_INPUT_PCAP=y
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_LEGACY_PTY_COUNT=8
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/h5000_defconfig b/arch/arm/configs/h5000_defconfig
index 37903e3..655b735 100644
--- a/arch/arm/configs/h5000_defconfig
+++ b/arch/arm/configs/h5000_defconfig
@@ -47,8 +47,9 @@ CONFIG_MTD_PHYSMAP=y
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_LEGACY_PTY_COUNT=32
 # CONFIG_HW_RANDOM is not set
 # CONFIG_HWMON is not set
diff --git a/arch/arm/configs/imote2_defconfig b/arch/arm/configs/imote2_defconfig
index fd996bb..49d45e9 100644
--- a/arch/arm/configs/imote2_defconfig
+++ b/arch/arm/configs/imote2_defconfig
@@ -193,8 +193,9 @@ CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=y
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_LEGACY_PTY_COUNT=8
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/lpd270_defconfig b/arch/arm/configs/lpd270_defconfig
index 1c8c9ee..c3927b6 100644
--- a/arch/arm/configs/lpd270_defconfig
+++ b/arch/arm/configs/lpd270_defconfig
@@ -38,8 +38,9 @@ CONFIG_SMC91X=y
 CONFIG_INPUT_EVDEV=y
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_HW_RANDOM is not set
 CONFIG_FB=y
 CONFIG_FB_PXA=y
diff --git a/arch/arm/configs/lubbock_defconfig b/arch/arm/configs/lubbock_defconfig
index c4ba274..c8b0436 100644
--- a/arch/arm/configs/lubbock_defconfig
+++ b/arch/arm/configs/lubbock_defconfig
@@ -37,8 +37,9 @@ CONFIG_PCMCIA_PCNET=y
 CONFIG_INPUT_EVDEV=y
 # CONFIG_SERIO_SERPORT is not set
 CONFIG_SERIO_SA1111=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_USB_GADGET=y
 CONFIG_USB_G_SERIAL=m
diff --git a/arch/arm/configs/mainstone_defconfig b/arch/arm/configs/mainstone_defconfig
index 04efa1b..768892c 100644
--- a/arch/arm/configs/mainstone_defconfig
+++ b/arch/arm/configs/mainstone_defconfig
@@ -34,8 +34,9 @@ CONFIG_SMC91X=y
 CONFIG_INPUT_EVDEV=y
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_FB=y
 CONFIG_FB_PXA=y
 # CONFIG_VGA_CONSOLE is not set
diff --git a/arch/arm/configs/mmp2_defconfig b/arch/arm/configs/mmp2_defconfig
index f1cb95e..1ced9df 100644
--- a/arch/arm/configs/mmp2_defconfig
+++ b/arch/arm/configs/mmp2_defconfig
@@ -44,8 +44,9 @@ CONFIG_SMC91X=y
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/pcm027_defconfig b/arch/arm/configs/pcm027_defconfig
index 2f136c3..1280128 100644
--- a/arch/arm/configs/pcm027_defconfig
+++ b/arch/arm/configs/pcm027_defconfig
@@ -60,8 +60,9 @@ CONFIG_SMC91X=y
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/pxa168_defconfig b/arch/arm/configs/pxa168_defconfig
index 74d7e01..1668dac 100644
--- a/arch/arm/configs/pxa168_defconfig
+++ b/arch/arm/configs/pxa168_defconfig
@@ -40,8 +40,9 @@ CONFIG_SMC91X=y
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 # CONFIG_HWMON is not set
diff --git a/arch/arm/configs/pxa255-idp_defconfig b/arch/arm/configs/pxa255-idp_defconfig
index 917a070..399a706 100644
--- a/arch/arm/configs/pxa255-idp_defconfig
+++ b/arch/arm/configs/pxa255-idp_defconfig
@@ -35,8 +35,9 @@ CONFIG_SMC91X=y
 CONFIG_INPUT_EVDEV=y
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_FB=y
 CONFIG_FB_PXA=y
 # CONFIG_VGA_CONSOLE is not set
diff --git a/arch/arm/configs/pxa3xx_defconfig b/arch/arm/configs/pxa3xx_defconfig
index 60e3138..7c3e052 100644
--- a/arch/arm/configs/pxa3xx_defconfig
+++ b/arch/arm/configs/pxa3xx_defconfig
@@ -56,8 +56,9 @@ CONFIG_KEYBOARD_PXA27x=y
 CONFIG_KEYBOARD_PXA930_ROTARY=y
 CONFIG_MOUSE_PXA930_TRKBALL=y
 CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/pxa910_defconfig b/arch/arm/configs/pxa910_defconfig
index 3bb7771..cdacfcb 100644
--- a/arch/arm/configs/pxa910_defconfig
+++ b/arch/arm/configs/pxa910_defconfig
@@ -40,8 +40,9 @@ CONFIG_SMC91X=y
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_SPI=y
 CONFIG_FB=y
 CONFIG_MMP_DISP=y
diff --git a/arch/arm/configs/raumfeld_defconfig b/arch/arm/configs/raumfeld_defconfig
index f7caa90..f1e16f2 100644
--- a/arch/arm/configs/raumfeld_defconfig
+++ b/arch/arm/configs/raumfeld_defconfig
@@ -67,8 +67,9 @@ CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_TOUCHSCREEN_EETI=m
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_GPIO_ROTARY_ENCODER=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_HW_RANDOM=y
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
diff --git a/arch/arm/configs/spitz_defconfig b/arch/arm/configs/spitz_defconfig
index 2e0419d..b6efcf5 100644
--- a/arch/arm/configs/spitz_defconfig
+++ b/arch/arm/configs/spitz_defconfig
@@ -128,10 +128,10 @@ CONFIG_TOUCHSCREEN_ADS7846=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=m
 # CONFIG_SERIO is not set
-CONFIG_SERIAL_8250=m
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_CS=m
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 CONFIG_SPI=y
 CONFIG_SPI_PXA2XX=y
diff --git a/arch/arm/configs/trizeps4_defconfig b/arch/arm/configs/trizeps4_defconfig
index 3162173..453c79c 100644
--- a/arch/arm/configs/trizeps4_defconfig
+++ b/arch/arm/configs/trizeps4_defconfig
@@ -132,8 +132,9 @@ CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=m
 CONFIG_SERIO_LIBPS2=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_HW_RANDOM=y
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
diff --git a/arch/arm/configs/viper_defconfig b/arch/arm/configs/viper_defconfig
index d36e0d3..4efac06 100644
--- a/arch/arm/configs/viper_defconfig
+++ b/arch/arm/configs/viper_defconfig
@@ -101,11 +101,11 @@ CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=m
 # CONFIG_CONSOLE_TRANSLATIONS is not set
 # CONFIG_VT_CONSOLE is not set
-CONFIG_SERIAL_8250=m
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_NR_UARTS=5
 CONFIG_SERIAL_8250_RUNTIME_UARTS=5
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
diff --git a/arch/arm/configs/xcep_defconfig b/arch/arm/configs/xcep_defconfig
index 721832f..b67aeaf 100644
--- a/arch/arm/configs/xcep_defconfig
+++ b/arch/arm/configs/xcep_defconfig
@@ -60,8 +60,9 @@ CONFIG_NET_ETHERNET=y
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
 # CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=m
diff --git a/drivers/tty/serial/8250/8250_pxa.c b/drivers/tty/serial/8250/8250_pxa.c
new file mode 100644
index 0000000..0da0d40
--- /dev/null
+++ b/drivers/tty/serial/8250/8250_pxa.c
@@ -0,0 +1,178 @@
+/*
+ *  drivers/tty/serial/8250/8250_pxa.c -- driver for PXA on-board UARTS
+ *  Copyright:	(C) 2013 Sergei Ianovich <ynvich@gmail.com>
+ *
+ *  replaces drivers/serial/pxa.c by Nicolas Pitre
+ *  Created:	Feb 20, 2003
+ *  Copyright:	(C) 2003 Monta Vista Software, Inc.
+ *
+ *  Based on drivers/serial/8250.c by Russell King.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/serial_8250.h>
+#include <linux/serial_core.h>
+#include <linux/serial_reg.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
+#include <linux/pm_runtime.h>
+
+#include "8250.h"
+
+struct pxa8250_data {
+	int			line;
+	struct clk		*clk;
+};
+
+#ifdef CONFIG_PM
+static int serial_pxa_suspend(struct device *dev)
+{
+	struct pxa8250_data *data = dev_get_drvdata(dev);
+
+	serial8250_suspend_port(data->line);
+
+	return 0;
+}
+
+static int serial_pxa_resume(struct device *dev)
+{
+	struct pxa8250_data *data = dev_get_drvdata(dev);
+
+	serial8250_resume_port(data->line);
+
+	return 0;
+}
+#endif
+
+static const struct dev_pm_ops serial_pxa_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(serial_pxa_suspend, serial_pxa_resume)
+};
+
+static struct of_device_id serial_pxa_dt_ids[] = {
+	{ .compatible = "mrvl,pxa-uart", },
+	{ .compatible = "mrvl,mmp-uart", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, serial_pxa_dt_ids);
+
+/* Uart divisor latch write */
+static void serial_pxa_dl_write(struct uart_8250_port *up, int value)
+{
+	unsigned int dll;
+
+	serial_out(up, UART_DLL, value & 0xff);
+	/*
+	 * work around Erratum #74 according to Marvel(R) PXA270M Processor
+	 * Specification Update (April 19, 2010)
+	 */
+	dll = serial_in(up, UART_DLL);
+	WARN_ON(dll != (value & 0xff));
+
+	serial_out(up, UART_DLM, value >> 8 & 0xff);
+}
+
+
+static void serial_pxa_pm(struct uart_port *port, unsigned int state,
+	      unsigned int oldstate)
+{
+	struct pxa8250_data *data = port->private_data;
+
+	if (!state)
+		clk_prepare_enable(data->clk);
+	else
+		clk_disable_unprepare(data->clk);
+}
+
+static int serial_pxa_probe(struct platform_device *pdev)
+{
+	struct uart_8250_port uart = {};
+	struct pxa8250_data *data;
+	struct resource *mmres, *irqres;
+	int ret;
+
+	mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	irqres = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!mmres || !irqres)
+		return -ENODEV;
+
+	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(data->clk))
+		return PTR_ERR(data->clk);
+
+	ret = clk_prepare(data->clk);
+	if (ret)
+		return ret;
+
+	uart.port.type = PORT_XSCALE;
+	uart.port.iotype = UPIO_MEM32;
+	uart.port.mapbase = mmres->start;
+	uart.port.regshift = 2;
+	uart.port.irq = irqres->start;
+	uart.port.fifosize = 64;
+	uart.port.flags = UPF_IOREMAP | UPF_SKIP_TEST;
+	uart.port.dev = &pdev->dev;
+	uart.port.uartclk = clk_get_rate(data->clk);
+	uart.port.pm = serial_pxa_pm;
+	uart.port.private_data = data;
+	uart.dl_write = serial_pxa_dl_write;
+
+	ret = serial8250_register_8250_port(&uart);
+	if (ret < 0)
+		goto err_clk;
+
+	data->line = ret;
+
+	platform_set_drvdata(pdev, data);
+
+	return 0;
+
+ err_clk:
+	clk_unprepare(data->clk);
+	return ret;
+}
+
+static int serial_pxa_remove(struct platform_device *pdev)
+{
+	struct pxa8250_data *data = platform_get_drvdata(pdev);
+
+	serial8250_unregister_port(data->line);
+
+	clk_unprepare(data->clk);
+
+	return 0;
+}
+
+static struct platform_driver serial_pxa_driver = {
+	.probe          = serial_pxa_probe,
+	.remove         = serial_pxa_remove,
+
+	.driver		= {
+		.name	= "pxa2xx-uart",
+		.owner	= THIS_MODULE,
+		.pm	= &serial_pxa_pm_ops,
+		.of_match_table = serial_pxa_dt_ids,
+	},
+};
+
+module_platform_driver(serial_pxa_driver);
+
+MODULE_AUTHOR("Sergei Ianovich");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:pxa2xx-uart");
diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
index 2332991..81bd7c9 100644
--- a/drivers/tty/serial/8250/Kconfig
+++ b/drivers/tty/serial/8250/Kconfig
@@ -302,3 +302,12 @@ config SERIAL_8250_RT288X
 	  If you have a Ralink RT288x/RT305x SoC based board and want to use the
 	  serial port, say Y to this option. The driver can handle up to 2 serial
 	  ports. If unsure, say N.
+
+config SERIAL_PXA
+	tristate "PXA serial port support"
+	depends on SERIAL_8250 && (ARCH_PXA || ARCH_MMP)
+	help
+	  If you have a machine based on an Intel XScale PXA2xx CPU you
+	  can enable its onboard serial ports by enabling this option.
+
+	  If you choose M here, the module name will be 8250_pxa.
diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile
index 36d68d0..b7d1b61 100644
--- a/drivers/tty/serial/8250/Makefile
+++ b/drivers/tty/serial/8250/Makefile
@@ -20,3 +20,4 @@ obj-$(CONFIG_SERIAL_8250_HUB6)		+= 8250_hub6.o
 obj-$(CONFIG_SERIAL_8250_FSL)		+= 8250_fsl.o
 obj-$(CONFIG_SERIAL_8250_DW)		+= 8250_dw.o
 obj-$(CONFIG_SERIAL_8250_EM)		+= 8250_em.o
+obj-$(CONFIG_SERIAL_PXA)		+= 8250_pxa.o
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index 2e6d8dd..da46e31 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -395,29 +395,6 @@ config SERIAL_MPSC_CONSOLE
 	help
 	  Say Y here if you want to support a serial console on a Marvell MPSC.
 
-config SERIAL_PXA
-	bool "PXA serial port support"
-	depends on ARCH_PXA || ARCH_MMP
-	select SERIAL_CORE
-	help
-	  If you have a machine based on an Intel XScale PXA2xx CPU you
-	  can enable its onboard serial ports by enabling this option.
-
-config SERIAL_PXA_CONSOLE
-	bool "Console on PXA serial port"
-	depends on SERIAL_PXA
-	select SERIAL_CORE_CONSOLE
-	help
-	  If you have enabled the serial port on the Intel XScale PXA
-	  CPU you can make it the console by answering Y to this option.
-
-	  Even if you say Y here, the currently visible virtual console
-	  (/dev/tty0) will still be used as the system console by default, but
-	  you can alter that using a kernel command line option such as
-	  "console=ttySA0". (Try "man bootparam" or see the documentation of
-	  your boot loader (lilo or loadlin) about how to pass options to the
-	  kernel at boot time.)
-
 config SERIAL_SA1100
 	bool "SA1100 serial port support"
 	depends on ARCH_SA1100
diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile
index 3680854..fd71d3f 100644
--- a/drivers/tty/serial/Makefile
+++ b/drivers/tty/serial/Makefile
@@ -20,7 +20,6 @@ obj-$(CONFIG_SERIAL_8250) += 8250/
 obj-$(CONFIG_SERIAL_AMBA_PL010) += amba-pl010.o
 obj-$(CONFIG_SERIAL_AMBA_PL011) += amba-pl011.o
 obj-$(CONFIG_SERIAL_CLPS711X) += clps711x.o
-obj-$(CONFIG_SERIAL_PXA) += pxa.o
 obj-$(CONFIG_SERIAL_PNX8XXX) += pnx8xxx_uart.o
 obj-$(CONFIG_SERIAL_SA1100) += sa1100.o
 obj-$(CONFIG_SERIAL_BCM63XX) += bcm63xx_uart.o
diff --git a/drivers/tty/serial/pxa.c b/drivers/tty/serial/pxa.c
deleted file mode 100644
index f9f20f3..0000000
--- a/drivers/tty/serial/pxa.c
+++ /dev/null
@@ -1,971 +0,0 @@
-/*
- *  Based on drivers/serial/8250.c by Russell King.
- *
- *  Author:	Nicolas Pitre
- *  Created:	Feb 20, 2003
- *  Copyright:	(C) 2003 Monta Vista Software, Inc.
- *
- * 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.
- *
- * Note 1: This driver is made separate from the already too overloaded
- * 8250.c because it needs some kirks of its own and that'll make it
- * easier to add DMA support.
- *
- * Note 2: I'm too sick of device allocation policies for serial ports.
- * If someone else wants to request an "official" allocation of major/minor
- * for this driver please be my guest.  And don't forget that new hardware
- * to come from Intel might have more than 3 or 4 of those UARTs.  Let's
- * hope for a better port registration and dynamic device allocation scheme
- * with the serial core maintainer satisfaction to appear soon.
- */
-
-
-#if defined(CONFIG_SERIAL_PXA_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-#define SUPPORT_SYSRQ
-#endif
-
-#include <linux/module.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-#include <linux/console.h>
-#include <linux/sysrq.h>
-#include <linux/serial_reg.h>
-#include <linux/circ_buf.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/of.h>
-#include <linux/platform_device.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/serial_core.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-
-#define PXA_NAME_LEN		8
-
-struct uart_pxa_port {
-	struct uart_port        port;
-	unsigned char           ier;
-	unsigned char           lcr;
-	unsigned char           mcr;
-	unsigned int            lsr_break_flag;
-	struct clk		*clk;
-	char			name[PXA_NAME_LEN];
-};
-
-static inline unsigned int serial_in(struct uart_pxa_port *up, int offset)
-{
-	offset <<= 2;
-	return readl(up->port.membase + offset);
-}
-
-static inline void serial_out(struct uart_pxa_port *up, int offset, int value)
-{
-	offset <<= 2;
-	writel(value, up->port.membase + offset);
-}
-
-static void serial_pxa_enable_ms(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	up->ier |= UART_IER_MSI;
-	serial_out(up, UART_IER, up->ier);
-}
-
-static void serial_pxa_stop_tx(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	if (up->ier & UART_IER_THRI) {
-		up->ier &= ~UART_IER_THRI;
-		serial_out(up, UART_IER, up->ier);
-	}
-}
-
-static void serial_pxa_stop_rx(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	up->ier &= ~UART_IER_RLSI;
-	up->port.read_status_mask &= ~UART_LSR_DR;
-	serial_out(up, UART_IER, up->ier);
-}
-
-static inline void receive_chars(struct uart_pxa_port *up, int *status)
-{
-	unsigned int ch, flag;
-	int max_count = 256;
-
-	do {
-		/* work around Errata #20 according to
-		 * Intel(R) PXA27x Processor Family
-		 * Specification Update (May 2005)
-		 *
-		 * Step 2
-		 * Disable the Reciever Time Out Interrupt via IER[RTOEI]
-		 */
-		up->ier &= ~UART_IER_RTOIE;
-		serial_out(up, UART_IER, up->ier);
-
-		ch = serial_in(up, UART_RX);
-		flag = TTY_NORMAL;
-		up->port.icount.rx++;
-
-		if (unlikely(*status & (UART_LSR_BI | UART_LSR_PE |
-				       UART_LSR_FE | UART_LSR_OE))) {
-			/*
-			 * For statistics only
-			 */
-			if (*status & UART_LSR_BI) {
-				*status &= ~(UART_LSR_FE | UART_LSR_PE);
-				up->port.icount.brk++;
-				/*
-				 * We do the SysRQ and SAK checking
-				 * here because otherwise the break
-				 * may get masked by ignore_status_mask
-				 * or read_status_mask.
-				 */
-				if (uart_handle_break(&up->port))
-					goto ignore_char;
-			} else if (*status & UART_LSR_PE)
-				up->port.icount.parity++;
-			else if (*status & UART_LSR_FE)
-				up->port.icount.frame++;
-			if (*status & UART_LSR_OE)
-				up->port.icount.overrun++;
-
-			/*
-			 * Mask off conditions which should be ignored.
-			 */
-			*status &= up->port.read_status_mask;
-
-#ifdef CONFIG_SERIAL_PXA_CONSOLE
-			if (up->port.line == up->port.cons->index) {
-				/* Recover the break flag from console xmit */
-				*status |= up->lsr_break_flag;
-				up->lsr_break_flag = 0;
-			}
-#endif
-			if (*status & UART_LSR_BI) {
-				flag = TTY_BREAK;
-			} else if (*status & UART_LSR_PE)
-				flag = TTY_PARITY;
-			else if (*status & UART_LSR_FE)
-				flag = TTY_FRAME;
-		}
-
-		if (uart_handle_sysrq_char(&up->port, ch))
-			goto ignore_char;
-
-		uart_insert_char(&up->port, *status, UART_LSR_OE, ch, flag);
-
-	ignore_char:
-		*status = serial_in(up, UART_LSR);
-	} while ((*status & UART_LSR_DR) && (max_count-- > 0));
-	tty_flip_buffer_push(&up->port.state->port);
-
-	/* work around Errata #20 according to
-	 * Intel(R) PXA27x Processor Family
-	 * Specification Update (May 2005)
-	 *
-	 * Step 6:
-	 * No more data in FIFO: Re-enable RTO interrupt via IER[RTOIE]
-	 */
-	up->ier |= UART_IER_RTOIE;
-	serial_out(up, UART_IER, up->ier);
-}
-
-static void transmit_chars(struct uart_pxa_port *up)
-{
-	struct circ_buf *xmit = &up->port.state->xmit;
-	int count;
-
-	if (up->port.x_char) {
-		serial_out(up, UART_TX, up->port.x_char);
-		up->port.icount.tx++;
-		up->port.x_char = 0;
-		return;
-	}
-	if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) {
-		serial_pxa_stop_tx(&up->port);
-		return;
-	}
-
-	count = up->port.fifosize / 2;
-	do {
-		serial_out(up, UART_TX, xmit->buf[xmit->tail]);
-		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
-		up->port.icount.tx++;
-		if (uart_circ_empty(xmit))
-			break;
-	} while (--count > 0);
-
-	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
-		uart_write_wakeup(&up->port);
-
-
-	if (uart_circ_empty(xmit))
-		serial_pxa_stop_tx(&up->port);
-}
-
-static void serial_pxa_start_tx(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	if (!(up->ier & UART_IER_THRI)) {
-		up->ier |= UART_IER_THRI;
-		serial_out(up, UART_IER, up->ier);
-	}
-}
-
-static inline void check_modem_status(struct uart_pxa_port *up)
-{
-	int status;
-
-	status = serial_in(up, UART_MSR);
-
-	if ((status & UART_MSR_ANY_DELTA) == 0)
-		return;
-
-	if (status & UART_MSR_TERI)
-		up->port.icount.rng++;
-	if (status & UART_MSR_DDSR)
-		up->port.icount.dsr++;
-	if (status & UART_MSR_DDCD)
-		uart_handle_dcd_change(&up->port, status & UART_MSR_DCD);
-	if (status & UART_MSR_DCTS)
-		uart_handle_cts_change(&up->port, status & UART_MSR_CTS);
-
-	wake_up_interruptible(&up->port.state->port.delta_msr_wait);
-}
-
-/*
- * This handles the interrupt from one port.
- */
-static inline irqreturn_t serial_pxa_irq(int irq, void *dev_id)
-{
-	struct uart_pxa_port *up = dev_id;
-	unsigned int iir, lsr;
-
-	iir = serial_in(up, UART_IIR);
-	if (iir & UART_IIR_NO_INT)
-		return IRQ_NONE;
-	lsr = serial_in(up, UART_LSR);
-	if (lsr & UART_LSR_DR)
-		receive_chars(up, &lsr);
-	check_modem_status(up);
-	if (lsr & UART_LSR_THRE)
-		transmit_chars(up);
-	return IRQ_HANDLED;
-}
-
-static unsigned int serial_pxa_tx_empty(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned long flags;
-	unsigned int ret;
-
-	spin_lock_irqsave(&up->port.lock, flags);
-	ret = serial_in(up, UART_LSR) & UART_LSR_TEMT ? TIOCSER_TEMT : 0;
-	spin_unlock_irqrestore(&up->port.lock, flags);
-
-	return ret;
-}
-
-static unsigned int serial_pxa_get_mctrl(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned char status;
-	unsigned int ret;
-
-	status = serial_in(up, UART_MSR);
-
-	ret = 0;
-	if (status & UART_MSR_DCD)
-		ret |= TIOCM_CAR;
-	if (status & UART_MSR_RI)
-		ret |= TIOCM_RNG;
-	if (status & UART_MSR_DSR)
-		ret |= TIOCM_DSR;
-	if (status & UART_MSR_CTS)
-		ret |= TIOCM_CTS;
-	return ret;
-}
-
-static void serial_pxa_set_mctrl(struct uart_port *port, unsigned int mctrl)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned char mcr = 0;
-
-	if (mctrl & TIOCM_RTS)
-		mcr |= UART_MCR_RTS;
-	if (mctrl & TIOCM_DTR)
-		mcr |= UART_MCR_DTR;
-	if (mctrl & TIOCM_OUT1)
-		mcr |= UART_MCR_OUT1;
-	if (mctrl & TIOCM_OUT2)
-		mcr |= UART_MCR_OUT2;
-	if (mctrl & TIOCM_LOOP)
-		mcr |= UART_MCR_LOOP;
-
-	mcr |= up->mcr;
-
-	serial_out(up, UART_MCR, mcr);
-}
-
-static void serial_pxa_break_ctl(struct uart_port *port, int break_state)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned long flags;
-
-	spin_lock_irqsave(&up->port.lock, flags);
-	if (break_state == -1)
-		up->lcr |= UART_LCR_SBC;
-	else
-		up->lcr &= ~UART_LCR_SBC;
-	serial_out(up, UART_LCR, up->lcr);
-	spin_unlock_irqrestore(&up->port.lock, flags);
-}
-
-static int serial_pxa_startup(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned long flags;
-	int retval;
-
-	if (port->line == 3) /* HWUART */
-		up->mcr |= UART_MCR_AFE;
-	else
-		up->mcr = 0;
-
-	up->port.uartclk = clk_get_rate(up->clk);
-
-	/*
-	 * Allocate the IRQ
-	 */
-	retval = request_irq(up->port.irq, serial_pxa_irq, 0, up->name, up);
-	if (retval)
-		return retval;
-
-	/*
-	 * Clear the FIFO buffers and disable them.
-	 * (they will be reenabled in set_termios())
-	 */
-	serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO);
-	serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO |
-			UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
-	serial_out(up, UART_FCR, 0);
-
-	/*
-	 * Clear the interrupt registers.
-	 */
-	(void) serial_in(up, UART_LSR);
-	(void) serial_in(up, UART_RX);
-	(void) serial_in(up, UART_IIR);
-	(void) serial_in(up, UART_MSR);
-
-	/*
-	 * Now, initialize the UART
-	 */
-	serial_out(up, UART_LCR, UART_LCR_WLEN8);
-
-	spin_lock_irqsave(&up->port.lock, flags);
-	up->port.mctrl |= TIOCM_OUT2;
-	serial_pxa_set_mctrl(&up->port, up->port.mctrl);
-	spin_unlock_irqrestore(&up->port.lock, flags);
-
-	/*
-	 * Finally, enable interrupts.  Note: Modem status interrupts
-	 * are set via set_termios(), which will be occurring imminently
-	 * anyway, so we don't enable them here.
-	 */
-	up->ier = UART_IER_RLSI | UART_IER_RDI | UART_IER_RTOIE | UART_IER_UUE;
-	serial_out(up, UART_IER, up->ier);
-
-	/*
-	 * And clear the interrupt registers again for luck.
-	 */
-	(void) serial_in(up, UART_LSR);
-	(void) serial_in(up, UART_RX);
-	(void) serial_in(up, UART_IIR);
-	(void) serial_in(up, UART_MSR);
-
-	return 0;
-}
-
-static void serial_pxa_shutdown(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned long flags;
-
-	free_irq(up->port.irq, up);
-
-	/*
-	 * Disable interrupts from this port
-	 */
-	up->ier = 0;
-	serial_out(up, UART_IER, 0);
-
-	spin_lock_irqsave(&up->port.lock, flags);
-	up->port.mctrl &= ~TIOCM_OUT2;
-	serial_pxa_set_mctrl(&up->port, up->port.mctrl);
-	spin_unlock_irqrestore(&up->port.lock, flags);
-
-	/*
-	 * Disable break condition and FIFOs
-	 */
-	serial_out(up, UART_LCR, serial_in(up, UART_LCR) & ~UART_LCR_SBC);
-	serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO |
-				  UART_FCR_CLEAR_RCVR |
-				  UART_FCR_CLEAR_XMIT);
-	serial_out(up, UART_FCR, 0);
-}
-
-static void
-serial_pxa_set_termios(struct uart_port *port, struct ktermios *termios,
-		       struct ktermios *old)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned char cval, fcr = 0;
-	unsigned long flags;
-	unsigned int baud, quot;
-	unsigned int dll;
-
-	switch (termios->c_cflag & CSIZE) {
-	case CS5:
-		cval = UART_LCR_WLEN5;
-		break;
-	case CS6:
-		cval = UART_LCR_WLEN6;
-		break;
-	case CS7:
-		cval = UART_LCR_WLEN7;
-		break;
-	default:
-	case CS8:
-		cval = UART_LCR_WLEN8;
-		break;
-	}
-
-	if (termios->c_cflag & CSTOPB)
-		cval |= UART_LCR_STOP;
-	if (termios->c_cflag & PARENB)
-		cval |= UART_LCR_PARITY;
-	if (!(termios->c_cflag & PARODD))
-		cval |= UART_LCR_EPAR;
-
-	/*
-	 * Ask the core to calculate the divisor for us.
-	 */
-	baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
-	quot = uart_get_divisor(port, baud);
-
-	if ((up->port.uartclk / quot) < (2400 * 16))
-		fcr = UART_FCR_ENABLE_FIFO | UART_FCR_PXAR1;
-	else if ((up->port.uartclk / quot) < (230400 * 16))
-		fcr = UART_FCR_ENABLE_FIFO | UART_FCR_PXAR8;
-	else
-		fcr = UART_FCR_ENABLE_FIFO | UART_FCR_PXAR32;
-
-	/*
-	 * Ok, we're now changing the port state.  Do it with
-	 * interrupts disabled.
-	 */
-	spin_lock_irqsave(&up->port.lock, flags);
-
-	/*
-	 * Ensure the port will be enabled.
-	 * This is required especially for serial console.
-	 */
-	up->ier |= UART_IER_UUE;
-
-	/*
-	 * Update the per-port timeout.
-	 */
-	uart_update_timeout(port, termios->c_cflag, baud);
-
-	up->port.read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;
-	if (termios->c_iflag & INPCK)
-		up->port.read_status_mask |= UART_LSR_FE | UART_LSR_PE;
-	if (termios->c_iflag & (BRKINT | PARMRK))
-		up->port.read_status_mask |= UART_LSR_BI;
-
-	/*
-	 * Characters to ignore
-	 */
-	up->port.ignore_status_mask = 0;
-	if (termios->c_iflag & IGNPAR)
-		up->port.ignore_status_mask |= UART_LSR_PE | UART_LSR_FE;
-	if (termios->c_iflag & IGNBRK) {
-		up->port.ignore_status_mask |= UART_LSR_BI;
-		/*
-		 * If we're ignoring parity and break indicators,
-		 * ignore overruns too (for real raw support).
-		 */
-		if (termios->c_iflag & IGNPAR)
-			up->port.ignore_status_mask |= UART_LSR_OE;
-	}
-
-	/*
-	 * ignore all characters if CREAD is not set
-	 */
-	if ((termios->c_cflag & CREAD) == 0)
-		up->port.ignore_status_mask |= UART_LSR_DR;
-
-	/*
-	 * CTS flow control flag and modem status interrupts
-	 */
-	up->ier &= ~UART_IER_MSI;
-	if (UART_ENABLE_MS(&up->port, termios->c_cflag))
-		up->ier |= UART_IER_MSI;
-
-	serial_out(up, UART_IER, up->ier);
-
-	if (termios->c_cflag & CRTSCTS)
-		up->mcr |= UART_MCR_AFE;
-	else
-		up->mcr &= ~UART_MCR_AFE;
-
-	serial_out(up, UART_LCR, cval | UART_LCR_DLAB);	/* set DLAB */
-	serial_out(up, UART_DLL, quot & 0xff);		/* LS of divisor */
-
-	/*
-	 * work around Errata #75 according to Intel(R) PXA27x Processor Family
-	 * Specification Update (Nov 2005)
-	 */
-	dll = serial_in(up, UART_DLL);
-	WARN_ON(dll != (quot & 0xff));
-
-	serial_out(up, UART_DLM, quot >> 8);		/* MS of divisor */
-	serial_out(up, UART_LCR, cval);			/* reset DLAB */
-	up->lcr = cval;					/* Save LCR */
-	serial_pxa_set_mctrl(&up->port, up->port.mctrl);
-	serial_out(up, UART_FCR, fcr);
-	spin_unlock_irqrestore(&up->port.lock, flags);
-}
-
-static void
-serial_pxa_pm(struct uart_port *port, unsigned int state,
-	      unsigned int oldstate)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	if (!state)
-		clk_prepare_enable(up->clk);
-	else
-		clk_disable_unprepare(up->clk);
-}
-
-static void serial_pxa_release_port(struct uart_port *port)
-{
-}
-
-static int serial_pxa_request_port(struct uart_port *port)
-{
-	return 0;
-}
-
-static void serial_pxa_config_port(struct uart_port *port, int flags)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	up->port.type = PORT_PXA;
-}
-
-static int
-serial_pxa_verify_port(struct uart_port *port, struct serial_struct *ser)
-{
-	/* we don't want the core code to modify any port params */
-	return -EINVAL;
-}
-
-static const char *
-serial_pxa_type(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	return up->name;
-}
-
-static struct uart_pxa_port *serial_pxa_ports[4];
-static struct uart_driver serial_pxa_reg;
-
-#ifdef CONFIG_SERIAL_PXA_CONSOLE
-
-#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
-
-/*
- *	Wait for transmitter & holding register to empty
- */
-static inline void wait_for_xmitr(struct uart_pxa_port *up)
-{
-	unsigned int status, tmout = 10000;
-
-	/* Wait up to 10ms for the character(s) to be sent. */
-	do {
-		status = serial_in(up, UART_LSR);
-
-		if (status & UART_LSR_BI)
-			up->lsr_break_flag = UART_LSR_BI;
-
-		if (--tmout == 0)
-			break;
-		udelay(1);
-	} while ((status & BOTH_EMPTY) != BOTH_EMPTY);
-
-	/* Wait up to 1s for flow control if necessary */
-	if (up->port.flags & UPF_CONS_FLOW) {
-		tmout = 1000000;
-		while (--tmout &&
-		       ((serial_in(up, UART_MSR) & UART_MSR_CTS) == 0))
-			udelay(1);
-	}
-}
-
-static void serial_pxa_console_putchar(struct uart_port *port, int ch)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	wait_for_xmitr(up);
-	serial_out(up, UART_TX, ch);
-}
-
-/*
- * Print a string to the serial port trying not to disturb
- * any possible real use of the port...
- *
- *	The console_lock must be held when we get here.
- */
-static void
-serial_pxa_console_write(struct console *co, const char *s, unsigned int count)
-{
-	struct uart_pxa_port *up = serial_pxa_ports[co->index];
-	unsigned int ier;
-	unsigned long flags;
-	int locked = 1;
-
-	clk_enable(up->clk);
-	local_irq_save(flags);
-	if (up->port.sysrq)
-		locked = 0;
-	else if (oops_in_progress)
-		locked = spin_trylock(&up->port.lock);
-	else
-		spin_lock(&up->port.lock);
-
-	/*
-	 *	First save the IER then disable the interrupts
-	 */
-	ier = serial_in(up, UART_IER);
-	serial_out(up, UART_IER, UART_IER_UUE);
-
-	uart_console_write(&up->port, s, count, serial_pxa_console_putchar);
-
-	/*
-	 *	Finally, wait for transmitter to become empty
-	 *	and restore the IER
-	 */
-	wait_for_xmitr(up);
-	serial_out(up, UART_IER, ier);
-
-	if (locked)
-		spin_unlock(&up->port.lock);
-	local_irq_restore(flags);
-	clk_disable(up->clk);
-
-}
-
-#ifdef CONFIG_CONSOLE_POLL
-/*
- * Console polling routines for writing and reading from the uart while
- * in an interrupt or debug context.
- */
-
-static int serial_pxa_get_poll_char(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned char lsr = serial_in(up, UART_LSR);
-
-	while (!(lsr & UART_LSR_DR))
-		lsr = serial_in(up, UART_LSR);
-
-	return serial_in(up, UART_RX);
-}
-
-
-static void serial_pxa_put_poll_char(struct uart_port *port,
-			 unsigned char c)
-{
-	unsigned int ier;
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	/*
-	 *	First save the IER then disable the interrupts
-	 */
-	ier = serial_in(up, UART_IER);
-	serial_out(up, UART_IER, UART_IER_UUE);
-
-	wait_for_xmitr(up);
-	/*
-	 *	Send the character out.
-	 *	If a LF, also do CR...
-	 */
-	serial_out(up, UART_TX, c);
-	if (c == 10) {
-		wait_for_xmitr(up);
-		serial_out(up, UART_TX, 13);
-	}
-
-	/*
-	 *	Finally, wait for transmitter to become empty
-	 *	and restore the IER
-	 */
-	wait_for_xmitr(up);
-	serial_out(up, UART_IER, ier);
-}
-
-#endif /* CONFIG_CONSOLE_POLL */
-
-static int __init
-serial_pxa_console_setup(struct console *co, char *options)
-{
-	struct uart_pxa_port *up;
-	int baud = 9600;
-	int bits = 8;
-	int parity = 'n';
-	int flow = 'n';
-
-	if (co->index == -1 || co->index >= serial_pxa_reg.nr)
-		co->index = 0;
-	up = serial_pxa_ports[co->index];
-	if (!up)
-		return -ENODEV;
-
-	if (options)
-		uart_parse_options(options, &baud, &parity, &bits, &flow);
-
-	return uart_set_options(&up->port, co, baud, parity, bits, flow);
-}
-
-static struct console serial_pxa_console = {
-	.name		= "ttyS",
-	.write		= serial_pxa_console_write,
-	.device		= uart_console_device,
-	.setup		= serial_pxa_console_setup,
-	.flags		= CON_PRINTBUFFER,
-	.index		= -1,
-	.data		= &serial_pxa_reg,
-};
-
-#define PXA_CONSOLE	&serial_pxa_console
-#else
-#define PXA_CONSOLE	NULL
-#endif
-
-static struct uart_ops serial_pxa_pops = {
-	.tx_empty	= serial_pxa_tx_empty,
-	.set_mctrl	= serial_pxa_set_mctrl,
-	.get_mctrl	= serial_pxa_get_mctrl,
-	.stop_tx	= serial_pxa_stop_tx,
-	.start_tx	= serial_pxa_start_tx,
-	.stop_rx	= serial_pxa_stop_rx,
-	.enable_ms	= serial_pxa_enable_ms,
-	.break_ctl	= serial_pxa_break_ctl,
-	.startup	= serial_pxa_startup,
-	.shutdown	= serial_pxa_shutdown,
-	.set_termios	= serial_pxa_set_termios,
-	.pm		= serial_pxa_pm,
-	.type		= serial_pxa_type,
-	.release_port	= serial_pxa_release_port,
-	.request_port	= serial_pxa_request_port,
-	.config_port	= serial_pxa_config_port,
-	.verify_port	= serial_pxa_verify_port,
-#ifdef CONFIG_CONSOLE_POLL
-	.poll_get_char = serial_pxa_get_poll_char,
-	.poll_put_char = serial_pxa_put_poll_char,
-#endif
-};
-
-static struct uart_driver serial_pxa_reg = {
-	.owner		= THIS_MODULE,
-	.driver_name	= "PXA serial",
-	.dev_name	= "ttyS",
-	.major		= TTY_MAJOR,
-	.minor		= 64,
-	.nr		= 4,
-	.cons		= PXA_CONSOLE,
-};
-
-#ifdef CONFIG_PM
-static int serial_pxa_suspend(struct device *dev)
-{
-        struct uart_pxa_port *sport = dev_get_drvdata(dev);
-
-        if (sport)
-                uart_suspend_port(&serial_pxa_reg, &sport->port);
-
-        return 0;
-}
-
-static int serial_pxa_resume(struct device *dev)
-{
-        struct uart_pxa_port *sport = dev_get_drvdata(dev);
-
-        if (sport)
-                uart_resume_port(&serial_pxa_reg, &sport->port);
-
-        return 0;
-}
-
-static const struct dev_pm_ops serial_pxa_pm_ops = {
-	.suspend	= serial_pxa_suspend,
-	.resume		= serial_pxa_resume,
-};
-#endif
-
-static struct of_device_id serial_pxa_dt_ids[] = {
-	{ .compatible = "mrvl,pxa-uart", },
-	{ .compatible = "mrvl,mmp-uart", },
-	{}
-};
-MODULE_DEVICE_TABLE(of, serial_pxa_dt_ids);
-
-static int serial_pxa_probe_dt(struct platform_device *pdev,
-			       struct uart_pxa_port *sport)
-{
-	struct device_node *np = pdev->dev.of_node;
-	int ret;
-
-	if (!np)
-		return 1;
-
-	ret = of_alias_get_id(np, "serial");
-	if (ret < 0) {
-		dev_err(&pdev->dev, "failed to get alias id, errno %d\n", ret);
-		return ret;
-	}
-	sport->port.line = ret;
-	return 0;
-}
-
-static int serial_pxa_probe(struct platform_device *dev)
-{
-	struct uart_pxa_port *sport;
-	struct resource *mmres, *irqres;
-	int ret;
-
-	mmres = platform_get_resource(dev, IORESOURCE_MEM, 0);
-	irqres = platform_get_resource(dev, IORESOURCE_IRQ, 0);
-	if (!mmres || !irqres)
-		return -ENODEV;
-
-	sport = kzalloc(sizeof(struct uart_pxa_port), GFP_KERNEL);
-	if (!sport)
-		return -ENOMEM;
-
-	sport->clk = clk_get(&dev->dev, NULL);
-	if (IS_ERR(sport->clk)) {
-		ret = PTR_ERR(sport->clk);
-		goto err_free;
-	}
-
-	ret = clk_prepare(sport->clk);
-	if (ret) {
-		clk_put(sport->clk);
-		goto err_free;
-	}
-
-	sport->port.type = PORT_PXA;
-	sport->port.iotype = UPIO_MEM;
-	sport->port.mapbase = mmres->start;
-	sport->port.irq = irqres->start;
-	sport->port.fifosize = 64;
-	sport->port.ops = &serial_pxa_pops;
-	sport->port.dev = &dev->dev;
-	sport->port.flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF;
-	sport->port.uartclk = clk_get_rate(sport->clk);
-
-	ret = serial_pxa_probe_dt(dev, sport);
-	if (ret > 0)
-		sport->port.line = dev->id;
-	else if (ret < 0)
-		goto err_clk;
-	snprintf(sport->name, PXA_NAME_LEN - 1, "UART%d", sport->port.line + 1);
-
-	sport->port.membase = ioremap(mmres->start, resource_size(mmres));
-	if (!sport->port.membase) {
-		ret = -ENOMEM;
-		goto err_clk;
-	}
-
-	serial_pxa_ports[sport->port.line] = sport;
-
-	uart_add_one_port(&serial_pxa_reg, &sport->port);
-	platform_set_drvdata(dev, sport);
-
-	return 0;
-
- err_clk:
-	clk_unprepare(sport->clk);
-	clk_put(sport->clk);
- err_free:
-	kfree(sport);
-	return ret;
-}
-
-static int serial_pxa_remove(struct platform_device *dev)
-{
-	struct uart_pxa_port *sport = platform_get_drvdata(dev);
-
-	uart_remove_one_port(&serial_pxa_reg, &sport->port);
-
-	clk_unprepare(sport->clk);
-	clk_put(sport->clk);
-	kfree(sport);
-
-	return 0;
-}
-
-static struct platform_driver serial_pxa_driver = {
-        .probe          = serial_pxa_probe,
-        .remove         = serial_pxa_remove,
-
-	.driver		= {
-	        .name	= "pxa2xx-uart",
-		.owner	= THIS_MODULE,
-#ifdef CONFIG_PM
-		.pm	= &serial_pxa_pm_ops,
-#endif
-		.of_match_table = serial_pxa_dt_ids,
-	},
-};
-
-static int __init serial_pxa_init(void)
-{
-	int ret;
-
-	ret = uart_register_driver(&serial_pxa_reg);
-	if (ret != 0)
-		return ret;
-
-	ret = platform_driver_register(&serial_pxa_driver);
-	if (ret != 0)
-		uart_unregister_driver(&serial_pxa_reg);
-
-	return ret;
-}
-
-static void __exit serial_pxa_exit(void)
-{
-	platform_driver_unregister(&serial_pxa_driver);
-	uart_unregister_driver(&serial_pxa_reg);
-}
-
-module_init(serial_pxa_init);
-module_exit(serial_pxa_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:pxa2xx-uart");
-- 
1.8.4.2


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

* [PATCH v4 01/21] serial: rewrite pxa2xx-uart to use 8250_core
@ 2014-04-16 17:13               ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2014-04-16 17:13 UTC (permalink / raw)
  To: linux-arm-kernel

pxa2xx-uart was a separate uart platform driver. It was declaring
the same device names and numbers as 8250 driver. As a result,
it was impossible to use 8250 driver on PXA SoCs.

Upon closer examination pxa2xx-uart turned out to be a clone of
8250_core driver.

Workaround for Erratum #19 according to Marvel(R) PXA270M Processor
Specification Update (April 19, 2010) is dropped. 8250_core reads
from FIFO immediately after checking DR bit in LSR.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Reviewed-by: James Cameron <quozl@laptop.org>
Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 Resenging together with the rest of the series as the series
 breaks without this one at [PATCH 12/21]

 no changes v3..v4

 changes v2..v3
 * remove devm_free/put as suggested by Heikki Krogerus
 * use SET_SYSTEM_SLEEP_PM_OPS macro to set pm ops as suggested
   by Heikki Krogerus

 changes v1..v2
 * actually implement workaround for E74 in dl_write as spooted
   by James Cameron
 * added comment about E19 in commit message

 arch/arm/configs/am200epdkit_defconfig    |   3 +-
 arch/arm/configs/cm_x2xx_defconfig        |   3 +-
 arch/arm/configs/cm_x300_defconfig        |   3 +-
 arch/arm/configs/colibri_pxa270_defconfig |   3 +-
 arch/arm/configs/colibri_pxa300_defconfig |   3 +-
 arch/arm/configs/corgi_defconfig          |   4 +-
 arch/arm/configs/em_x270_defconfig        |   3 +-
 arch/arm/configs/ezx_defconfig            |   3 +-
 arch/arm/configs/h5000_defconfig          |   3 +-
 arch/arm/configs/imote2_defconfig         |   3 +-
 arch/arm/configs/lpd270_defconfig         |   3 +-
 arch/arm/configs/lubbock_defconfig        |   3 +-
 arch/arm/configs/mainstone_defconfig      |   3 +-
 arch/arm/configs/mmp2_defconfig           |   3 +-
 arch/arm/configs/pcm027_defconfig         |   3 +-
 arch/arm/configs/pxa168_defconfig         |   3 +-
 arch/arm/configs/pxa255-idp_defconfig     |   3 +-
 arch/arm/configs/pxa3xx_defconfig         |   3 +-
 arch/arm/configs/pxa910_defconfig         |   3 +-
 arch/arm/configs/raumfeld_defconfig       |   3 +-
 arch/arm/configs/spitz_defconfig          |   4 +-
 arch/arm/configs/trizeps4_defconfig       |   3 +-
 arch/arm/configs/viper_defconfig          |   4 +-
 arch/arm/configs/xcep_defconfig           |   3 +-
 drivers/tty/serial/8250/8250_pxa.c        | 178 ++++++
 drivers/tty/serial/8250/Kconfig           |   9 +
 drivers/tty/serial/8250/Makefile          |   1 +
 drivers/tty/serial/Kconfig                |  23 -
 drivers/tty/serial/Makefile               |   1 -
 drivers/tty/serial/pxa.c                  | 971 ------------------------------
 30 files changed, 236 insertions(+), 1022 deletions(-)
 create mode 100644 drivers/tty/serial/8250/8250_pxa.c
 delete mode 100644 drivers/tty/serial/pxa.c

diff --git a/arch/arm/configs/am200epdkit_defconfig b/arch/arm/configs/am200epdkit_defconfig
index f0dea52..0cde234 100644
--- a/arch/arm/configs/am200epdkit_defconfig
+++ b/arch/arm/configs/am200epdkit_defconfig
@@ -60,8 +60,9 @@ CONFIG_BLK_DEV_IDECS=m
 CONFIG_NETDEVICES=y
 CONFIG_NET_ETHERNET=y
 CONFIG_SMC91X=m
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 # CONFIG_HWMON is not set
diff --git a/arch/arm/configs/cm_x2xx_defconfig b/arch/arm/configs/cm_x2xx_defconfig
index a93ff8d..b9fbe65 100644
--- a/arch/arm/configs/cm_x2xx_defconfig
+++ b/arch/arm/configs/cm_x2xx_defconfig
@@ -96,8 +96,9 @@ CONFIG_KEYBOARD_PXA27x=m
 CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_TOUCHSCREEN_UCB1400=m
 # CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_LEGACY_PTY_COUNT=16
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/cm_x300_defconfig b/arch/arm/configs/cm_x300_defconfig
index f4b7672..53a82ae 100644
--- a/arch/arm/configs/cm_x300_defconfig
+++ b/arch/arm/configs/cm_x300_defconfig
@@ -80,8 +80,9 @@ CONFIG_TOUCHSCREEN_WM97XX=m
 # CONFIG_TOUCHSCREEN_WM9713 is not set
 # CONFIG_SERIO is not set
 # CONFIG_LEGACY_PTYS is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
 CONFIG_I2C_PXA=y
diff --git a/arch/arm/configs/colibri_pxa270_defconfig b/arch/arm/configs/colibri_pxa270_defconfig
index 2ef2c5e..1ce0409 100644
--- a/arch/arm/configs/colibri_pxa270_defconfig
+++ b/arch/arm/configs/colibri_pxa270_defconfig
@@ -103,8 +103,9 @@ CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=m
 CONFIG_SERIO_LIBPS2=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_HW_RANDOM=y
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
diff --git a/arch/arm/configs/colibri_pxa300_defconfig b/arch/arm/configs/colibri_pxa300_defconfig
index b985334..f96bda0 100644
--- a/arch/arm/configs/colibri_pxa300_defconfig
+++ b/arch/arm/configs/colibri_pxa300_defconfig
@@ -31,8 +31,9 @@ CONFIG_INPUT_EVDEV=y
 # CONFIG_INPUT_MOUSE is not set
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_GPIO_ROTARY_ENCODER=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_HW_RANDOM=y
 CONFIG_DEBUG_GPIO=y
 # CONFIG_HWMON is not set
diff --git a/arch/arm/configs/corgi_defconfig b/arch/arm/configs/corgi_defconfig
index 1fd1d1d..bb4842d 100644
--- a/arch/arm/configs/corgi_defconfig
+++ b/arch/arm/configs/corgi_defconfig
@@ -131,10 +131,10 @@ CONFIG_TOUCHSCREEN_ADS7846=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=m
 # CONFIG_SERIO is not set
-CONFIG_SERIAL_8250=m
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_CS=m
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 CONFIG_I2C=y
 CONFIG_I2C_PXA=y
diff --git a/arch/arm/configs/em_x270_defconfig b/arch/arm/configs/em_x270_defconfig
index 60a21e0..ec0ec54 100644
--- a/arch/arm/configs/em_x270_defconfig
+++ b/arch/arm/configs/em_x270_defconfig
@@ -90,8 +90,9 @@ CONFIG_TOUCHSCREEN_WM97XX=m
 # CONFIG_TOUCHSCREEN_WM9705 is not set
 # CONFIG_TOUCHSCREEN_WM9713 is not set
 # CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_LEGACY_PTY_COUNT=16
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/ezx_defconfig b/arch/arm/configs/ezx_defconfig
index d95763d..631e2ec 100644
--- a/arch/arm/configs/ezx_defconfig
+++ b/arch/arm/configs/ezx_defconfig
@@ -215,8 +215,9 @@ CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=y
 CONFIG_INPUT_PCAP=y
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_LEGACY_PTY_COUNT=8
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/h5000_defconfig b/arch/arm/configs/h5000_defconfig
index 37903e3..655b735 100644
--- a/arch/arm/configs/h5000_defconfig
+++ b/arch/arm/configs/h5000_defconfig
@@ -47,8 +47,9 @@ CONFIG_MTD_PHYSMAP=y
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_LEGACY_PTY_COUNT=32
 # CONFIG_HW_RANDOM is not set
 # CONFIG_HWMON is not set
diff --git a/arch/arm/configs/imote2_defconfig b/arch/arm/configs/imote2_defconfig
index fd996bb..49d45e9 100644
--- a/arch/arm/configs/imote2_defconfig
+++ b/arch/arm/configs/imote2_defconfig
@@ -193,8 +193,9 @@ CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=y
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_LEGACY_PTY_COUNT=8
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/lpd270_defconfig b/arch/arm/configs/lpd270_defconfig
index 1c8c9ee..c3927b6 100644
--- a/arch/arm/configs/lpd270_defconfig
+++ b/arch/arm/configs/lpd270_defconfig
@@ -38,8 +38,9 @@ CONFIG_SMC91X=y
 CONFIG_INPUT_EVDEV=y
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_HW_RANDOM is not set
 CONFIG_FB=y
 CONFIG_FB_PXA=y
diff --git a/arch/arm/configs/lubbock_defconfig b/arch/arm/configs/lubbock_defconfig
index c4ba274..c8b0436 100644
--- a/arch/arm/configs/lubbock_defconfig
+++ b/arch/arm/configs/lubbock_defconfig
@@ -37,8 +37,9 @@ CONFIG_PCMCIA_PCNET=y
 CONFIG_INPUT_EVDEV=y
 # CONFIG_SERIO_SERPORT is not set
 CONFIG_SERIO_SA1111=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_USB_GADGET=y
 CONFIG_USB_G_SERIAL=m
diff --git a/arch/arm/configs/mainstone_defconfig b/arch/arm/configs/mainstone_defconfig
index 04efa1b..768892c 100644
--- a/arch/arm/configs/mainstone_defconfig
+++ b/arch/arm/configs/mainstone_defconfig
@@ -34,8 +34,9 @@ CONFIG_SMC91X=y
 CONFIG_INPUT_EVDEV=y
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_FB=y
 CONFIG_FB_PXA=y
 # CONFIG_VGA_CONSOLE is not set
diff --git a/arch/arm/configs/mmp2_defconfig b/arch/arm/configs/mmp2_defconfig
index f1cb95e..1ced9df 100644
--- a/arch/arm/configs/mmp2_defconfig
+++ b/arch/arm/configs/mmp2_defconfig
@@ -44,8 +44,9 @@ CONFIG_SMC91X=y
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/pcm027_defconfig b/arch/arm/configs/pcm027_defconfig
index 2f136c3..1280128 100644
--- a/arch/arm/configs/pcm027_defconfig
+++ b/arch/arm/configs/pcm027_defconfig
@@ -60,8 +60,9 @@ CONFIG_SMC91X=y
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/pxa168_defconfig b/arch/arm/configs/pxa168_defconfig
index 74d7e01..1668dac 100644
--- a/arch/arm/configs/pxa168_defconfig
+++ b/arch/arm/configs/pxa168_defconfig
@@ -40,8 +40,9 @@ CONFIG_SMC91X=y
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 # CONFIG_HWMON is not set
diff --git a/arch/arm/configs/pxa255-idp_defconfig b/arch/arm/configs/pxa255-idp_defconfig
index 917a070..399a706 100644
--- a/arch/arm/configs/pxa255-idp_defconfig
+++ b/arch/arm/configs/pxa255-idp_defconfig
@@ -35,8 +35,9 @@ CONFIG_SMC91X=y
 CONFIG_INPUT_EVDEV=y
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_FB=y
 CONFIG_FB_PXA=y
 # CONFIG_VGA_CONSOLE is not set
diff --git a/arch/arm/configs/pxa3xx_defconfig b/arch/arm/configs/pxa3xx_defconfig
index 60e3138..7c3e052 100644
--- a/arch/arm/configs/pxa3xx_defconfig
+++ b/arch/arm/configs/pxa3xx_defconfig
@@ -56,8 +56,9 @@ CONFIG_KEYBOARD_PXA27x=y
 CONFIG_KEYBOARD_PXA930_ROTARY=y
 CONFIG_MOUSE_PXA930_TRKBALL=y
 CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/pxa910_defconfig b/arch/arm/configs/pxa910_defconfig
index 3bb7771..cdacfcb 100644
--- a/arch/arm/configs/pxa910_defconfig
+++ b/arch/arm/configs/pxa910_defconfig
@@ -40,8 +40,9 @@ CONFIG_SMC91X=y
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_SPI=y
 CONFIG_FB=y
 CONFIG_MMP_DISP=y
diff --git a/arch/arm/configs/raumfeld_defconfig b/arch/arm/configs/raumfeld_defconfig
index f7caa90..f1e16f2 100644
--- a/arch/arm/configs/raumfeld_defconfig
+++ b/arch/arm/configs/raumfeld_defconfig
@@ -67,8 +67,9 @@ CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_TOUCHSCREEN_EETI=m
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_GPIO_ROTARY_ENCODER=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_HW_RANDOM=y
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
diff --git a/arch/arm/configs/spitz_defconfig b/arch/arm/configs/spitz_defconfig
index 2e0419d..b6efcf5 100644
--- a/arch/arm/configs/spitz_defconfig
+++ b/arch/arm/configs/spitz_defconfig
@@ -128,10 +128,10 @@ CONFIG_TOUCHSCREEN_ADS7846=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=m
 # CONFIG_SERIO is not set
-CONFIG_SERIAL_8250=m
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_CS=m
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 CONFIG_SPI=y
 CONFIG_SPI_PXA2XX=y
diff --git a/arch/arm/configs/trizeps4_defconfig b/arch/arm/configs/trizeps4_defconfig
index 3162173..453c79c 100644
--- a/arch/arm/configs/trizeps4_defconfig
+++ b/arch/arm/configs/trizeps4_defconfig
@@ -132,8 +132,9 @@ CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=m
 CONFIG_SERIO_LIBPS2=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_HW_RANDOM=y
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
diff --git a/arch/arm/configs/viper_defconfig b/arch/arm/configs/viper_defconfig
index d36e0d3..4efac06 100644
--- a/arch/arm/configs/viper_defconfig
+++ b/arch/arm/configs/viper_defconfig
@@ -101,11 +101,11 @@ CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=m
 # CONFIG_CONSOLE_TRANSLATIONS is not set
 # CONFIG_VT_CONSOLE is not set
-CONFIG_SERIAL_8250=m
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_NR_UARTS=5
 CONFIG_SERIAL_8250_RUNTIME_UARTS=5
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
diff --git a/arch/arm/configs/xcep_defconfig b/arch/arm/configs/xcep_defconfig
index 721832f..b67aeaf 100644
--- a/arch/arm/configs/xcep_defconfig
+++ b/arch/arm/configs/xcep_defconfig
@@ -60,8 +60,9 @@ CONFIG_NET_ETHERNET=y
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
 # CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=m
diff --git a/drivers/tty/serial/8250/8250_pxa.c b/drivers/tty/serial/8250/8250_pxa.c
new file mode 100644
index 0000000..0da0d40
--- /dev/null
+++ b/drivers/tty/serial/8250/8250_pxa.c
@@ -0,0 +1,178 @@
+/*
+ *  drivers/tty/serial/8250/8250_pxa.c -- driver for PXA on-board UARTS
+ *  Copyright:	(C) 2013 Sergei Ianovich <ynvich@gmail.com>
+ *
+ *  replaces drivers/serial/pxa.c by Nicolas Pitre
+ *  Created:	Feb 20, 2003
+ *  Copyright:	(C) 2003 Monta Vista Software, Inc.
+ *
+ *  Based on drivers/serial/8250.c by Russell King.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/serial_8250.h>
+#include <linux/serial_core.h>
+#include <linux/serial_reg.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
+#include <linux/pm_runtime.h>
+
+#include "8250.h"
+
+struct pxa8250_data {
+	int			line;
+	struct clk		*clk;
+};
+
+#ifdef CONFIG_PM
+static int serial_pxa_suspend(struct device *dev)
+{
+	struct pxa8250_data *data = dev_get_drvdata(dev);
+
+	serial8250_suspend_port(data->line);
+
+	return 0;
+}
+
+static int serial_pxa_resume(struct device *dev)
+{
+	struct pxa8250_data *data = dev_get_drvdata(dev);
+
+	serial8250_resume_port(data->line);
+
+	return 0;
+}
+#endif
+
+static const struct dev_pm_ops serial_pxa_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(serial_pxa_suspend, serial_pxa_resume)
+};
+
+static struct of_device_id serial_pxa_dt_ids[] = {
+	{ .compatible = "mrvl,pxa-uart", },
+	{ .compatible = "mrvl,mmp-uart", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, serial_pxa_dt_ids);
+
+/* Uart divisor latch write */
+static void serial_pxa_dl_write(struct uart_8250_port *up, int value)
+{
+	unsigned int dll;
+
+	serial_out(up, UART_DLL, value & 0xff);
+	/*
+	 * work around Erratum #74 according to Marvel(R) PXA270M Processor
+	 * Specification Update (April 19, 2010)
+	 */
+	dll = serial_in(up, UART_DLL);
+	WARN_ON(dll != (value & 0xff));
+
+	serial_out(up, UART_DLM, value >> 8 & 0xff);
+}
+
+
+static void serial_pxa_pm(struct uart_port *port, unsigned int state,
+	      unsigned int oldstate)
+{
+	struct pxa8250_data *data = port->private_data;
+
+	if (!state)
+		clk_prepare_enable(data->clk);
+	else
+		clk_disable_unprepare(data->clk);
+}
+
+static int serial_pxa_probe(struct platform_device *pdev)
+{
+	struct uart_8250_port uart = {};
+	struct pxa8250_data *data;
+	struct resource *mmres, *irqres;
+	int ret;
+
+	mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	irqres = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!mmres || !irqres)
+		return -ENODEV;
+
+	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(data->clk))
+		return PTR_ERR(data->clk);
+
+	ret = clk_prepare(data->clk);
+	if (ret)
+		return ret;
+
+	uart.port.type = PORT_XSCALE;
+	uart.port.iotype = UPIO_MEM32;
+	uart.port.mapbase = mmres->start;
+	uart.port.regshift = 2;
+	uart.port.irq = irqres->start;
+	uart.port.fifosize = 64;
+	uart.port.flags = UPF_IOREMAP | UPF_SKIP_TEST;
+	uart.port.dev = &pdev->dev;
+	uart.port.uartclk = clk_get_rate(data->clk);
+	uart.port.pm = serial_pxa_pm;
+	uart.port.private_data = data;
+	uart.dl_write = serial_pxa_dl_write;
+
+	ret = serial8250_register_8250_port(&uart);
+	if (ret < 0)
+		goto err_clk;
+
+	data->line = ret;
+
+	platform_set_drvdata(pdev, data);
+
+	return 0;
+
+ err_clk:
+	clk_unprepare(data->clk);
+	return ret;
+}
+
+static int serial_pxa_remove(struct platform_device *pdev)
+{
+	struct pxa8250_data *data = platform_get_drvdata(pdev);
+
+	serial8250_unregister_port(data->line);
+
+	clk_unprepare(data->clk);
+
+	return 0;
+}
+
+static struct platform_driver serial_pxa_driver = {
+	.probe          = serial_pxa_probe,
+	.remove         = serial_pxa_remove,
+
+	.driver		= {
+		.name	= "pxa2xx-uart",
+		.owner	= THIS_MODULE,
+		.pm	= &serial_pxa_pm_ops,
+		.of_match_table = serial_pxa_dt_ids,
+	},
+};
+
+module_platform_driver(serial_pxa_driver);
+
+MODULE_AUTHOR("Sergei Ianovich");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:pxa2xx-uart");
diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
index 2332991..81bd7c9 100644
--- a/drivers/tty/serial/8250/Kconfig
+++ b/drivers/tty/serial/8250/Kconfig
@@ -302,3 +302,12 @@ config SERIAL_8250_RT288X
 	  If you have a Ralink RT288x/RT305x SoC based board and want to use the
 	  serial port, say Y to this option. The driver can handle up to 2 serial
 	  ports. If unsure, say N.
+
+config SERIAL_PXA
+	tristate "PXA serial port support"
+	depends on SERIAL_8250 && (ARCH_PXA || ARCH_MMP)
+	help
+	  If you have a machine based on an Intel XScale PXA2xx CPU you
+	  can enable its onboard serial ports by enabling this option.
+
+	  If you choose M here, the module name will be 8250_pxa.
diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile
index 36d68d0..b7d1b61 100644
--- a/drivers/tty/serial/8250/Makefile
+++ b/drivers/tty/serial/8250/Makefile
@@ -20,3 +20,4 @@ obj-$(CONFIG_SERIAL_8250_HUB6)		+= 8250_hub6.o
 obj-$(CONFIG_SERIAL_8250_FSL)		+= 8250_fsl.o
 obj-$(CONFIG_SERIAL_8250_DW)		+= 8250_dw.o
 obj-$(CONFIG_SERIAL_8250_EM)		+= 8250_em.o
+obj-$(CONFIG_SERIAL_PXA)		+= 8250_pxa.o
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index 2e6d8dd..da46e31 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -395,29 +395,6 @@ config SERIAL_MPSC_CONSOLE
 	help
 	  Say Y here if you want to support a serial console on a Marvell MPSC.
 
-config SERIAL_PXA
-	bool "PXA serial port support"
-	depends on ARCH_PXA || ARCH_MMP
-	select SERIAL_CORE
-	help
-	  If you have a machine based on an Intel XScale PXA2xx CPU you
-	  can enable its onboard serial ports by enabling this option.
-
-config SERIAL_PXA_CONSOLE
-	bool "Console on PXA serial port"
-	depends on SERIAL_PXA
-	select SERIAL_CORE_CONSOLE
-	help
-	  If you have enabled the serial port on the Intel XScale PXA
-	  CPU you can make it the console by answering Y to this option.
-
-	  Even if you say Y here, the currently visible virtual console
-	  (/dev/tty0) will still be used as the system console by default, but
-	  you can alter that using a kernel command line option such as
-	  "console=ttySA0". (Try "man bootparam" or see the documentation of
-	  your boot loader (lilo or loadlin) about how to pass options to the
-	  kernel at boot time.)
-
 config SERIAL_SA1100
 	bool "SA1100 serial port support"
 	depends on ARCH_SA1100
diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile
index 3680854..fd71d3f 100644
--- a/drivers/tty/serial/Makefile
+++ b/drivers/tty/serial/Makefile
@@ -20,7 +20,6 @@ obj-$(CONFIG_SERIAL_8250) += 8250/
 obj-$(CONFIG_SERIAL_AMBA_PL010) += amba-pl010.o
 obj-$(CONFIG_SERIAL_AMBA_PL011) += amba-pl011.o
 obj-$(CONFIG_SERIAL_CLPS711X) += clps711x.o
-obj-$(CONFIG_SERIAL_PXA) += pxa.o
 obj-$(CONFIG_SERIAL_PNX8XXX) += pnx8xxx_uart.o
 obj-$(CONFIG_SERIAL_SA1100) += sa1100.o
 obj-$(CONFIG_SERIAL_BCM63XX) += bcm63xx_uart.o
diff --git a/drivers/tty/serial/pxa.c b/drivers/tty/serial/pxa.c
deleted file mode 100644
index f9f20f3..0000000
--- a/drivers/tty/serial/pxa.c
+++ /dev/null
@@ -1,971 +0,0 @@
-/*
- *  Based on drivers/serial/8250.c by Russell King.
- *
- *  Author:	Nicolas Pitre
- *  Created:	Feb 20, 2003
- *  Copyright:	(C) 2003 Monta Vista Software, Inc.
- *
- * 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.
- *
- * Note 1: This driver is made separate from the already too overloaded
- * 8250.c because it needs some kirks of its own and that'll make it
- * easier to add DMA support.
- *
- * Note 2: I'm too sick of device allocation policies for serial ports.
- * If someone else wants to request an "official" allocation of major/minor
- * for this driver please be my guest.  And don't forget that new hardware
- * to come from Intel might have more than 3 or 4 of those UARTs.  Let's
- * hope for a better port registration and dynamic device allocation scheme
- * with the serial core maintainer satisfaction to appear soon.
- */
-
-
-#if defined(CONFIG_SERIAL_PXA_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-#define SUPPORT_SYSRQ
-#endif
-
-#include <linux/module.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-#include <linux/console.h>
-#include <linux/sysrq.h>
-#include <linux/serial_reg.h>
-#include <linux/circ_buf.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/of.h>
-#include <linux/platform_device.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/serial_core.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-
-#define PXA_NAME_LEN		8
-
-struct uart_pxa_port {
-	struct uart_port        port;
-	unsigned char           ier;
-	unsigned char           lcr;
-	unsigned char           mcr;
-	unsigned int            lsr_break_flag;
-	struct clk		*clk;
-	char			name[PXA_NAME_LEN];
-};
-
-static inline unsigned int serial_in(struct uart_pxa_port *up, int offset)
-{
-	offset <<= 2;
-	return readl(up->port.membase + offset);
-}
-
-static inline void serial_out(struct uart_pxa_port *up, int offset, int value)
-{
-	offset <<= 2;
-	writel(value, up->port.membase + offset);
-}
-
-static void serial_pxa_enable_ms(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	up->ier |= UART_IER_MSI;
-	serial_out(up, UART_IER, up->ier);
-}
-
-static void serial_pxa_stop_tx(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	if (up->ier & UART_IER_THRI) {
-		up->ier &= ~UART_IER_THRI;
-		serial_out(up, UART_IER, up->ier);
-	}
-}
-
-static void serial_pxa_stop_rx(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	up->ier &= ~UART_IER_RLSI;
-	up->port.read_status_mask &= ~UART_LSR_DR;
-	serial_out(up, UART_IER, up->ier);
-}
-
-static inline void receive_chars(struct uart_pxa_port *up, int *status)
-{
-	unsigned int ch, flag;
-	int max_count = 256;
-
-	do {
-		/* work around Errata #20 according to
-		 * Intel(R) PXA27x Processor Family
-		 * Specification Update (May 2005)
-		 *
-		 * Step 2
-		 * Disable the Reciever Time Out Interrupt via IER[RTOEI]
-		 */
-		up->ier &= ~UART_IER_RTOIE;
-		serial_out(up, UART_IER, up->ier);
-
-		ch = serial_in(up, UART_RX);
-		flag = TTY_NORMAL;
-		up->port.icount.rx++;
-
-		if (unlikely(*status & (UART_LSR_BI | UART_LSR_PE |
-				       UART_LSR_FE | UART_LSR_OE))) {
-			/*
-			 * For statistics only
-			 */
-			if (*status & UART_LSR_BI) {
-				*status &= ~(UART_LSR_FE | UART_LSR_PE);
-				up->port.icount.brk++;
-				/*
-				 * We do the SysRQ and SAK checking
-				 * here because otherwise the break
-				 * may get masked by ignore_status_mask
-				 * or read_status_mask.
-				 */
-				if (uart_handle_break(&up->port))
-					goto ignore_char;
-			} else if (*status & UART_LSR_PE)
-				up->port.icount.parity++;
-			else if (*status & UART_LSR_FE)
-				up->port.icount.frame++;
-			if (*status & UART_LSR_OE)
-				up->port.icount.overrun++;
-
-			/*
-			 * Mask off conditions which should be ignored.
-			 */
-			*status &= up->port.read_status_mask;
-
-#ifdef CONFIG_SERIAL_PXA_CONSOLE
-			if (up->port.line == up->port.cons->index) {
-				/* Recover the break flag from console xmit */
-				*status |= up->lsr_break_flag;
-				up->lsr_break_flag = 0;
-			}
-#endif
-			if (*status & UART_LSR_BI) {
-				flag = TTY_BREAK;
-			} else if (*status & UART_LSR_PE)
-				flag = TTY_PARITY;
-			else if (*status & UART_LSR_FE)
-				flag = TTY_FRAME;
-		}
-
-		if (uart_handle_sysrq_char(&up->port, ch))
-			goto ignore_char;
-
-		uart_insert_char(&up->port, *status, UART_LSR_OE, ch, flag);
-
-	ignore_char:
-		*status = serial_in(up, UART_LSR);
-	} while ((*status & UART_LSR_DR) && (max_count-- > 0));
-	tty_flip_buffer_push(&up->port.state->port);
-
-	/* work around Errata #20 according to
-	 * Intel(R) PXA27x Processor Family
-	 * Specification Update (May 2005)
-	 *
-	 * Step 6:
-	 * No more data in FIFO: Re-enable RTO interrupt via IER[RTOIE]
-	 */
-	up->ier |= UART_IER_RTOIE;
-	serial_out(up, UART_IER, up->ier);
-}
-
-static void transmit_chars(struct uart_pxa_port *up)
-{
-	struct circ_buf *xmit = &up->port.state->xmit;
-	int count;
-
-	if (up->port.x_char) {
-		serial_out(up, UART_TX, up->port.x_char);
-		up->port.icount.tx++;
-		up->port.x_char = 0;
-		return;
-	}
-	if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) {
-		serial_pxa_stop_tx(&up->port);
-		return;
-	}
-
-	count = up->port.fifosize / 2;
-	do {
-		serial_out(up, UART_TX, xmit->buf[xmit->tail]);
-		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
-		up->port.icount.tx++;
-		if (uart_circ_empty(xmit))
-			break;
-	} while (--count > 0);
-
-	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
-		uart_write_wakeup(&up->port);
-
-
-	if (uart_circ_empty(xmit))
-		serial_pxa_stop_tx(&up->port);
-}
-
-static void serial_pxa_start_tx(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	if (!(up->ier & UART_IER_THRI)) {
-		up->ier |= UART_IER_THRI;
-		serial_out(up, UART_IER, up->ier);
-	}
-}
-
-static inline void check_modem_status(struct uart_pxa_port *up)
-{
-	int status;
-
-	status = serial_in(up, UART_MSR);
-
-	if ((status & UART_MSR_ANY_DELTA) == 0)
-		return;
-
-	if (status & UART_MSR_TERI)
-		up->port.icount.rng++;
-	if (status & UART_MSR_DDSR)
-		up->port.icount.dsr++;
-	if (status & UART_MSR_DDCD)
-		uart_handle_dcd_change(&up->port, status & UART_MSR_DCD);
-	if (status & UART_MSR_DCTS)
-		uart_handle_cts_change(&up->port, status & UART_MSR_CTS);
-
-	wake_up_interruptible(&up->port.state->port.delta_msr_wait);
-}
-
-/*
- * This handles the interrupt from one port.
- */
-static inline irqreturn_t serial_pxa_irq(int irq, void *dev_id)
-{
-	struct uart_pxa_port *up = dev_id;
-	unsigned int iir, lsr;
-
-	iir = serial_in(up, UART_IIR);
-	if (iir & UART_IIR_NO_INT)
-		return IRQ_NONE;
-	lsr = serial_in(up, UART_LSR);
-	if (lsr & UART_LSR_DR)
-		receive_chars(up, &lsr);
-	check_modem_status(up);
-	if (lsr & UART_LSR_THRE)
-		transmit_chars(up);
-	return IRQ_HANDLED;
-}
-
-static unsigned int serial_pxa_tx_empty(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned long flags;
-	unsigned int ret;
-
-	spin_lock_irqsave(&up->port.lock, flags);
-	ret = serial_in(up, UART_LSR) & UART_LSR_TEMT ? TIOCSER_TEMT : 0;
-	spin_unlock_irqrestore(&up->port.lock, flags);
-
-	return ret;
-}
-
-static unsigned int serial_pxa_get_mctrl(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned char status;
-	unsigned int ret;
-
-	status = serial_in(up, UART_MSR);
-
-	ret = 0;
-	if (status & UART_MSR_DCD)
-		ret |= TIOCM_CAR;
-	if (status & UART_MSR_RI)
-		ret |= TIOCM_RNG;
-	if (status & UART_MSR_DSR)
-		ret |= TIOCM_DSR;
-	if (status & UART_MSR_CTS)
-		ret |= TIOCM_CTS;
-	return ret;
-}
-
-static void serial_pxa_set_mctrl(struct uart_port *port, unsigned int mctrl)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned char mcr = 0;
-
-	if (mctrl & TIOCM_RTS)
-		mcr |= UART_MCR_RTS;
-	if (mctrl & TIOCM_DTR)
-		mcr |= UART_MCR_DTR;
-	if (mctrl & TIOCM_OUT1)
-		mcr |= UART_MCR_OUT1;
-	if (mctrl & TIOCM_OUT2)
-		mcr |= UART_MCR_OUT2;
-	if (mctrl & TIOCM_LOOP)
-		mcr |= UART_MCR_LOOP;
-
-	mcr |= up->mcr;
-
-	serial_out(up, UART_MCR, mcr);
-}
-
-static void serial_pxa_break_ctl(struct uart_port *port, int break_state)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned long flags;
-
-	spin_lock_irqsave(&up->port.lock, flags);
-	if (break_state == -1)
-		up->lcr |= UART_LCR_SBC;
-	else
-		up->lcr &= ~UART_LCR_SBC;
-	serial_out(up, UART_LCR, up->lcr);
-	spin_unlock_irqrestore(&up->port.lock, flags);
-}
-
-static int serial_pxa_startup(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned long flags;
-	int retval;
-
-	if (port->line == 3) /* HWUART */
-		up->mcr |= UART_MCR_AFE;
-	else
-		up->mcr = 0;
-
-	up->port.uartclk = clk_get_rate(up->clk);
-
-	/*
-	 * Allocate the IRQ
-	 */
-	retval = request_irq(up->port.irq, serial_pxa_irq, 0, up->name, up);
-	if (retval)
-		return retval;
-
-	/*
-	 * Clear the FIFO buffers and disable them.
-	 * (they will be reenabled in set_termios())
-	 */
-	serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO);
-	serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO |
-			UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
-	serial_out(up, UART_FCR, 0);
-
-	/*
-	 * Clear the interrupt registers.
-	 */
-	(void) serial_in(up, UART_LSR);
-	(void) serial_in(up, UART_RX);
-	(void) serial_in(up, UART_IIR);
-	(void) serial_in(up, UART_MSR);
-
-	/*
-	 * Now, initialize the UART
-	 */
-	serial_out(up, UART_LCR, UART_LCR_WLEN8);
-
-	spin_lock_irqsave(&up->port.lock, flags);
-	up->port.mctrl |= TIOCM_OUT2;
-	serial_pxa_set_mctrl(&up->port, up->port.mctrl);
-	spin_unlock_irqrestore(&up->port.lock, flags);
-
-	/*
-	 * Finally, enable interrupts.  Note: Modem status interrupts
-	 * are set via set_termios(), which will be occurring imminently
-	 * anyway, so we don't enable them here.
-	 */
-	up->ier = UART_IER_RLSI | UART_IER_RDI | UART_IER_RTOIE | UART_IER_UUE;
-	serial_out(up, UART_IER, up->ier);
-
-	/*
-	 * And clear the interrupt registers again for luck.
-	 */
-	(void) serial_in(up, UART_LSR);
-	(void) serial_in(up, UART_RX);
-	(void) serial_in(up, UART_IIR);
-	(void) serial_in(up, UART_MSR);
-
-	return 0;
-}
-
-static void serial_pxa_shutdown(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned long flags;
-
-	free_irq(up->port.irq, up);
-
-	/*
-	 * Disable interrupts from this port
-	 */
-	up->ier = 0;
-	serial_out(up, UART_IER, 0);
-
-	spin_lock_irqsave(&up->port.lock, flags);
-	up->port.mctrl &= ~TIOCM_OUT2;
-	serial_pxa_set_mctrl(&up->port, up->port.mctrl);
-	spin_unlock_irqrestore(&up->port.lock, flags);
-
-	/*
-	 * Disable break condition and FIFOs
-	 */
-	serial_out(up, UART_LCR, serial_in(up, UART_LCR) & ~UART_LCR_SBC);
-	serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO |
-				  UART_FCR_CLEAR_RCVR |
-				  UART_FCR_CLEAR_XMIT);
-	serial_out(up, UART_FCR, 0);
-}
-
-static void
-serial_pxa_set_termios(struct uart_port *port, struct ktermios *termios,
-		       struct ktermios *old)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned char cval, fcr = 0;
-	unsigned long flags;
-	unsigned int baud, quot;
-	unsigned int dll;
-
-	switch (termios->c_cflag & CSIZE) {
-	case CS5:
-		cval = UART_LCR_WLEN5;
-		break;
-	case CS6:
-		cval = UART_LCR_WLEN6;
-		break;
-	case CS7:
-		cval = UART_LCR_WLEN7;
-		break;
-	default:
-	case CS8:
-		cval = UART_LCR_WLEN8;
-		break;
-	}
-
-	if (termios->c_cflag & CSTOPB)
-		cval |= UART_LCR_STOP;
-	if (termios->c_cflag & PARENB)
-		cval |= UART_LCR_PARITY;
-	if (!(termios->c_cflag & PARODD))
-		cval |= UART_LCR_EPAR;
-
-	/*
-	 * Ask the core to calculate the divisor for us.
-	 */
-	baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
-	quot = uart_get_divisor(port, baud);
-
-	if ((up->port.uartclk / quot) < (2400 * 16))
-		fcr = UART_FCR_ENABLE_FIFO | UART_FCR_PXAR1;
-	else if ((up->port.uartclk / quot) < (230400 * 16))
-		fcr = UART_FCR_ENABLE_FIFO | UART_FCR_PXAR8;
-	else
-		fcr = UART_FCR_ENABLE_FIFO | UART_FCR_PXAR32;
-
-	/*
-	 * Ok, we're now changing the port state.  Do it with
-	 * interrupts disabled.
-	 */
-	spin_lock_irqsave(&up->port.lock, flags);
-
-	/*
-	 * Ensure the port will be enabled.
-	 * This is required especially for serial console.
-	 */
-	up->ier |= UART_IER_UUE;
-
-	/*
-	 * Update the per-port timeout.
-	 */
-	uart_update_timeout(port, termios->c_cflag, baud);
-
-	up->port.read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;
-	if (termios->c_iflag & INPCK)
-		up->port.read_status_mask |= UART_LSR_FE | UART_LSR_PE;
-	if (termios->c_iflag & (BRKINT | PARMRK))
-		up->port.read_status_mask |= UART_LSR_BI;
-
-	/*
-	 * Characters to ignore
-	 */
-	up->port.ignore_status_mask = 0;
-	if (termios->c_iflag & IGNPAR)
-		up->port.ignore_status_mask |= UART_LSR_PE | UART_LSR_FE;
-	if (termios->c_iflag & IGNBRK) {
-		up->port.ignore_status_mask |= UART_LSR_BI;
-		/*
-		 * If we're ignoring parity and break indicators,
-		 * ignore overruns too (for real raw support).
-		 */
-		if (termios->c_iflag & IGNPAR)
-			up->port.ignore_status_mask |= UART_LSR_OE;
-	}
-
-	/*
-	 * ignore all characters if CREAD is not set
-	 */
-	if ((termios->c_cflag & CREAD) == 0)
-		up->port.ignore_status_mask |= UART_LSR_DR;
-
-	/*
-	 * CTS flow control flag and modem status interrupts
-	 */
-	up->ier &= ~UART_IER_MSI;
-	if (UART_ENABLE_MS(&up->port, termios->c_cflag))
-		up->ier |= UART_IER_MSI;
-
-	serial_out(up, UART_IER, up->ier);
-
-	if (termios->c_cflag & CRTSCTS)
-		up->mcr |= UART_MCR_AFE;
-	else
-		up->mcr &= ~UART_MCR_AFE;
-
-	serial_out(up, UART_LCR, cval | UART_LCR_DLAB);	/* set DLAB */
-	serial_out(up, UART_DLL, quot & 0xff);		/* LS of divisor */
-
-	/*
-	 * work around Errata #75 according to Intel(R) PXA27x Processor Family
-	 * Specification Update (Nov 2005)
-	 */
-	dll = serial_in(up, UART_DLL);
-	WARN_ON(dll != (quot & 0xff));
-
-	serial_out(up, UART_DLM, quot >> 8);		/* MS of divisor */
-	serial_out(up, UART_LCR, cval);			/* reset DLAB */
-	up->lcr = cval;					/* Save LCR */
-	serial_pxa_set_mctrl(&up->port, up->port.mctrl);
-	serial_out(up, UART_FCR, fcr);
-	spin_unlock_irqrestore(&up->port.lock, flags);
-}
-
-static void
-serial_pxa_pm(struct uart_port *port, unsigned int state,
-	      unsigned int oldstate)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	if (!state)
-		clk_prepare_enable(up->clk);
-	else
-		clk_disable_unprepare(up->clk);
-}
-
-static void serial_pxa_release_port(struct uart_port *port)
-{
-}
-
-static int serial_pxa_request_port(struct uart_port *port)
-{
-	return 0;
-}
-
-static void serial_pxa_config_port(struct uart_port *port, int flags)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	up->port.type = PORT_PXA;
-}
-
-static int
-serial_pxa_verify_port(struct uart_port *port, struct serial_struct *ser)
-{
-	/* we don't want the core code to modify any port params */
-	return -EINVAL;
-}
-
-static const char *
-serial_pxa_type(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	return up->name;
-}
-
-static struct uart_pxa_port *serial_pxa_ports[4];
-static struct uart_driver serial_pxa_reg;
-
-#ifdef CONFIG_SERIAL_PXA_CONSOLE
-
-#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
-
-/*
- *	Wait for transmitter & holding register to empty
- */
-static inline void wait_for_xmitr(struct uart_pxa_port *up)
-{
-	unsigned int status, tmout = 10000;
-
-	/* Wait up to 10ms for the character(s) to be sent. */
-	do {
-		status = serial_in(up, UART_LSR);
-
-		if (status & UART_LSR_BI)
-			up->lsr_break_flag = UART_LSR_BI;
-
-		if (--tmout == 0)
-			break;
-		udelay(1);
-	} while ((status & BOTH_EMPTY) != BOTH_EMPTY);
-
-	/* Wait up to 1s for flow control if necessary */
-	if (up->port.flags & UPF_CONS_FLOW) {
-		tmout = 1000000;
-		while (--tmout &&
-		       ((serial_in(up, UART_MSR) & UART_MSR_CTS) == 0))
-			udelay(1);
-	}
-}
-
-static void serial_pxa_console_putchar(struct uart_port *port, int ch)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	wait_for_xmitr(up);
-	serial_out(up, UART_TX, ch);
-}
-
-/*
- * Print a string to the serial port trying not to disturb
- * any possible real use of the port...
- *
- *	The console_lock must be held when we get here.
- */
-static void
-serial_pxa_console_write(struct console *co, const char *s, unsigned int count)
-{
-	struct uart_pxa_port *up = serial_pxa_ports[co->index];
-	unsigned int ier;
-	unsigned long flags;
-	int locked = 1;
-
-	clk_enable(up->clk);
-	local_irq_save(flags);
-	if (up->port.sysrq)
-		locked = 0;
-	else if (oops_in_progress)
-		locked = spin_trylock(&up->port.lock);
-	else
-		spin_lock(&up->port.lock);
-
-	/*
-	 *	First save the IER then disable the interrupts
-	 */
-	ier = serial_in(up, UART_IER);
-	serial_out(up, UART_IER, UART_IER_UUE);
-
-	uart_console_write(&up->port, s, count, serial_pxa_console_putchar);
-
-	/*
-	 *	Finally, wait for transmitter to become empty
-	 *	and restore the IER
-	 */
-	wait_for_xmitr(up);
-	serial_out(up, UART_IER, ier);
-
-	if (locked)
-		spin_unlock(&up->port.lock);
-	local_irq_restore(flags);
-	clk_disable(up->clk);
-
-}
-
-#ifdef CONFIG_CONSOLE_POLL
-/*
- * Console polling routines for writing and reading from the uart while
- * in an interrupt or debug context.
- */
-
-static int serial_pxa_get_poll_char(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned char lsr = serial_in(up, UART_LSR);
-
-	while (!(lsr & UART_LSR_DR))
-		lsr = serial_in(up, UART_LSR);
-
-	return serial_in(up, UART_RX);
-}
-
-
-static void serial_pxa_put_poll_char(struct uart_port *port,
-			 unsigned char c)
-{
-	unsigned int ier;
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	/*
-	 *	First save the IER then disable the interrupts
-	 */
-	ier = serial_in(up, UART_IER);
-	serial_out(up, UART_IER, UART_IER_UUE);
-
-	wait_for_xmitr(up);
-	/*
-	 *	Send the character out.
-	 *	If a LF, also do CR...
-	 */
-	serial_out(up, UART_TX, c);
-	if (c == 10) {
-		wait_for_xmitr(up);
-		serial_out(up, UART_TX, 13);
-	}
-
-	/*
-	 *	Finally, wait for transmitter to become empty
-	 *	and restore the IER
-	 */
-	wait_for_xmitr(up);
-	serial_out(up, UART_IER, ier);
-}
-
-#endif /* CONFIG_CONSOLE_POLL */
-
-static int __init
-serial_pxa_console_setup(struct console *co, char *options)
-{
-	struct uart_pxa_port *up;
-	int baud = 9600;
-	int bits = 8;
-	int parity = 'n';
-	int flow = 'n';
-
-	if (co->index == -1 || co->index >= serial_pxa_reg.nr)
-		co->index = 0;
-	up = serial_pxa_ports[co->index];
-	if (!up)
-		return -ENODEV;
-
-	if (options)
-		uart_parse_options(options, &baud, &parity, &bits, &flow);
-
-	return uart_set_options(&up->port, co, baud, parity, bits, flow);
-}
-
-static struct console serial_pxa_console = {
-	.name		= "ttyS",
-	.write		= serial_pxa_console_write,
-	.device		= uart_console_device,
-	.setup		= serial_pxa_console_setup,
-	.flags		= CON_PRINTBUFFER,
-	.index		= -1,
-	.data		= &serial_pxa_reg,
-};
-
-#define PXA_CONSOLE	&serial_pxa_console
-#else
-#define PXA_CONSOLE	NULL
-#endif
-
-static struct uart_ops serial_pxa_pops = {
-	.tx_empty	= serial_pxa_tx_empty,
-	.set_mctrl	= serial_pxa_set_mctrl,
-	.get_mctrl	= serial_pxa_get_mctrl,
-	.stop_tx	= serial_pxa_stop_tx,
-	.start_tx	= serial_pxa_start_tx,
-	.stop_rx	= serial_pxa_stop_rx,
-	.enable_ms	= serial_pxa_enable_ms,
-	.break_ctl	= serial_pxa_break_ctl,
-	.startup	= serial_pxa_startup,
-	.shutdown	= serial_pxa_shutdown,
-	.set_termios	= serial_pxa_set_termios,
-	.pm		= serial_pxa_pm,
-	.type		= serial_pxa_type,
-	.release_port	= serial_pxa_release_port,
-	.request_port	= serial_pxa_request_port,
-	.config_port	= serial_pxa_config_port,
-	.verify_port	= serial_pxa_verify_port,
-#ifdef CONFIG_CONSOLE_POLL
-	.poll_get_char = serial_pxa_get_poll_char,
-	.poll_put_char = serial_pxa_put_poll_char,
-#endif
-};
-
-static struct uart_driver serial_pxa_reg = {
-	.owner		= THIS_MODULE,
-	.driver_name	= "PXA serial",
-	.dev_name	= "ttyS",
-	.major		= TTY_MAJOR,
-	.minor		= 64,
-	.nr		= 4,
-	.cons		= PXA_CONSOLE,
-};
-
-#ifdef CONFIG_PM
-static int serial_pxa_suspend(struct device *dev)
-{
-        struct uart_pxa_port *sport = dev_get_drvdata(dev);
-
-        if (sport)
-                uart_suspend_port(&serial_pxa_reg, &sport->port);
-
-        return 0;
-}
-
-static int serial_pxa_resume(struct device *dev)
-{
-        struct uart_pxa_port *sport = dev_get_drvdata(dev);
-
-        if (sport)
-                uart_resume_port(&serial_pxa_reg, &sport->port);
-
-        return 0;
-}
-
-static const struct dev_pm_ops serial_pxa_pm_ops = {
-	.suspend	= serial_pxa_suspend,
-	.resume		= serial_pxa_resume,
-};
-#endif
-
-static struct of_device_id serial_pxa_dt_ids[] = {
-	{ .compatible = "mrvl,pxa-uart", },
-	{ .compatible = "mrvl,mmp-uart", },
-	{}
-};
-MODULE_DEVICE_TABLE(of, serial_pxa_dt_ids);
-
-static int serial_pxa_probe_dt(struct platform_device *pdev,
-			       struct uart_pxa_port *sport)
-{
-	struct device_node *np = pdev->dev.of_node;
-	int ret;
-
-	if (!np)
-		return 1;
-
-	ret = of_alias_get_id(np, "serial");
-	if (ret < 0) {
-		dev_err(&pdev->dev, "failed to get alias id, errno %d\n", ret);
-		return ret;
-	}
-	sport->port.line = ret;
-	return 0;
-}
-
-static int serial_pxa_probe(struct platform_device *dev)
-{
-	struct uart_pxa_port *sport;
-	struct resource *mmres, *irqres;
-	int ret;
-
-	mmres = platform_get_resource(dev, IORESOURCE_MEM, 0);
-	irqres = platform_get_resource(dev, IORESOURCE_IRQ, 0);
-	if (!mmres || !irqres)
-		return -ENODEV;
-
-	sport = kzalloc(sizeof(struct uart_pxa_port), GFP_KERNEL);
-	if (!sport)
-		return -ENOMEM;
-
-	sport->clk = clk_get(&dev->dev, NULL);
-	if (IS_ERR(sport->clk)) {
-		ret = PTR_ERR(sport->clk);
-		goto err_free;
-	}
-
-	ret = clk_prepare(sport->clk);
-	if (ret) {
-		clk_put(sport->clk);
-		goto err_free;
-	}
-
-	sport->port.type = PORT_PXA;
-	sport->port.iotype = UPIO_MEM;
-	sport->port.mapbase = mmres->start;
-	sport->port.irq = irqres->start;
-	sport->port.fifosize = 64;
-	sport->port.ops = &serial_pxa_pops;
-	sport->port.dev = &dev->dev;
-	sport->port.flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF;
-	sport->port.uartclk = clk_get_rate(sport->clk);
-
-	ret = serial_pxa_probe_dt(dev, sport);
-	if (ret > 0)
-		sport->port.line = dev->id;
-	else if (ret < 0)
-		goto err_clk;
-	snprintf(sport->name, PXA_NAME_LEN - 1, "UART%d", sport->port.line + 1);
-
-	sport->port.membase = ioremap(mmres->start, resource_size(mmres));
-	if (!sport->port.membase) {
-		ret = -ENOMEM;
-		goto err_clk;
-	}
-
-	serial_pxa_ports[sport->port.line] = sport;
-
-	uart_add_one_port(&serial_pxa_reg, &sport->port);
-	platform_set_drvdata(dev, sport);
-
-	return 0;
-
- err_clk:
-	clk_unprepare(sport->clk);
-	clk_put(sport->clk);
- err_free:
-	kfree(sport);
-	return ret;
-}
-
-static int serial_pxa_remove(struct platform_device *dev)
-{
-	struct uart_pxa_port *sport = platform_get_drvdata(dev);
-
-	uart_remove_one_port(&serial_pxa_reg, &sport->port);
-
-	clk_unprepare(sport->clk);
-	clk_put(sport->clk);
-	kfree(sport);
-
-	return 0;
-}
-
-static struct platform_driver serial_pxa_driver = {
-        .probe          = serial_pxa_probe,
-        .remove         = serial_pxa_remove,
-
-	.driver		= {
-	        .name	= "pxa2xx-uart",
-		.owner	= THIS_MODULE,
-#ifdef CONFIG_PM
-		.pm	= &serial_pxa_pm_ops,
-#endif
-		.of_match_table = serial_pxa_dt_ids,
-	},
-};
-
-static int __init serial_pxa_init(void)
-{
-	int ret;
-
-	ret = uart_register_driver(&serial_pxa_reg);
-	if (ret != 0)
-		return ret;
-
-	ret = platform_driver_register(&serial_pxa_driver);
-	if (ret != 0)
-		uart_unregister_driver(&serial_pxa_reg);
-
-	return ret;
-}
-
-static void __exit serial_pxa_exit(void)
-{
-	platform_driver_unregister(&serial_pxa_driver);
-	uart_unregister_driver(&serial_pxa_reg);
-}
-
-module_init(serial_pxa_init);
-module_exit(serial_pxa_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:pxa2xx-uart");
-- 
1.8.4.2

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

* [PATCH v4 02/21] ARM: dts: pxa2xx fix compatible strings
  2014-04-16 17:13             ` Sergei Ianovich
  (?)
@ 2014-04-16 17:13               ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2014-04-16 17:13 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Daniel Mack, Haojian Zhuang, Arnd Bergmann,
	Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	Russell King, open list:OPEN FIRMWARE AND...

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Daniel Mack <zonque@gmail.com>
CC: Haojian Zhuang <haojian.zhuang@gmail.com>
CC: Arnd Bergmann <arnd@arndb.de>
---
   v3..v4
   v2..v3
   v1..v2
   * no changes

 arch/arm/boot/dts/pxa2xx.dtsi | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/arch/arm/boot/dts/pxa2xx.dtsi b/arch/arm/boot/dts/pxa2xx.dtsi
index a5e90f0..3419f87 100644
--- a/arch/arm/boot/dts/pxa2xx.dtsi
+++ b/arch/arm/boot/dts/pxa2xx.dtsi
@@ -18,7 +18,6 @@
 		serial1 = &btuart;
 		serial2 = &stuart;
 		serial3 = &hwuart;
-		i2c0 = &pwri2c;
 		i2c1 = &pxai2c1;
 	};
 
@@ -113,14 +112,14 @@
 		};
 
 		usb0: ohci@4c000000 {
-			compatible = "mrvl,pxa-ohci";
+			compatible = "marvell,pxa-ohci";
 			reg = <0x4c000000 0x10000>;
 			interrupts = <3>;
 			status = "disabled";
 		};
 
 		mmc0: mmc@41100000 {
-			compatible = "mrvl,pxa-mmc";
+			compatible = "marvell,pxa-mmc";
 			reg = <0x41100000 0x1000>;
 			interrupts = <23>;
 			status = "disabled";
-- 
1.8.4.2


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

* [PATCH v4 02/21] ARM: dts: pxa2xx fix compatible strings
@ 2014-04-16 17:13               ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2014-04-16 17:13 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Mark Rutland, open list:OPEN FIRMWARE AND...,
	Russell King, Arnd Bergmann, Pawel Moll, Ian Campbell,
	Haojian Zhuang, Daniel Mack, Sergei Ianovich, Rob Herring,
	Kumar Gala

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Daniel Mack <zonque@gmail.com>
CC: Haojian Zhuang <haojian.zhuang@gmail.com>
CC: Arnd Bergmann <arnd@arndb.de>
---
   v3..v4
   v2..v3
   v1..v2
   * no changes

 arch/arm/boot/dts/pxa2xx.dtsi | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/arch/arm/boot/dts/pxa2xx.dtsi b/arch/arm/boot/dts/pxa2xx.dtsi
index a5e90f0..3419f87 100644
--- a/arch/arm/boot/dts/pxa2xx.dtsi
+++ b/arch/arm/boot/dts/pxa2xx.dtsi
@@ -18,7 +18,6 @@
 		serial1 = &btuart;
 		serial2 = &stuart;
 		serial3 = &hwuart;
-		i2c0 = &pwri2c;
 		i2c1 = &pxai2c1;
 	};
 
@@ -113,14 +112,14 @@
 		};
 
 		usb0: ohci@4c000000 {
-			compatible = "mrvl,pxa-ohci";
+			compatible = "marvell,pxa-ohci";
 			reg = <0x4c000000 0x10000>;
 			interrupts = <3>;
 			status = "disabled";
 		};
 
 		mmc0: mmc@41100000 {
-			compatible = "mrvl,pxa-mmc";
+			compatible = "marvell,pxa-mmc";
 			reg = <0x41100000 0x1000>;
 			interrupts = <23>;
 			status = "disabled";
-- 
1.8.4.2

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

* [PATCH v4 02/21] ARM: dts: pxa2xx fix compatible strings
@ 2014-04-16 17:13               ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2014-04-16 17:13 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Daniel Mack <zonque@gmail.com>
CC: Haojian Zhuang <haojian.zhuang@gmail.com>
CC: Arnd Bergmann <arnd@arndb.de>
---
   v3..v4
   v2..v3
   v1..v2
   * no changes

 arch/arm/boot/dts/pxa2xx.dtsi | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/arch/arm/boot/dts/pxa2xx.dtsi b/arch/arm/boot/dts/pxa2xx.dtsi
index a5e90f0..3419f87 100644
--- a/arch/arm/boot/dts/pxa2xx.dtsi
+++ b/arch/arm/boot/dts/pxa2xx.dtsi
@@ -18,7 +18,6 @@
 		serial1 = &btuart;
 		serial2 = &stuart;
 		serial3 = &hwuart;
-		i2c0 = &pwri2c;
 		i2c1 = &pxai2c1;
 	};
 
@@ -113,14 +112,14 @@
 		};
 
 		usb0: ohci at 4c000000 {
-			compatible = "mrvl,pxa-ohci";
+			compatible = "marvell,pxa-ohci";
 			reg = <0x4c000000 0x10000>;
 			interrupts = <3>;
 			status = "disabled";
 		};
 
 		mmc0: mmc at 41100000 {
-			compatible = "mrvl,pxa-mmc";
+			compatible = "marvell,pxa-mmc";
 			reg = <0x41100000 0x1000>;
 			interrupts = <23>;
 			status = "disabled";
-- 
1.8.4.2

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

* [PATCH v4 03/21] ARM: dts: fix pxa27x-gpio interrupts
  2014-04-16 17:13             ` Sergei Ianovich
  (?)
@ 2014-04-16 17:13               ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2014-04-16 17:13 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Daniel Mack, Haojian Zhuang, Arnd Bergmann,
	Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	Russell King, open list:OPEN FIRMWARE AND...

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Daniel Mack <zonque@gmail.com>
CC: Haojian Zhuang <haojian.zhuang@gmail.com>
CC: Arnd Bergmann <arnd@arndb.de>
---
   v3..v4
   v2..v3
   v1..v2
   * no changes

 arch/arm/boot/dts/pxa27x.dtsi | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/arch/arm/boot/dts/pxa27x.dtsi b/arch/arm/boot/dts/pxa27x.dtsi
index a705469..39bed5e 100644
--- a/arch/arm/boot/dts/pxa27x.dtsi
+++ b/arch/arm/boot/dts/pxa27x.dtsi
@@ -34,5 +34,11 @@
 			reg = <0x40c00010 0x10>;
 			#pwm-cells = <1>;
 		};
+
+		gpio: gpio@40e00000 {
+			compatible = "intel,pxa27x-gpio";
+			interrupts = <8>, <9>, <10>;
+			interrupt-names = "gpio0", "gpio1", "gpio_mux";
+		};
 	};
 };
-- 
1.8.4.2


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

* [PATCH v4 03/21] ARM: dts: fix pxa27x-gpio interrupts
@ 2014-04-16 17:13               ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2014-04-16 17:13 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Daniel Mack, Haojian Zhuang, Arnd Bergmann,
	Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	Russell King, open list:OPEN FIRMWARE AND...

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Daniel Mack <zonque@gmail.com>
CC: Haojian Zhuang <haojian.zhuang@gmail.com>
CC: Arnd Bergmann <arnd@arndb.de>
---
   v3..v4
   v2..v3
   v1..v2
   * no changes

 arch/arm/boot/dts/pxa27x.dtsi | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/arch/arm/boot/dts/pxa27x.dtsi b/arch/arm/boot/dts/pxa27x.dtsi
index a705469..39bed5e 100644
--- a/arch/arm/boot/dts/pxa27x.dtsi
+++ b/arch/arm/boot/dts/pxa27x.dtsi
@@ -34,5 +34,11 @@
 			reg = <0x40c00010 0x10>;
 			#pwm-cells = <1>;
 		};
+
+		gpio: gpio@40e00000 {
+			compatible = "intel,pxa27x-gpio";
+			interrupts = <8>, <9>, <10>;
+			interrupt-names = "gpio0", "gpio1", "gpio_mux";
+		};
 	};
 };
-- 
1.8.4.2

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

* [PATCH v4 03/21] ARM: dts: fix pxa27x-gpio interrupts
@ 2014-04-16 17:13               ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2014-04-16 17:13 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Daniel Mack <zonque@gmail.com>
CC: Haojian Zhuang <haojian.zhuang@gmail.com>
CC: Arnd Bergmann <arnd@arndb.de>
---
   v3..v4
   v2..v3
   v1..v2
   * no changes

 arch/arm/boot/dts/pxa27x.dtsi | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/arch/arm/boot/dts/pxa27x.dtsi b/arch/arm/boot/dts/pxa27x.dtsi
index a705469..39bed5e 100644
--- a/arch/arm/boot/dts/pxa27x.dtsi
+++ b/arch/arm/boot/dts/pxa27x.dtsi
@@ -34,5 +34,11 @@
 			reg = <0x40c00010 0x10>;
 			#pwm-cells = <1>;
 		};
+
+		gpio: gpio at 40e00000 {
+			compatible = "intel,pxa27x-gpio";
+			interrupts = <8>, <9>, <10>;
+			interrupt-names = "gpio0", "gpio1", "gpio_mux";
+		};
 	};
 };
-- 
1.8.4.2

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

* [PATCH v4 04/21] ARM: dts: pxa3xx: move declaration to header
  2014-04-16 17:13             ` Sergei Ianovich
@ 2014-04-16 17:13               ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2014-04-16 17:13 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Daniel Mack, Haojian Zhuang, Arnd Bergmann,
	Eric Miao, Russell King

This way it will be more difficult to change the declaration in one
place, but not the other.

In addition, the change allows to use the binding for pxa-gpio on
other PXA CPUs.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Daniel Mack <zonque@gmail.com>
CC: Haojian Zhuang <haojian.zhuang@gmail.com>
CC: Arnd Bergmann <arnd@arndb.de>
---
   v3..v4
   v2..v3
   * no changes

   v1..v2
   * drop #ifdef in header file
   * number changed from 6 to 4 (dropped patches)

 arch/arm/mach-pxa/include/mach/irqs.h | 2 ++
 arch/arm/mach-pxa/pxa3xx.c            | 2 --
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-pxa/include/mach/irqs.h b/arch/arm/mach-pxa/include/mach/irqs.h
index 48c2fd8..732315d 100644
--- a/arch/arm/mach-pxa/include/mach/irqs.h
+++ b/arch/arm/mach-pxa/include/mach/irqs.h
@@ -113,4 +113,6 @@ void ichp_handle_irq(struct pt_regs *);
 void pxa_init_irq(int irq_nr, int (*set_wake)(struct irq_data *, unsigned int));
 #endif
 
+extern void __init pxa_dt_irq_init(int (*fn)(struct irq_data *, unsigned int));
+
 #endif /* __ASM_MACH_IRQS_H */
diff --git a/arch/arm/mach-pxa/pxa3xx.c b/arch/arm/mach-pxa/pxa3xx.c
index 87011f3..2397dec 100644
--- a/arch/arm/mach-pxa/pxa3xx.c
+++ b/arch/arm/mach-pxa/pxa3xx.c
@@ -42,8 +42,6 @@
 #define PECR_IE(n)	((1 << ((n) * 2)) << 28)
 #define PECR_IS(n)	((1 << ((n) * 2)) << 29)
 
-extern void __init pxa_dt_irq_init(int (*fn)(struct irq_data *, unsigned int));
-
 static DEFINE_PXA3_CKEN(pxa3xx_ffuart, FFUART, 14857000, 1);
 static DEFINE_PXA3_CKEN(pxa3xx_btuart, BTUART, 14857000, 1);
 static DEFINE_PXA3_CKEN(pxa3xx_stuart, STUART, 14857000, 1);
-- 
1.8.4.2


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

* [PATCH v4 04/21] ARM: dts: pxa3xx: move declaration to header
@ 2014-04-16 17:13               ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2014-04-16 17:13 UTC (permalink / raw)
  To: linux-arm-kernel

This way it will be more difficult to change the declaration in one
place, but not the other.

In addition, the change allows to use the binding for pxa-gpio on
other PXA CPUs.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Daniel Mack <zonque@gmail.com>
CC: Haojian Zhuang <haojian.zhuang@gmail.com>
CC: Arnd Bergmann <arnd@arndb.de>
---
   v3..v4
   v2..v3
   * no changes

   v1..v2
   * drop #ifdef in header file
   * number changed from 6 to 4 (dropped patches)

 arch/arm/mach-pxa/include/mach/irqs.h | 2 ++
 arch/arm/mach-pxa/pxa3xx.c            | 2 --
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-pxa/include/mach/irqs.h b/arch/arm/mach-pxa/include/mach/irqs.h
index 48c2fd8..732315d 100644
--- a/arch/arm/mach-pxa/include/mach/irqs.h
+++ b/arch/arm/mach-pxa/include/mach/irqs.h
@@ -113,4 +113,6 @@ void ichp_handle_irq(struct pt_regs *);
 void pxa_init_irq(int irq_nr, int (*set_wake)(struct irq_data *, unsigned int));
 #endif
 
+extern void __init pxa_dt_irq_init(int (*fn)(struct irq_data *, unsigned int));
+
 #endif /* __ASM_MACH_IRQS_H */
diff --git a/arch/arm/mach-pxa/pxa3xx.c b/arch/arm/mach-pxa/pxa3xx.c
index 87011f3..2397dec 100644
--- a/arch/arm/mach-pxa/pxa3xx.c
+++ b/arch/arm/mach-pxa/pxa3xx.c
@@ -42,8 +42,6 @@
 #define PECR_IE(n)	((1 << ((n) * 2)) << 28)
 #define PECR_IS(n)	((1 << ((n) * 2)) << 29)
 
-extern void __init pxa_dt_irq_init(int (*fn)(struct irq_data *, unsigned int));
-
 static DEFINE_PXA3_CKEN(pxa3xx_ffuart, FFUART, 14857000, 1);
 static DEFINE_PXA3_CKEN(pxa3xx_btuart, BTUART, 14857000, 1);
 static DEFINE_PXA3_CKEN(pxa3xx_stuart, STUART, 14857000, 1);
-- 
1.8.4.2

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

* [PATCH v4 05/21] ARM: dts: pxa27x: irq init using device tree
  2014-04-16 17:13             ` Sergei Ianovich
@ 2014-04-16 17:13               ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2014-04-16 17:13 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Daniel Mack, Haojian Zhuang, Arnd Bergmann,
	Eric Miao, Russell King

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Daniel Mack <zonque@gmail.com>
CC: Haojian Zhuang <haojian.zhuang@gmail.com>
CC: Arnd Bergmann <arnd@arndb.de>
---
   v3..v4
   v2..v3
   * no changes

   v1..v2
   * use of_have_populated_dt() instead of a static variable
   * drop #ifdef in header file
   * number changed from 8 to 5 (dropped patches)

 arch/arm/mach-pxa/include/mach/pxa27x.h |  1 +
 arch/arm/mach-pxa/pxa27x.c              | 10 ++++++++++
 2 files changed, 11 insertions(+)

diff --git a/arch/arm/mach-pxa/include/mach/pxa27x.h b/arch/arm/mach-pxa/include/mach/pxa27x.h
index 7cff640..34a4d6f 100644
--- a/arch/arm/mach-pxa/include/mach/pxa27x.h
+++ b/arch/arm/mach-pxa/include/mach/pxa27x.h
@@ -23,6 +23,7 @@ extern void __init pxa27x_map_io(void);
 extern void __init pxa27x_init_irq(void);
 extern int __init pxa27x_set_pwrmode(unsigned int mode);
 extern void pxa27x_cpu_pm_enter(suspend_state_t state);
+extern void __init pxa27x_dt_init_irq(void);
 
 #define pxa27x_handle_irq	ichp_handle_irq
 
diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c
index 301471a..c6b54f8 100644
--- a/arch/arm/mach-pxa/pxa27x.c
+++ b/arch/arm/mach-pxa/pxa27x.c
@@ -398,6 +398,13 @@ void __init pxa27x_init_irq(void)
 	pxa_init_irq(34, pxa27x_set_wake);
 }
 
+#ifdef CONFIG_OF
+void __init pxa27x_dt_init_irq(void)
+{
+	pxa_dt_irq_init(pxa27x_set_wake);
+}
+#endif  /* CONFIG_OF */
+
 static struct map_desc pxa27x_io_desc[] __initdata = {
 	{	/* Mem Ctl */
 		.virtual	= (unsigned long)SMEMC_VIRT,
@@ -471,6 +478,9 @@ static int __init pxa27x_init(void)
 		register_syscore_ops(&pxa2xx_mfp_syscore_ops);
 		register_syscore_ops(&pxa2xx_clock_syscore_ops);
 
+		if (of_have_populated_dt())
+			return 0;
+
 		pxa_register_device(&pxa27x_device_gpio, &pxa27x_gpio_info);
 		ret = platform_add_devices(devices, ARRAY_SIZE(devices));
 	}
-- 
1.8.4.2


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

* [PATCH v4 05/21] ARM: dts: pxa27x: irq init using device tree
@ 2014-04-16 17:13               ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2014-04-16 17:13 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Daniel Mack <zonque@gmail.com>
CC: Haojian Zhuang <haojian.zhuang@gmail.com>
CC: Arnd Bergmann <arnd@arndb.de>
---
   v3..v4
   v2..v3
   * no changes

   v1..v2
   * use of_have_populated_dt() instead of a static variable
   * drop #ifdef in header file
   * number changed from 8 to 5 (dropped patches)

 arch/arm/mach-pxa/include/mach/pxa27x.h |  1 +
 arch/arm/mach-pxa/pxa27x.c              | 10 ++++++++++
 2 files changed, 11 insertions(+)

diff --git a/arch/arm/mach-pxa/include/mach/pxa27x.h b/arch/arm/mach-pxa/include/mach/pxa27x.h
index 7cff640..34a4d6f 100644
--- a/arch/arm/mach-pxa/include/mach/pxa27x.h
+++ b/arch/arm/mach-pxa/include/mach/pxa27x.h
@@ -23,6 +23,7 @@ extern void __init pxa27x_map_io(void);
 extern void __init pxa27x_init_irq(void);
 extern int __init pxa27x_set_pwrmode(unsigned int mode);
 extern void pxa27x_cpu_pm_enter(suspend_state_t state);
+extern void __init pxa27x_dt_init_irq(void);
 
 #define pxa27x_handle_irq	ichp_handle_irq
 
diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c
index 301471a..c6b54f8 100644
--- a/arch/arm/mach-pxa/pxa27x.c
+++ b/arch/arm/mach-pxa/pxa27x.c
@@ -398,6 +398,13 @@ void __init pxa27x_init_irq(void)
 	pxa_init_irq(34, pxa27x_set_wake);
 }
 
+#ifdef CONFIG_OF
+void __init pxa27x_dt_init_irq(void)
+{
+	pxa_dt_irq_init(pxa27x_set_wake);
+}
+#endif  /* CONFIG_OF */
+
 static struct map_desc pxa27x_io_desc[] __initdata = {
 	{	/* Mem Ctl */
 		.virtual	= (unsigned long)SMEMC_VIRT,
@@ -471,6 +478,9 @@ static int __init pxa27x_init(void)
 		register_syscore_ops(&pxa2xx_mfp_syscore_ops);
 		register_syscore_ops(&pxa2xx_clock_syscore_ops);
 
+		if (of_have_populated_dt())
+			return 0;
+
 		pxa_register_device(&pxa27x_device_gpio, &pxa27x_gpio_info);
 		ret = platform_add_devices(devices, ARRAY_SIZE(devices));
 	}
-- 
1.8.4.2

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

* [PATCH v4 06/21] ARM: dts: provide DMA config to pxamci on PXA27x
  2014-04-16 17:13             ` Sergei Ianovich
  (?)
@ 2014-04-16 17:13               ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2014-04-16 17:13 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Daniel Mack, Haojian Zhuang, Arnd Bergmann,
	Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	Randy Dunlap, Russell King, open list:OPEN FIRMWARE AND...,
	open list:DOCUMENTATION

Non-dts implementation supply required DMA channel numbers as
IORESOURCE_DMA. We can also get them from the device tree, if it
is present.

This patch updates device tree with the proper dmaengine-based
"marvell,pdma-1.0" DMA.

There is no actual data handling in this patch, because the existing
driver cannot get DMA channel number from dmaengine API. The patch
in the series will provide temporary workaround by manually parsing
node attributes, until Daniel's series is ready to be merged.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Daniel Mack <zonque@gmail.com>
CC: Haojian Zhuang <haojian.zhuang@gmail.com>
CC: Arnd Bergmann <arnd@arndb.de>
---
   v3..v4
   * no changes

   v2..v3
   * split into good (this one) and temporary (PATCH 07/21) parts

   v1..v2
   * add binding for next-gen dma controller
   * use correct dma declararion
   * number changed from 5 to 3

 Documentation/devicetree/bindings/mmc/pxa-mmc.txt |  5 +++++
 arch/arm/boot/dts/pxa27x.dtsi                     | 14 ++++++++++++++
 2 files changed, 19 insertions(+)

diff --git a/Documentation/devicetree/bindings/mmc/pxa-mmc.txt b/Documentation/devicetree/bindings/mmc/pxa-mmc.txt
index b7025de..9f54c69 100644
--- a/Documentation/devicetree/bindings/mmc/pxa-mmc.txt
+++ b/Documentation/devicetree/bindings/mmc/pxa-mmc.txt
@@ -5,6 +5,8 @@ Driver bindings for the PXA MCI (MMC/SDIO) interfaces
 Required properties:
 - compatible: Should be "marvell,pxa-mmc".
 - vmmc-supply: A regulator for VMMC
+- dmas: Should be DMA specifiers for RX and TX
+- dma-names: Should be "rx" and "tx"
 
 Optional properties:
 - marvell,detect-delay-ms: sets the detection delay timeout in ms.
@@ -21,5 +23,8 @@ mmc0: mmc@41100000 {
 	interrupts = <23>;
 	cd-gpios = <&gpio 23 0>;
 	wp-gpios = <&gpio 24 0>;
+	dmas = <&dma 21
+		&dma 22>;
+	dma-names = "rx", "tx";
 };
 
diff --git a/arch/arm/boot/dts/pxa27x.dtsi b/arch/arm/boot/dts/pxa27x.dtsi
index 39bed5e..0150531 100644
--- a/arch/arm/boot/dts/pxa27x.dtsi
+++ b/arch/arm/boot/dts/pxa27x.dtsi
@@ -35,10 +35,24 @@
 			#pwm-cells = <1>;
 		};
 
+		dma: dma-controller@40000000 {
+			compatible = "marvell,pdma-1.0";
+			reg = <0x40000000 0x10000>;
+			interrupts = <25>;
+			#dma-cells = <1>;
+			dma-channels = <32>;
+		};
+
 		gpio: gpio@40e00000 {
 			compatible = "intel,pxa27x-gpio";
 			interrupts = <8>, <9>, <10>;
 			interrupt-names = "gpio0", "gpio1", "gpio_mux";
 		};
+
+		mmc@41100000 {
+			dmas = <&dma 21
+				&dma 22>;
+			dma-names = "rx", "tx";
+		};
 	};
 };
-- 
1.8.4.2


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

* [PATCH v4 06/21] ARM: dts: provide DMA config to pxamci on PXA27x
@ 2014-04-16 17:13               ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2014-04-16 17:13 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Daniel Mack, Haojian Zhuang, Arnd Bergmann,
	Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	Randy Dunlap, Russell King, open list:OPEN FIRMWARE AND...,
	open list:DOCUMENTATION

Non-dts implementation supply required DMA channel numbers as
IORESOURCE_DMA. We can also get them from the device tree, if it
is present.

This patch updates device tree with the proper dmaengine-based
"marvell,pdma-1.0" DMA.

There is no actual data handling in this patch, because the existing
driver cannot get DMA channel number from dmaengine API. The patch
in the series will provide temporary workaround by manually parsing
node attributes, until Daniel's series is ready to be merged.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Daniel Mack <zonque@gmail.com>
CC: Haojian Zhuang <haojian.zhuang@gmail.com>
CC: Arnd Bergmann <arnd@arndb.de>
---
   v3..v4
   * no changes

   v2..v3
   * split into good (this one) and temporary (PATCH 07/21) parts

   v1..v2
   * add binding for next-gen dma controller
   * use correct dma declararion
   * number changed from 5 to 3

 Documentation/devicetree/bindings/mmc/pxa-mmc.txt |  5 +++++
 arch/arm/boot/dts/pxa27x.dtsi                     | 14 ++++++++++++++
 2 files changed, 19 insertions(+)

diff --git a/Documentation/devicetree/bindings/mmc/pxa-mmc.txt b/Documentation/devicetree/bindings/mmc/pxa-mmc.txt
index b7025de..9f54c69 100644
--- a/Documentation/devicetree/bindings/mmc/pxa-mmc.txt
+++ b/Documentation/devicetree/bindings/mmc/pxa-mmc.txt
@@ -5,6 +5,8 @@ Driver bindings for the PXA MCI (MMC/SDIO) interfaces
 Required properties:
 - compatible: Should be "marvell,pxa-mmc".
 - vmmc-supply: A regulator for VMMC
+- dmas: Should be DMA specifiers for RX and TX
+- dma-names: Should be "rx" and "tx"
 
 Optional properties:
 - marvell,detect-delay-ms: sets the detection delay timeout in ms.
@@ -21,5 +23,8 @@ mmc0: mmc@41100000 {
 	interrupts = <23>;
 	cd-gpios = <&gpio 23 0>;
 	wp-gpios = <&gpio 24 0>;
+	dmas = <&dma 21
+		&dma 22>;
+	dma-names = "rx", "tx";
 };
 
diff --git a/arch/arm/boot/dts/pxa27x.dtsi b/arch/arm/boot/dts/pxa27x.dtsi
index 39bed5e..0150531 100644
--- a/arch/arm/boot/dts/pxa27x.dtsi
+++ b/arch/arm/boot/dts/pxa27x.dtsi
@@ -35,10 +35,24 @@
 			#pwm-cells = <1>;
 		};
 
+		dma: dma-controller@40000000 {
+			compatible = "marvell,pdma-1.0";
+			reg = <0x40000000 0x10000>;
+			interrupts = <25>;
+			#dma-cells = <1>;
+			dma-channels = <32>;
+		};
+
 		gpio: gpio@40e00000 {
 			compatible = "intel,pxa27x-gpio";
 			interrupts = <8>, <9>, <10>;
 			interrupt-names = "gpio0", "gpio1", "gpio_mux";
 		};
+
+		mmc@41100000 {
+			dmas = <&dma 21
+				&dma 22>;
+			dma-names = "rx", "tx";
+		};
 	};
 };
-- 
1.8.4.2

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

* [PATCH v4 06/21] ARM: dts: provide DMA config to pxamci on PXA27x
@ 2014-04-16 17:13               ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2014-04-16 17:13 UTC (permalink / raw)
  To: linux-arm-kernel

Non-dts implementation supply required DMA channel numbers as
IORESOURCE_DMA. We can also get them from the device tree, if it
is present.

This patch updates device tree with the proper dmaengine-based
"marvell,pdma-1.0" DMA.

There is no actual data handling in this patch, because the existing
driver cannot get DMA channel number from dmaengine API. The patch
in the series will provide temporary workaround by manually parsing
node attributes, until Daniel's series is ready to be merged.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Daniel Mack <zonque@gmail.com>
CC: Haojian Zhuang <haojian.zhuang@gmail.com>
CC: Arnd Bergmann <arnd@arndb.de>
---
   v3..v4
   * no changes

   v2..v3
   * split into good (this one) and temporary (PATCH 07/21) parts

   v1..v2
   * add binding for next-gen dma controller
   * use correct dma declararion
   * number changed from 5 to 3

 Documentation/devicetree/bindings/mmc/pxa-mmc.txt |  5 +++++
 arch/arm/boot/dts/pxa27x.dtsi                     | 14 ++++++++++++++
 2 files changed, 19 insertions(+)

diff --git a/Documentation/devicetree/bindings/mmc/pxa-mmc.txt b/Documentation/devicetree/bindings/mmc/pxa-mmc.txt
index b7025de..9f54c69 100644
--- a/Documentation/devicetree/bindings/mmc/pxa-mmc.txt
+++ b/Documentation/devicetree/bindings/mmc/pxa-mmc.txt
@@ -5,6 +5,8 @@ Driver bindings for the PXA MCI (MMC/SDIO) interfaces
 Required properties:
 - compatible: Should be "marvell,pxa-mmc".
 - vmmc-supply: A regulator for VMMC
+- dmas: Should be DMA specifiers for RX and TX
+- dma-names: Should be "rx" and "tx"
 
 Optional properties:
 - marvell,detect-delay-ms: sets the detection delay timeout in ms.
@@ -21,5 +23,8 @@ mmc0: mmc at 41100000 {
 	interrupts = <23>;
 	cd-gpios = <&gpio 23 0>;
 	wp-gpios = <&gpio 24 0>;
+	dmas = <&dma 21
+		&dma 22>;
+	dma-names = "rx", "tx";
 };
 
diff --git a/arch/arm/boot/dts/pxa27x.dtsi b/arch/arm/boot/dts/pxa27x.dtsi
index 39bed5e..0150531 100644
--- a/arch/arm/boot/dts/pxa27x.dtsi
+++ b/arch/arm/boot/dts/pxa27x.dtsi
@@ -35,10 +35,24 @@
 			#pwm-cells = <1>;
 		};
 
+		dma: dma-controller at 40000000 {
+			compatible = "marvell,pdma-1.0";
+			reg = <0x40000000 0x10000>;
+			interrupts = <25>;
+			#dma-cells = <1>;
+			dma-channels = <32>;
+		};
+
 		gpio: gpio at 40e00000 {
 			compatible = "intel,pxa27x-gpio";
 			interrupts = <8>, <9>, <10>;
 			interrupt-names = "gpio0", "gpio1", "gpio_mux";
 		};
+
+		mmc at 41100000 {
+			dmas = <&dma 21
+				&dma 22>;
+			dma-names = "rx", "tx";
+		};
 	};
 };
-- 
1.8.4.2

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

* [PATCH v4 07/21] ARM: dts: parse DMA config in pxamci
  2014-04-16 17:13               ` Sergei Ianovich
@ 2014-04-16 17:17                 ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2014-04-16 17:17 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Daniel Mack, Haojian Zhuang, Arnd Bergmann,
	Chris Ball, Ulf Hansson, Jaehoon Chung, Jingoo Han, Mark Brown,
	linux-mmc

The existing PXA MMC driver cannot get DMA channels in a proper
way from the respective device tree binding.

This patch provides temporary workaround which allows using the
existing driver in DT machines by pointing to the proper
dmaengine-based "marvell,pdma-1.0" DMA.

Even though the new DMA provider is not present we can parse device node
attributes manually and use channel numbers to acquire DMA channel
from the existing non-dmaengine provider.

When Daniel's DMA series is merged there will be no need to manually
parse for "dmas" and this patch can be safely reverted.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Daniel Mack <zonque@gmail.com>
CC: Haojian Zhuang <haojian.zhuang@gmail.com>
CC: Arnd Bergmann <arnd@arndb.de>
---
   v3..v4
   * no changes

   v2..v3
   * split into good (PATCH 07/21) and temporary (this one) parts

   v1..v2
   * add binding for next-gen dma controller
   * use correct dma declararion
   * number changed from 5 to 3

 drivers/mmc/host/pxamci.c | 59 ++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 48 insertions(+), 11 deletions(-)

diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c
index 32fe113..6b67764 100644
--- a/drivers/mmc/host/pxamci.c
+++ b/drivers/mmc/host/pxamci.c
@@ -613,11 +613,46 @@ static int pxamci_of_init(struct platform_device *pdev)
 
         return 0;
 }
+
+static int pxamci_of_init_dma(struct platform_device *pdev,
+		struct pxamci_host *host)
+{
+	struct device_node *np = pdev->dev.of_node;
+	u32 tmp;
+	int i;
+	int ret;
+
+	i = of_property_match_string(np, "dma-names", "rx");
+	if (i < 0)
+		return i;
+
+	ret = of_property_read_u32_index(np, "dmas", 2 * i + 1, &tmp);
+	if (ret < 0)
+		return ret;
+	host->dma_drcmrrx = tmp;
+
+	i = of_property_match_string(np, "dma-names", "tx");
+	if (i < 0)
+		return i;
+
+	ret = of_property_read_u32_index(np, "dmas", 2 * i + 1, &tmp);
+	if (ret < 0)
+		return ret;
+	host->dma_drcmrtx = tmp;
+
+	return 0;
+}
 #else
 static int pxamci_of_init(struct platform_device *pdev)
 {
         return 0;
 }
+
+static int pxamci_of_init_dma(struct platform_device *pdev,
+		struct pxamci_host *host)
+{
+	return -ENODATA;
+}
 #endif
 
 static int pxamci_probe(struct platform_device *pdev)
@@ -741,19 +776,21 @@ static int pxamci_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, mmc);
 
-	dmarx = platform_get_resource(pdev, IORESOURCE_DMA, 0);
-	if (!dmarx) {
-		ret = -ENXIO;
-		goto out;
-	}
-	host->dma_drcmrrx = dmarx->start;
+	if (pxamci_of_init_dma(pdev, host) < 0) {
+		dmarx = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+		if (!dmarx) {
+			ret = -ENXIO;
+			goto out;
+		}
+		host->dma_drcmrrx = dmarx->start;
 
-	dmatx = platform_get_resource(pdev, IORESOURCE_DMA, 1);
-	if (!dmatx) {
-		ret = -ENXIO;
-		goto out;
+		dmatx = platform_get_resource(pdev, IORESOURCE_DMA, 1);
+		if (!dmatx) {
+			ret = -ENXIO;
+			goto out;
+		}
+		host->dma_drcmrtx = dmatx->start;
 	}
-	host->dma_drcmrtx = dmatx->start;
 
 	if (host->pdata) {
 		gpio_cd = host->pdata->gpio_card_detect;
-- 
1.8.4.2


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

* [PATCH v4 07/21] ARM: dts: parse DMA config in pxamci
@ 2014-04-16 17:17                 ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2014-04-16 17:17 UTC (permalink / raw)
  To: linux-arm-kernel

The existing PXA MMC driver cannot get DMA channels in a proper
way from the respective device tree binding.

This patch provides temporary workaround which allows using the
existing driver in DT machines by pointing to the proper
dmaengine-based "marvell,pdma-1.0" DMA.

Even though the new DMA provider is not present we can parse device node
attributes manually and use channel numbers to acquire DMA channel
from the existing non-dmaengine provider.

When Daniel's DMA series is merged there will be no need to manually
parse for "dmas" and this patch can be safely reverted.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Daniel Mack <zonque@gmail.com>
CC: Haojian Zhuang <haojian.zhuang@gmail.com>
CC: Arnd Bergmann <arnd@arndb.de>
---
   v3..v4
   * no changes

   v2..v3
   * split into good (PATCH 07/21) and temporary (this one) parts

   v1..v2
   * add binding for next-gen dma controller
   * use correct dma declararion
   * number changed from 5 to 3

 drivers/mmc/host/pxamci.c | 59 ++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 48 insertions(+), 11 deletions(-)

diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c
index 32fe113..6b67764 100644
--- a/drivers/mmc/host/pxamci.c
+++ b/drivers/mmc/host/pxamci.c
@@ -613,11 +613,46 @@ static int pxamci_of_init(struct platform_device *pdev)
 
         return 0;
 }
+
+static int pxamci_of_init_dma(struct platform_device *pdev,
+		struct pxamci_host *host)
+{
+	struct device_node *np = pdev->dev.of_node;
+	u32 tmp;
+	int i;
+	int ret;
+
+	i = of_property_match_string(np, "dma-names", "rx");
+	if (i < 0)
+		return i;
+
+	ret = of_property_read_u32_index(np, "dmas", 2 * i + 1, &tmp);
+	if (ret < 0)
+		return ret;
+	host->dma_drcmrrx = tmp;
+
+	i = of_property_match_string(np, "dma-names", "tx");
+	if (i < 0)
+		return i;
+
+	ret = of_property_read_u32_index(np, "dmas", 2 * i + 1, &tmp);
+	if (ret < 0)
+		return ret;
+	host->dma_drcmrtx = tmp;
+
+	return 0;
+}
 #else
 static int pxamci_of_init(struct platform_device *pdev)
 {
         return 0;
 }
+
+static int pxamci_of_init_dma(struct platform_device *pdev,
+		struct pxamci_host *host)
+{
+	return -ENODATA;
+}
 #endif
 
 static int pxamci_probe(struct platform_device *pdev)
@@ -741,19 +776,21 @@ static int pxamci_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, mmc);
 
-	dmarx = platform_get_resource(pdev, IORESOURCE_DMA, 0);
-	if (!dmarx) {
-		ret = -ENXIO;
-		goto out;
-	}
-	host->dma_drcmrrx = dmarx->start;
+	if (pxamci_of_init_dma(pdev, host) < 0) {
+		dmarx = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+		if (!dmarx) {
+			ret = -ENXIO;
+			goto out;
+		}
+		host->dma_drcmrrx = dmarx->start;
 
-	dmatx = platform_get_resource(pdev, IORESOURCE_DMA, 1);
-	if (!dmatx) {
-		ret = -ENXIO;
-		goto out;
+		dmatx = platform_get_resource(pdev, IORESOURCE_DMA, 1);
+		if (!dmatx) {
+			ret = -ENXIO;
+			goto out;
+		}
+		host->dma_drcmrtx = dmatx->start;
 	}
-	host->dma_drcmrtx = dmatx->start;
 
 	if (host->pdata) {
 		gpio_cd = host->pdata->gpio_card_detect;
-- 
1.8.4.2

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

* [PATCH v4 08/21] ARM: pxa27x: device tree support ICP DAS LP-8x4x
  2014-04-16 17:17                 ` Sergei Ianovich
  (?)
@ 2014-04-16 17:17                   ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2014-04-16 17:17 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Daniel Mack, Arnd Bergmann, Rob Herring,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala, Randy Dunlap,
	Russell King, Eric Miao, Haojian Zhuang, Thierry Reding,
	Florian Vaussard, Jonathan Cameron, Shawn Guo, Andrew Lunn,
	Silvio F, Heikki Krogerus, open list:OPEN FIRMWARE AND...,
	open list:DOCUMENTATION

ICP DAS calls LP-8x4x 'programmable automation controller'. It is
an industrial computer based on PXA270 SoC. They ship it with a 2.6.19
kernel and proprietary kernel module and userspace library to access
its industrial IO.

This patch allows to boot the device with a modern kernel with device
tree. It adds support for:
* MMC card interface on PXA270
* USB 1.1 port on PXA270
* 2 NOR flash devices
* 2 onboard ethernet Davicom DM9000 devices
* 3 serial UART ports on PXA270
* front panel red LED
* 64bit 1-wire system ID chip
* 16 kiB EEPROM (reading)

Support for these devices will be added in separate patches, since
they are not currently supported by the kernel:
* DS1302 RTC
* 512kiB SRAM
* FPGA irq chip
* 3 built-in 16550A serial UART ports
* industrial IO parallel bus
* 10 position rotary switch
* 8 pin DIP switch
* 16 kiB EEPROM (writing)
* serial interface for digital and analog industrial IO modules on
  parallel bus (all I-87... modules)
* digital and analog industrial IO modules for parallel bus:
  ** I-8024 4 port analog output
  ** I-8041 32 port digital output
  ** I-8042 16 port digital output/16 port digital input

Not supported for now:
* VGA interface on PXA270 for lack of dts binding
* the rest of parallel bus (I-8...) modules for lack of hardware
* GPIO reset for lack of relevance (watchdog reset is working)

Newer devices have twice as much flash and a different partition
structure otherwise being the same. When each device is provided
with a correct device tree, all of them can be booted using the
same kernel.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Daniel Mack <zonque@gmail.com>
CC: Arnd Bergmann <arnd@arndb.de>
---
   v3..v4
   * move all declarations to one commit so the first DTB file can be
     used to boot any later kernel as suggested by Arnd Bergmann,
     Heikki Krogerus and Brian Norris
   * support new flavor of device (i105 suffix)

   v2..v3
   * added extbus which maps synchronous, static, and variable-latency
     I/O (VLIO) interfaces of PXA27x SoC as suggested by Arnd Bergmann
   * map is placed into platform include
   * configured existing kernel drivers to support:
     - front panel LED using gpio-leds
     - 64bit 1-wire system ID chip using w1-gpio
     - 16 kiB EEPROM using at24 over i2c-gpio
   * number change (06/16 -> 08/21)

   v1..v2
   * drop left-over extern declaration
   * use of_have_populated_dt() instead of a static variable
   * drop wildcards in compatible
   * drop machine-special machine description
   * number changed from 9 to 6 (dropped patches)

 .../devicetree/bindings/vendor-prefixes.txt        |   1 +
 arch/arm/boot/dts/Makefile                         |   2 +
 arch/arm/boot/dts/pxa27x-lp8x4x-i105.dts           |  43 ++++
 arch/arm/boot/dts/pxa27x-lp8x4x.dts                | 228 +++++++++++++++++++++
 arch/arm/boot/dts/pxa27x.dtsi                      |  17 ++
 arch/arm/configs/lp8x4x_defconfig                  | 168 +++++++++++++++
 arch/arm/mach-pxa/Kconfig                          |  15 ++
 arch/arm/mach-pxa/Makefile                         |   1 +
 arch/arm/mach-pxa/pxa27x-dt.c                      |  64 ++++++
 9 files changed, 539 insertions(+)
 create mode 100644 arch/arm/boot/dts/pxa27x-lp8x4x-i105.dts
 create mode 100644 arch/arm/boot/dts/pxa27x-lp8x4x.dts
 create mode 100644 arch/arm/configs/lp8x4x_defconfig
 create mode 100644 arch/arm/mach-pxa/pxa27x-dt.c

diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index 0f01c9b..1155c6c 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -54,6 +54,7 @@ hisilicon	Hisilicon Limited.
 honeywell	Honeywell
 hp	Hewlett Packard
 ibm	International Business Machines (IBM)
+icpdas	ICP DAS CO., LTD.
 idt	Integrated Device Technologies, Inc.
 img	Imagination Technologies Ltd.
 intel	Intel Corporation
diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index 35c146f..28175d7 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -408,6 +408,8 @@ dtb-$(CONFIG_MACH_DOVE) += dove-cm-a510.dtb \
 	dove-d2plug.dtb \
 	dove-d3plug.dtb \
 	dove-dove-db.dtb
+dtb-$(CONFIG_MACH_PXA27X_DT) += pxa27x-lp8x4x.dtb \
+	pxa27x-lp8x4x-i105.dtb
 
 targets += dtbs dtbs_install
 targets += $(dtb-y)
diff --git a/arch/arm/boot/dts/pxa27x-lp8x4x-i105.dts b/arch/arm/boot/dts/pxa27x-lp8x4x-i105.dts
new file mode 100644
index 0000000..8ddc9f5
--- /dev/null
+++ b/arch/arm/boot/dts/pxa27x-lp8x4x-i105.dts
@@ -0,0 +1,43 @@
+/* Device tree for ICP DAS LP-8x4x i105 flavor */
+
+#include "pxa27x-lp8x4x.dts"
+
+/ {
+	extbus {
+		flash@0 {
+			compatible = "cfi-flash";
+			reg = <0 0 0x04000000>;
+			bank-width = <4>;
+			device-width = <2>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			fs@0 {
+				label = "u-boot";
+				reg = <0 0x40000>;
+			};
+			fs@40000 {
+				label = "settings";
+				reg = <0x40000 0x40000>;
+			};
+			fs@80000 {
+				label = "device_tree";
+				reg = <0x80000 0x40000>;
+			};
+			fs@c0000 {
+				label = "kernel";
+				reg = <0xc0000 0x2c0000>;
+			};
+			fs@300000 {
+				label = "root_fs";
+				reg = <0x380000 0x3c80000>;
+			};
+		};
+
+		flash@1 {
+			compatible = "cfi-flash";
+			reg = <1 0x0 0x02000000>;
+			bank-width = <2>;
+			device-width = <1>;
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/pxa27x-lp8x4x.dts b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
new file mode 100644
index 0000000..38a3e46
--- /dev/null
+++ b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
@@ -0,0 +1,228 @@
+/* Device tree for ICP DAS LP-8x4x */
+/dts-v1/;
+
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include "pxa27x.dtsi"
+
+/ {
+	model = "ICP DAS LP-8x4x programmable automation controller";
+	compatible = "marvell,pxa270";
+
+	aliases {
+		ethernet0 = &eth0;
+		ethernet1 = &eth1;
+	};
+
+	memory {
+		reg = <0xa0000000 0x08000000>;
+	};
+
+	regulators {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		vmmc: regulator@0 {
+			compatible = "regulator-fixed";
+			reg = <0>;
+			regulator-name = "vmmc";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-always-on;
+		};
+	};
+
+	pxabus {
+		pxairq: interrupt-controller@40d00000 {
+			marvell,intc-priority;
+			marvell,intc-nr-irqs = <34>;
+		};
+
+		uart@40100000 {
+			status = "okay";
+		};
+
+		uart@40200000 {
+			status = "okay";
+		};
+
+		uart@40700000 {
+			status = "okay";
+		};
+
+		mmc@41100000 {
+			status = "okay";
+			vmmc-supply = <&vmmc>;
+		};
+
+		ohci@4c000000 {
+			status = "okay";
+			marvell,port-mode = <3>;
+			marvell,oc-mode-perport;
+			marvell,enable-port1;
+		};
+
+		leds {
+			compatible = "gpio-leds";
+
+			status {
+				gpios = <&gpio 84 1>;
+				linux,default-trigger = "heartbeat";
+			};
+		};
+
+		i2c: i2c-gpio {
+			compatible = "i2c-gpio";
+			gpios = <&gpio 22 0 /* sda */
+				 &gpio 12 0 /* scl */>;
+			i2c-gpio,delay-us = <1>;
+			i2c-gpio,timeout-ms = <1>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			eeprom@50 {
+				compatible = "atmel,24c128";
+				reg = <0x50>;
+				pagesize = <64>;
+			};
+		};
+
+		w1: w1-gpio {
+			compatible = "w1-gpio";
+			gpios = <&gpio 83 0>;
+		};
+	};
+
+	extbus {
+		flash@0 {
+			compatible = "cfi-flash";
+			reg = <0 0 0x02000000>;
+			bank-width = <4>;
+			device-width = <2>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			fs@0 {
+				label = "u-boot";
+				reg = <0 0x40000>;
+			};
+			fs@40000 {
+				label = "settings";
+				reg = <0x40000 0x40000>;
+			};
+			fs@80000 {
+				label = "device_tree";
+				reg = <0x80000 0x40000>;
+			};
+			fs@c0000 {
+				label = "kernel";
+				reg = <0xc0000 0x240000>;
+			};
+			fs@300000 {
+				label = "root_fs";
+				reg = <0x300000 0x1d00000>;
+			};
+		};
+
+		flash@1 {
+			compatible = "cfi-flash";
+			reg = <1 0x0 0x01000000>;
+			bank-width = <2>;
+			device-width = <1>;
+		};
+
+		netio@3 {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0 3 0 0x02000000>;
+			interrupt-parent = <&gpio>;
+
+			eth0: eth@0 {
+				compatible = "davicom,dm9000";
+				reg = <0x0 0x2
+				       0x4000 0x2>;
+				interrupts = <9 IRQ_TYPE_EDGE_RISING>;
+				status = "okay";
+			};
+
+			eth1: eth@1000000 {
+				compatible = "davicom,dm9000";
+				reg = <0x1000000 0x2
+				       0x1004000 0x2>;
+				interrupts = <82 IRQ_TYPE_EDGE_RISING>;
+				status = "okay";
+			};
+		};
+
+		fpga@5 {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0 5 0x3000000 0x10000>;
+			interrupt-parent = <&fpgairq>;
+
+			rtc@901c {
+				compatible = "dallas,rtc-ds1302";
+				reg = <0x901c 0x1>;
+				status = "okay";
+			};
+
+			sram@a000 {
+				compatible = "icpdas,sram-lp8x4x";
+				reg = <0xa000 0x1000
+				       0x901e 0x1>;
+			};
+
+			fpgairq: irq@9006 {
+				compatible = "icpdas,irq-lp8x4x";
+				reg = <0x9006 0x16>;
+				interrupt-parent = <&gpio>;
+				interrupts = <3 IRQ_TYPE_EDGE_FALLING>;
+				#interrupt-cells = <1>;
+				interrupt-controller;
+				status = "okay";
+			};
+
+			uart@9050 {
+				compatible = "icpdas,uart-lp8x4x";
+				reg = <0x9050 0x10
+				       0x9030 0x02>;
+				interrupts = <13>;
+				status = "okay";
+			};
+
+			uart@9060 {
+				compatible = "icpdas,uart-lp8x4x";
+				reg = <0x9060 0x10
+				       0x9032 0x02>;
+				interrupts = <14>;
+				status = "okay";
+			};
+
+			uart@9070 {
+				compatible = "icpdas,uart-lp8x4x";
+				reg = <0x9070 0x10
+				       0x9034 0x02>;
+				interrupts = <15>;
+				status = "okay";
+			};
+
+			backplane {
+				compatible = "icpdas,backplane-lp8x4x";
+				reg = <0x0 0x2
+				       0x1000 0x10
+				       0x2000 0x10
+				       0x3000 0x10
+				       0x4000 0x10
+				       0x5000 0x10
+				       0x6000 0x10
+				       0x7000 0x10
+				       0x8000 0x10
+				       0x9002 0x2
+				       0x9004 0x2
+				       0x9046 0x2>;
+				eeprom-gpios = <&gpio 4 0>;
+			};
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/pxa27x.dtsi b/arch/arm/boot/dts/pxa27x.dtsi
index 0150531..1e1c98c 100644
--- a/arch/arm/boot/dts/pxa27x.dtsi
+++ b/arch/arm/boot/dts/pxa27x.dtsi
@@ -55,4 +55,21 @@
 			dma-names = "rx", "tx";
 		};
 	};
+
+	extbus {
+		/*
+		 * PXA27x synchrous, static and
+		 * variable-latency IO interfaces
+		 */
+	        compatible = "simple-bus";
+
+		#address-cells = <2>; /* first cell is nCS, second is address */
+		#size-cells = <1>;
+		ranges = <0 0 0 0x04000000
+			  1 0 0x04000000 0x04000000
+			  2 0 0x08000000 0x04000000
+			  3 0 0x0c000000 0x04000000
+			  4 0 0x10000000 0x04000000
+			  5 0 0x14000000 0x04000000>;
+	};
 };
diff --git a/arch/arm/configs/lp8x4x_defconfig b/arch/arm/configs/lp8x4x_defconfig
new file mode 100644
index 0000000..9f1efb6
--- /dev/null
+++ b/arch/arm/configs/lp8x4x_defconfig
@@ -0,0 +1,168 @@
+# CONFIG_LOCALVERSION_AUTO is not set
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_RCU_BOOST=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_NS is not set
+# CONFIG_IPC_NS is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+# CONFIG_UID16 is not set
+# CONFIG_SHMEM is not set
+CONFIG_EMBEDDED=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_SLOB=y
+CONFIG_JUMP_LABEL=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+# CONFIG_LBDAF is not set
+CONFIG_BLK_CMDLINE_PARSER=y
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_ARCH_PXA=y
+CONFIG_MACH_PXA27X_DT=y
+# CONFIG_ARM_THUMB is not set
+CONFIG_PREEMPT=y
+CONFIG_AEABI=y
+# CONFIG_COMPACTION is not set
+# CONFIG_CROSS_MEMORY_ATTACH is not set
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="init=/sbin/init root=/dev/mmcblk0p1 rw rootfstype=ext4 console=ttyS0,115200 mem=128M rootwait"
+# CONFIG_SUSPEND is not set
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_BRIDGE=m
+CONFIG_BRIDGE_VLAN_FILTERING=y
+CONFIG_VLAN_8021Q=m
+CONFIG_VLAN_8021Q_GVRP=y
+CONFIG_VLAN_8021Q_MVRP=y
+# CONFIG_WIRELESS is not set
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+# CONFIG_FW_LOADER is not set
+CONFIG_MTD=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_CFI_GEOMETRY=y
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_PHYSMAP_OF=y
+CONFIG_PROC_DEVICETREE=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_LOOP_MIN_COUNT=2
+CONFIG_EEPROM_AT24=m
+CONFIG_SCSI=y
+# CONFIG_SCSI_PROC_FS is not set
+CONFIG_BLK_DEV_SD=y
+# CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_NETDEVICES=y
+CONFIG_BONDING=m
+CONFIG_MACVLAN=m
+CONFIG_MACVTAP=m
+CONFIG_TUN=m
+# CONFIG_NET_VENDOR_ARC is not set
+# CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_CIRRUS is not set
+CONFIG_DM9000=y
+CONFIG_DM9000_FORCE_SIMPLE_PHY_POLL=y
+# CONFIG_NET_VENDOR_FARADAY is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+CONFIG_PPP=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPPOE=m
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_SLIP=m
+CONFIG_SLIP_COMPRESSED=y
+# CONFIG_WLAN is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=800
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=600
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_SERIO is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_8250=y
+# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=40
+CONFIG_SERIAL_8250_RUNTIME_UARTS=40
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_PXA=y
+CONFIG_HW_RANDOM=y
+CONFIG_I2C=m
+# CONFIG_I2C_COMPAT is not set
+CONFIG_I2C_GPIO=m
+CONFIG_W1=m
+CONFIG_W1_MASTER_GPIO=m
+CONFIG_W1_SLAVE_SMEM=m
+# CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_SA1100_WATCHDOG=m
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_FB=y
+CONFIG_FB_PXA=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_LOGO=y
+CONFIG_USB=m
+CONFIG_USB_OHCI_HCD=m
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+CONFIG_USB_STORAGE=m
+CONFIG_USB_SERIAL=m
+CONFIG_MMC=y
+CONFIG_MMC_PXA=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_PXA=m
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_EXT2_FS=m
+CONFIG_EXT3_FS=y
+CONFIG_EXT4_FS=y
+CONFIG_REISERFS_FS=m
+CONFIG_ISO9660_FS=m
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_NTFS_FS=m
+CONFIG_NTFS_RW=y
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V4=y
+CONFIG_ROOT_NFS=y
+CONFIG_CIFS=m
+CONFIG_CIFS_STATS=y
+CONFIG_CODA_FS=m
+CONFIG_NLS_DEFAULT="cp855"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_855=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_UTF8=y
+CONFIG_PRINTK_TIME=y
diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig
index e6690a4..fc2e634 100644
--- a/arch/arm/mach-pxa/Kconfig
+++ b/arch/arm/mach-pxa/Kconfig
@@ -4,6 +4,21 @@ menu "Intel PXA2xx/PXA3xx Implementations"
 
 comment "Intel/Marvell Dev Platforms (sorted by hardware release time)"
 
+config MACH_PXA27X_DT
+	bool "Support PXA27x platforms from device tree"
+	select PXA27x
+	select USE_OF
+	help
+	  Include support for Marvell PXA27x based platforms using
+	  the device tree.
+
+	  While MACH_PXA27X_DT when enabled should boot any PXA27x
+	  compatible machine, it still makes sense to select specific
+	  machines. Those options will select required features and
+	  provide per-machine errata workarounds.
+
+	  If unsure, say Y.
+
 config MACH_PXA3XX_DT
 	bool "Support PXA3xx platforms from device tree"
 	select CPU_PXA300
diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile
index 648867a..adaa72a 100644
--- a/arch/arm/mach-pxa/Makefile
+++ b/arch/arm/mach-pxa/Makefile
@@ -20,6 +20,7 @@ obj-$(CONFIG_CPU_PXA930)	+= pxa930.o
 # NOTE: keep the order of boards in accordance to their order in Kconfig
 
 # Device Tree support
+obj-$(CONFIG_MACH_PXA27X_DT)	+= pxa27x-dt.o
 obj-$(CONFIG_MACH_PXA3XX_DT)	+= pxa-dt.o
 
 # Intel/Marvell Dev Platforms
diff --git a/arch/arm/mach-pxa/pxa27x-dt.c b/arch/arm/mach-pxa/pxa27x-dt.c
new file mode 100644
index 0000000..865cf46
--- /dev/null
+++ b/arch/arm/mach-pxa/pxa27x-dt.c
@@ -0,0 +1,64 @@
+/*
+ *  linux/arch/arm/mach-pxa/pxa27x-dt.c
+ *
+ *  Copyright (C) 2013 Sergei Ianovich
+ *
+ *  based mostly on linux/arch/arm/mach-pxa/pxa-dt.c by Daniel Mack
+ *
+ *  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
+ *  publishhed by the Free Software Foundation.
+ */
+
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <asm/io.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <mach/irqs.h>
+#include <mach/pxa27x.h>
+
+#include "generic.h"
+
+#ifdef CONFIG_PXA27x
+static const struct of_dev_auxdata pxa27x_auxdata_lookup[] __initconst = {
+	OF_DEV_AUXDATA("mrvl,pxa-uart",	    0x40100000, "pxa2xx-uart.0", NULL),
+	OF_DEV_AUXDATA("mrvl,pxa-uart",	    0x40200000, "pxa2xx-uart.1", NULL),
+	OF_DEV_AUXDATA("mrvl,pxa-uart",	    0x40700000, "pxa2xx-uart.2", NULL),
+	OF_DEV_AUXDATA("mrvl,pxa-uart",	    0x41600000, "pxa2xx-uart.3", NULL),
+	OF_DEV_AUXDATA("marvell,pxa-mmc",   0x41100000, "pxa2xx-mci.0", NULL),
+	OF_DEV_AUXDATA("intel,pxa27x-gpio", 0x40e00000, "pxa27x-gpio", NULL),
+	OF_DEV_AUXDATA("marvell,pxa-ohci",  0x4c000000, "pxa27x-ohci", NULL),
+	OF_DEV_AUXDATA("mrvl,pxa-i2c",	    0x40301680, "pxa2xx-i2c.0", NULL),
+	{}
+};
+
+static void __init pxa27x_dt_init(void)
+{
+	of_platform_populate(NULL, of_default_bus_match_table,
+			     pxa27x_auxdata_lookup, NULL);
+}
+
+static const char * const pxa27x_dt_board_compat[] __initconst = {
+	"marvell,pxa270",
+	"marvell,pxa271",
+	"marvell,pxa272",
+	NULL,
+};
+
+#endif
+
+#ifdef CONFIG_PXA27x
+DT_MACHINE_START(PXA27X_DT, "Marvell PXA27x (Device Tree Support)")
+	.map_io		= pxa27x_map_io,
+	.init_irq	= pxa27x_dt_init_irq,
+	.handle_irq	= pxa27x_handle_irq,
+	.init_time	= pxa_timer_init,
+	.restart	= pxa_restart,
+	.init_machine	= pxa27x_dt_init,
+	.dt_compat	= pxa27x_dt_board_compat,
+MACHINE_END
+
+#endif
-- 
1.8.4.2


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

* [PATCH v4 08/21] ARM: pxa27x: device tree support ICP DAS LP-8x4x
@ 2014-04-16 17:17                   ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2014-04-16 17:17 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Daniel Mack, Arnd Bergmann, Rob Herring,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala, Randy Dunlap,
	Russell King, Eric Miao, Haojian Zhuang, Thierry Reding,
	Florian Vaussard, Jonathan Cameron, Shawn Guo, Andrew Lunn,
	Silvio F, Heikki Krogerus, open list:OPEN FIRMWARE AND...,
	open list:DOCUMENTATION

ICP DAS calls LP-8x4x 'programmable automation controller'. It is
an industrial computer based on PXA270 SoC. They ship it with a 2.6.19
kernel and proprietary kernel module and userspace library to access
its industrial IO.

This patch allows to boot the device with a modern kernel with device
tree. It adds support for:
* MMC card interface on PXA270
* USB 1.1 port on PXA270
* 2 NOR flash devices
* 2 onboard ethernet Davicom DM9000 devices
* 3 serial UART ports on PXA270
* front panel red LED
* 64bit 1-wire system ID chip
* 16 kiB EEPROM (reading)

Support for these devices will be added in separate patches, since
they are not currently supported by the kernel:
* DS1302 RTC
* 512kiB SRAM
* FPGA irq chip
* 3 built-in 16550A serial UART ports
* industrial IO parallel bus
* 10 position rotary switch
* 8 pin DIP switch
* 16 kiB EEPROM (writing)
* serial interface for digital and analog industrial IO modules on
  parallel bus (all I-87... modules)
* digital and analog industrial IO modules for parallel bus:
  ** I-8024 4 port analog output
  ** I-8041 32 port digital output
  ** I-8042 16 port digital output/16 port digital input

Not supported for now:
* VGA interface on PXA270 for lack of dts binding
* the rest of parallel bus (I-8...) modules for lack of hardware
* GPIO reset for lack of relevance (watchdog reset is working)

Newer devices have twice as much flash and a different partition
structure otherwise being the same. When each device is provided
with a correct device tree, all of them can be booted using the
same kernel.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Daniel Mack <zonque@gmail.com>
CC: Arnd Bergmann <arnd@arndb.de>
---
   v3..v4
   * move all declarations to one commit so the first DTB file can be
     used to boot any later kernel as suggested by Arnd Bergmann,
     Heikki Krogerus and Brian Norris
   * support new flavor of device (i105 suffix)

   v2..v3
   * added extbus which maps synchronous, static, and variable-latency
     I/O (VLIO) interfaces of PXA27x SoC as suggested by Arnd Bergmann
   * map is placed into platform include
   * configured existing kernel drivers to support:
     - front panel LED using gpio-leds
     - 64bit 1-wire system ID chip using w1-gpio
     - 16 kiB EEPROM using at24 over i2c-gpio
   * number change (06/16 -> 08/21)

   v1..v2
   * drop left-over extern declaration
   * use of_have_populated_dt() instead of a static variable
   * drop wildcards in compatible
   * drop machine-special machine description
   * number changed from 9 to 6 (dropped patches)

 .../devicetree/bindings/vendor-prefixes.txt        |   1 +
 arch/arm/boot/dts/Makefile                         |   2 +
 arch/arm/boot/dts/pxa27x-lp8x4x-i105.dts           |  43 ++++
 arch/arm/boot/dts/pxa27x-lp8x4x.dts                | 228 +++++++++++++++++++++
 arch/arm/boot/dts/pxa27x.dtsi                      |  17 ++
 arch/arm/configs/lp8x4x_defconfig                  | 168 +++++++++++++++
 arch/arm/mach-pxa/Kconfig                          |  15 ++
 arch/arm/mach-pxa/Makefile                         |   1 +
 arch/arm/mach-pxa/pxa27x-dt.c                      |  64 ++++++
 9 files changed, 539 insertions(+)
 create mode 100644 arch/arm/boot/dts/pxa27x-lp8x4x-i105.dts
 create mode 100644 arch/arm/boot/dts/pxa27x-lp8x4x.dts
 create mode 100644 arch/arm/configs/lp8x4x_defconfig
 create mode 100644 arch/arm/mach-pxa/pxa27x-dt.c

diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index 0f01c9b..1155c6c 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -54,6 +54,7 @@ hisilicon	Hisilicon Limited.
 honeywell	Honeywell
 hp	Hewlett Packard
 ibm	International Business Machines (IBM)
+icpdas	ICP DAS CO., LTD.
 idt	Integrated Device Technologies, Inc.
 img	Imagination Technologies Ltd.
 intel	Intel Corporation
diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index 35c146f..28175d7 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -408,6 +408,8 @@ dtb-$(CONFIG_MACH_DOVE) += dove-cm-a510.dtb \
 	dove-d2plug.dtb \
 	dove-d3plug.dtb \
 	dove-dove-db.dtb
+dtb-$(CONFIG_MACH_PXA27X_DT) += pxa27x-lp8x4x.dtb \
+	pxa27x-lp8x4x-i105.dtb
 
 targets += dtbs dtbs_install
 targets += $(dtb-y)
diff --git a/arch/arm/boot/dts/pxa27x-lp8x4x-i105.dts b/arch/arm/boot/dts/pxa27x-lp8x4x-i105.dts
new file mode 100644
index 0000000..8ddc9f5
--- /dev/null
+++ b/arch/arm/boot/dts/pxa27x-lp8x4x-i105.dts
@@ -0,0 +1,43 @@
+/* Device tree for ICP DAS LP-8x4x i105 flavor */
+
+#include "pxa27x-lp8x4x.dts"
+
+/ {
+	extbus {
+		flash@0 {
+			compatible = "cfi-flash";
+			reg = <0 0 0x04000000>;
+			bank-width = <4>;
+			device-width = <2>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			fs@0 {
+				label = "u-boot";
+				reg = <0 0x40000>;
+			};
+			fs@40000 {
+				label = "settings";
+				reg = <0x40000 0x40000>;
+			};
+			fs@80000 {
+				label = "device_tree";
+				reg = <0x80000 0x40000>;
+			};
+			fs@c0000 {
+				label = "kernel";
+				reg = <0xc0000 0x2c0000>;
+			};
+			fs@300000 {
+				label = "root_fs";
+				reg = <0x380000 0x3c80000>;
+			};
+		};
+
+		flash@1 {
+			compatible = "cfi-flash";
+			reg = <1 0x0 0x02000000>;
+			bank-width = <2>;
+			device-width = <1>;
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/pxa27x-lp8x4x.dts b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
new file mode 100644
index 0000000..38a3e46
--- /dev/null
+++ b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
@@ -0,0 +1,228 @@
+/* Device tree for ICP DAS LP-8x4x */
+/dts-v1/;
+
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include "pxa27x.dtsi"
+
+/ {
+	model = "ICP DAS LP-8x4x programmable automation controller";
+	compatible = "marvell,pxa270";
+
+	aliases {
+		ethernet0 = &eth0;
+		ethernet1 = &eth1;
+	};
+
+	memory {
+		reg = <0xa0000000 0x08000000>;
+	};
+
+	regulators {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		vmmc: regulator@0 {
+			compatible = "regulator-fixed";
+			reg = <0>;
+			regulator-name = "vmmc";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-always-on;
+		};
+	};
+
+	pxabus {
+		pxairq: interrupt-controller@40d00000 {
+			marvell,intc-priority;
+			marvell,intc-nr-irqs = <34>;
+		};
+
+		uart@40100000 {
+			status = "okay";
+		};
+
+		uart@40200000 {
+			status = "okay";
+		};
+
+		uart@40700000 {
+			status = "okay";
+		};
+
+		mmc@41100000 {
+			status = "okay";
+			vmmc-supply = <&vmmc>;
+		};
+
+		ohci@4c000000 {
+			status = "okay";
+			marvell,port-mode = <3>;
+			marvell,oc-mode-perport;
+			marvell,enable-port1;
+		};
+
+		leds {
+			compatible = "gpio-leds";
+
+			status {
+				gpios = <&gpio 84 1>;
+				linux,default-trigger = "heartbeat";
+			};
+		};
+
+		i2c: i2c-gpio {
+			compatible = "i2c-gpio";
+			gpios = <&gpio 22 0 /* sda */
+				 &gpio 12 0 /* scl */>;
+			i2c-gpio,delay-us = <1>;
+			i2c-gpio,timeout-ms = <1>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			eeprom@50 {
+				compatible = "atmel,24c128";
+				reg = <0x50>;
+				pagesize = <64>;
+			};
+		};
+
+		w1: w1-gpio {
+			compatible = "w1-gpio";
+			gpios = <&gpio 83 0>;
+		};
+	};
+
+	extbus {
+		flash@0 {
+			compatible = "cfi-flash";
+			reg = <0 0 0x02000000>;
+			bank-width = <4>;
+			device-width = <2>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			fs@0 {
+				label = "u-boot";
+				reg = <0 0x40000>;
+			};
+			fs@40000 {
+				label = "settings";
+				reg = <0x40000 0x40000>;
+			};
+			fs@80000 {
+				label = "device_tree";
+				reg = <0x80000 0x40000>;
+			};
+			fs@c0000 {
+				label = "kernel";
+				reg = <0xc0000 0x240000>;
+			};
+			fs@300000 {
+				label = "root_fs";
+				reg = <0x300000 0x1d00000>;
+			};
+		};
+
+		flash@1 {
+			compatible = "cfi-flash";
+			reg = <1 0x0 0x01000000>;
+			bank-width = <2>;
+			device-width = <1>;
+		};
+
+		netio@3 {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0 3 0 0x02000000>;
+			interrupt-parent = <&gpio>;
+
+			eth0: eth@0 {
+				compatible = "davicom,dm9000";
+				reg = <0x0 0x2
+				       0x4000 0x2>;
+				interrupts = <9 IRQ_TYPE_EDGE_RISING>;
+				status = "okay";
+			};
+
+			eth1: eth@1000000 {
+				compatible = "davicom,dm9000";
+				reg = <0x1000000 0x2
+				       0x1004000 0x2>;
+				interrupts = <82 IRQ_TYPE_EDGE_RISING>;
+				status = "okay";
+			};
+		};
+
+		fpga@5 {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0 5 0x3000000 0x10000>;
+			interrupt-parent = <&fpgairq>;
+
+			rtc@901c {
+				compatible = "dallas,rtc-ds1302";
+				reg = <0x901c 0x1>;
+				status = "okay";
+			};
+
+			sram@a000 {
+				compatible = "icpdas,sram-lp8x4x";
+				reg = <0xa000 0x1000
+				       0x901e 0x1>;
+			};
+
+			fpgairq: irq@9006 {
+				compatible = "icpdas,irq-lp8x4x";
+				reg = <0x9006 0x16>;
+				interrupt-parent = <&gpio>;
+				interrupts = <3 IRQ_TYPE_EDGE_FALLING>;
+				#interrupt-cells = <1>;
+				interrupt-controller;
+				status = "okay";
+			};
+
+			uart@9050 {
+				compatible = "icpdas,uart-lp8x4x";
+				reg = <0x9050 0x10
+				       0x9030 0x02>;
+				interrupts = <13>;
+				status = "okay";
+			};
+
+			uart@9060 {
+				compatible = "icpdas,uart-lp8x4x";
+				reg = <0x9060 0x10
+				       0x9032 0x02>;
+				interrupts = <14>;
+				status = "okay";
+			};
+
+			uart@9070 {
+				compatible = "icpdas,uart-lp8x4x";
+				reg = <0x9070 0x10
+				       0x9034 0x02>;
+				interrupts = <15>;
+				status = "okay";
+			};
+
+			backplane {
+				compatible = "icpdas,backplane-lp8x4x";
+				reg = <0x0 0x2
+				       0x1000 0x10
+				       0x2000 0x10
+				       0x3000 0x10
+				       0x4000 0x10
+				       0x5000 0x10
+				       0x6000 0x10
+				       0x7000 0x10
+				       0x8000 0x10
+				       0x9002 0x2
+				       0x9004 0x2
+				       0x9046 0x2>;
+				eeprom-gpios = <&gpio 4 0>;
+			};
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/pxa27x.dtsi b/arch/arm/boot/dts/pxa27x.dtsi
index 0150531..1e1c98c 100644
--- a/arch/arm/boot/dts/pxa27x.dtsi
+++ b/arch/arm/boot/dts/pxa27x.dtsi
@@ -55,4 +55,21 @@
 			dma-names = "rx", "tx";
 		};
 	};
+
+	extbus {
+		/*
+		 * PXA27x synchrous, static and
+		 * variable-latency IO interfaces
+		 */
+	        compatible = "simple-bus";
+
+		#address-cells = <2>; /* first cell is nCS, second is address */
+		#size-cells = <1>;
+		ranges = <0 0 0 0x04000000
+			  1 0 0x04000000 0x04000000
+			  2 0 0x08000000 0x04000000
+			  3 0 0x0c000000 0x04000000
+			  4 0 0x10000000 0x04000000
+			  5 0 0x14000000 0x04000000>;
+	};
 };
diff --git a/arch/arm/configs/lp8x4x_defconfig b/arch/arm/configs/lp8x4x_defconfig
new file mode 100644
index 0000000..9f1efb6
--- /dev/null
+++ b/arch/arm/configs/lp8x4x_defconfig
@@ -0,0 +1,168 @@
+# CONFIG_LOCALVERSION_AUTO is not set
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_RCU_BOOST=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_NS is not set
+# CONFIG_IPC_NS is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+# CONFIG_UID16 is not set
+# CONFIG_SHMEM is not set
+CONFIG_EMBEDDED=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_SLOB=y
+CONFIG_JUMP_LABEL=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+# CONFIG_LBDAF is not set
+CONFIG_BLK_CMDLINE_PARSER=y
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_ARCH_PXA=y
+CONFIG_MACH_PXA27X_DT=y
+# CONFIG_ARM_THUMB is not set
+CONFIG_PREEMPT=y
+CONFIG_AEABI=y
+# CONFIG_COMPACTION is not set
+# CONFIG_CROSS_MEMORY_ATTACH is not set
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="init=/sbin/init root=/dev/mmcblk0p1 rw rootfstype=ext4 console=ttyS0,115200 mem=128M rootwait"
+# CONFIG_SUSPEND is not set
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_BRIDGE=m
+CONFIG_BRIDGE_VLAN_FILTERING=y
+CONFIG_VLAN_8021Q=m
+CONFIG_VLAN_8021Q_GVRP=y
+CONFIG_VLAN_8021Q_MVRP=y
+# CONFIG_WIRELESS is not set
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+# CONFIG_FW_LOADER is not set
+CONFIG_MTD=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_CFI_GEOMETRY=y
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_PHYSMAP_OF=y
+CONFIG_PROC_DEVICETREE=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_LOOP_MIN_COUNT=2
+CONFIG_EEPROM_AT24=m
+CONFIG_SCSI=y
+# CONFIG_SCSI_PROC_FS is not set
+CONFIG_BLK_DEV_SD=y
+# CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_NETDEVICES=y
+CONFIG_BONDING=m
+CONFIG_MACVLAN=m
+CONFIG_MACVTAP=m
+CONFIG_TUN=m
+# CONFIG_NET_VENDOR_ARC is not set
+# CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_CIRRUS is not set
+CONFIG_DM9000=y
+CONFIG_DM9000_FORCE_SIMPLE_PHY_POLL=y
+# CONFIG_NET_VENDOR_FARADAY is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+CONFIG_PPP=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPPOE=m
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_SLIP=m
+CONFIG_SLIP_COMPRESSED=y
+# CONFIG_WLAN is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=800
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=600
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_SERIO is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_8250=y
+# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=40
+CONFIG_SERIAL_8250_RUNTIME_UARTS=40
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_PXA=y
+CONFIG_HW_RANDOM=y
+CONFIG_I2C=m
+# CONFIG_I2C_COMPAT is not set
+CONFIG_I2C_GPIO=m
+CONFIG_W1=m
+CONFIG_W1_MASTER_GPIO=m
+CONFIG_W1_SLAVE_SMEM=m
+# CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_SA1100_WATCHDOG=m
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_FB=y
+CONFIG_FB_PXA=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_LOGO=y
+CONFIG_USB=m
+CONFIG_USB_OHCI_HCD=m
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+CONFIG_USB_STORAGE=m
+CONFIG_USB_SERIAL=m
+CONFIG_MMC=y
+CONFIG_MMC_PXA=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_PXA=m
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_EXT2_FS=m
+CONFIG_EXT3_FS=y
+CONFIG_EXT4_FS=y
+CONFIG_REISERFS_FS=m
+CONFIG_ISO9660_FS=m
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_NTFS_FS=m
+CONFIG_NTFS_RW=y
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V4=y
+CONFIG_ROOT_NFS=y
+CONFIG_CIFS=m
+CONFIG_CIFS_STATS=y
+CONFIG_CODA_FS=m
+CONFIG_NLS_DEFAULT="cp855"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_855=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_UTF8=y
+CONFIG_PRINTK_TIME=y
diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig
index e6690a4..fc2e634 100644
--- a/arch/arm/mach-pxa/Kconfig
+++ b/arch/arm/mach-pxa/Kconfig
@@ -4,6 +4,21 @@ menu "Intel PXA2xx/PXA3xx Implementations"
 
 comment "Intel/Marvell Dev Platforms (sorted by hardware release time)"
 
+config MACH_PXA27X_DT
+	bool "Support PXA27x platforms from device tree"
+	select PXA27x
+	select USE_OF
+	help
+	  Include support for Marvell PXA27x based platforms using
+	  the device tree.
+
+	  While MACH_PXA27X_DT when enabled should boot any PXA27x
+	  compatible machine, it still makes sense to select specific
+	  machines. Those options will select required features and
+	  provide per-machine errata workarounds.
+
+	  If unsure, say Y.
+
 config MACH_PXA3XX_DT
 	bool "Support PXA3xx platforms from device tree"
 	select CPU_PXA300
diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile
index 648867a..adaa72a 100644
--- a/arch/arm/mach-pxa/Makefile
+++ b/arch/arm/mach-pxa/Makefile
@@ -20,6 +20,7 @@ obj-$(CONFIG_CPU_PXA930)	+= pxa930.o
 # NOTE: keep the order of boards in accordance to their order in Kconfig
 
 # Device Tree support
+obj-$(CONFIG_MACH_PXA27X_DT)	+= pxa27x-dt.o
 obj-$(CONFIG_MACH_PXA3XX_DT)	+= pxa-dt.o
 
 # Intel/Marvell Dev Platforms
diff --git a/arch/arm/mach-pxa/pxa27x-dt.c b/arch/arm/mach-pxa/pxa27x-dt.c
new file mode 100644
index 0000000..865cf46
--- /dev/null
+++ b/arch/arm/mach-pxa/pxa27x-dt.c
@@ -0,0 +1,64 @@
+/*
+ *  linux/arch/arm/mach-pxa/pxa27x-dt.c
+ *
+ *  Copyright (C) 2013 Sergei Ianovich
+ *
+ *  based mostly on linux/arch/arm/mach-pxa/pxa-dt.c by Daniel Mack
+ *
+ *  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
+ *  publishhed by the Free Software Foundation.
+ */
+
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <asm/io.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <mach/irqs.h>
+#include <mach/pxa27x.h>
+
+#include "generic.h"
+
+#ifdef CONFIG_PXA27x
+static const struct of_dev_auxdata pxa27x_auxdata_lookup[] __initconst = {
+	OF_DEV_AUXDATA("mrvl,pxa-uart",	    0x40100000, "pxa2xx-uart.0", NULL),
+	OF_DEV_AUXDATA("mrvl,pxa-uart",	    0x40200000, "pxa2xx-uart.1", NULL),
+	OF_DEV_AUXDATA("mrvl,pxa-uart",	    0x40700000, "pxa2xx-uart.2", NULL),
+	OF_DEV_AUXDATA("mrvl,pxa-uart",	    0x41600000, "pxa2xx-uart.3", NULL),
+	OF_DEV_AUXDATA("marvell,pxa-mmc",   0x41100000, "pxa2xx-mci.0", NULL),
+	OF_DEV_AUXDATA("intel,pxa27x-gpio", 0x40e00000, "pxa27x-gpio", NULL),
+	OF_DEV_AUXDATA("marvell,pxa-ohci",  0x4c000000, "pxa27x-ohci", NULL),
+	OF_DEV_AUXDATA("mrvl,pxa-i2c",	    0x40301680, "pxa2xx-i2c.0", NULL),
+	{}
+};
+
+static void __init pxa27x_dt_init(void)
+{
+	of_platform_populate(NULL, of_default_bus_match_table,
+			     pxa27x_auxdata_lookup, NULL);
+}
+
+static const char * const pxa27x_dt_board_compat[] __initconst = {
+	"marvell,pxa270",
+	"marvell,pxa271",
+	"marvell,pxa272",
+	NULL,
+};
+
+#endif
+
+#ifdef CONFIG_PXA27x
+DT_MACHINE_START(PXA27X_DT, "Marvell PXA27x (Device Tree Support)")
+	.map_io		= pxa27x_map_io,
+	.init_irq	= pxa27x_dt_init_irq,
+	.handle_irq	= pxa27x_handle_irq,
+	.init_time	= pxa_timer_init,
+	.restart	= pxa_restart,
+	.init_machine	= pxa27x_dt_init,
+	.dt_compat	= pxa27x_dt_board_compat,
+MACHINE_END
+
+#endif
-- 
1.8.4.2

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

* [PATCH v4 08/21] ARM: pxa27x: device tree support ICP DAS LP-8x4x
@ 2014-04-16 17:17                   ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2014-04-16 17:17 UTC (permalink / raw)
  To: linux-arm-kernel

ICP DAS calls LP-8x4x 'programmable automation controller'. It is
an industrial computer based on PXA270 SoC. They ship it with a 2.6.19
kernel and proprietary kernel module and userspace library to access
its industrial IO.

This patch allows to boot the device with a modern kernel with device
tree. It adds support for:
* MMC card interface on PXA270
* USB 1.1 port on PXA270
* 2 NOR flash devices
* 2 onboard ethernet Davicom DM9000 devices
* 3 serial UART ports on PXA270
* front panel red LED
* 64bit 1-wire system ID chip
* 16 kiB EEPROM (reading)

Support for these devices will be added in separate patches, since
they are not currently supported by the kernel:
* DS1302 RTC
* 512kiB SRAM
* FPGA irq chip
* 3 built-in 16550A serial UART ports
* industrial IO parallel bus
* 10 position rotary switch
* 8 pin DIP switch
* 16 kiB EEPROM (writing)
* serial interface for digital and analog industrial IO modules on
  parallel bus (all I-87... modules)
* digital and analog industrial IO modules for parallel bus:
  ** I-8024 4 port analog output
  ** I-8041 32 port digital output
  ** I-8042 16 port digital output/16 port digital input

Not supported for now:
* VGA interface on PXA270 for lack of dts binding
* the rest of parallel bus (I-8...) modules for lack of hardware
* GPIO reset for lack of relevance (watchdog reset is working)

Newer devices have twice as much flash and a different partition
structure otherwise being the same. When each device is provided
with a correct device tree, all of them can be booted using the
same kernel.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Daniel Mack <zonque@gmail.com>
CC: Arnd Bergmann <arnd@arndb.de>
---
   v3..v4
   * move all declarations to one commit so the first DTB file can be
     used to boot any later kernel as suggested by Arnd Bergmann,
     Heikki Krogerus and Brian Norris
   * support new flavor of device (i105 suffix)

   v2..v3
   * added extbus which maps synchronous, static, and variable-latency
     I/O (VLIO) interfaces of PXA27x SoC as suggested by Arnd Bergmann
   * map is placed into platform include
   * configured existing kernel drivers to support:
     - front panel LED using gpio-leds
     - 64bit 1-wire system ID chip using w1-gpio
     - 16 kiB EEPROM using at24 over i2c-gpio
   * number change (06/16 -> 08/21)

   v1..v2
   * drop left-over extern declaration
   * use of_have_populated_dt() instead of a static variable
   * drop wildcards in compatible
   * drop machine-special machine description
   * number changed from 9 to 6 (dropped patches)

 .../devicetree/bindings/vendor-prefixes.txt        |   1 +
 arch/arm/boot/dts/Makefile                         |   2 +
 arch/arm/boot/dts/pxa27x-lp8x4x-i105.dts           |  43 ++++
 arch/arm/boot/dts/pxa27x-lp8x4x.dts                | 228 +++++++++++++++++++++
 arch/arm/boot/dts/pxa27x.dtsi                      |  17 ++
 arch/arm/configs/lp8x4x_defconfig                  | 168 +++++++++++++++
 arch/arm/mach-pxa/Kconfig                          |  15 ++
 arch/arm/mach-pxa/Makefile                         |   1 +
 arch/arm/mach-pxa/pxa27x-dt.c                      |  64 ++++++
 9 files changed, 539 insertions(+)
 create mode 100644 arch/arm/boot/dts/pxa27x-lp8x4x-i105.dts
 create mode 100644 arch/arm/boot/dts/pxa27x-lp8x4x.dts
 create mode 100644 arch/arm/configs/lp8x4x_defconfig
 create mode 100644 arch/arm/mach-pxa/pxa27x-dt.c

diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index 0f01c9b..1155c6c 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -54,6 +54,7 @@ hisilicon	Hisilicon Limited.
 honeywell	Honeywell
 hp	Hewlett Packard
 ibm	International Business Machines (IBM)
+icpdas	ICP DAS CO., LTD.
 idt	Integrated Device Technologies, Inc.
 img	Imagination Technologies Ltd.
 intel	Intel Corporation
diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index 35c146f..28175d7 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -408,6 +408,8 @@ dtb-$(CONFIG_MACH_DOVE) += dove-cm-a510.dtb \
 	dove-d2plug.dtb \
 	dove-d3plug.dtb \
 	dove-dove-db.dtb
+dtb-$(CONFIG_MACH_PXA27X_DT) += pxa27x-lp8x4x.dtb \
+	pxa27x-lp8x4x-i105.dtb
 
 targets += dtbs dtbs_install
 targets += $(dtb-y)
diff --git a/arch/arm/boot/dts/pxa27x-lp8x4x-i105.dts b/arch/arm/boot/dts/pxa27x-lp8x4x-i105.dts
new file mode 100644
index 0000000..8ddc9f5
--- /dev/null
+++ b/arch/arm/boot/dts/pxa27x-lp8x4x-i105.dts
@@ -0,0 +1,43 @@
+/* Device tree for ICP DAS LP-8x4x i105 flavor */
+
+#include "pxa27x-lp8x4x.dts"
+
+/ {
+	extbus {
+		flash at 0 {
+			compatible = "cfi-flash";
+			reg = <0 0 0x04000000>;
+			bank-width = <4>;
+			device-width = <2>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			fs at 0 {
+				label = "u-boot";
+				reg = <0 0x40000>;
+			};
+			fs at 40000 {
+				label = "settings";
+				reg = <0x40000 0x40000>;
+			};
+			fs at 80000 {
+				label = "device_tree";
+				reg = <0x80000 0x40000>;
+			};
+			fs at c0000 {
+				label = "kernel";
+				reg = <0xc0000 0x2c0000>;
+			};
+			fs at 300000 {
+				label = "root_fs";
+				reg = <0x380000 0x3c80000>;
+			};
+		};
+
+		flash at 1 {
+			compatible = "cfi-flash";
+			reg = <1 0x0 0x02000000>;
+			bank-width = <2>;
+			device-width = <1>;
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/pxa27x-lp8x4x.dts b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
new file mode 100644
index 0000000..38a3e46
--- /dev/null
+++ b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
@@ -0,0 +1,228 @@
+/* Device tree for ICP DAS LP-8x4x */
+/dts-v1/;
+
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include "pxa27x.dtsi"
+
+/ {
+	model = "ICP DAS LP-8x4x programmable automation controller";
+	compatible = "marvell,pxa270";
+
+	aliases {
+		ethernet0 = &eth0;
+		ethernet1 = &eth1;
+	};
+
+	memory {
+		reg = <0xa0000000 0x08000000>;
+	};
+
+	regulators {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		vmmc: regulator at 0 {
+			compatible = "regulator-fixed";
+			reg = <0>;
+			regulator-name = "vmmc";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-always-on;
+		};
+	};
+
+	pxabus {
+		pxairq: interrupt-controller at 40d00000 {
+			marvell,intc-priority;
+			marvell,intc-nr-irqs = <34>;
+		};
+
+		uart at 40100000 {
+			status = "okay";
+		};
+
+		uart at 40200000 {
+			status = "okay";
+		};
+
+		uart at 40700000 {
+			status = "okay";
+		};
+
+		mmc at 41100000 {
+			status = "okay";
+			vmmc-supply = <&vmmc>;
+		};
+
+		ohci at 4c000000 {
+			status = "okay";
+			marvell,port-mode = <3>;
+			marvell,oc-mode-perport;
+			marvell,enable-port1;
+		};
+
+		leds {
+			compatible = "gpio-leds";
+
+			status {
+				gpios = <&gpio 84 1>;
+				linux,default-trigger = "heartbeat";
+			};
+		};
+
+		i2c: i2c-gpio {
+			compatible = "i2c-gpio";
+			gpios = <&gpio 22 0 /* sda */
+				 &gpio 12 0 /* scl */>;
+			i2c-gpio,delay-us = <1>;
+			i2c-gpio,timeout-ms = <1>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			eeprom at 50 {
+				compatible = "atmel,24c128";
+				reg = <0x50>;
+				pagesize = <64>;
+			};
+		};
+
+		w1: w1-gpio {
+			compatible = "w1-gpio";
+			gpios = <&gpio 83 0>;
+		};
+	};
+
+	extbus {
+		flash at 0 {
+			compatible = "cfi-flash";
+			reg = <0 0 0x02000000>;
+			bank-width = <4>;
+			device-width = <2>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			fs at 0 {
+				label = "u-boot";
+				reg = <0 0x40000>;
+			};
+			fs at 40000 {
+				label = "settings";
+				reg = <0x40000 0x40000>;
+			};
+			fs at 80000 {
+				label = "device_tree";
+				reg = <0x80000 0x40000>;
+			};
+			fs at c0000 {
+				label = "kernel";
+				reg = <0xc0000 0x240000>;
+			};
+			fs at 300000 {
+				label = "root_fs";
+				reg = <0x300000 0x1d00000>;
+			};
+		};
+
+		flash at 1 {
+			compatible = "cfi-flash";
+			reg = <1 0x0 0x01000000>;
+			bank-width = <2>;
+			device-width = <1>;
+		};
+
+		netio at 3 {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0 3 0 0x02000000>;
+			interrupt-parent = <&gpio>;
+
+			eth0: eth at 0 {
+				compatible = "davicom,dm9000";
+				reg = <0x0 0x2
+				       0x4000 0x2>;
+				interrupts = <9 IRQ_TYPE_EDGE_RISING>;
+				status = "okay";
+			};
+
+			eth1: eth at 1000000 {
+				compatible = "davicom,dm9000";
+				reg = <0x1000000 0x2
+				       0x1004000 0x2>;
+				interrupts = <82 IRQ_TYPE_EDGE_RISING>;
+				status = "okay";
+			};
+		};
+
+		fpga at 5 {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0 5 0x3000000 0x10000>;
+			interrupt-parent = <&fpgairq>;
+
+			rtc at 901c {
+				compatible = "dallas,rtc-ds1302";
+				reg = <0x901c 0x1>;
+				status = "okay";
+			};
+
+			sram at a000 {
+				compatible = "icpdas,sram-lp8x4x";
+				reg = <0xa000 0x1000
+				       0x901e 0x1>;
+			};
+
+			fpgairq: irq at 9006 {
+				compatible = "icpdas,irq-lp8x4x";
+				reg = <0x9006 0x16>;
+				interrupt-parent = <&gpio>;
+				interrupts = <3 IRQ_TYPE_EDGE_FALLING>;
+				#interrupt-cells = <1>;
+				interrupt-controller;
+				status = "okay";
+			};
+
+			uart at 9050 {
+				compatible = "icpdas,uart-lp8x4x";
+				reg = <0x9050 0x10
+				       0x9030 0x02>;
+				interrupts = <13>;
+				status = "okay";
+			};
+
+			uart at 9060 {
+				compatible = "icpdas,uart-lp8x4x";
+				reg = <0x9060 0x10
+				       0x9032 0x02>;
+				interrupts = <14>;
+				status = "okay";
+			};
+
+			uart at 9070 {
+				compatible = "icpdas,uart-lp8x4x";
+				reg = <0x9070 0x10
+				       0x9034 0x02>;
+				interrupts = <15>;
+				status = "okay";
+			};
+
+			backplane {
+				compatible = "icpdas,backplane-lp8x4x";
+				reg = <0x0 0x2
+				       0x1000 0x10
+				       0x2000 0x10
+				       0x3000 0x10
+				       0x4000 0x10
+				       0x5000 0x10
+				       0x6000 0x10
+				       0x7000 0x10
+				       0x8000 0x10
+				       0x9002 0x2
+				       0x9004 0x2
+				       0x9046 0x2>;
+				eeprom-gpios = <&gpio 4 0>;
+			};
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/pxa27x.dtsi b/arch/arm/boot/dts/pxa27x.dtsi
index 0150531..1e1c98c 100644
--- a/arch/arm/boot/dts/pxa27x.dtsi
+++ b/arch/arm/boot/dts/pxa27x.dtsi
@@ -55,4 +55,21 @@
 			dma-names = "rx", "tx";
 		};
 	};
+
+	extbus {
+		/*
+		 * PXA27x synchrous, static and
+		 * variable-latency IO interfaces
+		 */
+	        compatible = "simple-bus";
+
+		#address-cells = <2>; /* first cell is nCS, second is address */
+		#size-cells = <1>;
+		ranges = <0 0 0 0x04000000
+			  1 0 0x04000000 0x04000000
+			  2 0 0x08000000 0x04000000
+			  3 0 0x0c000000 0x04000000
+			  4 0 0x10000000 0x04000000
+			  5 0 0x14000000 0x04000000>;
+	};
 };
diff --git a/arch/arm/configs/lp8x4x_defconfig b/arch/arm/configs/lp8x4x_defconfig
new file mode 100644
index 0000000..9f1efb6
--- /dev/null
+++ b/arch/arm/configs/lp8x4x_defconfig
@@ -0,0 +1,168 @@
+# CONFIG_LOCALVERSION_AUTO is not set
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_RCU_BOOST=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_NS is not set
+# CONFIG_IPC_NS is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+# CONFIG_UID16 is not set
+# CONFIG_SHMEM is not set
+CONFIG_EMBEDDED=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_SLOB=y
+CONFIG_JUMP_LABEL=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+# CONFIG_LBDAF is not set
+CONFIG_BLK_CMDLINE_PARSER=y
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_ARCH_PXA=y
+CONFIG_MACH_PXA27X_DT=y
+# CONFIG_ARM_THUMB is not set
+CONFIG_PREEMPT=y
+CONFIG_AEABI=y
+# CONFIG_COMPACTION is not set
+# CONFIG_CROSS_MEMORY_ATTACH is not set
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="init=/sbin/init root=/dev/mmcblk0p1 rw rootfstype=ext4 console=ttyS0,115200 mem=128M rootwait"
+# CONFIG_SUSPEND is not set
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_BRIDGE=m
+CONFIG_BRIDGE_VLAN_FILTERING=y
+CONFIG_VLAN_8021Q=m
+CONFIG_VLAN_8021Q_GVRP=y
+CONFIG_VLAN_8021Q_MVRP=y
+# CONFIG_WIRELESS is not set
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+# CONFIG_FW_LOADER is not set
+CONFIG_MTD=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_CFI_GEOMETRY=y
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_PHYSMAP_OF=y
+CONFIG_PROC_DEVICETREE=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_LOOP_MIN_COUNT=2
+CONFIG_EEPROM_AT24=m
+CONFIG_SCSI=y
+# CONFIG_SCSI_PROC_FS is not set
+CONFIG_BLK_DEV_SD=y
+# CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_NETDEVICES=y
+CONFIG_BONDING=m
+CONFIG_MACVLAN=m
+CONFIG_MACVTAP=m
+CONFIG_TUN=m
+# CONFIG_NET_VENDOR_ARC is not set
+# CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_CIRRUS is not set
+CONFIG_DM9000=y
+CONFIG_DM9000_FORCE_SIMPLE_PHY_POLL=y
+# CONFIG_NET_VENDOR_FARADAY is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+CONFIG_PPP=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPPOE=m
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_SLIP=m
+CONFIG_SLIP_COMPRESSED=y
+# CONFIG_WLAN is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=800
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=600
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_SERIO is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_8250=y
+# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=40
+CONFIG_SERIAL_8250_RUNTIME_UARTS=40
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_PXA=y
+CONFIG_HW_RANDOM=y
+CONFIG_I2C=m
+# CONFIG_I2C_COMPAT is not set
+CONFIG_I2C_GPIO=m
+CONFIG_W1=m
+CONFIG_W1_MASTER_GPIO=m
+CONFIG_W1_SLAVE_SMEM=m
+# CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_SA1100_WATCHDOG=m
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_FB=y
+CONFIG_FB_PXA=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_LOGO=y
+CONFIG_USB=m
+CONFIG_USB_OHCI_HCD=m
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+CONFIG_USB_STORAGE=m
+CONFIG_USB_SERIAL=m
+CONFIG_MMC=y
+CONFIG_MMC_PXA=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_PXA=m
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_EXT2_FS=m
+CONFIG_EXT3_FS=y
+CONFIG_EXT4_FS=y
+CONFIG_REISERFS_FS=m
+CONFIG_ISO9660_FS=m
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_NTFS_FS=m
+CONFIG_NTFS_RW=y
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V4=y
+CONFIG_ROOT_NFS=y
+CONFIG_CIFS=m
+CONFIG_CIFS_STATS=y
+CONFIG_CODA_FS=m
+CONFIG_NLS_DEFAULT="cp855"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_855=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_UTF8=y
+CONFIG_PRINTK_TIME=y
diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig
index e6690a4..fc2e634 100644
--- a/arch/arm/mach-pxa/Kconfig
+++ b/arch/arm/mach-pxa/Kconfig
@@ -4,6 +4,21 @@ menu "Intel PXA2xx/PXA3xx Implementations"
 
 comment "Intel/Marvell Dev Platforms (sorted by hardware release time)"
 
+config MACH_PXA27X_DT
+	bool "Support PXA27x platforms from device tree"
+	select PXA27x
+	select USE_OF
+	help
+	  Include support for Marvell PXA27x based platforms using
+	  the device tree.
+
+	  While MACH_PXA27X_DT when enabled should boot any PXA27x
+	  compatible machine, it still makes sense to select specific
+	  machines. Those options will select required features and
+	  provide per-machine errata workarounds.
+
+	  If unsure, say Y.
+
 config MACH_PXA3XX_DT
 	bool "Support PXA3xx platforms from device tree"
 	select CPU_PXA300
diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile
index 648867a..adaa72a 100644
--- a/arch/arm/mach-pxa/Makefile
+++ b/arch/arm/mach-pxa/Makefile
@@ -20,6 +20,7 @@ obj-$(CONFIG_CPU_PXA930)	+= pxa930.o
 # NOTE: keep the order of boards in accordance to their order in Kconfig
 
 # Device Tree support
+obj-$(CONFIG_MACH_PXA27X_DT)	+= pxa27x-dt.o
 obj-$(CONFIG_MACH_PXA3XX_DT)	+= pxa-dt.o
 
 # Intel/Marvell Dev Platforms
diff --git a/arch/arm/mach-pxa/pxa27x-dt.c b/arch/arm/mach-pxa/pxa27x-dt.c
new file mode 100644
index 0000000..865cf46
--- /dev/null
+++ b/arch/arm/mach-pxa/pxa27x-dt.c
@@ -0,0 +1,64 @@
+/*
+ *  linux/arch/arm/mach-pxa/pxa27x-dt.c
+ *
+ *  Copyright (C) 2013 Sergei Ianovich
+ *
+ *  based mostly on linux/arch/arm/mach-pxa/pxa-dt.c by Daniel Mack
+ *
+ *  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
+ *  publishhed by the Free Software Foundation.
+ */
+
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <asm/io.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <mach/irqs.h>
+#include <mach/pxa27x.h>
+
+#include "generic.h"
+
+#ifdef CONFIG_PXA27x
+static const struct of_dev_auxdata pxa27x_auxdata_lookup[] __initconst = {
+	OF_DEV_AUXDATA("mrvl,pxa-uart",	    0x40100000, "pxa2xx-uart.0", NULL),
+	OF_DEV_AUXDATA("mrvl,pxa-uart",	    0x40200000, "pxa2xx-uart.1", NULL),
+	OF_DEV_AUXDATA("mrvl,pxa-uart",	    0x40700000, "pxa2xx-uart.2", NULL),
+	OF_DEV_AUXDATA("mrvl,pxa-uart",	    0x41600000, "pxa2xx-uart.3", NULL),
+	OF_DEV_AUXDATA("marvell,pxa-mmc",   0x41100000, "pxa2xx-mci.0", NULL),
+	OF_DEV_AUXDATA("intel,pxa27x-gpio", 0x40e00000, "pxa27x-gpio", NULL),
+	OF_DEV_AUXDATA("marvell,pxa-ohci",  0x4c000000, "pxa27x-ohci", NULL),
+	OF_DEV_AUXDATA("mrvl,pxa-i2c",	    0x40301680, "pxa2xx-i2c.0", NULL),
+	{}
+};
+
+static void __init pxa27x_dt_init(void)
+{
+	of_platform_populate(NULL, of_default_bus_match_table,
+			     pxa27x_auxdata_lookup, NULL);
+}
+
+static const char * const pxa27x_dt_board_compat[] __initconst = {
+	"marvell,pxa270",
+	"marvell,pxa271",
+	"marvell,pxa272",
+	NULL,
+};
+
+#endif
+
+#ifdef CONFIG_PXA27x
+DT_MACHINE_START(PXA27X_DT, "Marvell PXA27x (Device Tree Support)")
+	.map_io		= pxa27x_map_io,
+	.init_irq	= pxa27x_dt_init_irq,
+	.handle_irq	= pxa27x_handle_irq,
+	.init_time	= pxa_timer_init,
+	.restart	= pxa_restart,
+	.init_machine	= pxa27x_dt_init,
+	.dt_compat	= pxa27x_dt_board_compat,
+MACHINE_END
+
+#endif
-- 
1.8.4.2

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

* [PATCH v4 09/21] rtc: support DS1302 RTC on ICP DAS LP-8x4x
@ 2014-04-16 17:17                   ` Sergey Yanovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2014-04-16 17:17 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Randy Dunlap, Russell King,
	Alessandro Zummo, Grant Likely, Heikki Krogerus,
	open list:OPEN FIRMWARE AND...,
	open list:DOCUMENTATION, rtc-linux

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
   v3..v4
   * move DTS bindings to a different patch (8/21)

   v2..v3
   * use usleep_range instead of custom nsleep
   * number change (07/16 -> 09/21)

   v0..v2
   * use device tree
   * use devm helpers where possible

 .../devicetree/bindings/rtc/rtc-ds1302.txt         |  14 +++
 arch/arm/configs/lp8x4x_defconfig                  |   1 +
 drivers/rtc/Kconfig                                |   2 +-
 drivers/rtc/rtc-ds1302.c                           | 100 ++++++++++++++++++++-
 4 files changed, 114 insertions(+), 3 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/rtc/rtc-ds1302.txt

diff --git a/Documentation/devicetree/bindings/rtc/rtc-ds1302.txt b/Documentation/devicetree/bindings/rtc/rtc-ds1302.txt
new file mode 100644
index 0000000..810613b
--- /dev/null
+++ b/Documentation/devicetree/bindings/rtc/rtc-ds1302.txt
@@ -0,0 +1,14 @@
+* Dallas Semiconductor DS-1302 RTC
+
+Simple device which could be used to store date/time between reboots.
+
+Required properties:
+- compatible : Should be "dallas,rtc-ds1302"
+- reg : Should be address and size of IO memory region
+
+Examples:
+
+rtc@40900000 {
+	compatible = "dallas,rtc-ds1302";
+	reg = <0x1700901c 0x1>;
+};
diff --git a/arch/arm/configs/lp8x4x_defconfig b/arch/arm/configs/lp8x4x_defconfig
index 9f1efb6..d60e37a 100644
--- a/arch/arm/configs/lp8x4x_defconfig
+++ b/arch/arm/configs/lp8x4x_defconfig
@@ -141,6 +141,7 @@ CONFIG_LEDS_GPIO=y
 CONFIG_LEDS_TRIGGERS=y
 CONFIG_LEDS_TRIGGER_HEARTBEAT=y
 CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_DS1302=y
 CONFIG_RTC_DRV_PXA=m
 # CONFIG_IOMMU_SUPPORT is not set
 CONFIG_EXT2_FS=m
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 2e565f8..80aaaa1 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -710,7 +710,7 @@ config RTC_DRV_DS1286
 
 config RTC_DRV_DS1302
 	tristate "Dallas DS1302"
-	depends on SH_SECUREEDGE5410
+	depends on SH_SECUREEDGE5410 || (ARCH_PXA && HIGH_RES_TIMERS)
 	help
 	  If you say yes here you get support for the Dallas DS1302 RTC chips.
 
diff --git a/drivers/rtc/rtc-ds1302.c b/drivers/rtc/rtc-ds1302.c
index 07e8d79..3c49023 100644
--- a/drivers/rtc/rtc-ds1302.c
+++ b/drivers/rtc/rtc-ds1302.c
@@ -50,7 +50,7 @@
 #define ds1302_set_tx()
 #define ds1302_set_rx()
 
-static inline int ds1302_hw_init(void)
+static inline int ds1302_hw_init(struct platform_device *pdev)
 {
 	return 0;
 }
@@ -86,6 +86,101 @@ static inline int ds1302_rxbit(void)
 	return !!(get_dp() & RTC_IODATA);
 }
 
+#elif defined(CONFIG_ARCH_PXA) && defined(CONFIG_HIGH_RES_TIMERS)
+
+#include <linux/delay.h>
+#include <linux/of.h>
+
+#define	RTC_CE		0x01
+#define	RTC_CLK		0x02
+#define	RTC_nWE		0x04
+#define	RTC_IODATA	0x08
+
+static unsigned long ds1302_state;
+
+static void *mem;
+
+static inline int ds1302_hw_init(struct platform_device *pdev)
+{
+	struct resource *r;
+
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!r)
+		return -ENODEV;
+
+	mem = devm_ioremap_resource(&pdev->dev, r);
+	if (!mem)
+		return -EFAULT;
+
+	return 0;
+}
+
+static inline void ds1302_reset(void)
+{
+	ds1302_state = 0;
+	iowrite8(ds1302_state, mem);
+	usleep_range(4, 5);
+}
+
+static inline void ds1302_clock(void)
+{
+	usleep_range(1, 2);
+	ds1302_state |= RTC_CLK;
+	iowrite8(ds1302_state, mem);
+	usleep_range(1, 2);
+	ds1302_state &= ~RTC_CLK;
+	iowrite8(ds1302_state, mem);
+}
+
+static inline void ds1302_start(void)
+{
+	ds1302_state &= ~RTC_CLK;
+	ds1302_state |= RTC_CE;
+	iowrite8(ds1302_state, mem);
+	usleep_range(3, 4);
+}
+
+static inline void ds1302_stop(void)
+{
+	ds1302_state &= ~RTC_CE;
+	iowrite8(ds1302_state, mem);
+}
+
+static inline void ds1302_set_tx(void)
+{
+	ds1302_state &= ~RTC_nWE;
+	iowrite8(ds1302_state, mem);
+}
+
+static inline void ds1302_set_rx(void)
+{
+	ds1302_state |= RTC_nWE;
+	iowrite8(ds1302_state, mem);
+}
+
+static inline void ds1302_txbit(int bit)
+{
+	if (bit)
+		ds1302_state |= RTC_IODATA;
+	else
+		ds1302_state &= ~RTC_IODATA;
+	iowrite8(ds1302_state, mem);
+}
+
+static inline int ds1302_rxbit(void)
+{
+	return ioread8(mem) & 0x1;
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id ds1302_dt_ids[] = {
+	{ .compatible = "dallas,rtc-ds1302" },
+	{ }
+};
+
+MODULE_DEVICE_TABLE(of, ds1302_dt_ids);
+#endif
+
 #else
 #error "Add support for your platform"
 #endif
@@ -216,7 +311,7 @@ static int __init ds1302_rtc_probe(struct platform_device *pdev)
 {
 	struct rtc_device *rtc;
 
-	if (ds1302_hw_init()) {
+	if (ds1302_hw_init(pdev)) {
 		dev_err(&pdev->dev, "Failed to init communication channel");
 		return -EINVAL;
 	}
@@ -245,6 +340,7 @@ static struct platform_driver ds1302_platform_driver = {
 	.driver		= {
 		.name	= DRV_NAME,
 		.owner	= THIS_MODULE,
+		.of_match_table = of_match_ptr(ds1302_dt_ids),
 	},
 };
 
-- 
1.8.4.2


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

* [v4,09/21] rtc: support DS1302 RTC on ICP DAS LP-8x4x
@ 2014-04-16 17:17                   ` Sergey Yanovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergey Yanovich @ 2014-04-16 17:17 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Randy Dunlap, Russell King,
	Alessandro Zummo, Grant Likely, Heikki Krogerus,
	open list:OPEN FIRMWARE AND...,
	open list:DOCUMENTATION, rtc-linux

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
   v3..v4
   * move DTS bindings to a different patch (8/21)

   v2..v3
   * use usleep_range instead of custom nsleep
   * number change (07/16 -> 09/21)

   v0..v2
   * use device tree
   * use devm helpers where possible

 .../devicetree/bindings/rtc/rtc-ds1302.txt         |  14 +++
 arch/arm/configs/lp8x4x_defconfig                  |   1 +
 drivers/rtc/Kconfig                                |   2 +-
 drivers/rtc/rtc-ds1302.c                           | 100 ++++++++++++++++++++-
 4 files changed, 114 insertions(+), 3 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/rtc/rtc-ds1302.txt

diff --git a/Documentation/devicetree/bindings/rtc/rtc-ds1302.txt b/Documentation/devicetree/bindings/rtc/rtc-ds1302.txt
new file mode 100644
index 0000000..810613b
--- /dev/null
+++ b/Documentation/devicetree/bindings/rtc/rtc-ds1302.txt
@@ -0,0 +1,14 @@
+* Dallas Semiconductor DS-1302 RTC
+
+Simple device which could be used to store date/time between reboots.
+
+Required properties:
+- compatible : Should be "dallas,rtc-ds1302"
+- reg : Should be address and size of IO memory region
+
+Examples:
+
+rtc@40900000 {
+	compatible = "dallas,rtc-ds1302";
+	reg = <0x1700901c 0x1>;
+};
diff --git a/arch/arm/configs/lp8x4x_defconfig b/arch/arm/configs/lp8x4x_defconfig
index 9f1efb6..d60e37a 100644
--- a/arch/arm/configs/lp8x4x_defconfig
+++ b/arch/arm/configs/lp8x4x_defconfig
@@ -141,6 +141,7 @@ CONFIG_LEDS_GPIO=y
 CONFIG_LEDS_TRIGGERS=y
 CONFIG_LEDS_TRIGGER_HEARTBEAT=y
 CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_DS1302=y
 CONFIG_RTC_DRV_PXA=m
 # CONFIG_IOMMU_SUPPORT is not set
 CONFIG_EXT2_FS=m
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 2e565f8..80aaaa1 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -710,7 +710,7 @@ config RTC_DRV_DS1286
 
 config RTC_DRV_DS1302
 	tristate "Dallas DS1302"
-	depends on SH_SECUREEDGE5410
+	depends on SH_SECUREEDGE5410 || (ARCH_PXA && HIGH_RES_TIMERS)
 	help
 	  If you say yes here you get support for the Dallas DS1302 RTC chips.
 
diff --git a/drivers/rtc/rtc-ds1302.c b/drivers/rtc/rtc-ds1302.c
index 07e8d79..3c49023 100644
--- a/drivers/rtc/rtc-ds1302.c
+++ b/drivers/rtc/rtc-ds1302.c
@@ -50,7 +50,7 @@
 #define ds1302_set_tx()
 #define ds1302_set_rx()
 
-static inline int ds1302_hw_init(void)
+static inline int ds1302_hw_init(struct platform_device *pdev)
 {
 	return 0;
 }
@@ -86,6 +86,101 @@ static inline int ds1302_rxbit(void)
 	return !!(get_dp() & RTC_IODATA);
 }
 
+#elif defined(CONFIG_ARCH_PXA) && defined(CONFIG_HIGH_RES_TIMERS)
+
+#include <linux/delay.h>
+#include <linux/of.h>
+
+#define	RTC_CE		0x01
+#define	RTC_CLK		0x02
+#define	RTC_nWE		0x04
+#define	RTC_IODATA	0x08
+
+static unsigned long ds1302_state;
+
+static void *mem;
+
+static inline int ds1302_hw_init(struct platform_device *pdev)
+{
+	struct resource *r;
+
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!r)
+		return -ENODEV;
+
+	mem = devm_ioremap_resource(&pdev->dev, r);
+	if (!mem)
+		return -EFAULT;
+
+	return 0;
+}
+
+static inline void ds1302_reset(void)
+{
+	ds1302_state = 0;
+	iowrite8(ds1302_state, mem);
+	usleep_range(4, 5);
+}
+
+static inline void ds1302_clock(void)
+{
+	usleep_range(1, 2);
+	ds1302_state |= RTC_CLK;
+	iowrite8(ds1302_state, mem);
+	usleep_range(1, 2);
+	ds1302_state &= ~RTC_CLK;
+	iowrite8(ds1302_state, mem);
+}
+
+static inline void ds1302_start(void)
+{
+	ds1302_state &= ~RTC_CLK;
+	ds1302_state |= RTC_CE;
+	iowrite8(ds1302_state, mem);
+	usleep_range(3, 4);
+}
+
+static inline void ds1302_stop(void)
+{
+	ds1302_state &= ~RTC_CE;
+	iowrite8(ds1302_state, mem);
+}
+
+static inline void ds1302_set_tx(void)
+{
+	ds1302_state &= ~RTC_nWE;
+	iowrite8(ds1302_state, mem);
+}
+
+static inline void ds1302_set_rx(void)
+{
+	ds1302_state |= RTC_nWE;
+	iowrite8(ds1302_state, mem);
+}
+
+static inline void ds1302_txbit(int bit)
+{
+	if (bit)
+		ds1302_state |= RTC_IODATA;
+	else
+		ds1302_state &= ~RTC_IODATA;
+	iowrite8(ds1302_state, mem);
+}
+
+static inline int ds1302_rxbit(void)
+{
+	return ioread8(mem) & 0x1;
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id ds1302_dt_ids[] = {
+	{ .compatible = "dallas,rtc-ds1302" },
+	{ }
+};
+
+MODULE_DEVICE_TABLE(of, ds1302_dt_ids);
+#endif
+
 #else
 #error "Add support for your platform"
 #endif
@@ -216,7 +311,7 @@ static int __init ds1302_rtc_probe(struct platform_device *pdev)
 {
 	struct rtc_device *rtc;
 
-	if (ds1302_hw_init()) {
+	if (ds1302_hw_init(pdev)) {
 		dev_err(&pdev->dev, "Failed to init communication channel");
 		return -EINVAL;
 	}
@@ -245,6 +340,7 @@ static struct platform_driver ds1302_platform_driver = {
 	.driver		= {
 		.name	= DRV_NAME,
 		.owner	= THIS_MODULE,
+		.of_match_table = of_match_ptr(ds1302_dt_ids),
 	},
 };
 

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

* [PATCH v4 09/21] rtc: support DS1302 RTC on ICP DAS LP-8x4x
@ 2014-04-16 17:17                   ` Sergey Yanovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2014-04-16 17:17 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Randy Dunlap, Russell King,
	Alessandro Zummo, Grant Likely, Heikki Krogerus,
	open list:OPEN FIRMWARE AND...,
	open list:DOCUMENTATION, rtc-linux

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
   v3..v4
   * move DTS bindings to a different patch (8/21)

   v2..v3
   * use usleep_range instead of custom nsleep
   * number change (07/16 -> 09/21)

   v0..v2
   * use device tree
   * use devm helpers where possible

 .../devicetree/bindings/rtc/rtc-ds1302.txt         |  14 +++
 arch/arm/configs/lp8x4x_defconfig                  |   1 +
 drivers/rtc/Kconfig                                |   2 +-
 drivers/rtc/rtc-ds1302.c                           | 100 ++++++++++++++++++++-
 4 files changed, 114 insertions(+), 3 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/rtc/rtc-ds1302.txt

diff --git a/Documentation/devicetree/bindings/rtc/rtc-ds1302.txt b/Documentation/devicetree/bindings/rtc/rtc-ds1302.txt
new file mode 100644
index 0000000..810613b
--- /dev/null
+++ b/Documentation/devicetree/bindings/rtc/rtc-ds1302.txt
@@ -0,0 +1,14 @@
+* Dallas Semiconductor DS-1302 RTC
+
+Simple device which could be used to store date/time between reboots.
+
+Required properties:
+- compatible : Should be "dallas,rtc-ds1302"
+- reg : Should be address and size of IO memory region
+
+Examples:
+
+rtc@40900000 {
+	compatible = "dallas,rtc-ds1302";
+	reg = <0x1700901c 0x1>;
+};
diff --git a/arch/arm/configs/lp8x4x_defconfig b/arch/arm/configs/lp8x4x_defconfig
index 9f1efb6..d60e37a 100644
--- a/arch/arm/configs/lp8x4x_defconfig
+++ b/arch/arm/configs/lp8x4x_defconfig
@@ -141,6 +141,7 @@ CONFIG_LEDS_GPIO=y
 CONFIG_LEDS_TRIGGERS=y
 CONFIG_LEDS_TRIGGER_HEARTBEAT=y
 CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_DS1302=y
 CONFIG_RTC_DRV_PXA=m
 # CONFIG_IOMMU_SUPPORT is not set
 CONFIG_EXT2_FS=m
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 2e565f8..80aaaa1 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -710,7 +710,7 @@ config RTC_DRV_DS1286
 
 config RTC_DRV_DS1302
 	tristate "Dallas DS1302"
-	depends on SH_SECUREEDGE5410
+	depends on SH_SECUREEDGE5410 || (ARCH_PXA && HIGH_RES_TIMERS)
 	help
 	  If you say yes here you get support for the Dallas DS1302 RTC chips.
 
diff --git a/drivers/rtc/rtc-ds1302.c b/drivers/rtc/rtc-ds1302.c
index 07e8d79..3c49023 100644
--- a/drivers/rtc/rtc-ds1302.c
+++ b/drivers/rtc/rtc-ds1302.c
@@ -50,7 +50,7 @@
 #define ds1302_set_tx()
 #define ds1302_set_rx()
 
-static inline int ds1302_hw_init(void)
+static inline int ds1302_hw_init(struct platform_device *pdev)
 {
 	return 0;
 }
@@ -86,6 +86,101 @@ static inline int ds1302_rxbit(void)
 	return !!(get_dp() & RTC_IODATA);
 }
 
+#elif defined(CONFIG_ARCH_PXA) && defined(CONFIG_HIGH_RES_TIMERS)
+
+#include <linux/delay.h>
+#include <linux/of.h>
+
+#define	RTC_CE		0x01
+#define	RTC_CLK		0x02
+#define	RTC_nWE		0x04
+#define	RTC_IODATA	0x08
+
+static unsigned long ds1302_state;
+
+static void *mem;
+
+static inline int ds1302_hw_init(struct platform_device *pdev)
+{
+	struct resource *r;
+
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!r)
+		return -ENODEV;
+
+	mem = devm_ioremap_resource(&pdev->dev, r);
+	if (!mem)
+		return -EFAULT;
+
+	return 0;
+}
+
+static inline void ds1302_reset(void)
+{
+	ds1302_state = 0;
+	iowrite8(ds1302_state, mem);
+	usleep_range(4, 5);
+}
+
+static inline void ds1302_clock(void)
+{
+	usleep_range(1, 2);
+	ds1302_state |= RTC_CLK;
+	iowrite8(ds1302_state, mem);
+	usleep_range(1, 2);
+	ds1302_state &= ~RTC_CLK;
+	iowrite8(ds1302_state, mem);
+}
+
+static inline void ds1302_start(void)
+{
+	ds1302_state &= ~RTC_CLK;
+	ds1302_state |= RTC_CE;
+	iowrite8(ds1302_state, mem);
+	usleep_range(3, 4);
+}
+
+static inline void ds1302_stop(void)
+{
+	ds1302_state &= ~RTC_CE;
+	iowrite8(ds1302_state, mem);
+}
+
+static inline void ds1302_set_tx(void)
+{
+	ds1302_state &= ~RTC_nWE;
+	iowrite8(ds1302_state, mem);
+}
+
+static inline void ds1302_set_rx(void)
+{
+	ds1302_state |= RTC_nWE;
+	iowrite8(ds1302_state, mem);
+}
+
+static inline void ds1302_txbit(int bit)
+{
+	if (bit)
+		ds1302_state |= RTC_IODATA;
+	else
+		ds1302_state &= ~RTC_IODATA;
+	iowrite8(ds1302_state, mem);
+}
+
+static inline int ds1302_rxbit(void)
+{
+	return ioread8(mem) & 0x1;
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id ds1302_dt_ids[] = {
+	{ .compatible = "dallas,rtc-ds1302" },
+	{ }
+};
+
+MODULE_DEVICE_TABLE(of, ds1302_dt_ids);
+#endif
+
 #else
 #error "Add support for your platform"
 #endif
@@ -216,7 +311,7 @@ static int __init ds1302_rtc_probe(struct platform_device *pdev)
 {
 	struct rtc_device *rtc;
 
-	if (ds1302_hw_init()) {
+	if (ds1302_hw_init(pdev)) {
 		dev_err(&pdev->dev, "Failed to init communication channel");
 		return -EINVAL;
 	}
@@ -245,6 +340,7 @@ static struct platform_driver ds1302_platform_driver = {
 	.driver		= {
 		.name	= DRV_NAME,
 		.owner	= THIS_MODULE,
+		.of_match_table = of_match_ptr(ds1302_dt_ids),
 	},
 };
 
-- 
1.8.4.2

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

* [PATCH v4 09/21] rtc: support DS1302 RTC on ICP DAS LP-8x4x
@ 2014-04-16 17:17                   ` Sergey Yanovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2014-04-16 17:17 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
   v3..v4
   * move DTS bindings to a different patch (8/21)

   v2..v3
   * use usleep_range instead of custom nsleep
   * number change (07/16 -> 09/21)

   v0..v2
   * use device tree
   * use devm helpers where possible

 .../devicetree/bindings/rtc/rtc-ds1302.txt         |  14 +++
 arch/arm/configs/lp8x4x_defconfig                  |   1 +
 drivers/rtc/Kconfig                                |   2 +-
 drivers/rtc/rtc-ds1302.c                           | 100 ++++++++++++++++++++-
 4 files changed, 114 insertions(+), 3 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/rtc/rtc-ds1302.txt

diff --git a/Documentation/devicetree/bindings/rtc/rtc-ds1302.txt b/Documentation/devicetree/bindings/rtc/rtc-ds1302.txt
new file mode 100644
index 0000000..810613b
--- /dev/null
+++ b/Documentation/devicetree/bindings/rtc/rtc-ds1302.txt
@@ -0,0 +1,14 @@
+* Dallas Semiconductor DS-1302 RTC
+
+Simple device which could be used to store date/time between reboots.
+
+Required properties:
+- compatible : Should be "dallas,rtc-ds1302"
+- reg : Should be address and size of IO memory region
+
+Examples:
+
+rtc at 40900000 {
+	compatible = "dallas,rtc-ds1302";
+	reg = <0x1700901c 0x1>;
+};
diff --git a/arch/arm/configs/lp8x4x_defconfig b/arch/arm/configs/lp8x4x_defconfig
index 9f1efb6..d60e37a 100644
--- a/arch/arm/configs/lp8x4x_defconfig
+++ b/arch/arm/configs/lp8x4x_defconfig
@@ -141,6 +141,7 @@ CONFIG_LEDS_GPIO=y
 CONFIG_LEDS_TRIGGERS=y
 CONFIG_LEDS_TRIGGER_HEARTBEAT=y
 CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_DS1302=y
 CONFIG_RTC_DRV_PXA=m
 # CONFIG_IOMMU_SUPPORT is not set
 CONFIG_EXT2_FS=m
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 2e565f8..80aaaa1 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -710,7 +710,7 @@ config RTC_DRV_DS1286
 
 config RTC_DRV_DS1302
 	tristate "Dallas DS1302"
-	depends on SH_SECUREEDGE5410
+	depends on SH_SECUREEDGE5410 || (ARCH_PXA && HIGH_RES_TIMERS)
 	help
 	  If you say yes here you get support for the Dallas DS1302 RTC chips.
 
diff --git a/drivers/rtc/rtc-ds1302.c b/drivers/rtc/rtc-ds1302.c
index 07e8d79..3c49023 100644
--- a/drivers/rtc/rtc-ds1302.c
+++ b/drivers/rtc/rtc-ds1302.c
@@ -50,7 +50,7 @@
 #define ds1302_set_tx()
 #define ds1302_set_rx()
 
-static inline int ds1302_hw_init(void)
+static inline int ds1302_hw_init(struct platform_device *pdev)
 {
 	return 0;
 }
@@ -86,6 +86,101 @@ static inline int ds1302_rxbit(void)
 	return !!(get_dp() & RTC_IODATA);
 }
 
+#elif defined(CONFIG_ARCH_PXA) && defined(CONFIG_HIGH_RES_TIMERS)
+
+#include <linux/delay.h>
+#include <linux/of.h>
+
+#define	RTC_CE		0x01
+#define	RTC_CLK		0x02
+#define	RTC_nWE		0x04
+#define	RTC_IODATA	0x08
+
+static unsigned long ds1302_state;
+
+static void *mem;
+
+static inline int ds1302_hw_init(struct platform_device *pdev)
+{
+	struct resource *r;
+
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!r)
+		return -ENODEV;
+
+	mem = devm_ioremap_resource(&pdev->dev, r);
+	if (!mem)
+		return -EFAULT;
+
+	return 0;
+}
+
+static inline void ds1302_reset(void)
+{
+	ds1302_state = 0;
+	iowrite8(ds1302_state, mem);
+	usleep_range(4, 5);
+}
+
+static inline void ds1302_clock(void)
+{
+	usleep_range(1, 2);
+	ds1302_state |= RTC_CLK;
+	iowrite8(ds1302_state, mem);
+	usleep_range(1, 2);
+	ds1302_state &= ~RTC_CLK;
+	iowrite8(ds1302_state, mem);
+}
+
+static inline void ds1302_start(void)
+{
+	ds1302_state &= ~RTC_CLK;
+	ds1302_state |= RTC_CE;
+	iowrite8(ds1302_state, mem);
+	usleep_range(3, 4);
+}
+
+static inline void ds1302_stop(void)
+{
+	ds1302_state &= ~RTC_CE;
+	iowrite8(ds1302_state, mem);
+}
+
+static inline void ds1302_set_tx(void)
+{
+	ds1302_state &= ~RTC_nWE;
+	iowrite8(ds1302_state, mem);
+}
+
+static inline void ds1302_set_rx(void)
+{
+	ds1302_state |= RTC_nWE;
+	iowrite8(ds1302_state, mem);
+}
+
+static inline void ds1302_txbit(int bit)
+{
+	if (bit)
+		ds1302_state |= RTC_IODATA;
+	else
+		ds1302_state &= ~RTC_IODATA;
+	iowrite8(ds1302_state, mem);
+}
+
+static inline int ds1302_rxbit(void)
+{
+	return ioread8(mem) & 0x1;
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id ds1302_dt_ids[] = {
+	{ .compatible = "dallas,rtc-ds1302" },
+	{ }
+};
+
+MODULE_DEVICE_TABLE(of, ds1302_dt_ids);
+#endif
+
 #else
 #error "Add support for your platform"
 #endif
@@ -216,7 +311,7 @@ static int __init ds1302_rtc_probe(struct platform_device *pdev)
 {
 	struct rtc_device *rtc;
 
-	if (ds1302_hw_init()) {
+	if (ds1302_hw_init(pdev)) {
 		dev_err(&pdev->dev, "Failed to init communication channel");
 		return -EINVAL;
 	}
@@ -245,6 +340,7 @@ static struct platform_driver ds1302_platform_driver = {
 	.driver		= {
 		.name	= DRV_NAME,
 		.owner	= THIS_MODULE,
+		.of_match_table = of_match_ptr(ds1302_dt_ids),
 	},
 };
 
-- 
1.8.4.2

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

* [PATCH v4 10/21] mtd: support BB SRAM on ICP DAS LP-8x4x
  2014-04-16 17:17                 ` Sergei Ianovich
  (?)
  (?)
@ 2014-04-16 17:17                   ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2014-04-16 17:17 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Randy Dunlap, Russell King,
	David Woodhouse, Brian Norris, Grant Likely, Heikki Krogerus,
	Lee Jones, Artem Bityutskiy, Robert Jarzmik, Michael Opdenacker,
	open list:OPEN FIRMWARE AND...,
	open list:DOCUMENTATION, open list:MEMORY TECHNOLOGY...

This provides an MTD device driver for 512kB of battery backed up SRAM
on ICPDAS LP-8X4X programmable automation controllers.

SRAM chip is connected via FPGA and is not accessible without a driver,
unlike flash memory which is wired to CPU MMU.

This SRAM becomes an excellent persisent storage of volatile process
data like counter values and sensor statuses. Storing those data in
flash or mmc card is not a viable solution.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
Reviewed-by: Brian Norris <computersforpeace@gmail.com>
---
   v3..v4 for Brian Norris 'Reviewed-by'
   * add doc file for DT binding
   * move DTS binding to a different patch (8/21)
   * drop unused include directive
   * drop safely unused callback
   * drop non-default partion probe types
   * drop duplicate error checks
   * drop duplicate error reporting
   * fixed error message on MTD registeration
   * fixed module removal routine

   v2..v3
   * no changes (except number 08/16 -> 10/21)

   v0..v2
   * use device tree
   * use devm helpers where possible

 .../devicetree/bindings/mtd/sram-lp8x4x.txt        |  22 +++
 arch/arm/configs/lp8x4x_defconfig                  |   1 +
 drivers/mtd/devices/Kconfig                        |  14 ++
 drivers/mtd/devices/Makefile                       |   1 +
 drivers/mtd/devices/sram_lp8x4x.c                  | 204 +++++++++++++++++++++
 5 files changed, 242 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mtd/sram-lp8x4x.txt
 create mode 100644 drivers/mtd/devices/sram_lp8x4x.c

diff --git a/Documentation/devicetree/bindings/mtd/sram-lp8x4x.txt b/Documentation/devicetree/bindings/mtd/sram-lp8x4x.txt
new file mode 100644
index 0000000..8b1e864
--- /dev/null
+++ b/Documentation/devicetree/bindings/mtd/sram-lp8x4x.txt
@@ -0,0 +1,22 @@
+512kB battery backed up SRAM on LP-8x4x industrial computers
+
+Required properties:
+- compatible : should be "icpdas,sram-lp8x4x"
+
+- reg: physical base addresses and region lengths of
+       * IO memory range
+       * SRAM page selector
+
+- eeprom-gpios : should point to active-low write enable GPIO
+
+SRAM chip is connected via FPGA and is not accessible without a driver,
+unlike flash memory which is wired to CPU MMU. Driver is essentially
+an address translation routine.
+
+Example:
+
+	sram@a000 {
+		compatible = "icpdas,sram-lp8x4x";
+		reg = <0xa000 0x1000
+		       0x901e 0x1>;
+	};
diff --git a/arch/arm/configs/lp8x4x_defconfig b/arch/arm/configs/lp8x4x_defconfig
index d60e37a..17a4e6f 100644
--- a/arch/arm/configs/lp8x4x_defconfig
+++ b/arch/arm/configs/lp8x4x_defconfig
@@ -57,6 +57,7 @@ CONFIG_MTD_CFI_ADV_OPTIONS=y
 CONFIG_MTD_CFI_GEOMETRY=y
 CONFIG_MTD_CFI_INTELEXT=y
 CONFIG_MTD_PHYSMAP_OF=y
+CONFIG_MTD_SRAM_LP8X4X=y
 CONFIG_PROC_DEVICETREE=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_LOOP_MIN_COUNT=2
diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig
index 1210bc2..fc8552b 100644
--- a/drivers/mtd/devices/Kconfig
+++ b/drivers/mtd/devices/Kconfig
@@ -225,4 +225,18 @@ config BCH_CONST_T
 	default 4
 endif
 
+config MTD_SRAM_LP8X4X
+	tristate "SRAM on ICPDAS LP-8X4X"
+	depends on OF && ARCH_PXA
+       ---help---
+	 This provides an MTD device driver for 512kiB of battery backed up SRAM
+	 on ICPDAS LP-8X4X programmable automation controllers.
+
+	 SRAM chip is connected via FPGA and is not accessible without a driver,
+	 unlike flash memory which is wired to CPU MMU.
+
+	 Say N, unless you plan to run this kernel on LP-8X4X.
+
+	 If you say M, the module will be called sram_lp8x4x.
+
 endmenu
diff --git a/drivers/mtd/devices/Makefile b/drivers/mtd/devices/Makefile
index c68868f..a7d86e2 100644
--- a/drivers/mtd/devices/Makefile
+++ b/drivers/mtd/devices/Makefile
@@ -17,6 +17,7 @@ obj-$(CONFIG_MTD_SPEAR_SMI)	+= spear_smi.o
 obj-$(CONFIG_MTD_SST25L)	+= sst25l.o
 obj-$(CONFIG_MTD_BCM47XXSFLASH)	+= bcm47xxsflash.o
 obj-$(CONFIG_MTD_ST_SPI_FSM)    += st_spi_fsm.o
+obj-$(CONFIG_MTD_SRAM_LP8X4X)	+= sram_lp8x4x.o
 
 
 CFLAGS_docg3.o			+= -I$(src)
diff --git a/drivers/mtd/devices/sram_lp8x4x.c b/drivers/mtd/devices/sram_lp8x4x.c
new file mode 100644
index 0000000..4cfa70b
--- /dev/null
+++ b/drivers/mtd/devices/sram_lp8x4x.c
@@ -0,0 +1,204 @@
+/*
+ *  linux/drivers/mtd/devices/lp8x4x_sram.c
+ *
+ *  MTD Driver for SRAM on ICPDAS LP-8x4x
+ *  Copyright (C) 2013 Sergei Ianovich <ynvich@gmail.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation or any later version.
+ */
+
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mtd/map.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/platform_device.h>
+#include <linux/of_device.h>
+#include <linux/slab.h>
+#include <linux/string_helpers.h>
+#include <linux/types.h>
+
+struct lp8x4x_sram_info {
+	void __iomem	*bank;
+	void __iomem	*virt;
+	struct mutex	lock;
+	unsigned	active_bank;
+	struct mtd_info	mtd;
+};
+
+static int
+lp8x4x_sram_erase(struct mtd_info *mtd, struct erase_info *instr)
+{
+	struct lp8x4x_sram_info *info = mtd->priv;
+	unsigned bank = instr->addr >> 11;
+	unsigned offset = (instr->addr & 0x7ff) << 1;
+	loff_t i;
+
+	mutex_lock(&info->lock);
+	if (unlikely(bank != info->active_bank)) {
+		info->active_bank = bank;
+		iowrite8(bank, info->bank);
+	}
+	for (i = 0; i < instr->len; i++) {
+		iowrite8(0xff, info->virt + offset);
+		offset += 2;
+		if (unlikely(offset == 0)) {
+			info->active_bank++;
+			iowrite8(info->active_bank, info->bank);
+		}
+	}
+	mutex_unlock(&info->lock);
+	instr->state = MTD_ERASE_DONE;
+	mtd_erase_callback(instr);
+
+	return 0;
+}
+
+static int
+lp8x4x_sram_write(struct mtd_info *mtd, loff_t to, size_t len,
+		size_t *retlen, const u_char *b)
+{
+	struct lp8x4x_sram_info *info = mtd->priv;
+	unsigned bank = to >> 11;
+	unsigned offset = (to & 0x7ff) << 1;
+	loff_t i;
+
+	mutex_lock(&info->lock);
+	if (unlikely(bank != info->active_bank)) {
+		info->active_bank = bank;
+		iowrite8(bank, info->bank);
+	}
+	for (i = 0; i < len; i++) {
+		iowrite8(b[i], info->virt + offset);
+		offset += 2;
+		if (unlikely(offset == 0)) {
+			info->active_bank++;
+			iowrite8(info->active_bank, info->bank);
+		}
+	}
+	mutex_unlock(&info->lock);
+	*retlen = len;
+	return 0;
+}
+
+static int
+lp8x4x_sram_read(struct mtd_info *mtd, loff_t from, size_t len,
+		size_t *retlen, u_char *b)
+{
+	struct lp8x4x_sram_info *info = mtd->priv;
+	unsigned bank = from >> 11;
+	unsigned offset = (from & 0x7ff) << 1;
+	loff_t i;
+
+	mutex_lock(&info->lock);
+	if (unlikely(bank != info->active_bank)) {
+		info->active_bank = bank;
+		iowrite8(bank, info->bank);
+	}
+	for (i = 0; i < len; i++) {
+		b[i] = ioread8(info->virt + offset);
+		offset += 2;
+		if (unlikely(offset == 0)) {
+			info->active_bank++;
+			iowrite8(info->active_bank, info->bank);
+		}
+	}
+	mutex_unlock(&info->lock);
+	*retlen = len;
+	return 0;
+}
+
+static struct of_device_id of_flash_match[] = {
+	{
+		.compatible	= "icpdas,sram-lp8x4x",
+	},
+	{ },
+};
+MODULE_DEVICE_TABLE(of, of_flash_match);
+
+static int
+lp8x4x_sram_probe(struct platform_device *pdev)
+{
+	const struct of_device_id *match;
+	struct lp8x4x_sram_info *info;
+	struct resource *res_virt, *res_bank;
+	char sz_str[16];
+	struct mtd_part_parser_data ppdata;
+	int err = 0;
+
+	match = of_match_device(of_flash_match, &pdev->dev);
+	if (!match)
+		return -EINVAL;
+
+	info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
+	if (!info)
+		return -ENOMEM;
+
+	res_virt = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	info->virt =  devm_ioremap_resource(&pdev->dev, res_virt);
+	if (IS_ERR(info->virt))
+		return PTR_ERR(info->virt);
+
+	res_bank = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	info->bank = devm_ioremap_resource(&pdev->dev, res_bank);
+	if (IS_ERR(info->bank))
+		return PTR_ERR(info->bank);
+
+	info->mtd.priv = info;
+	info->mtd.name = "SRAM";
+	info->mtd.type = MTD_RAM;
+	info->mtd.flags = MTD_CAP_RAM;
+	info->mtd.size = resource_size(res_virt) << 7;
+	info->mtd.erasesize = 512;
+	info->mtd.writesize = 4;
+	info->mtd._erase = lp8x4x_sram_erase;
+	info->mtd._write = lp8x4x_sram_write;
+	info->mtd._read = lp8x4x_sram_read;
+	info->mtd.owner = THIS_MODULE;
+
+	mutex_init(&info->lock);
+	iowrite8(info->active_bank, info->bank);
+	platform_set_drvdata(pdev, info);
+
+	ppdata.of_node = pdev->dev.of_node;
+	err = mtd_device_parse_register(&info->mtd, NULL, &ppdata,
+			NULL, 0);
+
+	if (err < 0) {
+		dev_err(&pdev->dev, "failed to register MTD\n");
+		return err;
+	}
+
+	string_get_size(info->mtd.size, STRING_UNITS_2, sz_str,
+			sizeof(sz_str));
+	dev_info(&pdev->dev, "using %s SRAM on LP-8X4X as %s\n", sz_str,
+			dev_name(&info->mtd.dev));
+	return 0;
+}
+
+static int
+lp8x4x_sram_remove(struct platform_device *dev)
+{
+	struct lp8x4x_sram_info *info = platform_get_drvdata(dev);
+	return mtd_device_unregister(&info->mtd);
+}
+
+static struct platform_driver lp8x4x_sram_driver = {
+	.driver = {
+		.name		= "sram-lp8x4x",
+		.owner		= THIS_MODULE,
+		.of_match_table = of_flash_match,
+	},
+	.probe		= lp8x4x_sram_probe,
+	.remove		= lp8x4x_sram_remove,
+};
+
+module_platform_driver(lp8x4x_sram_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Sergei Ianovich <ynvich@gmail.com>");
+MODULE_DESCRIPTION("MTD driver for SRAM on ICPDAS LP-8x4x");
-- 
1.8.4.2


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

* [PATCH v4 10/21] mtd: support BB SRAM on ICP DAS LP-8x4x
@ 2014-04-16 17:17                   ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2014-04-16 17:17 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Randy Dunlap, Russell King,
	David Woodhouse, Brian Norris, Grant Likely, Heikki Krogerus,
	Lee Jones, Artem Bityutskiy, Robert Jarzmik, Michael Opdenacker,
	open list:OPEN FIRMWARE AND...,
	open list:DOCUMENTATION, open list:MEMORY TECHNOLOGY...

This provides an MTD device driver for 512kB of battery backed up SRAM
on ICPDAS LP-8X4X programmable automation controllers.

SRAM chip is connected via FPGA and is not accessible without a driver,
unlike flash memory which is wired to CPU MMU.

This SRAM becomes an excellent persisent storage of volatile process
data like counter values and sensor statuses. Storing those data in
flash or mmc card is not a viable solution.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
Reviewed-by: Brian Norris <computersforpeace@gmail.com>
---
   v3..v4 for Brian Norris 'Reviewed-by'
   * add doc file for DT binding
   * move DTS binding to a different patch (8/21)
   * drop unused include directive
   * drop safely unused callback
   * drop non-default partion probe types
   * drop duplicate error checks
   * drop duplicate error reporting
   * fixed error message on MTD registeration
   * fixed module removal routine

   v2..v3
   * no changes (except number 08/16 -> 10/21)

   v0..v2
   * use device tree
   * use devm helpers where possible

 .../devicetree/bindings/mtd/sram-lp8x4x.txt        |  22 +++
 arch/arm/configs/lp8x4x_defconfig                  |   1 +
 drivers/mtd/devices/Kconfig                        |  14 ++
 drivers/mtd/devices/Makefile                       |   1 +
 drivers/mtd/devices/sram_lp8x4x.c                  | 204 +++++++++++++++++++++
 5 files changed, 242 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mtd/sram-lp8x4x.txt
 create mode 100644 drivers/mtd/devices/sram_lp8x4x.c

diff --git a/Documentation/devicetree/bindings/mtd/sram-lp8x4x.txt b/Documentation/devicetree/bindings/mtd/sram-lp8x4x.txt
new file mode 100644
index 0000000..8b1e864
--- /dev/null
+++ b/Documentation/devicetree/bindings/mtd/sram-lp8x4x.txt
@@ -0,0 +1,22 @@
+512kB battery backed up SRAM on LP-8x4x industrial computers
+
+Required properties:
+- compatible : should be "icpdas,sram-lp8x4x"
+
+- reg: physical base addresses and region lengths of
+       * IO memory range
+       * SRAM page selector
+
+- eeprom-gpios : should point to active-low write enable GPIO
+
+SRAM chip is connected via FPGA and is not accessible without a driver,
+unlike flash memory which is wired to CPU MMU. Driver is essentially
+an address translation routine.
+
+Example:
+
+	sram@a000 {
+		compatible = "icpdas,sram-lp8x4x";
+		reg = <0xa000 0x1000
+		       0x901e 0x1>;
+	};
diff --git a/arch/arm/configs/lp8x4x_defconfig b/arch/arm/configs/lp8x4x_defconfig
index d60e37a..17a4e6f 100644
--- a/arch/arm/configs/lp8x4x_defconfig
+++ b/arch/arm/configs/lp8x4x_defconfig
@@ -57,6 +57,7 @@ CONFIG_MTD_CFI_ADV_OPTIONS=y
 CONFIG_MTD_CFI_GEOMETRY=y
 CONFIG_MTD_CFI_INTELEXT=y
 CONFIG_MTD_PHYSMAP_OF=y
+CONFIG_MTD_SRAM_LP8X4X=y
 CONFIG_PROC_DEVICETREE=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_LOOP_MIN_COUNT=2
diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig
index 1210bc2..fc8552b 100644
--- a/drivers/mtd/devices/Kconfig
+++ b/drivers/mtd/devices/Kconfig
@@ -225,4 +225,18 @@ config BCH_CONST_T
 	default 4
 endif
 
+config MTD_SRAM_LP8X4X
+	tristate "SRAM on ICPDAS LP-8X4X"
+	depends on OF && ARCH_PXA
+       ---help---
+	 This provides an MTD device driver for 512kiB of battery backed up SRAM
+	 on ICPDAS LP-8X4X programmable automation controllers.
+
+	 SRAM chip is connected via FPGA and is not accessible without a driver,
+	 unlike flash memory which is wired to CPU MMU.
+
+	 Say N, unless you plan to run this kernel on LP-8X4X.
+
+	 If you say M, the module will be called sram_lp8x4x.
+
 endmenu
diff --git a/drivers/mtd/devices/Makefile b/drivers/mtd/devices/Makefile
index c68868f..a7d86e2 100644
--- a/drivers/mtd/devices/Makefile
+++ b/drivers/mtd/devices/Makefile
@@ -17,6 +17,7 @@ obj-$(CONFIG_MTD_SPEAR_SMI)	+= spear_smi.o
 obj-$(CONFIG_MTD_SST25L)	+= sst25l.o
 obj-$(CONFIG_MTD_BCM47XXSFLASH)	+= bcm47xxsflash.o
 obj-$(CONFIG_MTD_ST_SPI_FSM)    += st_spi_fsm.o
+obj-$(CONFIG_MTD_SRAM_LP8X4X)	+= sram_lp8x4x.o
 
 
 CFLAGS_docg3.o			+= -I$(src)
diff --git a/drivers/mtd/devices/sram_lp8x4x.c b/drivers/mtd/devices/sram_lp8x4x.c
new file mode 100644
index 0000000..4cfa70b
--- /dev/null
+++ b/drivers/mtd/devices/sram_lp8x4x.c
@@ -0,0 +1,204 @@
+/*
+ *  linux/drivers/mtd/devices/lp8x4x_sram.c
+ *
+ *  MTD Driver for SRAM on ICPDAS LP-8x4x
+ *  Copyright (C) 2013 Sergei Ianovich <ynvich@gmail.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation or any later version.
+ */
+
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mtd/map.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/platform_device.h>
+#include <linux/of_device.h>
+#include <linux/slab.h>
+#include <linux/string_helpers.h>
+#include <linux/types.h>
+
+struct lp8x4x_sram_info {
+	void __iomem	*bank;
+	void __iomem	*virt;
+	struct mutex	lock;
+	unsigned	active_bank;
+	struct mtd_info	mtd;
+};
+
+static int
+lp8x4x_sram_erase(struct mtd_info *mtd, struct erase_info *instr)
+{
+	struct lp8x4x_sram_info *info = mtd->priv;
+	unsigned bank = instr->addr >> 11;
+	unsigned offset = (instr->addr & 0x7ff) << 1;
+	loff_t i;
+
+	mutex_lock(&info->lock);
+	if (unlikely(bank != info->active_bank)) {
+		info->active_bank = bank;
+		iowrite8(bank, info->bank);
+	}
+	for (i = 0; i < instr->len; i++) {
+		iowrite8(0xff, info->virt + offset);
+		offset += 2;
+		if (unlikely(offset == 0)) {
+			info->active_bank++;
+			iowrite8(info->active_bank, info->bank);
+		}
+	}
+	mutex_unlock(&info->lock);
+	instr->state = MTD_ERASE_DONE;
+	mtd_erase_callback(instr);
+
+	return 0;
+}
+
+static int
+lp8x4x_sram_write(struct mtd_info *mtd, loff_t to, size_t len,
+		size_t *retlen, const u_char *b)
+{
+	struct lp8x4x_sram_info *info = mtd->priv;
+	unsigned bank = to >> 11;
+	unsigned offset = (to & 0x7ff) << 1;
+	loff_t i;
+
+	mutex_lock(&info->lock);
+	if (unlikely(bank != info->active_bank)) {
+		info->active_bank = bank;
+		iowrite8(bank, info->bank);
+	}
+	for (i = 0; i < len; i++) {
+		iowrite8(b[i], info->virt + offset);
+		offset += 2;
+		if (unlikely(offset == 0)) {
+			info->active_bank++;
+			iowrite8(info->active_bank, info->bank);
+		}
+	}
+	mutex_unlock(&info->lock);
+	*retlen = len;
+	return 0;
+}
+
+static int
+lp8x4x_sram_read(struct mtd_info *mtd, loff_t from, size_t len,
+		size_t *retlen, u_char *b)
+{
+	struct lp8x4x_sram_info *info = mtd->priv;
+	unsigned bank = from >> 11;
+	unsigned offset = (from & 0x7ff) << 1;
+	loff_t i;
+
+	mutex_lock(&info->lock);
+	if (unlikely(bank != info->active_bank)) {
+		info->active_bank = bank;
+		iowrite8(bank, info->bank);
+	}
+	for (i = 0; i < len; i++) {
+		b[i] = ioread8(info->virt + offset);
+		offset += 2;
+		if (unlikely(offset == 0)) {
+			info->active_bank++;
+			iowrite8(info->active_bank, info->bank);
+		}
+	}
+	mutex_unlock(&info->lock);
+	*retlen = len;
+	return 0;
+}
+
+static struct of_device_id of_flash_match[] = {
+	{
+		.compatible	= "icpdas,sram-lp8x4x",
+	},
+	{ },
+};
+MODULE_DEVICE_TABLE(of, of_flash_match);
+
+static int
+lp8x4x_sram_probe(struct platform_device *pdev)
+{
+	const struct of_device_id *match;
+	struct lp8x4x_sram_info *info;
+	struct resource *res_virt, *res_bank;
+	char sz_str[16];
+	struct mtd_part_parser_data ppdata;
+	int err = 0;
+
+	match = of_match_device(of_flash_match, &pdev->dev);
+	if (!match)
+		return -EINVAL;
+
+	info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
+	if (!info)
+		return -ENOMEM;
+
+	res_virt = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	info->virt =  devm_ioremap_resource(&pdev->dev, res_virt);
+	if (IS_ERR(info->virt))
+		return PTR_ERR(info->virt);
+
+	res_bank = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	info->bank = devm_ioremap_resource(&pdev->dev, res_bank);
+	if (IS_ERR(info->bank))
+		return PTR_ERR(info->bank);
+
+	info->mtd.priv = info;
+	info->mtd.name = "SRAM";
+	info->mtd.type = MTD_RAM;
+	info->mtd.flags = MTD_CAP_RAM;
+	info->mtd.size = resource_size(res_virt) << 7;
+	info->mtd.erasesize = 512;
+	info->mtd.writesize = 4;
+	info->mtd._erase = lp8x4x_sram_erase;
+	info->mtd._write = lp8x4x_sram_write;
+	info->mtd._read = lp8x4x_sram_read;
+	info->mtd.owner = THIS_MODULE;
+
+	mutex_init(&info->lock);
+	iowrite8(info->active_bank, info->bank);
+	platform_set_drvdata(pdev, info);
+
+	ppdata.of_node = pdev->dev.of_node;
+	err = mtd_device_parse_register(&info->mtd, NULL, &ppdata,
+			NULL, 0);
+
+	if (err < 0) {
+		dev_err(&pdev->dev, "failed to register MTD\n");
+		return err;
+	}
+
+	string_get_size(info->mtd.size, STRING_UNITS_2, sz_str,
+			sizeof(sz_str));
+	dev_info(&pdev->dev, "using %s SRAM on LP-8X4X as %s\n", sz_str,
+			dev_name(&info->mtd.dev));
+	return 0;
+}
+
+static int
+lp8x4x_sram_remove(struct platform_device *dev)
+{
+	struct lp8x4x_sram_info *info = platform_get_drvdata(dev);
+	return mtd_device_unregister(&info->mtd);
+}
+
+static struct platform_driver lp8x4x_sram_driver = {
+	.driver = {
+		.name		= "sram-lp8x4x",
+		.owner		= THIS_MODULE,
+		.of_match_table = of_flash_match,
+	},
+	.probe		= lp8x4x_sram_probe,
+	.remove		= lp8x4x_sram_remove,
+};
+
+module_platform_driver(lp8x4x_sram_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Sergei Ianovich <ynvich@gmail.com>");
+MODULE_DESCRIPTION("MTD driver for SRAM on ICPDAS LP-8x4x");
-- 
1.8.4.2

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

* [PATCH v4 10/21] mtd: support BB SRAM on ICP DAS LP-8x4x
@ 2014-04-16 17:17                   ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2014-04-16 17:17 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Mark Rutland, open list:OPEN FIRMWARE AND...,
	Heikki Krogerus, Russell King, open list:DOCUMENTATION,
	Pawel Moll, Ian Campbell, Lee Jones, Robert Jarzmik,
	Randy Dunlap, Artem Bityutskiy, Sergei Ianovich,
	Michael Opdenacker, Rob Herring, open list:MEMORY TECHNOLOGY...,
	Kumar Gala, Grant Likely, Brian Norris, David Woodhouse

This provides an MTD device driver for 512kB of battery backed up SRAM
on ICPDAS LP-8X4X programmable automation controllers.

SRAM chip is connected via FPGA and is not accessible without a driver,
unlike flash memory which is wired to CPU MMU.

This SRAM becomes an excellent persisent storage of volatile process
data like counter values and sensor statuses. Storing those data in
flash or mmc card is not a viable solution.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
Reviewed-by: Brian Norris <computersforpeace@gmail.com>
---
   v3..v4 for Brian Norris 'Reviewed-by'
   * add doc file for DT binding
   * move DTS binding to a different patch (8/21)
   * drop unused include directive
   * drop safely unused callback
   * drop non-default partion probe types
   * drop duplicate error checks
   * drop duplicate error reporting
   * fixed error message on MTD registeration
   * fixed module removal routine

   v2..v3
   * no changes (except number 08/16 -> 10/21)

   v0..v2
   * use device tree
   * use devm helpers where possible

 .../devicetree/bindings/mtd/sram-lp8x4x.txt        |  22 +++
 arch/arm/configs/lp8x4x_defconfig                  |   1 +
 drivers/mtd/devices/Kconfig                        |  14 ++
 drivers/mtd/devices/Makefile                       |   1 +
 drivers/mtd/devices/sram_lp8x4x.c                  | 204 +++++++++++++++++++++
 5 files changed, 242 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mtd/sram-lp8x4x.txt
 create mode 100644 drivers/mtd/devices/sram_lp8x4x.c

diff --git a/Documentation/devicetree/bindings/mtd/sram-lp8x4x.txt b/Documentation/devicetree/bindings/mtd/sram-lp8x4x.txt
new file mode 100644
index 0000000..8b1e864
--- /dev/null
+++ b/Documentation/devicetree/bindings/mtd/sram-lp8x4x.txt
@@ -0,0 +1,22 @@
+512kB battery backed up SRAM on LP-8x4x industrial computers
+
+Required properties:
+- compatible : should be "icpdas,sram-lp8x4x"
+
+- reg: physical base addresses and region lengths of
+       * IO memory range
+       * SRAM page selector
+
+- eeprom-gpios : should point to active-low write enable GPIO
+
+SRAM chip is connected via FPGA and is not accessible without a driver,
+unlike flash memory which is wired to CPU MMU. Driver is essentially
+an address translation routine.
+
+Example:
+
+	sram@a000 {
+		compatible = "icpdas,sram-lp8x4x";
+		reg = <0xa000 0x1000
+		       0x901e 0x1>;
+	};
diff --git a/arch/arm/configs/lp8x4x_defconfig b/arch/arm/configs/lp8x4x_defconfig
index d60e37a..17a4e6f 100644
--- a/arch/arm/configs/lp8x4x_defconfig
+++ b/arch/arm/configs/lp8x4x_defconfig
@@ -57,6 +57,7 @@ CONFIG_MTD_CFI_ADV_OPTIONS=y
 CONFIG_MTD_CFI_GEOMETRY=y
 CONFIG_MTD_CFI_INTELEXT=y
 CONFIG_MTD_PHYSMAP_OF=y
+CONFIG_MTD_SRAM_LP8X4X=y
 CONFIG_PROC_DEVICETREE=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_LOOP_MIN_COUNT=2
diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig
index 1210bc2..fc8552b 100644
--- a/drivers/mtd/devices/Kconfig
+++ b/drivers/mtd/devices/Kconfig
@@ -225,4 +225,18 @@ config BCH_CONST_T
 	default 4
 endif
 
+config MTD_SRAM_LP8X4X
+	tristate "SRAM on ICPDAS LP-8X4X"
+	depends on OF && ARCH_PXA
+       ---help---
+	 This provides an MTD device driver for 512kiB of battery backed up SRAM
+	 on ICPDAS LP-8X4X programmable automation controllers.
+
+	 SRAM chip is connected via FPGA and is not accessible without a driver,
+	 unlike flash memory which is wired to CPU MMU.
+
+	 Say N, unless you plan to run this kernel on LP-8X4X.
+
+	 If you say M, the module will be called sram_lp8x4x.
+
 endmenu
diff --git a/drivers/mtd/devices/Makefile b/drivers/mtd/devices/Makefile
index c68868f..a7d86e2 100644
--- a/drivers/mtd/devices/Makefile
+++ b/drivers/mtd/devices/Makefile
@@ -17,6 +17,7 @@ obj-$(CONFIG_MTD_SPEAR_SMI)	+= spear_smi.o
 obj-$(CONFIG_MTD_SST25L)	+= sst25l.o
 obj-$(CONFIG_MTD_BCM47XXSFLASH)	+= bcm47xxsflash.o
 obj-$(CONFIG_MTD_ST_SPI_FSM)    += st_spi_fsm.o
+obj-$(CONFIG_MTD_SRAM_LP8X4X)	+= sram_lp8x4x.o
 
 
 CFLAGS_docg3.o			+= -I$(src)
diff --git a/drivers/mtd/devices/sram_lp8x4x.c b/drivers/mtd/devices/sram_lp8x4x.c
new file mode 100644
index 0000000..4cfa70b
--- /dev/null
+++ b/drivers/mtd/devices/sram_lp8x4x.c
@@ -0,0 +1,204 @@
+/*
+ *  linux/drivers/mtd/devices/lp8x4x_sram.c
+ *
+ *  MTD Driver for SRAM on ICPDAS LP-8x4x
+ *  Copyright (C) 2013 Sergei Ianovich <ynvich@gmail.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation or any later version.
+ */
+
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mtd/map.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/platform_device.h>
+#include <linux/of_device.h>
+#include <linux/slab.h>
+#include <linux/string_helpers.h>
+#include <linux/types.h>
+
+struct lp8x4x_sram_info {
+	void __iomem	*bank;
+	void __iomem	*virt;
+	struct mutex	lock;
+	unsigned	active_bank;
+	struct mtd_info	mtd;
+};
+
+static int
+lp8x4x_sram_erase(struct mtd_info *mtd, struct erase_info *instr)
+{
+	struct lp8x4x_sram_info *info = mtd->priv;
+	unsigned bank = instr->addr >> 11;
+	unsigned offset = (instr->addr & 0x7ff) << 1;
+	loff_t i;
+
+	mutex_lock(&info->lock);
+	if (unlikely(bank != info->active_bank)) {
+		info->active_bank = bank;
+		iowrite8(bank, info->bank);
+	}
+	for (i = 0; i < instr->len; i++) {
+		iowrite8(0xff, info->virt + offset);
+		offset += 2;
+		if (unlikely(offset == 0)) {
+			info->active_bank++;
+			iowrite8(info->active_bank, info->bank);
+		}
+	}
+	mutex_unlock(&info->lock);
+	instr->state = MTD_ERASE_DONE;
+	mtd_erase_callback(instr);
+
+	return 0;
+}
+
+static int
+lp8x4x_sram_write(struct mtd_info *mtd, loff_t to, size_t len,
+		size_t *retlen, const u_char *b)
+{
+	struct lp8x4x_sram_info *info = mtd->priv;
+	unsigned bank = to >> 11;
+	unsigned offset = (to & 0x7ff) << 1;
+	loff_t i;
+
+	mutex_lock(&info->lock);
+	if (unlikely(bank != info->active_bank)) {
+		info->active_bank = bank;
+		iowrite8(bank, info->bank);
+	}
+	for (i = 0; i < len; i++) {
+		iowrite8(b[i], info->virt + offset);
+		offset += 2;
+		if (unlikely(offset == 0)) {
+			info->active_bank++;
+			iowrite8(info->active_bank, info->bank);
+		}
+	}
+	mutex_unlock(&info->lock);
+	*retlen = len;
+	return 0;
+}
+
+static int
+lp8x4x_sram_read(struct mtd_info *mtd, loff_t from, size_t len,
+		size_t *retlen, u_char *b)
+{
+	struct lp8x4x_sram_info *info = mtd->priv;
+	unsigned bank = from >> 11;
+	unsigned offset = (from & 0x7ff) << 1;
+	loff_t i;
+
+	mutex_lock(&info->lock);
+	if (unlikely(bank != info->active_bank)) {
+		info->active_bank = bank;
+		iowrite8(bank, info->bank);
+	}
+	for (i = 0; i < len; i++) {
+		b[i] = ioread8(info->virt + offset);
+		offset += 2;
+		if (unlikely(offset == 0)) {
+			info->active_bank++;
+			iowrite8(info->active_bank, info->bank);
+		}
+	}
+	mutex_unlock(&info->lock);
+	*retlen = len;
+	return 0;
+}
+
+static struct of_device_id of_flash_match[] = {
+	{
+		.compatible	= "icpdas,sram-lp8x4x",
+	},
+	{ },
+};
+MODULE_DEVICE_TABLE(of, of_flash_match);
+
+static int
+lp8x4x_sram_probe(struct platform_device *pdev)
+{
+	const struct of_device_id *match;
+	struct lp8x4x_sram_info *info;
+	struct resource *res_virt, *res_bank;
+	char sz_str[16];
+	struct mtd_part_parser_data ppdata;
+	int err = 0;
+
+	match = of_match_device(of_flash_match, &pdev->dev);
+	if (!match)
+		return -EINVAL;
+
+	info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
+	if (!info)
+		return -ENOMEM;
+
+	res_virt = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	info->virt =  devm_ioremap_resource(&pdev->dev, res_virt);
+	if (IS_ERR(info->virt))
+		return PTR_ERR(info->virt);
+
+	res_bank = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	info->bank = devm_ioremap_resource(&pdev->dev, res_bank);
+	if (IS_ERR(info->bank))
+		return PTR_ERR(info->bank);
+
+	info->mtd.priv = info;
+	info->mtd.name = "SRAM";
+	info->mtd.type = MTD_RAM;
+	info->mtd.flags = MTD_CAP_RAM;
+	info->mtd.size = resource_size(res_virt) << 7;
+	info->mtd.erasesize = 512;
+	info->mtd.writesize = 4;
+	info->mtd._erase = lp8x4x_sram_erase;
+	info->mtd._write = lp8x4x_sram_write;
+	info->mtd._read = lp8x4x_sram_read;
+	info->mtd.owner = THIS_MODULE;
+
+	mutex_init(&info->lock);
+	iowrite8(info->active_bank, info->bank);
+	platform_set_drvdata(pdev, info);
+
+	ppdata.of_node = pdev->dev.of_node;
+	err = mtd_device_parse_register(&info->mtd, NULL, &ppdata,
+			NULL, 0);
+
+	if (err < 0) {
+		dev_err(&pdev->dev, "failed to register MTD\n");
+		return err;
+	}
+
+	string_get_size(info->mtd.size, STRING_UNITS_2, sz_str,
+			sizeof(sz_str));
+	dev_info(&pdev->dev, "using %s SRAM on LP-8X4X as %s\n", sz_str,
+			dev_name(&info->mtd.dev));
+	return 0;
+}
+
+static int
+lp8x4x_sram_remove(struct platform_device *dev)
+{
+	struct lp8x4x_sram_info *info = platform_get_drvdata(dev);
+	return mtd_device_unregister(&info->mtd);
+}
+
+static struct platform_driver lp8x4x_sram_driver = {
+	.driver = {
+		.name		= "sram-lp8x4x",
+		.owner		= THIS_MODULE,
+		.of_match_table = of_flash_match,
+	},
+	.probe		= lp8x4x_sram_probe,
+	.remove		= lp8x4x_sram_remove,
+};
+
+module_platform_driver(lp8x4x_sram_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Sergei Ianovich <ynvich@gmail.com>");
+MODULE_DESCRIPTION("MTD driver for SRAM on ICPDAS LP-8x4x");
-- 
1.8.4.2

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

* [PATCH v4 10/21] mtd: support BB SRAM on ICP DAS LP-8x4x
@ 2014-04-16 17:17                   ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2014-04-16 17:17 UTC (permalink / raw)
  To: linux-arm-kernel

This provides an MTD device driver for 512kB of battery backed up SRAM
on ICPDAS LP-8X4X programmable automation controllers.

SRAM chip is connected via FPGA and is not accessible without a driver,
unlike flash memory which is wired to CPU MMU.

This SRAM becomes an excellent persisent storage of volatile process
data like counter values and sensor statuses. Storing those data in
flash or mmc card is not a viable solution.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
Reviewed-by: Brian Norris <computersforpeace@gmail.com>
---
   v3..v4 for Brian Norris 'Reviewed-by'
   * add doc file for DT binding
   * move DTS binding to a different patch (8/21)
   * drop unused include directive
   * drop safely unused callback
   * drop non-default partion probe types
   * drop duplicate error checks
   * drop duplicate error reporting
   * fixed error message on MTD registeration
   * fixed module removal routine

   v2..v3
   * no changes (except number 08/16 -> 10/21)

   v0..v2
   * use device tree
   * use devm helpers where possible

 .../devicetree/bindings/mtd/sram-lp8x4x.txt        |  22 +++
 arch/arm/configs/lp8x4x_defconfig                  |   1 +
 drivers/mtd/devices/Kconfig                        |  14 ++
 drivers/mtd/devices/Makefile                       |   1 +
 drivers/mtd/devices/sram_lp8x4x.c                  | 204 +++++++++++++++++++++
 5 files changed, 242 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mtd/sram-lp8x4x.txt
 create mode 100644 drivers/mtd/devices/sram_lp8x4x.c

diff --git a/Documentation/devicetree/bindings/mtd/sram-lp8x4x.txt b/Documentation/devicetree/bindings/mtd/sram-lp8x4x.txt
new file mode 100644
index 0000000..8b1e864
--- /dev/null
+++ b/Documentation/devicetree/bindings/mtd/sram-lp8x4x.txt
@@ -0,0 +1,22 @@
+512kB battery backed up SRAM on LP-8x4x industrial computers
+
+Required properties:
+- compatible : should be "icpdas,sram-lp8x4x"
+
+- reg: physical base addresses and region lengths of
+       * IO memory range
+       * SRAM page selector
+
+- eeprom-gpios : should point to active-low write enable GPIO
+
+SRAM chip is connected via FPGA and is not accessible without a driver,
+unlike flash memory which is wired to CPU MMU. Driver is essentially
+an address translation routine.
+
+Example:
+
+	sram at a000 {
+		compatible = "icpdas,sram-lp8x4x";
+		reg = <0xa000 0x1000
+		       0x901e 0x1>;
+	};
diff --git a/arch/arm/configs/lp8x4x_defconfig b/arch/arm/configs/lp8x4x_defconfig
index d60e37a..17a4e6f 100644
--- a/arch/arm/configs/lp8x4x_defconfig
+++ b/arch/arm/configs/lp8x4x_defconfig
@@ -57,6 +57,7 @@ CONFIG_MTD_CFI_ADV_OPTIONS=y
 CONFIG_MTD_CFI_GEOMETRY=y
 CONFIG_MTD_CFI_INTELEXT=y
 CONFIG_MTD_PHYSMAP_OF=y
+CONFIG_MTD_SRAM_LP8X4X=y
 CONFIG_PROC_DEVICETREE=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_LOOP_MIN_COUNT=2
diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig
index 1210bc2..fc8552b 100644
--- a/drivers/mtd/devices/Kconfig
+++ b/drivers/mtd/devices/Kconfig
@@ -225,4 +225,18 @@ config BCH_CONST_T
 	default 4
 endif
 
+config MTD_SRAM_LP8X4X
+	tristate "SRAM on ICPDAS LP-8X4X"
+	depends on OF && ARCH_PXA
+       ---help---
+	 This provides an MTD device driver for 512kiB of battery backed up SRAM
+	 on ICPDAS LP-8X4X programmable automation controllers.
+
+	 SRAM chip is connected via FPGA and is not accessible without a driver,
+	 unlike flash memory which is wired to CPU MMU.
+
+	 Say N, unless you plan to run this kernel on LP-8X4X.
+
+	 If you say M, the module will be called sram_lp8x4x.
+
 endmenu
diff --git a/drivers/mtd/devices/Makefile b/drivers/mtd/devices/Makefile
index c68868f..a7d86e2 100644
--- a/drivers/mtd/devices/Makefile
+++ b/drivers/mtd/devices/Makefile
@@ -17,6 +17,7 @@ obj-$(CONFIG_MTD_SPEAR_SMI)	+= spear_smi.o
 obj-$(CONFIG_MTD_SST25L)	+= sst25l.o
 obj-$(CONFIG_MTD_BCM47XXSFLASH)	+= bcm47xxsflash.o
 obj-$(CONFIG_MTD_ST_SPI_FSM)    += st_spi_fsm.o
+obj-$(CONFIG_MTD_SRAM_LP8X4X)	+= sram_lp8x4x.o
 
 
 CFLAGS_docg3.o			+= -I$(src)
diff --git a/drivers/mtd/devices/sram_lp8x4x.c b/drivers/mtd/devices/sram_lp8x4x.c
new file mode 100644
index 0000000..4cfa70b
--- /dev/null
+++ b/drivers/mtd/devices/sram_lp8x4x.c
@@ -0,0 +1,204 @@
+/*
+ *  linux/drivers/mtd/devices/lp8x4x_sram.c
+ *
+ *  MTD Driver for SRAM on ICPDAS LP-8x4x
+ *  Copyright (C) 2013 Sergei Ianovich <ynvich@gmail.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation or any later version.
+ */
+
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mtd/map.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/platform_device.h>
+#include <linux/of_device.h>
+#include <linux/slab.h>
+#include <linux/string_helpers.h>
+#include <linux/types.h>
+
+struct lp8x4x_sram_info {
+	void __iomem	*bank;
+	void __iomem	*virt;
+	struct mutex	lock;
+	unsigned	active_bank;
+	struct mtd_info	mtd;
+};
+
+static int
+lp8x4x_sram_erase(struct mtd_info *mtd, struct erase_info *instr)
+{
+	struct lp8x4x_sram_info *info = mtd->priv;
+	unsigned bank = instr->addr >> 11;
+	unsigned offset = (instr->addr & 0x7ff) << 1;
+	loff_t i;
+
+	mutex_lock(&info->lock);
+	if (unlikely(bank != info->active_bank)) {
+		info->active_bank = bank;
+		iowrite8(bank, info->bank);
+	}
+	for (i = 0; i < instr->len; i++) {
+		iowrite8(0xff, info->virt + offset);
+		offset += 2;
+		if (unlikely(offset == 0)) {
+			info->active_bank++;
+			iowrite8(info->active_bank, info->bank);
+		}
+	}
+	mutex_unlock(&info->lock);
+	instr->state = MTD_ERASE_DONE;
+	mtd_erase_callback(instr);
+
+	return 0;
+}
+
+static int
+lp8x4x_sram_write(struct mtd_info *mtd, loff_t to, size_t len,
+		size_t *retlen, const u_char *b)
+{
+	struct lp8x4x_sram_info *info = mtd->priv;
+	unsigned bank = to >> 11;
+	unsigned offset = (to & 0x7ff) << 1;
+	loff_t i;
+
+	mutex_lock(&info->lock);
+	if (unlikely(bank != info->active_bank)) {
+		info->active_bank = bank;
+		iowrite8(bank, info->bank);
+	}
+	for (i = 0; i < len; i++) {
+		iowrite8(b[i], info->virt + offset);
+		offset += 2;
+		if (unlikely(offset == 0)) {
+			info->active_bank++;
+			iowrite8(info->active_bank, info->bank);
+		}
+	}
+	mutex_unlock(&info->lock);
+	*retlen = len;
+	return 0;
+}
+
+static int
+lp8x4x_sram_read(struct mtd_info *mtd, loff_t from, size_t len,
+		size_t *retlen, u_char *b)
+{
+	struct lp8x4x_sram_info *info = mtd->priv;
+	unsigned bank = from >> 11;
+	unsigned offset = (from & 0x7ff) << 1;
+	loff_t i;
+
+	mutex_lock(&info->lock);
+	if (unlikely(bank != info->active_bank)) {
+		info->active_bank = bank;
+		iowrite8(bank, info->bank);
+	}
+	for (i = 0; i < len; i++) {
+		b[i] = ioread8(info->virt + offset);
+		offset += 2;
+		if (unlikely(offset == 0)) {
+			info->active_bank++;
+			iowrite8(info->active_bank, info->bank);
+		}
+	}
+	mutex_unlock(&info->lock);
+	*retlen = len;
+	return 0;
+}
+
+static struct of_device_id of_flash_match[] = {
+	{
+		.compatible	= "icpdas,sram-lp8x4x",
+	},
+	{ },
+};
+MODULE_DEVICE_TABLE(of, of_flash_match);
+
+static int
+lp8x4x_sram_probe(struct platform_device *pdev)
+{
+	const struct of_device_id *match;
+	struct lp8x4x_sram_info *info;
+	struct resource *res_virt, *res_bank;
+	char sz_str[16];
+	struct mtd_part_parser_data ppdata;
+	int err = 0;
+
+	match = of_match_device(of_flash_match, &pdev->dev);
+	if (!match)
+		return -EINVAL;
+
+	info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
+	if (!info)
+		return -ENOMEM;
+
+	res_virt = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	info->virt =  devm_ioremap_resource(&pdev->dev, res_virt);
+	if (IS_ERR(info->virt))
+		return PTR_ERR(info->virt);
+
+	res_bank = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	info->bank = devm_ioremap_resource(&pdev->dev, res_bank);
+	if (IS_ERR(info->bank))
+		return PTR_ERR(info->bank);
+
+	info->mtd.priv = info;
+	info->mtd.name = "SRAM";
+	info->mtd.type = MTD_RAM;
+	info->mtd.flags = MTD_CAP_RAM;
+	info->mtd.size = resource_size(res_virt) << 7;
+	info->mtd.erasesize = 512;
+	info->mtd.writesize = 4;
+	info->mtd._erase = lp8x4x_sram_erase;
+	info->mtd._write = lp8x4x_sram_write;
+	info->mtd._read = lp8x4x_sram_read;
+	info->mtd.owner = THIS_MODULE;
+
+	mutex_init(&info->lock);
+	iowrite8(info->active_bank, info->bank);
+	platform_set_drvdata(pdev, info);
+
+	ppdata.of_node = pdev->dev.of_node;
+	err = mtd_device_parse_register(&info->mtd, NULL, &ppdata,
+			NULL, 0);
+
+	if (err < 0) {
+		dev_err(&pdev->dev, "failed to register MTD\n");
+		return err;
+	}
+
+	string_get_size(info->mtd.size, STRING_UNITS_2, sz_str,
+			sizeof(sz_str));
+	dev_info(&pdev->dev, "using %s SRAM on LP-8X4X as %s\n", sz_str,
+			dev_name(&info->mtd.dev));
+	return 0;
+}
+
+static int
+lp8x4x_sram_remove(struct platform_device *dev)
+{
+	struct lp8x4x_sram_info *info = platform_get_drvdata(dev);
+	return mtd_device_unregister(&info->mtd);
+}
+
+static struct platform_driver lp8x4x_sram_driver = {
+	.driver = {
+		.name		= "sram-lp8x4x",
+		.owner		= THIS_MODULE,
+		.of_match_table = of_flash_match,
+	},
+	.probe		= lp8x4x_sram_probe,
+	.remove		= lp8x4x_sram_remove,
+};
+
+module_platform_driver(lp8x4x_sram_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Sergei Ianovich <ynvich@gmail.com>");
+MODULE_DESCRIPTION("MTD driver for SRAM on ICPDAS LP-8x4x");
-- 
1.8.4.2

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

* [PATCH v4 11/21] ARM: pxa: support ICP DAS LP-8x4x FPGA irq
  2014-04-16 17:17                 ` Sergei Ianovich
  (?)
@ 2014-04-16 17:17                   ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2014-04-16 17:17 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Arnd Bergmann, Rob Herring, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala, Randy Dunlap,
	Thomas Gleixner, Grant Likely, Linus Walleij,
	open list:OPEN FIRMWARE AND...,
	open list:DOCUMENTATION

ICP DAS LP-8x4x contains FPGA chip. The chip functions as an interrupt
source providing 16 additional interrupts among other things. The
interrupt lines are muxed to a GPIO pin of a 2nd level PXA-GPIO
interrupt controller. GPIO pins of the 2nd level controller are in turn
muxed to a CPU interrupt line.

Until pxa is completely converted to device tree, it is impossible
to use IRQCHIP_DECLARE() and the irqdomain needs to added manually.
Drivers for the on-CPU IRQs and GPIO-IRQs are loaded using
postcore_initcall(). We need to have all irq domain drivers loaded prior
to DT parsing in order to allow normal initialization of IRQ resources
with DT.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
CC: Arnd Bergmann <arnd@arndb.de>
---
   v3.2..v4
   * move DTS binding to a different patch (8/21)

   v3.1..v3.2
   fixes to apply Linus Walleij's "Reviewed-by":
   * add kerneldoc comment for state container struct
   * rename irq -> hwirq for clarity
   * drop overzealous error checks from the hotpaths

   v3..v3.1
   fixes according to Linus Walleij review comments:
   * update commit message
   * use state container instead of global variables
   * get hardware irq nums from irq_data, don't calculate them
   * use BIT() macro
   * add defines for system irq register masks
   * replace cycle control variable with break
   * use better names for resource variables
   * add a linear domain instead of a legacy one
   * use irq_create_mapping() instead of irq_alloc_desc()

   v2..v3
   * no changes (except number 09/16 -> 11/21)

   v0..v2
   * extract irqchip and move to drivers/irqchip/
   * use device tree
   * use devm helpers where possible

 .../bindings/interrupt-controller/irq-lp8x4x.txt   |  49 +++++
 drivers/irqchip/Kconfig                            |   5 +
 drivers/irqchip/Makefile                           |   1 +
 drivers/irqchip/irq-lp8x4x.c                       | 227 +++++++++++++++++++++
 4 files changed, 282 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/interrupt-controller/irq-lp8x4x.txt
 create mode 100644 drivers/irqchip/irq-lp8x4x.c

diff --git a/Documentation/devicetree/bindings/interrupt-controller/irq-lp8x4x.txt b/Documentation/devicetree/bindings/interrupt-controller/irq-lp8x4x.txt
new file mode 100644
index 0000000..c8940d2
--- /dev/null
+++ b/Documentation/devicetree/bindings/interrupt-controller/irq-lp8x4x.txt
@@ -0,0 +1,49 @@
+ICP DAS LP-8x4x FPGA Interrupt Controller
+
+ICP DAS LP-8x4x contains FPGA chip. The chip functions as a interrupt
+source providing 16 additional interrupts among other things.
+
+Required properties:
+- compatible : should be "icpdas,irq-lp8x4x"
+
+- reg: physical base address of the controller and length of memory mapped
+  region.
+
+- interrupt-controller : identifies the node as an interrupt controller
+
+- #interrupt-cells : should be 1
+
+- interrupts : should provide interrupt
+
+- interrupt-parent : should provide a link to interrupt controller either
+		     explicitly and implicitly from a parent node
+
+Example:
+
+	fpga: fpga@17000006 {
+		compatible = "icpdas,irq-lp8x4x";
+		reg = <0x17000006 0x16>;
+		interrupt-parent = <&gpio>;
+		interrupts = <3 IRQ_TYPE_EDGE_RISING>;
+		#interrupt-cells = <1>;
+		interrupt-controller;
+		status = "okay";
+	};
+
+	uart@17009050 {
+		compatible = "icpdas,uart-lp8x4x";
+		reg = <0x17009050 0x10
+		       0x17009030 0x02>;
+		interrupt-parent = <&fpga>;
+		interrupts = <13>;
+		status = "okay";
+	};
+
+	uart@17009060 {
+		compatible = "icpdas,uart-lp8x4x";
+		reg = <0x17009060 0x10
+		       0x17009032 0x02>;
+		interrupt-parent = <&fpga>;
+		interrupts = <14>;
+		status = "okay";
+	};
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index d770f74..ede3237 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -47,6 +47,11 @@ config CLPS711X_IRQCHIP
 	select SPARSE_IRQ
 	default y
 
+config LP8X4X_IRQ
+	bool
+	depends on OF && ARCH_PXA
+	select IRQ_DOMAIN
+
 config ORION_IRQCHIP
 	bool
 	select IRQ_DOMAIN
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index f180f8d..94f82c7 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -29,3 +29,4 @@ obj-$(CONFIG_TB10X_IRQC)		+= irq-tb10x.o
 obj-$(CONFIG_XTENSA)			+= irq-xtensa-pic.o
 obj-$(CONFIG_XTENSA_MX)			+= irq-xtensa-mx.o
 obj-$(CONFIG_IRQ_CROSSBAR)		+= irq-crossbar.o
+obj-$(CONFIG_LP8X4X_IRQ)		+= irq-lp8x4x.o
diff --git a/drivers/irqchip/irq-lp8x4x.c b/drivers/irqchip/irq-lp8x4x.c
new file mode 100644
index 0000000..12ccbb03
--- /dev/null
+++ b/drivers/irqchip/irq-lp8x4x.c
@@ -0,0 +1,227 @@
+/*
+ *  linux/drivers/irqchip/irq-lp8x4x.c
+ *
+ *  Support for ICP DAS LP-8x4x FPGA irq
+ *  Copyright (C) 2013 Sergei Ianovich <ynvich@gmail.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation or any later version.
+ */
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/irqchip/chained_irq.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+#define EOI			0x00000000
+#define INSINT			0x00000002
+#define ENSYSINT		0x00000004
+#define PRIMINT			0x00000006
+#define PRIMINT_MASK		0xe0
+#define SECOINT			0x00000008
+#define SECOINT_MASK		0x1f
+#define ENRISEINT		0x0000000A
+#define CLRRISEINT		0x0000000C
+#define ENHILVINT		0x0000000E
+#define CLRHILVINT		0x00000010
+#define ENFALLINT		0x00000012
+#define CLRFALLINT		0x00000014
+#define IRQ_MEM_SIZE		0x00000016
+#define LP8X4X_NUM_IRQ_DEFAULT	16
+
+/**
+ * struct lp8x4x_irq_data - LP8X4X custom irq controller state container
+ * @base:               base IO memory address
+ * @irq_domain:         Interrupt translation domain; responsible for mapping
+ *                      between hwirq number and linux irq number
+ * @irq_sys_enabled:    mask keeping track of interrupts enabled in the
+ *                      register which vendor calls 'system'
+ * @irq_high_enabled:   mask keeping track of interrupts enabled in the
+ *                      register which vendor calls 'high'
+ *
+ * The structure implements State Container from
+ * Documentation/driver-model/design-patterns.txt
+ */
+
+struct lp8x4x_irq_data {
+	void			*base;
+	struct irq_domain	*domain;
+	unsigned char		irq_sys_enabled;
+	unsigned char		irq_high_enabled;
+};
+
+static void lp8x4x_mask_irq(struct irq_data *d)
+{
+	unsigned mask;
+	unsigned long hwirq = d->hwirq;
+	struct lp8x4x_irq_data *host = irq_data_get_irq_chip_data(d);
+
+	if (hwirq < 8) {
+		host->irq_high_enabled &= ~BIT(hwirq);
+
+		mask = ioread8(host->base + ENHILVINT);
+		mask &= ~BIT(hwirq);
+		iowrite8(mask, host->base + ENHILVINT);
+	} else {
+		hwirq -= 8;
+		host->irq_sys_enabled &= ~BIT(hwirq);
+
+		mask = ioread8(host->base + ENSYSINT);
+		mask &= ~BIT(hwirq);
+		iowrite8(mask, host->base + ENSYSINT);
+	}
+}
+
+static void lp8x4x_unmask_irq(struct irq_data *d)
+{
+	unsigned mask;
+	unsigned long hwirq = d->hwirq;
+	struct lp8x4x_irq_data *host = irq_data_get_irq_chip_data(d);
+
+	if (hwirq < 8) {
+		host->irq_high_enabled |= BIT(hwirq);
+		mask = ioread8(host->base + CLRHILVINT);
+		mask |= BIT(hwirq);
+		iowrite8(mask, host->base + CLRHILVINT);
+
+		mask = ioread8(host->base + ENHILVINT);
+		mask |= BIT(hwirq);
+		iowrite8(mask, host->base + ENHILVINT);
+	} else {
+		hwirq -= 8;
+		host->irq_sys_enabled |= BIT(hwirq);
+
+		mask = ioread8(host->base + SECOINT);
+		mask |= BIT(hwirq);
+		iowrite8(mask, host->base + SECOINT);
+
+		mask = ioread8(host->base + ENSYSINT);
+		mask |= BIT(hwirq);
+		iowrite8(mask, host->base + ENSYSINT);
+	}
+}
+
+static struct irq_chip lp8x4x_irq_chip = {
+	.name			= "FPGA",
+	.irq_ack		= lp8x4x_mask_irq,
+	.irq_mask		= lp8x4x_mask_irq,
+	.irq_mask_ack		= lp8x4x_mask_irq,
+	.irq_unmask		= lp8x4x_unmask_irq,
+};
+
+static void lp8x4x_irq_handler(unsigned int irq, struct irq_desc *desc)
+{
+	int n;
+	unsigned long mask;
+	struct irq_chip *chip = irq_desc_get_chip(desc);
+	struct lp8x4x_irq_data *host = irq_desc_get_handler_data(desc);
+
+	chained_irq_enter(chip, desc);
+
+	for (;;) {
+		mask = ioread8(host->base + CLRHILVINT) & 0xff;
+		mask |= (ioread8(host->base + SECOINT) & SECOINT_MASK) << 8;
+		mask |= (ioread8(host->base + PRIMINT) & PRIMINT_MASK) << 8;
+		mask &= host->irq_high_enabled | (host->irq_sys_enabled << 8);
+		if (mask == 0)
+			break;
+		for_each_set_bit(n, &mask, BITS_PER_LONG)
+			generic_handle_irq(irq_find_mapping(host->domain, n));
+	}
+
+	iowrite8(0, host->base + EOI);
+	chained_irq_exit(chip, desc);
+}
+
+static int lp8x4x_irq_domain_map(struct irq_domain *d, unsigned int irq,
+				 irq_hw_number_t hw)
+{
+	struct lp8x4x_irq_data *host = d->host_data;
+	int err;
+
+	err = irq_set_chip_data(irq, host);
+	if (err < 0)
+		return err;
+
+	irq_set_chip_and_handler(irq, &lp8x4x_irq_chip, handle_level_irq);
+	set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+	return 0;
+}
+
+const struct irq_domain_ops lp8x4x_irq_domain_ops = {
+	.map	= lp8x4x_irq_domain_map,
+	.xlate	= irq_domain_xlate_onecell,
+};
+
+static struct of_device_id lp8x4x_irq_dt_ids[] = {
+	{ .compatible = "icpdas,irq-lp8x4x", },
+	{}
+};
+
+static int lp8x4x_irq_probe(struct platform_device *pdev)
+{
+	struct resource *res_mem, *res_irq;
+	struct device_node *np = pdev->dev.of_node;
+	struct lp8x4x_irq_data *host;
+	int i, err;
+
+	res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!res_mem || !res_irq || resource_size(res_mem) < IRQ_MEM_SIZE)
+		return -ENODEV;
+
+	host = devm_kzalloc(&pdev->dev, sizeof(*host), GFP_KERNEL);
+	if (!host)
+		return -ENODEV;
+
+	host->base = devm_ioremap_resource(&pdev->dev, res_mem);
+	if (!host->base) {
+		dev_err(&pdev->dev, "Failed to ioremap %p\n", host->base);
+		return -EFAULT;
+	}
+
+	host->domain = irq_domain_add_linear(np, LP8X4X_NUM_IRQ_DEFAULT,
+				       &lp8x4x_irq_domain_ops, host);
+	if (!host->domain) {
+		dev_err(&pdev->dev, "Failed to add IRQ domain\n");
+		return -ENOMEM;
+	}
+
+	for (i = 0; i < LP8X4X_NUM_IRQ_DEFAULT; i++) {
+		err = irq_create_mapping(host->domain, i);
+		if (err < 0)
+			dev_err(&pdev->dev, "Failed to map IRQ %i\n", i);
+	}
+
+	/* Initialize chip registers */
+	iowrite8(0, host->base + CLRRISEINT);
+	iowrite8(0, host->base + ENRISEINT);
+	iowrite8(0, host->base + CLRFALLINT);
+	iowrite8(0, host->base + ENFALLINT);
+	iowrite8(0, host->base + CLRHILVINT);
+	iowrite8(0, host->base + ENHILVINT);
+	iowrite8(0, host->base + ENSYSINT);
+	iowrite8(0, host->base + SECOINT);
+
+	irq_set_handler_data(res_irq->start, host);
+	irq_set_chained_handler(res_irq->start, lp8x4x_irq_handler);
+
+	return 0;
+}
+
+static struct platform_driver lp8x4x_irq_driver = {
+	.probe		= lp8x4x_irq_probe,
+	.driver		= {
+		.name	= "irq-lp8x4x",
+		.of_match_table = lp8x4x_irq_dt_ids,
+	},
+};
+
+static int __init lp8x4x_irq_init(void)
+{
+	return platform_driver_register(&lp8x4x_irq_driver);
+}
+postcore_initcall(lp8x4x_irq_init);
-- 
1.8.4.2


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

* [PATCH v4 11/21] ARM: pxa: support ICP DAS LP-8x4x FPGA irq
@ 2014-04-16 17:17                   ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2014-04-16 17:17 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Arnd Bergmann, Rob Herring, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala, Randy Dunlap,
	Thomas Gleixner, Grant Likely, Linus Walleij,
	open list:OPEN FIRMWARE AND...,
	open list:DOCUMENTATION

ICP DAS LP-8x4x contains FPGA chip. The chip functions as an interrupt
source providing 16 additional interrupts among other things. The
interrupt lines are muxed to a GPIO pin of a 2nd level PXA-GPIO
interrupt controller. GPIO pins of the 2nd level controller are in turn
muxed to a CPU interrupt line.

Until pxa is completely converted to device tree, it is impossible
to use IRQCHIP_DECLARE() and the irqdomain needs to added manually.
Drivers for the on-CPU IRQs and GPIO-IRQs are loaded using
postcore_initcall(). We need to have all irq domain drivers loaded prior
to DT parsing in order to allow normal initialization of IRQ resources
with DT.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
CC: Arnd Bergmann <arnd@arndb.de>
---
   v3.2..v4
   * move DTS binding to a different patch (8/21)

   v3.1..v3.2
   fixes to apply Linus Walleij's "Reviewed-by":
   * add kerneldoc comment for state container struct
   * rename irq -> hwirq for clarity
   * drop overzealous error checks from the hotpaths

   v3..v3.1
   fixes according to Linus Walleij review comments:
   * update commit message
   * use state container instead of global variables
   * get hardware irq nums from irq_data, don't calculate them
   * use BIT() macro
   * add defines for system irq register masks
   * replace cycle control variable with break
   * use better names for resource variables
   * add a linear domain instead of a legacy one
   * use irq_create_mapping() instead of irq_alloc_desc()

   v2..v3
   * no changes (except number 09/16 -> 11/21)

   v0..v2
   * extract irqchip and move to drivers/irqchip/
   * use device tree
   * use devm helpers where possible

 .../bindings/interrupt-controller/irq-lp8x4x.txt   |  49 +++++
 drivers/irqchip/Kconfig                            |   5 +
 drivers/irqchip/Makefile                           |   1 +
 drivers/irqchip/irq-lp8x4x.c                       | 227 +++++++++++++++++++++
 4 files changed, 282 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/interrupt-controller/irq-lp8x4x.txt
 create mode 100644 drivers/irqchip/irq-lp8x4x.c

diff --git a/Documentation/devicetree/bindings/interrupt-controller/irq-lp8x4x.txt b/Documentation/devicetree/bindings/interrupt-controller/irq-lp8x4x.txt
new file mode 100644
index 0000000..c8940d2
--- /dev/null
+++ b/Documentation/devicetree/bindings/interrupt-controller/irq-lp8x4x.txt
@@ -0,0 +1,49 @@
+ICP DAS LP-8x4x FPGA Interrupt Controller
+
+ICP DAS LP-8x4x contains FPGA chip. The chip functions as a interrupt
+source providing 16 additional interrupts among other things.
+
+Required properties:
+- compatible : should be "icpdas,irq-lp8x4x"
+
+- reg: physical base address of the controller and length of memory mapped
+  region.
+
+- interrupt-controller : identifies the node as an interrupt controller
+
+- #interrupt-cells : should be 1
+
+- interrupts : should provide interrupt
+
+- interrupt-parent : should provide a link to interrupt controller either
+		     explicitly and implicitly from a parent node
+
+Example:
+
+	fpga: fpga@17000006 {
+		compatible = "icpdas,irq-lp8x4x";
+		reg = <0x17000006 0x16>;
+		interrupt-parent = <&gpio>;
+		interrupts = <3 IRQ_TYPE_EDGE_RISING>;
+		#interrupt-cells = <1>;
+		interrupt-controller;
+		status = "okay";
+	};
+
+	uart@17009050 {
+		compatible = "icpdas,uart-lp8x4x";
+		reg = <0x17009050 0x10
+		       0x17009030 0x02>;
+		interrupt-parent = <&fpga>;
+		interrupts = <13>;
+		status = "okay";
+	};
+
+	uart@17009060 {
+		compatible = "icpdas,uart-lp8x4x";
+		reg = <0x17009060 0x10
+		       0x17009032 0x02>;
+		interrupt-parent = <&fpga>;
+		interrupts = <14>;
+		status = "okay";
+	};
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index d770f74..ede3237 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -47,6 +47,11 @@ config CLPS711X_IRQCHIP
 	select SPARSE_IRQ
 	default y
 
+config LP8X4X_IRQ
+	bool
+	depends on OF && ARCH_PXA
+	select IRQ_DOMAIN
+
 config ORION_IRQCHIP
 	bool
 	select IRQ_DOMAIN
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index f180f8d..94f82c7 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -29,3 +29,4 @@ obj-$(CONFIG_TB10X_IRQC)		+= irq-tb10x.o
 obj-$(CONFIG_XTENSA)			+= irq-xtensa-pic.o
 obj-$(CONFIG_XTENSA_MX)			+= irq-xtensa-mx.o
 obj-$(CONFIG_IRQ_CROSSBAR)		+= irq-crossbar.o
+obj-$(CONFIG_LP8X4X_IRQ)		+= irq-lp8x4x.o
diff --git a/drivers/irqchip/irq-lp8x4x.c b/drivers/irqchip/irq-lp8x4x.c
new file mode 100644
index 0000000..12ccbb03
--- /dev/null
+++ b/drivers/irqchip/irq-lp8x4x.c
@@ -0,0 +1,227 @@
+/*
+ *  linux/drivers/irqchip/irq-lp8x4x.c
+ *
+ *  Support for ICP DAS LP-8x4x FPGA irq
+ *  Copyright (C) 2013 Sergei Ianovich <ynvich@gmail.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation or any later version.
+ */
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/irqchip/chained_irq.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+#define EOI			0x00000000
+#define INSINT			0x00000002
+#define ENSYSINT		0x00000004
+#define PRIMINT			0x00000006
+#define PRIMINT_MASK		0xe0
+#define SECOINT			0x00000008
+#define SECOINT_MASK		0x1f
+#define ENRISEINT		0x0000000A
+#define CLRRISEINT		0x0000000C
+#define ENHILVINT		0x0000000E
+#define CLRHILVINT		0x00000010
+#define ENFALLINT		0x00000012
+#define CLRFALLINT		0x00000014
+#define IRQ_MEM_SIZE		0x00000016
+#define LP8X4X_NUM_IRQ_DEFAULT	16
+
+/**
+ * struct lp8x4x_irq_data - LP8X4X custom irq controller state container
+ * @base:               base IO memory address
+ * @irq_domain:         Interrupt translation domain; responsible for mapping
+ *                      between hwirq number and linux irq number
+ * @irq_sys_enabled:    mask keeping track of interrupts enabled in the
+ *                      register which vendor calls 'system'
+ * @irq_high_enabled:   mask keeping track of interrupts enabled in the
+ *                      register which vendor calls 'high'
+ *
+ * The structure implements State Container from
+ * Documentation/driver-model/design-patterns.txt
+ */
+
+struct lp8x4x_irq_data {
+	void			*base;
+	struct irq_domain	*domain;
+	unsigned char		irq_sys_enabled;
+	unsigned char		irq_high_enabled;
+};
+
+static void lp8x4x_mask_irq(struct irq_data *d)
+{
+	unsigned mask;
+	unsigned long hwirq = d->hwirq;
+	struct lp8x4x_irq_data *host = irq_data_get_irq_chip_data(d);
+
+	if (hwirq < 8) {
+		host->irq_high_enabled &= ~BIT(hwirq);
+
+		mask = ioread8(host->base + ENHILVINT);
+		mask &= ~BIT(hwirq);
+		iowrite8(mask, host->base + ENHILVINT);
+	} else {
+		hwirq -= 8;
+		host->irq_sys_enabled &= ~BIT(hwirq);
+
+		mask = ioread8(host->base + ENSYSINT);
+		mask &= ~BIT(hwirq);
+		iowrite8(mask, host->base + ENSYSINT);
+	}
+}
+
+static void lp8x4x_unmask_irq(struct irq_data *d)
+{
+	unsigned mask;
+	unsigned long hwirq = d->hwirq;
+	struct lp8x4x_irq_data *host = irq_data_get_irq_chip_data(d);
+
+	if (hwirq < 8) {
+		host->irq_high_enabled |= BIT(hwirq);
+		mask = ioread8(host->base + CLRHILVINT);
+		mask |= BIT(hwirq);
+		iowrite8(mask, host->base + CLRHILVINT);
+
+		mask = ioread8(host->base + ENHILVINT);
+		mask |= BIT(hwirq);
+		iowrite8(mask, host->base + ENHILVINT);
+	} else {
+		hwirq -= 8;
+		host->irq_sys_enabled |= BIT(hwirq);
+
+		mask = ioread8(host->base + SECOINT);
+		mask |= BIT(hwirq);
+		iowrite8(mask, host->base + SECOINT);
+
+		mask = ioread8(host->base + ENSYSINT);
+		mask |= BIT(hwirq);
+		iowrite8(mask, host->base + ENSYSINT);
+	}
+}
+
+static struct irq_chip lp8x4x_irq_chip = {
+	.name			= "FPGA",
+	.irq_ack		= lp8x4x_mask_irq,
+	.irq_mask		= lp8x4x_mask_irq,
+	.irq_mask_ack		= lp8x4x_mask_irq,
+	.irq_unmask		= lp8x4x_unmask_irq,
+};
+
+static void lp8x4x_irq_handler(unsigned int irq, struct irq_desc *desc)
+{
+	int n;
+	unsigned long mask;
+	struct irq_chip *chip = irq_desc_get_chip(desc);
+	struct lp8x4x_irq_data *host = irq_desc_get_handler_data(desc);
+
+	chained_irq_enter(chip, desc);
+
+	for (;;) {
+		mask = ioread8(host->base + CLRHILVINT) & 0xff;
+		mask |= (ioread8(host->base + SECOINT) & SECOINT_MASK) << 8;
+		mask |= (ioread8(host->base + PRIMINT) & PRIMINT_MASK) << 8;
+		mask &= host->irq_high_enabled | (host->irq_sys_enabled << 8);
+		if (mask == 0)
+			break;
+		for_each_set_bit(n, &mask, BITS_PER_LONG)
+			generic_handle_irq(irq_find_mapping(host->domain, n));
+	}
+
+	iowrite8(0, host->base + EOI);
+	chained_irq_exit(chip, desc);
+}
+
+static int lp8x4x_irq_domain_map(struct irq_domain *d, unsigned int irq,
+				 irq_hw_number_t hw)
+{
+	struct lp8x4x_irq_data *host = d->host_data;
+	int err;
+
+	err = irq_set_chip_data(irq, host);
+	if (err < 0)
+		return err;
+
+	irq_set_chip_and_handler(irq, &lp8x4x_irq_chip, handle_level_irq);
+	set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+	return 0;
+}
+
+const struct irq_domain_ops lp8x4x_irq_domain_ops = {
+	.map	= lp8x4x_irq_domain_map,
+	.xlate	= irq_domain_xlate_onecell,
+};
+
+static struct of_device_id lp8x4x_irq_dt_ids[] = {
+	{ .compatible = "icpdas,irq-lp8x4x", },
+	{}
+};
+
+static int lp8x4x_irq_probe(struct platform_device *pdev)
+{
+	struct resource *res_mem, *res_irq;
+	struct device_node *np = pdev->dev.of_node;
+	struct lp8x4x_irq_data *host;
+	int i, err;
+
+	res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!res_mem || !res_irq || resource_size(res_mem) < IRQ_MEM_SIZE)
+		return -ENODEV;
+
+	host = devm_kzalloc(&pdev->dev, sizeof(*host), GFP_KERNEL);
+	if (!host)
+		return -ENODEV;
+
+	host->base = devm_ioremap_resource(&pdev->dev, res_mem);
+	if (!host->base) {
+		dev_err(&pdev->dev, "Failed to ioremap %p\n", host->base);
+		return -EFAULT;
+	}
+
+	host->domain = irq_domain_add_linear(np, LP8X4X_NUM_IRQ_DEFAULT,
+				       &lp8x4x_irq_domain_ops, host);
+	if (!host->domain) {
+		dev_err(&pdev->dev, "Failed to add IRQ domain\n");
+		return -ENOMEM;
+	}
+
+	for (i = 0; i < LP8X4X_NUM_IRQ_DEFAULT; i++) {
+		err = irq_create_mapping(host->domain, i);
+		if (err < 0)
+			dev_err(&pdev->dev, "Failed to map IRQ %i\n", i);
+	}
+
+	/* Initialize chip registers */
+	iowrite8(0, host->base + CLRRISEINT);
+	iowrite8(0, host->base + ENRISEINT);
+	iowrite8(0, host->base + CLRFALLINT);
+	iowrite8(0, host->base + ENFALLINT);
+	iowrite8(0, host->base + CLRHILVINT);
+	iowrite8(0, host->base + ENHILVINT);
+	iowrite8(0, host->base + ENSYSINT);
+	iowrite8(0, host->base + SECOINT);
+
+	irq_set_handler_data(res_irq->start, host);
+	irq_set_chained_handler(res_irq->start, lp8x4x_irq_handler);
+
+	return 0;
+}
+
+static struct platform_driver lp8x4x_irq_driver = {
+	.probe		= lp8x4x_irq_probe,
+	.driver		= {
+		.name	= "irq-lp8x4x",
+		.of_match_table = lp8x4x_irq_dt_ids,
+	},
+};
+
+static int __init lp8x4x_irq_init(void)
+{
+	return platform_driver_register(&lp8x4x_irq_driver);
+}
+postcore_initcall(lp8x4x_irq_init);
-- 
1.8.4.2

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

* [PATCH v4 11/21] ARM: pxa: support ICP DAS LP-8x4x FPGA irq
@ 2014-04-16 17:17                   ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2014-04-16 17:17 UTC (permalink / raw)
  To: linux-arm-kernel

ICP DAS LP-8x4x contains FPGA chip. The chip functions as an interrupt
source providing 16 additional interrupts among other things. The
interrupt lines are muxed to a GPIO pin of a 2nd level PXA-GPIO
interrupt controller. GPIO pins of the 2nd level controller are in turn
muxed to a CPU interrupt line.

Until pxa is completely converted to device tree, it is impossible
to use IRQCHIP_DECLARE() and the irqdomain needs to added manually.
Drivers for the on-CPU IRQs and GPIO-IRQs are loaded using
postcore_initcall(). We need to have all irq domain drivers loaded prior
to DT parsing in order to allow normal initialization of IRQ resources
with DT.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
CC: Arnd Bergmann <arnd@arndb.de>
---
   v3.2..v4
   * move DTS binding to a different patch (8/21)

   v3.1..v3.2
   fixes to apply Linus Walleij's "Reviewed-by":
   * add kerneldoc comment for state container struct
   * rename irq -> hwirq for clarity
   * drop overzealous error checks from the hotpaths

   v3..v3.1
   fixes according to Linus Walleij review comments:
   * update commit message
   * use state container instead of global variables
   * get hardware irq nums from irq_data, don't calculate them
   * use BIT() macro
   * add defines for system irq register masks
   * replace cycle control variable with break
   * use better names for resource variables
   * add a linear domain instead of a legacy one
   * use irq_create_mapping() instead of irq_alloc_desc()

   v2..v3
   * no changes (except number 09/16 -> 11/21)

   v0..v2
   * extract irqchip and move to drivers/irqchip/
   * use device tree
   * use devm helpers where possible

 .../bindings/interrupt-controller/irq-lp8x4x.txt   |  49 +++++
 drivers/irqchip/Kconfig                            |   5 +
 drivers/irqchip/Makefile                           |   1 +
 drivers/irqchip/irq-lp8x4x.c                       | 227 +++++++++++++++++++++
 4 files changed, 282 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/interrupt-controller/irq-lp8x4x.txt
 create mode 100644 drivers/irqchip/irq-lp8x4x.c

diff --git a/Documentation/devicetree/bindings/interrupt-controller/irq-lp8x4x.txt b/Documentation/devicetree/bindings/interrupt-controller/irq-lp8x4x.txt
new file mode 100644
index 0000000..c8940d2
--- /dev/null
+++ b/Documentation/devicetree/bindings/interrupt-controller/irq-lp8x4x.txt
@@ -0,0 +1,49 @@
+ICP DAS LP-8x4x FPGA Interrupt Controller
+
+ICP DAS LP-8x4x contains FPGA chip. The chip functions as a interrupt
+source providing 16 additional interrupts among other things.
+
+Required properties:
+- compatible : should be "icpdas,irq-lp8x4x"
+
+- reg: physical base address of the controller and length of memory mapped
+  region.
+
+- interrupt-controller : identifies the node as an interrupt controller
+
+- #interrupt-cells : should be 1
+
+- interrupts : should provide interrupt
+
+- interrupt-parent : should provide a link to interrupt controller either
+		     explicitly and implicitly from a parent node
+
+Example:
+
+	fpga: fpga at 17000006 {
+		compatible = "icpdas,irq-lp8x4x";
+		reg = <0x17000006 0x16>;
+		interrupt-parent = <&gpio>;
+		interrupts = <3 IRQ_TYPE_EDGE_RISING>;
+		#interrupt-cells = <1>;
+		interrupt-controller;
+		status = "okay";
+	};
+
+	uart at 17009050 {
+		compatible = "icpdas,uart-lp8x4x";
+		reg = <0x17009050 0x10
+		       0x17009030 0x02>;
+		interrupt-parent = <&fpga>;
+		interrupts = <13>;
+		status = "okay";
+	};
+
+	uart at 17009060 {
+		compatible = "icpdas,uart-lp8x4x";
+		reg = <0x17009060 0x10
+		       0x17009032 0x02>;
+		interrupt-parent = <&fpga>;
+		interrupts = <14>;
+		status = "okay";
+	};
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index d770f74..ede3237 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -47,6 +47,11 @@ config CLPS711X_IRQCHIP
 	select SPARSE_IRQ
 	default y
 
+config LP8X4X_IRQ
+	bool
+	depends on OF && ARCH_PXA
+	select IRQ_DOMAIN
+
 config ORION_IRQCHIP
 	bool
 	select IRQ_DOMAIN
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index f180f8d..94f82c7 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -29,3 +29,4 @@ obj-$(CONFIG_TB10X_IRQC)		+= irq-tb10x.o
 obj-$(CONFIG_XTENSA)			+= irq-xtensa-pic.o
 obj-$(CONFIG_XTENSA_MX)			+= irq-xtensa-mx.o
 obj-$(CONFIG_IRQ_CROSSBAR)		+= irq-crossbar.o
+obj-$(CONFIG_LP8X4X_IRQ)		+= irq-lp8x4x.o
diff --git a/drivers/irqchip/irq-lp8x4x.c b/drivers/irqchip/irq-lp8x4x.c
new file mode 100644
index 0000000..12ccbb03
--- /dev/null
+++ b/drivers/irqchip/irq-lp8x4x.c
@@ -0,0 +1,227 @@
+/*
+ *  linux/drivers/irqchip/irq-lp8x4x.c
+ *
+ *  Support for ICP DAS LP-8x4x FPGA irq
+ *  Copyright (C) 2013 Sergei Ianovich <ynvich@gmail.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation or any later version.
+ */
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/irqchip/chained_irq.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+#define EOI			0x00000000
+#define INSINT			0x00000002
+#define ENSYSINT		0x00000004
+#define PRIMINT			0x00000006
+#define PRIMINT_MASK		0xe0
+#define SECOINT			0x00000008
+#define SECOINT_MASK		0x1f
+#define ENRISEINT		0x0000000A
+#define CLRRISEINT		0x0000000C
+#define ENHILVINT		0x0000000E
+#define CLRHILVINT		0x00000010
+#define ENFALLINT		0x00000012
+#define CLRFALLINT		0x00000014
+#define IRQ_MEM_SIZE		0x00000016
+#define LP8X4X_NUM_IRQ_DEFAULT	16
+
+/**
+ * struct lp8x4x_irq_data - LP8X4X custom irq controller state container
+ * @base:               base IO memory address
+ * @irq_domain:         Interrupt translation domain; responsible for mapping
+ *                      between hwirq number and linux irq number
+ * @irq_sys_enabled:    mask keeping track of interrupts enabled in the
+ *                      register which vendor calls 'system'
+ * @irq_high_enabled:   mask keeping track of interrupts enabled in the
+ *                      register which vendor calls 'high'
+ *
+ * The structure implements State Container from
+ * Documentation/driver-model/design-patterns.txt
+ */
+
+struct lp8x4x_irq_data {
+	void			*base;
+	struct irq_domain	*domain;
+	unsigned char		irq_sys_enabled;
+	unsigned char		irq_high_enabled;
+};
+
+static void lp8x4x_mask_irq(struct irq_data *d)
+{
+	unsigned mask;
+	unsigned long hwirq = d->hwirq;
+	struct lp8x4x_irq_data *host = irq_data_get_irq_chip_data(d);
+
+	if (hwirq < 8) {
+		host->irq_high_enabled &= ~BIT(hwirq);
+
+		mask = ioread8(host->base + ENHILVINT);
+		mask &= ~BIT(hwirq);
+		iowrite8(mask, host->base + ENHILVINT);
+	} else {
+		hwirq -= 8;
+		host->irq_sys_enabled &= ~BIT(hwirq);
+
+		mask = ioread8(host->base + ENSYSINT);
+		mask &= ~BIT(hwirq);
+		iowrite8(mask, host->base + ENSYSINT);
+	}
+}
+
+static void lp8x4x_unmask_irq(struct irq_data *d)
+{
+	unsigned mask;
+	unsigned long hwirq = d->hwirq;
+	struct lp8x4x_irq_data *host = irq_data_get_irq_chip_data(d);
+
+	if (hwirq < 8) {
+		host->irq_high_enabled |= BIT(hwirq);
+		mask = ioread8(host->base + CLRHILVINT);
+		mask |= BIT(hwirq);
+		iowrite8(mask, host->base + CLRHILVINT);
+
+		mask = ioread8(host->base + ENHILVINT);
+		mask |= BIT(hwirq);
+		iowrite8(mask, host->base + ENHILVINT);
+	} else {
+		hwirq -= 8;
+		host->irq_sys_enabled |= BIT(hwirq);
+
+		mask = ioread8(host->base + SECOINT);
+		mask |= BIT(hwirq);
+		iowrite8(mask, host->base + SECOINT);
+
+		mask = ioread8(host->base + ENSYSINT);
+		mask |= BIT(hwirq);
+		iowrite8(mask, host->base + ENSYSINT);
+	}
+}
+
+static struct irq_chip lp8x4x_irq_chip = {
+	.name			= "FPGA",
+	.irq_ack		= lp8x4x_mask_irq,
+	.irq_mask		= lp8x4x_mask_irq,
+	.irq_mask_ack		= lp8x4x_mask_irq,
+	.irq_unmask		= lp8x4x_unmask_irq,
+};
+
+static void lp8x4x_irq_handler(unsigned int irq, struct irq_desc *desc)
+{
+	int n;
+	unsigned long mask;
+	struct irq_chip *chip = irq_desc_get_chip(desc);
+	struct lp8x4x_irq_data *host = irq_desc_get_handler_data(desc);
+
+	chained_irq_enter(chip, desc);
+
+	for (;;) {
+		mask = ioread8(host->base + CLRHILVINT) & 0xff;
+		mask |= (ioread8(host->base + SECOINT) & SECOINT_MASK) << 8;
+		mask |= (ioread8(host->base + PRIMINT) & PRIMINT_MASK) << 8;
+		mask &= host->irq_high_enabled | (host->irq_sys_enabled << 8);
+		if (mask == 0)
+			break;
+		for_each_set_bit(n, &mask, BITS_PER_LONG)
+			generic_handle_irq(irq_find_mapping(host->domain, n));
+	}
+
+	iowrite8(0, host->base + EOI);
+	chained_irq_exit(chip, desc);
+}
+
+static int lp8x4x_irq_domain_map(struct irq_domain *d, unsigned int irq,
+				 irq_hw_number_t hw)
+{
+	struct lp8x4x_irq_data *host = d->host_data;
+	int err;
+
+	err = irq_set_chip_data(irq, host);
+	if (err < 0)
+		return err;
+
+	irq_set_chip_and_handler(irq, &lp8x4x_irq_chip, handle_level_irq);
+	set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+	return 0;
+}
+
+const struct irq_domain_ops lp8x4x_irq_domain_ops = {
+	.map	= lp8x4x_irq_domain_map,
+	.xlate	= irq_domain_xlate_onecell,
+};
+
+static struct of_device_id lp8x4x_irq_dt_ids[] = {
+	{ .compatible = "icpdas,irq-lp8x4x", },
+	{}
+};
+
+static int lp8x4x_irq_probe(struct platform_device *pdev)
+{
+	struct resource *res_mem, *res_irq;
+	struct device_node *np = pdev->dev.of_node;
+	struct lp8x4x_irq_data *host;
+	int i, err;
+
+	res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!res_mem || !res_irq || resource_size(res_mem) < IRQ_MEM_SIZE)
+		return -ENODEV;
+
+	host = devm_kzalloc(&pdev->dev, sizeof(*host), GFP_KERNEL);
+	if (!host)
+		return -ENODEV;
+
+	host->base = devm_ioremap_resource(&pdev->dev, res_mem);
+	if (!host->base) {
+		dev_err(&pdev->dev, "Failed to ioremap %p\n", host->base);
+		return -EFAULT;
+	}
+
+	host->domain = irq_domain_add_linear(np, LP8X4X_NUM_IRQ_DEFAULT,
+				       &lp8x4x_irq_domain_ops, host);
+	if (!host->domain) {
+		dev_err(&pdev->dev, "Failed to add IRQ domain\n");
+		return -ENOMEM;
+	}
+
+	for (i = 0; i < LP8X4X_NUM_IRQ_DEFAULT; i++) {
+		err = irq_create_mapping(host->domain, i);
+		if (err < 0)
+			dev_err(&pdev->dev, "Failed to map IRQ %i\n", i);
+	}
+
+	/* Initialize chip registers */
+	iowrite8(0, host->base + CLRRISEINT);
+	iowrite8(0, host->base + ENRISEINT);
+	iowrite8(0, host->base + CLRFALLINT);
+	iowrite8(0, host->base + ENFALLINT);
+	iowrite8(0, host->base + CLRHILVINT);
+	iowrite8(0, host->base + ENHILVINT);
+	iowrite8(0, host->base + ENSYSINT);
+	iowrite8(0, host->base + SECOINT);
+
+	irq_set_handler_data(res_irq->start, host);
+	irq_set_chained_handler(res_irq->start, lp8x4x_irq_handler);
+
+	return 0;
+}
+
+static struct platform_driver lp8x4x_irq_driver = {
+	.probe		= lp8x4x_irq_probe,
+	.driver		= {
+		.name	= "irq-lp8x4x",
+		.of_match_table = lp8x4x_irq_dt_ids,
+	},
+};
+
+static int __init lp8x4x_irq_init(void)
+{
+	return platform_driver_register(&lp8x4x_irq_driver);
+}
+postcore_initcall(lp8x4x_irq_init);
-- 
1.8.4.2

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

* [PATCH v4 12/21] serial: support for 16550A serial ports on LP-8x4x
  2014-04-16 17:17                 ` Sergei Ianovich
  (?)
@ 2014-04-16 17:17                   ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2014-04-16 17:17 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Randy Dunlap, Russell King,
	Greg Kroah-Hartman, Jiri Slaby, Grant Likely, Heikki Krogerus,
	Arnd Bergmann, Paul Bolle, Stefan Seyfried, James Cameron,
	open list:OPEN FIRMWARE AND...,
	open list:DOCUMENTATION, open list:SERIAL DRIVERS

The patch adds support for 3 additional LP-8x4x built-in serial
ports.

The device can also host up to 8 extension cards with 4 serial ports
on each card for a total of 35 ports. However, I don't have
the hardware to test extension cards, so they are not supported, yet.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
---
   v3..v4
   * move DTS bindings to a different patch (8/21) as suggested by
     Heikki Krogerus

   v2..v3
   * no changes (except number 10/16 -> 12/21)

   v0..v2
   * register platform driver instead of platform device
   * use device tree
   * use devm helpers where possible

 .../devicetree/bindings/serial/lp8x4x-serial.txt   |  35 +++++
 arch/arm/configs/lp8x4x_defconfig                  |   1 +
 drivers/tty/serial/8250/8250_lp8x4x.c              | 169 +++++++++++++++++++++
 drivers/tty/serial/8250/Kconfig                    |  12 ++
 drivers/tty/serial/8250/Makefile                   |   1 +
 5 files changed, 218 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/serial/lp8x4x-serial.txt
 create mode 100644 drivers/tty/serial/8250/8250_lp8x4x.c

diff --git a/Documentation/devicetree/bindings/serial/lp8x4x-serial.txt b/Documentation/devicetree/bindings/serial/lp8x4x-serial.txt
new file mode 100644
index 0000000..5f9a4c1
--- /dev/null
+++ b/Documentation/devicetree/bindings/serial/lp8x4x-serial.txt
@@ -0,0 +1,35 @@
+UART ports on ICP DAS LP-8x4x
+
+ICP DAS LP-8x4x contains three additional serial ports interfaced via
+Analog Devices ADM213EA chips in addition to 3 serial ports on PXA CPU.
+
+Required properties:
+- compatible : should be "icpdas,uart-lp8x4x"
+
+- reg : should provide 16 byte man IO memory region and 1 byte region for
+	termios
+
+- interrupts : should provide interrupt
+
+- interrupt-parent : should provide a link to interrupt controller either
+		     explicitly or implicitly from a parent node
+
+Examples (from pxa27x-lp8x4x.dts):
+
+		uart@9050 {
+			compatible = "icpdas,uart-lp8x4x";
+			reg = <0x9050 0x10
+			       0x9030 0x02>;
+			interrupt-parent = <&fpgairg>;
+			interrupts = <13>;
+			status = "okay";
+		};
+
+		uart@9060 {
+			compatible = "icpdas,uart-lp8x4x";
+			reg = <0x9060 0x10
+			       0x9032 0x02>;
+			interrupt-parent = <&fpgairg>;
+			interrupts = <14>;
+			status = "okay";
+		};
diff --git a/arch/arm/configs/lp8x4x_defconfig b/arch/arm/configs/lp8x4x_defconfig
index 17a4e6f..9116ce1 100644
--- a/arch/arm/configs/lp8x4x_defconfig
+++ b/arch/arm/configs/lp8x4x_defconfig
@@ -112,6 +112,7 @@ CONFIG_SERIAL_8250_EXTENDED=y
 CONFIG_SERIAL_8250_MANY_PORTS=y
 CONFIG_SERIAL_8250_SHARE_IRQ=y
 CONFIG_SERIAL_PXA=y
+CONFIG_SERIAL_8250_LP8X4X=m
 CONFIG_HW_RANDOM=y
 CONFIG_I2C=m
 # CONFIG_I2C_COMPAT is not set
diff --git a/drivers/tty/serial/8250/8250_lp8x4x.c b/drivers/tty/serial/8250/8250_lp8x4x.c
new file mode 100644
index 0000000..93e0f59
--- /dev/null
+++ b/drivers/tty/serial/8250/8250_lp8x4x.c
@@ -0,0 +1,169 @@
+/*  linux/drivers/tty/serial/8250/8250_lp8x4x.c
+ *
+ *  Support for 16550A serial ports on ICP DAS LP-8x4x
+ *
+ *  Copyright (C) 2013 Sergei Ianovich <ynvich@gmail.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/module.h>
+#include <linux/serial_8250.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+struct lp8x4x_serial_data {
+	int			line;
+	void			*ios_mem;
+};
+
+static void lp8x4x_serial_set_termios(struct uart_port *port,
+		struct ktermios *termios, struct ktermios *old)
+{
+	unsigned int len;
+	unsigned int baud;
+	struct lp8x4x_serial_data *data = port->private_data;
+
+	switch (termios->c_cflag & CSIZE) {
+	case CS5:
+		len = 7;
+		break;
+	case CS6:
+		len = 8;
+		break;
+	case CS7:
+		len = 9;
+		break;
+	default:
+	case CS8:
+		len = 10;
+		break;
+	}
+
+	if (termios->c_cflag & CSTOPB)
+		len++;
+	if (termios->c_cflag & PARENB)
+		len++;
+	if (!(termios->c_cflag & PARODD))
+		len++;
+#ifdef CMSPAR
+	if (termios->c_cflag & CMSPAR)
+		len++;
+#endif
+
+	len -= 9;
+	len &= 3;
+	len <<= 3;
+	/*
+	 * Ask the core to calculate the divisor for us.
+	 */
+	baud = uart_get_baud_rate(port, termios, old,
+				  port->uartclk / 16 / 0xffff,
+				  port->uartclk / 16);
+	switch (baud) {
+	case 2400:
+		len |= 1;
+		break;
+	case 4800:
+		len |= 2;
+		break;
+	case 19200:
+		len |= 4;
+		break;
+	case 38400:
+		len |= 5;
+		break;
+	case 57600:
+		len |= 6;
+		break;
+	case 115200:
+		len |= 7;
+		break;
+	case 9600:
+	default:
+		len |= 3;
+		break;
+	};
+	iowrite8(len, data->ios_mem);
+
+	serial8250_do_set_termios(port, termios, old);
+}
+
+static struct of_device_id lp8x4x_serial_dt_ids[] = {
+	{ .compatible = "icpdas,uart-lp8x4x", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, lp8x4x_serial_dt_ids);
+
+static int lp8x4x_serial_probe(struct platform_device *pdev)
+{
+	struct uart_8250_port uart = {};
+	struct lp8x4x_serial_data *data;
+	struct resource *mmres, *mires, *irqres;
+	int ret;
+
+	mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	mires = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	irqres = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!mmres || !mires || !irqres)
+		return -ENODEV;
+
+	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->ios_mem = devm_ioremap_resource(&pdev->dev, mires);
+	if (!data->ios_mem)
+		return -EFAULT;
+
+	uart.port.iotype = UPIO_MEM;
+	uart.port.mapbase = mmres->start;
+	uart.port.iobase = mmres->start;
+	uart.port.regshift = 1;
+	uart.port.irq = irqres->start;
+	uart.port.flags = UPF_IOREMAP;
+	uart.port.dev = &pdev->dev;
+	uart.port.uartclk = 14745600;
+	uart.port.set_termios = lp8x4x_serial_set_termios;
+	uart.port.private_data = data;
+
+	ret = serial8250_register_8250_port(&uart);
+	if (ret < 0)
+		return ret;
+
+	data->line = ret;
+
+	platform_set_drvdata(pdev, data);
+
+	return 0;
+}
+
+static int lp8x4x_serial_remove(struct platform_device *pdev)
+{
+	struct lp8x4x_serial_data *data = platform_get_drvdata(pdev);
+
+	serial8250_unregister_port(data->line);
+
+	return 0;
+}
+
+static struct platform_driver lp8x4x_serial_driver = {
+	.probe          = lp8x4x_serial_probe,
+	.remove         = lp8x4x_serial_remove,
+
+	.driver		= {
+		.name	= "uart-lp8x4x",
+		.owner	= THIS_MODULE,
+		.of_match_table = lp8x4x_serial_dt_ids,
+	},
+};
+
+module_platform_driver(lp8x4x_serial_driver);
+
+MODULE_AUTHOR("Sergei Ianovich");
+MODULE_DESCRIPTION("8250 serial port module for LP-8x4x");
+MODULE_LICENSE("GPL");
diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
index 81bd7c9..9fb0fbb 100644
--- a/drivers/tty/serial/8250/Kconfig
+++ b/drivers/tty/serial/8250/Kconfig
@@ -311,3 +311,15 @@ config SERIAL_PXA
 	  can enable its onboard serial ports by enabling this option.
 
 	  If you choose M here, the module name will be 8250_pxa.
+
+config SERIAL_8250_LP8X4X
+	tristate "Support 16550A ports on ICP DAS LP-8x4x"
+	depends on OF && SERIAL_8250 && SERIAL_8250_MANY_PORTS && ARCH_PXA
+	select LP8X4X_IRQ
+	help
+	  In addition to serial ports on PXA270 SoC, LP-8x4x has 1 dual
+	  RS232/RS485 port, 1 RS485 port and 1 RS232 port.
+
+	  Say N here, unless you plan to run this kernel on a LP-8x4x system.
+
+	  If you choose M here, the module name will be 8250_lp8x4x.
diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile
index b7d1b61..7370bfb 100644
--- a/drivers/tty/serial/8250/Makefile
+++ b/drivers/tty/serial/8250/Makefile
@@ -17,6 +17,7 @@ obj-$(CONFIG_SERIAL_8250_ACCENT)	+= 8250_accent.o
 obj-$(CONFIG_SERIAL_8250_BOCA)		+= 8250_boca.o
 obj-$(CONFIG_SERIAL_8250_EXAR_ST16C554)	+= 8250_exar_st16c554.o
 obj-$(CONFIG_SERIAL_8250_HUB6)		+= 8250_hub6.o
+obj-$(CONFIG_SERIAL_8250_LP8X4X)	+= 8250_lp8x4x.o
 obj-$(CONFIG_SERIAL_8250_FSL)		+= 8250_fsl.o
 obj-$(CONFIG_SERIAL_8250_DW)		+= 8250_dw.o
 obj-$(CONFIG_SERIAL_8250_EM)		+= 8250_em.o
-- 
1.8.4.2


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

* [PATCH v4 12/21] serial: support for 16550A serial ports on LP-8x4x
@ 2014-04-16 17:17                   ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2014-04-16 17:17 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Randy Dunlap, Russell King,
	Greg Kroah-Hartman, Jiri Slaby, Grant Likely, Heikki Krogerus,
	Arnd Bergmann, Paul Bolle, Stefan Seyfried, James Cameron,
	open list:OPEN FIRMWARE AND...,
	open list:DOCUMENTATION, open list:SERIAL DRIVERS

The patch adds support for 3 additional LP-8x4x built-in serial
ports.

The device can also host up to 8 extension cards with 4 serial ports
on each card for a total of 35 ports. However, I don't have
the hardware to test extension cards, so they are not supported, yet.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
---
   v3..v4
   * move DTS bindings to a different patch (8/21) as suggested by
     Heikki Krogerus

   v2..v3
   * no changes (except number 10/16 -> 12/21)

   v0..v2
   * register platform driver instead of platform device
   * use device tree
   * use devm helpers where possible

 .../devicetree/bindings/serial/lp8x4x-serial.txt   |  35 +++++
 arch/arm/configs/lp8x4x_defconfig                  |   1 +
 drivers/tty/serial/8250/8250_lp8x4x.c              | 169 +++++++++++++++++++++
 drivers/tty/serial/8250/Kconfig                    |  12 ++
 drivers/tty/serial/8250/Makefile                   |   1 +
 5 files changed, 218 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/serial/lp8x4x-serial.txt
 create mode 100644 drivers/tty/serial/8250/8250_lp8x4x.c

diff --git a/Documentation/devicetree/bindings/serial/lp8x4x-serial.txt b/Documentation/devicetree/bindings/serial/lp8x4x-serial.txt
new file mode 100644
index 0000000..5f9a4c1
--- /dev/null
+++ b/Documentation/devicetree/bindings/serial/lp8x4x-serial.txt
@@ -0,0 +1,35 @@
+UART ports on ICP DAS LP-8x4x
+
+ICP DAS LP-8x4x contains three additional serial ports interfaced via
+Analog Devices ADM213EA chips in addition to 3 serial ports on PXA CPU.
+
+Required properties:
+- compatible : should be "icpdas,uart-lp8x4x"
+
+- reg : should provide 16 byte man IO memory region and 1 byte region for
+	termios
+
+- interrupts : should provide interrupt
+
+- interrupt-parent : should provide a link to interrupt controller either
+		     explicitly or implicitly from a parent node
+
+Examples (from pxa27x-lp8x4x.dts):
+
+		uart@9050 {
+			compatible = "icpdas,uart-lp8x4x";
+			reg = <0x9050 0x10
+			       0x9030 0x02>;
+			interrupt-parent = <&fpgairg>;
+			interrupts = <13>;
+			status = "okay";
+		};
+
+		uart@9060 {
+			compatible = "icpdas,uart-lp8x4x";
+			reg = <0x9060 0x10
+			       0x9032 0x02>;
+			interrupt-parent = <&fpgairg>;
+			interrupts = <14>;
+			status = "okay";
+		};
diff --git a/arch/arm/configs/lp8x4x_defconfig b/arch/arm/configs/lp8x4x_defconfig
index 17a4e6f..9116ce1 100644
--- a/arch/arm/configs/lp8x4x_defconfig
+++ b/arch/arm/configs/lp8x4x_defconfig
@@ -112,6 +112,7 @@ CONFIG_SERIAL_8250_EXTENDED=y
 CONFIG_SERIAL_8250_MANY_PORTS=y
 CONFIG_SERIAL_8250_SHARE_IRQ=y
 CONFIG_SERIAL_PXA=y
+CONFIG_SERIAL_8250_LP8X4X=m
 CONFIG_HW_RANDOM=y
 CONFIG_I2C=m
 # CONFIG_I2C_COMPAT is not set
diff --git a/drivers/tty/serial/8250/8250_lp8x4x.c b/drivers/tty/serial/8250/8250_lp8x4x.c
new file mode 100644
index 0000000..93e0f59
--- /dev/null
+++ b/drivers/tty/serial/8250/8250_lp8x4x.c
@@ -0,0 +1,169 @@
+/*  linux/drivers/tty/serial/8250/8250_lp8x4x.c
+ *
+ *  Support for 16550A serial ports on ICP DAS LP-8x4x
+ *
+ *  Copyright (C) 2013 Sergei Ianovich <ynvich@gmail.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/module.h>
+#include <linux/serial_8250.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+struct lp8x4x_serial_data {
+	int			line;
+	void			*ios_mem;
+};
+
+static void lp8x4x_serial_set_termios(struct uart_port *port,
+		struct ktermios *termios, struct ktermios *old)
+{
+	unsigned int len;
+	unsigned int baud;
+	struct lp8x4x_serial_data *data = port->private_data;
+
+	switch (termios->c_cflag & CSIZE) {
+	case CS5:
+		len = 7;
+		break;
+	case CS6:
+		len = 8;
+		break;
+	case CS7:
+		len = 9;
+		break;
+	default:
+	case CS8:
+		len = 10;
+		break;
+	}
+
+	if (termios->c_cflag & CSTOPB)
+		len++;
+	if (termios->c_cflag & PARENB)
+		len++;
+	if (!(termios->c_cflag & PARODD))
+		len++;
+#ifdef CMSPAR
+	if (termios->c_cflag & CMSPAR)
+		len++;
+#endif
+
+	len -= 9;
+	len &= 3;
+	len <<= 3;
+	/*
+	 * Ask the core to calculate the divisor for us.
+	 */
+	baud = uart_get_baud_rate(port, termios, old,
+				  port->uartclk / 16 / 0xffff,
+				  port->uartclk / 16);
+	switch (baud) {
+	case 2400:
+		len |= 1;
+		break;
+	case 4800:
+		len |= 2;
+		break;
+	case 19200:
+		len |= 4;
+		break;
+	case 38400:
+		len |= 5;
+		break;
+	case 57600:
+		len |= 6;
+		break;
+	case 115200:
+		len |= 7;
+		break;
+	case 9600:
+	default:
+		len |= 3;
+		break;
+	};
+	iowrite8(len, data->ios_mem);
+
+	serial8250_do_set_termios(port, termios, old);
+}
+
+static struct of_device_id lp8x4x_serial_dt_ids[] = {
+	{ .compatible = "icpdas,uart-lp8x4x", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, lp8x4x_serial_dt_ids);
+
+static int lp8x4x_serial_probe(struct platform_device *pdev)
+{
+	struct uart_8250_port uart = {};
+	struct lp8x4x_serial_data *data;
+	struct resource *mmres, *mires, *irqres;
+	int ret;
+
+	mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	mires = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	irqres = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!mmres || !mires || !irqres)
+		return -ENODEV;
+
+	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->ios_mem = devm_ioremap_resource(&pdev->dev, mires);
+	if (!data->ios_mem)
+		return -EFAULT;
+
+	uart.port.iotype = UPIO_MEM;
+	uart.port.mapbase = mmres->start;
+	uart.port.iobase = mmres->start;
+	uart.port.regshift = 1;
+	uart.port.irq = irqres->start;
+	uart.port.flags = UPF_IOREMAP;
+	uart.port.dev = &pdev->dev;
+	uart.port.uartclk = 14745600;
+	uart.port.set_termios = lp8x4x_serial_set_termios;
+	uart.port.private_data = data;
+
+	ret = serial8250_register_8250_port(&uart);
+	if (ret < 0)
+		return ret;
+
+	data->line = ret;
+
+	platform_set_drvdata(pdev, data);
+
+	return 0;
+}
+
+static int lp8x4x_serial_remove(struct platform_device *pdev)
+{
+	struct lp8x4x_serial_data *data = platform_get_drvdata(pdev);
+
+	serial8250_unregister_port(data->line);
+
+	return 0;
+}
+
+static struct platform_driver lp8x4x_serial_driver = {
+	.probe          = lp8x4x_serial_probe,
+	.remove         = lp8x4x_serial_remove,
+
+	.driver		= {
+		.name	= "uart-lp8x4x",
+		.owner	= THIS_MODULE,
+		.of_match_table = lp8x4x_serial_dt_ids,
+	},
+};
+
+module_platform_driver(lp8x4x_serial_driver);
+
+MODULE_AUTHOR("Sergei Ianovich");
+MODULE_DESCRIPTION("8250 serial port module for LP-8x4x");
+MODULE_LICENSE("GPL");
diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
index 81bd7c9..9fb0fbb 100644
--- a/drivers/tty/serial/8250/Kconfig
+++ b/drivers/tty/serial/8250/Kconfig
@@ -311,3 +311,15 @@ config SERIAL_PXA
 	  can enable its onboard serial ports by enabling this option.
 
 	  If you choose M here, the module name will be 8250_pxa.
+
+config SERIAL_8250_LP8X4X
+	tristate "Support 16550A ports on ICP DAS LP-8x4x"
+	depends on OF && SERIAL_8250 && SERIAL_8250_MANY_PORTS && ARCH_PXA
+	select LP8X4X_IRQ
+	help
+	  In addition to serial ports on PXA270 SoC, LP-8x4x has 1 dual
+	  RS232/RS485 port, 1 RS485 port and 1 RS232 port.
+
+	  Say N here, unless you plan to run this kernel on a LP-8x4x system.
+
+	  If you choose M here, the module name will be 8250_lp8x4x.
diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile
index b7d1b61..7370bfb 100644
--- a/drivers/tty/serial/8250/Makefile
+++ b/drivers/tty/serial/8250/Makefile
@@ -17,6 +17,7 @@ obj-$(CONFIG_SERIAL_8250_ACCENT)	+= 8250_accent.o
 obj-$(CONFIG_SERIAL_8250_BOCA)		+= 8250_boca.o
 obj-$(CONFIG_SERIAL_8250_EXAR_ST16C554)	+= 8250_exar_st16c554.o
 obj-$(CONFIG_SERIAL_8250_HUB6)		+= 8250_hub6.o
+obj-$(CONFIG_SERIAL_8250_LP8X4X)	+= 8250_lp8x4x.o
 obj-$(CONFIG_SERIAL_8250_FSL)		+= 8250_fsl.o
 obj-$(CONFIG_SERIAL_8250_DW)		+= 8250_dw.o
 obj-$(CONFIG_SERIAL_8250_EM)		+= 8250_em.o
-- 
1.8.4.2

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

* [PATCH v4 12/21] serial: support for 16550A serial ports on LP-8x4x
@ 2014-04-16 17:17                   ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2014-04-16 17:17 UTC (permalink / raw)
  To: linux-arm-kernel

The patch adds support for 3 additional LP-8x4x built-in serial
ports.

The device can also host up to 8 extension cards with 4 serial ports
on each card for a total of 35 ports. However, I don't have
the hardware to test extension cards, so they are not supported, yet.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
---
   v3..v4
   * move DTS bindings to a different patch (8/21) as suggested by
     Heikki Krogerus

   v2..v3
   * no changes (except number 10/16 -> 12/21)

   v0..v2
   * register platform driver instead of platform device
   * use device tree
   * use devm helpers where possible

 .../devicetree/bindings/serial/lp8x4x-serial.txt   |  35 +++++
 arch/arm/configs/lp8x4x_defconfig                  |   1 +
 drivers/tty/serial/8250/8250_lp8x4x.c              | 169 +++++++++++++++++++++
 drivers/tty/serial/8250/Kconfig                    |  12 ++
 drivers/tty/serial/8250/Makefile                   |   1 +
 5 files changed, 218 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/serial/lp8x4x-serial.txt
 create mode 100644 drivers/tty/serial/8250/8250_lp8x4x.c

diff --git a/Documentation/devicetree/bindings/serial/lp8x4x-serial.txt b/Documentation/devicetree/bindings/serial/lp8x4x-serial.txt
new file mode 100644
index 0000000..5f9a4c1
--- /dev/null
+++ b/Documentation/devicetree/bindings/serial/lp8x4x-serial.txt
@@ -0,0 +1,35 @@
+UART ports on ICP DAS LP-8x4x
+
+ICP DAS LP-8x4x contains three additional serial ports interfaced via
+Analog Devices ADM213EA chips in addition to 3 serial ports on PXA CPU.
+
+Required properties:
+- compatible : should be "icpdas,uart-lp8x4x"
+
+- reg : should provide 16 byte man IO memory region and 1 byte region for
+	termios
+
+- interrupts : should provide interrupt
+
+- interrupt-parent : should provide a link to interrupt controller either
+		     explicitly or implicitly from a parent node
+
+Examples (from pxa27x-lp8x4x.dts):
+
+		uart at 9050 {
+			compatible = "icpdas,uart-lp8x4x";
+			reg = <0x9050 0x10
+			       0x9030 0x02>;
+			interrupt-parent = <&fpgairg>;
+			interrupts = <13>;
+			status = "okay";
+		};
+
+		uart at 9060 {
+			compatible = "icpdas,uart-lp8x4x";
+			reg = <0x9060 0x10
+			       0x9032 0x02>;
+			interrupt-parent = <&fpgairg>;
+			interrupts = <14>;
+			status = "okay";
+		};
diff --git a/arch/arm/configs/lp8x4x_defconfig b/arch/arm/configs/lp8x4x_defconfig
index 17a4e6f..9116ce1 100644
--- a/arch/arm/configs/lp8x4x_defconfig
+++ b/arch/arm/configs/lp8x4x_defconfig
@@ -112,6 +112,7 @@ CONFIG_SERIAL_8250_EXTENDED=y
 CONFIG_SERIAL_8250_MANY_PORTS=y
 CONFIG_SERIAL_8250_SHARE_IRQ=y
 CONFIG_SERIAL_PXA=y
+CONFIG_SERIAL_8250_LP8X4X=m
 CONFIG_HW_RANDOM=y
 CONFIG_I2C=m
 # CONFIG_I2C_COMPAT is not set
diff --git a/drivers/tty/serial/8250/8250_lp8x4x.c b/drivers/tty/serial/8250/8250_lp8x4x.c
new file mode 100644
index 0000000..93e0f59
--- /dev/null
+++ b/drivers/tty/serial/8250/8250_lp8x4x.c
@@ -0,0 +1,169 @@
+/*  linux/drivers/tty/serial/8250/8250_lp8x4x.c
+ *
+ *  Support for 16550A serial ports on ICP DAS LP-8x4x
+ *
+ *  Copyright (C) 2013 Sergei Ianovich <ynvich@gmail.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/module.h>
+#include <linux/serial_8250.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+struct lp8x4x_serial_data {
+	int			line;
+	void			*ios_mem;
+};
+
+static void lp8x4x_serial_set_termios(struct uart_port *port,
+		struct ktermios *termios, struct ktermios *old)
+{
+	unsigned int len;
+	unsigned int baud;
+	struct lp8x4x_serial_data *data = port->private_data;
+
+	switch (termios->c_cflag & CSIZE) {
+	case CS5:
+		len = 7;
+		break;
+	case CS6:
+		len = 8;
+		break;
+	case CS7:
+		len = 9;
+		break;
+	default:
+	case CS8:
+		len = 10;
+		break;
+	}
+
+	if (termios->c_cflag & CSTOPB)
+		len++;
+	if (termios->c_cflag & PARENB)
+		len++;
+	if (!(termios->c_cflag & PARODD))
+		len++;
+#ifdef CMSPAR
+	if (termios->c_cflag & CMSPAR)
+		len++;
+#endif
+
+	len -= 9;
+	len &= 3;
+	len <<= 3;
+	/*
+	 * Ask the core to calculate the divisor for us.
+	 */
+	baud = uart_get_baud_rate(port, termios, old,
+				  port->uartclk / 16 / 0xffff,
+				  port->uartclk / 16);
+	switch (baud) {
+	case 2400:
+		len |= 1;
+		break;
+	case 4800:
+		len |= 2;
+		break;
+	case 19200:
+		len |= 4;
+		break;
+	case 38400:
+		len |= 5;
+		break;
+	case 57600:
+		len |= 6;
+		break;
+	case 115200:
+		len |= 7;
+		break;
+	case 9600:
+	default:
+		len |= 3;
+		break;
+	};
+	iowrite8(len, data->ios_mem);
+
+	serial8250_do_set_termios(port, termios, old);
+}
+
+static struct of_device_id lp8x4x_serial_dt_ids[] = {
+	{ .compatible = "icpdas,uart-lp8x4x", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, lp8x4x_serial_dt_ids);
+
+static int lp8x4x_serial_probe(struct platform_device *pdev)
+{
+	struct uart_8250_port uart = {};
+	struct lp8x4x_serial_data *data;
+	struct resource *mmres, *mires, *irqres;
+	int ret;
+
+	mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	mires = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	irqres = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!mmres || !mires || !irqres)
+		return -ENODEV;
+
+	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->ios_mem = devm_ioremap_resource(&pdev->dev, mires);
+	if (!data->ios_mem)
+		return -EFAULT;
+
+	uart.port.iotype = UPIO_MEM;
+	uart.port.mapbase = mmres->start;
+	uart.port.iobase = mmres->start;
+	uart.port.regshift = 1;
+	uart.port.irq = irqres->start;
+	uart.port.flags = UPF_IOREMAP;
+	uart.port.dev = &pdev->dev;
+	uart.port.uartclk = 14745600;
+	uart.port.set_termios = lp8x4x_serial_set_termios;
+	uart.port.private_data = data;
+
+	ret = serial8250_register_8250_port(&uart);
+	if (ret < 0)
+		return ret;
+
+	data->line = ret;
+
+	platform_set_drvdata(pdev, data);
+
+	return 0;
+}
+
+static int lp8x4x_serial_remove(struct platform_device *pdev)
+{
+	struct lp8x4x_serial_data *data = platform_get_drvdata(pdev);
+
+	serial8250_unregister_port(data->line);
+
+	return 0;
+}
+
+static struct platform_driver lp8x4x_serial_driver = {
+	.probe          = lp8x4x_serial_probe,
+	.remove         = lp8x4x_serial_remove,
+
+	.driver		= {
+		.name	= "uart-lp8x4x",
+		.owner	= THIS_MODULE,
+		.of_match_table = lp8x4x_serial_dt_ids,
+	},
+};
+
+module_platform_driver(lp8x4x_serial_driver);
+
+MODULE_AUTHOR("Sergei Ianovich");
+MODULE_DESCRIPTION("8250 serial port module for LP-8x4x");
+MODULE_LICENSE("GPL");
diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
index 81bd7c9..9fb0fbb 100644
--- a/drivers/tty/serial/8250/Kconfig
+++ b/drivers/tty/serial/8250/Kconfig
@@ -311,3 +311,15 @@ config SERIAL_PXA
 	  can enable its onboard serial ports by enabling this option.
 
 	  If you choose M here, the module name will be 8250_pxa.
+
+config SERIAL_8250_LP8X4X
+	tristate "Support 16550A ports on ICP DAS LP-8x4x"
+	depends on OF && SERIAL_8250 && SERIAL_8250_MANY_PORTS && ARCH_PXA
+	select LP8X4X_IRQ
+	help
+	  In addition to serial ports on PXA270 SoC, LP-8x4x has 1 dual
+	  RS232/RS485 port, 1 RS485 port and 1 RS232 port.
+
+	  Say N here, unless you plan to run this kernel on a LP-8x4x system.
+
+	  If you choose M here, the module name will be 8250_lp8x4x.
diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile
index b7d1b61..7370bfb 100644
--- a/drivers/tty/serial/8250/Makefile
+++ b/drivers/tty/serial/8250/Makefile
@@ -17,6 +17,7 @@ obj-$(CONFIG_SERIAL_8250_ACCENT)	+= 8250_accent.o
 obj-$(CONFIG_SERIAL_8250_BOCA)		+= 8250_boca.o
 obj-$(CONFIG_SERIAL_8250_EXAR_ST16C554)	+= 8250_exar_st16c554.o
 obj-$(CONFIG_SERIAL_8250_HUB6)		+= 8250_hub6.o
+obj-$(CONFIG_SERIAL_8250_LP8X4X)	+= 8250_lp8x4x.o
 obj-$(CONFIG_SERIAL_8250_FSL)		+= 8250_fsl.o
 obj-$(CONFIG_SERIAL_8250_DW)		+= 8250_dw.o
 obj-$(CONFIG_SERIAL_8250_EM)		+= 8250_em.o
-- 
1.8.4.2

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

* [PATCH v4 13/21] misc: support for LP-8x4x custom parallel bus
  2014-04-16 17:17                 ` Sergei Ianovich
  (?)
@ 2014-04-16 17:17                   ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2014-04-16 17:17 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Randy Dunlap, Russell King,
	Arnd Bergmann, Greg Kroah-Hartman, Grant Likely, Heikki Krogerus,
	open list:OPEN FIRMWARE AND...,
	open list:DOCUMENTATION

This patch implements probing for the bus and reporting the number
of available expansion slots.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
   v3..v4
   * move DTS binding to a different patch (8/21)

   v2..v3
   * fixed goto after bus_register
   * number change (11/16 -> 13/21)

   v0..v2
   * use device tree
   * use devm helpers where possible

 .../devicetree/bindings/misc/lp8x4x-bus.txt        |  16 ++
 Documentation/misc-devices/lp8x4x_bus.txt          |  30 ++++
 arch/arm/configs/lp8x4x_defconfig                  |   1 +
 drivers/misc/Kconfig                               |  13 ++
 drivers/misc/Makefile                              |   1 +
 drivers/misc/lp8x4x_bus.c                          | 167 +++++++++++++++++++++
 6 files changed, 228 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
 create mode 100644 Documentation/misc-devices/lp8x4x_bus.txt
 create mode 100644 drivers/misc/lp8x4x_bus.c

diff --git a/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt b/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
new file mode 100644
index 0000000..1c87a29
--- /dev/null
+++ b/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
@@ -0,0 +1,16 @@
+Custom parallel bus on ICP DAS LP-8x4x industrial computers
+
+See Documentation/misc-devices/lp8x4x_bus.txt for details.
+
+Required properties:
+- compatible : should be "icpdas,backplane-lp8x4x"
+
+- reg: physical base address of the slot count register and the length
+       of the memory mapped region.
+
+Example:
+
+	backplane {
+		compatible = "icpdas,backplane-lp8x4x";
+		reg = <0x17009046 0x2>;
+	};
diff --git a/Documentation/misc-devices/lp8x4x_bus.txt b/Documentation/misc-devices/lp8x4x_bus.txt
new file mode 100644
index 0000000..f5392b3
--- /dev/null
+++ b/Documentation/misc-devices/lp8x4x_bus.txt
@@ -0,0 +1,30 @@
+Kernel driver lpx8x4x_bus
+======================
+
+Supported hardare:
+Custom parallel bus on ICP DAS LP-8x4x industrial computers
+
+Data sheet:
+Not freely available
+
+Author:
+Sergei Ianovich <ynvich@gmail.com>
+
+Description
+-----------
+
+http://www.icpdas.com/root/product/solutions/pac/linpac/lp-8x4x_hardware.html
+
+LP-8x4x is an ARM-based industrial computer with a custom parallel bus to
+connect expansion modules with digital input/output, analog input/output,
+serial, CAN and other types of ports.
+
+The bus is implemented by a FPGA.
+
+SYSFS
+-----
+
+/sys/bus/icpdas/devices/backplane:
+
+slot_count
+	RO - shows total number of expansion slots on the device
diff --git a/arch/arm/configs/lp8x4x_defconfig b/arch/arm/configs/lp8x4x_defconfig
index 9116ce1..c34eb2a 100644
--- a/arch/arm/configs/lp8x4x_defconfig
+++ b/arch/arm/configs/lp8x4x_defconfig
@@ -62,6 +62,7 @@ CONFIG_PROC_DEVICETREE=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_LOOP_MIN_COUNT=2
 CONFIG_EEPROM_AT24=m
+CONFIG_LP8X4X_BUS=m
 CONFIG_SCSI=y
 # CONFIG_SCSI_PROC_FS is not set
 CONFIG_BLK_DEV_SD=y
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 1cb7408..08ffe63 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -515,6 +515,19 @@ config SRAM
 	  the genalloc API. It is supposed to be used for small on-chip SRAM
 	  areas found on many SoCs.
 
+config LP8X4X_BUS
+	tristate "ICP DAS LP-8x4x industrial IO bus"
+	depends on OF && ARCH_PXA
+	select SYSFS
+	---help---
+	  This is a driver for ICP DAS LP-8x4x programmable automation
+	  controller. It exposes a custom parallel bus. The bus services
+	  data acquisition and control modules.
+
+	  Say N, unless you plan to run this kernel on a LP-8x4x system.
+
+	  If you say M here, the module will be called lp8x4x_bus.
+
 source "drivers/misc/c2port/Kconfig"
 source "drivers/misc/eeprom/Kconfig"
 source "drivers/misc/cb710/Kconfig"
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 7eb4b69..2bfe25d 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -55,3 +55,4 @@ obj-$(CONFIG_SRAM)		+= sram.o
 obj-y				+= mic/
 obj-$(CONFIG_GENWQE)		+= genwqe/
 obj-$(CONFIG_ECHO)		+= echo/
+obj-$(CONFIG_LP8X4X_BUS)	+= lp8x4x_bus.o
diff --git a/drivers/misc/lp8x4x_bus.c b/drivers/misc/lp8x4x_bus.c
new file mode 100644
index 0000000..7aa55cf
--- /dev/null
+++ b/drivers/misc/lp8x4x_bus.c
@@ -0,0 +1,167 @@
+/*
+ *  linux/misc/lp8x4x_bus.c
+ *
+ *  Support for ICP DAS LP-8x4x programmable automation controller bus
+ *  Copyright (C) 2013 Sergei Ianovich <ynvich@gmail.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation or any later version.
+ */
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#define MODULE_NAME	"lp8x4x-bus"
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Sergei Ianovich <ynvich@gmail.com>");
+MODULE_DESCRIPTION("ICP DAS LP-8x4x parallel bus driver");
+
+struct lp8x4x_master {
+	unsigned int		slot_count;
+	void			*count_addr;
+	struct device		dev;
+};
+
+static int lp8x4x_match(struct device *dev, struct device_driver *drv)
+{
+	return 1;
+}
+
+static struct bus_type lp8x4x_bus_type = {
+	.name		= "icpdas",
+	.match		= lp8x4x_match,
+};
+
+static void lp8x4x_master_release(struct device *dev)
+{
+	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
+	WARN_ON(!dev);
+
+	kfree(m);
+}
+
+static ssize_t slot_count_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
+
+	return sprintf(buf, "%u\n", m->slot_count);
+}
+
+static DEVICE_ATTR_RO(slot_count);
+
+static struct attribute *master_dev_attrs[] = {
+	&dev_attr_slot_count.attr,
+	NULL,
+};
+ATTRIBUTE_GROUPS(master_dev);
+
+
+static void devm_lp8x4x_bus_release(struct device *dev, void *res)
+{
+	struct lp8x4x_master *m = *(struct lp8x4x_master **)res;
+
+	dev_dbg(dev, "releasing devices\n");
+	device_unregister(&m->dev);
+	bus_unregister(&lp8x4x_bus_type);
+}
+
+static int __init lp8x4x_bus_probe(struct platform_device *pdev)
+{
+	struct lp8x4x_master *m, **p;
+	struct resource *res;
+	int err = 0;
+
+	m = kzalloc(sizeof(*m), GFP_KERNEL);
+	if (!m)
+		return -ENOMEM;
+
+	p = devres_alloc(devm_lp8x4x_bus_release, sizeof(*p), GFP_KERNEL);
+	if (!p) {
+		err = -ENOMEM;
+		goto err1;
+	}
+	*p = m;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "could not get slot count address\n");
+		err = -ENODEV;
+		goto err2;
+	}
+
+	m->count_addr = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(m->count_addr)) {
+		dev_err(&pdev->dev, "Failed to ioremap slot count address\n");
+		err = PTR_ERR(m->count_addr);
+		goto err2;
+	}
+
+	m->slot_count = ioread8(m->count_addr);
+	switch (m->slot_count) {
+	case 1:
+	case 4:
+		break;
+	case 7:
+		m->slot_count = 8;
+		break;
+	default:
+		dev_err(&pdev->dev, "unexpected slot number(%u)",
+				m->slot_count);
+		err = -ENODEV;
+		goto err2;
+	};
+
+	dev_info(&pdev->dev, "found bus with up to %u slots\n", m->slot_count);
+
+	err = bus_register(&lp8x4x_bus_type);
+	if (err < 0) {
+		dev_err(&pdev->dev, "failed to register bus type\n");
+		goto err2;
+	}
+
+	m->dev.bus = &lp8x4x_bus_type;
+	dev_set_name(&m->dev, "backplane");
+	m->dev.parent = &pdev->dev;
+	m->dev.release = lp8x4x_master_release;
+	m->dev.groups = master_dev_groups;
+
+	err = device_register(&m->dev);
+	if (err < 0) {
+		dev_err(&pdev->dev, "failed to register backplane device\n");
+		goto err3;
+	}
+
+	devres_add(&pdev->dev, p);
+	return 0;
+
+err3:
+	bus_unregister(&lp8x4x_bus_type);
+err2:
+	devres_free(p);
+err1:
+	kfree(m);
+	return err;
+}
+
+static const struct of_device_id lp8x4x_bus_dt_ids[] = {
+	{ .compatible = "icpdas,backplane-lp8x4x" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, lp8x4x_bus_dt_ids);
+
+static struct platform_driver lp8x4x_bus_driver = {
+	.driver		= {
+		.name	= MODULE_NAME,
+		.owner	= THIS_MODULE,
+		.of_match_table = lp8x4x_bus_dt_ids,
+	},
+};
+
+module_platform_driver_probe(lp8x4x_bus_driver, lp8x4x_bus_probe);
-- 
1.8.4.2


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

* [PATCH v4 13/21] misc: support for LP-8x4x custom parallel bus
@ 2014-04-16 17:17                   ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2014-04-16 17:17 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Mark Rutland, open list:OPEN FIRMWARE AND...,
	Heikki Krogerus, Russell King, Arnd Bergmann, Pawel Moll,
	Ian Campbell, Greg Kroah-Hartman, Randy Dunlap,
	open list:DOCUMENTATION, Sergei Ianovich, Rob Herring,
	Kumar Gala, Grant Likely

This patch implements probing for the bus and reporting the number
of available expansion slots.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
   v3..v4
   * move DTS binding to a different patch (8/21)

   v2..v3
   * fixed goto after bus_register
   * number change (11/16 -> 13/21)

   v0..v2
   * use device tree
   * use devm helpers where possible

 .../devicetree/bindings/misc/lp8x4x-bus.txt        |  16 ++
 Documentation/misc-devices/lp8x4x_bus.txt          |  30 ++++
 arch/arm/configs/lp8x4x_defconfig                  |   1 +
 drivers/misc/Kconfig                               |  13 ++
 drivers/misc/Makefile                              |   1 +
 drivers/misc/lp8x4x_bus.c                          | 167 +++++++++++++++++++++
 6 files changed, 228 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
 create mode 100644 Documentation/misc-devices/lp8x4x_bus.txt
 create mode 100644 drivers/misc/lp8x4x_bus.c

diff --git a/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt b/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
new file mode 100644
index 0000000..1c87a29
--- /dev/null
+++ b/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
@@ -0,0 +1,16 @@
+Custom parallel bus on ICP DAS LP-8x4x industrial computers
+
+See Documentation/misc-devices/lp8x4x_bus.txt for details.
+
+Required properties:
+- compatible : should be "icpdas,backplane-lp8x4x"
+
+- reg: physical base address of the slot count register and the length
+       of the memory mapped region.
+
+Example:
+
+	backplane {
+		compatible = "icpdas,backplane-lp8x4x";
+		reg = <0x17009046 0x2>;
+	};
diff --git a/Documentation/misc-devices/lp8x4x_bus.txt b/Documentation/misc-devices/lp8x4x_bus.txt
new file mode 100644
index 0000000..f5392b3
--- /dev/null
+++ b/Documentation/misc-devices/lp8x4x_bus.txt
@@ -0,0 +1,30 @@
+Kernel driver lpx8x4x_bus
+======================
+
+Supported hardare:
+Custom parallel bus on ICP DAS LP-8x4x industrial computers
+
+Data sheet:
+Not freely available
+
+Author:
+Sergei Ianovich <ynvich@gmail.com>
+
+Description
+-----------
+
+http://www.icpdas.com/root/product/solutions/pac/linpac/lp-8x4x_hardware.html
+
+LP-8x4x is an ARM-based industrial computer with a custom parallel bus to
+connect expansion modules with digital input/output, analog input/output,
+serial, CAN and other types of ports.
+
+The bus is implemented by a FPGA.
+
+SYSFS
+-----
+
+/sys/bus/icpdas/devices/backplane:
+
+slot_count
+	RO - shows total number of expansion slots on the device
diff --git a/arch/arm/configs/lp8x4x_defconfig b/arch/arm/configs/lp8x4x_defconfig
index 9116ce1..c34eb2a 100644
--- a/arch/arm/configs/lp8x4x_defconfig
+++ b/arch/arm/configs/lp8x4x_defconfig
@@ -62,6 +62,7 @@ CONFIG_PROC_DEVICETREE=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_LOOP_MIN_COUNT=2
 CONFIG_EEPROM_AT24=m
+CONFIG_LP8X4X_BUS=m
 CONFIG_SCSI=y
 # CONFIG_SCSI_PROC_FS is not set
 CONFIG_BLK_DEV_SD=y
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 1cb7408..08ffe63 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -515,6 +515,19 @@ config SRAM
 	  the genalloc API. It is supposed to be used for small on-chip SRAM
 	  areas found on many SoCs.
 
+config LP8X4X_BUS
+	tristate "ICP DAS LP-8x4x industrial IO bus"
+	depends on OF && ARCH_PXA
+	select SYSFS
+	---help---
+	  This is a driver for ICP DAS LP-8x4x programmable automation
+	  controller. It exposes a custom parallel bus. The bus services
+	  data acquisition and control modules.
+
+	  Say N, unless you plan to run this kernel on a LP-8x4x system.
+
+	  If you say M here, the module will be called lp8x4x_bus.
+
 source "drivers/misc/c2port/Kconfig"
 source "drivers/misc/eeprom/Kconfig"
 source "drivers/misc/cb710/Kconfig"
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 7eb4b69..2bfe25d 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -55,3 +55,4 @@ obj-$(CONFIG_SRAM)		+= sram.o
 obj-y				+= mic/
 obj-$(CONFIG_GENWQE)		+= genwqe/
 obj-$(CONFIG_ECHO)		+= echo/
+obj-$(CONFIG_LP8X4X_BUS)	+= lp8x4x_bus.o
diff --git a/drivers/misc/lp8x4x_bus.c b/drivers/misc/lp8x4x_bus.c
new file mode 100644
index 0000000..7aa55cf
--- /dev/null
+++ b/drivers/misc/lp8x4x_bus.c
@@ -0,0 +1,167 @@
+/*
+ *  linux/misc/lp8x4x_bus.c
+ *
+ *  Support for ICP DAS LP-8x4x programmable automation controller bus
+ *  Copyright (C) 2013 Sergei Ianovich <ynvich@gmail.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation or any later version.
+ */
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#define MODULE_NAME	"lp8x4x-bus"
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Sergei Ianovich <ynvich@gmail.com>");
+MODULE_DESCRIPTION("ICP DAS LP-8x4x parallel bus driver");
+
+struct lp8x4x_master {
+	unsigned int		slot_count;
+	void			*count_addr;
+	struct device		dev;
+};
+
+static int lp8x4x_match(struct device *dev, struct device_driver *drv)
+{
+	return 1;
+}
+
+static struct bus_type lp8x4x_bus_type = {
+	.name		= "icpdas",
+	.match		= lp8x4x_match,
+};
+
+static void lp8x4x_master_release(struct device *dev)
+{
+	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
+	WARN_ON(!dev);
+
+	kfree(m);
+}
+
+static ssize_t slot_count_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
+
+	return sprintf(buf, "%u\n", m->slot_count);
+}
+
+static DEVICE_ATTR_RO(slot_count);
+
+static struct attribute *master_dev_attrs[] = {
+	&dev_attr_slot_count.attr,
+	NULL,
+};
+ATTRIBUTE_GROUPS(master_dev);
+
+
+static void devm_lp8x4x_bus_release(struct device *dev, void *res)
+{
+	struct lp8x4x_master *m = *(struct lp8x4x_master **)res;
+
+	dev_dbg(dev, "releasing devices\n");
+	device_unregister(&m->dev);
+	bus_unregister(&lp8x4x_bus_type);
+}
+
+static int __init lp8x4x_bus_probe(struct platform_device *pdev)
+{
+	struct lp8x4x_master *m, **p;
+	struct resource *res;
+	int err = 0;
+
+	m = kzalloc(sizeof(*m), GFP_KERNEL);
+	if (!m)
+		return -ENOMEM;
+
+	p = devres_alloc(devm_lp8x4x_bus_release, sizeof(*p), GFP_KERNEL);
+	if (!p) {
+		err = -ENOMEM;
+		goto err1;
+	}
+	*p = m;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "could not get slot count address\n");
+		err = -ENODEV;
+		goto err2;
+	}
+
+	m->count_addr = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(m->count_addr)) {
+		dev_err(&pdev->dev, "Failed to ioremap slot count address\n");
+		err = PTR_ERR(m->count_addr);
+		goto err2;
+	}
+
+	m->slot_count = ioread8(m->count_addr);
+	switch (m->slot_count) {
+	case 1:
+	case 4:
+		break;
+	case 7:
+		m->slot_count = 8;
+		break;
+	default:
+		dev_err(&pdev->dev, "unexpected slot number(%u)",
+				m->slot_count);
+		err = -ENODEV;
+		goto err2;
+	};
+
+	dev_info(&pdev->dev, "found bus with up to %u slots\n", m->slot_count);
+
+	err = bus_register(&lp8x4x_bus_type);
+	if (err < 0) {
+		dev_err(&pdev->dev, "failed to register bus type\n");
+		goto err2;
+	}
+
+	m->dev.bus = &lp8x4x_bus_type;
+	dev_set_name(&m->dev, "backplane");
+	m->dev.parent = &pdev->dev;
+	m->dev.release = lp8x4x_master_release;
+	m->dev.groups = master_dev_groups;
+
+	err = device_register(&m->dev);
+	if (err < 0) {
+		dev_err(&pdev->dev, "failed to register backplane device\n");
+		goto err3;
+	}
+
+	devres_add(&pdev->dev, p);
+	return 0;
+
+err3:
+	bus_unregister(&lp8x4x_bus_type);
+err2:
+	devres_free(p);
+err1:
+	kfree(m);
+	return err;
+}
+
+static const struct of_device_id lp8x4x_bus_dt_ids[] = {
+	{ .compatible = "icpdas,backplane-lp8x4x" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, lp8x4x_bus_dt_ids);
+
+static struct platform_driver lp8x4x_bus_driver = {
+	.driver		= {
+		.name	= MODULE_NAME,
+		.owner	= THIS_MODULE,
+		.of_match_table = lp8x4x_bus_dt_ids,
+	},
+};
+
+module_platform_driver_probe(lp8x4x_bus_driver, lp8x4x_bus_probe);
-- 
1.8.4.2

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

* [PATCH v4 13/21] misc: support for LP-8x4x custom parallel bus
@ 2014-04-16 17:17                   ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2014-04-16 17:17 UTC (permalink / raw)
  To: linux-arm-kernel

This patch implements probing for the bus and reporting the number
of available expansion slots.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
   v3..v4
   * move DTS binding to a different patch (8/21)

   v2..v3
   * fixed goto after bus_register
   * number change (11/16 -> 13/21)

   v0..v2
   * use device tree
   * use devm helpers where possible

 .../devicetree/bindings/misc/lp8x4x-bus.txt        |  16 ++
 Documentation/misc-devices/lp8x4x_bus.txt          |  30 ++++
 arch/arm/configs/lp8x4x_defconfig                  |   1 +
 drivers/misc/Kconfig                               |  13 ++
 drivers/misc/Makefile                              |   1 +
 drivers/misc/lp8x4x_bus.c                          | 167 +++++++++++++++++++++
 6 files changed, 228 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
 create mode 100644 Documentation/misc-devices/lp8x4x_bus.txt
 create mode 100644 drivers/misc/lp8x4x_bus.c

diff --git a/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt b/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
new file mode 100644
index 0000000..1c87a29
--- /dev/null
+++ b/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
@@ -0,0 +1,16 @@
+Custom parallel bus on ICP DAS LP-8x4x industrial computers
+
+See Documentation/misc-devices/lp8x4x_bus.txt for details.
+
+Required properties:
+- compatible : should be "icpdas,backplane-lp8x4x"
+
+- reg: physical base address of the slot count register and the length
+       of the memory mapped region.
+
+Example:
+
+	backplane {
+		compatible = "icpdas,backplane-lp8x4x";
+		reg = <0x17009046 0x2>;
+	};
diff --git a/Documentation/misc-devices/lp8x4x_bus.txt b/Documentation/misc-devices/lp8x4x_bus.txt
new file mode 100644
index 0000000..f5392b3
--- /dev/null
+++ b/Documentation/misc-devices/lp8x4x_bus.txt
@@ -0,0 +1,30 @@
+Kernel driver lpx8x4x_bus
+======================
+
+Supported hardare:
+Custom parallel bus on ICP DAS LP-8x4x industrial computers
+
+Data sheet:
+Not freely available
+
+Author:
+Sergei Ianovich <ynvich@gmail.com>
+
+Description
+-----------
+
+http://www.icpdas.com/root/product/solutions/pac/linpac/lp-8x4x_hardware.html
+
+LP-8x4x is an ARM-based industrial computer with a custom parallel bus to
+connect expansion modules with digital input/output, analog input/output,
+serial, CAN and other types of ports.
+
+The bus is implemented by a FPGA.
+
+SYSFS
+-----
+
+/sys/bus/icpdas/devices/backplane:
+
+slot_count
+	RO - shows total number of expansion slots on the device
diff --git a/arch/arm/configs/lp8x4x_defconfig b/arch/arm/configs/lp8x4x_defconfig
index 9116ce1..c34eb2a 100644
--- a/arch/arm/configs/lp8x4x_defconfig
+++ b/arch/arm/configs/lp8x4x_defconfig
@@ -62,6 +62,7 @@ CONFIG_PROC_DEVICETREE=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_LOOP_MIN_COUNT=2
 CONFIG_EEPROM_AT24=m
+CONFIG_LP8X4X_BUS=m
 CONFIG_SCSI=y
 # CONFIG_SCSI_PROC_FS is not set
 CONFIG_BLK_DEV_SD=y
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 1cb7408..08ffe63 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -515,6 +515,19 @@ config SRAM
 	  the genalloc API. It is supposed to be used for small on-chip SRAM
 	  areas found on many SoCs.
 
+config LP8X4X_BUS
+	tristate "ICP DAS LP-8x4x industrial IO bus"
+	depends on OF && ARCH_PXA
+	select SYSFS
+	---help---
+	  This is a driver for ICP DAS LP-8x4x programmable automation
+	  controller. It exposes a custom parallel bus. The bus services
+	  data acquisition and control modules.
+
+	  Say N, unless you plan to run this kernel on a LP-8x4x system.
+
+	  If you say M here, the module will be called lp8x4x_bus.
+
 source "drivers/misc/c2port/Kconfig"
 source "drivers/misc/eeprom/Kconfig"
 source "drivers/misc/cb710/Kconfig"
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 7eb4b69..2bfe25d 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -55,3 +55,4 @@ obj-$(CONFIG_SRAM)		+= sram.o
 obj-y				+= mic/
 obj-$(CONFIG_GENWQE)		+= genwqe/
 obj-$(CONFIG_ECHO)		+= echo/
+obj-$(CONFIG_LP8X4X_BUS)	+= lp8x4x_bus.o
diff --git a/drivers/misc/lp8x4x_bus.c b/drivers/misc/lp8x4x_bus.c
new file mode 100644
index 0000000..7aa55cf
--- /dev/null
+++ b/drivers/misc/lp8x4x_bus.c
@@ -0,0 +1,167 @@
+/*
+ *  linux/misc/lp8x4x_bus.c
+ *
+ *  Support for ICP DAS LP-8x4x programmable automation controller bus
+ *  Copyright (C) 2013 Sergei Ianovich <ynvich@gmail.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation or any later version.
+ */
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#define MODULE_NAME	"lp8x4x-bus"
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Sergei Ianovich <ynvich@gmail.com>");
+MODULE_DESCRIPTION("ICP DAS LP-8x4x parallel bus driver");
+
+struct lp8x4x_master {
+	unsigned int		slot_count;
+	void			*count_addr;
+	struct device		dev;
+};
+
+static int lp8x4x_match(struct device *dev, struct device_driver *drv)
+{
+	return 1;
+}
+
+static struct bus_type lp8x4x_bus_type = {
+	.name		= "icpdas",
+	.match		= lp8x4x_match,
+};
+
+static void lp8x4x_master_release(struct device *dev)
+{
+	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
+	WARN_ON(!dev);
+
+	kfree(m);
+}
+
+static ssize_t slot_count_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
+
+	return sprintf(buf, "%u\n", m->slot_count);
+}
+
+static DEVICE_ATTR_RO(slot_count);
+
+static struct attribute *master_dev_attrs[] = {
+	&dev_attr_slot_count.attr,
+	NULL,
+};
+ATTRIBUTE_GROUPS(master_dev);
+
+
+static void devm_lp8x4x_bus_release(struct device *dev, void *res)
+{
+	struct lp8x4x_master *m = *(struct lp8x4x_master **)res;
+
+	dev_dbg(dev, "releasing devices\n");
+	device_unregister(&m->dev);
+	bus_unregister(&lp8x4x_bus_type);
+}
+
+static int __init lp8x4x_bus_probe(struct platform_device *pdev)
+{
+	struct lp8x4x_master *m, **p;
+	struct resource *res;
+	int err = 0;
+
+	m = kzalloc(sizeof(*m), GFP_KERNEL);
+	if (!m)
+		return -ENOMEM;
+
+	p = devres_alloc(devm_lp8x4x_bus_release, sizeof(*p), GFP_KERNEL);
+	if (!p) {
+		err = -ENOMEM;
+		goto err1;
+	}
+	*p = m;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "could not get slot count address\n");
+		err = -ENODEV;
+		goto err2;
+	}
+
+	m->count_addr = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(m->count_addr)) {
+		dev_err(&pdev->dev, "Failed to ioremap slot count address\n");
+		err = PTR_ERR(m->count_addr);
+		goto err2;
+	}
+
+	m->slot_count = ioread8(m->count_addr);
+	switch (m->slot_count) {
+	case 1:
+	case 4:
+		break;
+	case 7:
+		m->slot_count = 8;
+		break;
+	default:
+		dev_err(&pdev->dev, "unexpected slot number(%u)",
+				m->slot_count);
+		err = -ENODEV;
+		goto err2;
+	};
+
+	dev_info(&pdev->dev, "found bus with up to %u slots\n", m->slot_count);
+
+	err = bus_register(&lp8x4x_bus_type);
+	if (err < 0) {
+		dev_err(&pdev->dev, "failed to register bus type\n");
+		goto err2;
+	}
+
+	m->dev.bus = &lp8x4x_bus_type;
+	dev_set_name(&m->dev, "backplane");
+	m->dev.parent = &pdev->dev;
+	m->dev.release = lp8x4x_master_release;
+	m->dev.groups = master_dev_groups;
+
+	err = device_register(&m->dev);
+	if (err < 0) {
+		dev_err(&pdev->dev, "failed to register backplane device\n");
+		goto err3;
+	}
+
+	devres_add(&pdev->dev, p);
+	return 0;
+
+err3:
+	bus_unregister(&lp8x4x_bus_type);
+err2:
+	devres_free(p);
+err1:
+	kfree(m);
+	return err;
+}
+
+static const struct of_device_id lp8x4x_bus_dt_ids[] = {
+	{ .compatible = "icpdas,backplane-lp8x4x" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, lp8x4x_bus_dt_ids);
+
+static struct platform_driver lp8x4x_bus_driver = {
+	.driver		= {
+		.name	= MODULE_NAME,
+		.owner	= THIS_MODULE,
+		.of_match_table = lp8x4x_bus_dt_ids,
+	},
+};
+
+module_platform_driver_probe(lp8x4x_bus_driver, lp8x4x_bus_probe);
-- 
1.8.4.2

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

* [PATCH v4 14/21] misc: support for LP-8x4x rotary switch
  2014-04-16 17:17                 ` Sergei Ianovich
  (?)
@ 2014-04-16 17:17                   ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2014-04-16 17:17 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Randy Dunlap, Arnd Bergmann,
	Greg Kroah-Hartman, open list:OPEN FIRMWARE AND...,
	open list:DOCUMENTATION

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
   v3..v4
   * move DTS binding to a different patch (8/21)

   v2..v3
   * new patch

 .../devicetree/bindings/misc/lp8x4x-bus.txt        |  8 ++--
 Documentation/misc-devices/lp8x4x_bus.txt          |  3 ++
 drivers/misc/lp8x4x_bus.c                          | 43 ++++++++++++++++++----
 3 files changed, 43 insertions(+), 11 deletions(-)

diff --git a/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt b/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
index 1c87a29..8a55020 100644
--- a/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
+++ b/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
@@ -5,12 +5,14 @@ See Documentation/misc-devices/lp8x4x_bus.txt for details.
 Required properties:
 - compatible : should be "icpdas,backplane-lp8x4x"
 
-- reg: physical base address of the slot count register and the length
-       of the memory mapped region.
+- reg: physical base addresses and region lengths of
+       * the rotary switch
+       * the slot count register
 
 Example:
 
 	backplane {
 		compatible = "icpdas,backplane-lp8x4x";
-		reg = <0x17009046 0x2>;
+		reg = <0x0 0x2
+		       0x9046 0x2>;
 	};
diff --git a/Documentation/misc-devices/lp8x4x_bus.txt b/Documentation/misc-devices/lp8x4x_bus.txt
index f5392b3..bea435b 100644
--- a/Documentation/misc-devices/lp8x4x_bus.txt
+++ b/Documentation/misc-devices/lp8x4x_bus.txt
@@ -26,5 +26,8 @@ SYSFS
 
 /sys/bus/icpdas/devices/backplane:
 
+rotary
+	RO - shows position of LP-8x4x rotary switch (0-9)
+
 slot_count
 	RO - shows total number of expansion slots on the device
diff --git a/drivers/misc/lp8x4x_bus.c b/drivers/misc/lp8x4x_bus.c
index 7aa55cf..18ca8f8 100644
--- a/drivers/misc/lp8x4x_bus.c
+++ b/drivers/misc/lp8x4x_bus.c
@@ -25,6 +25,7 @@ MODULE_DESCRIPTION("ICP DAS LP-8x4x parallel bus driver");
 struct lp8x4x_master {
 	unsigned int		slot_count;
 	void			*count_addr;
+	void			*rotary_addr;
 	struct device		dev;
 };
 
@@ -56,8 +57,19 @@ static ssize_t slot_count_show(struct device *dev,
 
 static DEVICE_ATTR_RO(slot_count);
 
+static ssize_t rotary_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
+
+	return sprintf(buf, "%u\n", (ioread8(m->rotary_addr) ^ 0xf) & 0xf);
+}
+
+static DEVICE_ATTR_RO(rotary);
+
 static struct attribute *master_dev_attrs[] = {
 	&dev_attr_slot_count.attr,
+	&dev_attr_rotary.attr,
 	NULL,
 };
 ATTRIBUTE_GROUPS(master_dev);
@@ -76,6 +88,7 @@ static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 {
 	struct lp8x4x_master *m, **p;
 	struct resource *res;
+	int r = 0;
 	int err = 0;
 
 	m = kzalloc(sizeof(*m), GFP_KERNEL);
@@ -89,18 +102,32 @@ static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 	}
 	*p = m;
 
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	res = platform_get_resource(pdev, IORESOURCE_MEM, r++);
+	if (!res) {
+		dev_err(&pdev->dev, "Failed to get rotary address\n");
+		err = -ENODEV;
+		goto err_free;
+	}
+
+	m->rotary_addr = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(m->rotary_addr)) {
+		dev_err(&pdev->dev, "Failed to ioremap rotary address\n");
+		err = PTR_ERR(m->rotary_addr);
+		goto err_free;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, r++);
 	if (!res) {
 		dev_err(&pdev->dev, "could not get slot count address\n");
 		err = -ENODEV;
-		goto err2;
+		goto err_free;
 	}
 
 	m->count_addr = devm_ioremap_resource(&pdev->dev, res);
 	if (IS_ERR(m->count_addr)) {
 		dev_err(&pdev->dev, "Failed to ioremap slot count address\n");
 		err = PTR_ERR(m->count_addr);
-		goto err2;
+		goto err_free;
 	}
 
 	m->slot_count = ioread8(m->count_addr);
@@ -115,7 +142,7 @@ static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 		dev_err(&pdev->dev, "unexpected slot number(%u)",
 				m->slot_count);
 		err = -ENODEV;
-		goto err2;
+		goto err_free;
 	};
 
 	dev_info(&pdev->dev, "found bus with up to %u slots\n", m->slot_count);
@@ -123,7 +150,7 @@ static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 	err = bus_register(&lp8x4x_bus_type);
 	if (err < 0) {
 		dev_err(&pdev->dev, "failed to register bus type\n");
-		goto err2;
+		goto err_free;
 	}
 
 	m->dev.bus = &lp8x4x_bus_type;
@@ -135,15 +162,15 @@ static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 	err = device_register(&m->dev);
 	if (err < 0) {
 		dev_err(&pdev->dev, "failed to register backplane device\n");
-		goto err3;
+		goto err_bus;
 	}
 
 	devres_add(&pdev->dev, p);
 	return 0;
 
-err3:
+err_bus:
 	bus_unregister(&lp8x4x_bus_type);
-err2:
+err_free:
 	devres_free(p);
 err1:
 	kfree(m);
-- 
1.8.4.2


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

* [PATCH v4 14/21] misc: support for LP-8x4x rotary switch
@ 2014-04-16 17:17                   ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2014-04-16 17:17 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Randy Dunlap, Arnd Bergmann,
	Greg Kroah-Hartman, open list:OPEN FIRMWARE AND...,
	open list:DOCUMENTATION

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
   v3..v4
   * move DTS binding to a different patch (8/21)

   v2..v3
   * new patch

 .../devicetree/bindings/misc/lp8x4x-bus.txt        |  8 ++--
 Documentation/misc-devices/lp8x4x_bus.txt          |  3 ++
 drivers/misc/lp8x4x_bus.c                          | 43 ++++++++++++++++++----
 3 files changed, 43 insertions(+), 11 deletions(-)

diff --git a/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt b/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
index 1c87a29..8a55020 100644
--- a/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
+++ b/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
@@ -5,12 +5,14 @@ See Documentation/misc-devices/lp8x4x_bus.txt for details.
 Required properties:
 - compatible : should be "icpdas,backplane-lp8x4x"
 
-- reg: physical base address of the slot count register and the length
-       of the memory mapped region.
+- reg: physical base addresses and region lengths of
+       * the rotary switch
+       * the slot count register
 
 Example:
 
 	backplane {
 		compatible = "icpdas,backplane-lp8x4x";
-		reg = <0x17009046 0x2>;
+		reg = <0x0 0x2
+		       0x9046 0x2>;
 	};
diff --git a/Documentation/misc-devices/lp8x4x_bus.txt b/Documentation/misc-devices/lp8x4x_bus.txt
index f5392b3..bea435b 100644
--- a/Documentation/misc-devices/lp8x4x_bus.txt
+++ b/Documentation/misc-devices/lp8x4x_bus.txt
@@ -26,5 +26,8 @@ SYSFS
 
 /sys/bus/icpdas/devices/backplane:
 
+rotary
+	RO - shows position of LP-8x4x rotary switch (0-9)
+
 slot_count
 	RO - shows total number of expansion slots on the device
diff --git a/drivers/misc/lp8x4x_bus.c b/drivers/misc/lp8x4x_bus.c
index 7aa55cf..18ca8f8 100644
--- a/drivers/misc/lp8x4x_bus.c
+++ b/drivers/misc/lp8x4x_bus.c
@@ -25,6 +25,7 @@ MODULE_DESCRIPTION("ICP DAS LP-8x4x parallel bus driver");
 struct lp8x4x_master {
 	unsigned int		slot_count;
 	void			*count_addr;
+	void			*rotary_addr;
 	struct device		dev;
 };
 
@@ -56,8 +57,19 @@ static ssize_t slot_count_show(struct device *dev,
 
 static DEVICE_ATTR_RO(slot_count);
 
+static ssize_t rotary_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
+
+	return sprintf(buf, "%u\n", (ioread8(m->rotary_addr) ^ 0xf) & 0xf);
+}
+
+static DEVICE_ATTR_RO(rotary);
+
 static struct attribute *master_dev_attrs[] = {
 	&dev_attr_slot_count.attr,
+	&dev_attr_rotary.attr,
 	NULL,
 };
 ATTRIBUTE_GROUPS(master_dev);
@@ -76,6 +88,7 @@ static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 {
 	struct lp8x4x_master *m, **p;
 	struct resource *res;
+	int r = 0;
 	int err = 0;
 
 	m = kzalloc(sizeof(*m), GFP_KERNEL);
@@ -89,18 +102,32 @@ static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 	}
 	*p = m;
 
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	res = platform_get_resource(pdev, IORESOURCE_MEM, r++);
+	if (!res) {
+		dev_err(&pdev->dev, "Failed to get rotary address\n");
+		err = -ENODEV;
+		goto err_free;
+	}
+
+	m->rotary_addr = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(m->rotary_addr)) {
+		dev_err(&pdev->dev, "Failed to ioremap rotary address\n");
+		err = PTR_ERR(m->rotary_addr);
+		goto err_free;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, r++);
 	if (!res) {
 		dev_err(&pdev->dev, "could not get slot count address\n");
 		err = -ENODEV;
-		goto err2;
+		goto err_free;
 	}
 
 	m->count_addr = devm_ioremap_resource(&pdev->dev, res);
 	if (IS_ERR(m->count_addr)) {
 		dev_err(&pdev->dev, "Failed to ioremap slot count address\n");
 		err = PTR_ERR(m->count_addr);
-		goto err2;
+		goto err_free;
 	}
 
 	m->slot_count = ioread8(m->count_addr);
@@ -115,7 +142,7 @@ static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 		dev_err(&pdev->dev, "unexpected slot number(%u)",
 				m->slot_count);
 		err = -ENODEV;
-		goto err2;
+		goto err_free;
 	};
 
 	dev_info(&pdev->dev, "found bus with up to %u slots\n", m->slot_count);
@@ -123,7 +150,7 @@ static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 	err = bus_register(&lp8x4x_bus_type);
 	if (err < 0) {
 		dev_err(&pdev->dev, "failed to register bus type\n");
-		goto err2;
+		goto err_free;
 	}
 
 	m->dev.bus = &lp8x4x_bus_type;
@@ -135,15 +162,15 @@ static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 	err = device_register(&m->dev);
 	if (err < 0) {
 		dev_err(&pdev->dev, "failed to register backplane device\n");
-		goto err3;
+		goto err_bus;
 	}
 
 	devres_add(&pdev->dev, p);
 	return 0;
 
-err3:
+err_bus:
 	bus_unregister(&lp8x4x_bus_type);
-err2:
+err_free:
 	devres_free(p);
 err1:
 	kfree(m);
-- 
1.8.4.2

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

* [PATCH v4 14/21] misc: support for LP-8x4x rotary switch
@ 2014-04-16 17:17                   ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2014-04-16 17:17 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
   v3..v4
   * move DTS binding to a different patch (8/21)

   v2..v3
   * new patch

 .../devicetree/bindings/misc/lp8x4x-bus.txt        |  8 ++--
 Documentation/misc-devices/lp8x4x_bus.txt          |  3 ++
 drivers/misc/lp8x4x_bus.c                          | 43 ++++++++++++++++++----
 3 files changed, 43 insertions(+), 11 deletions(-)

diff --git a/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt b/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
index 1c87a29..8a55020 100644
--- a/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
+++ b/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
@@ -5,12 +5,14 @@ See Documentation/misc-devices/lp8x4x_bus.txt for details.
 Required properties:
 - compatible : should be "icpdas,backplane-lp8x4x"
 
-- reg: physical base address of the slot count register and the length
-       of the memory mapped region.
+- reg: physical base addresses and region lengths of
+       * the rotary switch
+       * the slot count register
 
 Example:
 
 	backplane {
 		compatible = "icpdas,backplane-lp8x4x";
-		reg = <0x17009046 0x2>;
+		reg = <0x0 0x2
+		       0x9046 0x2>;
 	};
diff --git a/Documentation/misc-devices/lp8x4x_bus.txt b/Documentation/misc-devices/lp8x4x_bus.txt
index f5392b3..bea435b 100644
--- a/Documentation/misc-devices/lp8x4x_bus.txt
+++ b/Documentation/misc-devices/lp8x4x_bus.txt
@@ -26,5 +26,8 @@ SYSFS
 
 /sys/bus/icpdas/devices/backplane:
 
+rotary
+	RO - shows position of LP-8x4x rotary switch (0-9)
+
 slot_count
 	RO - shows total number of expansion slots on the device
diff --git a/drivers/misc/lp8x4x_bus.c b/drivers/misc/lp8x4x_bus.c
index 7aa55cf..18ca8f8 100644
--- a/drivers/misc/lp8x4x_bus.c
+++ b/drivers/misc/lp8x4x_bus.c
@@ -25,6 +25,7 @@ MODULE_DESCRIPTION("ICP DAS LP-8x4x parallel bus driver");
 struct lp8x4x_master {
 	unsigned int		slot_count;
 	void			*count_addr;
+	void			*rotary_addr;
 	struct device		dev;
 };
 
@@ -56,8 +57,19 @@ static ssize_t slot_count_show(struct device *dev,
 
 static DEVICE_ATTR_RO(slot_count);
 
+static ssize_t rotary_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
+
+	return sprintf(buf, "%u\n", (ioread8(m->rotary_addr) ^ 0xf) & 0xf);
+}
+
+static DEVICE_ATTR_RO(rotary);
+
 static struct attribute *master_dev_attrs[] = {
 	&dev_attr_slot_count.attr,
+	&dev_attr_rotary.attr,
 	NULL,
 };
 ATTRIBUTE_GROUPS(master_dev);
@@ -76,6 +88,7 @@ static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 {
 	struct lp8x4x_master *m, **p;
 	struct resource *res;
+	int r = 0;
 	int err = 0;
 
 	m = kzalloc(sizeof(*m), GFP_KERNEL);
@@ -89,18 +102,32 @@ static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 	}
 	*p = m;
 
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	res = platform_get_resource(pdev, IORESOURCE_MEM, r++);
+	if (!res) {
+		dev_err(&pdev->dev, "Failed to get rotary address\n");
+		err = -ENODEV;
+		goto err_free;
+	}
+
+	m->rotary_addr = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(m->rotary_addr)) {
+		dev_err(&pdev->dev, "Failed to ioremap rotary address\n");
+		err = PTR_ERR(m->rotary_addr);
+		goto err_free;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, r++);
 	if (!res) {
 		dev_err(&pdev->dev, "could not get slot count address\n");
 		err = -ENODEV;
-		goto err2;
+		goto err_free;
 	}
 
 	m->count_addr = devm_ioremap_resource(&pdev->dev, res);
 	if (IS_ERR(m->count_addr)) {
 		dev_err(&pdev->dev, "Failed to ioremap slot count address\n");
 		err = PTR_ERR(m->count_addr);
-		goto err2;
+		goto err_free;
 	}
 
 	m->slot_count = ioread8(m->count_addr);
@@ -115,7 +142,7 @@ static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 		dev_err(&pdev->dev, "unexpected slot number(%u)",
 				m->slot_count);
 		err = -ENODEV;
-		goto err2;
+		goto err_free;
 	};
 
 	dev_info(&pdev->dev, "found bus with up to %u slots\n", m->slot_count);
@@ -123,7 +150,7 @@ static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 	err = bus_register(&lp8x4x_bus_type);
 	if (err < 0) {
 		dev_err(&pdev->dev, "failed to register bus type\n");
-		goto err2;
+		goto err_free;
 	}
 
 	m->dev.bus = &lp8x4x_bus_type;
@@ -135,15 +162,15 @@ static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 	err = device_register(&m->dev);
 	if (err < 0) {
 		dev_err(&pdev->dev, "failed to register backplane device\n");
-		goto err3;
+		goto err_bus;
 	}
 
 	devres_add(&pdev->dev, p);
 	return 0;
 
-err3:
+err_bus:
 	bus_unregister(&lp8x4x_bus_type);
-err2:
+err_free:
 	devres_free(p);
 err1:
 	kfree(m);
-- 
1.8.4.2

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

* [PATCH v4 15/21] misc: support for LP-8x4x DIP switch
  2014-04-16 17:17                 ` Sergei Ianovich
  (?)
@ 2014-04-16 17:17                   ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2014-04-16 17:17 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Randy Dunlap, Arnd Bergmann,
	Greg Kroah-Hartman, open list:OPEN FIRMWARE AND...,
	open list:DOCUMENTATION

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
   v3..v4
   * move DTS binding to a different patch (8/21)

   v2..v3
   * new patch

 .../devicetree/bindings/misc/lp8x4x-bus.txt        |  2 ++
 Documentation/misc-devices/lp8x4x_bus.txt          |  3 +++
 drivers/misc/lp8x4x_bus.c                          | 26 ++++++++++++++++++++++
 3 files changed, 31 insertions(+)

diff --git a/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt b/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
index 8a55020..1b1776a 100644
--- a/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
+++ b/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
@@ -7,6 +7,7 @@ Required properties:
 
 - reg: physical base addresses and region lengths of
        * the rotary switch
+       * the 8bit DIP switch
        * the slot count register
 
 Example:
@@ -14,5 +15,6 @@ Example:
 	backplane {
 		compatible = "icpdas,backplane-lp8x4x";
 		reg = <0x0 0x2
+		       0x9002 0x2
 		       0x9046 0x2>;
 	};
diff --git a/Documentation/misc-devices/lp8x4x_bus.txt b/Documentation/misc-devices/lp8x4x_bus.txt
index bea435b..829781b 100644
--- a/Documentation/misc-devices/lp8x4x_bus.txt
+++ b/Documentation/misc-devices/lp8x4x_bus.txt
@@ -26,6 +26,9 @@ SYSFS
 
 /sys/bus/icpdas/devices/backplane:
 
+dip
+	RO - shows status of LP-8x4x 8bit DIP switch
+
 rotary
 	RO - shows position of LP-8x4x rotary switch (0-9)
 
diff --git a/drivers/misc/lp8x4x_bus.c b/drivers/misc/lp8x4x_bus.c
index 18ca8f8..dfbc8c4 100644
--- a/drivers/misc/lp8x4x_bus.c
+++ b/drivers/misc/lp8x4x_bus.c
@@ -26,6 +26,7 @@ struct lp8x4x_master {
 	unsigned int		slot_count;
 	void			*count_addr;
 	void			*rotary_addr;
+	void			*dip_addr;
 	struct device		dev;
 };
 
@@ -67,9 +68,20 @@ static ssize_t rotary_show(struct device *dev,
 
 static DEVICE_ATTR_RO(rotary);
 
+static ssize_t dip_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
+
+	return sprintf(buf, "0x%02x\n", ioread8(m->dip_addr) ^ 0xff);
+}
+
+static DEVICE_ATTR_RO(dip);
+
 static struct attribute *master_dev_attrs[] = {
 	&dev_attr_slot_count.attr,
 	&dev_attr_rotary.attr,
+	&dev_attr_dip.attr,
 	NULL,
 };
 ATTRIBUTE_GROUPS(master_dev);
@@ -118,6 +130,20 @@ static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, r++);
 	if (!res) {
+		dev_err(&pdev->dev, "Failed to get DIP switch address\n");
+		err = -ENODEV;
+		goto err_free;
+	}
+
+	m->dip_addr = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(m->dip_addr)) {
+		dev_err(&pdev->dev, "Failed to ioremap DIP switch address\n");
+		err = PTR_ERR(m->dip_addr);
+		goto err_free;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, r++);
+	if (!res) {
 		dev_err(&pdev->dev, "could not get slot count address\n");
 		err = -ENODEV;
 		goto err_free;
-- 
1.8.4.2


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

* [PATCH v4 15/21] misc: support for LP-8x4x DIP switch
@ 2014-04-16 17:17                   ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2014-04-16 17:17 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Mark Rutland, open list:OPEN FIRMWARE AND...,
	Arnd Bergmann, Pawel Moll, Ian Campbell, Greg Kroah-Hartman,
	Randy Dunlap, open list:DOCUMENTATION, Sergei Ianovich,
	Rob Herring, Kumar Gala

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
   v3..v4
   * move DTS binding to a different patch (8/21)

   v2..v3
   * new patch

 .../devicetree/bindings/misc/lp8x4x-bus.txt        |  2 ++
 Documentation/misc-devices/lp8x4x_bus.txt          |  3 +++
 drivers/misc/lp8x4x_bus.c                          | 26 ++++++++++++++++++++++
 3 files changed, 31 insertions(+)

diff --git a/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt b/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
index 8a55020..1b1776a 100644
--- a/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
+++ b/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
@@ -7,6 +7,7 @@ Required properties:
 
 - reg: physical base addresses and region lengths of
        * the rotary switch
+       * the 8bit DIP switch
        * the slot count register
 
 Example:
@@ -14,5 +15,6 @@ Example:
 	backplane {
 		compatible = "icpdas,backplane-lp8x4x";
 		reg = <0x0 0x2
+		       0x9002 0x2
 		       0x9046 0x2>;
 	};
diff --git a/Documentation/misc-devices/lp8x4x_bus.txt b/Documentation/misc-devices/lp8x4x_bus.txt
index bea435b..829781b 100644
--- a/Documentation/misc-devices/lp8x4x_bus.txt
+++ b/Documentation/misc-devices/lp8x4x_bus.txt
@@ -26,6 +26,9 @@ SYSFS
 
 /sys/bus/icpdas/devices/backplane:
 
+dip
+	RO - shows status of LP-8x4x 8bit DIP switch
+
 rotary
 	RO - shows position of LP-8x4x rotary switch (0-9)
 
diff --git a/drivers/misc/lp8x4x_bus.c b/drivers/misc/lp8x4x_bus.c
index 18ca8f8..dfbc8c4 100644
--- a/drivers/misc/lp8x4x_bus.c
+++ b/drivers/misc/lp8x4x_bus.c
@@ -26,6 +26,7 @@ struct lp8x4x_master {
 	unsigned int		slot_count;
 	void			*count_addr;
 	void			*rotary_addr;
+	void			*dip_addr;
 	struct device		dev;
 };
 
@@ -67,9 +68,20 @@ static ssize_t rotary_show(struct device *dev,
 
 static DEVICE_ATTR_RO(rotary);
 
+static ssize_t dip_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
+
+	return sprintf(buf, "0x%02x\n", ioread8(m->dip_addr) ^ 0xff);
+}
+
+static DEVICE_ATTR_RO(dip);
+
 static struct attribute *master_dev_attrs[] = {
 	&dev_attr_slot_count.attr,
 	&dev_attr_rotary.attr,
+	&dev_attr_dip.attr,
 	NULL,
 };
 ATTRIBUTE_GROUPS(master_dev);
@@ -118,6 +130,20 @@ static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, r++);
 	if (!res) {
+		dev_err(&pdev->dev, "Failed to get DIP switch address\n");
+		err = -ENODEV;
+		goto err_free;
+	}
+
+	m->dip_addr = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(m->dip_addr)) {
+		dev_err(&pdev->dev, "Failed to ioremap DIP switch address\n");
+		err = PTR_ERR(m->dip_addr);
+		goto err_free;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, r++);
+	if (!res) {
 		dev_err(&pdev->dev, "could not get slot count address\n");
 		err = -ENODEV;
 		goto err_free;
-- 
1.8.4.2

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

* [PATCH v4 15/21] misc: support for LP-8x4x DIP switch
@ 2014-04-16 17:17                   ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2014-04-16 17:17 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
   v3..v4
   * move DTS binding to a different patch (8/21)

   v2..v3
   * new patch

 .../devicetree/bindings/misc/lp8x4x-bus.txt        |  2 ++
 Documentation/misc-devices/lp8x4x_bus.txt          |  3 +++
 drivers/misc/lp8x4x_bus.c                          | 26 ++++++++++++++++++++++
 3 files changed, 31 insertions(+)

diff --git a/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt b/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
index 8a55020..1b1776a 100644
--- a/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
+++ b/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
@@ -7,6 +7,7 @@ Required properties:
 
 - reg: physical base addresses and region lengths of
        * the rotary switch
+       * the 8bit DIP switch
        * the slot count register
 
 Example:
@@ -14,5 +15,6 @@ Example:
 	backplane {
 		compatible = "icpdas,backplane-lp8x4x";
 		reg = <0x0 0x2
+		       0x9002 0x2
 		       0x9046 0x2>;
 	};
diff --git a/Documentation/misc-devices/lp8x4x_bus.txt b/Documentation/misc-devices/lp8x4x_bus.txt
index bea435b..829781b 100644
--- a/Documentation/misc-devices/lp8x4x_bus.txt
+++ b/Documentation/misc-devices/lp8x4x_bus.txt
@@ -26,6 +26,9 @@ SYSFS
 
 /sys/bus/icpdas/devices/backplane:
 
+dip
+	RO - shows status of LP-8x4x 8bit DIP switch
+
 rotary
 	RO - shows position of LP-8x4x rotary switch (0-9)
 
diff --git a/drivers/misc/lp8x4x_bus.c b/drivers/misc/lp8x4x_bus.c
index 18ca8f8..dfbc8c4 100644
--- a/drivers/misc/lp8x4x_bus.c
+++ b/drivers/misc/lp8x4x_bus.c
@@ -26,6 +26,7 @@ struct lp8x4x_master {
 	unsigned int		slot_count;
 	void			*count_addr;
 	void			*rotary_addr;
+	void			*dip_addr;
 	struct device		dev;
 };
 
@@ -67,9 +68,20 @@ static ssize_t rotary_show(struct device *dev,
 
 static DEVICE_ATTR_RO(rotary);
 
+static ssize_t dip_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
+
+	return sprintf(buf, "0x%02x\n", ioread8(m->dip_addr) ^ 0xff);
+}
+
+static DEVICE_ATTR_RO(dip);
+
 static struct attribute *master_dev_attrs[] = {
 	&dev_attr_slot_count.attr,
 	&dev_attr_rotary.attr,
+	&dev_attr_dip.attr,
 	NULL,
 };
 ATTRIBUTE_GROUPS(master_dev);
@@ -118,6 +130,20 @@ static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, r++);
 	if (!res) {
+		dev_err(&pdev->dev, "Failed to get DIP switch address\n");
+		err = -ENODEV;
+		goto err_free;
+	}
+
+	m->dip_addr = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(m->dip_addr)) {
+		dev_err(&pdev->dev, "Failed to ioremap DIP switch address\n");
+		err = PTR_ERR(m->dip_addr);
+		goto err_free;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, r++);
+	if (!res) {
 		dev_err(&pdev->dev, "could not get slot count address\n");
 		err = -ENODEV;
 		goto err_free;
-- 
1.8.4.2

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

* [PATCH v4 16/21] misc: support for writing to LP-8x4x EEPROM
  2014-04-16 17:17                 ` Sergei Ianovich
  (?)
@ 2014-04-16 17:17                   ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2014-04-16 17:17 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Randy Dunlap, Arnd Bergmann,
	Greg Kroah-Hartman, open list:OPEN FIRMWARE AND...,
	open list:DOCUMENTATION

at24c128 write protection is implemented by a separate GPIO line.
EEPROM driver doesn't provide this option, so we implement it
in the board-specific device.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
   v3..v4
   * move DTS binding to a different patch (8/21)

   v2..v3
   * new patch

 .../devicetree/bindings/misc/lp8x4x-bus.txt        |  3 ++
 Documentation/misc-devices/lp8x4x_bus.txt          |  3 ++
 drivers/misc/lp8x4x_bus.c                          | 50 ++++++++++++++++++++++
 3 files changed, 56 insertions(+)

diff --git a/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt b/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
index 1b1776a..b0fb145 100644
--- a/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
+++ b/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
@@ -10,6 +10,8 @@ Required properties:
        * the 8bit DIP switch
        * the slot count register
 
+- eeprom-gpios : should point to active-low write enable GPIO
+
 Example:
 
 	backplane {
@@ -17,4 +19,5 @@ Example:
 		reg = <0x0 0x2
 		       0x9002 0x2
 		       0x9046 0x2>;
+		eeprom-gpios = <&gpio 4 0>;
 	};
diff --git a/Documentation/misc-devices/lp8x4x_bus.txt b/Documentation/misc-devices/lp8x4x_bus.txt
index 829781b..78ea0a89 100644
--- a/Documentation/misc-devices/lp8x4x_bus.txt
+++ b/Documentation/misc-devices/lp8x4x_bus.txt
@@ -29,6 +29,9 @@ SYSFS
 dip
 	RO - shows status of LP-8x4x 8bit DIP switch
 
+eeprom_write_enable
+	RW - controls write access to board's EEPROM (1 - enable)
+
 rotary
 	RO - shows position of LP-8x4x rotary switch (0-9)
 
diff --git a/drivers/misc/lp8x4x_bus.c b/drivers/misc/lp8x4x_bus.c
index dfbc8c4..567fe078 100644
--- a/drivers/misc/lp8x4x_bus.c
+++ b/drivers/misc/lp8x4x_bus.c
@@ -9,6 +9,7 @@
  *  published by the Free Software Foundation or any later version.
  */
 #include <linux/err.h>
+#include <linux/gpio/consumer.h>
 #include <linux/init.h>
 #include <linux/io.h>
 #include <linux/list.h>
@@ -27,6 +28,7 @@ struct lp8x4x_master {
 	void			*count_addr;
 	void			*rotary_addr;
 	void			*dip_addr;
+	struct gpio_desc        *eeprom_nWE;
 	struct device		dev;
 };
 
@@ -68,6 +70,40 @@ static ssize_t rotary_show(struct device *dev,
 
 static DEVICE_ATTR_RO(rotary);
 
+static ssize_t eeprom_write_enable_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
+
+	return sprintf(buf, "%u\n", !gpiod_get_value(m->eeprom_nWE));
+}
+
+static ssize_t eeprom_write_enable_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
+	unsigned int val = 0;
+	int err;
+
+	if (!buf)
+		return count;
+
+	if (0 == count)
+		return count;
+
+	err = kstrtouint(buf, 10, &val);
+	if (err != 0) {
+		dev_err(dev, "Bad input %s\n", buf);
+		return count;
+	}
+
+	gpiod_set_value(m->eeprom_nWE, !val);
+
+	return count;
+}
+
+static DEVICE_ATTR_RW(eeprom_write_enable);
+
 static ssize_t dip_show(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
@@ -81,6 +117,7 @@ static DEVICE_ATTR_RO(dip);
 static struct attribute *master_dev_attrs[] = {
 	&dev_attr_slot_count.attr,
 	&dev_attr_rotary.attr,
+	&dev_attr_eeprom_write_enable.attr,
 	&dev_attr_dip.attr,
 	NULL,
 };
@@ -156,6 +193,19 @@ static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 		goto err_free;
 	}
 
+	m->eeprom_nWE = devm_gpiod_get(&pdev->dev, "eeprom");
+	if (IS_ERR(m->eeprom_nWE)) {
+		err = PTR_ERR(m->eeprom_nWE);
+		dev_err(&pdev->dev, "Failed to get eeprom GPIO\n");
+		goto err_free;
+	}
+
+	err = gpiod_direction_output(m->eeprom_nWE, 1);
+	if (err < 0) {
+		dev_err(&pdev->dev, "Failed to set eeprom GPIO output\n");
+		goto err_free;
+	}
+
 	m->slot_count = ioread8(m->count_addr);
 	switch (m->slot_count) {
 	case 1:
-- 
1.8.4.2


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

* [PATCH v4 16/21] misc: support for writing to LP-8x4x EEPROM
@ 2014-04-16 17:17                   ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2014-04-16 17:17 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Randy Dunlap, Arnd Bergmann,
	Greg Kroah-Hartman, open list:OPEN FIRMWARE AND...,
	open list:DOCUMENTATION

at24c128 write protection is implemented by a separate GPIO line.
EEPROM driver doesn't provide this option, so we implement it
in the board-specific device.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
   v3..v4
   * move DTS binding to a different patch (8/21)

   v2..v3
   * new patch

 .../devicetree/bindings/misc/lp8x4x-bus.txt        |  3 ++
 Documentation/misc-devices/lp8x4x_bus.txt          |  3 ++
 drivers/misc/lp8x4x_bus.c                          | 50 ++++++++++++++++++++++
 3 files changed, 56 insertions(+)

diff --git a/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt b/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
index 1b1776a..b0fb145 100644
--- a/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
+++ b/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
@@ -10,6 +10,8 @@ Required properties:
        * the 8bit DIP switch
        * the slot count register
 
+- eeprom-gpios : should point to active-low write enable GPIO
+
 Example:
 
 	backplane {
@@ -17,4 +19,5 @@ Example:
 		reg = <0x0 0x2
 		       0x9002 0x2
 		       0x9046 0x2>;
+		eeprom-gpios = <&gpio 4 0>;
 	};
diff --git a/Documentation/misc-devices/lp8x4x_bus.txt b/Documentation/misc-devices/lp8x4x_bus.txt
index 829781b..78ea0a89 100644
--- a/Documentation/misc-devices/lp8x4x_bus.txt
+++ b/Documentation/misc-devices/lp8x4x_bus.txt
@@ -29,6 +29,9 @@ SYSFS
 dip
 	RO - shows status of LP-8x4x 8bit DIP switch
 
+eeprom_write_enable
+	RW - controls write access to board's EEPROM (1 - enable)
+
 rotary
 	RO - shows position of LP-8x4x rotary switch (0-9)
 
diff --git a/drivers/misc/lp8x4x_bus.c b/drivers/misc/lp8x4x_bus.c
index dfbc8c4..567fe078 100644
--- a/drivers/misc/lp8x4x_bus.c
+++ b/drivers/misc/lp8x4x_bus.c
@@ -9,6 +9,7 @@
  *  published by the Free Software Foundation or any later version.
  */
 #include <linux/err.h>
+#include <linux/gpio/consumer.h>
 #include <linux/init.h>
 #include <linux/io.h>
 #include <linux/list.h>
@@ -27,6 +28,7 @@ struct lp8x4x_master {
 	void			*count_addr;
 	void			*rotary_addr;
 	void			*dip_addr;
+	struct gpio_desc        *eeprom_nWE;
 	struct device		dev;
 };
 
@@ -68,6 +70,40 @@ static ssize_t rotary_show(struct device *dev,
 
 static DEVICE_ATTR_RO(rotary);
 
+static ssize_t eeprom_write_enable_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
+
+	return sprintf(buf, "%u\n", !gpiod_get_value(m->eeprom_nWE));
+}
+
+static ssize_t eeprom_write_enable_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
+	unsigned int val = 0;
+	int err;
+
+	if (!buf)
+		return count;
+
+	if (0 == count)
+		return count;
+
+	err = kstrtouint(buf, 10, &val);
+	if (err != 0) {
+		dev_err(dev, "Bad input %s\n", buf);
+		return count;
+	}
+
+	gpiod_set_value(m->eeprom_nWE, !val);
+
+	return count;
+}
+
+static DEVICE_ATTR_RW(eeprom_write_enable);
+
 static ssize_t dip_show(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
@@ -81,6 +117,7 @@ static DEVICE_ATTR_RO(dip);
 static struct attribute *master_dev_attrs[] = {
 	&dev_attr_slot_count.attr,
 	&dev_attr_rotary.attr,
+	&dev_attr_eeprom_write_enable.attr,
 	&dev_attr_dip.attr,
 	NULL,
 };
@@ -156,6 +193,19 @@ static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 		goto err_free;
 	}
 
+	m->eeprom_nWE = devm_gpiod_get(&pdev->dev, "eeprom");
+	if (IS_ERR(m->eeprom_nWE)) {
+		err = PTR_ERR(m->eeprom_nWE);
+		dev_err(&pdev->dev, "Failed to get eeprom GPIO\n");
+		goto err_free;
+	}
+
+	err = gpiod_direction_output(m->eeprom_nWE, 1);
+	if (err < 0) {
+		dev_err(&pdev->dev, "Failed to set eeprom GPIO output\n");
+		goto err_free;
+	}
+
 	m->slot_count = ioread8(m->count_addr);
 	switch (m->slot_count) {
 	case 1:
-- 
1.8.4.2

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

* [PATCH v4 16/21] misc: support for writing to LP-8x4x EEPROM
@ 2014-04-16 17:17                   ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2014-04-16 17:17 UTC (permalink / raw)
  To: linux-arm-kernel

at24c128 write protection is implemented by a separate GPIO line.
EEPROM driver doesn't provide this option, so we implement it
in the board-specific device.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
   v3..v4
   * move DTS binding to a different patch (8/21)

   v2..v3
   * new patch

 .../devicetree/bindings/misc/lp8x4x-bus.txt        |  3 ++
 Documentation/misc-devices/lp8x4x_bus.txt          |  3 ++
 drivers/misc/lp8x4x_bus.c                          | 50 ++++++++++++++++++++++
 3 files changed, 56 insertions(+)

diff --git a/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt b/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
index 1b1776a..b0fb145 100644
--- a/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
+++ b/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
@@ -10,6 +10,8 @@ Required properties:
        * the 8bit DIP switch
        * the slot count register
 
+- eeprom-gpios : should point to active-low write enable GPIO
+
 Example:
 
 	backplane {
@@ -17,4 +19,5 @@ Example:
 		reg = <0x0 0x2
 		       0x9002 0x2
 		       0x9046 0x2>;
+		eeprom-gpios = <&gpio 4 0>;
 	};
diff --git a/Documentation/misc-devices/lp8x4x_bus.txt b/Documentation/misc-devices/lp8x4x_bus.txt
index 829781b..78ea0a89 100644
--- a/Documentation/misc-devices/lp8x4x_bus.txt
+++ b/Documentation/misc-devices/lp8x4x_bus.txt
@@ -29,6 +29,9 @@ SYSFS
 dip
 	RO - shows status of LP-8x4x 8bit DIP switch
 
+eeprom_write_enable
+	RW - controls write access to board's EEPROM (1 - enable)
+
 rotary
 	RO - shows position of LP-8x4x rotary switch (0-9)
 
diff --git a/drivers/misc/lp8x4x_bus.c b/drivers/misc/lp8x4x_bus.c
index dfbc8c4..567fe078 100644
--- a/drivers/misc/lp8x4x_bus.c
+++ b/drivers/misc/lp8x4x_bus.c
@@ -9,6 +9,7 @@
  *  published by the Free Software Foundation or any later version.
  */
 #include <linux/err.h>
+#include <linux/gpio/consumer.h>
 #include <linux/init.h>
 #include <linux/io.h>
 #include <linux/list.h>
@@ -27,6 +28,7 @@ struct lp8x4x_master {
 	void			*count_addr;
 	void			*rotary_addr;
 	void			*dip_addr;
+	struct gpio_desc        *eeprom_nWE;
 	struct device		dev;
 };
 
@@ -68,6 +70,40 @@ static ssize_t rotary_show(struct device *dev,
 
 static DEVICE_ATTR_RO(rotary);
 
+static ssize_t eeprom_write_enable_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
+
+	return sprintf(buf, "%u\n", !gpiod_get_value(m->eeprom_nWE));
+}
+
+static ssize_t eeprom_write_enable_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
+	unsigned int val = 0;
+	int err;
+
+	if (!buf)
+		return count;
+
+	if (0 == count)
+		return count;
+
+	err = kstrtouint(buf, 10, &val);
+	if (err != 0) {
+		dev_err(dev, "Bad input %s\n", buf);
+		return count;
+	}
+
+	gpiod_set_value(m->eeprom_nWE, !val);
+
+	return count;
+}
+
+static DEVICE_ATTR_RW(eeprom_write_enable);
+
 static ssize_t dip_show(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
@@ -81,6 +117,7 @@ static DEVICE_ATTR_RO(dip);
 static struct attribute *master_dev_attrs[] = {
 	&dev_attr_slot_count.attr,
 	&dev_attr_rotary.attr,
+	&dev_attr_eeprom_write_enable.attr,
 	&dev_attr_dip.attr,
 	NULL,
 };
@@ -156,6 +193,19 @@ static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 		goto err_free;
 	}
 
+	m->eeprom_nWE = devm_gpiod_get(&pdev->dev, "eeprom");
+	if (IS_ERR(m->eeprom_nWE)) {
+		err = PTR_ERR(m->eeprom_nWE);
+		dev_err(&pdev->dev, "Failed to get eeprom GPIO\n");
+		goto err_free;
+	}
+
+	err = gpiod_direction_output(m->eeprom_nWE, 1);
+	if (err < 0) {
+		dev_err(&pdev->dev, "Failed to set eeprom GPIO output\n");
+		goto err_free;
+	}
+
 	m->slot_count = ioread8(m->count_addr);
 	switch (m->slot_count) {
 	case 1:
-- 
1.8.4.2

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

* [PATCH v4 17/21] misc: support for serial slots in LP-8x4x
  2014-04-16 17:17                 ` Sergei Ianovich
  (?)
@ 2014-04-16 17:17                   ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2014-04-16 17:17 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Randy Dunlap, Arnd Bergmann,
	Greg Kroah-Hartman, open list:OPEN FIRMWARE AND...,
	open list:DOCUMENTATION

Serial modules (I-870xxW series) implement DCON protocol which
allows one-master-many-slaves configuration over RS-485. When
these modules are installed into the device, they could be
accessed using the 2nd PXA built-in UART port (/dev/ttyS1).
However, it seems that addresses are not processed by the modules.
So the parallel bus needs to select which slot is connected.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
   v3..v4
   * move DTS binding to a different patch (8/21)

   v2..v3
   * no changes (except number 12/16 -> 17/21)

   v0..v2
   * use device tree
   * use devm helpers where possible

 .../devicetree/bindings/misc/lp8x4x-bus.txt        |  2 +
 Documentation/misc-devices/lp8x4x_bus.txt          | 15 +++++-
 drivers/misc/lp8x4x_bus.c                          | 63 ++++++++++++++++++++++
 3 files changed, 79 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt b/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
index b0fb145..24a8c62 100644
--- a/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
+++ b/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
@@ -8,6 +8,7 @@ Required properties:
 - reg: physical base addresses and region lengths of
        * the rotary switch
        * the 8bit DIP switch
+       * the serial slot select register
        * the slot count register
 
 - eeprom-gpios : should point to active-low write enable GPIO
@@ -18,6 +19,7 @@ Example:
 		compatible = "icpdas,backplane-lp8x4x";
 		reg = <0x0 0x2
 		       0x9002 0x2
+		       0x9004 0x2
 		       0x9046 0x2>;
 		eeprom-gpios = <&gpio 4 0>;
 	};
diff --git a/Documentation/misc-devices/lp8x4x_bus.txt b/Documentation/misc-devices/lp8x4x_bus.txt
index 78ea0a89..7b86797 100644
--- a/Documentation/misc-devices/lp8x4x_bus.txt
+++ b/Documentation/misc-devices/lp8x4x_bus.txt
@@ -19,13 +19,26 @@ LP-8x4x is an ARM-based industrial computer with a custom parallel bus to
 connect expansion modules with digital input/output, analog input/output,
 serial, CAN and other types of ports.
 
-The bus is implemented by a FPGA.
+The bus is implemented by a FPGA. There are two major groups of expansion
+modules: serial and parallel.
+
+Serial modules (I-870xxW series) implement DCON protocol which allows one-
+master-many-slaves configuration over RS-485. When these modules are installed
+into the device, they could be accessed using the 2nd PXA built-in UART port
+(/dev/ttyS1). However, it seems that addresses are not processed by
+the modules. So the parallel bus needs to select which slot is connected.
 
 SYSFS
 -----
 
 /sys/bus/icpdas/devices/backplane:
 
+active_slot
+	RW - connects the select slot for serial communications. If there
+	     is a parallel module in the selected slot, it simply ignores
+	     incoming packets. So it is safe to activate any available
+	     slot.
+
 dip
 	RO - shows status of LP-8x4x 8bit DIP switch
 
diff --git a/drivers/misc/lp8x4x_bus.c b/drivers/misc/lp8x4x_bus.c
index 567fe078..e805640 100644
--- a/drivers/misc/lp8x4x_bus.c
+++ b/drivers/misc/lp8x4x_bus.c
@@ -29,6 +29,8 @@ struct lp8x4x_master {
 	void			*rotary_addr;
 	void			*dip_addr;
 	struct gpio_desc        *eeprom_nWE;
+	unsigned int		active_slot;
+	void			*switch_addr;
 	struct device		dev;
 };
 
@@ -47,6 +49,9 @@ static void lp8x4x_master_release(struct device *dev)
 	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
 	WARN_ON(!dev);
 
+	/* Disable serial communications */
+	iowrite8(0xff, m->switch_addr);
+
 	kfree(m);
 }
 
@@ -114,11 +119,52 @@ static ssize_t dip_show(struct device *dev,
 
 static DEVICE_ATTR_RO(dip);
 
+static ssize_t active_slot_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
+
+	return sprintf(buf, "%u\n", m->active_slot);
+}
+
+static ssize_t active_slot_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
+	unsigned int active_slot = 0;
+	int err;
+
+	if (!buf)
+		return count;
+	if (0 == count)
+		return count;
+
+	err = kstrtouint(buf, 10, &active_slot);
+	if (err != 0 || active_slot > m->slot_count) {
+		dev_err(dev, "slot number is out of range 1..%u\n",
+				m->slot_count);
+		return count;
+	}
+
+	if (!active_slot) {
+		m->active_slot = 0;
+		iowrite8(0xff, m->switch_addr);
+		return count;
+	}
+
+	m->active_slot = active_slot;
+	iowrite8((1 << (m->active_slot - 1)) ^ 0xff, m->switch_addr);
+	return count;
+}
+
+static DEVICE_ATTR_RW(active_slot);
+
 static struct attribute *master_dev_attrs[] = {
 	&dev_attr_slot_count.attr,
 	&dev_attr_rotary.attr,
 	&dev_attr_eeprom_write_enable.attr,
 	&dev_attr_dip.attr,
+	&dev_attr_active_slot.attr,
 	NULL,
 };
 ATTRIBUTE_GROUPS(master_dev);
@@ -181,6 +227,20 @@ static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, r++);
 	if (!res) {
+		dev_err(&pdev->dev, "Failed to get slot switch address\n");
+		err = -ENODEV;
+		goto err_free;
+	}
+
+	m->switch_addr = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(m->switch_addr)) {
+		dev_err(&pdev->dev, "Failed to ioremap switch address\n");
+		err = PTR_ERR(m->switch_addr);
+		goto err_free;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, r++);
+	if (!res) {
 		dev_err(&pdev->dev, "could not get slot count address\n");
 		err = -ENODEV;
 		goto err_free;
@@ -223,6 +283,9 @@ static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 
 	dev_info(&pdev->dev, "found bus with up to %u slots\n", m->slot_count);
 
+	/* Disable serial communications until explicitly enabled */
+	iowrite8(0xff, m->switch_addr);
+
 	err = bus_register(&lp8x4x_bus_type);
 	if (err < 0) {
 		dev_err(&pdev->dev, "failed to register bus type\n");
-- 
1.8.4.2


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

* [PATCH v4 17/21] misc: support for serial slots in LP-8x4x
@ 2014-04-16 17:17                   ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2014-04-16 17:17 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Randy Dunlap, Arnd Bergmann,
	Greg Kroah-Hartman, open list:OPEN FIRMWARE AND...,
	open list:DOCUMENTATION

Serial modules (I-870xxW series) implement DCON protocol which
allows one-master-many-slaves configuration over RS-485. When
these modules are installed into the device, they could be
accessed using the 2nd PXA built-in UART port (/dev/ttyS1).
However, it seems that addresses are not processed by the modules.
So the parallel bus needs to select which slot is connected.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
   v3..v4
   * move DTS binding to a different patch (8/21)

   v2..v3
   * no changes (except number 12/16 -> 17/21)

   v0..v2
   * use device tree
   * use devm helpers where possible

 .../devicetree/bindings/misc/lp8x4x-bus.txt        |  2 +
 Documentation/misc-devices/lp8x4x_bus.txt          | 15 +++++-
 drivers/misc/lp8x4x_bus.c                          | 63 ++++++++++++++++++++++
 3 files changed, 79 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt b/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
index b0fb145..24a8c62 100644
--- a/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
+++ b/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
@@ -8,6 +8,7 @@ Required properties:
 - reg: physical base addresses and region lengths of
        * the rotary switch
        * the 8bit DIP switch
+       * the serial slot select register
        * the slot count register
 
 - eeprom-gpios : should point to active-low write enable GPIO
@@ -18,6 +19,7 @@ Example:
 		compatible = "icpdas,backplane-lp8x4x";
 		reg = <0x0 0x2
 		       0x9002 0x2
+		       0x9004 0x2
 		       0x9046 0x2>;
 		eeprom-gpios = <&gpio 4 0>;
 	};
diff --git a/Documentation/misc-devices/lp8x4x_bus.txt b/Documentation/misc-devices/lp8x4x_bus.txt
index 78ea0a89..7b86797 100644
--- a/Documentation/misc-devices/lp8x4x_bus.txt
+++ b/Documentation/misc-devices/lp8x4x_bus.txt
@@ -19,13 +19,26 @@ LP-8x4x is an ARM-based industrial computer with a custom parallel bus to
 connect expansion modules with digital input/output, analog input/output,
 serial, CAN and other types of ports.
 
-The bus is implemented by a FPGA.
+The bus is implemented by a FPGA. There are two major groups of expansion
+modules: serial and parallel.
+
+Serial modules (I-870xxW series) implement DCON protocol which allows one-
+master-many-slaves configuration over RS-485. When these modules are installed
+into the device, they could be accessed using the 2nd PXA built-in UART port
+(/dev/ttyS1). However, it seems that addresses are not processed by
+the modules. So the parallel bus needs to select which slot is connected.
 
 SYSFS
 -----
 
 /sys/bus/icpdas/devices/backplane:
 
+active_slot
+	RW - connects the select slot for serial communications. If there
+	     is a parallel module in the selected slot, it simply ignores
+	     incoming packets. So it is safe to activate any available
+	     slot.
+
 dip
 	RO - shows status of LP-8x4x 8bit DIP switch
 
diff --git a/drivers/misc/lp8x4x_bus.c b/drivers/misc/lp8x4x_bus.c
index 567fe078..e805640 100644
--- a/drivers/misc/lp8x4x_bus.c
+++ b/drivers/misc/lp8x4x_bus.c
@@ -29,6 +29,8 @@ struct lp8x4x_master {
 	void			*rotary_addr;
 	void			*dip_addr;
 	struct gpio_desc        *eeprom_nWE;
+	unsigned int		active_slot;
+	void			*switch_addr;
 	struct device		dev;
 };
 
@@ -47,6 +49,9 @@ static void lp8x4x_master_release(struct device *dev)
 	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
 	WARN_ON(!dev);
 
+	/* Disable serial communications */
+	iowrite8(0xff, m->switch_addr);
+
 	kfree(m);
 }
 
@@ -114,11 +119,52 @@ static ssize_t dip_show(struct device *dev,
 
 static DEVICE_ATTR_RO(dip);
 
+static ssize_t active_slot_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
+
+	return sprintf(buf, "%u\n", m->active_slot);
+}
+
+static ssize_t active_slot_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
+	unsigned int active_slot = 0;
+	int err;
+
+	if (!buf)
+		return count;
+	if (0 == count)
+		return count;
+
+	err = kstrtouint(buf, 10, &active_slot);
+	if (err != 0 || active_slot > m->slot_count) {
+		dev_err(dev, "slot number is out of range 1..%u\n",
+				m->slot_count);
+		return count;
+	}
+
+	if (!active_slot) {
+		m->active_slot = 0;
+		iowrite8(0xff, m->switch_addr);
+		return count;
+	}
+
+	m->active_slot = active_slot;
+	iowrite8((1 << (m->active_slot - 1)) ^ 0xff, m->switch_addr);
+	return count;
+}
+
+static DEVICE_ATTR_RW(active_slot);
+
 static struct attribute *master_dev_attrs[] = {
 	&dev_attr_slot_count.attr,
 	&dev_attr_rotary.attr,
 	&dev_attr_eeprom_write_enable.attr,
 	&dev_attr_dip.attr,
+	&dev_attr_active_slot.attr,
 	NULL,
 };
 ATTRIBUTE_GROUPS(master_dev);
@@ -181,6 +227,20 @@ static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, r++);
 	if (!res) {
+		dev_err(&pdev->dev, "Failed to get slot switch address\n");
+		err = -ENODEV;
+		goto err_free;
+	}
+
+	m->switch_addr = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(m->switch_addr)) {
+		dev_err(&pdev->dev, "Failed to ioremap switch address\n");
+		err = PTR_ERR(m->switch_addr);
+		goto err_free;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, r++);
+	if (!res) {
 		dev_err(&pdev->dev, "could not get slot count address\n");
 		err = -ENODEV;
 		goto err_free;
@@ -223,6 +283,9 @@ static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 
 	dev_info(&pdev->dev, "found bus with up to %u slots\n", m->slot_count);
 
+	/* Disable serial communications until explicitly enabled */
+	iowrite8(0xff, m->switch_addr);
+
 	err = bus_register(&lp8x4x_bus_type);
 	if (err < 0) {
 		dev_err(&pdev->dev, "failed to register bus type\n");
-- 
1.8.4.2


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

* [PATCH v4 17/21] misc: support for serial slots in LP-8x4x
@ 2014-04-16 17:17                   ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2014-04-16 17:17 UTC (permalink / raw)
  To: linux-arm-kernel

Serial modules (I-870xxW series) implement DCON protocol which
allows one-master-many-slaves configuration over RS-485. When
these modules are installed into the device, they could be
accessed using the 2nd PXA built-in UART port (/dev/ttyS1).
However, it seems that addresses are not processed by the modules.
So the parallel bus needs to select which slot is connected.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
   v3..v4
   * move DTS binding to a different patch (8/21)

   v2..v3
   * no changes (except number 12/16 -> 17/21)

   v0..v2
   * use device tree
   * use devm helpers where possible

 .../devicetree/bindings/misc/lp8x4x-bus.txt        |  2 +
 Documentation/misc-devices/lp8x4x_bus.txt          | 15 +++++-
 drivers/misc/lp8x4x_bus.c                          | 63 ++++++++++++++++++++++
 3 files changed, 79 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt b/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
index b0fb145..24a8c62 100644
--- a/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
+++ b/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
@@ -8,6 +8,7 @@ Required properties:
 - reg: physical base addresses and region lengths of
        * the rotary switch
        * the 8bit DIP switch
+       * the serial slot select register
        * the slot count register
 
 - eeprom-gpios : should point to active-low write enable GPIO
@@ -18,6 +19,7 @@ Example:
 		compatible = "icpdas,backplane-lp8x4x";
 		reg = <0x0 0x2
 		       0x9002 0x2
+		       0x9004 0x2
 		       0x9046 0x2>;
 		eeprom-gpios = <&gpio 4 0>;
 	};
diff --git a/Documentation/misc-devices/lp8x4x_bus.txt b/Documentation/misc-devices/lp8x4x_bus.txt
index 78ea0a89..7b86797 100644
--- a/Documentation/misc-devices/lp8x4x_bus.txt
+++ b/Documentation/misc-devices/lp8x4x_bus.txt
@@ -19,13 +19,26 @@ LP-8x4x is an ARM-based industrial computer with a custom parallel bus to
 connect expansion modules with digital input/output, analog input/output,
 serial, CAN and other types of ports.
 
-The bus is implemented by a FPGA.
+The bus is implemented by a FPGA. There are two major groups of expansion
+modules: serial and parallel.
+
+Serial modules (I-870xxW series) implement DCON protocol which allows one-
+master-many-slaves configuration over RS-485. When these modules are installed
+into the device, they could be accessed using the 2nd PXA built-in UART port
+(/dev/ttyS1). However, it seems that addresses are not processed by
+the modules. So the parallel bus needs to select which slot is connected.
 
 SYSFS
 -----
 
 /sys/bus/icpdas/devices/backplane:
 
+active_slot
+	RW - connects the select slot for serial communications. If there
+	     is a parallel module in the selected slot, it simply ignores
+	     incoming packets. So it is safe to activate any available
+	     slot.
+
 dip
 	RO - shows status of LP-8x4x 8bit DIP switch
 
diff --git a/drivers/misc/lp8x4x_bus.c b/drivers/misc/lp8x4x_bus.c
index 567fe078..e805640 100644
--- a/drivers/misc/lp8x4x_bus.c
+++ b/drivers/misc/lp8x4x_bus.c
@@ -29,6 +29,8 @@ struct lp8x4x_master {
 	void			*rotary_addr;
 	void			*dip_addr;
 	struct gpio_desc        *eeprom_nWE;
+	unsigned int		active_slot;
+	void			*switch_addr;
 	struct device		dev;
 };
 
@@ -47,6 +49,9 @@ static void lp8x4x_master_release(struct device *dev)
 	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
 	WARN_ON(!dev);
 
+	/* Disable serial communications */
+	iowrite8(0xff, m->switch_addr);
+
 	kfree(m);
 }
 
@@ -114,11 +119,52 @@ static ssize_t dip_show(struct device *dev,
 
 static DEVICE_ATTR_RO(dip);
 
+static ssize_t active_slot_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
+
+	return sprintf(buf, "%u\n", m->active_slot);
+}
+
+static ssize_t active_slot_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
+	unsigned int active_slot = 0;
+	int err;
+
+	if (!buf)
+		return count;
+	if (0 == count)
+		return count;
+
+	err = kstrtouint(buf, 10, &active_slot);
+	if (err != 0 || active_slot > m->slot_count) {
+		dev_err(dev, "slot number is out of range 1..%u\n",
+				m->slot_count);
+		return count;
+	}
+
+	if (!active_slot) {
+		m->active_slot = 0;
+		iowrite8(0xff, m->switch_addr);
+		return count;
+	}
+
+	m->active_slot = active_slot;
+	iowrite8((1 << (m->active_slot - 1)) ^ 0xff, m->switch_addr);
+	return count;
+}
+
+static DEVICE_ATTR_RW(active_slot);
+
 static struct attribute *master_dev_attrs[] = {
 	&dev_attr_slot_count.attr,
 	&dev_attr_rotary.attr,
 	&dev_attr_eeprom_write_enable.attr,
 	&dev_attr_dip.attr,
+	&dev_attr_active_slot.attr,
 	NULL,
 };
 ATTRIBUTE_GROUPS(master_dev);
@@ -181,6 +227,20 @@ static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, r++);
 	if (!res) {
+		dev_err(&pdev->dev, "Failed to get slot switch address\n");
+		err = -ENODEV;
+		goto err_free;
+	}
+
+	m->switch_addr = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(m->switch_addr)) {
+		dev_err(&pdev->dev, "Failed to ioremap switch address\n");
+		err = PTR_ERR(m->switch_addr);
+		goto err_free;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, r++);
+	if (!res) {
 		dev_err(&pdev->dev, "could not get slot count address\n");
 		err = -ENODEV;
 		goto err_free;
@@ -223,6 +283,9 @@ static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 
 	dev_info(&pdev->dev, "found bus with up to %u slots\n", m->slot_count);
 
+	/* Disable serial communications until explicitly enabled */
+	iowrite8(0xff, m->switch_addr);
+
 	err = bus_register(&lp8x4x_bus_type);
 	if (err < 0) {
 		dev_err(&pdev->dev, "failed to register bus type\n");
-- 
1.8.4.2

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

* [PATCH v4 18/21] misc: support for parallel slots in LP-8x4x
  2014-04-16 17:17                 ` Sergei Ianovich
  (?)
@ 2014-04-16 17:17                   ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2014-04-16 17:17 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Randy Dunlap, Arnd Bergmann,
	Greg Kroah-Hartman, open list:OPEN FIRMWARE AND...,
	open list:DOCUMENTATION

This patch enumerates parallel modules in expansion slots and exposes
model numbers via sysfs.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
   v3..v4
   * move DTS binding to a different patch (8/21)

   v2..v3
   * no changes (except number 13/16 -> 18/21)

   v0..v2
   * use device tree
   * use devm helpers where possible

 .../devicetree/bindings/misc/lp8x4x-bus.txt        |   9 ++
 Documentation/misc-devices/lp8x4x_bus.txt          |   8 ++
 drivers/misc/lp8x4x_bus.c                          | 119 +++++++++++++++++++++
 3 files changed, 136 insertions(+)

diff --git a/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt b/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
index 24a8c62..75ac3b2 100644
--- a/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
+++ b/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
@@ -7,6 +7,7 @@ Required properties:
 
 - reg: physical base addresses and region lengths of
        * the rotary switch
+       * 8 plugable industrial IO slots
        * the 8bit DIP switch
        * the serial slot select register
        * the slot count register
@@ -18,6 +19,14 @@ Example:
 	backplane {
 		compatible = "icpdas,backplane-lp8x4x";
 		reg = <0x0 0x2
+		       0x1000 0x10
+		       0x2000 0x10
+		       0x3000 0x10
+		       0x4000 0x10
+		       0x5000 0x10
+		       0x6000 0x10
+		       0x7000 0x10
+		       0x8000 0x10
 		       0x9002 0x2
 		       0x9004 0x2
 		       0x9046 0x2>;
diff --git a/Documentation/misc-devices/lp8x4x_bus.txt b/Documentation/misc-devices/lp8x4x_bus.txt
index 7b86797..09380fd 100644
--- a/Documentation/misc-devices/lp8x4x_bus.txt
+++ b/Documentation/misc-devices/lp8x4x_bus.txt
@@ -28,6 +28,9 @@ into the device, they could be accessed using the 2nd PXA built-in UART port
 (/dev/ttyS1). However, it seems that addresses are not processed by
 the modules. So the parallel bus needs to select which slot is connected.
 
+Parallel modules allow much faster communication. There are accessed using
+IO memory through the FPGA. Their ports are exposed via sysfs.
+
 SYSFS
 -----
 
@@ -50,3 +53,8 @@ rotary
 
 slot_count
 	RO - shows total number of expansion slots on the device
+
+/sys/bus/icpdas/devices/slot%02i:
+
+model
+	RO - shows expansion module model number
diff --git a/drivers/misc/lp8x4x_bus.c b/drivers/misc/lp8x4x_bus.c
index e805640..59dc767 100644
--- a/drivers/misc/lp8x4x_bus.c
+++ b/drivers/misc/lp8x4x_bus.c
@@ -23,6 +23,13 @@ MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Sergei Ianovich <ynvich@gmail.com>");
 MODULE_DESCRIPTION("ICP DAS LP-8x4x parallel bus driver");
 
+struct lp8x4x_slot {
+	void			*data_addr;
+	unsigned int		model;
+	struct device		dev;
+};
+
+#define LP8X4X_MAX_SLOT_COUNT	8
 struct lp8x4x_master {
 	unsigned int		slot_count;
 	void			*count_addr;
@@ -31,9 +38,45 @@ struct lp8x4x_master {
 	struct gpio_desc        *eeprom_nWE;
 	unsigned int		active_slot;
 	void			*switch_addr;
+	struct lp8x4x_slot	slot[LP8X4X_MAX_SLOT_COUNT];
 	struct device		dev;
 };
 
+static unsigned char lp8x4x_model[256] = {
+	   0,    0,    0, 0x11,    0, 0x18, 0x13, 0x11,
+	0x0e, 0x11,    0,    0,    0, 0x5a, 0x5b, 0x5c,
+	0x3c, 0x44, 0x34, 0x3a, 0x39, 0x36, 0x37, 0x33,
+	0x35, 0x40, 0x41, 0x42, 0x38, 0x3f, 0x32, 0x45,
+	0xac, 0x70, 0x8e, 0x8e, 0x1e, 0x72, 0x90, 0x29,
+	0x4a, 0x22, 0xd3, 0xd2, 0x28, 0x25, 0x2a, 0x29,
+	0x48, 0x49, 0x5d, 0x1f, 0x20, 0x23, 0x24, 0x4d,
+	0x3d, 0x3e,    0,    0,    0,    0,    0,    0,
+	   0, 0x78, 0x72, 0x2b, 0x5e, 0x5e, 0x36, 0xae,
+	0x30,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0, 0x5c, 0x5e,    0, 0x5e,    0,    0,
+	   0, 0x3b,    0,    0,    0,    0,    0,    0,
+	   0, 0x50, 0x2e,    0, 0x58,    0,    0, 0x43,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0, 0x54,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0
+};
+
 static int lp8x4x_match(struct device *dev, struct device_driver *drv)
 {
 	return 1;
@@ -44,6 +87,26 @@ static struct bus_type lp8x4x_bus_type = {
 	.match		= lp8x4x_match,
 };
 
+static void lp8x4x_slot_release(struct device *dev)
+{
+}
+
+static ssize_t model_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct lp8x4x_slot *s = container_of(dev, struct lp8x4x_slot, dev);
+
+	return sprintf(buf, "%u\n", s->model + 8000);
+}
+
+static DEVICE_ATTR_RO(model);
+
+static struct attribute *slot_dev_attrs[] = {
+	&dev_attr_model.attr,
+	NULL,
+};
+ATTRIBUTE_GROUPS(slot_dev);
+
 static void lp8x4x_master_release(struct device *dev)
 {
 	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
@@ -173,18 +236,50 @@ ATTRIBUTE_GROUPS(master_dev);
 static void devm_lp8x4x_bus_release(struct device *dev, void *res)
 {
 	struct lp8x4x_master *m = *(struct lp8x4x_master **)res;
+	struct lp8x4x_slot *s;
+	int i;
 
 	dev_dbg(dev, "releasing devices\n");
+	for (i = 0; i < LP8X4X_MAX_SLOT_COUNT; i++) {
+		s = &m->slot[i];
+		if (s->model)
+			device_unregister(&s->dev);
+	}
 	device_unregister(&m->dev);
 	bus_unregister(&lp8x4x_bus_type);
 }
 
+static void __init lp8x4x_bus_probe_slot(struct lp8x4x_master *m, int i,
+		unsigned char model)
+{
+	struct lp8x4x_slot *s = &m->slot[i];
+	int err;
+
+	dev_info(&m->dev, "found %u in slot %i\n", 8000 + model, i + 1);
+
+	s->dev.bus = &lp8x4x_bus_type;
+	dev_set_name(&s->dev, "slot%02i", i + 1);
+	s->dev.parent = &m->dev;
+	s->dev.release = lp8x4x_slot_release;
+	s->dev.groups = slot_dev_groups;
+	s->model = model;
+
+	err = device_register(&s->dev);
+	if (err < 0) {
+		dev_err(&s->dev, "failed to register device\n");
+		s->model = 0;
+		return;
+	}
+}
+
 static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 {
 	struct lp8x4x_master *m, **p;
 	struct resource *res;
 	int r = 0;
+	int i;
 	int err = 0;
+	unsigned int model;
 
 	m = kzalloc(sizeof(*m), GFP_KERNEL);
 	if (!m)
@@ -211,6 +306,23 @@ static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 		goto err_free;
 	}
 
+	for (i = 0; i < LP8X4X_MAX_SLOT_COUNT; i++) {
+		res = platform_get_resource(pdev, IORESOURCE_MEM, r++);
+		if (!res) {
+			dev_err(&pdev->dev, "Failed to get slot %i address\n",
+					i);
+			err = -ENODEV;
+			goto err_free;
+		}
+
+		m->slot[i].data_addr = devm_ioremap_resource(&pdev->dev, res);
+		if (IS_ERR(m->slot[i].data_addr)) {
+			dev_err(&pdev->dev, "Failed to ioremap slot %i\n", i);
+			err = PTR_ERR(m->slot[i].data_addr);
+			goto err_free;
+		}
+	}
+
 	res = platform_get_resource(pdev, IORESOURCE_MEM, r++);
 	if (!res) {
 		dev_err(&pdev->dev, "Failed to get DIP switch address\n");
@@ -305,6 +417,13 @@ static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 	}
 
 	devres_add(&pdev->dev, p);
+	for (i = 0; i < LP8X4X_MAX_SLOT_COUNT; i++) {
+		model = lp8x4x_model[ioread8(m->slot[i].data_addr)];
+		if (!model)
+			continue;
+
+		lp8x4x_bus_probe_slot(m, i, model);
+	}
 	return 0;
 
 err_bus:
-- 
1.8.4.2


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

* [PATCH v4 18/21] misc: support for parallel slots in LP-8x4x
@ 2014-04-16 17:17                   ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2014-04-16 17:17 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Randy Dunlap, Arnd Bergmann,
	Greg Kroah-Hartman, open list:OPEN FIRMWARE AND...,
	open list:DOCUMENTATION

This patch enumerates parallel modules in expansion slots and exposes
model numbers via sysfs.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
   v3..v4
   * move DTS binding to a different patch (8/21)

   v2..v3
   * no changes (except number 13/16 -> 18/21)

   v0..v2
   * use device tree
   * use devm helpers where possible

 .../devicetree/bindings/misc/lp8x4x-bus.txt        |   9 ++
 Documentation/misc-devices/lp8x4x_bus.txt          |   8 ++
 drivers/misc/lp8x4x_bus.c                          | 119 +++++++++++++++++++++
 3 files changed, 136 insertions(+)

diff --git a/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt b/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
index 24a8c62..75ac3b2 100644
--- a/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
+++ b/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
@@ -7,6 +7,7 @@ Required properties:
 
 - reg: physical base addresses and region lengths of
        * the rotary switch
+       * 8 plugable industrial IO slots
        * the 8bit DIP switch
        * the serial slot select register
        * the slot count register
@@ -18,6 +19,14 @@ Example:
 	backplane {
 		compatible = "icpdas,backplane-lp8x4x";
 		reg = <0x0 0x2
+		       0x1000 0x10
+		       0x2000 0x10
+		       0x3000 0x10
+		       0x4000 0x10
+		       0x5000 0x10
+		       0x6000 0x10
+		       0x7000 0x10
+		       0x8000 0x10
 		       0x9002 0x2
 		       0x9004 0x2
 		       0x9046 0x2>;
diff --git a/Documentation/misc-devices/lp8x4x_bus.txt b/Documentation/misc-devices/lp8x4x_bus.txt
index 7b86797..09380fd 100644
--- a/Documentation/misc-devices/lp8x4x_bus.txt
+++ b/Documentation/misc-devices/lp8x4x_bus.txt
@@ -28,6 +28,9 @@ into the device, they could be accessed using the 2nd PXA built-in UART port
 (/dev/ttyS1). However, it seems that addresses are not processed by
 the modules. So the parallel bus needs to select which slot is connected.
 
+Parallel modules allow much faster communication. There are accessed using
+IO memory through the FPGA. Their ports are exposed via sysfs.
+
 SYSFS
 -----
 
@@ -50,3 +53,8 @@ rotary
 
 slot_count
 	RO - shows total number of expansion slots on the device
+
+/sys/bus/icpdas/devices/slot%02i:
+
+model
+	RO - shows expansion module model number
diff --git a/drivers/misc/lp8x4x_bus.c b/drivers/misc/lp8x4x_bus.c
index e805640..59dc767 100644
--- a/drivers/misc/lp8x4x_bus.c
+++ b/drivers/misc/lp8x4x_bus.c
@@ -23,6 +23,13 @@ MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Sergei Ianovich <ynvich@gmail.com>");
 MODULE_DESCRIPTION("ICP DAS LP-8x4x parallel bus driver");
 
+struct lp8x4x_slot {
+	void			*data_addr;
+	unsigned int		model;
+	struct device		dev;
+};
+
+#define LP8X4X_MAX_SLOT_COUNT	8
 struct lp8x4x_master {
 	unsigned int		slot_count;
 	void			*count_addr;
@@ -31,9 +38,45 @@ struct lp8x4x_master {
 	struct gpio_desc        *eeprom_nWE;
 	unsigned int		active_slot;
 	void			*switch_addr;
+	struct lp8x4x_slot	slot[LP8X4X_MAX_SLOT_COUNT];
 	struct device		dev;
 };
 
+static unsigned char lp8x4x_model[256] = {
+	   0,    0,    0, 0x11,    0, 0x18, 0x13, 0x11,
+	0x0e, 0x11,    0,    0,    0, 0x5a, 0x5b, 0x5c,
+	0x3c, 0x44, 0x34, 0x3a, 0x39, 0x36, 0x37, 0x33,
+	0x35, 0x40, 0x41, 0x42, 0x38, 0x3f, 0x32, 0x45,
+	0xac, 0x70, 0x8e, 0x8e, 0x1e, 0x72, 0x90, 0x29,
+	0x4a, 0x22, 0xd3, 0xd2, 0x28, 0x25, 0x2a, 0x29,
+	0x48, 0x49, 0x5d, 0x1f, 0x20, 0x23, 0x24, 0x4d,
+	0x3d, 0x3e,    0,    0,    0,    0,    0,    0,
+	   0, 0x78, 0x72, 0x2b, 0x5e, 0x5e, 0x36, 0xae,
+	0x30,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0, 0x5c, 0x5e,    0, 0x5e,    0,    0,
+	   0, 0x3b,    0,    0,    0,    0,    0,    0,
+	   0, 0x50, 0x2e,    0, 0x58,    0,    0, 0x43,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0, 0x54,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0
+};
+
 static int lp8x4x_match(struct device *dev, struct device_driver *drv)
 {
 	return 1;
@@ -44,6 +87,26 @@ static struct bus_type lp8x4x_bus_type = {
 	.match		= lp8x4x_match,
 };
 
+static void lp8x4x_slot_release(struct device *dev)
+{
+}
+
+static ssize_t model_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct lp8x4x_slot *s = container_of(dev, struct lp8x4x_slot, dev);
+
+	return sprintf(buf, "%u\n", s->model + 8000);
+}
+
+static DEVICE_ATTR_RO(model);
+
+static struct attribute *slot_dev_attrs[] = {
+	&dev_attr_model.attr,
+	NULL,
+};
+ATTRIBUTE_GROUPS(slot_dev);
+
 static void lp8x4x_master_release(struct device *dev)
 {
 	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
@@ -173,18 +236,50 @@ ATTRIBUTE_GROUPS(master_dev);
 static void devm_lp8x4x_bus_release(struct device *dev, void *res)
 {
 	struct lp8x4x_master *m = *(struct lp8x4x_master **)res;
+	struct lp8x4x_slot *s;
+	int i;
 
 	dev_dbg(dev, "releasing devices\n");
+	for (i = 0; i < LP8X4X_MAX_SLOT_COUNT; i++) {
+		s = &m->slot[i];
+		if (s->model)
+			device_unregister(&s->dev);
+	}
 	device_unregister(&m->dev);
 	bus_unregister(&lp8x4x_bus_type);
 }
 
+static void __init lp8x4x_bus_probe_slot(struct lp8x4x_master *m, int i,
+		unsigned char model)
+{
+	struct lp8x4x_slot *s = &m->slot[i];
+	int err;
+
+	dev_info(&m->dev, "found %u in slot %i\n", 8000 + model, i + 1);
+
+	s->dev.bus = &lp8x4x_bus_type;
+	dev_set_name(&s->dev, "slot%02i", i + 1);
+	s->dev.parent = &m->dev;
+	s->dev.release = lp8x4x_slot_release;
+	s->dev.groups = slot_dev_groups;
+	s->model = model;
+
+	err = device_register(&s->dev);
+	if (err < 0) {
+		dev_err(&s->dev, "failed to register device\n");
+		s->model = 0;
+		return;
+	}
+}
+
 static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 {
 	struct lp8x4x_master *m, **p;
 	struct resource *res;
 	int r = 0;
+	int i;
 	int err = 0;
+	unsigned int model;
 
 	m = kzalloc(sizeof(*m), GFP_KERNEL);
 	if (!m)
@@ -211,6 +306,23 @@ static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 		goto err_free;
 	}
 
+	for (i = 0; i < LP8X4X_MAX_SLOT_COUNT; i++) {
+		res = platform_get_resource(pdev, IORESOURCE_MEM, r++);
+		if (!res) {
+			dev_err(&pdev->dev, "Failed to get slot %i address\n",
+					i);
+			err = -ENODEV;
+			goto err_free;
+		}
+
+		m->slot[i].data_addr = devm_ioremap_resource(&pdev->dev, res);
+		if (IS_ERR(m->slot[i].data_addr)) {
+			dev_err(&pdev->dev, "Failed to ioremap slot %i\n", i);
+			err = PTR_ERR(m->slot[i].data_addr);
+			goto err_free;
+		}
+	}
+
 	res = platform_get_resource(pdev, IORESOURCE_MEM, r++);
 	if (!res) {
 		dev_err(&pdev->dev, "Failed to get DIP switch address\n");
@@ -305,6 +417,13 @@ static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 	}
 
 	devres_add(&pdev->dev, p);
+	for (i = 0; i < LP8X4X_MAX_SLOT_COUNT; i++) {
+		model = lp8x4x_model[ioread8(m->slot[i].data_addr)];
+		if (!model)
+			continue;
+
+		lp8x4x_bus_probe_slot(m, i, model);
+	}
 	return 0;
 
 err_bus:
-- 
1.8.4.2

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

* [PATCH v4 18/21] misc: support for parallel slots in LP-8x4x
@ 2014-04-16 17:17                   ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2014-04-16 17:17 UTC (permalink / raw)
  To: linux-arm-kernel

This patch enumerates parallel modules in expansion slots and exposes
model numbers via sysfs.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
   v3..v4
   * move DTS binding to a different patch (8/21)

   v2..v3
   * no changes (except number 13/16 -> 18/21)

   v0..v2
   * use device tree
   * use devm helpers where possible

 .../devicetree/bindings/misc/lp8x4x-bus.txt        |   9 ++
 Documentation/misc-devices/lp8x4x_bus.txt          |   8 ++
 drivers/misc/lp8x4x_bus.c                          | 119 +++++++++++++++++++++
 3 files changed, 136 insertions(+)

diff --git a/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt b/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
index 24a8c62..75ac3b2 100644
--- a/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
+++ b/Documentation/devicetree/bindings/misc/lp8x4x-bus.txt
@@ -7,6 +7,7 @@ Required properties:
 
 - reg: physical base addresses and region lengths of
        * the rotary switch
+       * 8 plugable industrial IO slots
        * the 8bit DIP switch
        * the serial slot select register
        * the slot count register
@@ -18,6 +19,14 @@ Example:
 	backplane {
 		compatible = "icpdas,backplane-lp8x4x";
 		reg = <0x0 0x2
+		       0x1000 0x10
+		       0x2000 0x10
+		       0x3000 0x10
+		       0x4000 0x10
+		       0x5000 0x10
+		       0x6000 0x10
+		       0x7000 0x10
+		       0x8000 0x10
 		       0x9002 0x2
 		       0x9004 0x2
 		       0x9046 0x2>;
diff --git a/Documentation/misc-devices/lp8x4x_bus.txt b/Documentation/misc-devices/lp8x4x_bus.txt
index 7b86797..09380fd 100644
--- a/Documentation/misc-devices/lp8x4x_bus.txt
+++ b/Documentation/misc-devices/lp8x4x_bus.txt
@@ -28,6 +28,9 @@ into the device, they could be accessed using the 2nd PXA built-in UART port
 (/dev/ttyS1). However, it seems that addresses are not processed by
 the modules. So the parallel bus needs to select which slot is connected.
 
+Parallel modules allow much faster communication. There are accessed using
+IO memory through the FPGA. Their ports are exposed via sysfs.
+
 SYSFS
 -----
 
@@ -50,3 +53,8 @@ rotary
 
 slot_count
 	RO - shows total number of expansion slots on the device
+
+/sys/bus/icpdas/devices/slot%02i:
+
+model
+	RO - shows expansion module model number
diff --git a/drivers/misc/lp8x4x_bus.c b/drivers/misc/lp8x4x_bus.c
index e805640..59dc767 100644
--- a/drivers/misc/lp8x4x_bus.c
+++ b/drivers/misc/lp8x4x_bus.c
@@ -23,6 +23,13 @@ MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Sergei Ianovich <ynvich@gmail.com>");
 MODULE_DESCRIPTION("ICP DAS LP-8x4x parallel bus driver");
 
+struct lp8x4x_slot {
+	void			*data_addr;
+	unsigned int		model;
+	struct device		dev;
+};
+
+#define LP8X4X_MAX_SLOT_COUNT	8
 struct lp8x4x_master {
 	unsigned int		slot_count;
 	void			*count_addr;
@@ -31,9 +38,45 @@ struct lp8x4x_master {
 	struct gpio_desc        *eeprom_nWE;
 	unsigned int		active_slot;
 	void			*switch_addr;
+	struct lp8x4x_slot	slot[LP8X4X_MAX_SLOT_COUNT];
 	struct device		dev;
 };
 
+static unsigned char lp8x4x_model[256] = {
+	   0,    0,    0, 0x11,    0, 0x18, 0x13, 0x11,
+	0x0e, 0x11,    0,    0,    0, 0x5a, 0x5b, 0x5c,
+	0x3c, 0x44, 0x34, 0x3a, 0x39, 0x36, 0x37, 0x33,
+	0x35, 0x40, 0x41, 0x42, 0x38, 0x3f, 0x32, 0x45,
+	0xac, 0x70, 0x8e, 0x8e, 0x1e, 0x72, 0x90, 0x29,
+	0x4a, 0x22, 0xd3, 0xd2, 0x28, 0x25, 0x2a, 0x29,
+	0x48, 0x49, 0x5d, 0x1f, 0x20, 0x23, 0x24, 0x4d,
+	0x3d, 0x3e,    0,    0,    0,    0,    0,    0,
+	   0, 0x78, 0x72, 0x2b, 0x5e, 0x5e, 0x36, 0xae,
+	0x30,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0, 0x5c, 0x5e,    0, 0x5e,    0,    0,
+	   0, 0x3b,    0,    0,    0,    0,    0,    0,
+	   0, 0x50, 0x2e,    0, 0x58,    0,    0, 0x43,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0, 0x54,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0,
+	   0,    0,    0,    0,    0,    0,    0,    0
+};
+
 static int lp8x4x_match(struct device *dev, struct device_driver *drv)
 {
 	return 1;
@@ -44,6 +87,26 @@ static struct bus_type lp8x4x_bus_type = {
 	.match		= lp8x4x_match,
 };
 
+static void lp8x4x_slot_release(struct device *dev)
+{
+}
+
+static ssize_t model_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct lp8x4x_slot *s = container_of(dev, struct lp8x4x_slot, dev);
+
+	return sprintf(buf, "%u\n", s->model + 8000);
+}
+
+static DEVICE_ATTR_RO(model);
+
+static struct attribute *slot_dev_attrs[] = {
+	&dev_attr_model.attr,
+	NULL,
+};
+ATTRIBUTE_GROUPS(slot_dev);
+
 static void lp8x4x_master_release(struct device *dev)
 {
 	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
@@ -173,18 +236,50 @@ ATTRIBUTE_GROUPS(master_dev);
 static void devm_lp8x4x_bus_release(struct device *dev, void *res)
 {
 	struct lp8x4x_master *m = *(struct lp8x4x_master **)res;
+	struct lp8x4x_slot *s;
+	int i;
 
 	dev_dbg(dev, "releasing devices\n");
+	for (i = 0; i < LP8X4X_MAX_SLOT_COUNT; i++) {
+		s = &m->slot[i];
+		if (s->model)
+			device_unregister(&s->dev);
+	}
 	device_unregister(&m->dev);
 	bus_unregister(&lp8x4x_bus_type);
 }
 
+static void __init lp8x4x_bus_probe_slot(struct lp8x4x_master *m, int i,
+		unsigned char model)
+{
+	struct lp8x4x_slot *s = &m->slot[i];
+	int err;
+
+	dev_info(&m->dev, "found %u in slot %i\n", 8000 + model, i + 1);
+
+	s->dev.bus = &lp8x4x_bus_type;
+	dev_set_name(&s->dev, "slot%02i", i + 1);
+	s->dev.parent = &m->dev;
+	s->dev.release = lp8x4x_slot_release;
+	s->dev.groups = slot_dev_groups;
+	s->model = model;
+
+	err = device_register(&s->dev);
+	if (err < 0) {
+		dev_err(&s->dev, "failed to register device\n");
+		s->model = 0;
+		return;
+	}
+}
+
 static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 {
 	struct lp8x4x_master *m, **p;
 	struct resource *res;
 	int r = 0;
+	int i;
 	int err = 0;
+	unsigned int model;
 
 	m = kzalloc(sizeof(*m), GFP_KERNEL);
 	if (!m)
@@ -211,6 +306,23 @@ static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 		goto err_free;
 	}
 
+	for (i = 0; i < LP8X4X_MAX_SLOT_COUNT; i++) {
+		res = platform_get_resource(pdev, IORESOURCE_MEM, r++);
+		if (!res) {
+			dev_err(&pdev->dev, "Failed to get slot %i address\n",
+					i);
+			err = -ENODEV;
+			goto err_free;
+		}
+
+		m->slot[i].data_addr = devm_ioremap_resource(&pdev->dev, res);
+		if (IS_ERR(m->slot[i].data_addr)) {
+			dev_err(&pdev->dev, "Failed to ioremap slot %i\n", i);
+			err = PTR_ERR(m->slot[i].data_addr);
+			goto err_free;
+		}
+	}
+
 	res = platform_get_resource(pdev, IORESOURCE_MEM, r++);
 	if (!res) {
 		dev_err(&pdev->dev, "Failed to get DIP switch address\n");
@@ -305,6 +417,13 @@ static int __init lp8x4x_bus_probe(struct platform_device *pdev)
 	}
 
 	devres_add(&pdev->dev, p);
+	for (i = 0; i < LP8X4X_MAX_SLOT_COUNT; i++) {
+		model = lp8x4x_model[ioread8(m->slot[i].data_addr)];
+		if (!model)
+			continue;
+
+		lp8x4x_bus_probe_slot(m, i, model);
+	}
 	return 0;
 
 err_bus:
-- 
1.8.4.2

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

* [PATCH v4 19/21] misc: support for I-8041 in LP-8x4x
  2014-04-16 17:17                 ` Sergei Ianovich
@ 2014-04-16 17:17                   ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2014-04-16 17:17 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Randy Dunlap, Arnd Bergmann, Greg Kroah-Hartman,
	open list:DOCUMENTATION

Status of I-8041 32 digital output channels can be managed via
sysfs now.

http://www.icpdas.com/products/Remote_IO/i-8ke/i-8041w.htm

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
   v3..v4
   v2..v3
   v0..v2
   * no changes (except number 14/16 -> 19/21)

 Documentation/misc-devices/lp8x4x_bus.txt |  4 ++
 drivers/misc/lp8x4x_bus.c                 | 67 ++++++++++++++++++++++++++++++-
 2 files changed, 69 insertions(+), 2 deletions(-)

diff --git a/Documentation/misc-devices/lp8x4x_bus.txt b/Documentation/misc-devices/lp8x4x_bus.txt
index 09380fd..68fefde 100644
--- a/Documentation/misc-devices/lp8x4x_bus.txt
+++ b/Documentation/misc-devices/lp8x4x_bus.txt
@@ -58,3 +58,7 @@ slot_count
 
 model
 	RO - shows expansion module model number
+
+output_status
+	RW - set status of digital output channels on the module in
+	     the expansion slot. Value can be read back.
diff --git a/drivers/misc/lp8x4x_bus.c b/drivers/misc/lp8x4x_bus.c
index 59dc767..5af788d 100644
--- a/drivers/misc/lp8x4x_bus.c
+++ b/drivers/misc/lp8x4x_bus.c
@@ -26,6 +26,9 @@ MODULE_DESCRIPTION("ICP DAS LP-8x4x parallel bus driver");
 struct lp8x4x_slot {
 	void			*data_addr;
 	unsigned int		model;
+	struct mutex		lock;
+	unsigned int		DO_len;
+	u32			DO;
 	struct device		dev;
 };
 
@@ -91,6 +94,45 @@ static void lp8x4x_slot_release(struct device *dev)
 {
 }
 
+static void lp8x4x_slot_set_DO(struct lp8x4x_slot *s)
+{
+	int i;
+	mutex_lock(&s->lock);
+	for (i = 0; i < s->DO_len; i++)
+		iowrite8((s->DO >> (i * 8)) & 0xff, s->data_addr + 2 * i);
+	mutex_unlock(&s->lock);
+}
+
+static ssize_t output_status_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct lp8x4x_slot *s = container_of(dev, struct lp8x4x_slot, dev);
+
+	return sprintf(buf, "0x%08x\n", s->DO);
+}
+
+static ssize_t output_status_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct lp8x4x_slot *s = container_of(dev, struct lp8x4x_slot, dev);
+
+	if (!buf)
+		return count;
+	if (0 == count)
+		return count;
+
+	if (kstrtouint(buf, 16, &s->DO) != 0) {
+		dev_err(dev, "bad input\n");
+		return count;
+	}
+
+	lp8x4x_slot_set_DO(s);
+
+	return count;
+}
+
+static DEVICE_ATTR_RW(output_status);
+
 static ssize_t model_show(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
@@ -107,6 +149,13 @@ static struct attribute *slot_dev_attrs[] = {
 };
 ATTRIBUTE_GROUPS(slot_dev);
 
+static struct attribute *do_slot_dev_attrs[] = {
+	&dev_attr_model.attr,
+	&dev_attr_output_status.attr,
+	NULL,
+};
+ATTRIBUTE_GROUPS(do_slot_dev);
+
 static void lp8x4x_master_release(struct device *dev)
 {
 	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
@@ -242,8 +291,10 @@ static void devm_lp8x4x_bus_release(struct device *dev, void *res)
 	dev_dbg(dev, "releasing devices\n");
 	for (i = 0; i < LP8X4X_MAX_SLOT_COUNT; i++) {
 		s = &m->slot[i];
-		if (s->model)
+		if (s->model) {
 			device_unregister(&s->dev);
+			mutex_destroy(&s->lock);
+		}
 	}
 	device_unregister(&m->dev);
 	bus_unregister(&lp8x4x_bus_type);
@@ -261,13 +312,25 @@ static void __init lp8x4x_bus_probe_slot(struct lp8x4x_master *m, int i,
 	dev_set_name(&s->dev, "slot%02i", i + 1);
 	s->dev.parent = &m->dev;
 	s->dev.release = lp8x4x_slot_release;
-	s->dev.groups = slot_dev_groups;
 	s->model = model;
+	mutex_init(&s->lock);
+
+	switch (model) {
+	case 41:
+		s->DO_len = 4;
+		lp8x4x_slot_set_DO(s);
+		s->dev.groups = do_slot_dev_groups;
+		break;
+	default:
+		s->dev.groups = slot_dev_groups;
+		break;
+	};
 
 	err = device_register(&s->dev);
 	if (err < 0) {
 		dev_err(&s->dev, "failed to register device\n");
 		s->model = 0;
+		mutex_destroy(&s->lock);
 		return;
 	}
 }
-- 
1.8.4.2


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

* [PATCH v4 19/21] misc: support for I-8041 in LP-8x4x
@ 2014-04-16 17:17                   ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2014-04-16 17:17 UTC (permalink / raw)
  To: linux-arm-kernel

Status of I-8041 32 digital output channels can be managed via
sysfs now.

http://www.icpdas.com/products/Remote_IO/i-8ke/i-8041w.htm

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
   v3..v4
   v2..v3
   v0..v2
   * no changes (except number 14/16 -> 19/21)

 Documentation/misc-devices/lp8x4x_bus.txt |  4 ++
 drivers/misc/lp8x4x_bus.c                 | 67 ++++++++++++++++++++++++++++++-
 2 files changed, 69 insertions(+), 2 deletions(-)

diff --git a/Documentation/misc-devices/lp8x4x_bus.txt b/Documentation/misc-devices/lp8x4x_bus.txt
index 09380fd..68fefde 100644
--- a/Documentation/misc-devices/lp8x4x_bus.txt
+++ b/Documentation/misc-devices/lp8x4x_bus.txt
@@ -58,3 +58,7 @@ slot_count
 
 model
 	RO - shows expansion module model number
+
+output_status
+	RW - set status of digital output channels on the module in
+	     the expansion slot. Value can be read back.
diff --git a/drivers/misc/lp8x4x_bus.c b/drivers/misc/lp8x4x_bus.c
index 59dc767..5af788d 100644
--- a/drivers/misc/lp8x4x_bus.c
+++ b/drivers/misc/lp8x4x_bus.c
@@ -26,6 +26,9 @@ MODULE_DESCRIPTION("ICP DAS LP-8x4x parallel bus driver");
 struct lp8x4x_slot {
 	void			*data_addr;
 	unsigned int		model;
+	struct mutex		lock;
+	unsigned int		DO_len;
+	u32			DO;
 	struct device		dev;
 };
 
@@ -91,6 +94,45 @@ static void lp8x4x_slot_release(struct device *dev)
 {
 }
 
+static void lp8x4x_slot_set_DO(struct lp8x4x_slot *s)
+{
+	int i;
+	mutex_lock(&s->lock);
+	for (i = 0; i < s->DO_len; i++)
+		iowrite8((s->DO >> (i * 8)) & 0xff, s->data_addr + 2 * i);
+	mutex_unlock(&s->lock);
+}
+
+static ssize_t output_status_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct lp8x4x_slot *s = container_of(dev, struct lp8x4x_slot, dev);
+
+	return sprintf(buf, "0x%08x\n", s->DO);
+}
+
+static ssize_t output_status_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct lp8x4x_slot *s = container_of(dev, struct lp8x4x_slot, dev);
+
+	if (!buf)
+		return count;
+	if (0 == count)
+		return count;
+
+	if (kstrtouint(buf, 16, &s->DO) != 0) {
+		dev_err(dev, "bad input\n");
+		return count;
+	}
+
+	lp8x4x_slot_set_DO(s);
+
+	return count;
+}
+
+static DEVICE_ATTR_RW(output_status);
+
 static ssize_t model_show(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
@@ -107,6 +149,13 @@ static struct attribute *slot_dev_attrs[] = {
 };
 ATTRIBUTE_GROUPS(slot_dev);
 
+static struct attribute *do_slot_dev_attrs[] = {
+	&dev_attr_model.attr,
+	&dev_attr_output_status.attr,
+	NULL,
+};
+ATTRIBUTE_GROUPS(do_slot_dev);
+
 static void lp8x4x_master_release(struct device *dev)
 {
 	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
@@ -242,8 +291,10 @@ static void devm_lp8x4x_bus_release(struct device *dev, void *res)
 	dev_dbg(dev, "releasing devices\n");
 	for (i = 0; i < LP8X4X_MAX_SLOT_COUNT; i++) {
 		s = &m->slot[i];
-		if (s->model)
+		if (s->model) {
 			device_unregister(&s->dev);
+			mutex_destroy(&s->lock);
+		}
 	}
 	device_unregister(&m->dev);
 	bus_unregister(&lp8x4x_bus_type);
@@ -261,13 +312,25 @@ static void __init lp8x4x_bus_probe_slot(struct lp8x4x_master *m, int i,
 	dev_set_name(&s->dev, "slot%02i", i + 1);
 	s->dev.parent = &m->dev;
 	s->dev.release = lp8x4x_slot_release;
-	s->dev.groups = slot_dev_groups;
 	s->model = model;
+	mutex_init(&s->lock);
+
+	switch (model) {
+	case 41:
+		s->DO_len = 4;
+		lp8x4x_slot_set_DO(s);
+		s->dev.groups = do_slot_dev_groups;
+		break;
+	default:
+		s->dev.groups = slot_dev_groups;
+		break;
+	};
 
 	err = device_register(&s->dev);
 	if (err < 0) {
 		dev_err(&s->dev, "failed to register device\n");
 		s->model = 0;
+		mutex_destroy(&s->lock);
 		return;
 	}
 }
-- 
1.8.4.2

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

* [PATCH v4 20/21] misc: support for I-8042 in LP-8x4x
  2014-04-16 17:17                 ` Sergei Ianovich
@ 2014-04-16 17:17                   ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2014-04-16 17:17 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Randy Dunlap, Arnd Bergmann, Greg Kroah-Hartman,
	open list:DOCUMENTATION

Status of I-8042 16 digital output channels can be managed via
sysfs.

Status of I-8042 16 digital input channels can be read via sysfs.

http://www.icpdas.com/products/Remote_IO/i-8ke/i-8042w.htm

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
   v3..v4
   v2..v3
   v0..v2
   * no changes (except number 15/16 -> 20/21)

 Documentation/misc-devices/lp8x4x_bus.txt |  4 ++
 drivers/misc/lp8x4x_bus.c                 | 76 ++++++++++++++++++++++++++++++-
 2 files changed, 78 insertions(+), 2 deletions(-)

diff --git a/Documentation/misc-devices/lp8x4x_bus.txt b/Documentation/misc-devices/lp8x4x_bus.txt
index 68fefde..3ea257d 100644
--- a/Documentation/misc-devices/lp8x4x_bus.txt
+++ b/Documentation/misc-devices/lp8x4x_bus.txt
@@ -59,6 +59,10 @@ slot_count
 model
 	RO - shows expansion module model number
 
+input_status
+	RO - get status of digital input channels on the module in
+	     the expansion slot.
+
 output_status
 	RW - set status of digital output channels on the module in
 	     the expansion slot. Value can be read back.
diff --git a/drivers/misc/lp8x4x_bus.c b/drivers/misc/lp8x4x_bus.c
index 5af788d..3fb227d 100644
--- a/drivers/misc/lp8x4x_bus.c
+++ b/drivers/misc/lp8x4x_bus.c
@@ -29,6 +29,8 @@ struct lp8x4x_slot {
 	struct mutex		lock;
 	unsigned int		DO_len;
 	u32			DO;
+	unsigned int		DI_len;
+	u32			DI;
 	struct device		dev;
 };
 
@@ -94,6 +96,21 @@ static void lp8x4x_slot_release(struct device *dev)
 {
 }
 
+static void lp8x4x_slot_get_DI(struct lp8x4x_slot *s)
+{
+	int i;
+	u32 b;
+
+	mutex_lock(&s->lock);
+	s->DI = 0;
+	for (i = 0; i < s->DI_len; i++) {
+		b = ioread8(s->data_addr + 2 * (i + 1));
+		b ^= 0xff;
+		s->DI += b << (i * 8);
+	}
+	mutex_unlock(&s->lock);
+}
+
 static void lp8x4x_slot_set_DO(struct lp8x4x_slot *s)
 {
 	int i;
@@ -103,29 +120,70 @@ static void lp8x4x_slot_set_DO(struct lp8x4x_slot *s)
 	mutex_unlock(&s->lock);
 }
 
+static ssize_t input_status_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct lp8x4x_slot *s = container_of(dev, struct lp8x4x_slot, dev);
+
+	lp8x4x_slot_get_DI(s);
+	switch (s->DI_len) {
+	case 4:
+		return sprintf(buf, "0x%08x\n", s->DI);
+	case 2:
+		return sprintf(buf, "0x%04x\n", s->DI);
+	case 1:
+		return sprintf(buf, "0x%02x\n", s->DI);
+	default:
+		break;
+	}
+	return sprintf(buf, "0x%x\n", s->DI);
+}
+
+static DEVICE_ATTR_RO(input_status);
+
 static ssize_t output_status_show(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
 	struct lp8x4x_slot *s = container_of(dev, struct lp8x4x_slot, dev);
 
-	return sprintf(buf, "0x%08x\n", s->DO);
+	switch (s->DO_len) {
+	case 4:
+		return sprintf(buf, "0x%08x\n", s->DO);
+	case 2:
+		return sprintf(buf, "0x%04x\n", s->DO);
+	case 1:
+		return sprintf(buf, "0x%02x\n", s->DO);
+	default:
+		break;
+	}
+	return sprintf(buf, "0x%x\n", s->DO);
 }
 
 static ssize_t output_status_store(struct device *dev,
 		struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct lp8x4x_slot *s = container_of(dev, struct lp8x4x_slot, dev);
+	u32 DO;
+	u8 *b = (void *) &DO;
+	int i;
 
 	if (!buf)
 		return count;
 	if (0 == count)
 		return count;
 
-	if (kstrtouint(buf, 16, &s->DO) != 0) {
+	if (kstrtouint(buf, 16, &DO) != 0) {
 		dev_err(dev, "bad input\n");
 		return count;
 	}
 
+	for (i = 4; i > s->DO_len; i--)
+		if (b[i - 1] != 0) {
+			dev_err(dev, "bad input\n");
+			return count;
+		}
+
+	s->DO = DO;
 	lp8x4x_slot_set_DO(s);
 
 	return count;
@@ -156,6 +214,14 @@ static struct attribute *do_slot_dev_attrs[] = {
 };
 ATTRIBUTE_GROUPS(do_slot_dev);
 
+static struct attribute *dio_slot_dev_attrs[] = {
+	&dev_attr_model.attr,
+	&dev_attr_output_status.attr,
+	&dev_attr_input_status.attr,
+	NULL,
+};
+ATTRIBUTE_GROUPS(dio_slot_dev);
+
 static void lp8x4x_master_release(struct device *dev)
 {
 	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
@@ -321,6 +387,12 @@ static void __init lp8x4x_bus_probe_slot(struct lp8x4x_master *m, int i,
 		lp8x4x_slot_set_DO(s);
 		s->dev.groups = do_slot_dev_groups;
 		break;
+	case 42:
+		s->DI_len = 2;
+		s->DO_len = 2;
+		lp8x4x_slot_set_DO(s);
+		s->dev.groups = dio_slot_dev_groups;
+		break;
 	default:
 		s->dev.groups = slot_dev_groups;
 		break;
-- 
1.8.4.2


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

* [PATCH v4 20/21] misc: support for I-8042 in LP-8x4x
@ 2014-04-16 17:17                   ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2014-04-16 17:17 UTC (permalink / raw)
  To: linux-arm-kernel

Status of I-8042 16 digital output channels can be managed via
sysfs.

Status of I-8042 16 digital input channels can be read via sysfs.

http://www.icpdas.com/products/Remote_IO/i-8ke/i-8042w.htm

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
   v3..v4
   v2..v3
   v0..v2
   * no changes (except number 15/16 -> 20/21)

 Documentation/misc-devices/lp8x4x_bus.txt |  4 ++
 drivers/misc/lp8x4x_bus.c                 | 76 ++++++++++++++++++++++++++++++-
 2 files changed, 78 insertions(+), 2 deletions(-)

diff --git a/Documentation/misc-devices/lp8x4x_bus.txt b/Documentation/misc-devices/lp8x4x_bus.txt
index 68fefde..3ea257d 100644
--- a/Documentation/misc-devices/lp8x4x_bus.txt
+++ b/Documentation/misc-devices/lp8x4x_bus.txt
@@ -59,6 +59,10 @@ slot_count
 model
 	RO - shows expansion module model number
 
+input_status
+	RO - get status of digital input channels on the module in
+	     the expansion slot.
+
 output_status
 	RW - set status of digital output channels on the module in
 	     the expansion slot. Value can be read back.
diff --git a/drivers/misc/lp8x4x_bus.c b/drivers/misc/lp8x4x_bus.c
index 5af788d..3fb227d 100644
--- a/drivers/misc/lp8x4x_bus.c
+++ b/drivers/misc/lp8x4x_bus.c
@@ -29,6 +29,8 @@ struct lp8x4x_slot {
 	struct mutex		lock;
 	unsigned int		DO_len;
 	u32			DO;
+	unsigned int		DI_len;
+	u32			DI;
 	struct device		dev;
 };
 
@@ -94,6 +96,21 @@ static void lp8x4x_slot_release(struct device *dev)
 {
 }
 
+static void lp8x4x_slot_get_DI(struct lp8x4x_slot *s)
+{
+	int i;
+	u32 b;
+
+	mutex_lock(&s->lock);
+	s->DI = 0;
+	for (i = 0; i < s->DI_len; i++) {
+		b = ioread8(s->data_addr + 2 * (i + 1));
+		b ^= 0xff;
+		s->DI += b << (i * 8);
+	}
+	mutex_unlock(&s->lock);
+}
+
 static void lp8x4x_slot_set_DO(struct lp8x4x_slot *s)
 {
 	int i;
@@ -103,29 +120,70 @@ static void lp8x4x_slot_set_DO(struct lp8x4x_slot *s)
 	mutex_unlock(&s->lock);
 }
 
+static ssize_t input_status_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct lp8x4x_slot *s = container_of(dev, struct lp8x4x_slot, dev);
+
+	lp8x4x_slot_get_DI(s);
+	switch (s->DI_len) {
+	case 4:
+		return sprintf(buf, "0x%08x\n", s->DI);
+	case 2:
+		return sprintf(buf, "0x%04x\n", s->DI);
+	case 1:
+		return sprintf(buf, "0x%02x\n", s->DI);
+	default:
+		break;
+	}
+	return sprintf(buf, "0x%x\n", s->DI);
+}
+
+static DEVICE_ATTR_RO(input_status);
+
 static ssize_t output_status_show(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
 	struct lp8x4x_slot *s = container_of(dev, struct lp8x4x_slot, dev);
 
-	return sprintf(buf, "0x%08x\n", s->DO);
+	switch (s->DO_len) {
+	case 4:
+		return sprintf(buf, "0x%08x\n", s->DO);
+	case 2:
+		return sprintf(buf, "0x%04x\n", s->DO);
+	case 1:
+		return sprintf(buf, "0x%02x\n", s->DO);
+	default:
+		break;
+	}
+	return sprintf(buf, "0x%x\n", s->DO);
 }
 
 static ssize_t output_status_store(struct device *dev,
 		struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct lp8x4x_slot *s = container_of(dev, struct lp8x4x_slot, dev);
+	u32 DO;
+	u8 *b = (void *) &DO;
+	int i;
 
 	if (!buf)
 		return count;
 	if (0 == count)
 		return count;
 
-	if (kstrtouint(buf, 16, &s->DO) != 0) {
+	if (kstrtouint(buf, 16, &DO) != 0) {
 		dev_err(dev, "bad input\n");
 		return count;
 	}
 
+	for (i = 4; i > s->DO_len; i--)
+		if (b[i - 1] != 0) {
+			dev_err(dev, "bad input\n");
+			return count;
+		}
+
+	s->DO = DO;
 	lp8x4x_slot_set_DO(s);
 
 	return count;
@@ -156,6 +214,14 @@ static struct attribute *do_slot_dev_attrs[] = {
 };
 ATTRIBUTE_GROUPS(do_slot_dev);
 
+static struct attribute *dio_slot_dev_attrs[] = {
+	&dev_attr_model.attr,
+	&dev_attr_output_status.attr,
+	&dev_attr_input_status.attr,
+	NULL,
+};
+ATTRIBUTE_GROUPS(dio_slot_dev);
+
 static void lp8x4x_master_release(struct device *dev)
 {
 	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
@@ -321,6 +387,12 @@ static void __init lp8x4x_bus_probe_slot(struct lp8x4x_master *m, int i,
 		lp8x4x_slot_set_DO(s);
 		s->dev.groups = do_slot_dev_groups;
 		break;
+	case 42:
+		s->DI_len = 2;
+		s->DO_len = 2;
+		lp8x4x_slot_set_DO(s);
+		s->dev.groups = dio_slot_dev_groups;
+		break;
 	default:
 		s->dev.groups = slot_dev_groups;
 		break;
-- 
1.8.4.2

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

* [PATCH v4 21/21] misc: support for I-8024 in LP-8x4x
  2014-04-16 17:17                 ` Sergei Ianovich
@ 2014-04-16 17:17                   ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2014-04-16 17:17 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Sergei Ianovich, Randy Dunlap, Arnd Bergmann, Greg Kroah-Hartman,
	open list:DOCUMENTATION

Status of I-8042 4 analog output channels can be managed via
sysfs.

http://www.icpdas.com/root/product/solutions/remote_io/rs-485/i-8k_i-87k/i-8024w.html

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
   v3..v4
   * no changes

   v2..v3
   * use usleep_range instead of custom nsleep
   * number change (16/16 -> 21/21)

   v0..v2
   * no changes

 Documentation/misc-devices/lp8x4x_bus.txt | 15 ++++++
 drivers/misc/lp8x4x_bus.c                 | 78 +++++++++++++++++++++++++++++++
 2 files changed, 93 insertions(+)

diff --git a/Documentation/misc-devices/lp8x4x_bus.txt b/Documentation/misc-devices/lp8x4x_bus.txt
index 3ea257d..6076e01 100644
--- a/Documentation/misc-devices/lp8x4x_bus.txt
+++ b/Documentation/misc-devices/lp8x4x_bus.txt
@@ -66,3 +66,18 @@ input_status
 output_status
 	RW - set status of digital output channels on the module in
 	     the expansion slot. Value can be read back.
+
+analog_output
+	RW - set status of analog output channels on the module in
+	     the expansion slot. Tested with voltage output. Bits 0-13:
+	     0x00c0 is -10.0V
+	     0x2000 is   0.0V
+	     0x3f40 is +10.0V
+
+	     So 1 unit of output is 1.25 mV.
+
+	     Bits 15 and 14 determine which channel to apply the value:
+	     0x0000 is channel 1
+	     0x4000 is channel 2
+	     0x8000 is channel 3
+	     0xc000 is channel 4
diff --git a/drivers/misc/lp8x4x_bus.c b/drivers/misc/lp8x4x_bus.c
index 3fb227d..72cd0b2 100644
--- a/drivers/misc/lp8x4x_bus.c
+++ b/drivers/misc/lp8x4x_bus.c
@@ -8,6 +8,7 @@
  *  it under the terms of the GNU General Public License version 2 as
  *  published by the Free Software Foundation or any later version.
  */
+#include <linux/delay.h>
 #include <linux/err.h>
 #include <linux/gpio/consumer.h>
 #include <linux/init.h>
@@ -23,6 +24,7 @@ MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Sergei Ianovich <ynvich@gmail.com>");
 MODULE_DESCRIPTION("ICP DAS LP-8x4x parallel bus driver");
 
+#define LP8X4X_MAX_AO_CHANNELS	4
 struct lp8x4x_slot {
 	void			*data_addr;
 	unsigned int		model;
@@ -31,6 +33,8 @@ struct lp8x4x_slot {
 	u32			DO;
 	unsigned int		DI_len;
 	u32			DI;
+	unsigned int		AO_len;
+	u32			AO[LP8X4X_MAX_AO_CHANNELS];
 	struct device		dev;
 };
 
@@ -120,6 +124,26 @@ static void lp8x4x_slot_set_DO(struct lp8x4x_slot *s)
 	mutex_unlock(&s->lock);
 }
 
+static void lp8x4x_slot_reset_AO(struct lp8x4x_slot *s)
+{
+	int i;
+	mutex_lock(&s->lock);
+	for (i = 0; i < s->AO_len; i++)
+		s->AO[i] = 0x2000;
+	iowrite8(0x00, s->data_addr);
+	usleep_range(1, 2);
+	iowrite8(0xff, s->data_addr);
+	mutex_unlock(&s->lock);
+}
+
+static void lp8x4x_slot_set_AO(struct lp8x4x_slot *s, u32 val)
+{
+	mutex_lock(&s->lock);
+	iowrite8(val & 0xff, s->data_addr + 2);
+	iowrite8((val >> 8) & 0xff, s->data_addr + 4);
+	mutex_unlock(&s->lock);
+}
+
 static ssize_t input_status_show(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
@@ -191,6 +215,48 @@ static ssize_t output_status_store(struct device *dev,
 
 static DEVICE_ATTR_RW(output_status);
 
+static ssize_t analog_output_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct lp8x4x_slot *s = container_of(dev, struct lp8x4x_slot, dev);
+	int i, c = 0;
+
+	for (i = 0; i < s->AO_len; i++)
+		c += sprintf(&buf[c], "0x%04x\n", s->AO[i]);
+	return c;
+}
+
+static ssize_t analog_output_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct lp8x4x_slot *s = container_of(dev, struct lp8x4x_slot, dev);
+	u32 AO;
+	int i;
+
+	if (!buf)
+		return count;
+	if (0 == count)
+		return count;
+
+	if (kstrtouint(buf, 16, &AO) != 0) {
+		dev_err(dev, "bad input\n");
+		return count;
+	}
+
+	if (AO & 0xffff0000) {
+		dev_err(dev, "bad input\n");
+		return count;
+	}
+
+	i = AO >> 14;
+	s->AO[i] = AO & 0x3fff;
+	lp8x4x_slot_set_AO(s, AO);
+
+	return count;
+}
+
+static DEVICE_ATTR_RW(analog_output);
+
 static ssize_t model_show(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
@@ -222,6 +288,13 @@ static struct attribute *dio_slot_dev_attrs[] = {
 };
 ATTRIBUTE_GROUPS(dio_slot_dev);
 
+static struct attribute *ao_slot_dev_attrs[] = {
+	&dev_attr_model.attr,
+	&dev_attr_analog_output.attr,
+	NULL,
+};
+ATTRIBUTE_GROUPS(ao_slot_dev);
+
 static void lp8x4x_master_release(struct device *dev)
 {
 	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
@@ -382,6 +455,11 @@ static void __init lp8x4x_bus_probe_slot(struct lp8x4x_master *m, int i,
 	mutex_init(&s->lock);
 
 	switch (model) {
+	case 24:
+		s->AO_len = 4;
+		lp8x4x_slot_reset_AO(s);
+		s->dev.groups = ao_slot_dev_groups;
+		break;
 	case 41:
 		s->DO_len = 4;
 		lp8x4x_slot_set_DO(s);
-- 
1.8.4.2


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

* [PATCH v4 21/21] misc: support for I-8024 in LP-8x4x
@ 2014-04-16 17:17                   ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2014-04-16 17:17 UTC (permalink / raw)
  To: linux-arm-kernel

Status of I-8042 4 analog output channels can be managed via
sysfs.

http://www.icpdas.com/root/product/solutions/remote_io/rs-485/i-8k_i-87k/i-8024w.html

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
---
   v3..v4
   * no changes

   v2..v3
   * use usleep_range instead of custom nsleep
   * number change (16/16 -> 21/21)

   v0..v2
   * no changes

 Documentation/misc-devices/lp8x4x_bus.txt | 15 ++++++
 drivers/misc/lp8x4x_bus.c                 | 78 +++++++++++++++++++++++++++++++
 2 files changed, 93 insertions(+)

diff --git a/Documentation/misc-devices/lp8x4x_bus.txt b/Documentation/misc-devices/lp8x4x_bus.txt
index 3ea257d..6076e01 100644
--- a/Documentation/misc-devices/lp8x4x_bus.txt
+++ b/Documentation/misc-devices/lp8x4x_bus.txt
@@ -66,3 +66,18 @@ input_status
 output_status
 	RW - set status of digital output channels on the module in
 	     the expansion slot. Value can be read back.
+
+analog_output
+	RW - set status of analog output channels on the module in
+	     the expansion slot. Tested with voltage output. Bits 0-13:
+	     0x00c0 is -10.0V
+	     0x2000 is   0.0V
+	     0x3f40 is +10.0V
+
+	     So 1 unit of output is 1.25 mV.
+
+	     Bits 15 and 14 determine which channel to apply the value:
+	     0x0000 is channel 1
+	     0x4000 is channel 2
+	     0x8000 is channel 3
+	     0xc000 is channel 4
diff --git a/drivers/misc/lp8x4x_bus.c b/drivers/misc/lp8x4x_bus.c
index 3fb227d..72cd0b2 100644
--- a/drivers/misc/lp8x4x_bus.c
+++ b/drivers/misc/lp8x4x_bus.c
@@ -8,6 +8,7 @@
  *  it under the terms of the GNU General Public License version 2 as
  *  published by the Free Software Foundation or any later version.
  */
+#include <linux/delay.h>
 #include <linux/err.h>
 #include <linux/gpio/consumer.h>
 #include <linux/init.h>
@@ -23,6 +24,7 @@ MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Sergei Ianovich <ynvich@gmail.com>");
 MODULE_DESCRIPTION("ICP DAS LP-8x4x parallel bus driver");
 
+#define LP8X4X_MAX_AO_CHANNELS	4
 struct lp8x4x_slot {
 	void			*data_addr;
 	unsigned int		model;
@@ -31,6 +33,8 @@ struct lp8x4x_slot {
 	u32			DO;
 	unsigned int		DI_len;
 	u32			DI;
+	unsigned int		AO_len;
+	u32			AO[LP8X4X_MAX_AO_CHANNELS];
 	struct device		dev;
 };
 
@@ -120,6 +124,26 @@ static void lp8x4x_slot_set_DO(struct lp8x4x_slot *s)
 	mutex_unlock(&s->lock);
 }
 
+static void lp8x4x_slot_reset_AO(struct lp8x4x_slot *s)
+{
+	int i;
+	mutex_lock(&s->lock);
+	for (i = 0; i < s->AO_len; i++)
+		s->AO[i] = 0x2000;
+	iowrite8(0x00, s->data_addr);
+	usleep_range(1, 2);
+	iowrite8(0xff, s->data_addr);
+	mutex_unlock(&s->lock);
+}
+
+static void lp8x4x_slot_set_AO(struct lp8x4x_slot *s, u32 val)
+{
+	mutex_lock(&s->lock);
+	iowrite8(val & 0xff, s->data_addr + 2);
+	iowrite8((val >> 8) & 0xff, s->data_addr + 4);
+	mutex_unlock(&s->lock);
+}
+
 static ssize_t input_status_show(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
@@ -191,6 +215,48 @@ static ssize_t output_status_store(struct device *dev,
 
 static DEVICE_ATTR_RW(output_status);
 
+static ssize_t analog_output_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct lp8x4x_slot *s = container_of(dev, struct lp8x4x_slot, dev);
+	int i, c = 0;
+
+	for (i = 0; i < s->AO_len; i++)
+		c += sprintf(&buf[c], "0x%04x\n", s->AO[i]);
+	return c;
+}
+
+static ssize_t analog_output_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct lp8x4x_slot *s = container_of(dev, struct lp8x4x_slot, dev);
+	u32 AO;
+	int i;
+
+	if (!buf)
+		return count;
+	if (0 == count)
+		return count;
+
+	if (kstrtouint(buf, 16, &AO) != 0) {
+		dev_err(dev, "bad input\n");
+		return count;
+	}
+
+	if (AO & 0xffff0000) {
+		dev_err(dev, "bad input\n");
+		return count;
+	}
+
+	i = AO >> 14;
+	s->AO[i] = AO & 0x3fff;
+	lp8x4x_slot_set_AO(s, AO);
+
+	return count;
+}
+
+static DEVICE_ATTR_RW(analog_output);
+
 static ssize_t model_show(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
@@ -222,6 +288,13 @@ static struct attribute *dio_slot_dev_attrs[] = {
 };
 ATTRIBUTE_GROUPS(dio_slot_dev);
 
+static struct attribute *ao_slot_dev_attrs[] = {
+	&dev_attr_model.attr,
+	&dev_attr_analog_output.attr,
+	NULL,
+};
+ATTRIBUTE_GROUPS(ao_slot_dev);
+
 static void lp8x4x_master_release(struct device *dev)
 {
 	struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
@@ -382,6 +455,11 @@ static void __init lp8x4x_bus_probe_slot(struct lp8x4x_master *m, int i,
 	mutex_init(&s->lock);
 
 	switch (model) {
+	case 24:
+		s->AO_len = 4;
+		lp8x4x_slot_reset_AO(s);
+		s->dev.groups = ao_slot_dev_groups;
+		break;
 	case 41:
 		s->DO_len = 4;
 		lp8x4x_slot_set_DO(s);
-- 
1.8.4.2

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

* Re: [PATCH v4 00/21] ARM: support for ICP DAS LP-8x4x (with dts)
  2014-04-16 17:13             ` Sergei Ianovich
@ 2014-04-16 17:39               ` Daniel Mack
  -1 siblings, 0 replies; 700+ messages in thread
From: Daniel Mack @ 2014-04-16 17:39 UTC (permalink / raw)
  To: Sergei Ianovich, linux-kernel, linux-arm-kernel
  Cc: Arnd Bergmann, Haojian Zhuang

Hi,

On 04/16/2014 07:13 PM, Sergei Ianovich wrote:
> We had an intensive discussion of the series in the beginning of
> December 2013 [1]. The discussion resulted in 3 versions of the series
> in less than 3 weeks. Then there was a decision to block this series
> until Daniel Mack's DMA-engine-for-PXA series is ready.

For whatever reason, I only received patches 1-8 out of 21 in this series.

> Unfortunately Daniel neigther agrees to review my trivial temporary
> solution to the DMA-in-device-tree (patch 7 of 21), nor he is active
> in DMA series development. There is no progress for 3 months.

Well, IIRC, I asked you to look into the MMC performance regressions
that you reported and see what we can do about them. I currently don't
have hardware to reproduce this, so I can't do it myself.

My impression is that the transisiton will only be painless if the
mmp_pdma driver provides comparable performance to the existing
implementation. I also still think that adding hacks to the drivers to
manually parse the dma properties (as in #8) brings us further away from
a proper solution, not closer.

> As with any big out of tree series, its support is painful. It requires
> extensive merging when doing bisects, on each step.

I know that, and I'm not violently against getting your patches in. I
was just hoping for some help around here in order to sort out things
and implement it properly. The reason why I haven't been working on
these drivers lately is simply the sheer lack of time :(


Thanks,
Daniel


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

* [PATCH v4 00/21] ARM: support for ICP DAS LP-8x4x (with dts)
@ 2014-04-16 17:39               ` Daniel Mack
  0 siblings, 0 replies; 700+ messages in thread
From: Daniel Mack @ 2014-04-16 17:39 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

On 04/16/2014 07:13 PM, Sergei Ianovich wrote:
> We had an intensive discussion of the series in the beginning of
> December 2013 [1]. The discussion resulted in 3 versions of the series
> in less than 3 weeks. Then there was a decision to block this series
> until Daniel Mack's DMA-engine-for-PXA series is ready.

For whatever reason, I only received patches 1-8 out of 21 in this series.

> Unfortunately Daniel neigther agrees to review my trivial temporary
> solution to the DMA-in-device-tree (patch 7 of 21), nor he is active
> in DMA series development. There is no progress for 3 months.

Well, IIRC, I asked you to look into the MMC performance regressions
that you reported and see what we can do about them. I currently don't
have hardware to reproduce this, so I can't do it myself.

My impression is that the transisiton will only be painless if the
mmp_pdma driver provides comparable performance to the existing
implementation. I also still think that adding hacks to the drivers to
manually parse the dma properties (as in #8) brings us further away from
a proper solution, not closer.

> As with any big out of tree series, its support is painful. It requires
> extensive merging when doing bisects, on each step.

I know that, and I'm not violently against getting your patches in. I
was just hoping for some help around here in order to sort out things
and implement it properly. The reason why I haven't been working on
these drivers lately is simply the sheer lack of time :(


Thanks,
Daniel

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

* Re: [PATCH v4 12/21] serial: support for 16550A serial ports on LP-8x4x
  2014-04-16 17:17                   ` Sergei Ianovich
  (?)
@ 2014-04-16 18:35                     ` One Thousand Gnomes
  -1 siblings, 0 replies; 700+ messages in thread
From: One Thousand Gnomes @ 2014-04-16 18:35 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: linux-kernel, linux-arm-kernel, Rob Herring, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala, Randy Dunlap,
	Russell King, Greg Kroah-Hartman, Jiri Slaby, Grant Likely,
	Heikki Krogerus, Arnd Bergmann, Paul Bolle, Stefan Seyfried,
	James Cameron, open list:OPEN FIRMWARE AND...,
	open list:DOCUMENTATION, open list:SERIAL DRIVERS

> +	baud = uart_get_baud_rate(port, termios, old,
> +				  port->uartclk / 16 / 0xffff,
> +				  port->uartclk / 16);
> +	switch (baud) {
> +	case 2400:
> +		len |= 1;
> +		break;
> +	case 4800:
> +		len |= 2;
> +		break;
> +	case 19200:
> +		len |= 4;
> +		break;
> +	case 38400:
> +		len |= 5;
> +		break;
> +	case 57600:
> +		len |= 6;
> +		break;
> +	case 115200:
> +		len |= 7;
> +		break;
> +	case 9600:
> +	default:
> +		len |= 3;
> +		break;
> +	};

Some explanation of this would be useful - eg why is it set to 7 for
115200 baud and 3 for 115201 baud ?

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

* Re: [PATCH v4 12/21] serial: support for 16550A serial ports on LP-8x4x
@ 2014-04-16 18:35                     ` One Thousand Gnomes
  0 siblings, 0 replies; 700+ messages in thread
From: One Thousand Gnomes @ 2014-04-16 18:35 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: linux-kernel, linux-arm-kernel, Rob Herring, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala, Randy Dunlap,
	Russell King, Greg Kroah-Hartman, Jiri Slaby, Grant Likely,
	Heikki Krogerus, Arnd Bergmann, Paul Bolle, Stefan Seyfried,
	James Cameron, open list:OPEN FIRMWARE AND...,
	open list:DOCUMENTATION, open list:SERIAL DRIVERS

> +	baud = uart_get_baud_rate(port, termios, old,
> +				  port->uartclk / 16 / 0xffff,
> +				  port->uartclk / 16);
> +	switch (baud) {
> +	case 2400:
> +		len |= 1;
> +		break;
> +	case 4800:
> +		len |= 2;
> +		break;
> +	case 19200:
> +		len |= 4;
> +		break;
> +	case 38400:
> +		len |= 5;
> +		break;
> +	case 57600:
> +		len |= 6;
> +		break;
> +	case 115200:
> +		len |= 7;
> +		break;
> +	case 9600:
> +	default:
> +		len |= 3;
> +		break;
> +	};

Some explanation of this would be useful - eg why is it set to 7 for
115200 baud and 3 for 115201 baud ?

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

* [PATCH v4 12/21] serial: support for 16550A serial ports on LP-8x4x
@ 2014-04-16 18:35                     ` One Thousand Gnomes
  0 siblings, 0 replies; 700+ messages in thread
From: One Thousand Gnomes @ 2014-04-16 18:35 UTC (permalink / raw)
  To: linux-arm-kernel

> +	baud = uart_get_baud_rate(port, termios, old,
> +				  port->uartclk / 16 / 0xffff,
> +				  port->uartclk / 16);
> +	switch (baud) {
> +	case 2400:
> +		len |= 1;
> +		break;
> +	case 4800:
> +		len |= 2;
> +		break;
> +	case 19200:
> +		len |= 4;
> +		break;
> +	case 38400:
> +		len |= 5;
> +		break;
> +	case 57600:
> +		len |= 6;
> +		break;
> +	case 115200:
> +		len |= 7;
> +		break;
> +	case 9600:
> +	default:
> +		len |= 3;
> +		break;
> +	};

Some explanation of this would be useful - eg why is it set to 7 for
115200 baud and 3 for 115201 baud ?

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

* Re: [PATCH v4 21/21] misc: support for I-8024 in LP-8x4x
  2014-04-16 17:17                   ` Sergei Ianovich
@ 2014-04-16 18:39                     ` One Thousand Gnomes
  -1 siblings, 0 replies; 700+ messages in thread
From: One Thousand Gnomes @ 2014-04-16 18:39 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: linux-kernel, linux-arm-kernel, Randy Dunlap, Arnd Bergmann,
	Greg Kroah-Hartman, linux-doc

On Wed, 16 Apr 2014 21:17:26 +0400
Sergei Ianovich <ynvich@gmail.com> wrote:

> Status of I-8042 4 analog output channels can be managed via
> sysfs.

Surely this is an iio interface and should follow the same API as
everyone else ?

Alan

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

* [PATCH v4 21/21] misc: support for I-8024 in LP-8x4x
@ 2014-04-16 18:39                     ` One Thousand Gnomes
  0 siblings, 0 replies; 700+ messages in thread
From: One Thousand Gnomes @ 2014-04-16 18:39 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, 16 Apr 2014 21:17:26 +0400
Sergei Ianovich <ynvich@gmail.com> wrote:

> Status of I-8042 4 analog output channels can be managed via
> sysfs.

Surely this is an iio interface and should follow the same API as
everyone else ?

Alan

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

* Re: [PATCH v4 13/21] misc: support for LP-8x4x custom parallel bus
  2014-04-16 17:17                   ` Sergei Ianovich
  (?)
@ 2014-04-16 18:41                     ` One Thousand Gnomes
  -1 siblings, 0 replies; 700+ messages in thread
From: One Thousand Gnomes @ 2014-04-16 18:41 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: linux-kernel, linux-arm-kernel, Rob Herring, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala, Randy Dunlap,
	Russell King, Arnd Bergmann, Greg Kroah-Hartman, Grant Likely,
	Heikki Krogerus, open list:OPEN FIRMWARE AND...,
	open list:DOCUMENTATION

On Wed, 16 Apr 2014 21:17:18 +0400
Sergei Ianovich <ynvich@gmail.com> wrote:

> This patch implements probing for the bus and reporting the number
> of available expansion slots.

This appears to be a bus not a misc device. I don't think it belongs in
misc. As you've got devices on this bus (or nailed into the 'bus' driver)
perhaps this belongs as drivers/platform/lp8x4x or similar with any
specific drivers split out - or even drivers/lp8x4x if there will be more
of them and more than one platform using it ?

Alan

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

* Re: [PATCH v4 13/21] misc: support for LP-8x4x custom parallel bus
@ 2014-04-16 18:41                     ` One Thousand Gnomes
  0 siblings, 0 replies; 700+ messages in thread
From: One Thousand Gnomes @ 2014-04-16 18:41 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: linux-kernel, linux-arm-kernel, Rob Herring, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala, Randy Dunlap,
	Russell King, Arnd Bergmann, Greg Kroah-Hartman, Grant Likely,
	Heikki Krogerus, open list:OPEN FIRMWARE AND...,
	open list:DOCUMENTATION

On Wed, 16 Apr 2014 21:17:18 +0400
Sergei Ianovich <ynvich@gmail.com> wrote:

> This patch implements probing for the bus and reporting the number
> of available expansion slots.

This appears to be a bus not a misc device. I don't think it belongs in
misc. As you've got devices on this bus (or nailed into the 'bus' driver)
perhaps this belongs as drivers/platform/lp8x4x or similar with any
specific drivers split out - or even drivers/lp8x4x if there will be more
of them and more than one platform using it ?

Alan

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

* [PATCH v4 13/21] misc: support for LP-8x4x custom parallel bus
@ 2014-04-16 18:41                     ` One Thousand Gnomes
  0 siblings, 0 replies; 700+ messages in thread
From: One Thousand Gnomes @ 2014-04-16 18:41 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, 16 Apr 2014 21:17:18 +0400
Sergei Ianovich <ynvich@gmail.com> wrote:

> This patch implements probing for the bus and reporting the number
> of available expansion slots.

This appears to be a bus not a misc device. I don't think it belongs in
misc. As you've got devices on this bus (or nailed into the 'bus' driver)
perhaps this belongs as drivers/platform/lp8x4x or similar with any
specific drivers split out - or even drivers/lp8x4x if there will be more
of them and more than one platform using it ?

Alan

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

* Re: [PATCH v4 13/21] misc: support for LP-8x4x custom parallel bus
  2014-04-16 18:41                     ` One Thousand Gnomes
@ 2014-04-16 18:42                       ` Arnd Bergmann
  -1 siblings, 0 replies; 700+ messages in thread
From: Arnd Bergmann @ 2014-04-16 18:42 UTC (permalink / raw)
  To: One Thousand Gnomes
  Cc: Sergei Ianovich, linux-kernel, linux-arm-kernel, Rob Herring,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala, Randy Dunlap,
	Russell King, Greg Kroah-Hartman, Grant Likely, Heikki Krogerus,
	open list:OPEN FIRMWARE AND...,
	open list:DOCUMENTATION

On Wednesday 16 April 2014 19:41:09 One Thousand Gnomes wrote:
> On Wed, 16 Apr 2014 21:17:18 +0400
> Sergei Ianovich <ynvich@gmail.com> wrote:
> 
> > This patch implements probing for the bus and reporting the number
> > of available expansion slots.
> 
> This appears to be a bus not a misc device. I don't think it belongs in
> misc. As you've got devices on this bus (or nailed into the 'bus' driver)
> perhaps this belongs as drivers/platform/lp8x4x or similar with any
> specific drivers split out - or even drivers/lp8x4x if there will be more
> of them and more than one platform using it ?

We have drivers/bus now, I think it could fit well in there.

	Arnd

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

* [PATCH v4 13/21] misc: support for LP-8x4x custom parallel bus
@ 2014-04-16 18:42                       ` Arnd Bergmann
  0 siblings, 0 replies; 700+ messages in thread
From: Arnd Bergmann @ 2014-04-16 18:42 UTC (permalink / raw)
  To: linux-arm-kernel

On Wednesday 16 April 2014 19:41:09 One Thousand Gnomes wrote:
> On Wed, 16 Apr 2014 21:17:18 +0400
> Sergei Ianovich <ynvich@gmail.com> wrote:
> 
> > This patch implements probing for the bus and reporting the number
> > of available expansion slots.
> 
> This appears to be a bus not a misc device. I don't think it belongs in
> misc. As you've got devices on this bus (or nailed into the 'bus' driver)
> perhaps this belongs as drivers/platform/lp8x4x or similar with any
> specific drivers split out - or even drivers/lp8x4x if there will be more
> of them and more than one platform using it ?

We have drivers/bus now, I think it could fit well in there.

	Arnd

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

* Re: [PATCH v4 12/21] serial: support for 16550A serial ports on LP-8x4x
  2014-04-16 18:35                     ` One Thousand Gnomes
@ 2014-04-16 19:01                       ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2014-04-16 19:01 UTC (permalink / raw)
  To: One Thousand Gnomes
  Cc: linux-kernel, linux-arm-kernel, Rob Herring, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala, Randy Dunlap,
	Russell King, Greg Kroah-Hartman, Jiri Slaby, Grant Likely,
	Heikki Krogerus, Arnd Bergmann, Paul Bolle, Stefan Seyfried,
	James Cameron, devicetree, linux-doc, linux-serial

One Thousand Gnomes <gnomes@lxorguk.ukuu.org.uk> wrote:
>> +	baud = uart_get_baud_rate(port, termios, old,
>> +				  port->uartclk / 16 / 0xffff,
>> +				  port->uartclk / 16);
>> +	switch (baud) {
>> +	case 2400:
>> +		len |= 1;
>> +		break;
>> +	case 4800:
>> +		len |= 2;
>> +		break;
>> +	case 19200:
>> +		len |= 4;
>> +		break;
>> +	case 38400:
>> +		len |= 5;
>> +		break;
>> +	case 57600:
>> +		len |= 6;
>> +		break;
>> +	case 115200:
>> +		len |= 7;
>> +		break;
>> +	case 9600:
>> +	default:
>> +		len |= 3;
>> +		break;
>> +	};
>
>Some explanation of this would be useful - eg why is it set to 7 for
>115200 baud and 3 for 115201 baud ?

I am not related to the device vendor in any way, so please take my answers for what they are worth.

It seems that there is not enough pins to properly connect the chips to the memory bus and just you the standard 8250 UART driver. Instead, clock divisor is set using this register.

So, if you know you're asking for (115200) you get it. If you don't or guess (115201), you get the default 9600.

This is a policy, it may not be the right way to write a driver, but it is cheap and it works.


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

* [PATCH v4 12/21] serial: support for 16550A serial ports on LP-8x4x
@ 2014-04-16 19:01                       ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2014-04-16 19:01 UTC (permalink / raw)
  To: linux-arm-kernel

One Thousand Gnomes <gnomes@lxorguk.ukuu.org.uk> wrote:
>> +	baud = uart_get_baud_rate(port, termios, old,
>> +				  port->uartclk / 16 / 0xffff,
>> +				  port->uartclk / 16);
>> +	switch (baud) {
>> +	case 2400:
>> +		len |= 1;
>> +		break;
>> +	case 4800:
>> +		len |= 2;
>> +		break;
>> +	case 19200:
>> +		len |= 4;
>> +		break;
>> +	case 38400:
>> +		len |= 5;
>> +		break;
>> +	case 57600:
>> +		len |= 6;
>> +		break;
>> +	case 115200:
>> +		len |= 7;
>> +		break;
>> +	case 9600:
>> +	default:
>> +		len |= 3;
>> +		break;
>> +	};
>
>Some explanation of this would be useful - eg why is it set to 7 for
>115200 baud and 3 for 115201 baud ?

I am not related to the device vendor in any way, so please take my answers for what they are worth.

It seems that there is not enough pins to properly connect the chips to the memory bus and just you the standard 8250 UART driver. Instead, clock divisor is set using this register.

So, if you know you're asking for (115200) you get it. If you don't or guess (115201), you get the default 9600.

This is a policy, it may not be the right way to write a driver, but it is cheap and it works.

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

* Re: [PATCH v4 21/21] misc: support for I-8024 in LP-8x4x
  2014-04-16 18:39                     ` One Thousand Gnomes
@ 2014-04-16 19:28                       ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2014-04-16 19:28 UTC (permalink / raw)
  To: One Thousand Gnomes
  Cc: linux-kernel, linux-arm-kernel, Randy Dunlap, Arnd Bergmann,
	Greg Kroah-Hartman, linux-doc

One Thousand Gnomes <gnomes@lxorguk.ukuu.org.uk> wrote:
>On Wed, 16 Apr 2014 21:17:26 +0400
>Sergei Ianovich <ynvich@gmail.com> wrote:
>
>> Status of I-8042 4 analog output channels can be managed via
>> sysfs.
>
>Surely this is an iio interface and should follow the same API as
>everyone else ?

Thanks for the feedback. It's the first response to this particular driver ever.

I've looked around the tree and found tons of industrial io device drivers in different places: drivers/iio, drivers/misc, drivers/staging/comedi to name a few.

I've closely examined a dozen or two of drivers, but of them was close enough for I-8024 in terms of speed. Its channel takes 0.1 us to set up from kernel. Real user space programs can setup all for channels in 1 us with interface provided by this patch. That's said I don't have data on time that it takes for output to stabilize at the desired levels.

I've chosen drivers/misc as a location that looked to provide the shortest path for my driver to land. The driver needs support for the bus, and here it can be in one driver.

It would be great to have some more detailed input on this issue.



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

* [PATCH v4 21/21] misc: support for I-8024 in LP-8x4x
@ 2014-04-16 19:28                       ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2014-04-16 19:28 UTC (permalink / raw)
  To: linux-arm-kernel

One Thousand Gnomes <gnomes@lxorguk.ukuu.org.uk> wrote:
>On Wed, 16 Apr 2014 21:17:26 +0400
>Sergei Ianovich <ynvich@gmail.com> wrote:
>
>> Status of I-8042 4 analog output channels can be managed via
>> sysfs.
>
>Surely this is an iio interface and should follow the same API as
>everyone else ?

Thanks for the feedback. It's the first response to this particular driver ever.

I've looked around the tree and found tons of industrial io device drivers in different places: drivers/iio, drivers/misc, drivers/staging/comedi to name a few.

I've closely examined a dozen or two of drivers, but of them was close enough for I-8024 in terms of speed. Its channel takes 0.1 us to set up from kernel. Real user space programs can setup all for channels in 1 us with interface provided by this patch. That's said I don't have data on time that it takes for output to stabilize at the desired levels.

I've chosen drivers/misc as a location that looked to provide the shortest path for my driver to land. The driver needs support for the bus, and here it can be in one driver.

It would be great to have some more detailed input on this issue.

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

* Re: [PATCH v4 13/21] misc: support for LP-8x4x custom parallel bus
  2014-04-16 18:41                     ` One Thousand Gnomes
@ 2014-04-16 19:53                       ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2014-04-16 19:53 UTC (permalink / raw)
  To: One Thousand Gnomes
  Cc: linux-kernel, linux-arm-kernel, Rob Herring, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala, Randy Dunlap,
	Russell King, Arnd Bergmann, Greg Kroah-Hartman, Grant Likely,
	Heikki Krogerus, devicetree, linux-doc

One Thousand Gnomes <gnomes@lxorguk.ukuu.org.uk> wrote:
>On Wed, 16 Apr 2014 21:17:18 +0400
>Sergei Ianovich <ynvich@gmail.com> wrote:
>
>> This patch implements probing for the bus and reporting the number
>> of available expansion slots.
>
>This appears to be a bus not a misc device. I don't think it belongs in
>misc. As you've got devices on this bus (or nailed into the 'bus'
>driver)
>perhaps this belongs as drivers/platform/lp8x4x or similar with any
>specific drivers split out - or even drivers/lp8x4x if there will be
>more
>of them and more than one platform using it ?

Thanks again for responding. I don't have a clear idea about proper code organization concering this bus.

The total number of possible bus devices is quite large, around 30. Half of them would take less than 10 extra lines to get support. The rest is more complicated.

LP-8x4x has several features that would require a misc device anyway. It has a rotary switch which isn't an input device, because it produces no interrupts. The device also has a similar DIP switch. In addition, it acts as a kind of RS-485-port-to-multi-RS-232-ports logical bridge. It has a multiplexer which allows to talk to several serial modules which support a custom protocol designed for RS-485 using a RS-232 port.





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

* [PATCH v4 13/21] misc: support for LP-8x4x custom parallel bus
@ 2014-04-16 19:53                       ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2014-04-16 19:53 UTC (permalink / raw)
  To: linux-arm-kernel

One Thousand Gnomes <gnomes@lxorguk.ukuu.org.uk> wrote:
>On Wed, 16 Apr 2014 21:17:18 +0400
>Sergei Ianovich <ynvich@gmail.com> wrote:
>
>> This patch implements probing for the bus and reporting the number
>> of available expansion slots.
>
>This appears to be a bus not a misc device. I don't think it belongs in
>misc. As you've got devices on this bus (or nailed into the 'bus'
>driver)
>perhaps this belongs as drivers/platform/lp8x4x or similar with any
>specific drivers split out - or even drivers/lp8x4x if there will be
>more
>of them and more than one platform using it ?

Thanks again for responding. I don't have a clear idea about proper code organization concering this bus.

The total number of possible bus devices is quite large, around 30. Half of them would take less than 10 extra lines to get support. The rest is more complicated.

LP-8x4x has several features that would require a misc device anyway. It has a rotary switch which isn't an input device, because it produces no interrupts. The device also has a similar DIP switch. In addition, it acts as a kind of RS-485-port-to-multi-RS-232-ports logical bridge. It has a multiplexer which allows to talk to several serial modules which support a custom protocol designed for RS-485 using a RS-232 port.

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

* Re: [PATCH v4 21/21] misc: support for I-8024 in LP-8x4x
  2014-04-16 19:28                       ` Sergei Ianovich
@ 2014-04-16 19:56                         ` One Thousand Gnomes
  -1 siblings, 0 replies; 700+ messages in thread
From: One Thousand Gnomes @ 2014-04-16 19:56 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: linux-kernel, linux-arm-kernel, Randy Dunlap, Arnd Bergmann,
	Greg Kroah-Hartman, linux-doc

> I've closely examined a dozen or two of drivers, but of them was close enough for I-8024 in terms of speed. Its channel takes 0.1 us to set up from kernel. Real user space programs can setup all for channels in 1 us with interface provided by this patch. That's said I don't have data on time that it takes for output to stabilize at the desired levels.
> 
> I've chosen drivers/misc as a location that looked to provide the shortest path for my driver to land. The driver needs support for the bus, and here it can be in one driver.
> 
> It would be great to have some more detailed input on this issue.

IIO is where we are trying to standardise all the industrial control
devices. There is stuff in places like misc for historical reasons.


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

* [PATCH v4 21/21] misc: support for I-8024 in LP-8x4x
@ 2014-04-16 19:56                         ` One Thousand Gnomes
  0 siblings, 0 replies; 700+ messages in thread
From: One Thousand Gnomes @ 2014-04-16 19:56 UTC (permalink / raw)
  To: linux-arm-kernel

> I've closely examined a dozen or two of drivers, but of them was close enough for I-8024 in terms of speed. Its channel takes 0.1 us to set up from kernel. Real user space programs can setup all for channels in 1 us with interface provided by this patch. That's said I don't have data on time that it takes for output to stabilize at the desired levels.
> 
> I've chosen drivers/misc as a location that looked to provide the shortest path for my driver to land. The driver needs support for the bus, and here it can be in one driver.
> 
> It would be great to have some more detailed input on this issue.

IIO is where we are trying to standardise all the industrial control
devices. There is stuff in places like misc for historical reasons.

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

* Re: [PATCH v4 12/21] serial: support for 16550A serial ports on LP-8x4x
  2014-04-16 19:01                       ` Sergei Ianovich
@ 2014-04-16 20:00                         ` One Thousand Gnomes
  -1 siblings, 0 replies; 700+ messages in thread
From: One Thousand Gnomes @ 2014-04-16 20:00 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: linux-kernel, linux-arm-kernel, Rob Herring, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala, Randy Dunlap,
	Russell King, Greg Kroah-Hartman, Jiri Slaby, Grant Likely,
	Heikki Krogerus, Arnd Bergmann, Paul Bolle, Stefan Seyfried,
	James Cameron, devicetree, linux-doc, linux-serial

On Wed, 16 Apr 2014 23:01:47 +0400
Sergei Ianovich <ynvich@gmail.com> wrote:

> One Thousand Gnomes <gnomes@lxorguk.ukuu.org.uk> wrote:
> >> +	baud = uart_get_baud_rate(port, termios, old,
> >> +				  port->uartclk / 16 / 0xffff,
> >> +				  port->uartclk / 16);
> >> +	switch (baud) {
> >> +	case 2400:
> >> +		len |= 1;
> >> +		break;
> >> +	case 4800:
> >> +		len |= 2;
> >> +		break;
> >> +	case 19200:
> >> +		len |= 4;
> >> +		break;
> >> +	case 38400:
> >> +		len |= 5;
> >> +		break;
> >> +	case 57600:
> >> +		len |= 6;
> >> +		break;
> >> +	case 115200:
> >> +		len |= 7;
> >> +		break;
> >> +	case 9600:
> >> +	default:
> >> +		len |= 3;
> >> +		break;
> >> +	};
> >
> >Some explanation of this would be useful - eg why is it set to 7 for
> >115200 baud and 3 for 115201 baud ?
> 
> I am not related to the device vendor in any way, so please take my answers for what they are worth.
> 
> It seems that there is not enough pins to properly connect the chips to the memory bus and just you the standard 8250 UART driver. Instead, clock divisor is set using this register.
> 
> So, if you know you're asking for (115200) you get it. If you don't or guess (115201), you get the default 9600.

Thats not quite what the code actually implements though.

> This is a policy, it may not be the right way to write a driver, but it is cheap and it works.

If thats how the hardware works and only supports a few fixed rates then
fine, but for default: you need to actually update he baudrate in the
passed termios struct so that the userspace knows its request was not
matched.

Take a look how the standard 8250 termios does it.

Also looking at this and some of the other serial bits I see no
dependencies on the problematic DMA driver, so does that mean you've got
a set of pieces that can be submitted anyway while the DMA driver
discussion continues ?

Alan

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

* [PATCH v4 12/21] serial: support for 16550A serial ports on LP-8x4x
@ 2014-04-16 20:00                         ` One Thousand Gnomes
  0 siblings, 0 replies; 700+ messages in thread
From: One Thousand Gnomes @ 2014-04-16 20:00 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, 16 Apr 2014 23:01:47 +0400
Sergei Ianovich <ynvich@gmail.com> wrote:

> One Thousand Gnomes <gnomes@lxorguk.ukuu.org.uk> wrote:
> >> +	baud = uart_get_baud_rate(port, termios, old,
> >> +				  port->uartclk / 16 / 0xffff,
> >> +				  port->uartclk / 16);
> >> +	switch (baud) {
> >> +	case 2400:
> >> +		len |= 1;
> >> +		break;
> >> +	case 4800:
> >> +		len |= 2;
> >> +		break;
> >> +	case 19200:
> >> +		len |= 4;
> >> +		break;
> >> +	case 38400:
> >> +		len |= 5;
> >> +		break;
> >> +	case 57600:
> >> +		len |= 6;
> >> +		break;
> >> +	case 115200:
> >> +		len |= 7;
> >> +		break;
> >> +	case 9600:
> >> +	default:
> >> +		len |= 3;
> >> +		break;
> >> +	};
> >
> >Some explanation of this would be useful - eg why is it set to 7 for
> >115200 baud and 3 for 115201 baud ?
> 
> I am not related to the device vendor in any way, so please take my answers for what they are worth.
> 
> It seems that there is not enough pins to properly connect the chips to the memory bus and just you the standard 8250 UART driver. Instead, clock divisor is set using this register.
> 
> So, if you know you're asking for (115200) you get it. If you don't or guess (115201), you get the default 9600.

Thats not quite what the code actually implements though.

> This is a policy, it may not be the right way to write a driver, but it is cheap and it works.

If thats how the hardware works and only supports a few fixed rates then
fine, but for default: you need to actually update he baudrate in the
passed termios struct so that the userspace knows its request was not
matched.

Take a look how the standard 8250 termios does it.

Also looking at this and some of the other serial bits I see no
dependencies on the problematic DMA driver, so does that mean you've got
a set of pieces that can be submitted anyway while the DMA driver
discussion continues ?

Alan

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

* Re: [PATCH v4 21/21] misc: support for I-8024 in LP-8x4x
  2014-04-16 19:56                         ` One Thousand Gnomes
@ 2014-04-16 20:06                           ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2014-04-16 20:06 UTC (permalink / raw)
  To: One Thousand Gnomes
  Cc: linux-kernel, linux-arm-kernel, Randy Dunlap, Arnd Bergmann,
	Greg Kroah-Hartman, linux-doc

One Thousand Gnomes <gnomes@lxorguk.ukuu.org.uk> wrote:
>> I've closely examined a dozen or two of drivers, but of them was
>close enough for I-8024 in terms of speed. Its channel takes 0.1 us to
>set up from kernel. Real user space programs can setup all for channels
>in 1 us with interface provided by this patch. That's said I don't have
>data on time that it takes for output to stabilize at the desired
>levels.
>> 
>> I've chosen drivers/misc as a location that looked to provide the
>shortest path for my driver to land. The driver needs support for the
>bus, and here it can be in one driver.
>> 
>> It would be great to have some more detailed input on this issue.
>
>IIO is where we are trying to standardise all the industrial control
>devices. There is stuff in places like misc for historical reasons.

Great. I'll rewrite the driver using IIO, but the bus issue needs to be settled first.


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

* [PATCH v4 21/21] misc: support for I-8024 in LP-8x4x
@ 2014-04-16 20:06                           ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2014-04-16 20:06 UTC (permalink / raw)
  To: linux-arm-kernel

One Thousand Gnomes <gnomes@lxorguk.ukuu.org.uk> wrote:
>> I've closely examined a dozen or two of drivers, but of them was
>close enough for I-8024 in terms of speed. Its channel takes 0.1 us to
>set up from kernel. Real user space programs can setup all for channels
>in 1 us with interface provided by this patch. That's said I don't have
>data on time that it takes for output to stabilize at the desired
>levels.
>> 
>> I've chosen drivers/misc as a location that looked to provide the
>shortest path for my driver to land. The driver needs support for the
>bus, and here it can be in one driver.
>> 
>> It would be great to have some more detailed input on this issue.
>
>IIO is where we are trying to standardise all the industrial control
>devices. There is stuff in places like misc for historical reasons.

Great. I'll rewrite the driver using IIO, but the bus issue needs to be settled first.

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

* Re: [PATCH v4 13/21] misc: support for LP-8x4x custom parallel bus
  2014-04-16 18:42                       ` Arnd Bergmann
@ 2014-04-16 20:29                         ` One Thousand Gnomes
  -1 siblings, 0 replies; 700+ messages in thread
From: One Thousand Gnomes @ 2014-04-16 20:29 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Sergei Ianovich, linux-kernel, linux-arm-kernel, Rob Herring,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala, Randy Dunlap,
	Russell King, Greg Kroah-Hartman, Grant Likely, Heikki Krogerus,
	open list:OPEN FIRMWARE AND...,
	open list:DOCUMENTATION

On Wed, 16 Apr 2014 20:42:39 +0200
Arnd Bergmann <arnd@arndb.de> wrote:

> On Wednesday 16 April 2014 19:41:09 One Thousand Gnomes wrote:
> > On Wed, 16 Apr 2014 21:17:18 +0400
> > Sergei Ianovich <ynvich@gmail.com> wrote:
> > 
> > > This patch implements probing for the bus and reporting the number
> > > of available expansion slots.
> > 
> > This appears to be a bus not a misc device. I don't think it belongs in
> > misc. As you've got devices on this bus (or nailed into the 'bus' driver)
> > perhaps this belongs as drivers/platform/lp8x4x or similar with any
> > specific drivers split out - or even drivers/lp8x4x if there will be more
> > of them and more than one platform using it ?
> 
> We have drivers/bus now, I think it could fit well in there.

Agreed

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

* [PATCH v4 13/21] misc: support for LP-8x4x custom parallel bus
@ 2014-04-16 20:29                         ` One Thousand Gnomes
  0 siblings, 0 replies; 700+ messages in thread
From: One Thousand Gnomes @ 2014-04-16 20:29 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, 16 Apr 2014 20:42:39 +0200
Arnd Bergmann <arnd@arndb.de> wrote:

> On Wednesday 16 April 2014 19:41:09 One Thousand Gnomes wrote:
> > On Wed, 16 Apr 2014 21:17:18 +0400
> > Sergei Ianovich <ynvich@gmail.com> wrote:
> > 
> > > This patch implements probing for the bus and reporting the number
> > > of available expansion slots.
> > 
> > This appears to be a bus not a misc device. I don't think it belongs in
> > misc. As you've got devices on this bus (or nailed into the 'bus' driver)
> > perhaps this belongs as drivers/platform/lp8x4x or similar with any
> > specific drivers split out - or even drivers/lp8x4x if there will be more
> > of them and more than one platform using it ?
> 
> We have drivers/bus now, I think it could fit well in there.

Agreed

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

* Re: [PATCH v4 12/21] serial: support for 16550A serial ports on LP-8x4x
@ 2014-04-16 20:32                           ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2014-04-16 20:32 UTC (permalink / raw)
  To: One Thousand Gnomes
  Cc: linux-kernel, linux-arm-kernel, Rob Herring, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala, Randy Dunlap,
	Russell King, Greg Kroah-Hartman, Jiri Slaby, Grant Likely,
	Heikki Krogerus, Arnd Bergmann, Paul Bolle, Stefan Seyfried,
	James Cameron, devicetree, linux-doc, linux-serial

One Thousand Gnomes <gnomes@lxorguk.ukuu.org.uk> wrote:
>On Wed, 16 Apr 2014 23:01:47 +0400
>Sergei Ianovich <ynvich@gmail.com> wrote:
>
>> One Thousand Gnomes <gnomes@lxorguk.ukuu.org.uk> wrote:
>> >> +	baud = uart_get_baud_rate(port, termios, old,
>> >> +				  port->uartclk / 16 / 0xffff,
>> >> +				  port->uartclk / 16);
>> >> +	switch (baud) {
>> >> +	case 2400:
>> >> +		len |= 1;
>> >> +		break;
>> >> +	case 4800:
>> >> +		len |= 2;
>> >> +		break;
>> >> +	case 19200:
>> >> +		len |= 4;
>> >> +		break;
>> >> +	case 38400:
>> >> +		len |= 5;
>> >> +		break;
>> >> +	case 57600:
>> >> +		len |= 6;
>> >> +		break;
>> >> +	case 115200:
>> >> +		len |= 7;
>> >> +		break;
>> >> +	case 9600:
>> >> +	default:
>> >> +		len |= 3;
>> >> +		break;
>> >> +	};
>> >
>> >Some explanation of this would be useful - eg why is it set to 7 for
>> >115200 baud and 3 for 115201 baud ?
>> 
>> I am not related to the device vendor in any way, so please take my
>answers for what they are worth.
>> 
>> It seems that there is not enough pins to properly connect the chips
>to the memory bus and just you the standard 8250 UART driver. Instead,
>clock divisor is set using this register.
>> 
>> So, if you know you're asking for (115200) you get it. If you don't
>or guess (115201), you get the default 9600.
>
>Thats not quite what the code actually implements though.

>> This is a policy, it may not be the right way to write a driver, but
>it is cheap and it works.

>If thats how the hardware works and only supports a few fixed rates
>then
>fine, but for default: you need to actually update he baudrate in the
>passed termios struct so that the userspace knows its request was not
>matched.
>
>Take a look how the standard 8250 termios does it.

I will. I've tested the driver by setting termios from userspace. There was no chance to ask for arbitrary rate, so I didn't think much about this case.

>Also looking at this and some of the other serial bits I see no
>dependencies on the problematic DMA driver, so does that mean you've
>got
>a set of pieces that can be submitted anyway while the DMA driver
>discussion continues ?

Yes, getting each peace in will reduce the support burden.

The degree of interdependence varies from feature to feature. rtc, mtd, irq and serial could be taken independently.

The main patch is #8. It requires #1-7. The is problem with DMA is one of policy, not technical one. It is explained in #6-7 in details.

Everything in the misc depends on bus. But the bus is very simple. There is even no interrupts.


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

* Re: [PATCH v4 12/21] serial: support for 16550A serial ports on LP-8x4x
@ 2014-04-16 20:32                           ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2014-04-16 20:32 UTC (permalink / raw)
  To: One Thousand Gnomes
  Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Rob Herring,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala, Randy Dunlap,
	Russell King, Greg Kroah-Hartman, Jiri Slaby, Grant Likely,
	Heikki Krogerus, Arnd Bergmann, Paul Bolle, Stefan Seyfried,
	James Cameron, devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA,
	linux-serial-u79uwXL29TY76Z2rM5mHXA

One Thousand Gnomes <gnomes-qBU/x9rampVanCEyBjwyrvXRex20P6io@public.gmane.org> wrote:
>On Wed, 16 Apr 2014 23:01:47 +0400
>Sergei Ianovich <ynvich-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
>
>> One Thousand Gnomes <gnomes-qBU/x9rampVanCEyBjwyrvXRex20P6io@public.gmane.org> wrote:
>> >> +	baud = uart_get_baud_rate(port, termios, old,
>> >> +				  port->uartclk / 16 / 0xffff,
>> >> +				  port->uartclk / 16);
>> >> +	switch (baud) {
>> >> +	case 2400:
>> >> +		len |= 1;
>> >> +		break;
>> >> +	case 4800:
>> >> +		len |= 2;
>> >> +		break;
>> >> +	case 19200:
>> >> +		len |= 4;
>> >> +		break;
>> >> +	case 38400:
>> >> +		len |= 5;
>> >> +		break;
>> >> +	case 57600:
>> >> +		len |= 6;
>> >> +		break;
>> >> +	case 115200:
>> >> +		len |= 7;
>> >> +		break;
>> >> +	case 9600:
>> >> +	default:
>> >> +		len |= 3;
>> >> +		break;
>> >> +	};
>> >
>> >Some explanation of this would be useful - eg why is it set to 7 for
>> >115200 baud and 3 for 115201 baud ?
>> 
>> I am not related to the device vendor in any way, so please take my
>answers for what they are worth.
>> 
>> It seems that there is not enough pins to properly connect the chips
>to the memory bus and just you the standard 8250 UART driver. Instead,
>clock divisor is set using this register.
>> 
>> So, if you know you're asking for (115200) you get it. If you don't
>or guess (115201), you get the default 9600.
>
>Thats not quite what the code actually implements though.

>> This is a policy, it may not be the right way to write a driver, but
>it is cheap and it works.

>If thats how the hardware works and only supports a few fixed rates
>then
>fine, but for default: you need to actually update he baudrate in the
>passed termios struct so that the userspace knows its request was not
>matched.
>
>Take a look how the standard 8250 termios does it.

I will. I've tested the driver by setting termios from userspace. There was no chance to ask for arbitrary rate, so I didn't think much about this case.

>Also looking at this and some of the other serial bits I see no
>dependencies on the problematic DMA driver, so does that mean you've
>got
>a set of pieces that can be submitted anyway while the DMA driver
>discussion continues ?

Yes, getting each peace in will reduce the support burden.

The degree of interdependence varies from feature to feature. rtc, mtd, irq and serial could be taken independently.

The main patch is #8. It requires #1-7. The is problem with DMA is one of policy, not technical one. It is explained in #6-7 in details.

Everything in the misc depends on bus. But the bus is very simple. There is even no interrupts.

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH v4 12/21] serial: support for 16550A serial ports on LP-8x4x
@ 2014-04-16 20:32                           ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2014-04-16 20:32 UTC (permalink / raw)
  To: linux-arm-kernel

One Thousand Gnomes <gnomes@lxorguk.ukuu.org.uk> wrote:
>On Wed, 16 Apr 2014 23:01:47 +0400
>Sergei Ianovich <ynvich@gmail.com> wrote:
>
>> One Thousand Gnomes <gnomes@lxorguk.ukuu.org.uk> wrote:
>> >> +	baud = uart_get_baud_rate(port, termios, old,
>> >> +				  port->uartclk / 16 / 0xffff,
>> >> +				  port->uartclk / 16);
>> >> +	switch (baud) {
>> >> +	case 2400:
>> >> +		len |= 1;
>> >> +		break;
>> >> +	case 4800:
>> >> +		len |= 2;
>> >> +		break;
>> >> +	case 19200:
>> >> +		len |= 4;
>> >> +		break;
>> >> +	case 38400:
>> >> +		len |= 5;
>> >> +		break;
>> >> +	case 57600:
>> >> +		len |= 6;
>> >> +		break;
>> >> +	case 115200:
>> >> +		len |= 7;
>> >> +		break;
>> >> +	case 9600:
>> >> +	default:
>> >> +		len |= 3;
>> >> +		break;
>> >> +	};
>> >
>> >Some explanation of this would be useful - eg why is it set to 7 for
>> >115200 baud and 3 for 115201 baud ?
>> 
>> I am not related to the device vendor in any way, so please take my
>answers for what they are worth.
>> 
>> It seems that there is not enough pins to properly connect the chips
>to the memory bus and just you the standard 8250 UART driver. Instead,
>clock divisor is set using this register.
>> 
>> So, if you know you're asking for (115200) you get it. If you don't
>or guess (115201), you get the default 9600.
>
>Thats not quite what the code actually implements though.

>> This is a policy, it may not be the right way to write a driver, but
>it is cheap and it works.

>If thats how the hardware works and only supports a few fixed rates
>then
>fine, but for default: you need to actually update he baudrate in the
>passed termios struct so that the userspace knows its request was not
>matched.
>
>Take a look how the standard 8250 termios does it.

I will. I've tested the driver by setting termios from userspace. There was no chance to ask for arbitrary rate, so I didn't think much about this case.

>Also looking at this and some of the other serial bits I see no
>dependencies on the problematic DMA driver, so does that mean you've
>got
>a set of pieces that can be submitted anyway while the DMA driver
>discussion continues ?

Yes, getting each peace in will reduce the support burden.

The degree of interdependence varies from feature to feature. rtc, mtd, irq and serial could be taken independently.

The main patch is #8. It requires #1-7. The is problem with DMA is one of policy, not technical one. It is explained in #6-7 in details.

Everything in the misc depends on bus. But the bus is very simple. There is even no interrupts.

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

* Re: [PATCH v4 00/21] ARM: support for ICP DAS LP-8x4x (with dts)
  2014-04-16 17:39               ` Daniel Mack
@ 2014-04-16 20:59                 ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2014-04-16 20:59 UTC (permalink / raw)
  To: Daniel Mack, linux-kernel, linux-arm-kernel; +Cc: Arnd Bergmann, Haojian Zhuang

Daniel Mack <zonque@gmail.com> wrote:
>Hi,
>
>On 04/16/2014 07:13 PM, Sergei Ianovich wrote:
>> We had an intensive discussion of the series in the beginning of
>> December 2013 [1]. The discussion resulted in 3 versions of the
>series
>> in less than 3 weeks. Then there was a decision to block this series
>> until Daniel Mack's DMA-engine-for-PXA series is ready.
>
>For whatever reason, I only received patches 1-8 out of 21 in this
>series.

The rest is related to exotic parts of the tree and 'scripts/get_maintainer.pl' decided not to spam you. The whole series is sent to both lkml and arm lists. I can add you to cc by hand if you are interested. 

>> Unfortunately Daniel neigther agrees to review my trivial temporary
>> solution to the DMA-in-device-tree (patch 7 of 21), nor he is active
>> in DMA series development. There is no progress for 3 months.
>
>Well, IIRC, I asked you to look into the MMC performance regressions
>that you reported and see what we can do about them. I currently don't
>have hardware to reproduce this, so I can't do it myself.

I hate to point fingers, but you promissed to refresh the code on several occasions. It is from 3.8 tree at the moment. The regression may be introduced by an error in my merging of your patches. I published the one I tested in one piece with the results. 

>My impression is that the transisiton will only be painless if the
>mmp_pdma driver provides comparable performance to the existing
>implementation. I also still think that adding hacks to the drivers to
>manually parse the dma properties (as in #8) brings us further away
>from
>a proper solution, not closer

No doubt about that. But the regression is not the only problem. Driver for video capture requires an extensive rewrite as well. The result is that a working pxa DT device is kept out of the tree and there is no supported DT devices in tree. So no proper examples for new devices and no drive-by improvements. All of this prevents rather than facilitates eventual DT migration of tha PXA platform.


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

* [PATCH v4 00/21] ARM: support for ICP DAS LP-8x4x (with dts)
@ 2014-04-16 20:59                 ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2014-04-16 20:59 UTC (permalink / raw)
  To: linux-arm-kernel

Daniel Mack <zonque@gmail.com> wrote:
>Hi,
>
>On 04/16/2014 07:13 PM, Sergei Ianovich wrote:
>> We had an intensive discussion of the series in the beginning of
>> December 2013 [1]. The discussion resulted in 3 versions of the
>series
>> in less than 3 weeks. Then there was a decision to block this series
>> until Daniel Mack's DMA-engine-for-PXA series is ready.
>
>For whatever reason, I only received patches 1-8 out of 21 in this
>series.

The rest is related to exotic parts of the tree and 'scripts/get_maintainer.pl' decided not to spam you. The whole series is sent to both lkml and arm lists. I can add you to cc by hand if you are interested. 

>> Unfortunately Daniel neigther agrees to review my trivial temporary
>> solution to the DMA-in-device-tree (patch 7 of 21), nor he is active
>> in DMA series development. There is no progress for 3 months.
>
>Well, IIRC, I asked you to look into the MMC performance regressions
>that you reported and see what we can do about them. I currently don't
>have hardware to reproduce this, so I can't do it myself.

I hate to point fingers, but you promissed to refresh the code on several occasions. It is from 3.8 tree at the moment. The regression may be introduced by an error in my merging of your patches. I published the one I tested in one piece with the results. 

>My impression is that the transisiton will only be painless if the
>mmp_pdma driver provides comparable performance to the existing
>implementation. I also still think that adding hacks to the drivers to
>manually parse the dma properties (as in #8) brings us further away
>from
>a proper solution, not closer

No doubt about that. But the regression is not the only problem. Driver for video capture requires an extensive rewrite as well. The result is that a working pxa DT device is kept out of the tree and there is no supported DT devices in tree. So no proper examples for new devices and no drive-by improvements. All of this prevents rather than facilitates eventual DT migration of tha PXA platform.

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

* Re: [PATCH v4 00/21] ARM: support for ICP DAS LP-8x4x (with dts)
  2014-04-16 20:59                 ` Sergei Ianovich
@ 2014-04-17 10:38                   ` Daniel Mack
  -1 siblings, 0 replies; 700+ messages in thread
From: Daniel Mack @ 2014-04-17 10:38 UTC (permalink / raw)
  To: Sergei Ianovich, linux-kernel, linux-arm-kernel
  Cc: Arnd Bergmann, Haojian Zhuang, laurent.pinchart, kernel

On 04/16/2014 10:59 PM, Sergei Ianovich wrote:
>> Well, IIRC, I asked you to look into the MMC performance
>> regressions that you reported and see what we can do about them. I
>> currently don't have hardware to reproduce this, so I can't do it
>> myself.
> 
> I hate to point fingers, but you promissed to refresh the code on
> several occasions. It is from 3.8 tree at the moment. The regression
> may be introduced by an error in my merging of your patches. I
> published the one I tested in one piece with the results.

Ok, well. I didn't see this as a potential reason, sorry. Point taken.

I spent some hours on this topic again now, and rebased and tested my
tree to 3.15-rc1. Pushed it here:

  https://github.com/zonque/linux/tree/pxa-dma-3.15

There's some overlap to the patches you sent, which I'll comment on
directly soon.

I'm booting my board with pxa[23]xx.dtsi taken from my tree.

Please, if you find some time, test this tree and see if you still see
the performance regression.

>> My impression is that the transisiton will only be painless if the 
>> mmp_pdma driver provides comparable performance to the existing 
>> implementation. I also still think that adding hacks to the drivers
>> to manually parse the dma properties (as in #8) brings us further
>> away from a proper solution, not closer
> 
> No doubt about that. But the regression is not the only problem.
> Driver for video capture requires an extensive rewrite as well.

Jup, I totally see your point. I was hoping for more support from
someone with access to hardware to work on this, and possibly add the
missing bits to the DMA framework to make the hot-linking possible. This
didn't happen, which is unfortunate, so we in fact might need to
recondider on how to move forward here.

> The
> result is that a working pxa DT device is kept out of the tree and
> there is no supported DT devices in tree. So no proper examples for
> new devices and no drive-by improvements. All of this prevents rather
> than facilitates eventual DT migration of tha PXA platform.

Ok, so how about this:

1. We keep the old API around, along with compat wrappers for existing
drivers until someone finally finds time to at least test the patches
that I can only compile-test myself.

2. For platforms that don't need those exotic drivers for devices that
nobody seems to be interested in, use DT and the pxa-mmp-dma driver, and
make sure it performs as well as the old implementation.

3. Do not add hacks for DT-compatability of existing drivers to make
them work with the old DMA implementation (like your patch #7).

4. For new drivers, don't add any compat code for the old DMA
implementation but soley rely on the new DMA framework.



Does this sound suitable for you?


Thanks,
Daniel

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

* [PATCH v4 00/21] ARM: support for ICP DAS LP-8x4x (with dts)
@ 2014-04-17 10:38                   ` Daniel Mack
  0 siblings, 0 replies; 700+ messages in thread
From: Daniel Mack @ 2014-04-17 10:38 UTC (permalink / raw)
  To: linux-arm-kernel

On 04/16/2014 10:59 PM, Sergei Ianovich wrote:
>> Well, IIRC, I asked you to look into the MMC performance
>> regressions that you reported and see what we can do about them. I
>> currently don't have hardware to reproduce this, so I can't do it
>> myself.
> 
> I hate to point fingers, but you promissed to refresh the code on
> several occasions. It is from 3.8 tree at the moment. The regression
> may be introduced by an error in my merging of your patches. I
> published the one I tested in one piece with the results.

Ok, well. I didn't see this as a potential reason, sorry. Point taken.

I spent some hours on this topic again now, and rebased and tested my
tree to 3.15-rc1. Pushed it here:

  https://github.com/zonque/linux/tree/pxa-dma-3.15

There's some overlap to the patches you sent, which I'll comment on
directly soon.

I'm booting my board with pxa[23]xx.dtsi taken from my tree.

Please, if you find some time, test this tree and see if you still see
the performance regression.

>> My impression is that the transisiton will only be painless if the 
>> mmp_pdma driver provides comparable performance to the existing 
>> implementation. I also still think that adding hacks to the drivers
>> to manually parse the dma properties (as in #8) brings us further
>> away from a proper solution, not closer
> 
> No doubt about that. But the regression is not the only problem.
> Driver for video capture requires an extensive rewrite as well.

Jup, I totally see your point. I was hoping for more support from
someone with access to hardware to work on this, and possibly add the
missing bits to the DMA framework to make the hot-linking possible. This
didn't happen, which is unfortunate, so we in fact might need to
recondider on how to move forward here.

> The
> result is that a working pxa DT device is kept out of the tree and
> there is no supported DT devices in tree. So no proper examples for
> new devices and no drive-by improvements. All of this prevents rather
> than facilitates eventual DT migration of tha PXA platform.

Ok, so how about this:

1. We keep the old API around, along with compat wrappers for existing
drivers until someone finally finds time to at least test the patches
that I can only compile-test myself.

2. For platforms that don't need those exotic drivers for devices that
nobody seems to be interested in, use DT and the pxa-mmp-dma driver, and
make sure it performs as well as the old implementation.

3. Do not add hacks for DT-compatability of existing drivers to make
them work with the old DMA implementation (like your patch #7).

4. For new drivers, don't add any compat code for the old DMA
implementation but soley rely on the new DMA framework.



Does this sound suitable for you?


Thanks,
Daniel

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

* Re: [PATCH v4 08/21] ARM: pxa27x: device tree support ICP DAS LP-8x4x
  2014-04-16 17:17                   ` Sergei Ianovich
  (?)
  (?)
@ 2014-04-17 10:54                   ` Daniel Mack
  -1 siblings, 0 replies; 700+ messages in thread
From: Daniel Mack @ 2014-04-17 10:54 UTC (permalink / raw)
  To: Sergei Ianovich, linux-kernel, linux-arm-kernel
  Cc: Arnd Bergmann, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Randy Dunlap, Russell King, Eric Miao,
	Haojian Zhuang, Thierry Reding, Florian Vaussard,
	Jonathan Cameron, Shawn Guo, Andrew Lunn, Silvio F,
	Heikki Krogerus, open list:OPEN FIRMWARE AND...,
	open, list, DOCUMENTATION

On 04/16/2014 07:17 PM, Sergei Ianovich wrote:
> diff --git a/arch/arm/mach-pxa/pxa27x-dt.c b/arch/arm/mach-pxa/pxa27x-dt.c
> new file mode 100644
> index 0000000..865cf46
> --- /dev/null
> +++ b/arch/arm/mach-pxa/pxa27x-dt.c
> @@ -0,0 +1,64 @@
> +/*
> + *  linux/arch/arm/mach-pxa/pxa27x-dt.c
> + *
> + *  Copyright (C) 2013 Sergei Ianovich
> + *
> + *  based mostly on linux/arch/arm/mach-pxa/pxa-dt.c by Daniel Mack
> + *
> + *  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
> + *  publishhed by the Free Software Foundation.
> + */
> +
> +#include <linux/irq.h>
> +#include <linux/irqdomain.h>
> +#include <linux/of_irq.h>
> +#include <linux/of_platform.h>
> +#include <asm/io.h>
> +#include <asm/mach/arch.h>
> +#include <asm/mach/time.h>
> +#include <mach/irqs.h>
> +#include <mach/pxa27x.h>
> +
> +#include "generic.h"
> +
> +#ifdef CONFIG_PXA27x
> +static const struct of_dev_auxdata pxa27x_auxdata_lookup[] __initconst = {
> +	OF_DEV_AUXDATA("mrvl,pxa-uart",	    0x40100000, "pxa2xx-uart.0", NULL),
> +	OF_DEV_AUXDATA("mrvl,pxa-uart",	    0x40200000, "pxa2xx-uart.1", NULL),
> +	OF_DEV_AUXDATA("mrvl,pxa-uart",	    0x40700000, "pxa2xx-uart.2", NULL),
> +	OF_DEV_AUXDATA("mrvl,pxa-uart",	    0x41600000, "pxa2xx-uart.3", NULL),
> +	OF_DEV_AUXDATA("marvell,pxa-mmc",   0x41100000, "pxa2xx-mci.0", NULL),
> +	OF_DEV_AUXDATA("intel,pxa27x-gpio", 0x40e00000, "pxa27x-gpio", NULL),
> +	OF_DEV_AUXDATA("marvell,pxa-ohci",  0x4c000000, "pxa27x-ohci", NULL),
> +	OF_DEV_AUXDATA("mrvl,pxa-i2c",	    0x40301680, "pxa2xx-i2c.0", NULL),
> +	{}
> +};

This patch should be split into a generic pxa27x part and one for your
platform. The former should also include the changes to pxa27x.dtsi.


Thanks,
Daniel

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

* Re: [PATCH v4 00/21] ARM: support for ICP DAS LP-8x4x (with dts)
  2014-04-17 10:38                   ` Daniel Mack
@ 2014-04-17 12:12                     ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2014-04-17 12:12 UTC (permalink / raw)
  To: Daniel Mack
  Cc: linux-kernel, linux-arm-kernel, Arnd Bergmann, Haojian Zhuang,
	laurent.pinchart, kernel

On Thu, 2014-04-17 at 12:38 +0200, Daniel Mack wrote:
> I spent some hours on this topic again now, and rebased and tested my
> tree to 3.15-rc1. Pushed it here:
> 
>   https://github.com/zonque/linux/tree/pxa-dma-3.15

Great.

> There's some overlap to the patches you sent, which I'll comment on
> directly soon.
> 
> I'm booting my board with pxa[23]xx.dtsi taken from my tree.
> 
> Please, if you find some time, test this tree and see if you still see
> the performance regression.

Sure.

> Ok, so how about this:
> 
> 1. We keep the old API around, along with compat wrappers for existing
> drivers until someone finally finds time to at least test the patches
> that I can only compile-test myself.
> 
> 2. For platforms that don't need those exotic drivers for devices that
> nobody seems to be interested in, use DT and the pxa-mmp-dma driver, and
> make sure it performs as well as the old implementation.
> 
> 3. Do not add hacks for DT-compatability of existing drivers to make
> them work with the old DMA implementation (like your patch #7).
> 
> 4. For new drivers, don't add any compat code for the old DMA
> implementation but soley rely on the new DMA framework.
> 
> 
> 
> Does this sound suitable for you?

No. I see no value in #3. There are obvious reasons to use DT whenever
possible. #3 effectively blocks DT usage for new devices. I have all the
reasons to believe, that LP-8x4x support would already have be merged,
if I didn't try to use DT.

My plan:
A. We need to know whether the new DMA implementation performs on par
with the old one. (I'm starting to check).

if so
B. We need to thinks whether it's acceptable to kill support for video
capture.

In short:

if (A && B)
  we drop old DMA
else
  we take my patch #7


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

* [PATCH v4 00/21] ARM: support for ICP DAS LP-8x4x (with dts)
@ 2014-04-17 12:12                     ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2014-04-17 12:12 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, 2014-04-17 at 12:38 +0200, Daniel Mack wrote:
> I spent some hours on this topic again now, and rebased and tested my
> tree to 3.15-rc1. Pushed it here:
> 
>   https://github.com/zonque/linux/tree/pxa-dma-3.15

Great.

> There's some overlap to the patches you sent, which I'll comment on
> directly soon.
> 
> I'm booting my board with pxa[23]xx.dtsi taken from my tree.
> 
> Please, if you find some time, test this tree and see if you still see
> the performance regression.

Sure.

> Ok, so how about this:
> 
> 1. We keep the old API around, along with compat wrappers for existing
> drivers until someone finally finds time to at least test the patches
> that I can only compile-test myself.
> 
> 2. For platforms that don't need those exotic drivers for devices that
> nobody seems to be interested in, use DT and the pxa-mmp-dma driver, and
> make sure it performs as well as the old implementation.
> 
> 3. Do not add hacks for DT-compatability of existing drivers to make
> them work with the old DMA implementation (like your patch #7).
> 
> 4. For new drivers, don't add any compat code for the old DMA
> implementation but soley rely on the new DMA framework.
> 
> 
> 
> Does this sound suitable for you?

No. I see no value in #3. There are obvious reasons to use DT whenever
possible. #3 effectively blocks DT usage for new devices. I have all the
reasons to believe, that LP-8x4x support would already have be merged,
if I didn't try to use DT.

My plan:
A. We need to know whether the new DMA implementation performs on par
with the old one. (I'm starting to check).

if so
B. We need to thinks whether it's acceptable to kill support for video
capture.

In short:

if (A && B)
  we drop old DMA
else
  we take my patch #7

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

* Re: [PATCH v4 00/21] ARM: support for ICP DAS LP-8x4x (with dts)
  2014-04-17 12:12                     ` Sergei Ianovich
@ 2014-04-17 12:34                       ` Daniel Mack
  -1 siblings, 0 replies; 700+ messages in thread
From: Daniel Mack @ 2014-04-17 12:34 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: linux-kernel, linux-arm-kernel, Arnd Bergmann, Haojian Zhuang,
	laurent.pinchart, kernel

On 04/17/2014 02:12 PM, Sergei Ianovich wrote:
> On Thu, 2014-04-17 at 12:38 +0200, Daniel Mack wrote:

>> 1. We keep the old API around, along with compat wrappers for existing
>> drivers until someone finally finds time to at least test the patches
>> that I can only compile-test myself.
>>
>> 2. For platforms that don't need those exotic drivers for devices that
>> nobody seems to be interested in, use DT and the pxa-mmp-dma driver, and
>> make sure it performs as well as the old implementation.
>>
>> 3. Do not add hacks for DT-compatability of existing drivers to make
>> them work with the old DMA implementation (like your patch #7).
>>
>> 4. For new drivers, don't add any compat code for the old DMA
>> implementation but soley rely on the new DMA framework.
>>
>> Does this sound suitable for you?
> 
> No. I see no value in #3. There are obvious reasons to use DT whenever
> possible.

Of course. But if you do, you should really use the mmp-pdma driver, and
make sure it works. That way, that driver gets more test coverage.
Please, let's *not* introduce new hacks that lead to more users of the
old DMA API instead.

> #3 effectively blocks DT usage for new devices.

No, it doesn't. It just makes sure those new boards use the new dma
implementation, and obtain their DMA runtime information from the common
APIs. After all, the problem here is the lack of users who are willing
to dig into the DMA bits of the drivers they're using. By making it a
requirement to use the new pdma driver, we can possibly change that.

> I have all the
> reasons to believe, that LP-8x4x support would already have be merged,
> if I didn't try to use DT.

That might be, but that's not the point. We want progress here, and that
means we occasionally have to get rid of legacy.

> My plan:
> A. We need to know whether the new DMA implementation performs on par
> with the old one. (I'm starting to check).

Good, thanks!

> if so
> B. We need to thinks whether it's acceptable to kill support for video
> capture.

We can't. As I said, for this particular driver, we can keep the old API
around. We can even make it depend on !CONFIG_DMA_ENGINE, so if anyone
actually wants to use it with DT-enabled boards, we finally have a user
and things can be fixed up. Similar for other drivers we can't test
ourselves.

> In short:
> 
> if (A && B)
>   we drop old DMA
> else
>   we take my patch #7

If A works, there's no need to for patch #7, right? If A doesn't work,
we have to check why and fix it.

Arnd, any oppinion on this?


Thanks,
Daniel



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

* [PATCH v4 00/21] ARM: support for ICP DAS LP-8x4x (with dts)
@ 2014-04-17 12:34                       ` Daniel Mack
  0 siblings, 0 replies; 700+ messages in thread
From: Daniel Mack @ 2014-04-17 12:34 UTC (permalink / raw)
  To: linux-arm-kernel

On 04/17/2014 02:12 PM, Sergei Ianovich wrote:
> On Thu, 2014-04-17 at 12:38 +0200, Daniel Mack wrote:

>> 1. We keep the old API around, along with compat wrappers for existing
>> drivers until someone finally finds time to at least test the patches
>> that I can only compile-test myself.
>>
>> 2. For platforms that don't need those exotic drivers for devices that
>> nobody seems to be interested in, use DT and the pxa-mmp-dma driver, and
>> make sure it performs as well as the old implementation.
>>
>> 3. Do not add hacks for DT-compatability of existing drivers to make
>> them work with the old DMA implementation (like your patch #7).
>>
>> 4. For new drivers, don't add any compat code for the old DMA
>> implementation but soley rely on the new DMA framework.
>>
>> Does this sound suitable for you?
> 
> No. I see no value in #3. There are obvious reasons to use DT whenever
> possible.

Of course. But if you do, you should really use the mmp-pdma driver, and
make sure it works. That way, that driver gets more test coverage.
Please, let's *not* introduce new hacks that lead to more users of the
old DMA API instead.

> #3 effectively blocks DT usage for new devices.

No, it doesn't. It just makes sure those new boards use the new dma
implementation, and obtain their DMA runtime information from the common
APIs. After all, the problem here is the lack of users who are willing
to dig into the DMA bits of the drivers they're using. By making it a
requirement to use the new pdma driver, we can possibly change that.

> I have all the
> reasons to believe, that LP-8x4x support would already have be merged,
> if I didn't try to use DT.

That might be, but that's not the point. We want progress here, and that
means we occasionally have to get rid of legacy.

> My plan:
> A. We need to know whether the new DMA implementation performs on par
> with the old one. (I'm starting to check).

Good, thanks!

> if so
> B. We need to thinks whether it's acceptable to kill support for video
> capture.

We can't. As I said, for this particular driver, we can keep the old API
around. We can even make it depend on !CONFIG_DMA_ENGINE, so if anyone
actually wants to use it with DT-enabled boards, we finally have a user
and things can be fixed up. Similar for other drivers we can't test
ourselves.

> In short:
> 
> if (A && B)
>   we drop old DMA
> else
>   we take my patch #7

If A works, there's no need to for patch #7, right? If A doesn't work,
we have to check why and fix it.

Arnd, any oppinion on this?


Thanks,
Daniel

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

* Re: [PATCH v4 00/21] ARM: support for ICP DAS LP-8x4x (with dts)
  2014-04-17 12:34                       ` Daniel Mack
@ 2014-04-19 11:59                         ` Arnd Bergmann
  -1 siblings, 0 replies; 700+ messages in thread
From: Arnd Bergmann @ 2014-04-19 11:59 UTC (permalink / raw)
  To: Daniel Mack
  Cc: Sergei Ianovich, linux-kernel, linux-arm-kernel, Haojian Zhuang,
	laurent.pinchart, kernel

On Thursday 17 April 2014, Daniel Mack wrote:
> On 04/17/2014 02:12 PM, Sergei Ianovich wrote:
> > On Thu, 2014-04-17 at 12:38 +0200, Daniel Mack wrote
> > I have all the
> > reasons to believe, that LP-8x4x support would already have be merged,
> > if I didn't try to use DT.
> 
> That might be, but that's not the point. We want progress here, and that
> means we occasionally have to get rid of legacy.

In most cases, I would strongly support that statement. However, for PXA
in particular, my opinion is that progress is not the highest priority
as I see no realistic hope of converting all the existing machines over
to use DT and change the platform to "multiplatform" support. Anything
more modern than PXA I hope we can eventually get at least done for
multiplatform, same for a few of the older and simpler platforms.

Then again, I'm certainly not stopping you from trying to use add
modern platforms to PXA.

One of the ideas I had earlier was to extend mach-mmp enough to
run any fully DT-enabled PXA machines and leave mach-pxa for the
old ATAGS support and stuff like the legacy DMA support.
However, I don't think we should try that as long as mach-mmp is
lacking some essential DT support, e.g. for the clocks that were
only partially converted to use the common clock framework.

> > if so
> > B. We need to thinks whether it's acceptable to kill support for video
> > capture.
> 
> We can't. As I said, for this particular driver, we can keep the old API
> around. We can even make it depend on !CONFIG_DMA_ENGINE, so if anyone
> actually wants to use it with DT-enabled boards, we finally have a user
> and things can be fixed up. Similar for other drivers we can't test
> ourselves.

Sounds good to me.

> > In short:
> > 
> > if (A && B)
> >   we drop old DMA
> > else
> >   we take my patch #7
> 
> If A works, there's no need to for patch #7, right? If A doesn't work,
> we have to check why and fix it.
> 
> Arnd, any oppinion on this?

No strong opinion, I wouldn't object patch #7 if there is a strong reason
to not use the dmaengine driver for PXA like I would object doing it for
MMP. Then again, I see that you and recently also Laurent are driving a
lot of good work on PXA, and if neither the arm-soc maintainers nor the
three maintainers listed for mach-pxa have a strong opinion, I'd rather
leave it up to your judgement.

	Arnd

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

* [PATCH v4 00/21] ARM: support for ICP DAS LP-8x4x (with dts)
@ 2014-04-19 11:59                         ` Arnd Bergmann
  0 siblings, 0 replies; 700+ messages in thread
From: Arnd Bergmann @ 2014-04-19 11:59 UTC (permalink / raw)
  To: linux-arm-kernel

On Thursday 17 April 2014, Daniel Mack wrote:
> On 04/17/2014 02:12 PM, Sergei Ianovich wrote:
> > On Thu, 2014-04-17 at 12:38 +0200, Daniel Mack wrote
> > I have all the
> > reasons to believe, that LP-8x4x support would already have be merged,
> > if I didn't try to use DT.
> 
> That might be, but that's not the point. We want progress here, and that
> means we occasionally have to get rid of legacy.

In most cases, I would strongly support that statement. However, for PXA
in particular, my opinion is that progress is not the highest priority
as I see no realistic hope of converting all the existing machines over
to use DT and change the platform to "multiplatform" support. Anything
more modern than PXA I hope we can eventually get at least done for
multiplatform, same for a few of the older and simpler platforms.

Then again, I'm certainly not stopping you from trying to use add
modern platforms to PXA.

One of the ideas I had earlier was to extend mach-mmp enough to
run any fully DT-enabled PXA machines and leave mach-pxa for the
old ATAGS support and stuff like the legacy DMA support.
However, I don't think we should try that as long as mach-mmp is
lacking some essential DT support, e.g. for the clocks that were
only partially converted to use the common clock framework.

> > if so
> > B. We need to thinks whether it's acceptable to kill support for video
> > capture.
> 
> We can't. As I said, for this particular driver, we can keep the old API
> around. We can even make it depend on !CONFIG_DMA_ENGINE, so if anyone
> actually wants to use it with DT-enabled boards, we finally have a user
> and things can be fixed up. Similar for other drivers we can't test
> ourselves.

Sounds good to me.

> > In short:
> > 
> > if (A && B)
> >   we drop old DMA
> > else
> >   we take my patch #7
> 
> If A works, there's no need to for patch #7, right? If A doesn't work,
> we have to check why and fix it.
> 
> Arnd, any oppinion on this?

No strong opinion, I wouldn't object patch #7 if there is a strong reason
to not use the dmaengine driver for PXA like I would object doing it for
MMP. Then again, I see that you and recently also Laurent are driving a
lot of good work on PXA, and if neither the arm-soc maintainers nor the
three maintainers listed for mach-pxa have a strong opinion, I'd rather
leave it up to your judgement.

	Arnd

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

* Re: [PATCH v4 10/21] mtd: support BB SRAM on ICP DAS LP-8x4x
  2014-04-16 17:17                   ` Sergei Ianovich
  (?)
@ 2014-04-30 17:21                     ` Brian Norris
  -1 siblings, 0 replies; 700+ messages in thread
From: Brian Norris @ 2014-04-30 17:21 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: linux-kernel, linux-arm-kernel, Rob Herring, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala, Randy Dunlap,
	Russell King, David Woodhouse, Grant Likely, Heikki Krogerus,
	Lee Jones, Artem Bityutskiy, Robert Jarzmik, Michael Opdenacker,
	open list:OPEN FIRMWARE AND...,
	open list:DOCUMENTATION, open list:MEMORY TECHNOLOGY...

Hi Sergei,

A few more small comments.

On Wed, Apr 16, 2014 at 09:17:15PM +0400, Sergei Ianovich wrote:
> This provides an MTD device driver for 512kB of battery backed up SRAM
> on ICPDAS LP-8X4X programmable automation controllers.
> 
> SRAM chip is connected via FPGA and is not accessible without a driver,
> unlike flash memory which is wired to CPU MMU.
> 
> This SRAM becomes an excellent persisent storage of volatile process
> data like counter values and sensor statuses. Storing those data in
> flash or mmc card is not a viable solution.
> 
> Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
> Reviewed-by: Brian Norris <computersforpeace@gmail.com>
> ---
>    v3..v4 for Brian Norris 'Reviewed-by'
>    * add doc file for DT binding
>    * move DTS binding to a different patch (8/21)
>    * drop unused include directive
>    * drop safely unused callback
>    * drop non-default partion probe types
>    * drop duplicate error checks
>    * drop duplicate error reporting
>    * fixed error message on MTD registeration
>    * fixed module removal routine

Thanks for the updates. This patch looks pretty good to me.

>    v2..v3
>    * no changes (except number 08/16 -> 10/21)
> 
>    v0..v2
>    * use device tree
>    * use devm helpers where possible
> 
>  .../devicetree/bindings/mtd/sram-lp8x4x.txt        |  22 +++
>  arch/arm/configs/lp8x4x_defconfig                  |   1 +
>  drivers/mtd/devices/Kconfig                        |  14 ++
>  drivers/mtd/devices/Makefile                       |   1 +
>  drivers/mtd/devices/sram_lp8x4x.c                  | 204 +++++++++++++++++++++
>  5 files changed, 242 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/mtd/sram-lp8x4x.txt
>  create mode 100644 drivers/mtd/devices/sram_lp8x4x.c
> 
> diff --git a/Documentation/devicetree/bindings/mtd/sram-lp8x4x.txt b/Documentation/devicetree/bindings/mtd/sram-lp8x4x.txt
> new file mode 100644
> index 0000000..8b1e864
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/mtd/sram-lp8x4x.txt
> @@ -0,0 +1,22 @@
> +512kB battery backed up SRAM on LP-8x4x industrial computers
> +
> +Required properties:
> +- compatible : should be "icpdas,sram-lp8x4x"
> +
> +- reg: physical base addresses and region lengths of
> +       * IO memory range
> +       * SRAM page selector

Are these region types pretty static for this type of hardware? If not,
it helps to have a reg-names property in the DT, when there are 2 or
more register resources.

> +- eeprom-gpios : should point to active-low write enable GPIO

I'm curious: your driver doesn't actually utilize this binding. Is this
intentional? Is it actually optional? (I note that the example DT below
doesn't have this property...)

> +
> +SRAM chip is connected via FPGA and is not accessible without a driver,
> +unlike flash memory which is wired to CPU MMU. Driver is essentially
> +an address translation routine.
> +
> +Example:
> +
> +	sram@a000 {
> +		compatible = "icpdas,sram-lp8x4x";
> +		reg = <0xa000 0x1000
> +		       0x901e 0x1>;
> +	};
> diff --git a/arch/arm/configs/lp8x4x_defconfig b/arch/arm/configs/lp8x4x_defconfig
> index d60e37a..17a4e6f 100644
> --- a/arch/arm/configs/lp8x4x_defconfig
> +++ b/arch/arm/configs/lp8x4x_defconfig
> @@ -57,6 +57,7 @@ CONFIG_MTD_CFI_ADV_OPTIONS=y
>  CONFIG_MTD_CFI_GEOMETRY=y
>  CONFIG_MTD_CFI_INTELEXT=y
>  CONFIG_MTD_PHYSMAP_OF=y
> +CONFIG_MTD_SRAM_LP8X4X=y
>  CONFIG_PROC_DEVICETREE=y
>  CONFIG_BLK_DEV_LOOP=y
>  CONFIG_BLK_DEV_LOOP_MIN_COUNT=2

I can't take the defconfig update via MTD; it will need to go via the
appropriate ARM tree (arm-soc?). So this hunk needs to move to another
patch.

> diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig
> index 1210bc2..fc8552b 100644
> --- a/drivers/mtd/devices/Kconfig
> +++ b/drivers/mtd/devices/Kconfig
> @@ -225,4 +225,18 @@ config BCH_CONST_T
>  	default 4
>  endif
>  
> +config MTD_SRAM_LP8X4X
> +	tristate "SRAM on ICPDAS LP-8X4X"
> +	depends on OF && ARCH_PXA
> +       ---help---
> +	 This provides an MTD device driver for 512kiB of battery backed up SRAM
> +	 on ICPDAS LP-8X4X programmable automation controllers.
> +
> +	 SRAM chip is connected via FPGA and is not accessible without a driver,
> +	 unlike flash memory which is wired to CPU MMU.
> +
> +	 Say N, unless you plan to run this kernel on LP-8X4X.
> +
> +	 If you say M, the module will be called sram_lp8x4x.
> +
>  endmenu
> diff --git a/drivers/mtd/devices/Makefile b/drivers/mtd/devices/Makefile
> index c68868f..a7d86e2 100644
> --- a/drivers/mtd/devices/Makefile
> +++ b/drivers/mtd/devices/Makefile
> @@ -17,6 +17,7 @@ obj-$(CONFIG_MTD_SPEAR_SMI)	+= spear_smi.o
>  obj-$(CONFIG_MTD_SST25L)	+= sst25l.o
>  obj-$(CONFIG_MTD_BCM47XXSFLASH)	+= bcm47xxsflash.o
>  obj-$(CONFIG_MTD_ST_SPI_FSM)    += st_spi_fsm.o
> +obj-$(CONFIG_MTD_SRAM_LP8X4X)	+= sram_lp8x4x.o
>  
>  
>  CFLAGS_docg3.o			+= -I$(src)
> diff --git a/drivers/mtd/devices/sram_lp8x4x.c b/drivers/mtd/devices/sram_lp8x4x.c
> new file mode 100644
> index 0000000..4cfa70b
> --- /dev/null
> +++ b/drivers/mtd/devices/sram_lp8x4x.c
> @@ -0,0 +1,204 @@
> +/*
> + *  linux/drivers/mtd/devices/lp8x4x_sram.c
> + *
> + *  MTD Driver for SRAM on ICPDAS LP-8x4x
> + *  Copyright (C) 2013 Sergei Ianovich <ynvich@gmail.com>
> + *
> + *  This program is free software; you can redistribute it and/or modify
> + *  it under the terms of the GNU General Public License version 2 as
> + *  published by the Free Software Foundation or any later version.
> + */
> +
> +#include <linux/init.h>
> +#include <linux/io.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/mtd/map.h>
> +#include <linux/mtd/mtd.h>
> +#include <linux/mtd/partitions.h>
> +#include <linux/platform_device.h>
> +#include <linux/of_device.h>
> +#include <linux/slab.h>
> +#include <linux/string_helpers.h>
> +#include <linux/types.h>
> +
> +struct lp8x4x_sram_info {
> +	void __iomem	*bank;
> +	void __iomem	*virt;
> +	struct mutex	lock;
> +	unsigned	active_bank;
> +	struct mtd_info	mtd;
> +};
> +
> +static int
> +lp8x4x_sram_erase(struct mtd_info *mtd, struct erase_info *instr)
> +{
> +	struct lp8x4x_sram_info *info = mtd->priv;
> +	unsigned bank = instr->addr >> 11;
> +	unsigned offset = (instr->addr & 0x7ff) << 1;
> +	loff_t i;
> +
> +	mutex_lock(&info->lock);
> +	if (unlikely(bank != info->active_bank)) {
> +		info->active_bank = bank;
> +		iowrite8(bank, info->bank);
> +	}
> +	for (i = 0; i < instr->len; i++) {
> +		iowrite8(0xff, info->virt + offset);
> +		offset += 2;
> +		if (unlikely(offset == 0)) {
> +			info->active_bank++;
> +			iowrite8(info->active_bank, info->bank);
> +		}
> +	}
> +	mutex_unlock(&info->lock);
> +	instr->state = MTD_ERASE_DONE;
> +	mtd_erase_callback(instr);
> +
> +	return 0;
> +}
> +
> +static int
> +lp8x4x_sram_write(struct mtd_info *mtd, loff_t to, size_t len,
> +		size_t *retlen, const u_char *b)
> +{
> +	struct lp8x4x_sram_info *info = mtd->priv;
> +	unsigned bank = to >> 11;
> +	unsigned offset = (to & 0x7ff) << 1;
> +	loff_t i;
> +
> +	mutex_lock(&info->lock);
> +	if (unlikely(bank != info->active_bank)) {
> +		info->active_bank = bank;
> +		iowrite8(bank, info->bank);
> +	}
> +	for (i = 0; i < len; i++) {
> +		iowrite8(b[i], info->virt + offset);
> +		offset += 2;
> +		if (unlikely(offset == 0)) {
> +			info->active_bank++;
> +			iowrite8(info->active_bank, info->bank);
> +		}
> +	}
> +	mutex_unlock(&info->lock);
> +	*retlen = len;
> +	return 0;
> +}
> +
> +static int
> +lp8x4x_sram_read(struct mtd_info *mtd, loff_t from, size_t len,
> +		size_t *retlen, u_char *b)
> +{
> +	struct lp8x4x_sram_info *info = mtd->priv;
> +	unsigned bank = from >> 11;
> +	unsigned offset = (from & 0x7ff) << 1;
> +	loff_t i;
> +
> +	mutex_lock(&info->lock);
> +	if (unlikely(bank != info->active_bank)) {
> +		info->active_bank = bank;
> +		iowrite8(bank, info->bank);
> +	}
> +	for (i = 0; i < len; i++) {
> +		b[i] = ioread8(info->virt + offset);
> +		offset += 2;
> +		if (unlikely(offset == 0)) {
> +			info->active_bank++;
> +			iowrite8(info->active_bank, info->bank);
> +		}
> +	}
> +	mutex_unlock(&info->lock);
> +	*retlen = len;
> +	return 0;
> +}
> +
> +static struct of_device_id of_flash_match[] = {
> +	{
> +		.compatible	= "icpdas,sram-lp8x4x",
> +	},
> +	{ },
> +};
> +MODULE_DEVICE_TABLE(of, of_flash_match);
> +
> +static int
> +lp8x4x_sram_probe(struct platform_device *pdev)
> +{
> +	const struct of_device_id *match;
> +	struct lp8x4x_sram_info *info;
> +	struct resource *res_virt, *res_bank;
> +	char sz_str[16];
> +	struct mtd_part_parser_data ppdata;
> +	int err = 0;
> +
> +	match = of_match_device(of_flash_match, &pdev->dev);
> +	if (!match)
> +		return -EINVAL;

Does this of_match_device() serve any particular purpose? Your driver
already matches against these IDs, and you're not actually retrieving
any of-data from the match, so this looks redundant.

> +
> +	info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
> +	if (!info)
> +		return -ENOMEM;
> +
> +	res_virt = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	info->virt =  devm_ioremap_resource(&pdev->dev, res_virt);
> +	if (IS_ERR(info->virt))
> +		return PTR_ERR(info->virt);
> +
> +	res_bank = platform_get_resource(pdev, IORESOURCE_MEM, 1);
> +	info->bank = devm_ioremap_resource(&pdev->dev, res_bank);
> +	if (IS_ERR(info->bank))
> +		return PTR_ERR(info->bank);
> +
> +	info->mtd.priv = info;
> +	info->mtd.name = "SRAM";

Are you absolutely sure there is only ever a single SRAM device on a
given system? Because otherwise, you will get redundantly-named MTD's.
If the answer is no, you might consider a unique naming scheme.

> +	info->mtd.type = MTD_RAM;
> +	info->mtd.flags = MTD_CAP_RAM;
> +	info->mtd.size = resource_size(res_virt) << 7;
> +	info->mtd.erasesize = 512;
> +	info->mtd.writesize = 4;
> +	info->mtd._erase = lp8x4x_sram_erase;
> +	info->mtd._write = lp8x4x_sram_write;
> +	info->mtd._read = lp8x4x_sram_read;
> +	info->mtd.owner = THIS_MODULE;
> +
> +	mutex_init(&info->lock);
> +	iowrite8(info->active_bank, info->bank);
> +	platform_set_drvdata(pdev, info);
> +
> +	ppdata.of_node = pdev->dev.of_node;
> +	err = mtd_device_parse_register(&info->mtd, NULL, &ppdata,
> +			NULL, 0);
> +
> +	if (err < 0) {
> +		dev_err(&pdev->dev, "failed to register MTD\n");
> +		return err;
> +	}
> +
> +	string_get_size(info->mtd.size, STRING_UNITS_2, sz_str,
> +			sizeof(sz_str));
> +	dev_info(&pdev->dev, "using %s SRAM on LP-8X4X as %s\n", sz_str,
> +			dev_name(&info->mtd.dev));
> +	return 0;
> +}
> +
> +static int
> +lp8x4x_sram_remove(struct platform_device *dev)
> +{
> +	struct lp8x4x_sram_info *info = platform_get_drvdata(dev);
> +	return mtd_device_unregister(&info->mtd);
> +}
> +
> +static struct platform_driver lp8x4x_sram_driver = {
> +	.driver = {
> +		.name		= "sram-lp8x4x",
> +		.owner		= THIS_MODULE,
> +		.of_match_table = of_flash_match,
> +	},
> +	.probe		= lp8x4x_sram_probe,
> +	.remove		= lp8x4x_sram_remove,
> +};
> +
> +module_platform_driver(lp8x4x_sram_driver);
> +
> +MODULE_LICENSE("GPL");
> +MODULE_AUTHOR("Sergei Ianovich <ynvich@gmail.com>");
> +MODULE_DESCRIPTION("MTD driver for SRAM on ICPDAS LP-8x4x");

Thanks,
Brian

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

* Re: [PATCH v4 10/21] mtd: support BB SRAM on ICP DAS LP-8x4x
@ 2014-04-30 17:21                     ` Brian Norris
  0 siblings, 0 replies; 700+ messages in thread
From: Brian Norris @ 2014-04-30 17:21 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: Mark Rutland, open list:OPEN FIRMWARE AND...,
	Heikki Krogerus, Russell King, open list:DOCUMENTATION,
	Pawel Moll, Ian Campbell, Lee Jones, Robert Jarzmik,
	Randy Dunlap, Artem Bityutskiy, linux-kernel, Michael Opdenacker,
	Rob Herring, open list:MEMORY TECHNOLOGY...,
	Kumar Gala, Grant Likely, David Woodhouse, linux-arm-kernel

Hi Sergei,

A few more small comments.

On Wed, Apr 16, 2014 at 09:17:15PM +0400, Sergei Ianovich wrote:
> This provides an MTD device driver for 512kB of battery backed up SRAM
> on ICPDAS LP-8X4X programmable automation controllers.
> 
> SRAM chip is connected via FPGA and is not accessible without a driver,
> unlike flash memory which is wired to CPU MMU.
> 
> This SRAM becomes an excellent persisent storage of volatile process
> data like counter values and sensor statuses. Storing those data in
> flash or mmc card is not a viable solution.
> 
> Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
> Reviewed-by: Brian Norris <computersforpeace@gmail.com>
> ---
>    v3..v4 for Brian Norris 'Reviewed-by'
>    * add doc file for DT binding
>    * move DTS binding to a different patch (8/21)
>    * drop unused include directive
>    * drop safely unused callback
>    * drop non-default partion probe types
>    * drop duplicate error checks
>    * drop duplicate error reporting
>    * fixed error message on MTD registeration
>    * fixed module removal routine

Thanks for the updates. This patch looks pretty good to me.

>    v2..v3
>    * no changes (except number 08/16 -> 10/21)
> 
>    v0..v2
>    * use device tree
>    * use devm helpers where possible
> 
>  .../devicetree/bindings/mtd/sram-lp8x4x.txt        |  22 +++
>  arch/arm/configs/lp8x4x_defconfig                  |   1 +
>  drivers/mtd/devices/Kconfig                        |  14 ++
>  drivers/mtd/devices/Makefile                       |   1 +
>  drivers/mtd/devices/sram_lp8x4x.c                  | 204 +++++++++++++++++++++
>  5 files changed, 242 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/mtd/sram-lp8x4x.txt
>  create mode 100644 drivers/mtd/devices/sram_lp8x4x.c
> 
> diff --git a/Documentation/devicetree/bindings/mtd/sram-lp8x4x.txt b/Documentation/devicetree/bindings/mtd/sram-lp8x4x.txt
> new file mode 100644
> index 0000000..8b1e864
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/mtd/sram-lp8x4x.txt
> @@ -0,0 +1,22 @@
> +512kB battery backed up SRAM on LP-8x4x industrial computers
> +
> +Required properties:
> +- compatible : should be "icpdas,sram-lp8x4x"
> +
> +- reg: physical base addresses and region lengths of
> +       * IO memory range
> +       * SRAM page selector

Are these region types pretty static for this type of hardware? If not,
it helps to have a reg-names property in the DT, when there are 2 or
more register resources.

> +- eeprom-gpios : should point to active-low write enable GPIO

I'm curious: your driver doesn't actually utilize this binding. Is this
intentional? Is it actually optional? (I note that the example DT below
doesn't have this property...)

> +
> +SRAM chip is connected via FPGA and is not accessible without a driver,
> +unlike flash memory which is wired to CPU MMU. Driver is essentially
> +an address translation routine.
> +
> +Example:
> +
> +	sram@a000 {
> +		compatible = "icpdas,sram-lp8x4x";
> +		reg = <0xa000 0x1000
> +		       0x901e 0x1>;
> +	};
> diff --git a/arch/arm/configs/lp8x4x_defconfig b/arch/arm/configs/lp8x4x_defconfig
> index d60e37a..17a4e6f 100644
> --- a/arch/arm/configs/lp8x4x_defconfig
> +++ b/arch/arm/configs/lp8x4x_defconfig
> @@ -57,6 +57,7 @@ CONFIG_MTD_CFI_ADV_OPTIONS=y
>  CONFIG_MTD_CFI_GEOMETRY=y
>  CONFIG_MTD_CFI_INTELEXT=y
>  CONFIG_MTD_PHYSMAP_OF=y
> +CONFIG_MTD_SRAM_LP8X4X=y
>  CONFIG_PROC_DEVICETREE=y
>  CONFIG_BLK_DEV_LOOP=y
>  CONFIG_BLK_DEV_LOOP_MIN_COUNT=2

I can't take the defconfig update via MTD; it will need to go via the
appropriate ARM tree (arm-soc?). So this hunk needs to move to another
patch.

> diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig
> index 1210bc2..fc8552b 100644
> --- a/drivers/mtd/devices/Kconfig
> +++ b/drivers/mtd/devices/Kconfig
> @@ -225,4 +225,18 @@ config BCH_CONST_T
>  	default 4
>  endif
>  
> +config MTD_SRAM_LP8X4X
> +	tristate "SRAM on ICPDAS LP-8X4X"
> +	depends on OF && ARCH_PXA
> +       ---help---
> +	 This provides an MTD device driver for 512kiB of battery backed up SRAM
> +	 on ICPDAS LP-8X4X programmable automation controllers.
> +
> +	 SRAM chip is connected via FPGA and is not accessible without a driver,
> +	 unlike flash memory which is wired to CPU MMU.
> +
> +	 Say N, unless you plan to run this kernel on LP-8X4X.
> +
> +	 If you say M, the module will be called sram_lp8x4x.
> +
>  endmenu
> diff --git a/drivers/mtd/devices/Makefile b/drivers/mtd/devices/Makefile
> index c68868f..a7d86e2 100644
> --- a/drivers/mtd/devices/Makefile
> +++ b/drivers/mtd/devices/Makefile
> @@ -17,6 +17,7 @@ obj-$(CONFIG_MTD_SPEAR_SMI)	+= spear_smi.o
>  obj-$(CONFIG_MTD_SST25L)	+= sst25l.o
>  obj-$(CONFIG_MTD_BCM47XXSFLASH)	+= bcm47xxsflash.o
>  obj-$(CONFIG_MTD_ST_SPI_FSM)    += st_spi_fsm.o
> +obj-$(CONFIG_MTD_SRAM_LP8X4X)	+= sram_lp8x4x.o
>  
>  
>  CFLAGS_docg3.o			+= -I$(src)
> diff --git a/drivers/mtd/devices/sram_lp8x4x.c b/drivers/mtd/devices/sram_lp8x4x.c
> new file mode 100644
> index 0000000..4cfa70b
> --- /dev/null
> +++ b/drivers/mtd/devices/sram_lp8x4x.c
> @@ -0,0 +1,204 @@
> +/*
> + *  linux/drivers/mtd/devices/lp8x4x_sram.c
> + *
> + *  MTD Driver for SRAM on ICPDAS LP-8x4x
> + *  Copyright (C) 2013 Sergei Ianovich <ynvich@gmail.com>
> + *
> + *  This program is free software; you can redistribute it and/or modify
> + *  it under the terms of the GNU General Public License version 2 as
> + *  published by the Free Software Foundation or any later version.
> + */
> +
> +#include <linux/init.h>
> +#include <linux/io.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/mtd/map.h>
> +#include <linux/mtd/mtd.h>
> +#include <linux/mtd/partitions.h>
> +#include <linux/platform_device.h>
> +#include <linux/of_device.h>
> +#include <linux/slab.h>
> +#include <linux/string_helpers.h>
> +#include <linux/types.h>
> +
> +struct lp8x4x_sram_info {
> +	void __iomem	*bank;
> +	void __iomem	*virt;
> +	struct mutex	lock;
> +	unsigned	active_bank;
> +	struct mtd_info	mtd;
> +};
> +
> +static int
> +lp8x4x_sram_erase(struct mtd_info *mtd, struct erase_info *instr)
> +{
> +	struct lp8x4x_sram_info *info = mtd->priv;
> +	unsigned bank = instr->addr >> 11;
> +	unsigned offset = (instr->addr & 0x7ff) << 1;
> +	loff_t i;
> +
> +	mutex_lock(&info->lock);
> +	if (unlikely(bank != info->active_bank)) {
> +		info->active_bank = bank;
> +		iowrite8(bank, info->bank);
> +	}
> +	for (i = 0; i < instr->len; i++) {
> +		iowrite8(0xff, info->virt + offset);
> +		offset += 2;
> +		if (unlikely(offset == 0)) {
> +			info->active_bank++;
> +			iowrite8(info->active_bank, info->bank);
> +		}
> +	}
> +	mutex_unlock(&info->lock);
> +	instr->state = MTD_ERASE_DONE;
> +	mtd_erase_callback(instr);
> +
> +	return 0;
> +}
> +
> +static int
> +lp8x4x_sram_write(struct mtd_info *mtd, loff_t to, size_t len,
> +		size_t *retlen, const u_char *b)
> +{
> +	struct lp8x4x_sram_info *info = mtd->priv;
> +	unsigned bank = to >> 11;
> +	unsigned offset = (to & 0x7ff) << 1;
> +	loff_t i;
> +
> +	mutex_lock(&info->lock);
> +	if (unlikely(bank != info->active_bank)) {
> +		info->active_bank = bank;
> +		iowrite8(bank, info->bank);
> +	}
> +	for (i = 0; i < len; i++) {
> +		iowrite8(b[i], info->virt + offset);
> +		offset += 2;
> +		if (unlikely(offset == 0)) {
> +			info->active_bank++;
> +			iowrite8(info->active_bank, info->bank);
> +		}
> +	}
> +	mutex_unlock(&info->lock);
> +	*retlen = len;
> +	return 0;
> +}
> +
> +static int
> +lp8x4x_sram_read(struct mtd_info *mtd, loff_t from, size_t len,
> +		size_t *retlen, u_char *b)
> +{
> +	struct lp8x4x_sram_info *info = mtd->priv;
> +	unsigned bank = from >> 11;
> +	unsigned offset = (from & 0x7ff) << 1;
> +	loff_t i;
> +
> +	mutex_lock(&info->lock);
> +	if (unlikely(bank != info->active_bank)) {
> +		info->active_bank = bank;
> +		iowrite8(bank, info->bank);
> +	}
> +	for (i = 0; i < len; i++) {
> +		b[i] = ioread8(info->virt + offset);
> +		offset += 2;
> +		if (unlikely(offset == 0)) {
> +			info->active_bank++;
> +			iowrite8(info->active_bank, info->bank);
> +		}
> +	}
> +	mutex_unlock(&info->lock);
> +	*retlen = len;
> +	return 0;
> +}
> +
> +static struct of_device_id of_flash_match[] = {
> +	{
> +		.compatible	= "icpdas,sram-lp8x4x",
> +	},
> +	{ },
> +};
> +MODULE_DEVICE_TABLE(of, of_flash_match);
> +
> +static int
> +lp8x4x_sram_probe(struct platform_device *pdev)
> +{
> +	const struct of_device_id *match;
> +	struct lp8x4x_sram_info *info;
> +	struct resource *res_virt, *res_bank;
> +	char sz_str[16];
> +	struct mtd_part_parser_data ppdata;
> +	int err = 0;
> +
> +	match = of_match_device(of_flash_match, &pdev->dev);
> +	if (!match)
> +		return -EINVAL;

Does this of_match_device() serve any particular purpose? Your driver
already matches against these IDs, and you're not actually retrieving
any of-data from the match, so this looks redundant.

> +
> +	info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
> +	if (!info)
> +		return -ENOMEM;
> +
> +	res_virt = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	info->virt =  devm_ioremap_resource(&pdev->dev, res_virt);
> +	if (IS_ERR(info->virt))
> +		return PTR_ERR(info->virt);
> +
> +	res_bank = platform_get_resource(pdev, IORESOURCE_MEM, 1);
> +	info->bank = devm_ioremap_resource(&pdev->dev, res_bank);
> +	if (IS_ERR(info->bank))
> +		return PTR_ERR(info->bank);
> +
> +	info->mtd.priv = info;
> +	info->mtd.name = "SRAM";

Are you absolutely sure there is only ever a single SRAM device on a
given system? Because otherwise, you will get redundantly-named MTD's.
If the answer is no, you might consider a unique naming scheme.

> +	info->mtd.type = MTD_RAM;
> +	info->mtd.flags = MTD_CAP_RAM;
> +	info->mtd.size = resource_size(res_virt) << 7;
> +	info->mtd.erasesize = 512;
> +	info->mtd.writesize = 4;
> +	info->mtd._erase = lp8x4x_sram_erase;
> +	info->mtd._write = lp8x4x_sram_write;
> +	info->mtd._read = lp8x4x_sram_read;
> +	info->mtd.owner = THIS_MODULE;
> +
> +	mutex_init(&info->lock);
> +	iowrite8(info->active_bank, info->bank);
> +	platform_set_drvdata(pdev, info);
> +
> +	ppdata.of_node = pdev->dev.of_node;
> +	err = mtd_device_parse_register(&info->mtd, NULL, &ppdata,
> +			NULL, 0);
> +
> +	if (err < 0) {
> +		dev_err(&pdev->dev, "failed to register MTD\n");
> +		return err;
> +	}
> +
> +	string_get_size(info->mtd.size, STRING_UNITS_2, sz_str,
> +			sizeof(sz_str));
> +	dev_info(&pdev->dev, "using %s SRAM on LP-8X4X as %s\n", sz_str,
> +			dev_name(&info->mtd.dev));
> +	return 0;
> +}
> +
> +static int
> +lp8x4x_sram_remove(struct platform_device *dev)
> +{
> +	struct lp8x4x_sram_info *info = platform_get_drvdata(dev);
> +	return mtd_device_unregister(&info->mtd);
> +}
> +
> +static struct platform_driver lp8x4x_sram_driver = {
> +	.driver = {
> +		.name		= "sram-lp8x4x",
> +		.owner		= THIS_MODULE,
> +		.of_match_table = of_flash_match,
> +	},
> +	.probe		= lp8x4x_sram_probe,
> +	.remove		= lp8x4x_sram_remove,
> +};
> +
> +module_platform_driver(lp8x4x_sram_driver);
> +
> +MODULE_LICENSE("GPL");
> +MODULE_AUTHOR("Sergei Ianovich <ynvich@gmail.com>");
> +MODULE_DESCRIPTION("MTD driver for SRAM on ICPDAS LP-8x4x");

Thanks,
Brian

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

* [PATCH v4 10/21] mtd: support BB SRAM on ICP DAS LP-8x4x
@ 2014-04-30 17:21                     ` Brian Norris
  0 siblings, 0 replies; 700+ messages in thread
From: Brian Norris @ 2014-04-30 17:21 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Sergei,

A few more small comments.

On Wed, Apr 16, 2014 at 09:17:15PM +0400, Sergei Ianovich wrote:
> This provides an MTD device driver for 512kB of battery backed up SRAM
> on ICPDAS LP-8X4X programmable automation controllers.
> 
> SRAM chip is connected via FPGA and is not accessible without a driver,
> unlike flash memory which is wired to CPU MMU.
> 
> This SRAM becomes an excellent persisent storage of volatile process
> data like counter values and sensor statuses. Storing those data in
> flash or mmc card is not a viable solution.
> 
> Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
> Reviewed-by: Brian Norris <computersforpeace@gmail.com>
> ---
>    v3..v4 for Brian Norris 'Reviewed-by'
>    * add doc file for DT binding
>    * move DTS binding to a different patch (8/21)
>    * drop unused include directive
>    * drop safely unused callback
>    * drop non-default partion probe types
>    * drop duplicate error checks
>    * drop duplicate error reporting
>    * fixed error message on MTD registeration
>    * fixed module removal routine

Thanks for the updates. This patch looks pretty good to me.

>    v2..v3
>    * no changes (except number 08/16 -> 10/21)
> 
>    v0..v2
>    * use device tree
>    * use devm helpers where possible
> 
>  .../devicetree/bindings/mtd/sram-lp8x4x.txt        |  22 +++
>  arch/arm/configs/lp8x4x_defconfig                  |   1 +
>  drivers/mtd/devices/Kconfig                        |  14 ++
>  drivers/mtd/devices/Makefile                       |   1 +
>  drivers/mtd/devices/sram_lp8x4x.c                  | 204 +++++++++++++++++++++
>  5 files changed, 242 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/mtd/sram-lp8x4x.txt
>  create mode 100644 drivers/mtd/devices/sram_lp8x4x.c
> 
> diff --git a/Documentation/devicetree/bindings/mtd/sram-lp8x4x.txt b/Documentation/devicetree/bindings/mtd/sram-lp8x4x.txt
> new file mode 100644
> index 0000000..8b1e864
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/mtd/sram-lp8x4x.txt
> @@ -0,0 +1,22 @@
> +512kB battery backed up SRAM on LP-8x4x industrial computers
> +
> +Required properties:
> +- compatible : should be "icpdas,sram-lp8x4x"
> +
> +- reg: physical base addresses and region lengths of
> +       * IO memory range
> +       * SRAM page selector

Are these region types pretty static for this type of hardware? If not,
it helps to have a reg-names property in the DT, when there are 2 or
more register resources.

> +- eeprom-gpios : should point to active-low write enable GPIO

I'm curious: your driver doesn't actually utilize this binding. Is this
intentional? Is it actually optional? (I note that the example DT below
doesn't have this property...)

> +
> +SRAM chip is connected via FPGA and is not accessible without a driver,
> +unlike flash memory which is wired to CPU MMU. Driver is essentially
> +an address translation routine.
> +
> +Example:
> +
> +	sram at a000 {
> +		compatible = "icpdas,sram-lp8x4x";
> +		reg = <0xa000 0x1000
> +		       0x901e 0x1>;
> +	};
> diff --git a/arch/arm/configs/lp8x4x_defconfig b/arch/arm/configs/lp8x4x_defconfig
> index d60e37a..17a4e6f 100644
> --- a/arch/arm/configs/lp8x4x_defconfig
> +++ b/arch/arm/configs/lp8x4x_defconfig
> @@ -57,6 +57,7 @@ CONFIG_MTD_CFI_ADV_OPTIONS=y
>  CONFIG_MTD_CFI_GEOMETRY=y
>  CONFIG_MTD_CFI_INTELEXT=y
>  CONFIG_MTD_PHYSMAP_OF=y
> +CONFIG_MTD_SRAM_LP8X4X=y
>  CONFIG_PROC_DEVICETREE=y
>  CONFIG_BLK_DEV_LOOP=y
>  CONFIG_BLK_DEV_LOOP_MIN_COUNT=2

I can't take the defconfig update via MTD; it will need to go via the
appropriate ARM tree (arm-soc?). So this hunk needs to move to another
patch.

> diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig
> index 1210bc2..fc8552b 100644
> --- a/drivers/mtd/devices/Kconfig
> +++ b/drivers/mtd/devices/Kconfig
> @@ -225,4 +225,18 @@ config BCH_CONST_T
>  	default 4
>  endif
>  
> +config MTD_SRAM_LP8X4X
> +	tristate "SRAM on ICPDAS LP-8X4X"
> +	depends on OF && ARCH_PXA
> +       ---help---
> +	 This provides an MTD device driver for 512kiB of battery backed up SRAM
> +	 on ICPDAS LP-8X4X programmable automation controllers.
> +
> +	 SRAM chip is connected via FPGA and is not accessible without a driver,
> +	 unlike flash memory which is wired to CPU MMU.
> +
> +	 Say N, unless you plan to run this kernel on LP-8X4X.
> +
> +	 If you say M, the module will be called sram_lp8x4x.
> +
>  endmenu
> diff --git a/drivers/mtd/devices/Makefile b/drivers/mtd/devices/Makefile
> index c68868f..a7d86e2 100644
> --- a/drivers/mtd/devices/Makefile
> +++ b/drivers/mtd/devices/Makefile
> @@ -17,6 +17,7 @@ obj-$(CONFIG_MTD_SPEAR_SMI)	+= spear_smi.o
>  obj-$(CONFIG_MTD_SST25L)	+= sst25l.o
>  obj-$(CONFIG_MTD_BCM47XXSFLASH)	+= bcm47xxsflash.o
>  obj-$(CONFIG_MTD_ST_SPI_FSM)    += st_spi_fsm.o
> +obj-$(CONFIG_MTD_SRAM_LP8X4X)	+= sram_lp8x4x.o
>  
>  
>  CFLAGS_docg3.o			+= -I$(src)
> diff --git a/drivers/mtd/devices/sram_lp8x4x.c b/drivers/mtd/devices/sram_lp8x4x.c
> new file mode 100644
> index 0000000..4cfa70b
> --- /dev/null
> +++ b/drivers/mtd/devices/sram_lp8x4x.c
> @@ -0,0 +1,204 @@
> +/*
> + *  linux/drivers/mtd/devices/lp8x4x_sram.c
> + *
> + *  MTD Driver for SRAM on ICPDAS LP-8x4x
> + *  Copyright (C) 2013 Sergei Ianovich <ynvich@gmail.com>
> + *
> + *  This program is free software; you can redistribute it and/or modify
> + *  it under the terms of the GNU General Public License version 2 as
> + *  published by the Free Software Foundation or any later version.
> + */
> +
> +#include <linux/init.h>
> +#include <linux/io.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/mtd/map.h>
> +#include <linux/mtd/mtd.h>
> +#include <linux/mtd/partitions.h>
> +#include <linux/platform_device.h>
> +#include <linux/of_device.h>
> +#include <linux/slab.h>
> +#include <linux/string_helpers.h>
> +#include <linux/types.h>
> +
> +struct lp8x4x_sram_info {
> +	void __iomem	*bank;
> +	void __iomem	*virt;
> +	struct mutex	lock;
> +	unsigned	active_bank;
> +	struct mtd_info	mtd;
> +};
> +
> +static int
> +lp8x4x_sram_erase(struct mtd_info *mtd, struct erase_info *instr)
> +{
> +	struct lp8x4x_sram_info *info = mtd->priv;
> +	unsigned bank = instr->addr >> 11;
> +	unsigned offset = (instr->addr & 0x7ff) << 1;
> +	loff_t i;
> +
> +	mutex_lock(&info->lock);
> +	if (unlikely(bank != info->active_bank)) {
> +		info->active_bank = bank;
> +		iowrite8(bank, info->bank);
> +	}
> +	for (i = 0; i < instr->len; i++) {
> +		iowrite8(0xff, info->virt + offset);
> +		offset += 2;
> +		if (unlikely(offset == 0)) {
> +			info->active_bank++;
> +			iowrite8(info->active_bank, info->bank);
> +		}
> +	}
> +	mutex_unlock(&info->lock);
> +	instr->state = MTD_ERASE_DONE;
> +	mtd_erase_callback(instr);
> +
> +	return 0;
> +}
> +
> +static int
> +lp8x4x_sram_write(struct mtd_info *mtd, loff_t to, size_t len,
> +		size_t *retlen, const u_char *b)
> +{
> +	struct lp8x4x_sram_info *info = mtd->priv;
> +	unsigned bank = to >> 11;
> +	unsigned offset = (to & 0x7ff) << 1;
> +	loff_t i;
> +
> +	mutex_lock(&info->lock);
> +	if (unlikely(bank != info->active_bank)) {
> +		info->active_bank = bank;
> +		iowrite8(bank, info->bank);
> +	}
> +	for (i = 0; i < len; i++) {
> +		iowrite8(b[i], info->virt + offset);
> +		offset += 2;
> +		if (unlikely(offset == 0)) {
> +			info->active_bank++;
> +			iowrite8(info->active_bank, info->bank);
> +		}
> +	}
> +	mutex_unlock(&info->lock);
> +	*retlen = len;
> +	return 0;
> +}
> +
> +static int
> +lp8x4x_sram_read(struct mtd_info *mtd, loff_t from, size_t len,
> +		size_t *retlen, u_char *b)
> +{
> +	struct lp8x4x_sram_info *info = mtd->priv;
> +	unsigned bank = from >> 11;
> +	unsigned offset = (from & 0x7ff) << 1;
> +	loff_t i;
> +
> +	mutex_lock(&info->lock);
> +	if (unlikely(bank != info->active_bank)) {
> +		info->active_bank = bank;
> +		iowrite8(bank, info->bank);
> +	}
> +	for (i = 0; i < len; i++) {
> +		b[i] = ioread8(info->virt + offset);
> +		offset += 2;
> +		if (unlikely(offset == 0)) {
> +			info->active_bank++;
> +			iowrite8(info->active_bank, info->bank);
> +		}
> +	}
> +	mutex_unlock(&info->lock);
> +	*retlen = len;
> +	return 0;
> +}
> +
> +static struct of_device_id of_flash_match[] = {
> +	{
> +		.compatible	= "icpdas,sram-lp8x4x",
> +	},
> +	{ },
> +};
> +MODULE_DEVICE_TABLE(of, of_flash_match);
> +
> +static int
> +lp8x4x_sram_probe(struct platform_device *pdev)
> +{
> +	const struct of_device_id *match;
> +	struct lp8x4x_sram_info *info;
> +	struct resource *res_virt, *res_bank;
> +	char sz_str[16];
> +	struct mtd_part_parser_data ppdata;
> +	int err = 0;
> +
> +	match = of_match_device(of_flash_match, &pdev->dev);
> +	if (!match)
> +		return -EINVAL;

Does this of_match_device() serve any particular purpose? Your driver
already matches against these IDs, and you're not actually retrieving
any of-data from the match, so this looks redundant.

> +
> +	info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
> +	if (!info)
> +		return -ENOMEM;
> +
> +	res_virt = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	info->virt =  devm_ioremap_resource(&pdev->dev, res_virt);
> +	if (IS_ERR(info->virt))
> +		return PTR_ERR(info->virt);
> +
> +	res_bank = platform_get_resource(pdev, IORESOURCE_MEM, 1);
> +	info->bank = devm_ioremap_resource(&pdev->dev, res_bank);
> +	if (IS_ERR(info->bank))
> +		return PTR_ERR(info->bank);
> +
> +	info->mtd.priv = info;
> +	info->mtd.name = "SRAM";

Are you absolutely sure there is only ever a single SRAM device on a
given system? Because otherwise, you will get redundantly-named MTD's.
If the answer is no, you might consider a unique naming scheme.

> +	info->mtd.type = MTD_RAM;
> +	info->mtd.flags = MTD_CAP_RAM;
> +	info->mtd.size = resource_size(res_virt) << 7;
> +	info->mtd.erasesize = 512;
> +	info->mtd.writesize = 4;
> +	info->mtd._erase = lp8x4x_sram_erase;
> +	info->mtd._write = lp8x4x_sram_write;
> +	info->mtd._read = lp8x4x_sram_read;
> +	info->mtd.owner = THIS_MODULE;
> +
> +	mutex_init(&info->lock);
> +	iowrite8(info->active_bank, info->bank);
> +	platform_set_drvdata(pdev, info);
> +
> +	ppdata.of_node = pdev->dev.of_node;
> +	err = mtd_device_parse_register(&info->mtd, NULL, &ppdata,
> +			NULL, 0);
> +
> +	if (err < 0) {
> +		dev_err(&pdev->dev, "failed to register MTD\n");
> +		return err;
> +	}
> +
> +	string_get_size(info->mtd.size, STRING_UNITS_2, sz_str,
> +			sizeof(sz_str));
> +	dev_info(&pdev->dev, "using %s SRAM on LP-8X4X as %s\n", sz_str,
> +			dev_name(&info->mtd.dev));
> +	return 0;
> +}
> +
> +static int
> +lp8x4x_sram_remove(struct platform_device *dev)
> +{
> +	struct lp8x4x_sram_info *info = platform_get_drvdata(dev);
> +	return mtd_device_unregister(&info->mtd);
> +}
> +
> +static struct platform_driver lp8x4x_sram_driver = {
> +	.driver = {
> +		.name		= "sram-lp8x4x",
> +		.owner		= THIS_MODULE,
> +		.of_match_table = of_flash_match,
> +	},
> +	.probe		= lp8x4x_sram_probe,
> +	.remove		= lp8x4x_sram_remove,
> +};
> +
> +module_platform_driver(lp8x4x_sram_driver);
> +
> +MODULE_LICENSE("GPL");
> +MODULE_AUTHOR("Sergei Ianovich <ynvich@gmail.com>");
> +MODULE_DESCRIPTION("MTD driver for SRAM on ICPDAS LP-8x4x");

Thanks,
Brian

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

* Re: [PATCH v4 10/21] mtd: support BB SRAM on ICP DAS LP-8x4x
  2014-04-30 17:21                     ` Brian Norris
  (?)
@ 2014-04-30 17:35                       ` ООО "ЭлектроПлюс"
  -1 siblings, 0 replies; 700+ messages in thread
From: ООО "ЭлектроПлюс" @ 2014-04-30 17:35 UTC (permalink / raw)
  To: Brian Norris
  Cc: linux-kernel, linux-arm-kernel, Rob Herring, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala, Randy Dunlap,
	Russell King, David Woodhouse, Grant Likely, Heikki Krogerus,
	Lee Jones, Artem Bityutskiy, Robert Jarzmik, Michael Opdenacker,
	open list:OPEN FIRMWARE AND...,
	open list:DOCUMENTATION, open list:MEMORY TECHNOLOGY...

Hi Brian,

On Wed, 2014-04-30 at 10:21 -0700, Brian Norris wrote:
> A few more small comments.
> 
> On Wed, Apr 16, 2014 at 09:17:15PM +0400, Sergei Ianovich wrote:
> > +++ b/Documentation/devicetree/bindings/mtd/sram-lp8x4x.txt
> > @@ -0,0 +1,22 @@
> > +512kB battery backed up SRAM on LP-8x4x industrial computers
> > +
> > +Required properties:
> > +- compatible : should be "icpdas,sram-lp8x4x"
> > +
> > +- reg: physical base addresses and region lengths of
> > +       * IO memory range
> > +       * SRAM page selector
> 
> Are these region types pretty static for this type of hardware? If not,
> it helps to have a reg-names property in the DT, when there are 2 or
> more register resources.

The regions are fixed. The addresses are hard-wired.

> > +- eeprom-gpios : should point to active-low write enable GPIO
> 
> I'm curious: your driver doesn't actually utilize this binding. Is this
> intentional? Is it actually optional? (I note that the example DT below
> doesn't have this property...)

Thanks for noticing. It's an artifact of copy-paste. I'll drop this.

> > +++ b/arch/arm/configs/lp8x4x_defconfig
> > @@ -57,6 +57,7 @@ CONFIG_MTD_CFI_ADV_OPTIONS=y
> >  CONFIG_MTD_CFI_GEOMETRY=y
> >  CONFIG_MTD_CFI_INTELEXT=y
> >  CONFIG_MTD_PHYSMAP_OF=y
> > +CONFIG_MTD_SRAM_LP8X4X=y
> >  CONFIG_PROC_DEVICETREE=y
> >  CONFIG_BLK_DEV_LOOP=y
> >  CONFIG_BLK_DEV_LOOP_MIN_COUNT=2
> 
> I can't take the defconfig update via MTD; it will need to go via the
> appropriate ARM tree (arm-soc?). So this hunk needs to move to another
> patch.

Sure. I'll remove this chunk and put it into main device patch.

> > +	match = of_match_device(of_flash_match, &pdev->dev);
> > +	if (!match)
> > +		return -EINVAL;
> 
> Does this of_match_device() serve any particular purpose? Your driver
> already matches against these IDs, and you're not actually retrieving
> any of-data from the match, so this looks redundant.

Point taken, I'll drop this.

> > +
> > +	info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
> > +	if (!info)
> > +		return -ENOMEM;
> > +
> > +	res_virt = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > +	info->virt =  devm_ioremap_resource(&pdev->dev, res_virt);
> > +	if (IS_ERR(info->virt))
> > +		return PTR_ERR(info->virt);
> > +
> > +	res_bank = platform_get_resource(pdev, IORESOURCE_MEM, 1);
> > +	info->bank = devm_ioremap_resource(&pdev->dev, res_bank);
> > +	if (IS_ERR(info->bank))
> > +		return PTR_ERR(info->bank);
> > +
> > +	info->mtd.priv = info;
> > +	info->mtd.name = "SRAM";
> 
> Are you absolutely sure there is only ever a single SRAM device on a
> given system? Because otherwise, you will get redundantly-named MTD's.
> If the answer is no, you might consider a unique naming scheme.

Like .999999 sure. This one is hard-wired. There is no extension slots
to plug in any memory device.

I'll post a new version with the rest of the series. Thanks for
reviewing.


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

* Re: [PATCH v4 10/21] mtd: support BB SRAM on ICP DAS LP-8x4x
@ 2014-04-30 17:35                       ` ООО "ЭлектроПлюс"
  0 siblings, 0 replies; 700+ messages in thread
From: ООО "ЭлектроПлюс" @ 2014-04-30 17:35 UTC (permalink / raw)
  To: Brian Norris
  Cc: Mark Rutland, open list:OPEN FIRMWARE AND...,
	Heikki Krogerus, Russell King, open list:DOCUMENTATION,
	Pawel Moll, Ian Campbell, Lee Jones, Robert Jarzmik,
	Randy Dunlap, Artem Bityutskiy, linux-kernel, Michael Opdenacker,
	Rob Herring, open list:MEMORY TECHNOLOGY...,
	Kumar Gala, Grant Likely, David Woodhouse, linux-arm-kernel

Hi Brian,

On Wed, 2014-04-30 at 10:21 -0700, Brian Norris wrote:
> A few more small comments.
> 
> On Wed, Apr 16, 2014 at 09:17:15PM +0400, Sergei Ianovich wrote:
> > +++ b/Documentation/devicetree/bindings/mtd/sram-lp8x4x.txt
> > @@ -0,0 +1,22 @@
> > +512kB battery backed up SRAM on LP-8x4x industrial computers
> > +
> > +Required properties:
> > +- compatible : should be "icpdas,sram-lp8x4x"
> > +
> > +- reg: physical base addresses and region lengths of
> > +       * IO memory range
> > +       * SRAM page selector
> 
> Are these region types pretty static for this type of hardware? If not,
> it helps to have a reg-names property in the DT, when there are 2 or
> more register resources.

The regions are fixed. The addresses are hard-wired.

> > +- eeprom-gpios : should point to active-low write enable GPIO
> 
> I'm curious: your driver doesn't actually utilize this binding. Is this
> intentional? Is it actually optional? (I note that the example DT below
> doesn't have this property...)

Thanks for noticing. It's an artifact of copy-paste. I'll drop this.

> > +++ b/arch/arm/configs/lp8x4x_defconfig
> > @@ -57,6 +57,7 @@ CONFIG_MTD_CFI_ADV_OPTIONS=y
> >  CONFIG_MTD_CFI_GEOMETRY=y
> >  CONFIG_MTD_CFI_INTELEXT=y
> >  CONFIG_MTD_PHYSMAP_OF=y
> > +CONFIG_MTD_SRAM_LP8X4X=y
> >  CONFIG_PROC_DEVICETREE=y
> >  CONFIG_BLK_DEV_LOOP=y
> >  CONFIG_BLK_DEV_LOOP_MIN_COUNT=2
> 
> I can't take the defconfig update via MTD; it will need to go via the
> appropriate ARM tree (arm-soc?). So this hunk needs to move to another
> patch.

Sure. I'll remove this chunk and put it into main device patch.

> > +	match = of_match_device(of_flash_match, &pdev->dev);
> > +	if (!match)
> > +		return -EINVAL;
> 
> Does this of_match_device() serve any particular purpose? Your driver
> already matches against these IDs, and you're not actually retrieving
> any of-data from the match, so this looks redundant.

Point taken, I'll drop this.

> > +
> > +	info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
> > +	if (!info)
> > +		return -ENOMEM;
> > +
> > +	res_virt = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > +	info->virt =  devm_ioremap_resource(&pdev->dev, res_virt);
> > +	if (IS_ERR(info->virt))
> > +		return PTR_ERR(info->virt);
> > +
> > +	res_bank = platform_get_resource(pdev, IORESOURCE_MEM, 1);
> > +	info->bank = devm_ioremap_resource(&pdev->dev, res_bank);
> > +	if (IS_ERR(info->bank))
> > +		return PTR_ERR(info->bank);
> > +
> > +	info->mtd.priv = info;
> > +	info->mtd.name = "SRAM";
> 
> Are you absolutely sure there is only ever a single SRAM device on a
> given system? Because otherwise, you will get redundantly-named MTD's.
> If the answer is no, you might consider a unique naming scheme.

Like .999999 sure. This one is hard-wired. There is no extension slots
to plug in any memory device.

I'll post a new version with the rest of the series. Thanks for
reviewing.

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

* [PATCH v4 10/21] mtd: support BB SRAM on ICP DAS LP-8x4x
@ 2014-04-30 17:35                       ` ООО "ЭлектроПлюс"
  0 siblings, 0 replies; 700+ messages in thread
From: ООО "ЭлектроПлюс" @ 2014-04-30 17:35 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Brian,

On Wed, 2014-04-30 at 10:21 -0700, Brian Norris wrote:
> A few more small comments.
> 
> On Wed, Apr 16, 2014 at 09:17:15PM +0400, Sergei Ianovich wrote:
> > +++ b/Documentation/devicetree/bindings/mtd/sram-lp8x4x.txt
> > @@ -0,0 +1,22 @@
> > +512kB battery backed up SRAM on LP-8x4x industrial computers
> > +
> > +Required properties:
> > +- compatible : should be "icpdas,sram-lp8x4x"
> > +
> > +- reg: physical base addresses and region lengths of
> > +       * IO memory range
> > +       * SRAM page selector
> 
> Are these region types pretty static for this type of hardware? If not,
> it helps to have a reg-names property in the DT, when there are 2 or
> more register resources.

The regions are fixed. The addresses are hard-wired.

> > +- eeprom-gpios : should point to active-low write enable GPIO
> 
> I'm curious: your driver doesn't actually utilize this binding. Is this
> intentional? Is it actually optional? (I note that the example DT below
> doesn't have this property...)

Thanks for noticing. It's an artifact of copy-paste. I'll drop this.

> > +++ b/arch/arm/configs/lp8x4x_defconfig
> > @@ -57,6 +57,7 @@ CONFIG_MTD_CFI_ADV_OPTIONS=y
> >  CONFIG_MTD_CFI_GEOMETRY=y
> >  CONFIG_MTD_CFI_INTELEXT=y
> >  CONFIG_MTD_PHYSMAP_OF=y
> > +CONFIG_MTD_SRAM_LP8X4X=y
> >  CONFIG_PROC_DEVICETREE=y
> >  CONFIG_BLK_DEV_LOOP=y
> >  CONFIG_BLK_DEV_LOOP_MIN_COUNT=2
> 
> I can't take the defconfig update via MTD; it will need to go via the
> appropriate ARM tree (arm-soc?). So this hunk needs to move to another
> patch.

Sure. I'll remove this chunk and put it into main device patch.

> > +	match = of_match_device(of_flash_match, &pdev->dev);
> > +	if (!match)
> > +		return -EINVAL;
> 
> Does this of_match_device() serve any particular purpose? Your driver
> already matches against these IDs, and you're not actually retrieving
> any of-data from the match, so this looks redundant.

Point taken, I'll drop this.

> > +
> > +	info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
> > +	if (!info)
> > +		return -ENOMEM;
> > +
> > +	res_virt = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > +	info->virt =  devm_ioremap_resource(&pdev->dev, res_virt);
> > +	if (IS_ERR(info->virt))
> > +		return PTR_ERR(info->virt);
> > +
> > +	res_bank = platform_get_resource(pdev, IORESOURCE_MEM, 1);
> > +	info->bank = devm_ioremap_resource(&pdev->dev, res_bank);
> > +	if (IS_ERR(info->bank))
> > +		return PTR_ERR(info->bank);
> > +
> > +	info->mtd.priv = info;
> > +	info->mtd.name = "SRAM";
> 
> Are you absolutely sure there is only ever a single SRAM device on a
> given system? Because otherwise, you will get redundantly-named MTD's.
> If the answer is no, you might consider a unique naming scheme.

Like .999999 sure. This one is hard-wired. There is no extension slots
to plug in any memory device.

I'll post a new version with the rest of the series. Thanks for
reviewing.

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

* Re: [PATCH v4 01/21] serial: rewrite pxa2xx-uart to use 8250_core
  2014-04-16 17:13               ` Sergei Ianovich
  (?)
@ 2015-01-19 18:08                 ` Rob Herring
  -1 siblings, 0 replies; 700+ messages in thread
From: Rob Herring @ 2015-01-19 18:08 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: linux-kernel, linux-arm-kernel, Russell King, Greg Kroah-Hartman,
	Jiri Slaby, Grant Likely, Rob Herring, James Cameron,
	Heikki Krogerus, Paul Bolle, Arnd Bergmann, Randy Dunlap,
	Stefan Seyfried, open list:SERIAL DRIVERS,
	open list:OPEN FIRMWARE AND...

On Wed, Apr 16, 2014 at 12:13 PM, Sergei Ianovich <ynvich@gmail.com> wrote:
> pxa2xx-uart was a separate uart platform driver. It was declaring
> the same device names and numbers as 8250 driver. As a result,
> it was impossible to use 8250 driver on PXA SoCs.
>
> Upon closer examination pxa2xx-uart turned out to be a clone of
> 8250_core driver.
>
> Workaround for Erratum #19 according to Marvel(R) PXA270M Processor
> Specification Update (April 19, 2010) is dropped. 8250_core reads
> from FIFO immediately after checking DR bit in LSR.
>
> Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
> Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
> Reviewed-by: James Cameron <quozl@laptop.org>
> Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> ---
>  Resenging together with the rest of the series as the series
>  breaks without this one at [PATCH 12/21]

Whatever happened with merging this? I'm asking because either this or
fixes to PXA uart are needed to coexist with the 8250 driver and for
earlycon to work.

Rob

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

* Re: [PATCH v4 01/21] serial: rewrite pxa2xx-uart to use 8250_core
@ 2015-01-19 18:08                 ` Rob Herring
  0 siblings, 0 replies; 700+ messages in thread
From: Rob Herring @ 2015-01-19 18:08 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: linux-kernel, linux-arm-kernel, Russell King, Greg Kroah-Hartman,
	Jiri Slaby, Grant Likely, Rob Herring, James Cameron,
	Heikki Krogerus, Paul Bolle, Arnd Bergmann, Randy Dunlap,
	Stefan Seyfried, open list:SERIAL DRIVERS,
	open list:OPEN FIRMWARE AND...

On Wed, Apr 16, 2014 at 12:13 PM, Sergei Ianovich <ynvich@gmail.com> wrote:
> pxa2xx-uart was a separate uart platform driver. It was declaring
> the same device names and numbers as 8250 driver. As a result,
> it was impossible to use 8250 driver on PXA SoCs.
>
> Upon closer examination pxa2xx-uart turned out to be a clone of
> 8250_core driver.
>
> Workaround for Erratum #19 according to Marvel(R) PXA270M Processor
> Specification Update (April 19, 2010) is dropped. 8250_core reads
> from FIFO immediately after checking DR bit in LSR.
>
> Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
> Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
> Reviewed-by: James Cameron <quozl@laptop.org>
> Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> ---
>  Resenging together with the rest of the series as the series
>  breaks without this one at [PATCH 12/21]

Whatever happened with merging this? I'm asking because either this or
fixes to PXA uart are needed to coexist with the 8250 driver and for
earlycon to work.

Rob

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

* [PATCH v4 01/21] serial: rewrite pxa2xx-uart to use 8250_core
@ 2015-01-19 18:08                 ` Rob Herring
  0 siblings, 0 replies; 700+ messages in thread
From: Rob Herring @ 2015-01-19 18:08 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Apr 16, 2014 at 12:13 PM, Sergei Ianovich <ynvich@gmail.com> wrote:
> pxa2xx-uart was a separate uart platform driver. It was declaring
> the same device names and numbers as 8250 driver. As a result,
> it was impossible to use 8250 driver on PXA SoCs.
>
> Upon closer examination pxa2xx-uart turned out to be a clone of
> 8250_core driver.
>
> Workaround for Erratum #19 according to Marvel(R) PXA270M Processor
> Specification Update (April 19, 2010) is dropped. 8250_core reads
> from FIFO immediately after checking DR bit in LSR.
>
> Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
> Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
> Reviewed-by: James Cameron <quozl@laptop.org>
> Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> ---
>  Resenging together with the rest of the series as the series
>  breaks without this one at [PATCH 12/21]

Whatever happened with merging this? I'm asking because either this or
fixes to PXA uart are needed to coexist with the 8250 driver and for
earlycon to work.

Rob

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

* Re: [v4,09/21] rtc: support DS1302 RTC on ICP DAS LP-8x4x
  2014-04-16 17:17                   ` [v4,09/21] " Sergey Yanovich
@ 2015-06-08 12:07                     ` Alexandre Belloni
  -1 siblings, 0 replies; 700+ messages in thread
From: Alexandre Belloni @ 2015-06-08 12:07 UTC (permalink / raw)
  To: Sergey Yanovich
  Cc: linux-kernel, linux-arm-kernel, Kumar Gala, Randy Dunlap,
	Russell King, Alessandro Zummo, Grant Likely, Heikki Krogerus,
	open list:OPEN FIRMWARE AND...,
	open list:DOCUMENTATION, rtc-linux

Hi Sergey,

Are you still interested in seeing that patch going upstream?

On 16/04/2014 at 21:17:14 +0400, Sergey Yanovich wrote :
> Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
> ---
>    v3..v4
>    * move DTS bindings to a different patch (8/21)
> 
>    v2..v3
>    * use usleep_range instead of custom nsleep
>    * number change (07/16 -> 09/21)
> 
>    v0..v2
>    * use device tree
>    * use devm helpers where possible
> 
>  .../devicetree/bindings/rtc/rtc-ds1302.txt         |  14 +++
>  arch/arm/configs/lp8x4x_defconfig                  |   1 +
>  drivers/rtc/Kconfig                                |   2 +-
>  drivers/rtc/rtc-ds1302.c                           | 100 ++++++++++++++++++++-
>  4 files changed, 114 insertions(+), 3 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/rtc/rtc-ds1302.txt
> 
> diff --git a/Documentation/devicetree/bindings/rtc/rtc-ds1302.txt b/Documentation/devicetree/bindings/rtc/rtc-ds1302.txt
> new file mode 100644
> index 0000000..810613b
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/rtc/rtc-ds1302.txt
> @@ -0,0 +1,14 @@
> +* Dallas Semiconductor DS-1302 RTC
> +
> +Simple device which could be used to store date/time between reboots.
> +
> +Required properties:
> +- compatible : Should be "dallas,rtc-ds1302"
> +- reg : Should be address and size of IO memory region
> +
> +Examples:
> +
> +rtc@40900000 {
> +	compatible = "dallas,rtc-ds1302";
> +	reg = <0x1700901c 0x1>;
> +};
> diff --git a/arch/arm/configs/lp8x4x_defconfig b/arch/arm/configs/lp8x4x_defconfig
> index 9f1efb6..d60e37a 100644
> --- a/arch/arm/configs/lp8x4x_defconfig
> +++ b/arch/arm/configs/lp8x4x_defconfig
> @@ -141,6 +141,7 @@ CONFIG_LEDS_GPIO=y
>  CONFIG_LEDS_TRIGGERS=y
>  CONFIG_LEDS_TRIGGER_HEARTBEAT=y
>  CONFIG_RTC_CLASS=y
> +CONFIG_RTC_DRV_DS1302=y
>  CONFIG_RTC_DRV_PXA=m
>  # CONFIG_IOMMU_SUPPORT is not set
>  CONFIG_EXT2_FS=m
> diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
> index 2e565f8..80aaaa1 100644
> --- a/drivers/rtc/Kconfig
> +++ b/drivers/rtc/Kconfig
> @@ -710,7 +710,7 @@ config RTC_DRV_DS1286
>  
>  config RTC_DRV_DS1302
>  	tristate "Dallas DS1302"
> -	depends on SH_SECUREEDGE5410
> +	depends on SH_SECUREEDGE5410 || (ARCH_PXA && HIGH_RES_TIMERS)
>  	help
>  	  If you say yes here you get support for the Dallas DS1302 RTC chips.
>  
> diff --git a/drivers/rtc/rtc-ds1302.c b/drivers/rtc/rtc-ds1302.c
> index 07e8d79..3c49023 100644
> --- a/drivers/rtc/rtc-ds1302.c
> +++ b/drivers/rtc/rtc-ds1302.c
> @@ -50,7 +50,7 @@
>  #define ds1302_set_tx()
>  #define ds1302_set_rx()
>  
> -static inline int ds1302_hw_init(void)
> +static inline int ds1302_hw_init(struct platform_device *pdev)
>  {
>  	return 0;
>  }
> @@ -86,6 +86,101 @@ static inline int ds1302_rxbit(void)
>  	return !!(get_dp() & RTC_IODATA);
>  }
>  
> +#elif defined(CONFIG_ARCH_PXA) && defined(CONFIG_HIGH_RES_TIMERS)
> +
> +#include <linux/delay.h>
> +#include <linux/of.h>
> +
> +#define	RTC_CE		0x01
> +#define	RTC_CLK		0x02
> +#define	RTC_nWE		0x04
> +#define	RTC_IODATA	0x08
> +
> +static unsigned long ds1302_state;
> +
> +static void *mem;
> +
> +static inline int ds1302_hw_init(struct platform_device *pdev)
> +{
> +	struct resource *r;
> +
> +	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	if (!r)
> +		return -ENODEV;
> +
> +	mem = devm_ioremap_resource(&pdev->dev, r);
> +	if (!mem)
> +		return -EFAULT;
> +
> +	return 0;
> +}
> +
> +static inline void ds1302_reset(void)
> +{
> +	ds1302_state = 0;
> +	iowrite8(ds1302_state, mem);
> +	usleep_range(4, 5);
> +}
> +
> +static inline void ds1302_clock(void)
> +{
> +	usleep_range(1, 2);
> +	ds1302_state |= RTC_CLK;
> +	iowrite8(ds1302_state, mem);
> +	usleep_range(1, 2);
> +	ds1302_state &= ~RTC_CLK;
> +	iowrite8(ds1302_state, mem);
> +}
> +
> +static inline void ds1302_start(void)
> +{
> +	ds1302_state &= ~RTC_CLK;
> +	ds1302_state |= RTC_CE;
> +	iowrite8(ds1302_state, mem);
> +	usleep_range(3, 4);
> +}
> +
> +static inline void ds1302_stop(void)
> +{
> +	ds1302_state &= ~RTC_CE;
> +	iowrite8(ds1302_state, mem);
> +}
> +
> +static inline void ds1302_set_tx(void)
> +{
> +	ds1302_state &= ~RTC_nWE;
> +	iowrite8(ds1302_state, mem);
> +}
> +
> +static inline void ds1302_set_rx(void)
> +{
> +	ds1302_state |= RTC_nWE;
> +	iowrite8(ds1302_state, mem);
> +}
> +
> +static inline void ds1302_txbit(int bit)
> +{
> +	if (bit)
> +		ds1302_state |= RTC_IODATA;
> +	else
> +		ds1302_state &= ~RTC_IODATA;
> +	iowrite8(ds1302_state, mem);
> +}
> +
> +static inline int ds1302_rxbit(void)
> +{
> +	return ioread8(mem) & 0x1;
> +}
> +
> +#ifdef CONFIG_OF
> +static const struct of_device_id ds1302_dt_ids[] = {
> +	{ .compatible = "dallas,rtc-ds1302" },
> +	{ }
> +};
> +
> +MODULE_DEVICE_TABLE(of, ds1302_dt_ids);
> +#endif
> +
>  #else
>  #error "Add support for your platform"
>  #endif
> @@ -216,7 +311,7 @@ static int __init ds1302_rtc_probe(struct platform_device *pdev)
>  {
>  	struct rtc_device *rtc;
>  
> -	if (ds1302_hw_init()) {
> +	if (ds1302_hw_init(pdev)) {
>  		dev_err(&pdev->dev, "Failed to init communication channel");
>  		return -EINVAL;
>  	}
> @@ -245,6 +340,7 @@ static struct platform_driver ds1302_platform_driver = {
>  	.driver		= {
>  		.name	= DRV_NAME,
>  		.owner	= THIS_MODULE,
> +		.of_match_table = of_match_ptr(ds1302_dt_ids),
>  	},
>  };
>  

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

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

* [v4,09/21] rtc: support DS1302 RTC on ICP DAS LP-8x4x
@ 2015-06-08 12:07                     ` Alexandre Belloni
  0 siblings, 0 replies; 700+ messages in thread
From: Alexandre Belloni @ 2015-06-08 12:07 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Sergey,

Are you still interested in seeing that patch going upstream?

On 16/04/2014 at 21:17:14 +0400, Sergey Yanovich wrote :
> Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
> ---
>    v3..v4
>    * move DTS bindings to a different patch (8/21)
> 
>    v2..v3
>    * use usleep_range instead of custom nsleep
>    * number change (07/16 -> 09/21)
> 
>    v0..v2
>    * use device tree
>    * use devm helpers where possible
> 
>  .../devicetree/bindings/rtc/rtc-ds1302.txt         |  14 +++
>  arch/arm/configs/lp8x4x_defconfig                  |   1 +
>  drivers/rtc/Kconfig                                |   2 +-
>  drivers/rtc/rtc-ds1302.c                           | 100 ++++++++++++++++++++-
>  4 files changed, 114 insertions(+), 3 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/rtc/rtc-ds1302.txt
> 
> diff --git a/Documentation/devicetree/bindings/rtc/rtc-ds1302.txt b/Documentation/devicetree/bindings/rtc/rtc-ds1302.txt
> new file mode 100644
> index 0000000..810613b
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/rtc/rtc-ds1302.txt
> @@ -0,0 +1,14 @@
> +* Dallas Semiconductor DS-1302 RTC
> +
> +Simple device which could be used to store date/time between reboots.
> +
> +Required properties:
> +- compatible : Should be "dallas,rtc-ds1302"
> +- reg : Should be address and size of IO memory region
> +
> +Examples:
> +
> +rtc at 40900000 {
> +	compatible = "dallas,rtc-ds1302";
> +	reg = <0x1700901c 0x1>;
> +};
> diff --git a/arch/arm/configs/lp8x4x_defconfig b/arch/arm/configs/lp8x4x_defconfig
> index 9f1efb6..d60e37a 100644
> --- a/arch/arm/configs/lp8x4x_defconfig
> +++ b/arch/arm/configs/lp8x4x_defconfig
> @@ -141,6 +141,7 @@ CONFIG_LEDS_GPIO=y
>  CONFIG_LEDS_TRIGGERS=y
>  CONFIG_LEDS_TRIGGER_HEARTBEAT=y
>  CONFIG_RTC_CLASS=y
> +CONFIG_RTC_DRV_DS1302=y
>  CONFIG_RTC_DRV_PXA=m
>  # CONFIG_IOMMU_SUPPORT is not set
>  CONFIG_EXT2_FS=m
> diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
> index 2e565f8..80aaaa1 100644
> --- a/drivers/rtc/Kconfig
> +++ b/drivers/rtc/Kconfig
> @@ -710,7 +710,7 @@ config RTC_DRV_DS1286
>  
>  config RTC_DRV_DS1302
>  	tristate "Dallas DS1302"
> -	depends on SH_SECUREEDGE5410
> +	depends on SH_SECUREEDGE5410 || (ARCH_PXA && HIGH_RES_TIMERS)
>  	help
>  	  If you say yes here you get support for the Dallas DS1302 RTC chips.
>  
> diff --git a/drivers/rtc/rtc-ds1302.c b/drivers/rtc/rtc-ds1302.c
> index 07e8d79..3c49023 100644
> --- a/drivers/rtc/rtc-ds1302.c
> +++ b/drivers/rtc/rtc-ds1302.c
> @@ -50,7 +50,7 @@
>  #define ds1302_set_tx()
>  #define ds1302_set_rx()
>  
> -static inline int ds1302_hw_init(void)
> +static inline int ds1302_hw_init(struct platform_device *pdev)
>  {
>  	return 0;
>  }
> @@ -86,6 +86,101 @@ static inline int ds1302_rxbit(void)
>  	return !!(get_dp() & RTC_IODATA);
>  }
>  
> +#elif defined(CONFIG_ARCH_PXA) && defined(CONFIG_HIGH_RES_TIMERS)
> +
> +#include <linux/delay.h>
> +#include <linux/of.h>
> +
> +#define	RTC_CE		0x01
> +#define	RTC_CLK		0x02
> +#define	RTC_nWE		0x04
> +#define	RTC_IODATA	0x08
> +
> +static unsigned long ds1302_state;
> +
> +static void *mem;
> +
> +static inline int ds1302_hw_init(struct platform_device *pdev)
> +{
> +	struct resource *r;
> +
> +	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	if (!r)
> +		return -ENODEV;
> +
> +	mem = devm_ioremap_resource(&pdev->dev, r);
> +	if (!mem)
> +		return -EFAULT;
> +
> +	return 0;
> +}
> +
> +static inline void ds1302_reset(void)
> +{
> +	ds1302_state = 0;
> +	iowrite8(ds1302_state, mem);
> +	usleep_range(4, 5);
> +}
> +
> +static inline void ds1302_clock(void)
> +{
> +	usleep_range(1, 2);
> +	ds1302_state |= RTC_CLK;
> +	iowrite8(ds1302_state, mem);
> +	usleep_range(1, 2);
> +	ds1302_state &= ~RTC_CLK;
> +	iowrite8(ds1302_state, mem);
> +}
> +
> +static inline void ds1302_start(void)
> +{
> +	ds1302_state &= ~RTC_CLK;
> +	ds1302_state |= RTC_CE;
> +	iowrite8(ds1302_state, mem);
> +	usleep_range(3, 4);
> +}
> +
> +static inline void ds1302_stop(void)
> +{
> +	ds1302_state &= ~RTC_CE;
> +	iowrite8(ds1302_state, mem);
> +}
> +
> +static inline void ds1302_set_tx(void)
> +{
> +	ds1302_state &= ~RTC_nWE;
> +	iowrite8(ds1302_state, mem);
> +}
> +
> +static inline void ds1302_set_rx(void)
> +{
> +	ds1302_state |= RTC_nWE;
> +	iowrite8(ds1302_state, mem);
> +}
> +
> +static inline void ds1302_txbit(int bit)
> +{
> +	if (bit)
> +		ds1302_state |= RTC_IODATA;
> +	else
> +		ds1302_state &= ~RTC_IODATA;
> +	iowrite8(ds1302_state, mem);
> +}
> +
> +static inline int ds1302_rxbit(void)
> +{
> +	return ioread8(mem) & 0x1;
> +}
> +
> +#ifdef CONFIG_OF
> +static const struct of_device_id ds1302_dt_ids[] = {
> +	{ .compatible = "dallas,rtc-ds1302" },
> +	{ }
> +};
> +
> +MODULE_DEVICE_TABLE(of, ds1302_dt_ids);
> +#endif
> +
>  #else
>  #error "Add support for your platform"
>  #endif
> @@ -216,7 +311,7 @@ static int __init ds1302_rtc_probe(struct platform_device *pdev)
>  {
>  	struct rtc_device *rtc;
>  
> -	if (ds1302_hw_init()) {
> +	if (ds1302_hw_init(pdev)) {
>  		dev_err(&pdev->dev, "Failed to init communication channel");
>  		return -EINVAL;
>  	}
> @@ -245,6 +340,7 @@ static struct platform_driver ds1302_platform_driver = {
>  	.driver		= {
>  		.name	= DRV_NAME,
>  		.owner	= THIS_MODULE,
> +		.of_match_table = of_match_ptr(ds1302_dt_ids),
>  	},
>  };
>  

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

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

* Re: [v4,09/21] rtc: support DS1302 RTC on ICP DAS LP-8x4x
  2015-06-08 12:07                     ` Alexandre Belloni
  (?)
@ 2015-06-08 12:12                       ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2015-06-08 12:12 UTC (permalink / raw)
  To: Alexandre Belloni
  Cc: linux-kernel, linux-arm-kernel, Kumar Gala, Randy Dunlap,
	Russell King, Alessandro Zummo, Grant Likely, Heikki Krogerus,
	open list:OPEN FIRMWARE AND...,
	open list:DOCUMENTATION, rtc-linux

Hi Alexandre,

On Mon, 2015-06-08 at 14:07 +0200, Alexandre Belloni wrote:
> Are you still interested in seeing that patch going upstream?

Sure.


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

* [rtc-linux] Re: [v4,09/21] rtc: support DS1302 RTC on ICP DAS LP-8x4x
@ 2015-06-08 12:12                       ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2015-06-08 12:12 UTC (permalink / raw)
  To: Alexandre Belloni
  Cc: linux-kernel, linux-arm-kernel, Kumar Gala, Randy Dunlap,
	Russell King, Alessandro Zummo, Grant Likely, Heikki Krogerus,
	open list:OPEN FIRMWARE AND...,
	open list:DOCUMENTATION, rtc-linux

Hi Alexandre,

On Mon, 2015-06-08 at 14:07 +0200, Alexandre Belloni wrote:
> Are you still interested in seeing that patch going upstream?

Sure.

-- 
-- 
You received this message because you are subscribed to "rtc-linux".
Membership options at http://groups.google.com/group/rtc-linux .
Please read http://groups.google.com/group/rtc-linux/web/checklist
before submitting a driver.
--- 
You received this message because you are subscribed to the Google Groups "rtc-linux" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rtc-linux+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

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

* [v4,09/21] rtc: support DS1302 RTC on ICP DAS LP-8x4x
@ 2015-06-08 12:12                       ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2015-06-08 12:12 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Alexandre,

On Mon, 2015-06-08 at 14:07 +0200, Alexandre Belloni wrote:
> Are you still interested in seeing that patch going upstream?

Sure.

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

* [PATCH v4 0/2] series to support for ICP DAS LP-8x4x (ARM PXA270)
  2013-12-17 19:37           ` Sergei Ianovich
                             ` (22 preceding siblings ...)
  (?)
@ 2015-12-09 22:28           ` Sergei Ianovich
  2015-12-09 22:28               ` Sergei Ianovich
  2015-12-09 22:28               ` Sergei Ianovich
  -1 siblings, 2 replies; 700+ messages in thread
From: Sergei Ianovich @ 2015-12-09 22:28 UTC (permalink / raw)
  To: linux-kernel
  Cc: Sergei Ianovich, Daniel Mack, Arnd Bergmann, Robert Jarzmik,
	Haojian Zhuang

PXA device tree support has almost grown to the level when it becomes
possible to add device support without code changes. Thanks to everyone
involved.

The only obstacle with this device is character device major index
conflict between pxa serial and 8250 serial drivers. The first patch
fixes the conflict rewriting pxa serial using 8250 serial driver.

Device support is now close to 95%, pluggable module support is
at around 20%. It should be possible to handle most unsupported modules
by already working get_DI/DO/AO set_DO/AO functions. I am not including
support, since I didn't actually test the hardware. The same is true
about RS232/485 pluggable port.

ICP DAS calls LP-8x4x 'programmable automation controller'. It is
an industrial computer based on PXA270 SoC. They ship it with a 2.6.19
kernel and proprietary kernel module and userspace library to access
its industrial IO.

This patch allows to boot the device with a modern kernel with device
tree. It adds support for:
* MMC card interface on PXA270
* USB 1.1 port on PXA270
* 2 NOR flash devices
* 2 onboard ethernet Davicom DM9000 devices
* 3 serial UART ports on PXA270
* front panel red LED
* 64bit 1-wire system ID chip
* 16 kiB EEPROM (reading)

Support for the following devices will be added in separate patches,
since they are not currently supported by the kernel:
* DS1302 RTC
* 512kiB SRAM
* FPGA irq chip
* 3 built-in 16550A serial UART ports
* industrial IO parallel bus
* 10 position rotary switch
* 8 pin DIP switch
* 16 kiB EEPROM (writing)
* serial interface for digital and analog industrial IO modules on
  parallel bus (all I-87xxx modules)
* digital and analog industrial IO modules for parallel bus:
  ** I-8024 4 port analog output
  ** I-8041 32 port digital output
  ** I-8042 16 port digital output/16 port digital input

Not supported for now:
* VGA interface on PXA270 for lack of dts binding
* the rest of parallel bus (I-8xxx) modules for lack of hardware
* GPIO reset for lack of relevance (watchdog reset is working)

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Daniel Mack <zonque@gmail.com>
CC: Arnd Bergmann <arnd@arndb.de>
CC: Robert Jarzmik <robert.jarzmik@free.fr>
CC: Haojian Zhuang <haojian.zhuang@gmail.com>

Sergei Ianovich (2):
  serial: rewrite pxa2xx-uart to use 8250_core
  arm: pxa27x: support for ICP DAS LP-8x4x w/ DT

 .../devicetree/bindings/vendor-prefixes.txt        |   1 +
 arch/arm/boot/dts/Makefile                         |   3 +
 arch/arm/boot/dts/pxa27x-lp8x4x-i105.dts           |  50 ++
 arch/arm/boot/dts/pxa27x-lp8x4x.dts                | 260 ++++++
 arch/arm/configs/am200epdkit_defconfig             |   5 +-
 arch/arm/configs/cm_x2xx_defconfig                 |   5 +-
 arch/arm/configs/cm_x300_defconfig                 |   5 +-
 arch/arm/configs/colibri_pxa270_defconfig          |   5 +-
 arch/arm/configs/colibri_pxa300_defconfig          |   5 +-
 arch/arm/configs/corgi_defconfig                   |   6 +-
 arch/arm/configs/em_x270_defconfig                 |   5 +-
 arch/arm/configs/ezx_defconfig                     |   5 +-
 arch/arm/configs/h5000_defconfig                   |   5 +-
 arch/arm/configs/imote2_defconfig                  |   5 +-
 arch/arm/configs/lp8x4x_defconfig                  | 176 ++++
 arch/arm/configs/lpd270_defconfig                  |   5 +-
 arch/arm/configs/lubbock_defconfig                 |   5 +-
 arch/arm/configs/mainstone_defconfig               |   5 +-
 arch/arm/configs/mmp2_defconfig                    |   5 +-
 arch/arm/configs/pcm027_defconfig                  |   5 +-
 arch/arm/configs/pxa168_defconfig                  |   5 +-
 arch/arm/configs/pxa255-idp_defconfig              |   5 +-
 arch/arm/configs/pxa3xx_defconfig                  |   5 +-
 arch/arm/configs/pxa910_defconfig                  |   5 +-
 arch/arm/configs/raumfeld_defconfig                |   5 +-
 arch/arm/configs/spitz_defconfig                   |   6 +-
 arch/arm/configs/trizeps4_defconfig                |   5 +-
 arch/arm/configs/viper_defconfig                   |   6 +-
 arch/arm/configs/xcep_defconfig                    |   5 +-
 drivers/tty/serial/8250/8250_pxa.c                 | 177 ++++
 drivers/tty/serial/8250/Kconfig                    |   9 +
 drivers/tty/serial/8250/Makefile                   |   1 +
 drivers/tty/serial/Kconfig                         |  23 -
 drivers/tty/serial/Makefile                        |   1 -
 drivers/tty/serial/pxa.c                           | 968 ---------------------
 35 files changed, 749 insertions(+), 1043 deletions(-)
 create mode 100644 arch/arm/boot/dts/pxa27x-lp8x4x-i105.dts
 create mode 100644 arch/arm/boot/dts/pxa27x-lp8x4x.dts
 create mode 100644 arch/arm/configs/lp8x4x_defconfig
 create mode 100644 drivers/tty/serial/8250/8250_pxa.c
 delete mode 100644 drivers/tty/serial/pxa.c

-- 
2.6.2


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

* [PATCH v4 1/2] serial: rewrite pxa2xx-uart to use 8250_core
  2015-12-09 22:28           ` [PATCH v4 0/2] series to support for ICP DAS LP-8x4x (ARM PXA270) Sergei Ianovich
  2015-12-09 22:28               ` Sergei Ianovich
@ 2015-12-09 22:28               ` Sergei Ianovich
  1 sibling, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2015-12-09 22:28 UTC (permalink / raw)
  To: linux-kernel
  Cc: Sergei Ianovich, Russell King, Greg Kroah-Hartman, Jiri Slaby,
	Heikki Krogerus, James Cameron, Alexandre Belloni,
	Robert Jarzmik, Rob Herring, Ulf Hansson, Rafael J. Wysocki,
	Kevin Hilman, Andy Shevchenko, Arnd Bergmann, Paul Gortmaker,
	Scott Wood, Sebastian Andrzej Siewior, Paul Burton,
	Joachim Eastwood, Mans Rullgard, Masahiro Yamada, Peter Hurley,
	moderated list:ARM PORT, open list:SERIAL DRIVERS

pxa2xx-uart was a separate uart platform driver. It was declaring
the same device names and numbers as 8250 driver. As a result,
it was impossible to use 8250 driver on PXA SoCs.

Upon closer examination pxa2xx-uart turned out to be a clone of
8250_core driver.

Workaround for Erratum #19 according to Marvel(R) PXA270M Processor
Specification Update (April 19, 2010) is dropped. 8250_core reads
from FIFO immediately after checking DR bit in LSR.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Reviewed-by: James Cameron <quozl@laptop.org>
Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 The patch was reviewed/acked at version 3. Changes in version 4
 are simple unbitrotting, so the flags are carried over.

 changes v3..v4
 * remove owner field from platform_driver structure
 * make of_device_id structure constant
 * use CONFIG_SERIAL_8250_PXA instead of CONFIG_SERIAL_PXA

 changes v2..v3
 * remove devm_free/put as suggested by Heikki Krogerus
 * use SET_SYSTEM_SLEEP_PM_OPS macro to set pm ops as suggested
   by Heikki Krogerus

 changes v1..v2
 * actually implement workaround for E74 in dl_write as spooted
   by James Cameron
 * added comment about E19 in commit message

 arch/arm/configs/am200epdkit_defconfig    |   5 +-
 arch/arm/configs/cm_x2xx_defconfig        |   5 +-
 arch/arm/configs/cm_x300_defconfig        |   5 +-
 arch/arm/configs/colibri_pxa270_defconfig |   5 +-
 arch/arm/configs/colibri_pxa300_defconfig |   5 +-
 arch/arm/configs/corgi_defconfig          |   6 +-
 arch/arm/configs/em_x270_defconfig        |   5 +-
 arch/arm/configs/ezx_defconfig            |   5 +-
 arch/arm/configs/h5000_defconfig          |   5 +-
 arch/arm/configs/imote2_defconfig         |   5 +-
 arch/arm/configs/lpd270_defconfig         |   5 +-
 arch/arm/configs/lubbock_defconfig        |   5 +-
 arch/arm/configs/mainstone_defconfig      |   5 +-
 arch/arm/configs/mmp2_defconfig           |   5 +-
 arch/arm/configs/pcm027_defconfig         |   5 +-
 arch/arm/configs/pxa168_defconfig         |   5 +-
 arch/arm/configs/pxa255-idp_defconfig     |   5 +-
 arch/arm/configs/pxa3xx_defconfig         |   5 +-
 arch/arm/configs/pxa910_defconfig         |   5 +-
 arch/arm/configs/raumfeld_defconfig       |   5 +-
 arch/arm/configs/spitz_defconfig          |   6 +-
 arch/arm/configs/trizeps4_defconfig       |   5 +-
 arch/arm/configs/viper_defconfig          |   6 +-
 arch/arm/configs/xcep_defconfig           |   5 +-
 drivers/tty/serial/8250/8250_pxa.c        | 177 ++++++
 drivers/tty/serial/8250/Kconfig           |   9 +
 drivers/tty/serial/8250/Makefile          |   1 +
 drivers/tty/serial/Kconfig                |  23 -
 drivers/tty/serial/Makefile               |   1 -
 drivers/tty/serial/pxa.c                  | 968 ------------------------------
 30 files changed, 259 insertions(+), 1043 deletions(-)
 create mode 100644 drivers/tty/serial/8250/8250_pxa.c
 delete mode 100644 drivers/tty/serial/pxa.c

diff --git a/arch/arm/configs/am200epdkit_defconfig b/arch/arm/configs/am200epdkit_defconfig
index f0dea52..5f78ee7 100644
--- a/arch/arm/configs/am200epdkit_defconfig
+++ b/arch/arm/configs/am200epdkit_defconfig
@@ -60,8 +60,9 @@ CONFIG_BLK_DEV_IDECS=m
 CONFIG_NETDEVICES=y
 CONFIG_NET_ETHERNET=y
 CONFIG_SMC91X=m
-CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PXA=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 # CONFIG_HWMON is not set
diff --git a/arch/arm/configs/cm_x2xx_defconfig b/arch/arm/configs/cm_x2xx_defconfig
index 3b32d5f..f1ae370 100644
--- a/arch/arm/configs/cm_x2xx_defconfig
+++ b/arch/arm/configs/cm_x2xx_defconfig
@@ -96,8 +96,9 @@ CONFIG_KEYBOARD_PXA27x=m
 CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_TOUCHSCREEN_UCB1400=m
 # CONFIG_SERIO_SERPORT is not set
-CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PXA=y
 CONFIG_LEGACY_PTY_COUNT=16
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/cm_x300_defconfig b/arch/arm/configs/cm_x300_defconfig
index 7df040e..07bf9b2 100644
--- a/arch/arm/configs/cm_x300_defconfig
+++ b/arch/arm/configs/cm_x300_defconfig
@@ -80,8 +80,9 @@ CONFIG_TOUCHSCREEN_WM97XX=m
 # CONFIG_TOUCHSCREEN_WM9713 is not set
 # CONFIG_SERIO is not set
 # CONFIG_LEGACY_PTYS is not set
-CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PXA=y
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
 CONFIG_I2C_PXA=y
diff --git a/arch/arm/configs/colibri_pxa270_defconfig b/arch/arm/configs/colibri_pxa270_defconfig
index 18c311a..5ea17d4 100644
--- a/arch/arm/configs/colibri_pxa270_defconfig
+++ b/arch/arm/configs/colibri_pxa270_defconfig
@@ -103,8 +103,9 @@ CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=m
 CONFIG_SERIO_LIBPS2=y
-CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PXA=y
 CONFIG_HW_RANDOM=y
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
diff --git a/arch/arm/configs/colibri_pxa300_defconfig b/arch/arm/configs/colibri_pxa300_defconfig
index be02fe2..e12af54 100644
--- a/arch/arm/configs/colibri_pxa300_defconfig
+++ b/arch/arm/configs/colibri_pxa300_defconfig
@@ -31,8 +31,9 @@ CONFIG_INPUT_EVDEV=y
 # CONFIG_INPUT_MOUSE is not set
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_GPIO_ROTARY_ENCODER=y
-CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PXA=y
 CONFIG_HW_RANDOM=y
 CONFIG_DEBUG_GPIO=y
 # CONFIG_HWMON is not set
diff --git a/arch/arm/configs/corgi_defconfig b/arch/arm/configs/corgi_defconfig
index c1470a0..d94212b 100644
--- a/arch/arm/configs/corgi_defconfig
+++ b/arch/arm/configs/corgi_defconfig
@@ -131,10 +131,10 @@ CONFIG_TOUCHSCREEN_ADS7846=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=m
 # CONFIG_SERIO is not set
-CONFIG_SERIAL_8250=m
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_CS=m
-CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_8250_PXA=y
 # CONFIG_LEGACY_PTYS is not set
 CONFIG_I2C=y
 CONFIG_I2C_PXA=y
diff --git a/arch/arm/configs/em_x270_defconfig b/arch/arm/configs/em_x270_defconfig
index 8e10df7..8ac6b84 100644
--- a/arch/arm/configs/em_x270_defconfig
+++ b/arch/arm/configs/em_x270_defconfig
@@ -90,8 +90,9 @@ CONFIG_TOUCHSCREEN_WM97XX=m
 # CONFIG_TOUCHSCREEN_WM9705 is not set
 # CONFIG_TOUCHSCREEN_WM9713 is not set
 # CONFIG_SERIO_SERPORT is not set
-CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PXA=y
 CONFIG_LEGACY_PTY_COUNT=16
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/ezx_defconfig b/arch/arm/configs/ezx_defconfig
index ea316c4..5d365f4 100644
--- a/arch/arm/configs/ezx_defconfig
+++ b/arch/arm/configs/ezx_defconfig
@@ -214,8 +214,9 @@ CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=y
 CONFIG_INPUT_PCAP=y
 # CONFIG_SERIO is not set
-CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PXA=y
 CONFIG_LEGACY_PTY_COUNT=8
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/h5000_defconfig b/arch/arm/configs/h5000_defconfig
index 37903e3..d366c87 100644
--- a/arch/arm/configs/h5000_defconfig
+++ b/arch/arm/configs/h5000_defconfig
@@ -47,8 +47,9 @@ CONFIG_MTD_PHYSMAP=y
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
-CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PXA=y
 CONFIG_LEGACY_PTY_COUNT=32
 # CONFIG_HW_RANDOM is not set
 # CONFIG_HWMON is not set
diff --git a/arch/arm/configs/imote2_defconfig b/arch/arm/configs/imote2_defconfig
index 18e59fe..0cc503b 100644
--- a/arch/arm/configs/imote2_defconfig
+++ b/arch/arm/configs/imote2_defconfig
@@ -192,8 +192,9 @@ CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=y
 # CONFIG_SERIO is not set
-CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PXA=y
 CONFIG_LEGACY_PTY_COUNT=8
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/lpd270_defconfig b/arch/arm/configs/lpd270_defconfig
index 1c8c9ee..7774fb2 100644
--- a/arch/arm/configs/lpd270_defconfig
+++ b/arch/arm/configs/lpd270_defconfig
@@ -38,8 +38,9 @@ CONFIG_SMC91X=y
 CONFIG_INPUT_EVDEV=y
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO_SERPORT is not set
-CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PXA=y
 # CONFIG_HW_RANDOM is not set
 CONFIG_FB=y
 CONFIG_FB_PXA=y
diff --git a/arch/arm/configs/lubbock_defconfig b/arch/arm/configs/lubbock_defconfig
index c4ba274..d2c18e6 100644
--- a/arch/arm/configs/lubbock_defconfig
+++ b/arch/arm/configs/lubbock_defconfig
@@ -37,8 +37,9 @@ CONFIG_PCMCIA_PCNET=y
 CONFIG_INPUT_EVDEV=y
 # CONFIG_SERIO_SERPORT is not set
 CONFIG_SERIO_SA1111=y
-CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PXA=y
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_USB_GADGET=y
 CONFIG_USB_G_SERIAL=m
diff --git a/arch/arm/configs/mainstone_defconfig b/arch/arm/configs/mainstone_defconfig
index 04efa1b..ece034c 100644
--- a/arch/arm/configs/mainstone_defconfig
+++ b/arch/arm/configs/mainstone_defconfig
@@ -34,8 +34,9 @@ CONFIG_SMC91X=y
 CONFIG_INPUT_EVDEV=y
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO_SERPORT is not set
-CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PXA=y
 CONFIG_FB=y
 CONFIG_FB_PXA=y
 # CONFIG_VGA_CONSOLE is not set
diff --git a/arch/arm/configs/mmp2_defconfig b/arch/arm/configs/mmp2_defconfig
index f1cb95e..a56f2a0 100644
--- a/arch/arm/configs/mmp2_defconfig
+++ b/arch/arm/configs/mmp2_defconfig
@@ -44,8 +44,9 @@ CONFIG_SMC91X=y
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
-CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PXA=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/pcm027_defconfig b/arch/arm/configs/pcm027_defconfig
index b5624e3..93bc85c 100644
--- a/arch/arm/configs/pcm027_defconfig
+++ b/arch/arm/configs/pcm027_defconfig
@@ -60,8 +60,9 @@ CONFIG_SMC91X=y
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
-CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PXA=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/pxa168_defconfig b/arch/arm/configs/pxa168_defconfig
index 74d7e01..8dc8a99 100644
--- a/arch/arm/configs/pxa168_defconfig
+++ b/arch/arm/configs/pxa168_defconfig
@@ -40,8 +40,9 @@ CONFIG_SMC91X=y
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
-CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PXA=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 # CONFIG_HWMON is not set
diff --git a/arch/arm/configs/pxa255-idp_defconfig b/arch/arm/configs/pxa255-idp_defconfig
index 917a070b..688578d 100644
--- a/arch/arm/configs/pxa255-idp_defconfig
+++ b/arch/arm/configs/pxa255-idp_defconfig
@@ -35,8 +35,9 @@ CONFIG_SMC91X=y
 CONFIG_INPUT_EVDEV=y
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO_SERPORT is not set
-CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PXA=y
 CONFIG_FB=y
 CONFIG_FB_PXA=y
 # CONFIG_VGA_CONSOLE is not set
diff --git a/arch/arm/configs/pxa3xx_defconfig b/arch/arm/configs/pxa3xx_defconfig
index 5f337d7..1dedeaf 100644
--- a/arch/arm/configs/pxa3xx_defconfig
+++ b/arch/arm/configs/pxa3xx_defconfig
@@ -56,8 +56,9 @@ CONFIG_KEYBOARD_PXA27x=y
 CONFIG_KEYBOARD_PXA930_ROTARY=y
 CONFIG_MOUSE_PXA930_TRKBALL=y
 CONFIG_INPUT_TOUCHSCREEN=y
-CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PXA=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/pxa910_defconfig b/arch/arm/configs/pxa910_defconfig
index 3bb7771..9be8045 100644
--- a/arch/arm/configs/pxa910_defconfig
+++ b/arch/arm/configs/pxa910_defconfig
@@ -40,8 +40,9 @@ CONFIG_SMC91X=y
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
-CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PXA=y
 CONFIG_SPI=y
 CONFIG_FB=y
 CONFIG_MMP_DISP=y
diff --git a/arch/arm/configs/raumfeld_defconfig b/arch/arm/configs/raumfeld_defconfig
index 3d833ae..b4c23e3 100644
--- a/arch/arm/configs/raumfeld_defconfig
+++ b/arch/arm/configs/raumfeld_defconfig
@@ -67,8 +67,9 @@ CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_TOUCHSCREEN_EETI=m
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_GPIO_ROTARY_ENCODER=y
-CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PXA=y
 CONFIG_HW_RANDOM=y
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
diff --git a/arch/arm/configs/spitz_defconfig b/arch/arm/configs/spitz_defconfig
index a1ede19..fb07d0b 100644
--- a/arch/arm/configs/spitz_defconfig
+++ b/arch/arm/configs/spitz_defconfig
@@ -128,10 +128,10 @@ CONFIG_TOUCHSCREEN_ADS7846=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=m
 # CONFIG_SERIO is not set
-CONFIG_SERIAL_8250=m
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_CS=m
-CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_8250_PXA=y
 # CONFIG_LEGACY_PTYS is not set
 CONFIG_SPI=y
 CONFIG_SPI_PXA2XX=y
diff --git a/arch/arm/configs/trizeps4_defconfig b/arch/arm/configs/trizeps4_defconfig
index 4bc8700..cbd0226 100644
--- a/arch/arm/configs/trizeps4_defconfig
+++ b/arch/arm/configs/trizeps4_defconfig
@@ -132,8 +132,9 @@ CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=m
 CONFIG_SERIO_LIBPS2=y
-CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PXA=y
 CONFIG_HW_RANDOM=y
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
diff --git a/arch/arm/configs/viper_defconfig b/arch/arm/configs/viper_defconfig
index 0d717a5..6e5ca7e 100644
--- a/arch/arm/configs/viper_defconfig
+++ b/arch/arm/configs/viper_defconfig
@@ -101,11 +101,11 @@ CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=m
 # CONFIG_CONSOLE_TRANSLATIONS is not set
 # CONFIG_VT_CONSOLE is not set
-CONFIG_SERIAL_8250=m
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_NR_UARTS=5
 CONFIG_SERIAL_8250_RUNTIME_UARTS=5
-CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_8250_PXA=y
 # CONFIG_LEGACY_PTYS is not set
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
diff --git a/arch/arm/configs/xcep_defconfig b/arch/arm/configs/xcep_defconfig
index 721832f..007967a 100644
--- a/arch/arm/configs/xcep_defconfig
+++ b/arch/arm/configs/xcep_defconfig
@@ -60,8 +60,9 @@ CONFIG_NET_ETHERNET=y
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
 # CONFIG_DEVKMEM is not set
-CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PXA=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=m
diff --git a/drivers/tty/serial/8250/8250_pxa.c b/drivers/tty/serial/8250/8250_pxa.c
new file mode 100644
index 0000000..6a14df0
--- /dev/null
+++ b/drivers/tty/serial/8250/8250_pxa.c
@@ -0,0 +1,177 @@
+/*
+ *  drivers/tty/serial/8250/8250_pxa.c -- driver for PXA on-board UARTS
+ *  Copyright:	(C) 2013 Sergei Ianovich <ynvich@gmail.com>
+ *
+ *  replaces drivers/serial/pxa.c by Nicolas Pitre
+ *  Created:	Feb 20, 2003
+ *  Copyright:	(C) 2003 Monta Vista Software, Inc.
+ *
+ *  Based on drivers/serial/8250.c by Russell King.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/serial_8250.h>
+#include <linux/serial_core.h>
+#include <linux/serial_reg.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
+#include <linux/pm_runtime.h>
+
+#include "8250.h"
+
+struct pxa8250_data {
+	int			line;
+	struct clk		*clk;
+};
+
+#ifdef CONFIG_PM
+static int serial_pxa_suspend(struct device *dev)
+{
+	struct pxa8250_data *data = dev_get_drvdata(dev);
+
+	serial8250_suspend_port(data->line);
+
+	return 0;
+}
+
+static int serial_pxa_resume(struct device *dev)
+{
+	struct pxa8250_data *data = dev_get_drvdata(dev);
+
+	serial8250_resume_port(data->line);
+
+	return 0;
+}
+#endif
+
+static const struct dev_pm_ops serial_pxa_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(serial_pxa_suspend, serial_pxa_resume)
+};
+
+static const struct of_device_id serial_pxa_dt_ids[] = {
+	{ .compatible = "mrvl,pxa-uart", },
+	{ .compatible = "mrvl,mmp-uart", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, serial_pxa_dt_ids);
+
+/* Uart divisor latch write */
+static void serial_pxa_dl_write(struct uart_8250_port *up, int value)
+{
+	unsigned int dll;
+
+	serial_out(up, UART_DLL, value & 0xff);
+	/*
+	 * work around Erratum #74 according to Marvel(R) PXA270M Processor
+	 * Specification Update (April 19, 2010)
+	 */
+	dll = serial_in(up, UART_DLL);
+	WARN_ON(dll != (value & 0xff));
+
+	serial_out(up, UART_DLM, value >> 8 & 0xff);
+}
+
+
+static void serial_pxa_pm(struct uart_port *port, unsigned int state,
+	      unsigned int oldstate)
+{
+	struct pxa8250_data *data = port->private_data;
+
+	if (!state)
+		clk_prepare_enable(data->clk);
+	else
+		clk_disable_unprepare(data->clk);
+}
+
+static int serial_pxa_probe(struct platform_device *pdev)
+{
+	struct uart_8250_port uart = {};
+	struct pxa8250_data *data;
+	struct resource *mmres, *irqres;
+	int ret;
+
+	mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	irqres = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!mmres || !irqres)
+		return -ENODEV;
+
+	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(data->clk))
+		return PTR_ERR(data->clk);
+
+	ret = clk_prepare(data->clk);
+	if (ret)
+		return ret;
+
+	uart.port.type = PORT_XSCALE;
+	uart.port.iotype = UPIO_MEM32;
+	uart.port.mapbase = mmres->start;
+	uart.port.regshift = 2;
+	uart.port.irq = irqres->start;
+	uart.port.fifosize = 64;
+	uart.port.flags = UPF_IOREMAP | UPF_SKIP_TEST;
+	uart.port.dev = &pdev->dev;
+	uart.port.uartclk = clk_get_rate(data->clk);
+	uart.port.pm = serial_pxa_pm;
+	uart.port.private_data = data;
+	uart.dl_write = serial_pxa_dl_write;
+
+	ret = serial8250_register_8250_port(&uart);
+	if (ret < 0)
+		goto err_clk;
+
+	data->line = ret;
+
+	platform_set_drvdata(pdev, data);
+
+	return 0;
+
+ err_clk:
+	clk_unprepare(data->clk);
+	return ret;
+}
+
+static int serial_pxa_remove(struct platform_device *pdev)
+{
+	struct pxa8250_data *data = platform_get_drvdata(pdev);
+
+	serial8250_unregister_port(data->line);
+
+	clk_unprepare(data->clk);
+
+	return 0;
+}
+
+static struct platform_driver serial_pxa_driver = {
+	.probe          = serial_pxa_probe,
+	.remove         = serial_pxa_remove,
+
+	.driver		= {
+		.name	= "pxa2xx-uart",
+		.pm	= &serial_pxa_pm_ops,
+		.of_match_table = serial_pxa_dt_ids,
+	},
+};
+
+module_platform_driver(serial_pxa_driver);
+
+MODULE_AUTHOR("Sergei Ianovich");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:pxa2xx-uart");
diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
index 6412f14..48b6253 100644
--- a/drivers/tty/serial/8250/Kconfig
+++ b/drivers/tty/serial/8250/Kconfig
@@ -378,3 +378,12 @@ config SERIAL_8250_MID
 	  Selecting this option will enable handling of the extra features
 	  present on the UART found on Intel Medfield SOC and various other
 	  Intel platforms.
+
+config SERIAL_8250_PXA
+	tristate "PXA serial port support"
+	depends on SERIAL_8250 && (ARCH_PXA || ARCH_MMP)
+	help
+	  If you have a machine based on an Intel XScale PXA2xx CPU you
+	  can enable its onboard serial ports by enabling this option.
+
+	  If you choose M here, the module name will be 8250_pxa.
diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile
index e177f86..7e54413 100644
--- a/drivers/tty/serial/8250/Makefile
+++ b/drivers/tty/serial/8250/Makefile
@@ -28,5 +28,6 @@ obj-$(CONFIG_SERIAL_8250_MT6577)	+= 8250_mtk.o
 obj-$(CONFIG_SERIAL_8250_UNIPHIER)	+= 8250_uniphier.o
 obj-$(CONFIG_SERIAL_8250_INGENIC)	+= 8250_ingenic.o
 obj-$(CONFIG_SERIAL_8250_MID)		+= 8250_mid.o
+obj-$(CONFIG_SERIAL_8250_PXA)		+= 8250_pxa.o
 
 CFLAGS_8250_ingenic.o += -I$(srctree)/scripts/dtc/libfdt
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index f38beb2..8c40c83 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -435,29 +435,6 @@ config SERIAL_MPSC_CONSOLE
 	help
 	  Say Y here if you want to support a serial console on a Marvell MPSC.
 
-config SERIAL_PXA
-	bool "PXA serial port support"
-	depends on ARCH_PXA || ARCH_MMP
-	select SERIAL_CORE
-	help
-	  If you have a machine based on an Intel XScale PXA2xx CPU you
-	  can enable its onboard serial ports by enabling this option.
-
-config SERIAL_PXA_CONSOLE
-	bool "Console on PXA serial port"
-	depends on SERIAL_PXA
-	select SERIAL_CORE_CONSOLE
-	help
-	  If you have enabled the serial port on the Intel XScale PXA
-	  CPU you can make it the console by answering Y to this option.
-
-	  Even if you say Y here, the currently visible virtual console
-	  (/dev/tty0) will still be used as the system console by default, but
-	  you can alter that using a kernel command line option such as
-	  "console=ttySA0". (Try "man bootparam" or see the documentation of
-	  your boot loader (lilo or loadlin) about how to pass options to the
-	  kernel at boot time.)
-
 config SERIAL_SA1100
 	bool "SA1100 serial port support"
 	depends on ARCH_SA1100
diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile
index 5ab4111..5cd5c68 100644
--- a/drivers/tty/serial/Makefile
+++ b/drivers/tty/serial/Makefile
@@ -23,7 +23,6 @@ obj-$(CONFIG_SERIAL_8250) += 8250/
 obj-$(CONFIG_SERIAL_AMBA_PL010) += amba-pl010.o
 obj-$(CONFIG_SERIAL_AMBA_PL011) += amba-pl011.o
 obj-$(CONFIG_SERIAL_CLPS711X) += clps711x.o
-obj-$(CONFIG_SERIAL_PXA) += pxa.o
 obj-$(CONFIG_SERIAL_PNX8XXX) += pnx8xxx_uart.o
 obj-$(CONFIG_SERIAL_SA1100) += sa1100.o
 obj-$(CONFIG_SERIAL_BCM63XX) += bcm63xx_uart.o
diff --git a/drivers/tty/serial/pxa.c b/drivers/tty/serial/pxa.c
deleted file mode 100644
index 9becba6..0000000
--- a/drivers/tty/serial/pxa.c
+++ /dev/null
@@ -1,968 +0,0 @@
-/*
- *  Based on drivers/serial/8250.c by Russell King.
- *
- *  Author:	Nicolas Pitre
- *  Created:	Feb 20, 2003
- *  Copyright:	(C) 2003 Monta Vista Software, Inc.
- *
- * 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.
- *
- * Note 1: This driver is made separate from the already too overloaded
- * 8250.c because it needs some kirks of its own and that'll make it
- * easier to add DMA support.
- *
- * Note 2: I'm too sick of device allocation policies for serial ports.
- * If someone else wants to request an "official" allocation of major/minor
- * for this driver please be my guest.  And don't forget that new hardware
- * to come from Intel might have more than 3 or 4 of those UARTs.  Let's
- * hope for a better port registration and dynamic device allocation scheme
- * with the serial core maintainer satisfaction to appear soon.
- */
-
-
-#if defined(CONFIG_SERIAL_PXA_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-#define SUPPORT_SYSRQ
-#endif
-
-#include <linux/module.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-#include <linux/console.h>
-#include <linux/sysrq.h>
-#include <linux/serial_reg.h>
-#include <linux/circ_buf.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/of.h>
-#include <linux/platform_device.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/serial_core.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-
-#define PXA_NAME_LEN		8
-
-struct uart_pxa_port {
-	struct uart_port        port;
-	unsigned char           ier;
-	unsigned char           lcr;
-	unsigned char           mcr;
-	unsigned int            lsr_break_flag;
-	struct clk		*clk;
-	char			name[PXA_NAME_LEN];
-};
-
-static inline unsigned int serial_in(struct uart_pxa_port *up, int offset)
-{
-	offset <<= 2;
-	return readl(up->port.membase + offset);
-}
-
-static inline void serial_out(struct uart_pxa_port *up, int offset, int value)
-{
-	offset <<= 2;
-	writel(value, up->port.membase + offset);
-}
-
-static void serial_pxa_enable_ms(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	up->ier |= UART_IER_MSI;
-	serial_out(up, UART_IER, up->ier);
-}
-
-static void serial_pxa_stop_tx(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	if (up->ier & UART_IER_THRI) {
-		up->ier &= ~UART_IER_THRI;
-		serial_out(up, UART_IER, up->ier);
-	}
-}
-
-static void serial_pxa_stop_rx(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	up->ier &= ~UART_IER_RLSI;
-	up->port.read_status_mask &= ~UART_LSR_DR;
-	serial_out(up, UART_IER, up->ier);
-}
-
-static inline void receive_chars(struct uart_pxa_port *up, int *status)
-{
-	unsigned int ch, flag;
-	int max_count = 256;
-
-	do {
-		/* work around Errata #20 according to
-		 * Intel(R) PXA27x Processor Family
-		 * Specification Update (May 2005)
-		 *
-		 * Step 2
-		 * Disable the Reciever Time Out Interrupt via IER[RTOEI]
-		 */
-		up->ier &= ~UART_IER_RTOIE;
-		serial_out(up, UART_IER, up->ier);
-
-		ch = serial_in(up, UART_RX);
-		flag = TTY_NORMAL;
-		up->port.icount.rx++;
-
-		if (unlikely(*status & (UART_LSR_BI | UART_LSR_PE |
-				       UART_LSR_FE | UART_LSR_OE))) {
-			/*
-			 * For statistics only
-			 */
-			if (*status & UART_LSR_BI) {
-				*status &= ~(UART_LSR_FE | UART_LSR_PE);
-				up->port.icount.brk++;
-				/*
-				 * We do the SysRQ and SAK checking
-				 * here because otherwise the break
-				 * may get masked by ignore_status_mask
-				 * or read_status_mask.
-				 */
-				if (uart_handle_break(&up->port))
-					goto ignore_char;
-			} else if (*status & UART_LSR_PE)
-				up->port.icount.parity++;
-			else if (*status & UART_LSR_FE)
-				up->port.icount.frame++;
-			if (*status & UART_LSR_OE)
-				up->port.icount.overrun++;
-
-			/*
-			 * Mask off conditions which should be ignored.
-			 */
-			*status &= up->port.read_status_mask;
-
-#ifdef CONFIG_SERIAL_PXA_CONSOLE
-			if (up->port.line == up->port.cons->index) {
-				/* Recover the break flag from console xmit */
-				*status |= up->lsr_break_flag;
-				up->lsr_break_flag = 0;
-			}
-#endif
-			if (*status & UART_LSR_BI) {
-				flag = TTY_BREAK;
-			} else if (*status & UART_LSR_PE)
-				flag = TTY_PARITY;
-			else if (*status & UART_LSR_FE)
-				flag = TTY_FRAME;
-		}
-
-		if (uart_handle_sysrq_char(&up->port, ch))
-			goto ignore_char;
-
-		uart_insert_char(&up->port, *status, UART_LSR_OE, ch, flag);
-
-	ignore_char:
-		*status = serial_in(up, UART_LSR);
-	} while ((*status & UART_LSR_DR) && (max_count-- > 0));
-	tty_flip_buffer_push(&up->port.state->port);
-
-	/* work around Errata #20 according to
-	 * Intel(R) PXA27x Processor Family
-	 * Specification Update (May 2005)
-	 *
-	 * Step 6:
-	 * No more data in FIFO: Re-enable RTO interrupt via IER[RTOIE]
-	 */
-	up->ier |= UART_IER_RTOIE;
-	serial_out(up, UART_IER, up->ier);
-}
-
-static void transmit_chars(struct uart_pxa_port *up)
-{
-	struct circ_buf *xmit = &up->port.state->xmit;
-	int count;
-
-	if (up->port.x_char) {
-		serial_out(up, UART_TX, up->port.x_char);
-		up->port.icount.tx++;
-		up->port.x_char = 0;
-		return;
-	}
-	if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) {
-		serial_pxa_stop_tx(&up->port);
-		return;
-	}
-
-	count = up->port.fifosize / 2;
-	do {
-		serial_out(up, UART_TX, xmit->buf[xmit->tail]);
-		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
-		up->port.icount.tx++;
-		if (uart_circ_empty(xmit))
-			break;
-	} while (--count > 0);
-
-	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
-		uart_write_wakeup(&up->port);
-
-
-	if (uart_circ_empty(xmit))
-		serial_pxa_stop_tx(&up->port);
-}
-
-static void serial_pxa_start_tx(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	if (!(up->ier & UART_IER_THRI)) {
-		up->ier |= UART_IER_THRI;
-		serial_out(up, UART_IER, up->ier);
-	}
-}
-
-/* should hold up->port.lock */
-static inline void check_modem_status(struct uart_pxa_port *up)
-{
-	int status;
-
-	status = serial_in(up, UART_MSR);
-
-	if ((status & UART_MSR_ANY_DELTA) == 0)
-		return;
-
-	if (status & UART_MSR_TERI)
-		up->port.icount.rng++;
-	if (status & UART_MSR_DDSR)
-		up->port.icount.dsr++;
-	if (status & UART_MSR_DDCD)
-		uart_handle_dcd_change(&up->port, status & UART_MSR_DCD);
-	if (status & UART_MSR_DCTS)
-		uart_handle_cts_change(&up->port, status & UART_MSR_CTS);
-
-	wake_up_interruptible(&up->port.state->port.delta_msr_wait);
-}
-
-/*
- * This handles the interrupt from one port.
- */
-static inline irqreturn_t serial_pxa_irq(int irq, void *dev_id)
-{
-	struct uart_pxa_port *up = dev_id;
-	unsigned int iir, lsr;
-
-	iir = serial_in(up, UART_IIR);
-	if (iir & UART_IIR_NO_INT)
-		return IRQ_NONE;
-	spin_lock(&up->port.lock);
-	lsr = serial_in(up, UART_LSR);
-	if (lsr & UART_LSR_DR)
-		receive_chars(up, &lsr);
-	check_modem_status(up);
-	if (lsr & UART_LSR_THRE)
-		transmit_chars(up);
-	spin_unlock(&up->port.lock);
-	return IRQ_HANDLED;
-}
-
-static unsigned int serial_pxa_tx_empty(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned long flags;
-	unsigned int ret;
-
-	spin_lock_irqsave(&up->port.lock, flags);
-	ret = serial_in(up, UART_LSR) & UART_LSR_TEMT ? TIOCSER_TEMT : 0;
-	spin_unlock_irqrestore(&up->port.lock, flags);
-
-	return ret;
-}
-
-static unsigned int serial_pxa_get_mctrl(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned char status;
-	unsigned int ret;
-
-	status = serial_in(up, UART_MSR);
-
-	ret = 0;
-	if (status & UART_MSR_DCD)
-		ret |= TIOCM_CAR;
-	if (status & UART_MSR_RI)
-		ret |= TIOCM_RNG;
-	if (status & UART_MSR_DSR)
-		ret |= TIOCM_DSR;
-	if (status & UART_MSR_CTS)
-		ret |= TIOCM_CTS;
-	return ret;
-}
-
-static void serial_pxa_set_mctrl(struct uart_port *port, unsigned int mctrl)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned char mcr = 0;
-
-	if (mctrl & TIOCM_RTS)
-		mcr |= UART_MCR_RTS;
-	if (mctrl & TIOCM_DTR)
-		mcr |= UART_MCR_DTR;
-	if (mctrl & TIOCM_OUT1)
-		mcr |= UART_MCR_OUT1;
-	if (mctrl & TIOCM_OUT2)
-		mcr |= UART_MCR_OUT2;
-	if (mctrl & TIOCM_LOOP)
-		mcr |= UART_MCR_LOOP;
-
-	mcr |= up->mcr;
-
-	serial_out(up, UART_MCR, mcr);
-}
-
-static void serial_pxa_break_ctl(struct uart_port *port, int break_state)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned long flags;
-
-	spin_lock_irqsave(&up->port.lock, flags);
-	if (break_state == -1)
-		up->lcr |= UART_LCR_SBC;
-	else
-		up->lcr &= ~UART_LCR_SBC;
-	serial_out(up, UART_LCR, up->lcr);
-	spin_unlock_irqrestore(&up->port.lock, flags);
-}
-
-static int serial_pxa_startup(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned long flags;
-	int retval;
-
-	if (port->line == 3) /* HWUART */
-		up->mcr |= UART_MCR_AFE;
-	else
-		up->mcr = 0;
-
-	up->port.uartclk = clk_get_rate(up->clk);
-
-	/*
-	 * Allocate the IRQ
-	 */
-	retval = request_irq(up->port.irq, serial_pxa_irq, 0, up->name, up);
-	if (retval)
-		return retval;
-
-	/*
-	 * Clear the FIFO buffers and disable them.
-	 * (they will be reenabled in set_termios())
-	 */
-	serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO);
-	serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO |
-			UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
-	serial_out(up, UART_FCR, 0);
-
-	/*
-	 * Clear the interrupt registers.
-	 */
-	(void) serial_in(up, UART_LSR);
-	(void) serial_in(up, UART_RX);
-	(void) serial_in(up, UART_IIR);
-	(void) serial_in(up, UART_MSR);
-
-	/*
-	 * Now, initialize the UART
-	 */
-	serial_out(up, UART_LCR, UART_LCR_WLEN8);
-
-	spin_lock_irqsave(&up->port.lock, flags);
-	up->port.mctrl |= TIOCM_OUT2;
-	serial_pxa_set_mctrl(&up->port, up->port.mctrl);
-	spin_unlock_irqrestore(&up->port.lock, flags);
-
-	/*
-	 * Finally, enable interrupts.  Note: Modem status interrupts
-	 * are set via set_termios(), which will be occurring imminently
-	 * anyway, so we don't enable them here.
-	 */
-	up->ier = UART_IER_RLSI | UART_IER_RDI | UART_IER_RTOIE | UART_IER_UUE;
-	serial_out(up, UART_IER, up->ier);
-
-	/*
-	 * And clear the interrupt registers again for luck.
-	 */
-	(void) serial_in(up, UART_LSR);
-	(void) serial_in(up, UART_RX);
-	(void) serial_in(up, UART_IIR);
-	(void) serial_in(up, UART_MSR);
-
-	return 0;
-}
-
-static void serial_pxa_shutdown(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned long flags;
-
-	free_irq(up->port.irq, up);
-
-	/*
-	 * Disable interrupts from this port
-	 */
-	up->ier = 0;
-	serial_out(up, UART_IER, 0);
-
-	spin_lock_irqsave(&up->port.lock, flags);
-	up->port.mctrl &= ~TIOCM_OUT2;
-	serial_pxa_set_mctrl(&up->port, up->port.mctrl);
-	spin_unlock_irqrestore(&up->port.lock, flags);
-
-	/*
-	 * Disable break condition and FIFOs
-	 */
-	serial_out(up, UART_LCR, serial_in(up, UART_LCR) & ~UART_LCR_SBC);
-	serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO |
-				  UART_FCR_CLEAR_RCVR |
-				  UART_FCR_CLEAR_XMIT);
-	serial_out(up, UART_FCR, 0);
-}
-
-static void
-serial_pxa_set_termios(struct uart_port *port, struct ktermios *termios,
-		       struct ktermios *old)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned char cval, fcr = 0;
-	unsigned long flags;
-	unsigned int baud, quot;
-	unsigned int dll;
-
-	switch (termios->c_cflag & CSIZE) {
-	case CS5:
-		cval = UART_LCR_WLEN5;
-		break;
-	case CS6:
-		cval = UART_LCR_WLEN6;
-		break;
-	case CS7:
-		cval = UART_LCR_WLEN7;
-		break;
-	default:
-	case CS8:
-		cval = UART_LCR_WLEN8;
-		break;
-	}
-
-	if (termios->c_cflag & CSTOPB)
-		cval |= UART_LCR_STOP;
-	if (termios->c_cflag & PARENB)
-		cval |= UART_LCR_PARITY;
-	if (!(termios->c_cflag & PARODD))
-		cval |= UART_LCR_EPAR;
-
-	/*
-	 * Ask the core to calculate the divisor for us.
-	 */
-	baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
-	quot = uart_get_divisor(port, baud);
-
-	if ((up->port.uartclk / quot) < (2400 * 16))
-		fcr = UART_FCR_ENABLE_FIFO | UART_FCR_PXAR1;
-	else if ((up->port.uartclk / quot) < (230400 * 16))
-		fcr = UART_FCR_ENABLE_FIFO | UART_FCR_PXAR8;
-	else
-		fcr = UART_FCR_ENABLE_FIFO | UART_FCR_PXAR32;
-
-	/*
-	 * Ok, we're now changing the port state.  Do it with
-	 * interrupts disabled.
-	 */
-	spin_lock_irqsave(&up->port.lock, flags);
-
-	/*
-	 * Ensure the port will be enabled.
-	 * This is required especially for serial console.
-	 */
-	up->ier |= UART_IER_UUE;
-
-	/*
-	 * Update the per-port timeout.
-	 */
-	uart_update_timeout(port, termios->c_cflag, baud);
-
-	up->port.read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;
-	if (termios->c_iflag & INPCK)
-		up->port.read_status_mask |= UART_LSR_FE | UART_LSR_PE;
-	if (termios->c_iflag & (IGNBRK | BRKINT | PARMRK))
-		up->port.read_status_mask |= UART_LSR_BI;
-
-	/*
-	 * Characters to ignore
-	 */
-	up->port.ignore_status_mask = 0;
-	if (termios->c_iflag & IGNPAR)
-		up->port.ignore_status_mask |= UART_LSR_PE | UART_LSR_FE;
-	if (termios->c_iflag & IGNBRK) {
-		up->port.ignore_status_mask |= UART_LSR_BI;
-		/*
-		 * If we're ignoring parity and break indicators,
-		 * ignore overruns too (for real raw support).
-		 */
-		if (termios->c_iflag & IGNPAR)
-			up->port.ignore_status_mask |= UART_LSR_OE;
-	}
-
-	/*
-	 * ignore all characters if CREAD is not set
-	 */
-	if ((termios->c_cflag & CREAD) == 0)
-		up->port.ignore_status_mask |= UART_LSR_DR;
-
-	/*
-	 * CTS flow control flag and modem status interrupts
-	 */
-	up->ier &= ~UART_IER_MSI;
-	if (UART_ENABLE_MS(&up->port, termios->c_cflag))
-		up->ier |= UART_IER_MSI;
-
-	serial_out(up, UART_IER, up->ier);
-
-	if (termios->c_cflag & CRTSCTS)
-		up->mcr |= UART_MCR_AFE;
-	else
-		up->mcr &= ~UART_MCR_AFE;
-
-	serial_out(up, UART_LCR, cval | UART_LCR_DLAB);	/* set DLAB */
-	serial_out(up, UART_DLL, quot & 0xff);		/* LS of divisor */
-
-	/*
-	 * work around Errata #75 according to Intel(R) PXA27x Processor Family
-	 * Specification Update (Nov 2005)
-	 */
-	dll = serial_in(up, UART_DLL);
-	WARN_ON(dll != (quot & 0xff));
-
-	serial_out(up, UART_DLM, quot >> 8);		/* MS of divisor */
-	serial_out(up, UART_LCR, cval);			/* reset DLAB */
-	up->lcr = cval;					/* Save LCR */
-	serial_pxa_set_mctrl(&up->port, up->port.mctrl);
-	serial_out(up, UART_FCR, fcr);
-	spin_unlock_irqrestore(&up->port.lock, flags);
-}
-
-static void
-serial_pxa_pm(struct uart_port *port, unsigned int state,
-	      unsigned int oldstate)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	if (!state)
-		clk_prepare_enable(up->clk);
-	else
-		clk_disable_unprepare(up->clk);
-}
-
-static void serial_pxa_release_port(struct uart_port *port)
-{
-}
-
-static int serial_pxa_request_port(struct uart_port *port)
-{
-	return 0;
-}
-
-static void serial_pxa_config_port(struct uart_port *port, int flags)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	up->port.type = PORT_PXA;
-}
-
-static int
-serial_pxa_verify_port(struct uart_port *port, struct serial_struct *ser)
-{
-	/* we don't want the core code to modify any port params */
-	return -EINVAL;
-}
-
-static const char *
-serial_pxa_type(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	return up->name;
-}
-
-static struct uart_pxa_port *serial_pxa_ports[4];
-static struct uart_driver serial_pxa_reg;
-
-#ifdef CONFIG_SERIAL_PXA_CONSOLE
-
-#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
-
-/*
- *	Wait for transmitter & holding register to empty
- */
-static inline void wait_for_xmitr(struct uart_pxa_port *up)
-{
-	unsigned int status, tmout = 10000;
-
-	/* Wait up to 10ms for the character(s) to be sent. */
-	do {
-		status = serial_in(up, UART_LSR);
-
-		if (status & UART_LSR_BI)
-			up->lsr_break_flag = UART_LSR_BI;
-
-		if (--tmout == 0)
-			break;
-		udelay(1);
-	} while ((status & BOTH_EMPTY) != BOTH_EMPTY);
-
-	/* Wait up to 1s for flow control if necessary */
-	if (up->port.flags & UPF_CONS_FLOW) {
-		tmout = 1000000;
-		while (--tmout &&
-		       ((serial_in(up, UART_MSR) & UART_MSR_CTS) == 0))
-			udelay(1);
-	}
-}
-
-static void serial_pxa_console_putchar(struct uart_port *port, int ch)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	wait_for_xmitr(up);
-	serial_out(up, UART_TX, ch);
-}
-
-/*
- * Print a string to the serial port trying not to disturb
- * any possible real use of the port...
- *
- *	The console_lock must be held when we get here.
- */
-static void
-serial_pxa_console_write(struct console *co, const char *s, unsigned int count)
-{
-	struct uart_pxa_port *up = serial_pxa_ports[co->index];
-	unsigned int ier;
-	unsigned long flags;
-	int locked = 1;
-
-	clk_enable(up->clk);
-	local_irq_save(flags);
-	if (up->port.sysrq)
-		locked = 0;
-	else if (oops_in_progress)
-		locked = spin_trylock(&up->port.lock);
-	else
-		spin_lock(&up->port.lock);
-
-	/*
-	 *	First save the IER then disable the interrupts
-	 */
-	ier = serial_in(up, UART_IER);
-	serial_out(up, UART_IER, UART_IER_UUE);
-
-	uart_console_write(&up->port, s, count, serial_pxa_console_putchar);
-
-	/*
-	 *	Finally, wait for transmitter to become empty
-	 *	and restore the IER
-	 */
-	wait_for_xmitr(up);
-	serial_out(up, UART_IER, ier);
-
-	if (locked)
-		spin_unlock(&up->port.lock);
-	local_irq_restore(flags);
-	clk_disable(up->clk);
-
-}
-
-#ifdef CONFIG_CONSOLE_POLL
-/*
- * Console polling routines for writing and reading from the uart while
- * in an interrupt or debug context.
- */
-
-static int serial_pxa_get_poll_char(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned char lsr = serial_in(up, UART_LSR);
-
-	while (!(lsr & UART_LSR_DR))
-		lsr = serial_in(up, UART_LSR);
-
-	return serial_in(up, UART_RX);
-}
-
-
-static void serial_pxa_put_poll_char(struct uart_port *port,
-			 unsigned char c)
-{
-	unsigned int ier;
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	/*
-	 *	First save the IER then disable the interrupts
-	 */
-	ier = serial_in(up, UART_IER);
-	serial_out(up, UART_IER, UART_IER_UUE);
-
-	wait_for_xmitr(up);
-	/*
-	 *	Send the character out.
-	 */
-	serial_out(up, UART_TX, c);
-
-	/*
-	 *	Finally, wait for transmitter to become empty
-	 *	and restore the IER
-	 */
-	wait_for_xmitr(up);
-	serial_out(up, UART_IER, ier);
-}
-
-#endif /* CONFIG_CONSOLE_POLL */
-
-static int __init
-serial_pxa_console_setup(struct console *co, char *options)
-{
-	struct uart_pxa_port *up;
-	int baud = 9600;
-	int bits = 8;
-	int parity = 'n';
-	int flow = 'n';
-
-	if (co->index == -1 || co->index >= serial_pxa_reg.nr)
-		co->index = 0;
-	up = serial_pxa_ports[co->index];
-	if (!up)
-		return -ENODEV;
-
-	if (options)
-		uart_parse_options(options, &baud, &parity, &bits, &flow);
-
-	return uart_set_options(&up->port, co, baud, parity, bits, flow);
-}
-
-static struct console serial_pxa_console = {
-	.name		= "ttyS",
-	.write		= serial_pxa_console_write,
-	.device		= uart_console_device,
-	.setup		= serial_pxa_console_setup,
-	.flags		= CON_PRINTBUFFER,
-	.index		= -1,
-	.data		= &serial_pxa_reg,
-};
-
-#define PXA_CONSOLE	&serial_pxa_console
-#else
-#define PXA_CONSOLE	NULL
-#endif
-
-static struct uart_ops serial_pxa_pops = {
-	.tx_empty	= serial_pxa_tx_empty,
-	.set_mctrl	= serial_pxa_set_mctrl,
-	.get_mctrl	= serial_pxa_get_mctrl,
-	.stop_tx	= serial_pxa_stop_tx,
-	.start_tx	= serial_pxa_start_tx,
-	.stop_rx	= serial_pxa_stop_rx,
-	.enable_ms	= serial_pxa_enable_ms,
-	.break_ctl	= serial_pxa_break_ctl,
-	.startup	= serial_pxa_startup,
-	.shutdown	= serial_pxa_shutdown,
-	.set_termios	= serial_pxa_set_termios,
-	.pm		= serial_pxa_pm,
-	.type		= serial_pxa_type,
-	.release_port	= serial_pxa_release_port,
-	.request_port	= serial_pxa_request_port,
-	.config_port	= serial_pxa_config_port,
-	.verify_port	= serial_pxa_verify_port,
-#if defined(CONFIG_CONSOLE_POLL) && defined(CONFIG_SERIAL_PXA_CONSOLE)
-	.poll_get_char = serial_pxa_get_poll_char,
-	.poll_put_char = serial_pxa_put_poll_char,
-#endif
-};
-
-static struct uart_driver serial_pxa_reg = {
-	.owner		= THIS_MODULE,
-	.driver_name	= "PXA serial",
-	.dev_name	= "ttyS",
-	.major		= TTY_MAJOR,
-	.minor		= 64,
-	.nr		= 4,
-	.cons		= PXA_CONSOLE,
-};
-
-#ifdef CONFIG_PM
-static int serial_pxa_suspend(struct device *dev)
-{
-        struct uart_pxa_port *sport = dev_get_drvdata(dev);
-
-        if (sport)
-                uart_suspend_port(&serial_pxa_reg, &sport->port);
-
-        return 0;
-}
-
-static int serial_pxa_resume(struct device *dev)
-{
-        struct uart_pxa_port *sport = dev_get_drvdata(dev);
-
-        if (sport)
-                uart_resume_port(&serial_pxa_reg, &sport->port);
-
-        return 0;
-}
-
-static const struct dev_pm_ops serial_pxa_pm_ops = {
-	.suspend	= serial_pxa_suspend,
-	.resume		= serial_pxa_resume,
-};
-#endif
-
-static const struct of_device_id serial_pxa_dt_ids[] = {
-	{ .compatible = "mrvl,pxa-uart", },
-	{ .compatible = "mrvl,mmp-uart", },
-	{}
-};
-MODULE_DEVICE_TABLE(of, serial_pxa_dt_ids);
-
-static int serial_pxa_probe_dt(struct platform_device *pdev,
-			       struct uart_pxa_port *sport)
-{
-	struct device_node *np = pdev->dev.of_node;
-	int ret;
-
-	if (!np)
-		return 1;
-
-	ret = of_alias_get_id(np, "serial");
-	if (ret < 0) {
-		dev_err(&pdev->dev, "failed to get alias id, errno %d\n", ret);
-		return ret;
-	}
-	sport->port.line = ret;
-	return 0;
-}
-
-static int serial_pxa_probe(struct platform_device *dev)
-{
-	struct uart_pxa_port *sport;
-	struct resource *mmres, *irqres;
-	int ret;
-
-	mmres = platform_get_resource(dev, IORESOURCE_MEM, 0);
-	irqres = platform_get_resource(dev, IORESOURCE_IRQ, 0);
-	if (!mmres || !irqres)
-		return -ENODEV;
-
-	sport = kzalloc(sizeof(struct uart_pxa_port), GFP_KERNEL);
-	if (!sport)
-		return -ENOMEM;
-
-	sport->clk = clk_get(&dev->dev, NULL);
-	if (IS_ERR(sport->clk)) {
-		ret = PTR_ERR(sport->clk);
-		goto err_free;
-	}
-
-	ret = clk_prepare(sport->clk);
-	if (ret) {
-		clk_put(sport->clk);
-		goto err_free;
-	}
-
-	sport->port.type = PORT_PXA;
-	sport->port.iotype = UPIO_MEM;
-	sport->port.mapbase = mmres->start;
-	sport->port.irq = irqres->start;
-	sport->port.fifosize = 64;
-	sport->port.ops = &serial_pxa_pops;
-	sport->port.dev = &dev->dev;
-	sport->port.flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF;
-	sport->port.uartclk = clk_get_rate(sport->clk);
-
-	ret = serial_pxa_probe_dt(dev, sport);
-	if (ret > 0)
-		sport->port.line = dev->id;
-	else if (ret < 0)
-		goto err_clk;
-	snprintf(sport->name, PXA_NAME_LEN - 1, "UART%d", sport->port.line + 1);
-
-	sport->port.membase = ioremap(mmres->start, resource_size(mmres));
-	if (!sport->port.membase) {
-		ret = -ENOMEM;
-		goto err_clk;
-	}
-
-	serial_pxa_ports[sport->port.line] = sport;
-
-	uart_add_one_port(&serial_pxa_reg, &sport->port);
-	platform_set_drvdata(dev, sport);
-
-	return 0;
-
- err_clk:
-	clk_unprepare(sport->clk);
-	clk_put(sport->clk);
- err_free:
-	kfree(sport);
-	return ret;
-}
-
-static int serial_pxa_remove(struct platform_device *dev)
-{
-	struct uart_pxa_port *sport = platform_get_drvdata(dev);
-
-	uart_remove_one_port(&serial_pxa_reg, &sport->port);
-
-	clk_unprepare(sport->clk);
-	clk_put(sport->clk);
-	kfree(sport);
-
-	return 0;
-}
-
-static struct platform_driver serial_pxa_driver = {
-        .probe          = serial_pxa_probe,
-        .remove         = serial_pxa_remove,
-
-	.driver		= {
-	        .name	= "pxa2xx-uart",
-#ifdef CONFIG_PM
-		.pm	= &serial_pxa_pm_ops,
-#endif
-		.of_match_table = serial_pxa_dt_ids,
-	},
-};
-
-static int __init serial_pxa_init(void)
-{
-	int ret;
-
-	ret = uart_register_driver(&serial_pxa_reg);
-	if (ret != 0)
-		return ret;
-
-	ret = platform_driver_register(&serial_pxa_driver);
-	if (ret != 0)
-		uart_unregister_driver(&serial_pxa_reg);
-
-	return ret;
-}
-
-static void __exit serial_pxa_exit(void)
-{
-	platform_driver_unregister(&serial_pxa_driver);
-	uart_unregister_driver(&serial_pxa_reg);
-}
-
-module_init(serial_pxa_init);
-module_exit(serial_pxa_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:pxa2xx-uart");
-- 
2.6.2


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

* [PATCH v4 1/2] serial: rewrite pxa2xx-uart to use 8250_core
@ 2015-12-09 22:28               ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2015-12-09 22:28 UTC (permalink / raw)
  To: linux-kernel
  Cc: Sergei Ianovich, Russell King, Greg Kroah-Hartman, Jiri Slaby,
	Heikki Krogerus, James Cameron, Alexandre Belloni,
	Robert Jarzmik, Rob Herring, Ulf Hansson, Rafael J. Wysocki,
	Kevin Hilman, Andy Shevchenko, Arnd Bergmann, Paul Gortmaker,
	Scott Wood, Sebastian Andrzej Siewior, Paul Burton,
	Joachim Eastwood, Mans Rullgard, Masahiro Yamada, Peter

pxa2xx-uart was a separate uart platform driver. It was declaring
the same device names and numbers as 8250 driver. As a result,
it was impossible to use 8250 driver on PXA SoCs.

Upon closer examination pxa2xx-uart turned out to be a clone of
8250_core driver.

Workaround for Erratum #19 according to Marvel(R) PXA270M Processor
Specification Update (April 19, 2010) is dropped. 8250_core reads
from FIFO immediately after checking DR bit in LSR.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Reviewed-by: James Cameron <quozl@laptop.org>
Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 The patch was reviewed/acked at version 3. Changes in version 4
 are simple unbitrotting, so the flags are carried over.

 changes v3..v4
 * remove owner field from platform_driver structure
 * make of_device_id structure constant
 * use CONFIG_SERIAL_8250_PXA instead of CONFIG_SERIAL_PXA

 changes v2..v3
 * remove devm_free/put as suggested by Heikki Krogerus
 * use SET_SYSTEM_SLEEP_PM_OPS macro to set pm ops as suggested
   by Heikki Krogerus

 changes v1..v2
 * actually implement workaround for E74 in dl_write as spooted
   by James Cameron
 * added comment about E19 in commit message

 arch/arm/configs/am200epdkit_defconfig    |   5 +-
 arch/arm/configs/cm_x2xx_defconfig        |   5 +-
 arch/arm/configs/cm_x300_defconfig        |   5 +-
 arch/arm/configs/colibri_pxa270_defconfig |   5 +-
 arch/arm/configs/colibri_pxa300_defconfig |   5 +-
 arch/arm/configs/corgi_defconfig          |   6 +-
 arch/arm/configs/em_x270_defconfig        |   5 +-
 arch/arm/configs/ezx_defconfig            |   5 +-
 arch/arm/configs/h5000_defconfig          |   5 +-
 arch/arm/configs/imote2_defconfig         |   5 +-
 arch/arm/configs/lpd270_defconfig         |   5 +-
 arch/arm/configs/lubbock_defconfig        |   5 +-
 arch/arm/configs/mainstone_defconfig      |   5 +-
 arch/arm/configs/mmp2_defconfig           |   5 +-
 arch/arm/configs/pcm027_defconfig         |   5 +-
 arch/arm/configs/pxa168_defconfig         |   5 +-
 arch/arm/configs/pxa255-idp_defconfig     |   5 +-
 arch/arm/configs/pxa3xx_defconfig         |   5 +-
 arch/arm/configs/pxa910_defconfig         |   5 +-
 arch/arm/configs/raumfeld_defconfig       |   5 +-
 arch/arm/configs/spitz_defconfig          |   6 +-
 arch/arm/configs/trizeps4_defconfig       |   5 +-
 arch/arm/configs/viper_defconfig          |   6 +-
 arch/arm/configs/xcep_defconfig           |   5 +-
 drivers/tty/serial/8250/8250_pxa.c        | 177 ++++++
 drivers/tty/serial/8250/Kconfig           |   9 +
 drivers/tty/serial/8250/Makefile          |   1 +
 drivers/tty/serial/Kconfig                |  23 -
 drivers/tty/serial/Makefile               |   1 -
 drivers/tty/serial/pxa.c                  | 968 ------------------------------
 30 files changed, 259 insertions(+), 1043 deletions(-)
 create mode 100644 drivers/tty/serial/8250/8250_pxa.c
 delete mode 100644 drivers/tty/serial/pxa.c

diff --git a/arch/arm/configs/am200epdkit_defconfig b/arch/arm/configs/am200epdkit_defconfig
index f0dea52..5f78ee7 100644
--- a/arch/arm/configs/am200epdkit_defconfig
+++ b/arch/arm/configs/am200epdkit_defconfig
@@ -60,8 +60,9 @@ CONFIG_BLK_DEV_IDECS=m
 CONFIG_NETDEVICES=y
 CONFIG_NET_ETHERNET=y
 CONFIG_SMC91X=m
-CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PXA=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 # CONFIG_HWMON is not set
diff --git a/arch/arm/configs/cm_x2xx_defconfig b/arch/arm/configs/cm_x2xx_defconfig
index 3b32d5f..f1ae370 100644
--- a/arch/arm/configs/cm_x2xx_defconfig
+++ b/arch/arm/configs/cm_x2xx_defconfig
@@ -96,8 +96,9 @@ CONFIG_KEYBOARD_PXA27x=m
 CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_TOUCHSCREEN_UCB1400=m
 # CONFIG_SERIO_SERPORT is not set
-CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PXA=y
 CONFIG_LEGACY_PTY_COUNT=16
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/cm_x300_defconfig b/arch/arm/configs/cm_x300_defconfig
index 7df040e..07bf9b2 100644
--- a/arch/arm/configs/cm_x300_defconfig
+++ b/arch/arm/configs/cm_x300_defconfig
@@ -80,8 +80,9 @@ CONFIG_TOUCHSCREEN_WM97XX=m
 # CONFIG_TOUCHSCREEN_WM9713 is not set
 # CONFIG_SERIO is not set
 # CONFIG_LEGACY_PTYS is not set
-CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PXA=y
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
 CONFIG_I2C_PXA=y
diff --git a/arch/arm/configs/colibri_pxa270_defconfig b/arch/arm/configs/colibri_pxa270_defconfig
index 18c311a..5ea17d4 100644
--- a/arch/arm/configs/colibri_pxa270_defconfig
+++ b/arch/arm/configs/colibri_pxa270_defconfig
@@ -103,8 +103,9 @@ CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=m
 CONFIG_SERIO_LIBPS2=y
-CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PXA=y
 CONFIG_HW_RANDOM=y
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
diff --git a/arch/arm/configs/colibri_pxa300_defconfig b/arch/arm/configs/colibri_pxa300_defconfig
index be02fe2..e12af54 100644
--- a/arch/arm/configs/colibri_pxa300_defconfig
+++ b/arch/arm/configs/colibri_pxa300_defconfig
@@ -31,8 +31,9 @@ CONFIG_INPUT_EVDEV=y
 # CONFIG_INPUT_MOUSE is not set
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_GPIO_ROTARY_ENCODER=y
-CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PXA=y
 CONFIG_HW_RANDOM=y
 CONFIG_DEBUG_GPIO=y
 # CONFIG_HWMON is not set
diff --git a/arch/arm/configs/corgi_defconfig b/arch/arm/configs/corgi_defconfig
index c1470a0..d94212b 100644
--- a/arch/arm/configs/corgi_defconfig
+++ b/arch/arm/configs/corgi_defconfig
@@ -131,10 +131,10 @@ CONFIG_TOUCHSCREEN_ADS7846=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=m
 # CONFIG_SERIO is not set
-CONFIG_SERIAL_8250=m
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_CS=m
-CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_8250_PXA=y
 # CONFIG_LEGACY_PTYS is not set
 CONFIG_I2C=y
 CONFIG_I2C_PXA=y
diff --git a/arch/arm/configs/em_x270_defconfig b/arch/arm/configs/em_x270_defconfig
index 8e10df7..8ac6b84 100644
--- a/arch/arm/configs/em_x270_defconfig
+++ b/arch/arm/configs/em_x270_defconfig
@@ -90,8 +90,9 @@ CONFIG_TOUCHSCREEN_WM97XX=m
 # CONFIG_TOUCHSCREEN_WM9705 is not set
 # CONFIG_TOUCHSCREEN_WM9713 is not set
 # CONFIG_SERIO_SERPORT is not set
-CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PXA=y
 CONFIG_LEGACY_PTY_COUNT=16
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/ezx_defconfig b/arch/arm/configs/ezx_defconfig
index ea316c4..5d365f4 100644
--- a/arch/arm/configs/ezx_defconfig
+++ b/arch/arm/configs/ezx_defconfig
@@ -214,8 +214,9 @@ CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=y
 CONFIG_INPUT_PCAP=y
 # CONFIG_SERIO is not set
-CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PXA=y
 CONFIG_LEGACY_PTY_COUNT=8
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/h5000_defconfig b/arch/arm/configs/h5000_defconfig
index 37903e3..d366c87 100644
--- a/arch/arm/configs/h5000_defconfig
+++ b/arch/arm/configs/h5000_defconfig
@@ -47,8 +47,9 @@ CONFIG_MTD_PHYSMAP=y
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
-CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PXA=y
 CONFIG_LEGACY_PTY_COUNT=32
 # CONFIG_HW_RANDOM is not set
 # CONFIG_HWMON is not set
diff --git a/arch/arm/configs/imote2_defconfig b/arch/arm/configs/imote2_defconfig
index 18e59fe..0cc503b 100644
--- a/arch/arm/configs/imote2_defconfig
+++ b/arch/arm/configs/imote2_defconfig
@@ -192,8 +192,9 @@ CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=y
 # CONFIG_SERIO is not set
-CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PXA=y
 CONFIG_LEGACY_PTY_COUNT=8
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/lpd270_defconfig b/arch/arm/configs/lpd270_defconfig
index 1c8c9ee..7774fb2 100644
--- a/arch/arm/configs/lpd270_defconfig
+++ b/arch/arm/configs/lpd270_defconfig
@@ -38,8 +38,9 @@ CONFIG_SMC91X=y
 CONFIG_INPUT_EVDEV=y
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO_SERPORT is not set
-CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PXA=y
 # CONFIG_HW_RANDOM is not set
 CONFIG_FB=y
 CONFIG_FB_PXA=y
diff --git a/arch/arm/configs/lubbock_defconfig b/arch/arm/configs/lubbock_defconfig
index c4ba274..d2c18e6 100644
--- a/arch/arm/configs/lubbock_defconfig
+++ b/arch/arm/configs/lubbock_defconfig
@@ -37,8 +37,9 @@ CONFIG_PCMCIA_PCNET=y
 CONFIG_INPUT_EVDEV=y
 # CONFIG_SERIO_SERPORT is not set
 CONFIG_SERIO_SA1111=y
-CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PXA=y
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_USB_GADGET=y
 CONFIG_USB_G_SERIAL=m
diff --git a/arch/arm/configs/mainstone_defconfig b/arch/arm/configs/mainstone_defconfig
index 04efa1b..ece034c 100644
--- a/arch/arm/configs/mainstone_defconfig
+++ b/arch/arm/configs/mainstone_defconfig
@@ -34,8 +34,9 @@ CONFIG_SMC91X=y
 CONFIG_INPUT_EVDEV=y
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO_SERPORT is not set
-CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PXA=y
 CONFIG_FB=y
 CONFIG_FB_PXA=y
 # CONFIG_VGA_CONSOLE is not set
diff --git a/arch/arm/configs/mmp2_defconfig b/arch/arm/configs/mmp2_defconfig
index f1cb95e..a56f2a0 100644
--- a/arch/arm/configs/mmp2_defconfig
+++ b/arch/arm/configs/mmp2_defconfig
@@ -44,8 +44,9 @@ CONFIG_SMC91X=y
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
-CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PXA=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/pcm027_defconfig b/arch/arm/configs/pcm027_defconfig
index b5624e3..93bc85c 100644
--- a/arch/arm/configs/pcm027_defconfig
+++ b/arch/arm/configs/pcm027_defconfig
@@ -60,8 +60,9 @@ CONFIG_SMC91X=y
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
-CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PXA=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/pxa168_defconfig b/arch/arm/configs/pxa168_defconfig
index 74d7e01..8dc8a99 100644
--- a/arch/arm/configs/pxa168_defconfig
+++ b/arch/arm/configs/pxa168_defconfig
@@ -40,8 +40,9 @@ CONFIG_SMC91X=y
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
-CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PXA=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 # CONFIG_HWMON is not set
diff --git a/arch/arm/configs/pxa255-idp_defconfig b/arch/arm/configs/pxa255-idp_defconfig
index 917a070b..688578d 100644
--- a/arch/arm/configs/pxa255-idp_defconfig
+++ b/arch/arm/configs/pxa255-idp_defconfig
@@ -35,8 +35,9 @@ CONFIG_SMC91X=y
 CONFIG_INPUT_EVDEV=y
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO_SERPORT is not set
-CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PXA=y
 CONFIG_FB=y
 CONFIG_FB_PXA=y
 # CONFIG_VGA_CONSOLE is not set
diff --git a/arch/arm/configs/pxa3xx_defconfig b/arch/arm/configs/pxa3xx_defconfig
index 5f337d7..1dedeaf 100644
--- a/arch/arm/configs/pxa3xx_defconfig
+++ b/arch/arm/configs/pxa3xx_defconfig
@@ -56,8 +56,9 @@ CONFIG_KEYBOARD_PXA27x=y
 CONFIG_KEYBOARD_PXA930_ROTARY=y
 CONFIG_MOUSE_PXA930_TRKBALL=y
 CONFIG_INPUT_TOUCHSCREEN=y
-CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PXA=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/pxa910_defconfig b/arch/arm/configs/pxa910_defconfig
index 3bb7771..9be8045 100644
--- a/arch/arm/configs/pxa910_defconfig
+++ b/arch/arm/configs/pxa910_defconfig
@@ -40,8 +40,9 @@ CONFIG_SMC91X=y
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
-CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PXA=y
 CONFIG_SPI=y
 CONFIG_FB=y
 CONFIG_MMP_DISP=y
diff --git a/arch/arm/configs/raumfeld_defconfig b/arch/arm/configs/raumfeld_defconfig
index 3d833ae..b4c23e3 100644
--- a/arch/arm/configs/raumfeld_defconfig
+++ b/arch/arm/configs/raumfeld_defconfig
@@ -67,8 +67,9 @@ CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_TOUCHSCREEN_EETI=m
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_GPIO_ROTARY_ENCODER=y
-CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PXA=y
 CONFIG_HW_RANDOM=y
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
diff --git a/arch/arm/configs/spitz_defconfig b/arch/arm/configs/spitz_defconfig
index a1ede19..fb07d0b 100644
--- a/arch/arm/configs/spitz_defconfig
+++ b/arch/arm/configs/spitz_defconfig
@@ -128,10 +128,10 @@ CONFIG_TOUCHSCREEN_ADS7846=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=m
 # CONFIG_SERIO is not set
-CONFIG_SERIAL_8250=m
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_CS=m
-CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_8250_PXA=y
 # CONFIG_LEGACY_PTYS is not set
 CONFIG_SPI=y
 CONFIG_SPI_PXA2XX=y
diff --git a/arch/arm/configs/trizeps4_defconfig b/arch/arm/configs/trizeps4_defconfig
index 4bc8700..cbd0226 100644
--- a/arch/arm/configs/trizeps4_defconfig
+++ b/arch/arm/configs/trizeps4_defconfig
@@ -132,8 +132,9 @@ CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=m
 CONFIG_SERIO_LIBPS2=y
-CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PXA=y
 CONFIG_HW_RANDOM=y
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
diff --git a/arch/arm/configs/viper_defconfig b/arch/arm/configs/viper_defconfig
index 0d717a5..6e5ca7e 100644
--- a/arch/arm/configs/viper_defconfig
+++ b/arch/arm/configs/viper_defconfig
@@ -101,11 +101,11 @@ CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=m
 # CONFIG_CONSOLE_TRANSLATIONS is not set
 # CONFIG_VT_CONSOLE is not set
-CONFIG_SERIAL_8250=m
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_NR_UARTS=5
 CONFIG_SERIAL_8250_RUNTIME_UARTS=5
-CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_8250_PXA=y
 # CONFIG_LEGACY_PTYS is not set
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
diff --git a/arch/arm/configs/xcep_defconfig b/arch/arm/configs/xcep_defconfig
index 721832f..007967a 100644
--- a/arch/arm/configs/xcep_defconfig
+++ b/arch/arm/configs/xcep_defconfig
@@ -60,8 +60,9 @@ CONFIG_NET_ETHERNET=y
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
 # CONFIG_DEVKMEM is not set
-CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PXA=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=m
diff --git a/drivers/tty/serial/8250/8250_pxa.c b/drivers/tty/serial/8250/8250_pxa.c
new file mode 100644
index 0000000..6a14df0
--- /dev/null
+++ b/drivers/tty/serial/8250/8250_pxa.c
@@ -0,0 +1,177 @@
+/*
+ *  drivers/tty/serial/8250/8250_pxa.c -- driver for PXA on-board UARTS
+ *  Copyright:	(C) 2013 Sergei Ianovich <ynvich@gmail.com>
+ *
+ *  replaces drivers/serial/pxa.c by Nicolas Pitre
+ *  Created:	Feb 20, 2003
+ *  Copyright:	(C) 2003 Monta Vista Software, Inc.
+ *
+ *  Based on drivers/serial/8250.c by Russell King.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/serial_8250.h>
+#include <linux/serial_core.h>
+#include <linux/serial_reg.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
+#include <linux/pm_runtime.h>
+
+#include "8250.h"
+
+struct pxa8250_data {
+	int			line;
+	struct clk		*clk;
+};
+
+#ifdef CONFIG_PM
+static int serial_pxa_suspend(struct device *dev)
+{
+	struct pxa8250_data *data = dev_get_drvdata(dev);
+
+	serial8250_suspend_port(data->line);
+
+	return 0;
+}
+
+static int serial_pxa_resume(struct device *dev)
+{
+	struct pxa8250_data *data = dev_get_drvdata(dev);
+
+	serial8250_resume_port(data->line);
+
+	return 0;
+}
+#endif
+
+static const struct dev_pm_ops serial_pxa_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(serial_pxa_suspend, serial_pxa_resume)
+};
+
+static const struct of_device_id serial_pxa_dt_ids[] = {
+	{ .compatible = "mrvl,pxa-uart", },
+	{ .compatible = "mrvl,mmp-uart", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, serial_pxa_dt_ids);
+
+/* Uart divisor latch write */
+static void serial_pxa_dl_write(struct uart_8250_port *up, int value)
+{
+	unsigned int dll;
+
+	serial_out(up, UART_DLL, value & 0xff);
+	/*
+	 * work around Erratum #74 according to Marvel(R) PXA270M Processor
+	 * Specification Update (April 19, 2010)
+	 */
+	dll = serial_in(up, UART_DLL);
+	WARN_ON(dll != (value & 0xff));
+
+	serial_out(up, UART_DLM, value >> 8 & 0xff);
+}
+
+
+static void serial_pxa_pm(struct uart_port *port, unsigned int state,
+	      unsigned int oldstate)
+{
+	struct pxa8250_data *data = port->private_data;
+
+	if (!state)
+		clk_prepare_enable(data->clk);
+	else
+		clk_disable_unprepare(data->clk);
+}
+
+static int serial_pxa_probe(struct platform_device *pdev)
+{
+	struct uart_8250_port uart = {};
+	struct pxa8250_data *data;
+	struct resource *mmres, *irqres;
+	int ret;
+
+	mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	irqres = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!mmres || !irqres)
+		return -ENODEV;
+
+	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(data->clk))
+		return PTR_ERR(data->clk);
+
+	ret = clk_prepare(data->clk);
+	if (ret)
+		return ret;
+
+	uart.port.type = PORT_XSCALE;
+	uart.port.iotype = UPIO_MEM32;
+	uart.port.mapbase = mmres->start;
+	uart.port.regshift = 2;
+	uart.port.irq = irqres->start;
+	uart.port.fifosize = 64;
+	uart.port.flags = UPF_IOREMAP | UPF_SKIP_TEST;
+	uart.port.dev = &pdev->dev;
+	uart.port.uartclk = clk_get_rate(data->clk);
+	uart.port.pm = serial_pxa_pm;
+	uart.port.private_data = data;
+	uart.dl_write = serial_pxa_dl_write;
+
+	ret = serial8250_register_8250_port(&uart);
+	if (ret < 0)
+		goto err_clk;
+
+	data->line = ret;
+
+	platform_set_drvdata(pdev, data);
+
+	return 0;
+
+ err_clk:
+	clk_unprepare(data->clk);
+	return ret;
+}
+
+static int serial_pxa_remove(struct platform_device *pdev)
+{
+	struct pxa8250_data *data = platform_get_drvdata(pdev);
+
+	serial8250_unregister_port(data->line);
+
+	clk_unprepare(data->clk);
+
+	return 0;
+}
+
+static struct platform_driver serial_pxa_driver = {
+	.probe          = serial_pxa_probe,
+	.remove         = serial_pxa_remove,
+
+	.driver		= {
+		.name	= "pxa2xx-uart",
+		.pm	= &serial_pxa_pm_ops,
+		.of_match_table = serial_pxa_dt_ids,
+	},
+};
+
+module_platform_driver(serial_pxa_driver);
+
+MODULE_AUTHOR("Sergei Ianovich");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:pxa2xx-uart");
diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
index 6412f14..48b6253 100644
--- a/drivers/tty/serial/8250/Kconfig
+++ b/drivers/tty/serial/8250/Kconfig
@@ -378,3 +378,12 @@ config SERIAL_8250_MID
 	  Selecting this option will enable handling of the extra features
 	  present on the UART found on Intel Medfield SOC and various other
 	  Intel platforms.
+
+config SERIAL_8250_PXA
+	tristate "PXA serial port support"
+	depends on SERIAL_8250 && (ARCH_PXA || ARCH_MMP)
+	help
+	  If you have a machine based on an Intel XScale PXA2xx CPU you
+	  can enable its onboard serial ports by enabling this option.
+
+	  If you choose M here, the module name will be 8250_pxa.
diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile
index e177f86..7e54413 100644
--- a/drivers/tty/serial/8250/Makefile
+++ b/drivers/tty/serial/8250/Makefile
@@ -28,5 +28,6 @@ obj-$(CONFIG_SERIAL_8250_MT6577)	+= 8250_mtk.o
 obj-$(CONFIG_SERIAL_8250_UNIPHIER)	+= 8250_uniphier.o
 obj-$(CONFIG_SERIAL_8250_INGENIC)	+= 8250_ingenic.o
 obj-$(CONFIG_SERIAL_8250_MID)		+= 8250_mid.o
+obj-$(CONFIG_SERIAL_8250_PXA)		+= 8250_pxa.o
 
 CFLAGS_8250_ingenic.o += -I$(srctree)/scripts/dtc/libfdt
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index f38beb2..8c40c83 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -435,29 +435,6 @@ config SERIAL_MPSC_CONSOLE
 	help
 	  Say Y here if you want to support a serial console on a Marvell MPSC.
 
-config SERIAL_PXA
-	bool "PXA serial port support"
-	depends on ARCH_PXA || ARCH_MMP
-	select SERIAL_CORE
-	help
-	  If you have a machine based on an Intel XScale PXA2xx CPU you
-	  can enable its onboard serial ports by enabling this option.
-
-config SERIAL_PXA_CONSOLE
-	bool "Console on PXA serial port"
-	depends on SERIAL_PXA
-	select SERIAL_CORE_CONSOLE
-	help
-	  If you have enabled the serial port on the Intel XScale PXA
-	  CPU you can make it the console by answering Y to this option.
-
-	  Even if you say Y here, the currently visible virtual console
-	  (/dev/tty0) will still be used as the system console by default, but
-	  you can alter that using a kernel command line option such as
-	  "console=ttySA0". (Try "man bootparam" or see the documentation of
-	  your boot loader (lilo or loadlin) about how to pass options to the
-	  kernel at boot time.)
-
 config SERIAL_SA1100
 	bool "SA1100 serial port support"
 	depends on ARCH_SA1100
diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile
index 5ab4111..5cd5c68 100644
--- a/drivers/tty/serial/Makefile
+++ b/drivers/tty/serial/Makefile
@@ -23,7 +23,6 @@ obj-$(CONFIG_SERIAL_8250) += 8250/
 obj-$(CONFIG_SERIAL_AMBA_PL010) += amba-pl010.o
 obj-$(CONFIG_SERIAL_AMBA_PL011) += amba-pl011.o
 obj-$(CONFIG_SERIAL_CLPS711X) += clps711x.o
-obj-$(CONFIG_SERIAL_PXA) += pxa.o
 obj-$(CONFIG_SERIAL_PNX8XXX) += pnx8xxx_uart.o
 obj-$(CONFIG_SERIAL_SA1100) += sa1100.o
 obj-$(CONFIG_SERIAL_BCM63XX) += bcm63xx_uart.o
diff --git a/drivers/tty/serial/pxa.c b/drivers/tty/serial/pxa.c
deleted file mode 100644
index 9becba6..0000000
--- a/drivers/tty/serial/pxa.c
+++ /dev/null
@@ -1,968 +0,0 @@
-/*
- *  Based on drivers/serial/8250.c by Russell King.
- *
- *  Author:	Nicolas Pitre
- *  Created:	Feb 20, 2003
- *  Copyright:	(C) 2003 Monta Vista Software, Inc.
- *
- * 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.
- *
- * Note 1: This driver is made separate from the already too overloaded
- * 8250.c because it needs some kirks of its own and that'll make it
- * easier to add DMA support.
- *
- * Note 2: I'm too sick of device allocation policies for serial ports.
- * If someone else wants to request an "official" allocation of major/minor
- * for this driver please be my guest.  And don't forget that new hardware
- * to come from Intel might have more than 3 or 4 of those UARTs.  Let's
- * hope for a better port registration and dynamic device allocation scheme
- * with the serial core maintainer satisfaction to appear soon.
- */
-
-
-#if defined(CONFIG_SERIAL_PXA_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-#define SUPPORT_SYSRQ
-#endif
-
-#include <linux/module.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-#include <linux/console.h>
-#include <linux/sysrq.h>
-#include <linux/serial_reg.h>
-#include <linux/circ_buf.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/of.h>
-#include <linux/platform_device.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/serial_core.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-
-#define PXA_NAME_LEN		8
-
-struct uart_pxa_port {
-	struct uart_port        port;
-	unsigned char           ier;
-	unsigned char           lcr;
-	unsigned char           mcr;
-	unsigned int            lsr_break_flag;
-	struct clk		*clk;
-	char			name[PXA_NAME_LEN];
-};
-
-static inline unsigned int serial_in(struct uart_pxa_port *up, int offset)
-{
-	offset <<= 2;
-	return readl(up->port.membase + offset);
-}
-
-static inline void serial_out(struct uart_pxa_port *up, int offset, int value)
-{
-	offset <<= 2;
-	writel(value, up->port.membase + offset);
-}
-
-static void serial_pxa_enable_ms(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	up->ier |= UART_IER_MSI;
-	serial_out(up, UART_IER, up->ier);
-}
-
-static void serial_pxa_stop_tx(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	if (up->ier & UART_IER_THRI) {
-		up->ier &= ~UART_IER_THRI;
-		serial_out(up, UART_IER, up->ier);
-	}
-}
-
-static void serial_pxa_stop_rx(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	up->ier &= ~UART_IER_RLSI;
-	up->port.read_status_mask &= ~UART_LSR_DR;
-	serial_out(up, UART_IER, up->ier);
-}
-
-static inline void receive_chars(struct uart_pxa_port *up, int *status)
-{
-	unsigned int ch, flag;
-	int max_count = 256;
-
-	do {
-		/* work around Errata #20 according to
-		 * Intel(R) PXA27x Processor Family
-		 * Specification Update (May 2005)
-		 *
-		 * Step 2
-		 * Disable the Reciever Time Out Interrupt via IER[RTOEI]
-		 */
-		up->ier &= ~UART_IER_RTOIE;
-		serial_out(up, UART_IER, up->ier);
-
-		ch = serial_in(up, UART_RX);
-		flag = TTY_NORMAL;
-		up->port.icount.rx++;
-
-		if (unlikely(*status & (UART_LSR_BI | UART_LSR_PE |
-				       UART_LSR_FE | UART_LSR_OE))) {
-			/*
-			 * For statistics only
-			 */
-			if (*status & UART_LSR_BI) {
-				*status &= ~(UART_LSR_FE | UART_LSR_PE);
-				up->port.icount.brk++;
-				/*
-				 * We do the SysRQ and SAK checking
-				 * here because otherwise the break
-				 * may get masked by ignore_status_mask
-				 * or read_status_mask.
-				 */
-				if (uart_handle_break(&up->port))
-					goto ignore_char;
-			} else if (*status & UART_LSR_PE)
-				up->port.icount.parity++;
-			else if (*status & UART_LSR_FE)
-				up->port.icount.frame++;
-			if (*status & UART_LSR_OE)
-				up->port.icount.overrun++;
-
-			/*
-			 * Mask off conditions which should be ignored.
-			 */
-			*status &= up->port.read_status_mask;
-
-#ifdef CONFIG_SERIAL_PXA_CONSOLE
-			if (up->port.line == up->port.cons->index) {
-				/* Recover the break flag from console xmit */
-				*status |= up->lsr_break_flag;
-				up->lsr_break_flag = 0;
-			}
-#endif
-			if (*status & UART_LSR_BI) {
-				flag = TTY_BREAK;
-			} else if (*status & UART_LSR_PE)
-				flag = TTY_PARITY;
-			else if (*status & UART_LSR_FE)
-				flag = TTY_FRAME;
-		}
-
-		if (uart_handle_sysrq_char(&up->port, ch))
-			goto ignore_char;
-
-		uart_insert_char(&up->port, *status, UART_LSR_OE, ch, flag);
-
-	ignore_char:
-		*status = serial_in(up, UART_LSR);
-	} while ((*status & UART_LSR_DR) && (max_count-- > 0));
-	tty_flip_buffer_push(&up->port.state->port);
-
-	/* work around Errata #20 according to
-	 * Intel(R) PXA27x Processor Family
-	 * Specification Update (May 2005)
-	 *
-	 * Step 6:
-	 * No more data in FIFO: Re-enable RTO interrupt via IER[RTOIE]
-	 */
-	up->ier |= UART_IER_RTOIE;
-	serial_out(up, UART_IER, up->ier);
-}
-
-static void transmit_chars(struct uart_pxa_port *up)
-{
-	struct circ_buf *xmit = &up->port.state->xmit;
-	int count;
-
-	if (up->port.x_char) {
-		serial_out(up, UART_TX, up->port.x_char);
-		up->port.icount.tx++;
-		up->port.x_char = 0;
-		return;
-	}
-	if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) {
-		serial_pxa_stop_tx(&up->port);
-		return;
-	}
-
-	count = up->port.fifosize / 2;
-	do {
-		serial_out(up, UART_TX, xmit->buf[xmit->tail]);
-		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
-		up->port.icount.tx++;
-		if (uart_circ_empty(xmit))
-			break;
-	} while (--count > 0);
-
-	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
-		uart_write_wakeup(&up->port);
-
-
-	if (uart_circ_empty(xmit))
-		serial_pxa_stop_tx(&up->port);
-}
-
-static void serial_pxa_start_tx(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	if (!(up->ier & UART_IER_THRI)) {
-		up->ier |= UART_IER_THRI;
-		serial_out(up, UART_IER, up->ier);
-	}
-}
-
-/* should hold up->port.lock */
-static inline void check_modem_status(struct uart_pxa_port *up)
-{
-	int status;
-
-	status = serial_in(up, UART_MSR);
-
-	if ((status & UART_MSR_ANY_DELTA) == 0)
-		return;
-
-	if (status & UART_MSR_TERI)
-		up->port.icount.rng++;
-	if (status & UART_MSR_DDSR)
-		up->port.icount.dsr++;
-	if (status & UART_MSR_DDCD)
-		uart_handle_dcd_change(&up->port, status & UART_MSR_DCD);
-	if (status & UART_MSR_DCTS)
-		uart_handle_cts_change(&up->port, status & UART_MSR_CTS);
-
-	wake_up_interruptible(&up->port.state->port.delta_msr_wait);
-}
-
-/*
- * This handles the interrupt from one port.
- */
-static inline irqreturn_t serial_pxa_irq(int irq, void *dev_id)
-{
-	struct uart_pxa_port *up = dev_id;
-	unsigned int iir, lsr;
-
-	iir = serial_in(up, UART_IIR);
-	if (iir & UART_IIR_NO_INT)
-		return IRQ_NONE;
-	spin_lock(&up->port.lock);
-	lsr = serial_in(up, UART_LSR);
-	if (lsr & UART_LSR_DR)
-		receive_chars(up, &lsr);
-	check_modem_status(up);
-	if (lsr & UART_LSR_THRE)
-		transmit_chars(up);
-	spin_unlock(&up->port.lock);
-	return IRQ_HANDLED;
-}
-
-static unsigned int serial_pxa_tx_empty(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned long flags;
-	unsigned int ret;
-
-	spin_lock_irqsave(&up->port.lock, flags);
-	ret = serial_in(up, UART_LSR) & UART_LSR_TEMT ? TIOCSER_TEMT : 0;
-	spin_unlock_irqrestore(&up->port.lock, flags);
-
-	return ret;
-}
-
-static unsigned int serial_pxa_get_mctrl(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned char status;
-	unsigned int ret;
-
-	status = serial_in(up, UART_MSR);
-
-	ret = 0;
-	if (status & UART_MSR_DCD)
-		ret |= TIOCM_CAR;
-	if (status & UART_MSR_RI)
-		ret |= TIOCM_RNG;
-	if (status & UART_MSR_DSR)
-		ret |= TIOCM_DSR;
-	if (status & UART_MSR_CTS)
-		ret |= TIOCM_CTS;
-	return ret;
-}
-
-static void serial_pxa_set_mctrl(struct uart_port *port, unsigned int mctrl)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned char mcr = 0;
-
-	if (mctrl & TIOCM_RTS)
-		mcr |= UART_MCR_RTS;
-	if (mctrl & TIOCM_DTR)
-		mcr |= UART_MCR_DTR;
-	if (mctrl & TIOCM_OUT1)
-		mcr |= UART_MCR_OUT1;
-	if (mctrl & TIOCM_OUT2)
-		mcr |= UART_MCR_OUT2;
-	if (mctrl & TIOCM_LOOP)
-		mcr |= UART_MCR_LOOP;
-
-	mcr |= up->mcr;
-
-	serial_out(up, UART_MCR, mcr);
-}
-
-static void serial_pxa_break_ctl(struct uart_port *port, int break_state)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned long flags;
-
-	spin_lock_irqsave(&up->port.lock, flags);
-	if (break_state == -1)
-		up->lcr |= UART_LCR_SBC;
-	else
-		up->lcr &= ~UART_LCR_SBC;
-	serial_out(up, UART_LCR, up->lcr);
-	spin_unlock_irqrestore(&up->port.lock, flags);
-}
-
-static int serial_pxa_startup(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned long flags;
-	int retval;
-
-	if (port->line == 3) /* HWUART */
-		up->mcr |= UART_MCR_AFE;
-	else
-		up->mcr = 0;
-
-	up->port.uartclk = clk_get_rate(up->clk);
-
-	/*
-	 * Allocate the IRQ
-	 */
-	retval = request_irq(up->port.irq, serial_pxa_irq, 0, up->name, up);
-	if (retval)
-		return retval;
-
-	/*
-	 * Clear the FIFO buffers and disable them.
-	 * (they will be reenabled in set_termios())
-	 */
-	serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO);
-	serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO |
-			UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
-	serial_out(up, UART_FCR, 0);
-
-	/*
-	 * Clear the interrupt registers.
-	 */
-	(void) serial_in(up, UART_LSR);
-	(void) serial_in(up, UART_RX);
-	(void) serial_in(up, UART_IIR);
-	(void) serial_in(up, UART_MSR);
-
-	/*
-	 * Now, initialize the UART
-	 */
-	serial_out(up, UART_LCR, UART_LCR_WLEN8);
-
-	spin_lock_irqsave(&up->port.lock, flags);
-	up->port.mctrl |= TIOCM_OUT2;
-	serial_pxa_set_mctrl(&up->port, up->port.mctrl);
-	spin_unlock_irqrestore(&up->port.lock, flags);
-
-	/*
-	 * Finally, enable interrupts.  Note: Modem status interrupts
-	 * are set via set_termios(), which will be occurring imminently
-	 * anyway, so we don't enable them here.
-	 */
-	up->ier = UART_IER_RLSI | UART_IER_RDI | UART_IER_RTOIE | UART_IER_UUE;
-	serial_out(up, UART_IER, up->ier);
-
-	/*
-	 * And clear the interrupt registers again for luck.
-	 */
-	(void) serial_in(up, UART_LSR);
-	(void) serial_in(up, UART_RX);
-	(void) serial_in(up, UART_IIR);
-	(void) serial_in(up, UART_MSR);
-
-	return 0;
-}
-
-static void serial_pxa_shutdown(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned long flags;
-
-	free_irq(up->port.irq, up);
-
-	/*
-	 * Disable interrupts from this port
-	 */
-	up->ier = 0;
-	serial_out(up, UART_IER, 0);
-
-	spin_lock_irqsave(&up->port.lock, flags);
-	up->port.mctrl &= ~TIOCM_OUT2;
-	serial_pxa_set_mctrl(&up->port, up->port.mctrl);
-	spin_unlock_irqrestore(&up->port.lock, flags);
-
-	/*
-	 * Disable break condition and FIFOs
-	 */
-	serial_out(up, UART_LCR, serial_in(up, UART_LCR) & ~UART_LCR_SBC);
-	serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO |
-				  UART_FCR_CLEAR_RCVR |
-				  UART_FCR_CLEAR_XMIT);
-	serial_out(up, UART_FCR, 0);
-}
-
-static void
-serial_pxa_set_termios(struct uart_port *port, struct ktermios *termios,
-		       struct ktermios *old)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned char cval, fcr = 0;
-	unsigned long flags;
-	unsigned int baud, quot;
-	unsigned int dll;
-
-	switch (termios->c_cflag & CSIZE) {
-	case CS5:
-		cval = UART_LCR_WLEN5;
-		break;
-	case CS6:
-		cval = UART_LCR_WLEN6;
-		break;
-	case CS7:
-		cval = UART_LCR_WLEN7;
-		break;
-	default:
-	case CS8:
-		cval = UART_LCR_WLEN8;
-		break;
-	}
-
-	if (termios->c_cflag & CSTOPB)
-		cval |= UART_LCR_STOP;
-	if (termios->c_cflag & PARENB)
-		cval |= UART_LCR_PARITY;
-	if (!(termios->c_cflag & PARODD))
-		cval |= UART_LCR_EPAR;
-
-	/*
-	 * Ask the core to calculate the divisor for us.
-	 */
-	baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
-	quot = uart_get_divisor(port, baud);
-
-	if ((up->port.uartclk / quot) < (2400 * 16))
-		fcr = UART_FCR_ENABLE_FIFO | UART_FCR_PXAR1;
-	else if ((up->port.uartclk / quot) < (230400 * 16))
-		fcr = UART_FCR_ENABLE_FIFO | UART_FCR_PXAR8;
-	else
-		fcr = UART_FCR_ENABLE_FIFO | UART_FCR_PXAR32;
-
-	/*
-	 * Ok, we're now changing the port state.  Do it with
-	 * interrupts disabled.
-	 */
-	spin_lock_irqsave(&up->port.lock, flags);
-
-	/*
-	 * Ensure the port will be enabled.
-	 * This is required especially for serial console.
-	 */
-	up->ier |= UART_IER_UUE;
-
-	/*
-	 * Update the per-port timeout.
-	 */
-	uart_update_timeout(port, termios->c_cflag, baud);
-
-	up->port.read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;
-	if (termios->c_iflag & INPCK)
-		up->port.read_status_mask |= UART_LSR_FE | UART_LSR_PE;
-	if (termios->c_iflag & (IGNBRK | BRKINT | PARMRK))
-		up->port.read_status_mask |= UART_LSR_BI;
-
-	/*
-	 * Characters to ignore
-	 */
-	up->port.ignore_status_mask = 0;
-	if (termios->c_iflag & IGNPAR)
-		up->port.ignore_status_mask |= UART_LSR_PE | UART_LSR_FE;
-	if (termios->c_iflag & IGNBRK) {
-		up->port.ignore_status_mask |= UART_LSR_BI;
-		/*
-		 * If we're ignoring parity and break indicators,
-		 * ignore overruns too (for real raw support).
-		 */
-		if (termios->c_iflag & IGNPAR)
-			up->port.ignore_status_mask |= UART_LSR_OE;
-	}
-
-	/*
-	 * ignore all characters if CREAD is not set
-	 */
-	if ((termios->c_cflag & CREAD) == 0)
-		up->port.ignore_status_mask |= UART_LSR_DR;
-
-	/*
-	 * CTS flow control flag and modem status interrupts
-	 */
-	up->ier &= ~UART_IER_MSI;
-	if (UART_ENABLE_MS(&up->port, termios->c_cflag))
-		up->ier |= UART_IER_MSI;
-
-	serial_out(up, UART_IER, up->ier);
-
-	if (termios->c_cflag & CRTSCTS)
-		up->mcr |= UART_MCR_AFE;
-	else
-		up->mcr &= ~UART_MCR_AFE;
-
-	serial_out(up, UART_LCR, cval | UART_LCR_DLAB);	/* set DLAB */
-	serial_out(up, UART_DLL, quot & 0xff);		/* LS of divisor */
-
-	/*
-	 * work around Errata #75 according to Intel(R) PXA27x Processor Family
-	 * Specification Update (Nov 2005)
-	 */
-	dll = serial_in(up, UART_DLL);
-	WARN_ON(dll != (quot & 0xff));
-
-	serial_out(up, UART_DLM, quot >> 8);		/* MS of divisor */
-	serial_out(up, UART_LCR, cval);			/* reset DLAB */
-	up->lcr = cval;					/* Save LCR */
-	serial_pxa_set_mctrl(&up->port, up->port.mctrl);
-	serial_out(up, UART_FCR, fcr);
-	spin_unlock_irqrestore(&up->port.lock, flags);
-}
-
-static void
-serial_pxa_pm(struct uart_port *port, unsigned int state,
-	      unsigned int oldstate)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	if (!state)
-		clk_prepare_enable(up->clk);
-	else
-		clk_disable_unprepare(up->clk);
-}
-
-static void serial_pxa_release_port(struct uart_port *port)
-{
-}
-
-static int serial_pxa_request_port(struct uart_port *port)
-{
-	return 0;
-}
-
-static void serial_pxa_config_port(struct uart_port *port, int flags)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	up->port.type = PORT_PXA;
-}
-
-static int
-serial_pxa_verify_port(struct uart_port *port, struct serial_struct *ser)
-{
-	/* we don't want the core code to modify any port params */
-	return -EINVAL;
-}
-
-static const char *
-serial_pxa_type(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	return up->name;
-}
-
-static struct uart_pxa_port *serial_pxa_ports[4];
-static struct uart_driver serial_pxa_reg;
-
-#ifdef CONFIG_SERIAL_PXA_CONSOLE
-
-#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
-
-/*
- *	Wait for transmitter & holding register to empty
- */
-static inline void wait_for_xmitr(struct uart_pxa_port *up)
-{
-	unsigned int status, tmout = 10000;
-
-	/* Wait up to 10ms for the character(s) to be sent. */
-	do {
-		status = serial_in(up, UART_LSR);
-
-		if (status & UART_LSR_BI)
-			up->lsr_break_flag = UART_LSR_BI;
-
-		if (--tmout == 0)
-			break;
-		udelay(1);
-	} while ((status & BOTH_EMPTY) != BOTH_EMPTY);
-
-	/* Wait up to 1s for flow control if necessary */
-	if (up->port.flags & UPF_CONS_FLOW) {
-		tmout = 1000000;
-		while (--tmout &&
-		       ((serial_in(up, UART_MSR) & UART_MSR_CTS) == 0))
-			udelay(1);
-	}
-}
-
-static void serial_pxa_console_putchar(struct uart_port *port, int ch)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	wait_for_xmitr(up);
-	serial_out(up, UART_TX, ch);
-}
-
-/*
- * Print a string to the serial port trying not to disturb
- * any possible real use of the port...
- *
- *	The console_lock must be held when we get here.
- */
-static void
-serial_pxa_console_write(struct console *co, const char *s, unsigned int count)
-{
-	struct uart_pxa_port *up = serial_pxa_ports[co->index];
-	unsigned int ier;
-	unsigned long flags;
-	int locked = 1;
-
-	clk_enable(up->clk);
-	local_irq_save(flags);
-	if (up->port.sysrq)
-		locked = 0;
-	else if (oops_in_progress)
-		locked = spin_trylock(&up->port.lock);
-	else
-		spin_lock(&up->port.lock);
-
-	/*
-	 *	First save the IER then disable the interrupts
-	 */
-	ier = serial_in(up, UART_IER);
-	serial_out(up, UART_IER, UART_IER_UUE);
-
-	uart_console_write(&up->port, s, count, serial_pxa_console_putchar);
-
-	/*
-	 *	Finally, wait for transmitter to become empty
-	 *	and restore the IER
-	 */
-	wait_for_xmitr(up);
-	serial_out(up, UART_IER, ier);
-
-	if (locked)
-		spin_unlock(&up->port.lock);
-	local_irq_restore(flags);
-	clk_disable(up->clk);
-
-}
-
-#ifdef CONFIG_CONSOLE_POLL
-/*
- * Console polling routines for writing and reading from the uart while
- * in an interrupt or debug context.
- */
-
-static int serial_pxa_get_poll_char(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned char lsr = serial_in(up, UART_LSR);
-
-	while (!(lsr & UART_LSR_DR))
-		lsr = serial_in(up, UART_LSR);
-
-	return serial_in(up, UART_RX);
-}
-
-
-static void serial_pxa_put_poll_char(struct uart_port *port,
-			 unsigned char c)
-{
-	unsigned int ier;
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	/*
-	 *	First save the IER then disable the interrupts
-	 */
-	ier = serial_in(up, UART_IER);
-	serial_out(up, UART_IER, UART_IER_UUE);
-
-	wait_for_xmitr(up);
-	/*
-	 *	Send the character out.
-	 */
-	serial_out(up, UART_TX, c);
-
-	/*
-	 *	Finally, wait for transmitter to become empty
-	 *	and restore the IER
-	 */
-	wait_for_xmitr(up);
-	serial_out(up, UART_IER, ier);
-}
-
-#endif /* CONFIG_CONSOLE_POLL */
-
-static int __init
-serial_pxa_console_setup(struct console *co, char *options)
-{
-	struct uart_pxa_port *up;
-	int baud = 9600;
-	int bits = 8;
-	int parity = 'n';
-	int flow = 'n';
-
-	if (co->index == -1 || co->index >= serial_pxa_reg.nr)
-		co->index = 0;
-	up = serial_pxa_ports[co->index];
-	if (!up)
-		return -ENODEV;
-
-	if (options)
-		uart_parse_options(options, &baud, &parity, &bits, &flow);
-
-	return uart_set_options(&up->port, co, baud, parity, bits, flow);
-}
-
-static struct console serial_pxa_console = {
-	.name		= "ttyS",
-	.write		= serial_pxa_console_write,
-	.device		= uart_console_device,
-	.setup		= serial_pxa_console_setup,
-	.flags		= CON_PRINTBUFFER,
-	.index		= -1,
-	.data		= &serial_pxa_reg,
-};
-
-#define PXA_CONSOLE	&serial_pxa_console
-#else
-#define PXA_CONSOLE	NULL
-#endif
-
-static struct uart_ops serial_pxa_pops = {
-	.tx_empty	= serial_pxa_tx_empty,
-	.set_mctrl	= serial_pxa_set_mctrl,
-	.get_mctrl	= serial_pxa_get_mctrl,
-	.stop_tx	= serial_pxa_stop_tx,
-	.start_tx	= serial_pxa_start_tx,
-	.stop_rx	= serial_pxa_stop_rx,
-	.enable_ms	= serial_pxa_enable_ms,
-	.break_ctl	= serial_pxa_break_ctl,
-	.startup	= serial_pxa_startup,
-	.shutdown	= serial_pxa_shutdown,
-	.set_termios	= serial_pxa_set_termios,
-	.pm		= serial_pxa_pm,
-	.type		= serial_pxa_type,
-	.release_port	= serial_pxa_release_port,
-	.request_port	= serial_pxa_request_port,
-	.config_port	= serial_pxa_config_port,
-	.verify_port	= serial_pxa_verify_port,
-#if defined(CONFIG_CONSOLE_POLL) && defined(CONFIG_SERIAL_PXA_CONSOLE)
-	.poll_get_char = serial_pxa_get_poll_char,
-	.poll_put_char = serial_pxa_put_poll_char,
-#endif
-};
-
-static struct uart_driver serial_pxa_reg = {
-	.owner		= THIS_MODULE,
-	.driver_name	= "PXA serial",
-	.dev_name	= "ttyS",
-	.major		= TTY_MAJOR,
-	.minor		= 64,
-	.nr		= 4,
-	.cons		= PXA_CONSOLE,
-};
-
-#ifdef CONFIG_PM
-static int serial_pxa_suspend(struct device *dev)
-{
-        struct uart_pxa_port *sport = dev_get_drvdata(dev);
-
-        if (sport)
-                uart_suspend_port(&serial_pxa_reg, &sport->port);
-
-        return 0;
-}
-
-static int serial_pxa_resume(struct device *dev)
-{
-        struct uart_pxa_port *sport = dev_get_drvdata(dev);
-
-        if (sport)
-                uart_resume_port(&serial_pxa_reg, &sport->port);
-
-        return 0;
-}
-
-static const struct dev_pm_ops serial_pxa_pm_ops = {
-	.suspend	= serial_pxa_suspend,
-	.resume		= serial_pxa_resume,
-};
-#endif
-
-static const struct of_device_id serial_pxa_dt_ids[] = {
-	{ .compatible = "mrvl,pxa-uart", },
-	{ .compatible = "mrvl,mmp-uart", },
-	{}
-};
-MODULE_DEVICE_TABLE(of, serial_pxa_dt_ids);
-
-static int serial_pxa_probe_dt(struct platform_device *pdev,
-			       struct uart_pxa_port *sport)
-{
-	struct device_node *np = pdev->dev.of_node;
-	int ret;
-
-	if (!np)
-		return 1;
-
-	ret = of_alias_get_id(np, "serial");
-	if (ret < 0) {
-		dev_err(&pdev->dev, "failed to get alias id, errno %d\n", ret);
-		return ret;
-	}
-	sport->port.line = ret;
-	return 0;
-}
-
-static int serial_pxa_probe(struct platform_device *dev)
-{
-	struct uart_pxa_port *sport;
-	struct resource *mmres, *irqres;
-	int ret;
-
-	mmres = platform_get_resource(dev, IORESOURCE_MEM, 0);
-	irqres = platform_get_resource(dev, IORESOURCE_IRQ, 0);
-	if (!mmres || !irqres)
-		return -ENODEV;
-
-	sport = kzalloc(sizeof(struct uart_pxa_port), GFP_KERNEL);
-	if (!sport)
-		return -ENOMEM;
-
-	sport->clk = clk_get(&dev->dev, NULL);
-	if (IS_ERR(sport->clk)) {
-		ret = PTR_ERR(sport->clk);
-		goto err_free;
-	}
-
-	ret = clk_prepare(sport->clk);
-	if (ret) {
-		clk_put(sport->clk);
-		goto err_free;
-	}
-
-	sport->port.type = PORT_PXA;
-	sport->port.iotype = UPIO_MEM;
-	sport->port.mapbase = mmres->start;
-	sport->port.irq = irqres->start;
-	sport->port.fifosize = 64;
-	sport->port.ops = &serial_pxa_pops;
-	sport->port.dev = &dev->dev;
-	sport->port.flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF;
-	sport->port.uartclk = clk_get_rate(sport->clk);
-
-	ret = serial_pxa_probe_dt(dev, sport);
-	if (ret > 0)
-		sport->port.line = dev->id;
-	else if (ret < 0)
-		goto err_clk;
-	snprintf(sport->name, PXA_NAME_LEN - 1, "UART%d", sport->port.line + 1);
-
-	sport->port.membase = ioremap(mmres->start, resource_size(mmres));
-	if (!sport->port.membase) {
-		ret = -ENOMEM;
-		goto err_clk;
-	}
-
-	serial_pxa_ports[sport->port.line] = sport;
-
-	uart_add_one_port(&serial_pxa_reg, &sport->port);
-	platform_set_drvdata(dev, sport);
-
-	return 0;
-
- err_clk:
-	clk_unprepare(sport->clk);
-	clk_put(sport->clk);
- err_free:
-	kfree(sport);
-	return ret;
-}
-
-static int serial_pxa_remove(struct platform_device *dev)
-{
-	struct uart_pxa_port *sport = platform_get_drvdata(dev);
-
-	uart_remove_one_port(&serial_pxa_reg, &sport->port);
-
-	clk_unprepare(sport->clk);
-	clk_put(sport->clk);
-	kfree(sport);
-
-	return 0;
-}
-
-static struct platform_driver serial_pxa_driver = {
-        .probe          = serial_pxa_probe,
-        .remove         = serial_pxa_remove,
-
-	.driver		= {
-	        .name	= "pxa2xx-uart",
-#ifdef CONFIG_PM
-		.pm	= &serial_pxa_pm_ops,
-#endif
-		.of_match_table = serial_pxa_dt_ids,
-	},
-};
-
-static int __init serial_pxa_init(void)
-{
-	int ret;
-
-	ret = uart_register_driver(&serial_pxa_reg);
-	if (ret != 0)
-		return ret;
-
-	ret = platform_driver_register(&serial_pxa_driver);
-	if (ret != 0)
-		uart_unregister_driver(&serial_pxa_reg);
-
-	return ret;
-}
-
-static void __exit serial_pxa_exit(void)
-{
-	platform_driver_unregister(&serial_pxa_driver);
-	uart_unregister_driver(&serial_pxa_reg);
-}
-
-module_init(serial_pxa_init);
-module_exit(serial_pxa_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:pxa2xx-uart");
-- 
2.6.2

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

* [PATCH v4 1/2] serial: rewrite pxa2xx-uart to use 8250_core
@ 2015-12-09 22:28               ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2015-12-09 22:28 UTC (permalink / raw)
  To: linux-arm-kernel

pxa2xx-uart was a separate uart platform driver. It was declaring
the same device names and numbers as 8250 driver. As a result,
it was impossible to use 8250 driver on PXA SoCs.

Upon closer examination pxa2xx-uart turned out to be a clone of
8250_core driver.

Workaround for Erratum #19 according to Marvel(R) PXA270M Processor
Specification Update (April 19, 2010) is dropped. 8250_core reads
from FIFO immediately after checking DR bit in LSR.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Reviewed-by: James Cameron <quozl@laptop.org>
Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 The patch was reviewed/acked at version 3. Changes in version 4
 are simple unbitrotting, so the flags are carried over.

 changes v3..v4
 * remove owner field from platform_driver structure
 * make of_device_id structure constant
 * use CONFIG_SERIAL_8250_PXA instead of CONFIG_SERIAL_PXA

 changes v2..v3
 * remove devm_free/put as suggested by Heikki Krogerus
 * use SET_SYSTEM_SLEEP_PM_OPS macro to set pm ops as suggested
   by Heikki Krogerus

 changes v1..v2
 * actually implement workaround for E74 in dl_write as spooted
   by James Cameron
 * added comment about E19 in commit message

 arch/arm/configs/am200epdkit_defconfig    |   5 +-
 arch/arm/configs/cm_x2xx_defconfig        |   5 +-
 arch/arm/configs/cm_x300_defconfig        |   5 +-
 arch/arm/configs/colibri_pxa270_defconfig |   5 +-
 arch/arm/configs/colibri_pxa300_defconfig |   5 +-
 arch/arm/configs/corgi_defconfig          |   6 +-
 arch/arm/configs/em_x270_defconfig        |   5 +-
 arch/arm/configs/ezx_defconfig            |   5 +-
 arch/arm/configs/h5000_defconfig          |   5 +-
 arch/arm/configs/imote2_defconfig         |   5 +-
 arch/arm/configs/lpd270_defconfig         |   5 +-
 arch/arm/configs/lubbock_defconfig        |   5 +-
 arch/arm/configs/mainstone_defconfig      |   5 +-
 arch/arm/configs/mmp2_defconfig           |   5 +-
 arch/arm/configs/pcm027_defconfig         |   5 +-
 arch/arm/configs/pxa168_defconfig         |   5 +-
 arch/arm/configs/pxa255-idp_defconfig     |   5 +-
 arch/arm/configs/pxa3xx_defconfig         |   5 +-
 arch/arm/configs/pxa910_defconfig         |   5 +-
 arch/arm/configs/raumfeld_defconfig       |   5 +-
 arch/arm/configs/spitz_defconfig          |   6 +-
 arch/arm/configs/trizeps4_defconfig       |   5 +-
 arch/arm/configs/viper_defconfig          |   6 +-
 arch/arm/configs/xcep_defconfig           |   5 +-
 drivers/tty/serial/8250/8250_pxa.c        | 177 ++++++
 drivers/tty/serial/8250/Kconfig           |   9 +
 drivers/tty/serial/8250/Makefile          |   1 +
 drivers/tty/serial/Kconfig                |  23 -
 drivers/tty/serial/Makefile               |   1 -
 drivers/tty/serial/pxa.c                  | 968 ------------------------------
 30 files changed, 259 insertions(+), 1043 deletions(-)
 create mode 100644 drivers/tty/serial/8250/8250_pxa.c
 delete mode 100644 drivers/tty/serial/pxa.c

diff --git a/arch/arm/configs/am200epdkit_defconfig b/arch/arm/configs/am200epdkit_defconfig
index f0dea52..5f78ee7 100644
--- a/arch/arm/configs/am200epdkit_defconfig
+++ b/arch/arm/configs/am200epdkit_defconfig
@@ -60,8 +60,9 @@ CONFIG_BLK_DEV_IDECS=m
 CONFIG_NETDEVICES=y
 CONFIG_NET_ETHERNET=y
 CONFIG_SMC91X=m
-CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PXA=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 # CONFIG_HWMON is not set
diff --git a/arch/arm/configs/cm_x2xx_defconfig b/arch/arm/configs/cm_x2xx_defconfig
index 3b32d5f..f1ae370 100644
--- a/arch/arm/configs/cm_x2xx_defconfig
+++ b/arch/arm/configs/cm_x2xx_defconfig
@@ -96,8 +96,9 @@ CONFIG_KEYBOARD_PXA27x=m
 CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_TOUCHSCREEN_UCB1400=m
 # CONFIG_SERIO_SERPORT is not set
-CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PXA=y
 CONFIG_LEGACY_PTY_COUNT=16
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/cm_x300_defconfig b/arch/arm/configs/cm_x300_defconfig
index 7df040e..07bf9b2 100644
--- a/arch/arm/configs/cm_x300_defconfig
+++ b/arch/arm/configs/cm_x300_defconfig
@@ -80,8 +80,9 @@ CONFIG_TOUCHSCREEN_WM97XX=m
 # CONFIG_TOUCHSCREEN_WM9713 is not set
 # CONFIG_SERIO is not set
 # CONFIG_LEGACY_PTYS is not set
-CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PXA=y
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
 CONFIG_I2C_PXA=y
diff --git a/arch/arm/configs/colibri_pxa270_defconfig b/arch/arm/configs/colibri_pxa270_defconfig
index 18c311a..5ea17d4 100644
--- a/arch/arm/configs/colibri_pxa270_defconfig
+++ b/arch/arm/configs/colibri_pxa270_defconfig
@@ -103,8 +103,9 @@ CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=m
 CONFIG_SERIO_LIBPS2=y
-CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PXA=y
 CONFIG_HW_RANDOM=y
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
diff --git a/arch/arm/configs/colibri_pxa300_defconfig b/arch/arm/configs/colibri_pxa300_defconfig
index be02fe2..e12af54 100644
--- a/arch/arm/configs/colibri_pxa300_defconfig
+++ b/arch/arm/configs/colibri_pxa300_defconfig
@@ -31,8 +31,9 @@ CONFIG_INPUT_EVDEV=y
 # CONFIG_INPUT_MOUSE is not set
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_GPIO_ROTARY_ENCODER=y
-CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PXA=y
 CONFIG_HW_RANDOM=y
 CONFIG_DEBUG_GPIO=y
 # CONFIG_HWMON is not set
diff --git a/arch/arm/configs/corgi_defconfig b/arch/arm/configs/corgi_defconfig
index c1470a0..d94212b 100644
--- a/arch/arm/configs/corgi_defconfig
+++ b/arch/arm/configs/corgi_defconfig
@@ -131,10 +131,10 @@ CONFIG_TOUCHSCREEN_ADS7846=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=m
 # CONFIG_SERIO is not set
-CONFIG_SERIAL_8250=m
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_CS=m
-CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_8250_PXA=y
 # CONFIG_LEGACY_PTYS is not set
 CONFIG_I2C=y
 CONFIG_I2C_PXA=y
diff --git a/arch/arm/configs/em_x270_defconfig b/arch/arm/configs/em_x270_defconfig
index 8e10df7..8ac6b84 100644
--- a/arch/arm/configs/em_x270_defconfig
+++ b/arch/arm/configs/em_x270_defconfig
@@ -90,8 +90,9 @@ CONFIG_TOUCHSCREEN_WM97XX=m
 # CONFIG_TOUCHSCREEN_WM9705 is not set
 # CONFIG_TOUCHSCREEN_WM9713 is not set
 # CONFIG_SERIO_SERPORT is not set
-CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PXA=y
 CONFIG_LEGACY_PTY_COUNT=16
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/ezx_defconfig b/arch/arm/configs/ezx_defconfig
index ea316c4..5d365f4 100644
--- a/arch/arm/configs/ezx_defconfig
+++ b/arch/arm/configs/ezx_defconfig
@@ -214,8 +214,9 @@ CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=y
 CONFIG_INPUT_PCAP=y
 # CONFIG_SERIO is not set
-CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PXA=y
 CONFIG_LEGACY_PTY_COUNT=8
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/h5000_defconfig b/arch/arm/configs/h5000_defconfig
index 37903e3..d366c87 100644
--- a/arch/arm/configs/h5000_defconfig
+++ b/arch/arm/configs/h5000_defconfig
@@ -47,8 +47,9 @@ CONFIG_MTD_PHYSMAP=y
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
-CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PXA=y
 CONFIG_LEGACY_PTY_COUNT=32
 # CONFIG_HW_RANDOM is not set
 # CONFIG_HWMON is not set
diff --git a/arch/arm/configs/imote2_defconfig b/arch/arm/configs/imote2_defconfig
index 18e59fe..0cc503b 100644
--- a/arch/arm/configs/imote2_defconfig
+++ b/arch/arm/configs/imote2_defconfig
@@ -192,8 +192,9 @@ CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=y
 # CONFIG_SERIO is not set
-CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PXA=y
 CONFIG_LEGACY_PTY_COUNT=8
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/lpd270_defconfig b/arch/arm/configs/lpd270_defconfig
index 1c8c9ee..7774fb2 100644
--- a/arch/arm/configs/lpd270_defconfig
+++ b/arch/arm/configs/lpd270_defconfig
@@ -38,8 +38,9 @@ CONFIG_SMC91X=y
 CONFIG_INPUT_EVDEV=y
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO_SERPORT is not set
-CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PXA=y
 # CONFIG_HW_RANDOM is not set
 CONFIG_FB=y
 CONFIG_FB_PXA=y
diff --git a/arch/arm/configs/lubbock_defconfig b/arch/arm/configs/lubbock_defconfig
index c4ba274..d2c18e6 100644
--- a/arch/arm/configs/lubbock_defconfig
+++ b/arch/arm/configs/lubbock_defconfig
@@ -37,8 +37,9 @@ CONFIG_PCMCIA_PCNET=y
 CONFIG_INPUT_EVDEV=y
 # CONFIG_SERIO_SERPORT is not set
 CONFIG_SERIO_SA1111=y
-CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PXA=y
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_USB_GADGET=y
 CONFIG_USB_G_SERIAL=m
diff --git a/arch/arm/configs/mainstone_defconfig b/arch/arm/configs/mainstone_defconfig
index 04efa1b..ece034c 100644
--- a/arch/arm/configs/mainstone_defconfig
+++ b/arch/arm/configs/mainstone_defconfig
@@ -34,8 +34,9 @@ CONFIG_SMC91X=y
 CONFIG_INPUT_EVDEV=y
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO_SERPORT is not set
-CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PXA=y
 CONFIG_FB=y
 CONFIG_FB_PXA=y
 # CONFIG_VGA_CONSOLE is not set
diff --git a/arch/arm/configs/mmp2_defconfig b/arch/arm/configs/mmp2_defconfig
index f1cb95e..a56f2a0 100644
--- a/arch/arm/configs/mmp2_defconfig
+++ b/arch/arm/configs/mmp2_defconfig
@@ -44,8 +44,9 @@ CONFIG_SMC91X=y
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
-CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PXA=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/pcm027_defconfig b/arch/arm/configs/pcm027_defconfig
index b5624e3..93bc85c 100644
--- a/arch/arm/configs/pcm027_defconfig
+++ b/arch/arm/configs/pcm027_defconfig
@@ -60,8 +60,9 @@ CONFIG_SMC91X=y
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
-CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PXA=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/pxa168_defconfig b/arch/arm/configs/pxa168_defconfig
index 74d7e01..8dc8a99 100644
--- a/arch/arm/configs/pxa168_defconfig
+++ b/arch/arm/configs/pxa168_defconfig
@@ -40,8 +40,9 @@ CONFIG_SMC91X=y
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
-CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PXA=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 # CONFIG_HWMON is not set
diff --git a/arch/arm/configs/pxa255-idp_defconfig b/arch/arm/configs/pxa255-idp_defconfig
index 917a070b..688578d 100644
--- a/arch/arm/configs/pxa255-idp_defconfig
+++ b/arch/arm/configs/pxa255-idp_defconfig
@@ -35,8 +35,9 @@ CONFIG_SMC91X=y
 CONFIG_INPUT_EVDEV=y
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO_SERPORT is not set
-CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PXA=y
 CONFIG_FB=y
 CONFIG_FB_PXA=y
 # CONFIG_VGA_CONSOLE is not set
diff --git a/arch/arm/configs/pxa3xx_defconfig b/arch/arm/configs/pxa3xx_defconfig
index 5f337d7..1dedeaf 100644
--- a/arch/arm/configs/pxa3xx_defconfig
+++ b/arch/arm/configs/pxa3xx_defconfig
@@ -56,8 +56,9 @@ CONFIG_KEYBOARD_PXA27x=y
 CONFIG_KEYBOARD_PXA930_ROTARY=y
 CONFIG_MOUSE_PXA930_TRKBALL=y
 CONFIG_INPUT_TOUCHSCREEN=y
-CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PXA=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/pxa910_defconfig b/arch/arm/configs/pxa910_defconfig
index 3bb7771..9be8045 100644
--- a/arch/arm/configs/pxa910_defconfig
+++ b/arch/arm/configs/pxa910_defconfig
@@ -40,8 +40,9 @@ CONFIG_SMC91X=y
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
-CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PXA=y
 CONFIG_SPI=y
 CONFIG_FB=y
 CONFIG_MMP_DISP=y
diff --git a/arch/arm/configs/raumfeld_defconfig b/arch/arm/configs/raumfeld_defconfig
index 3d833ae..b4c23e3 100644
--- a/arch/arm/configs/raumfeld_defconfig
+++ b/arch/arm/configs/raumfeld_defconfig
@@ -67,8 +67,9 @@ CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_TOUCHSCREEN_EETI=m
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_GPIO_ROTARY_ENCODER=y
-CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PXA=y
 CONFIG_HW_RANDOM=y
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
diff --git a/arch/arm/configs/spitz_defconfig b/arch/arm/configs/spitz_defconfig
index a1ede19..fb07d0b 100644
--- a/arch/arm/configs/spitz_defconfig
+++ b/arch/arm/configs/spitz_defconfig
@@ -128,10 +128,10 @@ CONFIG_TOUCHSCREEN_ADS7846=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=m
 # CONFIG_SERIO is not set
-CONFIG_SERIAL_8250=m
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_CS=m
-CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_8250_PXA=y
 # CONFIG_LEGACY_PTYS is not set
 CONFIG_SPI=y
 CONFIG_SPI_PXA2XX=y
diff --git a/arch/arm/configs/trizeps4_defconfig b/arch/arm/configs/trizeps4_defconfig
index 4bc8700..cbd0226 100644
--- a/arch/arm/configs/trizeps4_defconfig
+++ b/arch/arm/configs/trizeps4_defconfig
@@ -132,8 +132,9 @@ CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=m
 CONFIG_SERIO_LIBPS2=y
-CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PXA=y
 CONFIG_HW_RANDOM=y
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
diff --git a/arch/arm/configs/viper_defconfig b/arch/arm/configs/viper_defconfig
index 0d717a5..6e5ca7e 100644
--- a/arch/arm/configs/viper_defconfig
+++ b/arch/arm/configs/viper_defconfig
@@ -101,11 +101,11 @@ CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=m
 # CONFIG_CONSOLE_TRANSLATIONS is not set
 # CONFIG_VT_CONSOLE is not set
-CONFIG_SERIAL_8250=m
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_NR_UARTS=5
 CONFIG_SERIAL_8250_RUNTIME_UARTS=5
-CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_8250_PXA=y
 # CONFIG_LEGACY_PTYS is not set
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
diff --git a/arch/arm/configs/xcep_defconfig b/arch/arm/configs/xcep_defconfig
index 721832f..007967a 100644
--- a/arch/arm/configs/xcep_defconfig
+++ b/arch/arm/configs/xcep_defconfig
@@ -60,8 +60,9 @@ CONFIG_NET_ETHERNET=y
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
 # CONFIG_DEVKMEM is not set
-CONFIG_SERIAL_PXA=y
-CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PXA=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=m
diff --git a/drivers/tty/serial/8250/8250_pxa.c b/drivers/tty/serial/8250/8250_pxa.c
new file mode 100644
index 0000000..6a14df0
--- /dev/null
+++ b/drivers/tty/serial/8250/8250_pxa.c
@@ -0,0 +1,177 @@
+/*
+ *  drivers/tty/serial/8250/8250_pxa.c -- driver for PXA on-board UARTS
+ *  Copyright:	(C) 2013 Sergei Ianovich <ynvich@gmail.com>
+ *
+ *  replaces drivers/serial/pxa.c by Nicolas Pitre
+ *  Created:	Feb 20, 2003
+ *  Copyright:	(C) 2003 Monta Vista Software, Inc.
+ *
+ *  Based on drivers/serial/8250.c by Russell King.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/serial_8250.h>
+#include <linux/serial_core.h>
+#include <linux/serial_reg.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
+#include <linux/pm_runtime.h>
+
+#include "8250.h"
+
+struct pxa8250_data {
+	int			line;
+	struct clk		*clk;
+};
+
+#ifdef CONFIG_PM
+static int serial_pxa_suspend(struct device *dev)
+{
+	struct pxa8250_data *data = dev_get_drvdata(dev);
+
+	serial8250_suspend_port(data->line);
+
+	return 0;
+}
+
+static int serial_pxa_resume(struct device *dev)
+{
+	struct pxa8250_data *data = dev_get_drvdata(dev);
+
+	serial8250_resume_port(data->line);
+
+	return 0;
+}
+#endif
+
+static const struct dev_pm_ops serial_pxa_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(serial_pxa_suspend, serial_pxa_resume)
+};
+
+static const struct of_device_id serial_pxa_dt_ids[] = {
+	{ .compatible = "mrvl,pxa-uart", },
+	{ .compatible = "mrvl,mmp-uart", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, serial_pxa_dt_ids);
+
+/* Uart divisor latch write */
+static void serial_pxa_dl_write(struct uart_8250_port *up, int value)
+{
+	unsigned int dll;
+
+	serial_out(up, UART_DLL, value & 0xff);
+	/*
+	 * work around Erratum #74 according to Marvel(R) PXA270M Processor
+	 * Specification Update (April 19, 2010)
+	 */
+	dll = serial_in(up, UART_DLL);
+	WARN_ON(dll != (value & 0xff));
+
+	serial_out(up, UART_DLM, value >> 8 & 0xff);
+}
+
+
+static void serial_pxa_pm(struct uart_port *port, unsigned int state,
+	      unsigned int oldstate)
+{
+	struct pxa8250_data *data = port->private_data;
+
+	if (!state)
+		clk_prepare_enable(data->clk);
+	else
+		clk_disable_unprepare(data->clk);
+}
+
+static int serial_pxa_probe(struct platform_device *pdev)
+{
+	struct uart_8250_port uart = {};
+	struct pxa8250_data *data;
+	struct resource *mmres, *irqres;
+	int ret;
+
+	mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	irqres = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!mmres || !irqres)
+		return -ENODEV;
+
+	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(data->clk))
+		return PTR_ERR(data->clk);
+
+	ret = clk_prepare(data->clk);
+	if (ret)
+		return ret;
+
+	uart.port.type = PORT_XSCALE;
+	uart.port.iotype = UPIO_MEM32;
+	uart.port.mapbase = mmres->start;
+	uart.port.regshift = 2;
+	uart.port.irq = irqres->start;
+	uart.port.fifosize = 64;
+	uart.port.flags = UPF_IOREMAP | UPF_SKIP_TEST;
+	uart.port.dev = &pdev->dev;
+	uart.port.uartclk = clk_get_rate(data->clk);
+	uart.port.pm = serial_pxa_pm;
+	uart.port.private_data = data;
+	uart.dl_write = serial_pxa_dl_write;
+
+	ret = serial8250_register_8250_port(&uart);
+	if (ret < 0)
+		goto err_clk;
+
+	data->line = ret;
+
+	platform_set_drvdata(pdev, data);
+
+	return 0;
+
+ err_clk:
+	clk_unprepare(data->clk);
+	return ret;
+}
+
+static int serial_pxa_remove(struct platform_device *pdev)
+{
+	struct pxa8250_data *data = platform_get_drvdata(pdev);
+
+	serial8250_unregister_port(data->line);
+
+	clk_unprepare(data->clk);
+
+	return 0;
+}
+
+static struct platform_driver serial_pxa_driver = {
+	.probe          = serial_pxa_probe,
+	.remove         = serial_pxa_remove,
+
+	.driver		= {
+		.name	= "pxa2xx-uart",
+		.pm	= &serial_pxa_pm_ops,
+		.of_match_table = serial_pxa_dt_ids,
+	},
+};
+
+module_platform_driver(serial_pxa_driver);
+
+MODULE_AUTHOR("Sergei Ianovich");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:pxa2xx-uart");
diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
index 6412f14..48b6253 100644
--- a/drivers/tty/serial/8250/Kconfig
+++ b/drivers/tty/serial/8250/Kconfig
@@ -378,3 +378,12 @@ config SERIAL_8250_MID
 	  Selecting this option will enable handling of the extra features
 	  present on the UART found on Intel Medfield SOC and various other
 	  Intel platforms.
+
+config SERIAL_8250_PXA
+	tristate "PXA serial port support"
+	depends on SERIAL_8250 && (ARCH_PXA || ARCH_MMP)
+	help
+	  If you have a machine based on an Intel XScale PXA2xx CPU you
+	  can enable its onboard serial ports by enabling this option.
+
+	  If you choose M here, the module name will be 8250_pxa.
diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile
index e177f86..7e54413 100644
--- a/drivers/tty/serial/8250/Makefile
+++ b/drivers/tty/serial/8250/Makefile
@@ -28,5 +28,6 @@ obj-$(CONFIG_SERIAL_8250_MT6577)	+= 8250_mtk.o
 obj-$(CONFIG_SERIAL_8250_UNIPHIER)	+= 8250_uniphier.o
 obj-$(CONFIG_SERIAL_8250_INGENIC)	+= 8250_ingenic.o
 obj-$(CONFIG_SERIAL_8250_MID)		+= 8250_mid.o
+obj-$(CONFIG_SERIAL_8250_PXA)		+= 8250_pxa.o
 
 CFLAGS_8250_ingenic.o += -I$(srctree)/scripts/dtc/libfdt
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index f38beb2..8c40c83 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -435,29 +435,6 @@ config SERIAL_MPSC_CONSOLE
 	help
 	  Say Y here if you want to support a serial console on a Marvell MPSC.
 
-config SERIAL_PXA
-	bool "PXA serial port support"
-	depends on ARCH_PXA || ARCH_MMP
-	select SERIAL_CORE
-	help
-	  If you have a machine based on an Intel XScale PXA2xx CPU you
-	  can enable its onboard serial ports by enabling this option.
-
-config SERIAL_PXA_CONSOLE
-	bool "Console on PXA serial port"
-	depends on SERIAL_PXA
-	select SERIAL_CORE_CONSOLE
-	help
-	  If you have enabled the serial port on the Intel XScale PXA
-	  CPU you can make it the console by answering Y to this option.
-
-	  Even if you say Y here, the currently visible virtual console
-	  (/dev/tty0) will still be used as the system console by default, but
-	  you can alter that using a kernel command line option such as
-	  "console=ttySA0". (Try "man bootparam" or see the documentation of
-	  your boot loader (lilo or loadlin) about how to pass options to the
-	  kernel at boot time.)
-
 config SERIAL_SA1100
 	bool "SA1100 serial port support"
 	depends on ARCH_SA1100
diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile
index 5ab4111..5cd5c68 100644
--- a/drivers/tty/serial/Makefile
+++ b/drivers/tty/serial/Makefile
@@ -23,7 +23,6 @@ obj-$(CONFIG_SERIAL_8250) += 8250/
 obj-$(CONFIG_SERIAL_AMBA_PL010) += amba-pl010.o
 obj-$(CONFIG_SERIAL_AMBA_PL011) += amba-pl011.o
 obj-$(CONFIG_SERIAL_CLPS711X) += clps711x.o
-obj-$(CONFIG_SERIAL_PXA) += pxa.o
 obj-$(CONFIG_SERIAL_PNX8XXX) += pnx8xxx_uart.o
 obj-$(CONFIG_SERIAL_SA1100) += sa1100.o
 obj-$(CONFIG_SERIAL_BCM63XX) += bcm63xx_uart.o
diff --git a/drivers/tty/serial/pxa.c b/drivers/tty/serial/pxa.c
deleted file mode 100644
index 9becba6..0000000
--- a/drivers/tty/serial/pxa.c
+++ /dev/null
@@ -1,968 +0,0 @@
-/*
- *  Based on drivers/serial/8250.c by Russell King.
- *
- *  Author:	Nicolas Pitre
- *  Created:	Feb 20, 2003
- *  Copyright:	(C) 2003 Monta Vista Software, Inc.
- *
- * 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.
- *
- * Note 1: This driver is made separate from the already too overloaded
- * 8250.c because it needs some kirks of its own and that'll make it
- * easier to add DMA support.
- *
- * Note 2: I'm too sick of device allocation policies for serial ports.
- * If someone else wants to request an "official" allocation of major/minor
- * for this driver please be my guest.  And don't forget that new hardware
- * to come from Intel might have more than 3 or 4 of those UARTs.  Let's
- * hope for a better port registration and dynamic device allocation scheme
- * with the serial core maintainer satisfaction to appear soon.
- */
-
-
-#if defined(CONFIG_SERIAL_PXA_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-#define SUPPORT_SYSRQ
-#endif
-
-#include <linux/module.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-#include <linux/console.h>
-#include <linux/sysrq.h>
-#include <linux/serial_reg.h>
-#include <linux/circ_buf.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/of.h>
-#include <linux/platform_device.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/serial_core.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-
-#define PXA_NAME_LEN		8
-
-struct uart_pxa_port {
-	struct uart_port        port;
-	unsigned char           ier;
-	unsigned char           lcr;
-	unsigned char           mcr;
-	unsigned int            lsr_break_flag;
-	struct clk		*clk;
-	char			name[PXA_NAME_LEN];
-};
-
-static inline unsigned int serial_in(struct uart_pxa_port *up, int offset)
-{
-	offset <<= 2;
-	return readl(up->port.membase + offset);
-}
-
-static inline void serial_out(struct uart_pxa_port *up, int offset, int value)
-{
-	offset <<= 2;
-	writel(value, up->port.membase + offset);
-}
-
-static void serial_pxa_enable_ms(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	up->ier |= UART_IER_MSI;
-	serial_out(up, UART_IER, up->ier);
-}
-
-static void serial_pxa_stop_tx(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	if (up->ier & UART_IER_THRI) {
-		up->ier &= ~UART_IER_THRI;
-		serial_out(up, UART_IER, up->ier);
-	}
-}
-
-static void serial_pxa_stop_rx(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	up->ier &= ~UART_IER_RLSI;
-	up->port.read_status_mask &= ~UART_LSR_DR;
-	serial_out(up, UART_IER, up->ier);
-}
-
-static inline void receive_chars(struct uart_pxa_port *up, int *status)
-{
-	unsigned int ch, flag;
-	int max_count = 256;
-
-	do {
-		/* work around Errata #20 according to
-		 * Intel(R) PXA27x Processor Family
-		 * Specification Update (May 2005)
-		 *
-		 * Step 2
-		 * Disable the Reciever Time Out Interrupt via IER[RTOEI]
-		 */
-		up->ier &= ~UART_IER_RTOIE;
-		serial_out(up, UART_IER, up->ier);
-
-		ch = serial_in(up, UART_RX);
-		flag = TTY_NORMAL;
-		up->port.icount.rx++;
-
-		if (unlikely(*status & (UART_LSR_BI | UART_LSR_PE |
-				       UART_LSR_FE | UART_LSR_OE))) {
-			/*
-			 * For statistics only
-			 */
-			if (*status & UART_LSR_BI) {
-				*status &= ~(UART_LSR_FE | UART_LSR_PE);
-				up->port.icount.brk++;
-				/*
-				 * We do the SysRQ and SAK checking
-				 * here because otherwise the break
-				 * may get masked by ignore_status_mask
-				 * or read_status_mask.
-				 */
-				if (uart_handle_break(&up->port))
-					goto ignore_char;
-			} else if (*status & UART_LSR_PE)
-				up->port.icount.parity++;
-			else if (*status & UART_LSR_FE)
-				up->port.icount.frame++;
-			if (*status & UART_LSR_OE)
-				up->port.icount.overrun++;
-
-			/*
-			 * Mask off conditions which should be ignored.
-			 */
-			*status &= up->port.read_status_mask;
-
-#ifdef CONFIG_SERIAL_PXA_CONSOLE
-			if (up->port.line == up->port.cons->index) {
-				/* Recover the break flag from console xmit */
-				*status |= up->lsr_break_flag;
-				up->lsr_break_flag = 0;
-			}
-#endif
-			if (*status & UART_LSR_BI) {
-				flag = TTY_BREAK;
-			} else if (*status & UART_LSR_PE)
-				flag = TTY_PARITY;
-			else if (*status & UART_LSR_FE)
-				flag = TTY_FRAME;
-		}
-
-		if (uart_handle_sysrq_char(&up->port, ch))
-			goto ignore_char;
-
-		uart_insert_char(&up->port, *status, UART_LSR_OE, ch, flag);
-
-	ignore_char:
-		*status = serial_in(up, UART_LSR);
-	} while ((*status & UART_LSR_DR) && (max_count-- > 0));
-	tty_flip_buffer_push(&up->port.state->port);
-
-	/* work around Errata #20 according to
-	 * Intel(R) PXA27x Processor Family
-	 * Specification Update (May 2005)
-	 *
-	 * Step 6:
-	 * No more data in FIFO: Re-enable RTO interrupt via IER[RTOIE]
-	 */
-	up->ier |= UART_IER_RTOIE;
-	serial_out(up, UART_IER, up->ier);
-}
-
-static void transmit_chars(struct uart_pxa_port *up)
-{
-	struct circ_buf *xmit = &up->port.state->xmit;
-	int count;
-
-	if (up->port.x_char) {
-		serial_out(up, UART_TX, up->port.x_char);
-		up->port.icount.tx++;
-		up->port.x_char = 0;
-		return;
-	}
-	if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) {
-		serial_pxa_stop_tx(&up->port);
-		return;
-	}
-
-	count = up->port.fifosize / 2;
-	do {
-		serial_out(up, UART_TX, xmit->buf[xmit->tail]);
-		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
-		up->port.icount.tx++;
-		if (uart_circ_empty(xmit))
-			break;
-	} while (--count > 0);
-
-	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
-		uart_write_wakeup(&up->port);
-
-
-	if (uart_circ_empty(xmit))
-		serial_pxa_stop_tx(&up->port);
-}
-
-static void serial_pxa_start_tx(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	if (!(up->ier & UART_IER_THRI)) {
-		up->ier |= UART_IER_THRI;
-		serial_out(up, UART_IER, up->ier);
-	}
-}
-
-/* should hold up->port.lock */
-static inline void check_modem_status(struct uart_pxa_port *up)
-{
-	int status;
-
-	status = serial_in(up, UART_MSR);
-
-	if ((status & UART_MSR_ANY_DELTA) == 0)
-		return;
-
-	if (status & UART_MSR_TERI)
-		up->port.icount.rng++;
-	if (status & UART_MSR_DDSR)
-		up->port.icount.dsr++;
-	if (status & UART_MSR_DDCD)
-		uart_handle_dcd_change(&up->port, status & UART_MSR_DCD);
-	if (status & UART_MSR_DCTS)
-		uart_handle_cts_change(&up->port, status & UART_MSR_CTS);
-
-	wake_up_interruptible(&up->port.state->port.delta_msr_wait);
-}
-
-/*
- * This handles the interrupt from one port.
- */
-static inline irqreturn_t serial_pxa_irq(int irq, void *dev_id)
-{
-	struct uart_pxa_port *up = dev_id;
-	unsigned int iir, lsr;
-
-	iir = serial_in(up, UART_IIR);
-	if (iir & UART_IIR_NO_INT)
-		return IRQ_NONE;
-	spin_lock(&up->port.lock);
-	lsr = serial_in(up, UART_LSR);
-	if (lsr & UART_LSR_DR)
-		receive_chars(up, &lsr);
-	check_modem_status(up);
-	if (lsr & UART_LSR_THRE)
-		transmit_chars(up);
-	spin_unlock(&up->port.lock);
-	return IRQ_HANDLED;
-}
-
-static unsigned int serial_pxa_tx_empty(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned long flags;
-	unsigned int ret;
-
-	spin_lock_irqsave(&up->port.lock, flags);
-	ret = serial_in(up, UART_LSR) & UART_LSR_TEMT ? TIOCSER_TEMT : 0;
-	spin_unlock_irqrestore(&up->port.lock, flags);
-
-	return ret;
-}
-
-static unsigned int serial_pxa_get_mctrl(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned char status;
-	unsigned int ret;
-
-	status = serial_in(up, UART_MSR);
-
-	ret = 0;
-	if (status & UART_MSR_DCD)
-		ret |= TIOCM_CAR;
-	if (status & UART_MSR_RI)
-		ret |= TIOCM_RNG;
-	if (status & UART_MSR_DSR)
-		ret |= TIOCM_DSR;
-	if (status & UART_MSR_CTS)
-		ret |= TIOCM_CTS;
-	return ret;
-}
-
-static void serial_pxa_set_mctrl(struct uart_port *port, unsigned int mctrl)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned char mcr = 0;
-
-	if (mctrl & TIOCM_RTS)
-		mcr |= UART_MCR_RTS;
-	if (mctrl & TIOCM_DTR)
-		mcr |= UART_MCR_DTR;
-	if (mctrl & TIOCM_OUT1)
-		mcr |= UART_MCR_OUT1;
-	if (mctrl & TIOCM_OUT2)
-		mcr |= UART_MCR_OUT2;
-	if (mctrl & TIOCM_LOOP)
-		mcr |= UART_MCR_LOOP;
-
-	mcr |= up->mcr;
-
-	serial_out(up, UART_MCR, mcr);
-}
-
-static void serial_pxa_break_ctl(struct uart_port *port, int break_state)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned long flags;
-
-	spin_lock_irqsave(&up->port.lock, flags);
-	if (break_state == -1)
-		up->lcr |= UART_LCR_SBC;
-	else
-		up->lcr &= ~UART_LCR_SBC;
-	serial_out(up, UART_LCR, up->lcr);
-	spin_unlock_irqrestore(&up->port.lock, flags);
-}
-
-static int serial_pxa_startup(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned long flags;
-	int retval;
-
-	if (port->line == 3) /* HWUART */
-		up->mcr |= UART_MCR_AFE;
-	else
-		up->mcr = 0;
-
-	up->port.uartclk = clk_get_rate(up->clk);
-
-	/*
-	 * Allocate the IRQ
-	 */
-	retval = request_irq(up->port.irq, serial_pxa_irq, 0, up->name, up);
-	if (retval)
-		return retval;
-
-	/*
-	 * Clear the FIFO buffers and disable them.
-	 * (they will be reenabled in set_termios())
-	 */
-	serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO);
-	serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO |
-			UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
-	serial_out(up, UART_FCR, 0);
-
-	/*
-	 * Clear the interrupt registers.
-	 */
-	(void) serial_in(up, UART_LSR);
-	(void) serial_in(up, UART_RX);
-	(void) serial_in(up, UART_IIR);
-	(void) serial_in(up, UART_MSR);
-
-	/*
-	 * Now, initialize the UART
-	 */
-	serial_out(up, UART_LCR, UART_LCR_WLEN8);
-
-	spin_lock_irqsave(&up->port.lock, flags);
-	up->port.mctrl |= TIOCM_OUT2;
-	serial_pxa_set_mctrl(&up->port, up->port.mctrl);
-	spin_unlock_irqrestore(&up->port.lock, flags);
-
-	/*
-	 * Finally, enable interrupts.  Note: Modem status interrupts
-	 * are set via set_termios(), which will be occurring imminently
-	 * anyway, so we don't enable them here.
-	 */
-	up->ier = UART_IER_RLSI | UART_IER_RDI | UART_IER_RTOIE | UART_IER_UUE;
-	serial_out(up, UART_IER, up->ier);
-
-	/*
-	 * And clear the interrupt registers again for luck.
-	 */
-	(void) serial_in(up, UART_LSR);
-	(void) serial_in(up, UART_RX);
-	(void) serial_in(up, UART_IIR);
-	(void) serial_in(up, UART_MSR);
-
-	return 0;
-}
-
-static void serial_pxa_shutdown(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned long flags;
-
-	free_irq(up->port.irq, up);
-
-	/*
-	 * Disable interrupts from this port
-	 */
-	up->ier = 0;
-	serial_out(up, UART_IER, 0);
-
-	spin_lock_irqsave(&up->port.lock, flags);
-	up->port.mctrl &= ~TIOCM_OUT2;
-	serial_pxa_set_mctrl(&up->port, up->port.mctrl);
-	spin_unlock_irqrestore(&up->port.lock, flags);
-
-	/*
-	 * Disable break condition and FIFOs
-	 */
-	serial_out(up, UART_LCR, serial_in(up, UART_LCR) & ~UART_LCR_SBC);
-	serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO |
-				  UART_FCR_CLEAR_RCVR |
-				  UART_FCR_CLEAR_XMIT);
-	serial_out(up, UART_FCR, 0);
-}
-
-static void
-serial_pxa_set_termios(struct uart_port *port, struct ktermios *termios,
-		       struct ktermios *old)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned char cval, fcr = 0;
-	unsigned long flags;
-	unsigned int baud, quot;
-	unsigned int dll;
-
-	switch (termios->c_cflag & CSIZE) {
-	case CS5:
-		cval = UART_LCR_WLEN5;
-		break;
-	case CS6:
-		cval = UART_LCR_WLEN6;
-		break;
-	case CS7:
-		cval = UART_LCR_WLEN7;
-		break;
-	default:
-	case CS8:
-		cval = UART_LCR_WLEN8;
-		break;
-	}
-
-	if (termios->c_cflag & CSTOPB)
-		cval |= UART_LCR_STOP;
-	if (termios->c_cflag & PARENB)
-		cval |= UART_LCR_PARITY;
-	if (!(termios->c_cflag & PARODD))
-		cval |= UART_LCR_EPAR;
-
-	/*
-	 * Ask the core to calculate the divisor for us.
-	 */
-	baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
-	quot = uart_get_divisor(port, baud);
-
-	if ((up->port.uartclk / quot) < (2400 * 16))
-		fcr = UART_FCR_ENABLE_FIFO | UART_FCR_PXAR1;
-	else if ((up->port.uartclk / quot) < (230400 * 16))
-		fcr = UART_FCR_ENABLE_FIFO | UART_FCR_PXAR8;
-	else
-		fcr = UART_FCR_ENABLE_FIFO | UART_FCR_PXAR32;
-
-	/*
-	 * Ok, we're now changing the port state.  Do it with
-	 * interrupts disabled.
-	 */
-	spin_lock_irqsave(&up->port.lock, flags);
-
-	/*
-	 * Ensure the port will be enabled.
-	 * This is required especially for serial console.
-	 */
-	up->ier |= UART_IER_UUE;
-
-	/*
-	 * Update the per-port timeout.
-	 */
-	uart_update_timeout(port, termios->c_cflag, baud);
-
-	up->port.read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;
-	if (termios->c_iflag & INPCK)
-		up->port.read_status_mask |= UART_LSR_FE | UART_LSR_PE;
-	if (termios->c_iflag & (IGNBRK | BRKINT | PARMRK))
-		up->port.read_status_mask |= UART_LSR_BI;
-
-	/*
-	 * Characters to ignore
-	 */
-	up->port.ignore_status_mask = 0;
-	if (termios->c_iflag & IGNPAR)
-		up->port.ignore_status_mask |= UART_LSR_PE | UART_LSR_FE;
-	if (termios->c_iflag & IGNBRK) {
-		up->port.ignore_status_mask |= UART_LSR_BI;
-		/*
-		 * If we're ignoring parity and break indicators,
-		 * ignore overruns too (for real raw support).
-		 */
-		if (termios->c_iflag & IGNPAR)
-			up->port.ignore_status_mask |= UART_LSR_OE;
-	}
-
-	/*
-	 * ignore all characters if CREAD is not set
-	 */
-	if ((termios->c_cflag & CREAD) == 0)
-		up->port.ignore_status_mask |= UART_LSR_DR;
-
-	/*
-	 * CTS flow control flag and modem status interrupts
-	 */
-	up->ier &= ~UART_IER_MSI;
-	if (UART_ENABLE_MS(&up->port, termios->c_cflag))
-		up->ier |= UART_IER_MSI;
-
-	serial_out(up, UART_IER, up->ier);
-
-	if (termios->c_cflag & CRTSCTS)
-		up->mcr |= UART_MCR_AFE;
-	else
-		up->mcr &= ~UART_MCR_AFE;
-
-	serial_out(up, UART_LCR, cval | UART_LCR_DLAB);	/* set DLAB */
-	serial_out(up, UART_DLL, quot & 0xff);		/* LS of divisor */
-
-	/*
-	 * work around Errata #75 according to Intel(R) PXA27x Processor Family
-	 * Specification Update (Nov 2005)
-	 */
-	dll = serial_in(up, UART_DLL);
-	WARN_ON(dll != (quot & 0xff));
-
-	serial_out(up, UART_DLM, quot >> 8);		/* MS of divisor */
-	serial_out(up, UART_LCR, cval);			/* reset DLAB */
-	up->lcr = cval;					/* Save LCR */
-	serial_pxa_set_mctrl(&up->port, up->port.mctrl);
-	serial_out(up, UART_FCR, fcr);
-	spin_unlock_irqrestore(&up->port.lock, flags);
-}
-
-static void
-serial_pxa_pm(struct uart_port *port, unsigned int state,
-	      unsigned int oldstate)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	if (!state)
-		clk_prepare_enable(up->clk);
-	else
-		clk_disable_unprepare(up->clk);
-}
-
-static void serial_pxa_release_port(struct uart_port *port)
-{
-}
-
-static int serial_pxa_request_port(struct uart_port *port)
-{
-	return 0;
-}
-
-static void serial_pxa_config_port(struct uart_port *port, int flags)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	up->port.type = PORT_PXA;
-}
-
-static int
-serial_pxa_verify_port(struct uart_port *port, struct serial_struct *ser)
-{
-	/* we don't want the core code to modify any port params */
-	return -EINVAL;
-}
-
-static const char *
-serial_pxa_type(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	return up->name;
-}
-
-static struct uart_pxa_port *serial_pxa_ports[4];
-static struct uart_driver serial_pxa_reg;
-
-#ifdef CONFIG_SERIAL_PXA_CONSOLE
-
-#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
-
-/*
- *	Wait for transmitter & holding register to empty
- */
-static inline void wait_for_xmitr(struct uart_pxa_port *up)
-{
-	unsigned int status, tmout = 10000;
-
-	/* Wait up to 10ms for the character(s) to be sent. */
-	do {
-		status = serial_in(up, UART_LSR);
-
-		if (status & UART_LSR_BI)
-			up->lsr_break_flag = UART_LSR_BI;
-
-		if (--tmout == 0)
-			break;
-		udelay(1);
-	} while ((status & BOTH_EMPTY) != BOTH_EMPTY);
-
-	/* Wait up to 1s for flow control if necessary */
-	if (up->port.flags & UPF_CONS_FLOW) {
-		tmout = 1000000;
-		while (--tmout &&
-		       ((serial_in(up, UART_MSR) & UART_MSR_CTS) == 0))
-			udelay(1);
-	}
-}
-
-static void serial_pxa_console_putchar(struct uart_port *port, int ch)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	wait_for_xmitr(up);
-	serial_out(up, UART_TX, ch);
-}
-
-/*
- * Print a string to the serial port trying not to disturb
- * any possible real use of the port...
- *
- *	The console_lock must be held when we get here.
- */
-static void
-serial_pxa_console_write(struct console *co, const char *s, unsigned int count)
-{
-	struct uart_pxa_port *up = serial_pxa_ports[co->index];
-	unsigned int ier;
-	unsigned long flags;
-	int locked = 1;
-
-	clk_enable(up->clk);
-	local_irq_save(flags);
-	if (up->port.sysrq)
-		locked = 0;
-	else if (oops_in_progress)
-		locked = spin_trylock(&up->port.lock);
-	else
-		spin_lock(&up->port.lock);
-
-	/*
-	 *	First save the IER then disable the interrupts
-	 */
-	ier = serial_in(up, UART_IER);
-	serial_out(up, UART_IER, UART_IER_UUE);
-
-	uart_console_write(&up->port, s, count, serial_pxa_console_putchar);
-
-	/*
-	 *	Finally, wait for transmitter to become empty
-	 *	and restore the IER
-	 */
-	wait_for_xmitr(up);
-	serial_out(up, UART_IER, ier);
-
-	if (locked)
-		spin_unlock(&up->port.lock);
-	local_irq_restore(flags);
-	clk_disable(up->clk);
-
-}
-
-#ifdef CONFIG_CONSOLE_POLL
-/*
- * Console polling routines for writing and reading from the uart while
- * in an interrupt or debug context.
- */
-
-static int serial_pxa_get_poll_char(struct uart_port *port)
-{
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	unsigned char lsr = serial_in(up, UART_LSR);
-
-	while (!(lsr & UART_LSR_DR))
-		lsr = serial_in(up, UART_LSR);
-
-	return serial_in(up, UART_RX);
-}
-
-
-static void serial_pxa_put_poll_char(struct uart_port *port,
-			 unsigned char c)
-{
-	unsigned int ier;
-	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
-	/*
-	 *	First save the IER then disable the interrupts
-	 */
-	ier = serial_in(up, UART_IER);
-	serial_out(up, UART_IER, UART_IER_UUE);
-
-	wait_for_xmitr(up);
-	/*
-	 *	Send the character out.
-	 */
-	serial_out(up, UART_TX, c);
-
-	/*
-	 *	Finally, wait for transmitter to become empty
-	 *	and restore the IER
-	 */
-	wait_for_xmitr(up);
-	serial_out(up, UART_IER, ier);
-}
-
-#endif /* CONFIG_CONSOLE_POLL */
-
-static int __init
-serial_pxa_console_setup(struct console *co, char *options)
-{
-	struct uart_pxa_port *up;
-	int baud = 9600;
-	int bits = 8;
-	int parity = 'n';
-	int flow = 'n';
-
-	if (co->index == -1 || co->index >= serial_pxa_reg.nr)
-		co->index = 0;
-	up = serial_pxa_ports[co->index];
-	if (!up)
-		return -ENODEV;
-
-	if (options)
-		uart_parse_options(options, &baud, &parity, &bits, &flow);
-
-	return uart_set_options(&up->port, co, baud, parity, bits, flow);
-}
-
-static struct console serial_pxa_console = {
-	.name		= "ttyS",
-	.write		= serial_pxa_console_write,
-	.device		= uart_console_device,
-	.setup		= serial_pxa_console_setup,
-	.flags		= CON_PRINTBUFFER,
-	.index		= -1,
-	.data		= &serial_pxa_reg,
-};
-
-#define PXA_CONSOLE	&serial_pxa_console
-#else
-#define PXA_CONSOLE	NULL
-#endif
-
-static struct uart_ops serial_pxa_pops = {
-	.tx_empty	= serial_pxa_tx_empty,
-	.set_mctrl	= serial_pxa_set_mctrl,
-	.get_mctrl	= serial_pxa_get_mctrl,
-	.stop_tx	= serial_pxa_stop_tx,
-	.start_tx	= serial_pxa_start_tx,
-	.stop_rx	= serial_pxa_stop_rx,
-	.enable_ms	= serial_pxa_enable_ms,
-	.break_ctl	= serial_pxa_break_ctl,
-	.startup	= serial_pxa_startup,
-	.shutdown	= serial_pxa_shutdown,
-	.set_termios	= serial_pxa_set_termios,
-	.pm		= serial_pxa_pm,
-	.type		= serial_pxa_type,
-	.release_port	= serial_pxa_release_port,
-	.request_port	= serial_pxa_request_port,
-	.config_port	= serial_pxa_config_port,
-	.verify_port	= serial_pxa_verify_port,
-#if defined(CONFIG_CONSOLE_POLL) && defined(CONFIG_SERIAL_PXA_CONSOLE)
-	.poll_get_char = serial_pxa_get_poll_char,
-	.poll_put_char = serial_pxa_put_poll_char,
-#endif
-};
-
-static struct uart_driver serial_pxa_reg = {
-	.owner		= THIS_MODULE,
-	.driver_name	= "PXA serial",
-	.dev_name	= "ttyS",
-	.major		= TTY_MAJOR,
-	.minor		= 64,
-	.nr		= 4,
-	.cons		= PXA_CONSOLE,
-};
-
-#ifdef CONFIG_PM
-static int serial_pxa_suspend(struct device *dev)
-{
-        struct uart_pxa_port *sport = dev_get_drvdata(dev);
-
-        if (sport)
-                uart_suspend_port(&serial_pxa_reg, &sport->port);
-
-        return 0;
-}
-
-static int serial_pxa_resume(struct device *dev)
-{
-        struct uart_pxa_port *sport = dev_get_drvdata(dev);
-
-        if (sport)
-                uart_resume_port(&serial_pxa_reg, &sport->port);
-
-        return 0;
-}
-
-static const struct dev_pm_ops serial_pxa_pm_ops = {
-	.suspend	= serial_pxa_suspend,
-	.resume		= serial_pxa_resume,
-};
-#endif
-
-static const struct of_device_id serial_pxa_dt_ids[] = {
-	{ .compatible = "mrvl,pxa-uart", },
-	{ .compatible = "mrvl,mmp-uart", },
-	{}
-};
-MODULE_DEVICE_TABLE(of, serial_pxa_dt_ids);
-
-static int serial_pxa_probe_dt(struct platform_device *pdev,
-			       struct uart_pxa_port *sport)
-{
-	struct device_node *np = pdev->dev.of_node;
-	int ret;
-
-	if (!np)
-		return 1;
-
-	ret = of_alias_get_id(np, "serial");
-	if (ret < 0) {
-		dev_err(&pdev->dev, "failed to get alias id, errno %d\n", ret);
-		return ret;
-	}
-	sport->port.line = ret;
-	return 0;
-}
-
-static int serial_pxa_probe(struct platform_device *dev)
-{
-	struct uart_pxa_port *sport;
-	struct resource *mmres, *irqres;
-	int ret;
-
-	mmres = platform_get_resource(dev, IORESOURCE_MEM, 0);
-	irqres = platform_get_resource(dev, IORESOURCE_IRQ, 0);
-	if (!mmres || !irqres)
-		return -ENODEV;
-
-	sport = kzalloc(sizeof(struct uart_pxa_port), GFP_KERNEL);
-	if (!sport)
-		return -ENOMEM;
-
-	sport->clk = clk_get(&dev->dev, NULL);
-	if (IS_ERR(sport->clk)) {
-		ret = PTR_ERR(sport->clk);
-		goto err_free;
-	}
-
-	ret = clk_prepare(sport->clk);
-	if (ret) {
-		clk_put(sport->clk);
-		goto err_free;
-	}
-
-	sport->port.type = PORT_PXA;
-	sport->port.iotype = UPIO_MEM;
-	sport->port.mapbase = mmres->start;
-	sport->port.irq = irqres->start;
-	sport->port.fifosize = 64;
-	sport->port.ops = &serial_pxa_pops;
-	sport->port.dev = &dev->dev;
-	sport->port.flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF;
-	sport->port.uartclk = clk_get_rate(sport->clk);
-
-	ret = serial_pxa_probe_dt(dev, sport);
-	if (ret > 0)
-		sport->port.line = dev->id;
-	else if (ret < 0)
-		goto err_clk;
-	snprintf(sport->name, PXA_NAME_LEN - 1, "UART%d", sport->port.line + 1);
-
-	sport->port.membase = ioremap(mmres->start, resource_size(mmres));
-	if (!sport->port.membase) {
-		ret = -ENOMEM;
-		goto err_clk;
-	}
-
-	serial_pxa_ports[sport->port.line] = sport;
-
-	uart_add_one_port(&serial_pxa_reg, &sport->port);
-	platform_set_drvdata(dev, sport);
-
-	return 0;
-
- err_clk:
-	clk_unprepare(sport->clk);
-	clk_put(sport->clk);
- err_free:
-	kfree(sport);
-	return ret;
-}
-
-static int serial_pxa_remove(struct platform_device *dev)
-{
-	struct uart_pxa_port *sport = platform_get_drvdata(dev);
-
-	uart_remove_one_port(&serial_pxa_reg, &sport->port);
-
-	clk_unprepare(sport->clk);
-	clk_put(sport->clk);
-	kfree(sport);
-
-	return 0;
-}
-
-static struct platform_driver serial_pxa_driver = {
-        .probe          = serial_pxa_probe,
-        .remove         = serial_pxa_remove,
-
-	.driver		= {
-	        .name	= "pxa2xx-uart",
-#ifdef CONFIG_PM
-		.pm	= &serial_pxa_pm_ops,
-#endif
-		.of_match_table = serial_pxa_dt_ids,
-	},
-};
-
-static int __init serial_pxa_init(void)
-{
-	int ret;
-
-	ret = uart_register_driver(&serial_pxa_reg);
-	if (ret != 0)
-		return ret;
-
-	ret = platform_driver_register(&serial_pxa_driver);
-	if (ret != 0)
-		uart_unregister_driver(&serial_pxa_reg);
-
-	return ret;
-}
-
-static void __exit serial_pxa_exit(void)
-{
-	platform_driver_unregister(&serial_pxa_driver);
-	uart_unregister_driver(&serial_pxa_reg);
-}
-
-module_init(serial_pxa_init);
-module_exit(serial_pxa_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:pxa2xx-uart");
-- 
2.6.2

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

* [PATCH v4 2/2] arm: pxa27x: support for ICP DAS LP-8x4x w/ DT
@ 2015-12-09 22:28               ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2015-12-09 22:28 UTC (permalink / raw)
  To: linux-kernel
  Cc: Sergei Ianovich, Daniel Mack, Robert Jarzmik, Arnd Bergmann,
	Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	Russell King, Thierry Reding, Jonathan Cameron, Dmitry Torokhov,
	Philipp Zabel, Arnaud Ebalard, Kuninori Morimoto,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	moderated list:ARM PORT

ICP DAS calls LP-8x4x 'programmable automation controller'. It is
an industrial computer based on PXA270 SoC. They ship it with a 2.6.19
kernel and proprietary kernel module and userspace library to access
its industrial IO.

This patch allows to boot a modern kernel with device tree on
the device. It adds support for:
* MMC card interface on PXA270
* USB 1.1 port on PXA270
* 2 NOR flash devices
* 2 onboard ethernet Davicom DM9000 devices
* 3 serial UART ports on PXA270
* front panel red LED
* 64bit 1-wire system ID chip
* 16 kiB EEPROM (reading)

Support for these devices will be added in separate patches, since
they are not currently supported by the kernel:
* DS1302 RTC
* 512kiB SRAM
* FPGA irq chip
* 3 built-in 16550A serial UART ports
* industrial IO parallel bus
* 10 position rotary switch
* 8 pin DIP switch
* 16 kiB EEPROM (writing)
* serial interface for digital and analog industrial IO modules on
  parallel bus (all I-87xxx modules)
* digital and analog industrial IO modules for parallel bus:
  ** I-8024 4 port analog output
  ** I-8041 32 port digital output
  ** I-8042 16 port digital output/16 port digital input

Not supported for now:
* VGA interface on PXA270 for lack of dts binding
* the rest of parallel bus (I-8xxx) modules for lack of hardware
* GPIO reset for lack of relevance (watchdog reset is working)

Newer LP-8x4x devices have twice as much flash and a different
partition structure otherwise being the same. When each device
is provided with a correct device tree, all of them can be booted
using the same kernel.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Daniel Mack <zonque@gmail.com>
CC: Robert Jarzmik <robert.jarzmik@free.fr>
CC: Arnd Bergmann <arnd@arndb.de>
---
   v3..v4
   * support for newer flavor w/ 96Mb flash memory
   * use 'partitions' subnodes
   * move device-specific tweaking to device .dts file and drop
     patches to pxa27x.dtsi 

   v2..v3
   * added extbus which maps synchronous, static, and variable-latency
     I/O (VLIO) interfaces of PXA27x SoC as suggested by Arnd Bergmann
   * map is placed into platform include
   * configured existing kernel drivers to support:
     - front panel LED using gpio-leds
     - 64bit 1-wire system ID chip using w1-gpio
     - 16 kiB EEPROM using at24 over i2c-gpio
   * number change (06/16 -> 08/21)

   v1..v2
   * drop left-over extern declaration
   * use of_have_populated_dt() instead of a static variable
   * drop wildcards in compatible
   * drop machine-special machine description
   * number changed from 9 to 6 (dropped patches)

 .../devicetree/bindings/vendor-prefixes.txt        |   1 +
 arch/arm/boot/dts/Makefile                         |   3 +
 arch/arm/boot/dts/pxa27x-lp8x4x-i105.dts           |  50 ++++
 arch/arm/boot/dts/pxa27x-lp8x4x.dts                | 260 +++++++++++++++++++++
 arch/arm/configs/lp8x4x_defconfig                  | 176 ++++++++++++++
 5 files changed, 490 insertions(+)
 create mode 100644 arch/arm/boot/dts/pxa27x-lp8x4x-i105.dts
 create mode 100644 arch/arm/boot/dts/pxa27x-lp8x4x.dts
 create mode 100644 arch/arm/configs/lp8x4x_defconfig

diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index 55df1d4..2f1b078 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -109,6 +109,7 @@ honeywell	Honeywell
 hp	Hewlett Packard
 i2se	I2SE GmbH
 ibm	International Business Machines (IBM)
+icpdas	ICP DAS CO., LTD.
 idt	Integrated Device Technologies, Inc.
 iom	Iomega Corporation
 img	Imagination Technologies Ltd.
diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index 30bbc37..ed182ea 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -499,6 +499,9 @@ dtb-$(CONFIG_ARCH_ORION5X) += \
 	orion5x-rd88f5182-nas.dtb
 dtb-$(CONFIG_ARCH_PRIMA2) += \
 	prima2-evb.dtb
+dtb-$(CONFIG_MACH_PXA27X_DT) += \
+	pxa27x-lp8x4x.dtb \
+	pxa27x-lp8x4x-i105.dtb
 dtb-$(CONFIG_ARCH_QCOM) += \
 	qcom-apq8064-cm-qs600.dtb \
 	qcom-apq8064-ifc6410.dtb \
diff --git a/arch/arm/boot/dts/pxa27x-lp8x4x-i105.dts b/arch/arm/boot/dts/pxa27x-lp8x4x-i105.dts
new file mode 100644
index 0000000..903f5c7
--- /dev/null
+++ b/arch/arm/boot/dts/pxa27x-lp8x4x-i105.dts
@@ -0,0 +1,50 @@
+/* Device tree for ICP DAS LP-8x4x i105 flavor */
+
+#include "pxa27x-lp8x4x.dts"
+
+/ {
+	extbus {
+		flash@0 {
+			compatible = "cfi-flash";
+			reg = <0 0 0x04000000>;
+			bank-width = <4>;
+			device-width = <2>;
+
+			partitions {
+				#address-cells = <1>;
+				#size-cells = <1>;
+				fs@0 {
+					label = "u-boot";
+					reg = <0 0x40000>;
+				};
+				fs@40000 {
+					label = "settings";
+					reg = <0x40000 0x40000>;
+				};
+				fs@80000 {
+					label = "device_tree";
+					reg = <0x80000 0x40000>;
+				};
+				fs@c0000 {
+					label = "kernel";
+					reg = <0xc0000 0x2c0000>;
+				};
+				fs@300000 {
+					label = "root_fs";
+					reg = <0x380000 0x3c80000>;
+				};
+			};
+		};
+
+		flash@1 {
+			compatible = "cfi-flash";
+			reg = <1 0x0 0x02000000>;
+			bank-width = <2>;
+			device-width = <1>;
+			partitions {
+				#address-cells = <1>;
+				#size-cells = <1>;
+			};
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/pxa27x-lp8x4x.dts b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
new file mode 100644
index 0000000..bbb5b75
--- /dev/null
+++ b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
@@ -0,0 +1,260 @@
+/* Device tree for ICP DAS LP-8x4x */
+/dts-v1/;
+
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include "pxa27x.dtsi"
+
+/ {
+	model = "ICP DAS LP-8x4x programmable automation controller";
+	compatible = "marvell,pxa270";
+
+	aliases {
+		ethernet0 = &eth0;
+		ethernet1 = &eth1;
+	};
+
+	memory {
+		reg = <0xa0000000 0x08000000>;
+	};
+
+	regulators {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		vmmc: regulator@0 {
+			compatible = "regulator-fixed";
+			reg = <0>;
+			regulator-name = "vmmc";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-always-on;
+		};
+	};
+
+	pxabus {
+		pxairq: interrupt-controller@40d00000 {
+			marvell,intc-priority;
+			marvell,intc-nr-irqs = <34>;
+		};
+
+		gpio: gpio@40e00000 {
+			interrupts = <8>, <9>, <10>;
+			interrupt-names = "gpio0", "gpio1", "gpio_mux";
+		};
+
+		uart@40100000 {
+			status = "okay";
+		};
+
+		uart@40200000 {
+			status = "okay";
+		};
+
+		uart@40700000 {
+			status = "okay";
+		};
+
+		mmc0: mmc@41100000 {
+			vmmc-supply = <&vmmc>;
+			status = "okay";
+		};
+
+		usb0: ohci@4c000000 {
+			marvell,port-mode = <3>;
+			marvell,oc-mode-perport;
+			marvell,enable-port1;
+			status = "okay";
+		};
+
+		leds {
+			compatible = "gpio-leds";
+
+			status {
+				gpios = <&gpio 84 1>;
+				linux,default-trigger = "heartbeat";
+			};
+		};
+
+		i2c: i2c-gpio {
+			compatible = "i2c-gpio";
+			gpios = <&gpio 22 0 /* sda */
+				 &gpio 12 0 /* scl */>;
+			i2c-gpio,delay-us = <1>;
+			i2c-gpio,timeout-ms = <1>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			eeprom@50 {
+				compatible = "atmel,24c128";
+				reg = <0x50>;
+				pagesize = <64>;
+			};
+		};
+
+		w1: w1-gpio {
+			compatible = "w1-gpio";
+			gpios = <&gpio 83 0>;
+		};
+	};
+
+	extbus {
+		/*
+		 * PXA27x synchrous, static and
+		 * variable-latency IO interfaces
+		 */
+		compatible = "simple-bus";
+
+		#address-cells = <2>; /* first cell is nCS, second is address */
+		#size-cells = <1>;
+		ranges = <0 0 0 0x04000000
+			  1 0 0x04000000 0x04000000
+			  2 0 0x08000000 0x04000000
+			  3 0 0x0c000000 0x04000000
+			  4 0 0x10000000 0x04000000
+			  5 0 0x14000000 0x04000000>;
+
+		flash@0 {
+			compatible = "cfi-flash";
+			reg = <0 0 0x02000000>;
+			bank-width = <4>;
+			device-width = <2>;
+
+			partitions {
+				#address-cells = <1>;
+				#size-cells = <1>;
+				fs@0 {
+					label = "u-boot";
+					reg = <0 0x40000>;
+				};
+				fs@40000 {
+					label = "settings";
+					reg = <0x40000 0x40000>;
+				};
+				fs@80000 {
+					label = "device_tree";
+					reg = <0x80000 0x40000>;
+				};
+				fs@c0000 {
+					label = "kernel";
+					reg = <0xc0000 0x240000>;
+				};
+				fs@300000 {
+					label = "root_fs";
+					reg = <0x300000 0x1d00000>;
+				};
+			};
+		};
+
+		flash@1 {
+			compatible = "cfi-flash";
+			reg = <1 0x0 0x01000000>;
+			bank-width = <2>;
+			device-width = <1>;
+			partitions {
+				#address-cells = <1>;
+				#size-cells = <1>;
+			};
+		};
+
+		netio@3 {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0 3 0 0x02000000>;
+			interrupt-parent = <&gpio>;
+
+			eth0: eth@0 {
+				compatible = "davicom,dm9000";
+				reg = <0x0 0x2
+				       0x4000 0x2>;
+				interrupts = <9 IRQ_TYPE_EDGE_RISING>;
+				status = "okay";
+			};
+
+			eth1: eth@1000000 {
+				compatible = "davicom,dm9000";
+				reg = <0x1000000 0x2
+				       0x1004000 0x2>;
+				interrupts = <82 IRQ_TYPE_EDGE_RISING>;
+				status = "okay";
+			};
+		};
+
+		fpga@5 {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0 5 0x3000000 0x10000>;
+			interrupt-parent = <&fpgairq>;
+
+			rtc@901c {
+				compatible = "dallas,rtc-ds1302";
+				reg = <0x901c 0x1>;
+				status = "okay";
+			};
+
+			sram@a000 {
+				compatible = "icpdas,sram-lp8x4x";
+				reg = <0xa000 0x1000
+				       0x901e 0x1>;
+
+				partitions {
+					#address-cells = <1>;
+					#size-cells = <1>;
+				};
+			};
+
+			fpgairq: irq@9006 {
+				compatible = "icpdas,irq-lp8x4x";
+				reg = <0x9006 0x16>;
+				interrupt-parent = <&gpio>;
+				interrupts = <3 IRQ_TYPE_EDGE_FALLING>;
+				#interrupt-cells = <1>;
+				interrupt-controller;
+				status = "okay";
+			};
+
+			uart@9050 {
+				compatible = "icpdas,uart-lp8x4x";
+				reg = <0x9050 0x10
+				       0x9030 0x02>;
+				interrupts = <13>;
+				status = "okay";
+			};
+
+			uart@9060 {
+				compatible = "icpdas,uart-lp8x4x";
+				reg = <0x9060 0x10
+				       0x9032 0x02>;
+				interrupts = <14>;
+				status = "okay";
+			};
+
+			uart@9070 {
+				compatible = "icpdas,uart-lp8x4x";
+				reg = <0x9070 0x10
+				       0x9034 0x02>;
+				interrupts = <15>;
+				status = "okay";
+			};
+
+			backplane {
+				compatible = "icpdas,backplane-lp8x4x";
+				reg = <0x0 0x2
+				       0x1000 0x10
+				       0x2000 0x10
+				       0x3000 0x10
+				       0x4000 0x10
+				       0x5000 0x10
+				       0x6000 0x10
+				       0x7000 0x10
+				       0x8000 0x10
+				       0x9002 0x2
+				       0x9004 0x2
+				       0x9046 0x2>;
+				eeprom-gpios = <&gpio 4 0>;
+			};
+		};
+	};
+};
diff --git a/arch/arm/configs/lp8x4x_defconfig b/arch/arm/configs/lp8x4x_defconfig
new file mode 100644
index 0000000..0eb87df
--- /dev/null
+++ b/arch/arm/configs/lp8x4x_defconfig
@@ -0,0 +1,176 @@
+# CONFIG_LOCALVERSION_AUTO is not set
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_RCU_BOOST=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_NS is not set
+# CONFIG_IPC_NS is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+# CONFIG_UID16 is not set
+# CONFIG_SHMEM is not set
+CONFIG_EMBEDDED=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_SLOB=y
+CONFIG_JUMP_LABEL=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+# CONFIG_LBDAF is not set
+CONFIG_BLK_CMDLINE_PARSER=y
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_ARCH_PXA=y
+CONFIG_MACH_PXA27X_DT=y
+# CONFIG_ARM_THUMB is not set
+CONFIG_PREEMPT=y
+CONFIG_AEABI=y
+# CONFIG_COMPACTION is not set
+# CONFIG_CROSS_MEMORY_ATTACH is not set
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="init=/sbin/init root=/dev/mmcblk0p1 rw rootfstype=ext4 console=ttyS0,115200 mem=128M rootwait"
+# CONFIG_SUSPEND is not set
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_BRIDGE=m
+CONFIG_BRIDGE_VLAN_FILTERING=y
+CONFIG_VLAN_8021Q=m
+CONFIG_VLAN_8021Q_GVRP=y
+CONFIG_VLAN_8021Q_MVRP=y
+# CONFIG_WIRELESS is not set
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+# CONFIG_FW_LOADER is not set
+CONFIG_MTD=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_CFI_GEOMETRY=y
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_PHYSMAP_OF=y
+CONFIG_MTD_SRAM_LP8X4X=y
+CONFIG_PROC_DEVICETREE=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_LOOP_MIN_COUNT=2
+CONFIG_EEPROM_AT24=m
+CONFIG_LP8X4X_BUS=m
+CONFIG_SCSI=y
+# CONFIG_SCSI_PROC_FS is not set
+CONFIG_BLK_DEV_SD=y
+# CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_NETDEVICES=y
+CONFIG_BONDING=m
+CONFIG_MACVLAN=m
+CONFIG_MACVTAP=m
+CONFIG_TUN=m
+# CONFIG_NET_VENDOR_ARC is not set
+# CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_CIRRUS is not set
+CONFIG_DM9000=y
+CONFIG_DM9000_FORCE_SIMPLE_PHY_POLL=y
+# CONFIG_NET_VENDOR_FARADAY is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+CONFIG_PPP=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPPOE=m
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_SLIP=m
+CONFIG_SLIP_COMPRESSED=y
+# CONFIG_WLAN is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=800
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=600
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_SERIO is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_8250=y
+# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=40
+CONFIG_SERIAL_8250_RUNTIME_UARTS=40
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_8250_PXA=y
+CONFIG_SERIAL_8250_LP8X4X=m
+CONFIG_HW_RANDOM=y
+CONFIG_I2C=m
+# CONFIG_I2C_COMPAT is not set
+CONFIG_I2C_GPIO=m
+CONFIG_W1=m
+CONFIG_W1_MASTER_GPIO=m
+CONFIG_W1_SLAVE_SMEM=m
+# CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_SA1100_WATCHDOG=m
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_FB=y
+CONFIG_FB_PXA=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_LOGO=y
+CONFIG_USB=m
+CONFIG_USB_OHCI_HCD=m
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+CONFIG_USB_STORAGE=m
+CONFIG_USB_SERIAL=m
+CONFIG_MMC=y
+CONFIG_MMC_PXA=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_DS1302=y
+CONFIG_RTC_DRV_PXA=m
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_DMA_ENGINE=y
+CONFIG_DMA_VIRTUAL_CHANNELS=y
+CONFIG_DMA_OF=y
+CONFIG_PXA_DMA=y
+CONFIG_EXT2_FS=m
+CONFIG_EXT3_FS=y
+CONFIG_EXT4_FS=y
+CONFIG_REISERFS_FS=m
+CONFIG_ISO9660_FS=m
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_NTFS_FS=m
+CONFIG_NTFS_RW=y
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V4=y
+CONFIG_ROOT_NFS=y
+CONFIG_CIFS=m
+CONFIG_CIFS_STATS=y
+CONFIG_CODA_FS=m
+CONFIG_NLS_DEFAULT="cp855"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_855=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_UTF8=y
+CONFIG_PRINTK_TIME=y
-- 
2.6.2


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

* [PATCH v4 2/2] arm: pxa27x: support for ICP DAS LP-8x4x w/ DT
@ 2015-12-09 22:28               ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2015-12-09 22:28 UTC (permalink / raw)
  To: linux-kernel-u79uwXL29TY76Z2rM5mHXA
  Cc: Sergei Ianovich, Daniel Mack, Robert Jarzmik, Arnd Bergmann,
	Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	Russell King, Thierry Reding, Jonathan Cameron, Dmitry Torokhov,
	Philipp Zabel, Arnaud Ebalard, Kuninori Morimoto,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	moderated list:ARM PORT

ICP DAS calls LP-8x4x 'programmable automation controller'. It is
an industrial computer based on PXA270 SoC. They ship it with a 2.6.19
kernel and proprietary kernel module and userspace library to access
its industrial IO.

This patch allows to boot a modern kernel with device tree on
the device. It adds support for:
* MMC card interface on PXA270
* USB 1.1 port on PXA270
* 2 NOR flash devices
* 2 onboard ethernet Davicom DM9000 devices
* 3 serial UART ports on PXA270
* front panel red LED
* 64bit 1-wire system ID chip
* 16 kiB EEPROM (reading)

Support for these devices will be added in separate patches, since
they are not currently supported by the kernel:
* DS1302 RTC
* 512kiB SRAM
* FPGA irq chip
* 3 built-in 16550A serial UART ports
* industrial IO parallel bus
* 10 position rotary switch
* 8 pin DIP switch
* 16 kiB EEPROM (writing)
* serial interface for digital and analog industrial IO modules on
  parallel bus (all I-87xxx modules)
* digital and analog industrial IO modules for parallel bus:
  ** I-8024 4 port analog output
  ** I-8041 32 port digital output
  ** I-8042 16 port digital output/16 port digital input

Not supported for now:
* VGA interface on PXA270 for lack of dts binding
* the rest of parallel bus (I-8xxx) modules for lack of hardware
* GPIO reset for lack of relevance (watchdog reset is working)

Newer LP-8x4x devices have twice as much flash and a different
partition structure otherwise being the same. When each device
is provided with a correct device tree, all of them can be booted
using the same kernel.

Signed-off-by: Sergei Ianovich <ynvich-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
CC: Daniel Mack <zonque-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
CC: Robert Jarzmik <robert.jarzmik-GANU6spQydw@public.gmane.org>
CC: Arnd Bergmann <arnd-r2nGTMty4D4@public.gmane.org>
---
   v3..v4
   * support for newer flavor w/ 96Mb flash memory
   * use 'partitions' subnodes
   * move device-specific tweaking to device .dts file and drop
     patches to pxa27x.dtsi 

   v2..v3
   * added extbus which maps synchronous, static, and variable-latency
     I/O (VLIO) interfaces of PXA27x SoC as suggested by Arnd Bergmann
   * map is placed into platform include
   * configured existing kernel drivers to support:
     - front panel LED using gpio-leds
     - 64bit 1-wire system ID chip using w1-gpio
     - 16 kiB EEPROM using at24 over i2c-gpio
   * number change (06/16 -> 08/21)

   v1..v2
   * drop left-over extern declaration
   * use of_have_populated_dt() instead of a static variable
   * drop wildcards in compatible
   * drop machine-special machine description
   * number changed from 9 to 6 (dropped patches)

 .../devicetree/bindings/vendor-prefixes.txt        |   1 +
 arch/arm/boot/dts/Makefile                         |   3 +
 arch/arm/boot/dts/pxa27x-lp8x4x-i105.dts           |  50 ++++
 arch/arm/boot/dts/pxa27x-lp8x4x.dts                | 260 +++++++++++++++++++++
 arch/arm/configs/lp8x4x_defconfig                  | 176 ++++++++++++++
 5 files changed, 490 insertions(+)
 create mode 100644 arch/arm/boot/dts/pxa27x-lp8x4x-i105.dts
 create mode 100644 arch/arm/boot/dts/pxa27x-lp8x4x.dts
 create mode 100644 arch/arm/configs/lp8x4x_defconfig

diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index 55df1d4..2f1b078 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -109,6 +109,7 @@ honeywell	Honeywell
 hp	Hewlett Packard
 i2se	I2SE GmbH
 ibm	International Business Machines (IBM)
+icpdas	ICP DAS CO., LTD.
 idt	Integrated Device Technologies, Inc.
 iom	Iomega Corporation
 img	Imagination Technologies Ltd.
diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index 30bbc37..ed182ea 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -499,6 +499,9 @@ dtb-$(CONFIG_ARCH_ORION5X) += \
 	orion5x-rd88f5182-nas.dtb
 dtb-$(CONFIG_ARCH_PRIMA2) += \
 	prima2-evb.dtb
+dtb-$(CONFIG_MACH_PXA27X_DT) += \
+	pxa27x-lp8x4x.dtb \
+	pxa27x-lp8x4x-i105.dtb
 dtb-$(CONFIG_ARCH_QCOM) += \
 	qcom-apq8064-cm-qs600.dtb \
 	qcom-apq8064-ifc6410.dtb \
diff --git a/arch/arm/boot/dts/pxa27x-lp8x4x-i105.dts b/arch/arm/boot/dts/pxa27x-lp8x4x-i105.dts
new file mode 100644
index 0000000..903f5c7
--- /dev/null
+++ b/arch/arm/boot/dts/pxa27x-lp8x4x-i105.dts
@@ -0,0 +1,50 @@
+/* Device tree for ICP DAS LP-8x4x i105 flavor */
+
+#include "pxa27x-lp8x4x.dts"
+
+/ {
+	extbus {
+		flash@0 {
+			compatible = "cfi-flash";
+			reg = <0 0 0x04000000>;
+			bank-width = <4>;
+			device-width = <2>;
+
+			partitions {
+				#address-cells = <1>;
+				#size-cells = <1>;
+				fs@0 {
+					label = "u-boot";
+					reg = <0 0x40000>;
+				};
+				fs@40000 {
+					label = "settings";
+					reg = <0x40000 0x40000>;
+				};
+				fs@80000 {
+					label = "device_tree";
+					reg = <0x80000 0x40000>;
+				};
+				fs@c0000 {
+					label = "kernel";
+					reg = <0xc0000 0x2c0000>;
+				};
+				fs@300000 {
+					label = "root_fs";
+					reg = <0x380000 0x3c80000>;
+				};
+			};
+		};
+
+		flash@1 {
+			compatible = "cfi-flash";
+			reg = <1 0x0 0x02000000>;
+			bank-width = <2>;
+			device-width = <1>;
+			partitions {
+				#address-cells = <1>;
+				#size-cells = <1>;
+			};
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/pxa27x-lp8x4x.dts b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
new file mode 100644
index 0000000..bbb5b75
--- /dev/null
+++ b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
@@ -0,0 +1,260 @@
+/* Device tree for ICP DAS LP-8x4x */
+/dts-v1/;
+
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include "pxa27x.dtsi"
+
+/ {
+	model = "ICP DAS LP-8x4x programmable automation controller";
+	compatible = "marvell,pxa270";
+
+	aliases {
+		ethernet0 = &eth0;
+		ethernet1 = &eth1;
+	};
+
+	memory {
+		reg = <0xa0000000 0x08000000>;
+	};
+
+	regulators {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		vmmc: regulator@0 {
+			compatible = "regulator-fixed";
+			reg = <0>;
+			regulator-name = "vmmc";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-always-on;
+		};
+	};
+
+	pxabus {
+		pxairq: interrupt-controller@40d00000 {
+			marvell,intc-priority;
+			marvell,intc-nr-irqs = <34>;
+		};
+
+		gpio: gpio@40e00000 {
+			interrupts = <8>, <9>, <10>;
+			interrupt-names = "gpio0", "gpio1", "gpio_mux";
+		};
+
+		uart@40100000 {
+			status = "okay";
+		};
+
+		uart@40200000 {
+			status = "okay";
+		};
+
+		uart@40700000 {
+			status = "okay";
+		};
+
+		mmc0: mmc@41100000 {
+			vmmc-supply = <&vmmc>;
+			status = "okay";
+		};
+
+		usb0: ohci@4c000000 {
+			marvell,port-mode = <3>;
+			marvell,oc-mode-perport;
+			marvell,enable-port1;
+			status = "okay";
+		};
+
+		leds {
+			compatible = "gpio-leds";
+
+			status {
+				gpios = <&gpio 84 1>;
+				linux,default-trigger = "heartbeat";
+			};
+		};
+
+		i2c: i2c-gpio {
+			compatible = "i2c-gpio";
+			gpios = <&gpio 22 0 /* sda */
+				 &gpio 12 0 /* scl */>;
+			i2c-gpio,delay-us = <1>;
+			i2c-gpio,timeout-ms = <1>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			eeprom@50 {
+				compatible = "atmel,24c128";
+				reg = <0x50>;
+				pagesize = <64>;
+			};
+		};
+
+		w1: w1-gpio {
+			compatible = "w1-gpio";
+			gpios = <&gpio 83 0>;
+		};
+	};
+
+	extbus {
+		/*
+		 * PXA27x synchrous, static and
+		 * variable-latency IO interfaces
+		 */
+		compatible = "simple-bus";
+
+		#address-cells = <2>; /* first cell is nCS, second is address */
+		#size-cells = <1>;
+		ranges = <0 0 0 0x04000000
+			  1 0 0x04000000 0x04000000
+			  2 0 0x08000000 0x04000000
+			  3 0 0x0c000000 0x04000000
+			  4 0 0x10000000 0x04000000
+			  5 0 0x14000000 0x04000000>;
+
+		flash@0 {
+			compatible = "cfi-flash";
+			reg = <0 0 0x02000000>;
+			bank-width = <4>;
+			device-width = <2>;
+
+			partitions {
+				#address-cells = <1>;
+				#size-cells = <1>;
+				fs@0 {
+					label = "u-boot";
+					reg = <0 0x40000>;
+				};
+				fs@40000 {
+					label = "settings";
+					reg = <0x40000 0x40000>;
+				};
+				fs@80000 {
+					label = "device_tree";
+					reg = <0x80000 0x40000>;
+				};
+				fs@c0000 {
+					label = "kernel";
+					reg = <0xc0000 0x240000>;
+				};
+				fs@300000 {
+					label = "root_fs";
+					reg = <0x300000 0x1d00000>;
+				};
+			};
+		};
+
+		flash@1 {
+			compatible = "cfi-flash";
+			reg = <1 0x0 0x01000000>;
+			bank-width = <2>;
+			device-width = <1>;
+			partitions {
+				#address-cells = <1>;
+				#size-cells = <1>;
+			};
+		};
+
+		netio@3 {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0 3 0 0x02000000>;
+			interrupt-parent = <&gpio>;
+
+			eth0: eth@0 {
+				compatible = "davicom,dm9000";
+				reg = <0x0 0x2
+				       0x4000 0x2>;
+				interrupts = <9 IRQ_TYPE_EDGE_RISING>;
+				status = "okay";
+			};
+
+			eth1: eth@1000000 {
+				compatible = "davicom,dm9000";
+				reg = <0x1000000 0x2
+				       0x1004000 0x2>;
+				interrupts = <82 IRQ_TYPE_EDGE_RISING>;
+				status = "okay";
+			};
+		};
+
+		fpga@5 {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0 5 0x3000000 0x10000>;
+			interrupt-parent = <&fpgairq>;
+
+			rtc@901c {
+				compatible = "dallas,rtc-ds1302";
+				reg = <0x901c 0x1>;
+				status = "okay";
+			};
+
+			sram@a000 {
+				compatible = "icpdas,sram-lp8x4x";
+				reg = <0xa000 0x1000
+				       0x901e 0x1>;
+
+				partitions {
+					#address-cells = <1>;
+					#size-cells = <1>;
+				};
+			};
+
+			fpgairq: irq@9006 {
+				compatible = "icpdas,irq-lp8x4x";
+				reg = <0x9006 0x16>;
+				interrupt-parent = <&gpio>;
+				interrupts = <3 IRQ_TYPE_EDGE_FALLING>;
+				#interrupt-cells = <1>;
+				interrupt-controller;
+				status = "okay";
+			};
+
+			uart@9050 {
+				compatible = "icpdas,uart-lp8x4x";
+				reg = <0x9050 0x10
+				       0x9030 0x02>;
+				interrupts = <13>;
+				status = "okay";
+			};
+
+			uart@9060 {
+				compatible = "icpdas,uart-lp8x4x";
+				reg = <0x9060 0x10
+				       0x9032 0x02>;
+				interrupts = <14>;
+				status = "okay";
+			};
+
+			uart@9070 {
+				compatible = "icpdas,uart-lp8x4x";
+				reg = <0x9070 0x10
+				       0x9034 0x02>;
+				interrupts = <15>;
+				status = "okay";
+			};
+
+			backplane {
+				compatible = "icpdas,backplane-lp8x4x";
+				reg = <0x0 0x2
+				       0x1000 0x10
+				       0x2000 0x10
+				       0x3000 0x10
+				       0x4000 0x10
+				       0x5000 0x10
+				       0x6000 0x10
+				       0x7000 0x10
+				       0x8000 0x10
+				       0x9002 0x2
+				       0x9004 0x2
+				       0x9046 0x2>;
+				eeprom-gpios = <&gpio 4 0>;
+			};
+		};
+	};
+};
diff --git a/arch/arm/configs/lp8x4x_defconfig b/arch/arm/configs/lp8x4x_defconfig
new file mode 100644
index 0000000..0eb87df
--- /dev/null
+++ b/arch/arm/configs/lp8x4x_defconfig
@@ -0,0 +1,176 @@
+# CONFIG_LOCALVERSION_AUTO is not set
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_RCU_BOOST=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_NS is not set
+# CONFIG_IPC_NS is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+# CONFIG_UID16 is not set
+# CONFIG_SHMEM is not set
+CONFIG_EMBEDDED=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_SLOB=y
+CONFIG_JUMP_LABEL=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+# CONFIG_LBDAF is not set
+CONFIG_BLK_CMDLINE_PARSER=y
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_ARCH_PXA=y
+CONFIG_MACH_PXA27X_DT=y
+# CONFIG_ARM_THUMB is not set
+CONFIG_PREEMPT=y
+CONFIG_AEABI=y
+# CONFIG_COMPACTION is not set
+# CONFIG_CROSS_MEMORY_ATTACH is not set
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="init=/sbin/init root=/dev/mmcblk0p1 rw rootfstype=ext4 console=ttyS0,115200 mem=128M rootwait"
+# CONFIG_SUSPEND is not set
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_BRIDGE=m
+CONFIG_BRIDGE_VLAN_FILTERING=y
+CONFIG_VLAN_8021Q=m
+CONFIG_VLAN_8021Q_GVRP=y
+CONFIG_VLAN_8021Q_MVRP=y
+# CONFIG_WIRELESS is not set
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+# CONFIG_FW_LOADER is not set
+CONFIG_MTD=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_CFI_GEOMETRY=y
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_PHYSMAP_OF=y
+CONFIG_MTD_SRAM_LP8X4X=y
+CONFIG_PROC_DEVICETREE=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_LOOP_MIN_COUNT=2
+CONFIG_EEPROM_AT24=m
+CONFIG_LP8X4X_BUS=m
+CONFIG_SCSI=y
+# CONFIG_SCSI_PROC_FS is not set
+CONFIG_BLK_DEV_SD=y
+# CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_NETDEVICES=y
+CONFIG_BONDING=m
+CONFIG_MACVLAN=m
+CONFIG_MACVTAP=m
+CONFIG_TUN=m
+# CONFIG_NET_VENDOR_ARC is not set
+# CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_CIRRUS is not set
+CONFIG_DM9000=y
+CONFIG_DM9000_FORCE_SIMPLE_PHY_POLL=y
+# CONFIG_NET_VENDOR_FARADAY is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+CONFIG_PPP=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPPOE=m
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_SLIP=m
+CONFIG_SLIP_COMPRESSED=y
+# CONFIG_WLAN is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=800
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=600
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_SERIO is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_8250=y
+# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=40
+CONFIG_SERIAL_8250_RUNTIME_UARTS=40
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_8250_PXA=y
+CONFIG_SERIAL_8250_LP8X4X=m
+CONFIG_HW_RANDOM=y
+CONFIG_I2C=m
+# CONFIG_I2C_COMPAT is not set
+CONFIG_I2C_GPIO=m
+CONFIG_W1=m
+CONFIG_W1_MASTER_GPIO=m
+CONFIG_W1_SLAVE_SMEM=m
+# CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_SA1100_WATCHDOG=m
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_FB=y
+CONFIG_FB_PXA=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_LOGO=y
+CONFIG_USB=m
+CONFIG_USB_OHCI_HCD=m
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+CONFIG_USB_STORAGE=m
+CONFIG_USB_SERIAL=m
+CONFIG_MMC=y
+CONFIG_MMC_PXA=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_DS1302=y
+CONFIG_RTC_DRV_PXA=m
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_DMA_ENGINE=y
+CONFIG_DMA_VIRTUAL_CHANNELS=y
+CONFIG_DMA_OF=y
+CONFIG_PXA_DMA=y
+CONFIG_EXT2_FS=m
+CONFIG_EXT3_FS=y
+CONFIG_EXT4_FS=y
+CONFIG_REISERFS_FS=m
+CONFIG_ISO9660_FS=m
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_NTFS_FS=m
+CONFIG_NTFS_RW=y
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V4=y
+CONFIG_ROOT_NFS=y
+CONFIG_CIFS=m
+CONFIG_CIFS_STATS=y
+CONFIG_CODA_FS=m
+CONFIG_NLS_DEFAULT="cp855"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_855=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_UTF8=y
+CONFIG_PRINTK_TIME=y
-- 
2.6.2

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH v4 2/2] arm: pxa27x: support for ICP DAS LP-8x4x w/ DT
@ 2015-12-09 22:28               ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2015-12-09 22:28 UTC (permalink / raw)
  To: linux-arm-kernel

ICP DAS calls LP-8x4x 'programmable automation controller'. It is
an industrial computer based on PXA270 SoC. They ship it with a 2.6.19
kernel and proprietary kernel module and userspace library to access
its industrial IO.

This patch allows to boot a modern kernel with device tree on
the device. It adds support for:
* MMC card interface on PXA270
* USB 1.1 port on PXA270
* 2 NOR flash devices
* 2 onboard ethernet Davicom DM9000 devices
* 3 serial UART ports on PXA270
* front panel red LED
* 64bit 1-wire system ID chip
* 16 kiB EEPROM (reading)

Support for these devices will be added in separate patches, since
they are not currently supported by the kernel:
* DS1302 RTC
* 512kiB SRAM
* FPGA irq chip
* 3 built-in 16550A serial UART ports
* industrial IO parallel bus
* 10 position rotary switch
* 8 pin DIP switch
* 16 kiB EEPROM (writing)
* serial interface for digital and analog industrial IO modules on
  parallel bus (all I-87xxx modules)
* digital and analog industrial IO modules for parallel bus:
  ** I-8024 4 port analog output
  ** I-8041 32 port digital output
  ** I-8042 16 port digital output/16 port digital input

Not supported for now:
* VGA interface on PXA270 for lack of dts binding
* the rest of parallel bus (I-8xxx) modules for lack of hardware
* GPIO reset for lack of relevance (watchdog reset is working)

Newer LP-8x4x devices have twice as much flash and a different
partition structure otherwise being the same. When each device
is provided with a correct device tree, all of them can be booted
using the same kernel.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Daniel Mack <zonque@gmail.com>
CC: Robert Jarzmik <robert.jarzmik@free.fr>
CC: Arnd Bergmann <arnd@arndb.de>
---
   v3..v4
   * support for newer flavor w/ 96Mb flash memory
   * use 'partitions' subnodes
   * move device-specific tweaking to device .dts file and drop
     patches to pxa27x.dtsi 

   v2..v3
   * added extbus which maps synchronous, static, and variable-latency
     I/O (VLIO) interfaces of PXA27x SoC as suggested by Arnd Bergmann
   * map is placed into platform include
   * configured existing kernel drivers to support:
     - front panel LED using gpio-leds
     - 64bit 1-wire system ID chip using w1-gpio
     - 16 kiB EEPROM using at24 over i2c-gpio
   * number change (06/16 -> 08/21)

   v1..v2
   * drop left-over extern declaration
   * use of_have_populated_dt() instead of a static variable
   * drop wildcards in compatible
   * drop machine-special machine description
   * number changed from 9 to 6 (dropped patches)

 .../devicetree/bindings/vendor-prefixes.txt        |   1 +
 arch/arm/boot/dts/Makefile                         |   3 +
 arch/arm/boot/dts/pxa27x-lp8x4x-i105.dts           |  50 ++++
 arch/arm/boot/dts/pxa27x-lp8x4x.dts                | 260 +++++++++++++++++++++
 arch/arm/configs/lp8x4x_defconfig                  | 176 ++++++++++++++
 5 files changed, 490 insertions(+)
 create mode 100644 arch/arm/boot/dts/pxa27x-lp8x4x-i105.dts
 create mode 100644 arch/arm/boot/dts/pxa27x-lp8x4x.dts
 create mode 100644 arch/arm/configs/lp8x4x_defconfig

diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index 55df1d4..2f1b078 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -109,6 +109,7 @@ honeywell	Honeywell
 hp	Hewlett Packard
 i2se	I2SE GmbH
 ibm	International Business Machines (IBM)
+icpdas	ICP DAS CO., LTD.
 idt	Integrated Device Technologies, Inc.
 iom	Iomega Corporation
 img	Imagination Technologies Ltd.
diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index 30bbc37..ed182ea 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -499,6 +499,9 @@ dtb-$(CONFIG_ARCH_ORION5X) += \
 	orion5x-rd88f5182-nas.dtb
 dtb-$(CONFIG_ARCH_PRIMA2) += \
 	prima2-evb.dtb
+dtb-$(CONFIG_MACH_PXA27X_DT) += \
+	pxa27x-lp8x4x.dtb \
+	pxa27x-lp8x4x-i105.dtb
 dtb-$(CONFIG_ARCH_QCOM) += \
 	qcom-apq8064-cm-qs600.dtb \
 	qcom-apq8064-ifc6410.dtb \
diff --git a/arch/arm/boot/dts/pxa27x-lp8x4x-i105.dts b/arch/arm/boot/dts/pxa27x-lp8x4x-i105.dts
new file mode 100644
index 0000000..903f5c7
--- /dev/null
+++ b/arch/arm/boot/dts/pxa27x-lp8x4x-i105.dts
@@ -0,0 +1,50 @@
+/* Device tree for ICP DAS LP-8x4x i105 flavor */
+
+#include "pxa27x-lp8x4x.dts"
+
+/ {
+	extbus {
+		flash at 0 {
+			compatible = "cfi-flash";
+			reg = <0 0 0x04000000>;
+			bank-width = <4>;
+			device-width = <2>;
+
+			partitions {
+				#address-cells = <1>;
+				#size-cells = <1>;
+				fs at 0 {
+					label = "u-boot";
+					reg = <0 0x40000>;
+				};
+				fs at 40000 {
+					label = "settings";
+					reg = <0x40000 0x40000>;
+				};
+				fs at 80000 {
+					label = "device_tree";
+					reg = <0x80000 0x40000>;
+				};
+				fs at c0000 {
+					label = "kernel";
+					reg = <0xc0000 0x2c0000>;
+				};
+				fs at 300000 {
+					label = "root_fs";
+					reg = <0x380000 0x3c80000>;
+				};
+			};
+		};
+
+		flash at 1 {
+			compatible = "cfi-flash";
+			reg = <1 0x0 0x02000000>;
+			bank-width = <2>;
+			device-width = <1>;
+			partitions {
+				#address-cells = <1>;
+				#size-cells = <1>;
+			};
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/pxa27x-lp8x4x.dts b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
new file mode 100644
index 0000000..bbb5b75
--- /dev/null
+++ b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
@@ -0,0 +1,260 @@
+/* Device tree for ICP DAS LP-8x4x */
+/dts-v1/;
+
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include "pxa27x.dtsi"
+
+/ {
+	model = "ICP DAS LP-8x4x programmable automation controller";
+	compatible = "marvell,pxa270";
+
+	aliases {
+		ethernet0 = &eth0;
+		ethernet1 = &eth1;
+	};
+
+	memory {
+		reg = <0xa0000000 0x08000000>;
+	};
+
+	regulators {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		vmmc: regulator at 0 {
+			compatible = "regulator-fixed";
+			reg = <0>;
+			regulator-name = "vmmc";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-always-on;
+		};
+	};
+
+	pxabus {
+		pxairq: interrupt-controller at 40d00000 {
+			marvell,intc-priority;
+			marvell,intc-nr-irqs = <34>;
+		};
+
+		gpio: gpio at 40e00000 {
+			interrupts = <8>, <9>, <10>;
+			interrupt-names = "gpio0", "gpio1", "gpio_mux";
+		};
+
+		uart at 40100000 {
+			status = "okay";
+		};
+
+		uart at 40200000 {
+			status = "okay";
+		};
+
+		uart at 40700000 {
+			status = "okay";
+		};
+
+		mmc0: mmc at 41100000 {
+			vmmc-supply = <&vmmc>;
+			status = "okay";
+		};
+
+		usb0: ohci at 4c000000 {
+			marvell,port-mode = <3>;
+			marvell,oc-mode-perport;
+			marvell,enable-port1;
+			status = "okay";
+		};
+
+		leds {
+			compatible = "gpio-leds";
+
+			status {
+				gpios = <&gpio 84 1>;
+				linux,default-trigger = "heartbeat";
+			};
+		};
+
+		i2c: i2c-gpio {
+			compatible = "i2c-gpio";
+			gpios = <&gpio 22 0 /* sda */
+				 &gpio 12 0 /* scl */>;
+			i2c-gpio,delay-us = <1>;
+			i2c-gpio,timeout-ms = <1>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			eeprom at 50 {
+				compatible = "atmel,24c128";
+				reg = <0x50>;
+				pagesize = <64>;
+			};
+		};
+
+		w1: w1-gpio {
+			compatible = "w1-gpio";
+			gpios = <&gpio 83 0>;
+		};
+	};
+
+	extbus {
+		/*
+		 * PXA27x synchrous, static and
+		 * variable-latency IO interfaces
+		 */
+		compatible = "simple-bus";
+
+		#address-cells = <2>; /* first cell is nCS, second is address */
+		#size-cells = <1>;
+		ranges = <0 0 0 0x04000000
+			  1 0 0x04000000 0x04000000
+			  2 0 0x08000000 0x04000000
+			  3 0 0x0c000000 0x04000000
+			  4 0 0x10000000 0x04000000
+			  5 0 0x14000000 0x04000000>;
+
+		flash at 0 {
+			compatible = "cfi-flash";
+			reg = <0 0 0x02000000>;
+			bank-width = <4>;
+			device-width = <2>;
+
+			partitions {
+				#address-cells = <1>;
+				#size-cells = <1>;
+				fs at 0 {
+					label = "u-boot";
+					reg = <0 0x40000>;
+				};
+				fs at 40000 {
+					label = "settings";
+					reg = <0x40000 0x40000>;
+				};
+				fs at 80000 {
+					label = "device_tree";
+					reg = <0x80000 0x40000>;
+				};
+				fs at c0000 {
+					label = "kernel";
+					reg = <0xc0000 0x240000>;
+				};
+				fs at 300000 {
+					label = "root_fs";
+					reg = <0x300000 0x1d00000>;
+				};
+			};
+		};
+
+		flash at 1 {
+			compatible = "cfi-flash";
+			reg = <1 0x0 0x01000000>;
+			bank-width = <2>;
+			device-width = <1>;
+			partitions {
+				#address-cells = <1>;
+				#size-cells = <1>;
+			};
+		};
+
+		netio at 3 {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0 3 0 0x02000000>;
+			interrupt-parent = <&gpio>;
+
+			eth0: eth at 0 {
+				compatible = "davicom,dm9000";
+				reg = <0x0 0x2
+				       0x4000 0x2>;
+				interrupts = <9 IRQ_TYPE_EDGE_RISING>;
+				status = "okay";
+			};
+
+			eth1: eth at 1000000 {
+				compatible = "davicom,dm9000";
+				reg = <0x1000000 0x2
+				       0x1004000 0x2>;
+				interrupts = <82 IRQ_TYPE_EDGE_RISING>;
+				status = "okay";
+			};
+		};
+
+		fpga at 5 {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0 5 0x3000000 0x10000>;
+			interrupt-parent = <&fpgairq>;
+
+			rtc at 901c {
+				compatible = "dallas,rtc-ds1302";
+				reg = <0x901c 0x1>;
+				status = "okay";
+			};
+
+			sram at a000 {
+				compatible = "icpdas,sram-lp8x4x";
+				reg = <0xa000 0x1000
+				       0x901e 0x1>;
+
+				partitions {
+					#address-cells = <1>;
+					#size-cells = <1>;
+				};
+			};
+
+			fpgairq: irq at 9006 {
+				compatible = "icpdas,irq-lp8x4x";
+				reg = <0x9006 0x16>;
+				interrupt-parent = <&gpio>;
+				interrupts = <3 IRQ_TYPE_EDGE_FALLING>;
+				#interrupt-cells = <1>;
+				interrupt-controller;
+				status = "okay";
+			};
+
+			uart at 9050 {
+				compatible = "icpdas,uart-lp8x4x";
+				reg = <0x9050 0x10
+				       0x9030 0x02>;
+				interrupts = <13>;
+				status = "okay";
+			};
+
+			uart at 9060 {
+				compatible = "icpdas,uart-lp8x4x";
+				reg = <0x9060 0x10
+				       0x9032 0x02>;
+				interrupts = <14>;
+				status = "okay";
+			};
+
+			uart at 9070 {
+				compatible = "icpdas,uart-lp8x4x";
+				reg = <0x9070 0x10
+				       0x9034 0x02>;
+				interrupts = <15>;
+				status = "okay";
+			};
+
+			backplane {
+				compatible = "icpdas,backplane-lp8x4x";
+				reg = <0x0 0x2
+				       0x1000 0x10
+				       0x2000 0x10
+				       0x3000 0x10
+				       0x4000 0x10
+				       0x5000 0x10
+				       0x6000 0x10
+				       0x7000 0x10
+				       0x8000 0x10
+				       0x9002 0x2
+				       0x9004 0x2
+				       0x9046 0x2>;
+				eeprom-gpios = <&gpio 4 0>;
+			};
+		};
+	};
+};
diff --git a/arch/arm/configs/lp8x4x_defconfig b/arch/arm/configs/lp8x4x_defconfig
new file mode 100644
index 0000000..0eb87df
--- /dev/null
+++ b/arch/arm/configs/lp8x4x_defconfig
@@ -0,0 +1,176 @@
+# CONFIG_LOCALVERSION_AUTO is not set
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_RCU_BOOST=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_NS is not set
+# CONFIG_IPC_NS is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+# CONFIG_UID16 is not set
+# CONFIG_SHMEM is not set
+CONFIG_EMBEDDED=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_SLOB=y
+CONFIG_JUMP_LABEL=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+# CONFIG_LBDAF is not set
+CONFIG_BLK_CMDLINE_PARSER=y
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_ARCH_PXA=y
+CONFIG_MACH_PXA27X_DT=y
+# CONFIG_ARM_THUMB is not set
+CONFIG_PREEMPT=y
+CONFIG_AEABI=y
+# CONFIG_COMPACTION is not set
+# CONFIG_CROSS_MEMORY_ATTACH is not set
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="init=/sbin/init root=/dev/mmcblk0p1 rw rootfstype=ext4 console=ttyS0,115200 mem=128M rootwait"
+# CONFIG_SUSPEND is not set
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_BRIDGE=m
+CONFIG_BRIDGE_VLAN_FILTERING=y
+CONFIG_VLAN_8021Q=m
+CONFIG_VLAN_8021Q_GVRP=y
+CONFIG_VLAN_8021Q_MVRP=y
+# CONFIG_WIRELESS is not set
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+# CONFIG_FW_LOADER is not set
+CONFIG_MTD=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_CFI_GEOMETRY=y
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_PHYSMAP_OF=y
+CONFIG_MTD_SRAM_LP8X4X=y
+CONFIG_PROC_DEVICETREE=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_LOOP_MIN_COUNT=2
+CONFIG_EEPROM_AT24=m
+CONFIG_LP8X4X_BUS=m
+CONFIG_SCSI=y
+# CONFIG_SCSI_PROC_FS is not set
+CONFIG_BLK_DEV_SD=y
+# CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_NETDEVICES=y
+CONFIG_BONDING=m
+CONFIG_MACVLAN=m
+CONFIG_MACVTAP=m
+CONFIG_TUN=m
+# CONFIG_NET_VENDOR_ARC is not set
+# CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_CIRRUS is not set
+CONFIG_DM9000=y
+CONFIG_DM9000_FORCE_SIMPLE_PHY_POLL=y
+# CONFIG_NET_VENDOR_FARADAY is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+CONFIG_PPP=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPPOE=m
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_SLIP=m
+CONFIG_SLIP_COMPRESSED=y
+# CONFIG_WLAN is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=800
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=600
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_SERIO is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_8250=y
+# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=40
+CONFIG_SERIAL_8250_RUNTIME_UARTS=40
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_8250_PXA=y
+CONFIG_SERIAL_8250_LP8X4X=m
+CONFIG_HW_RANDOM=y
+CONFIG_I2C=m
+# CONFIG_I2C_COMPAT is not set
+CONFIG_I2C_GPIO=m
+CONFIG_W1=m
+CONFIG_W1_MASTER_GPIO=m
+CONFIG_W1_SLAVE_SMEM=m
+# CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_SA1100_WATCHDOG=m
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_FB=y
+CONFIG_FB_PXA=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_LOGO=y
+CONFIG_USB=m
+CONFIG_USB_OHCI_HCD=m
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+CONFIG_USB_STORAGE=m
+CONFIG_USB_SERIAL=m
+CONFIG_MMC=y
+CONFIG_MMC_PXA=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_DS1302=y
+CONFIG_RTC_DRV_PXA=m
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_DMA_ENGINE=y
+CONFIG_DMA_VIRTUAL_CHANNELS=y
+CONFIG_DMA_OF=y
+CONFIG_PXA_DMA=y
+CONFIG_EXT2_FS=m
+CONFIG_EXT3_FS=y
+CONFIG_EXT4_FS=y
+CONFIG_REISERFS_FS=m
+CONFIG_ISO9660_FS=m
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_NTFS_FS=m
+CONFIG_NTFS_RW=y
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V4=y
+CONFIG_ROOT_NFS=y
+CONFIG_CIFS=m
+CONFIG_CIFS_STATS=y
+CONFIG_CODA_FS=m
+CONFIG_NLS_DEFAULT="cp855"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_855=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_UTF8=y
+CONFIG_PRINTK_TIME=y
-- 
2.6.2

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

* Re: [PATCH v4 2/2] arm: pxa27x: support for ICP DAS LP-8x4x w/ DT
  2015-12-09 22:28               ` Sergei Ianovich
  (?)
@ 2015-12-11  2:53                 ` Rob Herring
  -1 siblings, 0 replies; 700+ messages in thread
From: Rob Herring @ 2015-12-11  2:53 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: linux-kernel, Daniel Mack, Robert Jarzmik, Arnd Bergmann,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala, Russell King,
	Thierry Reding, Jonathan Cameron, Dmitry Torokhov, Philipp Zabel,
	Arnaud Ebalard, Kuninori Morimoto,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	moderated list:ARM PORT

On Thu, Dec 10, 2015 at 01:28:08AM +0300, Sergei Ianovich wrote:
> ICP DAS calls LP-8x4x 'programmable automation controller'. It is
> an industrial computer based on PXA270 SoC. They ship it with a 2.6.19
> kernel and proprietary kernel module and userspace library to access
> its industrial IO.

2 comments, otherwise:

Acked-by: Rob Herring <robh@kernel.org>

> diff --git a/arch/arm/boot/dts/pxa27x-lp8x4x.dts b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
> new file mode 100644
> index 0000000..bbb5b75
> --- /dev/null
> +++ b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
> @@ -0,0 +1,260 @@
> +/* Device tree for ICP DAS LP-8x4x */
> +/dts-v1/;
> +
> +#include <dt-bindings/interrupt-controller/arm-gic.h>

Pretty sure this does not have a GIC.

> +#include "pxa27x.dtsi"
> +
> +/ {
> +	model = "ICP DAS LP-8x4x programmable automation controller";
> +	compatible = "marvell,pxa270";

You should have a compatible string for this board.

Rob

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

* Re: [PATCH v4 2/2] arm: pxa27x: support for ICP DAS LP-8x4x w/ DT
@ 2015-12-11  2:53                 ` Rob Herring
  0 siblings, 0 replies; 700+ messages in thread
From: Rob Herring @ 2015-12-11  2:53 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: linux-kernel, Daniel Mack, Robert Jarzmik, Arnd Bergmann,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala, Russell King,
	Thierry Reding, Jonathan Cameron, Dmitry Torokhov, Philipp Zabel,
	Arnaud Ebalard, Kuninori Morimoto,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	moderated list:ARM PORT

On Thu, Dec 10, 2015 at 01:28:08AM +0300, Sergei Ianovich wrote:
> ICP DAS calls LP-8x4x 'programmable automation controller'. It is
> an industrial computer based on PXA270 SoC. They ship it with a 2.6.19
> kernel and proprietary kernel module and userspace library to access
> its industrial IO.

2 comments, otherwise:

Acked-by: Rob Herring <robh@kernel.org>

> diff --git a/arch/arm/boot/dts/pxa27x-lp8x4x.dts b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
> new file mode 100644
> index 0000000..bbb5b75
> --- /dev/null
> +++ b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
> @@ -0,0 +1,260 @@
> +/* Device tree for ICP DAS LP-8x4x */
> +/dts-v1/;
> +
> +#include <dt-bindings/interrupt-controller/arm-gic.h>

Pretty sure this does not have a GIC.

> +#include "pxa27x.dtsi"
> +
> +/ {
> +	model = "ICP DAS LP-8x4x programmable automation controller";
> +	compatible = "marvell,pxa270";

You should have a compatible string for this board.

Rob

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

* [PATCH v4 2/2] arm: pxa27x: support for ICP DAS LP-8x4x w/ DT
@ 2015-12-11  2:53                 ` Rob Herring
  0 siblings, 0 replies; 700+ messages in thread
From: Rob Herring @ 2015-12-11  2:53 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Dec 10, 2015 at 01:28:08AM +0300, Sergei Ianovich wrote:
> ICP DAS calls LP-8x4x 'programmable automation controller'. It is
> an industrial computer based on PXA270 SoC. They ship it with a 2.6.19
> kernel and proprietary kernel module and userspace library to access
> its industrial IO.

2 comments, otherwise:

Acked-by: Rob Herring <robh@kernel.org>

> diff --git a/arch/arm/boot/dts/pxa27x-lp8x4x.dts b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
> new file mode 100644
> index 0000000..bbb5b75
> --- /dev/null
> +++ b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
> @@ -0,0 +1,260 @@
> +/* Device tree for ICP DAS LP-8x4x */
> +/dts-v1/;
> +
> +#include <dt-bindings/interrupt-controller/arm-gic.h>

Pretty sure this does not have a GIC.

> +#include "pxa27x.dtsi"
> +
> +/ {
> +	model = "ICP DAS LP-8x4x programmable automation controller";
> +	compatible = "marvell,pxa270";

You should have a compatible string for this board.

Rob

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

* [PATCH v5 2/2] arm: pxa27x: support for ICP DAS LP-8x4x w/ DT
@ 2015-12-15 16:27                 ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2015-12-15 16:27 UTC (permalink / raw)
  To: linux-kernel
  Cc: Sergei Ianovich, Daniel Mack, Robert Jarzmik, Arnd Bergmann,
	Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	Russell King, Thierry Reding, Jonathan Cameron, Dmitry Torokhov,
	Philipp Zabel, Arnaud Ebalard, Kuninori Morimoto,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	moderated list:ARM PORT

ICP DAS calls LP-8x4x 'programmable automation controller'. It is
an industrial computer based on PXA270 SoC. They ship it with a 2.6.19
kernel and proprietary kernel module and userspace library to access
its industrial IO.

This patch allows to boot a modern kernel with device tree on
the device. It adds support for:
* MMC card interface on PXA270
* USB 1.1 port on PXA270
* 2 NOR flash devices
* 2 onboard ethernet Davicom DM9000 devices
* 3 serial UART ports on PXA270
* front panel red LED
* 64bit 1-wire system ID chip
* 16 kiB EEPROM (reading)

Support for these devices will be added in separate patches, since
they are not currently supported by the kernel:
* DS1302 RTC
* 512kiB SRAM
* FPGA irq chip
* 3 built-in 16550A serial UART ports
* industrial IO parallel bus
* 10 position rotary switch
* 8 pin DIP switch
* 16 kiB EEPROM (writing)
* serial interface for digital and analog industrial IO modules on
  parallel bus (all I-87xxx modules)
* digital and analog industrial IO modules for parallel bus:
  ** I-8024 4 port analog output
  ** I-8041 32 port digital output
  ** I-8042 16 port digital output/16 port digital input

Not supported for now:
* VGA interface on PXA270 for lack of dts binding
* the rest of parallel bus (I-8xxx) modules for lack of hardware
* GPIO reset for lack of relevance (watchdog reset is working)

Newer LP-8x4x devices have twice as much flash and a different
partition structure otherwise being the same. When each device
is provided with a correct device tree, all of them can be booted
using the same kernel.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
Acked-by: Rob Herring <robh@kernel.org>
CC: Daniel Mack <zonque@gmail.com>
CC: Robert Jarzmik <robert.jarzmik@free.fr>
CC: Arnd Bergmann <arnd@arndb.de>
---
   v4..v5
   fixes to apply Rob Herring's "Acked-by":
   * provide board compatible string
   * remove unused include directive in pxa27x-lp8x4x.dts

   v3..v4
   * support for newer flavor w/ 96Mb flash memory
   * use 'partitions' subnodes
   * move device-specific tweaking to device .dts file and drop
     patches to pxa27x.dtsi 

   v2..v3
   * added extbus which maps synchronous, static, and variable-latency
     I/O (VLIO) interfaces of PXA27x SoC as suggested by Arnd Bergmann
   * map is placed into platform include
   * configured existing kernel drivers to support:
     - front panel LED using gpio-leds
     - 64bit 1-wire system ID chip using w1-gpio
     - 16 kiB EEPROM using at24 over i2c-gpio
   * number change (06/16 -> 08/21)

   v1..v2
   * drop left-over extern declaration
   * use of_have_populated_dt() instead of a static variable
   * drop wildcards in compatible
   * drop machine-special machine description
   * number changed from 9 to 6 (dropped patches)

 .../devicetree/bindings/vendor-prefixes.txt        |   1 +
 arch/arm/boot/dts/Makefile                         |   3 +
 arch/arm/boot/dts/pxa27x-lp8x4x-i105.dts           |  50 ++++
 arch/arm/boot/dts/pxa27x-lp8x4x.dts                | 259 +++++++++++++++++++++
 arch/arm/configs/lp8x4x_defconfig                  | 176 ++++++++++++++
 5 files changed, 489 insertions(+)
 create mode 100644 arch/arm/boot/dts/pxa27x-lp8x4x-i105.dts
 create mode 100644 arch/arm/boot/dts/pxa27x-lp8x4x.dts
 create mode 100644 arch/arm/configs/lp8x4x_defconfig

diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index 55df1d4..2f1b078 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -109,6 +109,7 @@ honeywell	Honeywell
 hp	Hewlett Packard
 i2se	I2SE GmbH
 ibm	International Business Machines (IBM)
+icpdas	ICP DAS CO., LTD.
 idt	Integrated Device Technologies, Inc.
 iom	Iomega Corporation
 img	Imagination Technologies Ltd.
diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index 30bbc37..ed182ea 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -499,6 +499,9 @@ dtb-$(CONFIG_ARCH_ORION5X) += \
 	orion5x-rd88f5182-nas.dtb
 dtb-$(CONFIG_ARCH_PRIMA2) += \
 	prima2-evb.dtb
+dtb-$(CONFIG_MACH_PXA27X_DT) += \
+	pxa27x-lp8x4x.dtb \
+	pxa27x-lp8x4x-i105.dtb
 dtb-$(CONFIG_ARCH_QCOM) += \
 	qcom-apq8064-cm-qs600.dtb \
 	qcom-apq8064-ifc6410.dtb \
diff --git a/arch/arm/boot/dts/pxa27x-lp8x4x-i105.dts b/arch/arm/boot/dts/pxa27x-lp8x4x-i105.dts
new file mode 100644
index 0000000..903f5c7
--- /dev/null
+++ b/arch/arm/boot/dts/pxa27x-lp8x4x-i105.dts
@@ -0,0 +1,50 @@
+/* Device tree for ICP DAS LP-8x4x i105 flavor */
+
+#include "pxa27x-lp8x4x.dts"
+
+/ {
+	extbus {
+		flash@0 {
+			compatible = "cfi-flash";
+			reg = <0 0 0x04000000>;
+			bank-width = <4>;
+			device-width = <2>;
+
+			partitions {
+				#address-cells = <1>;
+				#size-cells = <1>;
+				fs@0 {
+					label = "u-boot";
+					reg = <0 0x40000>;
+				};
+				fs@40000 {
+					label = "settings";
+					reg = <0x40000 0x40000>;
+				};
+				fs@80000 {
+					label = "device_tree";
+					reg = <0x80000 0x40000>;
+				};
+				fs@c0000 {
+					label = "kernel";
+					reg = <0xc0000 0x2c0000>;
+				};
+				fs@300000 {
+					label = "root_fs";
+					reg = <0x380000 0x3c80000>;
+				};
+			};
+		};
+
+		flash@1 {
+			compatible = "cfi-flash";
+			reg = <1 0x0 0x02000000>;
+			bank-width = <2>;
+			device-width = <1>;
+			partitions {
+				#address-cells = <1>;
+				#size-cells = <1>;
+			};
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/pxa27x-lp8x4x.dts b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
new file mode 100644
index 0000000..7f33912c
--- /dev/null
+++ b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
@@ -0,0 +1,259 @@
+/* Device tree for ICP DAS LP-8x4x */
+/dts-v1/;
+
+#include "pxa27x.dtsi"
+
+/ {
+	model = "ICP DAS LP-8x4x programmable automation controller";
+	compatible = "icpdas,lp8x4x", "marvell,pxa270";
+
+	aliases {
+		ethernet0 = &eth0;
+		ethernet1 = &eth1;
+	};
+
+	memory {
+		reg = <0xa0000000 0x08000000>;
+	};
+
+	regulators {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		vmmc: regulator@0 {
+			compatible = "regulator-fixed";
+			reg = <0>;
+			regulator-name = "vmmc";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-always-on;
+		};
+	};
+
+	pxabus {
+		pxairq: interrupt-controller@40d00000 {
+			marvell,intc-priority;
+			marvell,intc-nr-irqs = <34>;
+		};
+
+		gpio: gpio@40e00000 {
+			interrupts = <8>, <9>, <10>;
+			interrupt-names = "gpio0", "gpio1", "gpio_mux";
+		};
+
+		uart@40100000 {
+			status = "okay";
+		};
+
+		uart@40200000 {
+			status = "okay";
+		};
+
+		uart@40700000 {
+			status = "okay";
+		};
+
+		mmc0: mmc@41100000 {
+			vmmc-supply = <&vmmc>;
+			status = "okay";
+		};
+
+		usb0: ohci@4c000000 {
+			marvell,port-mode = <3>;
+			marvell,oc-mode-perport;
+			marvell,enable-port1;
+			status = "okay";
+		};
+
+		leds {
+			compatible = "gpio-leds";
+
+			status {
+				gpios = <&gpio 84 1>;
+				linux,default-trigger = "heartbeat";
+			};
+		};
+
+		i2c: i2c-gpio {
+			compatible = "i2c-gpio";
+			gpios = <&gpio 22 0 /* sda */
+				 &gpio 12 0 /* scl */>;
+			i2c-gpio,delay-us = <1>;
+			i2c-gpio,timeout-ms = <1>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			eeprom@50 {
+				compatible = "atmel,24c128";
+				reg = <0x50>;
+				pagesize = <64>;
+			};
+		};
+
+		w1: w1-gpio {
+			compatible = "w1-gpio";
+			gpios = <&gpio 83 0>;
+		};
+	};
+
+	extbus {
+		/*
+		 * PXA27x synchrous, static and
+		 * variable-latency IO interfaces
+		 */
+		compatible = "simple-bus";
+
+		#address-cells = <2>; /* first cell is nCS, second is address */
+		#size-cells = <1>;
+		ranges = <0 0 0 0x04000000
+			  1 0 0x04000000 0x04000000
+			  2 0 0x08000000 0x04000000
+			  3 0 0x0c000000 0x04000000
+			  4 0 0x10000000 0x04000000
+			  5 0 0x14000000 0x04000000>;
+
+		flash@0 {
+			compatible = "cfi-flash";
+			reg = <0 0 0x02000000>;
+			bank-width = <4>;
+			device-width = <2>;
+
+			partitions {
+				#address-cells = <1>;
+				#size-cells = <1>;
+				fs@0 {
+					label = "u-boot";
+					reg = <0 0x40000>;
+				};
+				fs@40000 {
+					label = "settings";
+					reg = <0x40000 0x40000>;
+				};
+				fs@80000 {
+					label = "device_tree";
+					reg = <0x80000 0x40000>;
+				};
+				fs@c0000 {
+					label = "kernel";
+					reg = <0xc0000 0x240000>;
+				};
+				fs@300000 {
+					label = "root_fs";
+					reg = <0x300000 0x1d00000>;
+				};
+			};
+		};
+
+		flash@1 {
+			compatible = "cfi-flash";
+			reg = <1 0x0 0x01000000>;
+			bank-width = <2>;
+			device-width = <1>;
+			partitions {
+				#address-cells = <1>;
+				#size-cells = <1>;
+			};
+		};
+
+		netio@3 {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0 3 0 0x02000000>;
+			interrupt-parent = <&gpio>;
+
+			eth0: eth@0 {
+				compatible = "davicom,dm9000";
+				reg = <0x0 0x2
+				       0x4000 0x2>;
+				interrupts = <9 IRQ_TYPE_EDGE_RISING>;
+				status = "okay";
+			};
+
+			eth1: eth@1000000 {
+				compatible = "davicom,dm9000";
+				reg = <0x1000000 0x2
+				       0x1004000 0x2>;
+				interrupts = <82 IRQ_TYPE_EDGE_RISING>;
+				status = "okay";
+			};
+		};
+
+		fpga@5 {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0 5 0x3000000 0x10000>;
+			interrupt-parent = <&fpgairq>;
+
+			rtc@901c {
+				compatible = "dallas,rtc-ds1302";
+				reg = <0x901c 0x1>;
+				status = "okay";
+			};
+
+			sram@a000 {
+				compatible = "icpdas,sram-lp8x4x";
+				reg = <0xa000 0x1000
+				       0x901e 0x1>;
+
+				partitions {
+					#address-cells = <1>;
+					#size-cells = <1>;
+				};
+			};
+
+			fpgairq: irq@9006 {
+				compatible = "icpdas,irq-lp8x4x";
+				reg = <0x9006 0x16>;
+				interrupt-parent = <&gpio>;
+				interrupts = <3 IRQ_TYPE_EDGE_FALLING>;
+				#interrupt-cells = <1>;
+				interrupt-controller;
+				status = "okay";
+			};
+
+			uart@9050 {
+				compatible = "icpdas,uart-lp8x4x";
+				reg = <0x9050 0x10
+				       0x9030 0x02>;
+				interrupts = <13>;
+				status = "okay";
+			};
+
+			uart@9060 {
+				compatible = "icpdas,uart-lp8x4x";
+				reg = <0x9060 0x10
+				       0x9032 0x02>;
+				interrupts = <14>;
+				status = "okay";
+			};
+
+			uart@9070 {
+				compatible = "icpdas,uart-lp8x4x";
+				reg = <0x9070 0x10
+				       0x9034 0x02>;
+				interrupts = <15>;
+				status = "okay";
+			};
+
+			backplane {
+				compatible = "icpdas,backplane-lp8x4x";
+				reg = <0x0 0x2
+				       0x1000 0x10
+				       0x2000 0x10
+				       0x3000 0x10
+				       0x4000 0x10
+				       0x5000 0x10
+				       0x6000 0x10
+				       0x7000 0x10
+				       0x8000 0x10
+				       0x9002 0x2
+				       0x9004 0x2
+				       0x9046 0x2>;
+				eeprom-gpios = <&gpio 4 0>;
+			};
+		};
+	};
+};
diff --git a/arch/arm/configs/lp8x4x_defconfig b/arch/arm/configs/lp8x4x_defconfig
new file mode 100644
index 0000000..0eb87df
--- /dev/null
+++ b/arch/arm/configs/lp8x4x_defconfig
@@ -0,0 +1,176 @@
+# CONFIG_LOCALVERSION_AUTO is not set
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_RCU_BOOST=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_NS is not set
+# CONFIG_IPC_NS is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+# CONFIG_UID16 is not set
+# CONFIG_SHMEM is not set
+CONFIG_EMBEDDED=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_SLOB=y
+CONFIG_JUMP_LABEL=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+# CONFIG_LBDAF is not set
+CONFIG_BLK_CMDLINE_PARSER=y
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_ARCH_PXA=y
+CONFIG_MACH_PXA27X_DT=y
+# CONFIG_ARM_THUMB is not set
+CONFIG_PREEMPT=y
+CONFIG_AEABI=y
+# CONFIG_COMPACTION is not set
+# CONFIG_CROSS_MEMORY_ATTACH is not set
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="init=/sbin/init root=/dev/mmcblk0p1 rw rootfstype=ext4 console=ttyS0,115200 mem=128M rootwait"
+# CONFIG_SUSPEND is not set
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_BRIDGE=m
+CONFIG_BRIDGE_VLAN_FILTERING=y
+CONFIG_VLAN_8021Q=m
+CONFIG_VLAN_8021Q_GVRP=y
+CONFIG_VLAN_8021Q_MVRP=y
+# CONFIG_WIRELESS is not set
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+# CONFIG_FW_LOADER is not set
+CONFIG_MTD=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_CFI_GEOMETRY=y
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_PHYSMAP_OF=y
+CONFIG_MTD_SRAM_LP8X4X=y
+CONFIG_PROC_DEVICETREE=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_LOOP_MIN_COUNT=2
+CONFIG_EEPROM_AT24=m
+CONFIG_LP8X4X_BUS=m
+CONFIG_SCSI=y
+# CONFIG_SCSI_PROC_FS is not set
+CONFIG_BLK_DEV_SD=y
+# CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_NETDEVICES=y
+CONFIG_BONDING=m
+CONFIG_MACVLAN=m
+CONFIG_MACVTAP=m
+CONFIG_TUN=m
+# CONFIG_NET_VENDOR_ARC is not set
+# CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_CIRRUS is not set
+CONFIG_DM9000=y
+CONFIG_DM9000_FORCE_SIMPLE_PHY_POLL=y
+# CONFIG_NET_VENDOR_FARADAY is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+CONFIG_PPP=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPPOE=m
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_SLIP=m
+CONFIG_SLIP_COMPRESSED=y
+# CONFIG_WLAN is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=800
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=600
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_SERIO is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_8250=y
+# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=40
+CONFIG_SERIAL_8250_RUNTIME_UARTS=40
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_8250_PXA=y
+CONFIG_SERIAL_8250_LP8X4X=m
+CONFIG_HW_RANDOM=y
+CONFIG_I2C=m
+# CONFIG_I2C_COMPAT is not set
+CONFIG_I2C_GPIO=m
+CONFIG_W1=m
+CONFIG_W1_MASTER_GPIO=m
+CONFIG_W1_SLAVE_SMEM=m
+# CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_SA1100_WATCHDOG=m
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_FB=y
+CONFIG_FB_PXA=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_LOGO=y
+CONFIG_USB=m
+CONFIG_USB_OHCI_HCD=m
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+CONFIG_USB_STORAGE=m
+CONFIG_USB_SERIAL=m
+CONFIG_MMC=y
+CONFIG_MMC_PXA=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_DS1302=y
+CONFIG_RTC_DRV_PXA=m
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_DMA_ENGINE=y
+CONFIG_DMA_VIRTUAL_CHANNELS=y
+CONFIG_DMA_OF=y
+CONFIG_PXA_DMA=y
+CONFIG_EXT2_FS=m
+CONFIG_EXT3_FS=y
+CONFIG_EXT4_FS=y
+CONFIG_REISERFS_FS=m
+CONFIG_ISO9660_FS=m
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_NTFS_FS=m
+CONFIG_NTFS_RW=y
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V4=y
+CONFIG_ROOT_NFS=y
+CONFIG_CIFS=m
+CONFIG_CIFS_STATS=y
+CONFIG_CODA_FS=m
+CONFIG_NLS_DEFAULT="cp855"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_855=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_UTF8=y
+CONFIG_PRINTK_TIME=y
-- 
2.6.2


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

* [PATCH v5 2/2] arm: pxa27x: support for ICP DAS LP-8x4x w/ DT
@ 2015-12-15 16:27                 ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2015-12-15 16:27 UTC (permalink / raw)
  To: linux-kernel-u79uwXL29TY76Z2rM5mHXA
  Cc: Sergei Ianovich, Daniel Mack, Robert Jarzmik, Arnd Bergmann,
	Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	Russell King, Thierry Reding, Jonathan Cameron, Dmitry Torokhov,
	Philipp Zabel, Arnaud Ebalard, Kuninori Morimoto,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	moderated list:ARM PORT

ICP DAS calls LP-8x4x 'programmable automation controller'. It is
an industrial computer based on PXA270 SoC. They ship it with a 2.6.19
kernel and proprietary kernel module and userspace library to access
its industrial IO.

This patch allows to boot a modern kernel with device tree on
the device. It adds support for:
* MMC card interface on PXA270
* USB 1.1 port on PXA270
* 2 NOR flash devices
* 2 onboard ethernet Davicom DM9000 devices
* 3 serial UART ports on PXA270
* front panel red LED
* 64bit 1-wire system ID chip
* 16 kiB EEPROM (reading)

Support for these devices will be added in separate patches, since
they are not currently supported by the kernel:
* DS1302 RTC
* 512kiB SRAM
* FPGA irq chip
* 3 built-in 16550A serial UART ports
* industrial IO parallel bus
* 10 position rotary switch
* 8 pin DIP switch
* 16 kiB EEPROM (writing)
* serial interface for digital and analog industrial IO modules on
  parallel bus (all I-87xxx modules)
* digital and analog industrial IO modules for parallel bus:
  ** I-8024 4 port analog output
  ** I-8041 32 port digital output
  ** I-8042 16 port digital output/16 port digital input

Not supported for now:
* VGA interface on PXA270 for lack of dts binding
* the rest of parallel bus (I-8xxx) modules for lack of hardware
* GPIO reset for lack of relevance (watchdog reset is working)

Newer LP-8x4x devices have twice as much flash and a different
partition structure otherwise being the same. When each device
is provided with a correct device tree, all of them can be booted
using the same kernel.

Signed-off-by: Sergei Ianovich <ynvich-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Acked-by: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
CC: Daniel Mack <zonque-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
CC: Robert Jarzmik <robert.jarzmik-GANU6spQydw@public.gmane.org>
CC: Arnd Bergmann <arnd-r2nGTMty4D4@public.gmane.org>
---
   v4..v5
   fixes to apply Rob Herring's "Acked-by":
   * provide board compatible string
   * remove unused include directive in pxa27x-lp8x4x.dts

   v3..v4
   * support for newer flavor w/ 96Mb flash memory
   * use 'partitions' subnodes
   * move device-specific tweaking to device .dts file and drop
     patches to pxa27x.dtsi 

   v2..v3
   * added extbus which maps synchronous, static, and variable-latency
     I/O (VLIO) interfaces of PXA27x SoC as suggested by Arnd Bergmann
   * map is placed into platform include
   * configured existing kernel drivers to support:
     - front panel LED using gpio-leds
     - 64bit 1-wire system ID chip using w1-gpio
     - 16 kiB EEPROM using at24 over i2c-gpio
   * number change (06/16 -> 08/21)

   v1..v2
   * drop left-over extern declaration
   * use of_have_populated_dt() instead of a static variable
   * drop wildcards in compatible
   * drop machine-special machine description
   * number changed from 9 to 6 (dropped patches)

 .../devicetree/bindings/vendor-prefixes.txt        |   1 +
 arch/arm/boot/dts/Makefile                         |   3 +
 arch/arm/boot/dts/pxa27x-lp8x4x-i105.dts           |  50 ++++
 arch/arm/boot/dts/pxa27x-lp8x4x.dts                | 259 +++++++++++++++++++++
 arch/arm/configs/lp8x4x_defconfig                  | 176 ++++++++++++++
 5 files changed, 489 insertions(+)
 create mode 100644 arch/arm/boot/dts/pxa27x-lp8x4x-i105.dts
 create mode 100644 arch/arm/boot/dts/pxa27x-lp8x4x.dts
 create mode 100644 arch/arm/configs/lp8x4x_defconfig

diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index 55df1d4..2f1b078 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -109,6 +109,7 @@ honeywell	Honeywell
 hp	Hewlett Packard
 i2se	I2SE GmbH
 ibm	International Business Machines (IBM)
+icpdas	ICP DAS CO., LTD.
 idt	Integrated Device Technologies, Inc.
 iom	Iomega Corporation
 img	Imagination Technologies Ltd.
diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index 30bbc37..ed182ea 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -499,6 +499,9 @@ dtb-$(CONFIG_ARCH_ORION5X) += \
 	orion5x-rd88f5182-nas.dtb
 dtb-$(CONFIG_ARCH_PRIMA2) += \
 	prima2-evb.dtb
+dtb-$(CONFIG_MACH_PXA27X_DT) += \
+	pxa27x-lp8x4x.dtb \
+	pxa27x-lp8x4x-i105.dtb
 dtb-$(CONFIG_ARCH_QCOM) += \
 	qcom-apq8064-cm-qs600.dtb \
 	qcom-apq8064-ifc6410.dtb \
diff --git a/arch/arm/boot/dts/pxa27x-lp8x4x-i105.dts b/arch/arm/boot/dts/pxa27x-lp8x4x-i105.dts
new file mode 100644
index 0000000..903f5c7
--- /dev/null
+++ b/arch/arm/boot/dts/pxa27x-lp8x4x-i105.dts
@@ -0,0 +1,50 @@
+/* Device tree for ICP DAS LP-8x4x i105 flavor */
+
+#include "pxa27x-lp8x4x.dts"
+
+/ {
+	extbus {
+		flash@0 {
+			compatible = "cfi-flash";
+			reg = <0 0 0x04000000>;
+			bank-width = <4>;
+			device-width = <2>;
+
+			partitions {
+				#address-cells = <1>;
+				#size-cells = <1>;
+				fs@0 {
+					label = "u-boot";
+					reg = <0 0x40000>;
+				};
+				fs@40000 {
+					label = "settings";
+					reg = <0x40000 0x40000>;
+				};
+				fs@80000 {
+					label = "device_tree";
+					reg = <0x80000 0x40000>;
+				};
+				fs@c0000 {
+					label = "kernel";
+					reg = <0xc0000 0x2c0000>;
+				};
+				fs@300000 {
+					label = "root_fs";
+					reg = <0x380000 0x3c80000>;
+				};
+			};
+		};
+
+		flash@1 {
+			compatible = "cfi-flash";
+			reg = <1 0x0 0x02000000>;
+			bank-width = <2>;
+			device-width = <1>;
+			partitions {
+				#address-cells = <1>;
+				#size-cells = <1>;
+			};
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/pxa27x-lp8x4x.dts b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
new file mode 100644
index 0000000..7f33912c
--- /dev/null
+++ b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
@@ -0,0 +1,259 @@
+/* Device tree for ICP DAS LP-8x4x */
+/dts-v1/;
+
+#include "pxa27x.dtsi"
+
+/ {
+	model = "ICP DAS LP-8x4x programmable automation controller";
+	compatible = "icpdas,lp8x4x", "marvell,pxa270";
+
+	aliases {
+		ethernet0 = &eth0;
+		ethernet1 = &eth1;
+	};
+
+	memory {
+		reg = <0xa0000000 0x08000000>;
+	};
+
+	regulators {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		vmmc: regulator@0 {
+			compatible = "regulator-fixed";
+			reg = <0>;
+			regulator-name = "vmmc";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-always-on;
+		};
+	};
+
+	pxabus {
+		pxairq: interrupt-controller@40d00000 {
+			marvell,intc-priority;
+			marvell,intc-nr-irqs = <34>;
+		};
+
+		gpio: gpio@40e00000 {
+			interrupts = <8>, <9>, <10>;
+			interrupt-names = "gpio0", "gpio1", "gpio_mux";
+		};
+
+		uart@40100000 {
+			status = "okay";
+		};
+
+		uart@40200000 {
+			status = "okay";
+		};
+
+		uart@40700000 {
+			status = "okay";
+		};
+
+		mmc0: mmc@41100000 {
+			vmmc-supply = <&vmmc>;
+			status = "okay";
+		};
+
+		usb0: ohci@4c000000 {
+			marvell,port-mode = <3>;
+			marvell,oc-mode-perport;
+			marvell,enable-port1;
+			status = "okay";
+		};
+
+		leds {
+			compatible = "gpio-leds";
+
+			status {
+				gpios = <&gpio 84 1>;
+				linux,default-trigger = "heartbeat";
+			};
+		};
+
+		i2c: i2c-gpio {
+			compatible = "i2c-gpio";
+			gpios = <&gpio 22 0 /* sda */
+				 &gpio 12 0 /* scl */>;
+			i2c-gpio,delay-us = <1>;
+			i2c-gpio,timeout-ms = <1>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			eeprom@50 {
+				compatible = "atmel,24c128";
+				reg = <0x50>;
+				pagesize = <64>;
+			};
+		};
+
+		w1: w1-gpio {
+			compatible = "w1-gpio";
+			gpios = <&gpio 83 0>;
+		};
+	};
+
+	extbus {
+		/*
+		 * PXA27x synchrous, static and
+		 * variable-latency IO interfaces
+		 */
+		compatible = "simple-bus";
+
+		#address-cells = <2>; /* first cell is nCS, second is address */
+		#size-cells = <1>;
+		ranges = <0 0 0 0x04000000
+			  1 0 0x04000000 0x04000000
+			  2 0 0x08000000 0x04000000
+			  3 0 0x0c000000 0x04000000
+			  4 0 0x10000000 0x04000000
+			  5 0 0x14000000 0x04000000>;
+
+		flash@0 {
+			compatible = "cfi-flash";
+			reg = <0 0 0x02000000>;
+			bank-width = <4>;
+			device-width = <2>;
+
+			partitions {
+				#address-cells = <1>;
+				#size-cells = <1>;
+				fs@0 {
+					label = "u-boot";
+					reg = <0 0x40000>;
+				};
+				fs@40000 {
+					label = "settings";
+					reg = <0x40000 0x40000>;
+				};
+				fs@80000 {
+					label = "device_tree";
+					reg = <0x80000 0x40000>;
+				};
+				fs@c0000 {
+					label = "kernel";
+					reg = <0xc0000 0x240000>;
+				};
+				fs@300000 {
+					label = "root_fs";
+					reg = <0x300000 0x1d00000>;
+				};
+			};
+		};
+
+		flash@1 {
+			compatible = "cfi-flash";
+			reg = <1 0x0 0x01000000>;
+			bank-width = <2>;
+			device-width = <1>;
+			partitions {
+				#address-cells = <1>;
+				#size-cells = <1>;
+			};
+		};
+
+		netio@3 {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0 3 0 0x02000000>;
+			interrupt-parent = <&gpio>;
+
+			eth0: eth@0 {
+				compatible = "davicom,dm9000";
+				reg = <0x0 0x2
+				       0x4000 0x2>;
+				interrupts = <9 IRQ_TYPE_EDGE_RISING>;
+				status = "okay";
+			};
+
+			eth1: eth@1000000 {
+				compatible = "davicom,dm9000";
+				reg = <0x1000000 0x2
+				       0x1004000 0x2>;
+				interrupts = <82 IRQ_TYPE_EDGE_RISING>;
+				status = "okay";
+			};
+		};
+
+		fpga@5 {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0 5 0x3000000 0x10000>;
+			interrupt-parent = <&fpgairq>;
+
+			rtc@901c {
+				compatible = "dallas,rtc-ds1302";
+				reg = <0x901c 0x1>;
+				status = "okay";
+			};
+
+			sram@a000 {
+				compatible = "icpdas,sram-lp8x4x";
+				reg = <0xa000 0x1000
+				       0x901e 0x1>;
+
+				partitions {
+					#address-cells = <1>;
+					#size-cells = <1>;
+				};
+			};
+
+			fpgairq: irq@9006 {
+				compatible = "icpdas,irq-lp8x4x";
+				reg = <0x9006 0x16>;
+				interrupt-parent = <&gpio>;
+				interrupts = <3 IRQ_TYPE_EDGE_FALLING>;
+				#interrupt-cells = <1>;
+				interrupt-controller;
+				status = "okay";
+			};
+
+			uart@9050 {
+				compatible = "icpdas,uart-lp8x4x";
+				reg = <0x9050 0x10
+				       0x9030 0x02>;
+				interrupts = <13>;
+				status = "okay";
+			};
+
+			uart@9060 {
+				compatible = "icpdas,uart-lp8x4x";
+				reg = <0x9060 0x10
+				       0x9032 0x02>;
+				interrupts = <14>;
+				status = "okay";
+			};
+
+			uart@9070 {
+				compatible = "icpdas,uart-lp8x4x";
+				reg = <0x9070 0x10
+				       0x9034 0x02>;
+				interrupts = <15>;
+				status = "okay";
+			};
+
+			backplane {
+				compatible = "icpdas,backplane-lp8x4x";
+				reg = <0x0 0x2
+				       0x1000 0x10
+				       0x2000 0x10
+				       0x3000 0x10
+				       0x4000 0x10
+				       0x5000 0x10
+				       0x6000 0x10
+				       0x7000 0x10
+				       0x8000 0x10
+				       0x9002 0x2
+				       0x9004 0x2
+				       0x9046 0x2>;
+				eeprom-gpios = <&gpio 4 0>;
+			};
+		};
+	};
+};
diff --git a/arch/arm/configs/lp8x4x_defconfig b/arch/arm/configs/lp8x4x_defconfig
new file mode 100644
index 0000000..0eb87df
--- /dev/null
+++ b/arch/arm/configs/lp8x4x_defconfig
@@ -0,0 +1,176 @@
+# CONFIG_LOCALVERSION_AUTO is not set
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_RCU_BOOST=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_NS is not set
+# CONFIG_IPC_NS is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+# CONFIG_UID16 is not set
+# CONFIG_SHMEM is not set
+CONFIG_EMBEDDED=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_SLOB=y
+CONFIG_JUMP_LABEL=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+# CONFIG_LBDAF is not set
+CONFIG_BLK_CMDLINE_PARSER=y
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_ARCH_PXA=y
+CONFIG_MACH_PXA27X_DT=y
+# CONFIG_ARM_THUMB is not set
+CONFIG_PREEMPT=y
+CONFIG_AEABI=y
+# CONFIG_COMPACTION is not set
+# CONFIG_CROSS_MEMORY_ATTACH is not set
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="init=/sbin/init root=/dev/mmcblk0p1 rw rootfstype=ext4 console=ttyS0,115200 mem=128M rootwait"
+# CONFIG_SUSPEND is not set
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_BRIDGE=m
+CONFIG_BRIDGE_VLAN_FILTERING=y
+CONFIG_VLAN_8021Q=m
+CONFIG_VLAN_8021Q_GVRP=y
+CONFIG_VLAN_8021Q_MVRP=y
+# CONFIG_WIRELESS is not set
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+# CONFIG_FW_LOADER is not set
+CONFIG_MTD=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_CFI_GEOMETRY=y
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_PHYSMAP_OF=y
+CONFIG_MTD_SRAM_LP8X4X=y
+CONFIG_PROC_DEVICETREE=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_LOOP_MIN_COUNT=2
+CONFIG_EEPROM_AT24=m
+CONFIG_LP8X4X_BUS=m
+CONFIG_SCSI=y
+# CONFIG_SCSI_PROC_FS is not set
+CONFIG_BLK_DEV_SD=y
+# CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_NETDEVICES=y
+CONFIG_BONDING=m
+CONFIG_MACVLAN=m
+CONFIG_MACVTAP=m
+CONFIG_TUN=m
+# CONFIG_NET_VENDOR_ARC is not set
+# CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_CIRRUS is not set
+CONFIG_DM9000=y
+CONFIG_DM9000_FORCE_SIMPLE_PHY_POLL=y
+# CONFIG_NET_VENDOR_FARADAY is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+CONFIG_PPP=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPPOE=m
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_SLIP=m
+CONFIG_SLIP_COMPRESSED=y
+# CONFIG_WLAN is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=800
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=600
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_SERIO is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_8250=y
+# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=40
+CONFIG_SERIAL_8250_RUNTIME_UARTS=40
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_8250_PXA=y
+CONFIG_SERIAL_8250_LP8X4X=m
+CONFIG_HW_RANDOM=y
+CONFIG_I2C=m
+# CONFIG_I2C_COMPAT is not set
+CONFIG_I2C_GPIO=m
+CONFIG_W1=m
+CONFIG_W1_MASTER_GPIO=m
+CONFIG_W1_SLAVE_SMEM=m
+# CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_SA1100_WATCHDOG=m
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_FB=y
+CONFIG_FB_PXA=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_LOGO=y
+CONFIG_USB=m
+CONFIG_USB_OHCI_HCD=m
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+CONFIG_USB_STORAGE=m
+CONFIG_USB_SERIAL=m
+CONFIG_MMC=y
+CONFIG_MMC_PXA=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_DS1302=y
+CONFIG_RTC_DRV_PXA=m
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_DMA_ENGINE=y
+CONFIG_DMA_VIRTUAL_CHANNELS=y
+CONFIG_DMA_OF=y
+CONFIG_PXA_DMA=y
+CONFIG_EXT2_FS=m
+CONFIG_EXT3_FS=y
+CONFIG_EXT4_FS=y
+CONFIG_REISERFS_FS=m
+CONFIG_ISO9660_FS=m
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_NTFS_FS=m
+CONFIG_NTFS_RW=y
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V4=y
+CONFIG_ROOT_NFS=y
+CONFIG_CIFS=m
+CONFIG_CIFS_STATS=y
+CONFIG_CODA_FS=m
+CONFIG_NLS_DEFAULT="cp855"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_855=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_UTF8=y
+CONFIG_PRINTK_TIME=y
-- 
2.6.2

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH v5 2/2] arm: pxa27x: support for ICP DAS LP-8x4x w/ DT
@ 2015-12-15 16:27                 ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2015-12-15 16:27 UTC (permalink / raw)
  To: linux-arm-kernel

ICP DAS calls LP-8x4x 'programmable automation controller'. It is
an industrial computer based on PXA270 SoC. They ship it with a 2.6.19
kernel and proprietary kernel module and userspace library to access
its industrial IO.

This patch allows to boot a modern kernel with device tree on
the device. It adds support for:
* MMC card interface on PXA270
* USB 1.1 port on PXA270
* 2 NOR flash devices
* 2 onboard ethernet Davicom DM9000 devices
* 3 serial UART ports on PXA270
* front panel red LED
* 64bit 1-wire system ID chip
* 16 kiB EEPROM (reading)

Support for these devices will be added in separate patches, since
they are not currently supported by the kernel:
* DS1302 RTC
* 512kiB SRAM
* FPGA irq chip
* 3 built-in 16550A serial UART ports
* industrial IO parallel bus
* 10 position rotary switch
* 8 pin DIP switch
* 16 kiB EEPROM (writing)
* serial interface for digital and analog industrial IO modules on
  parallel bus (all I-87xxx modules)
* digital and analog industrial IO modules for parallel bus:
  ** I-8024 4 port analog output
  ** I-8041 32 port digital output
  ** I-8042 16 port digital output/16 port digital input

Not supported for now:
* VGA interface on PXA270 for lack of dts binding
* the rest of parallel bus (I-8xxx) modules for lack of hardware
* GPIO reset for lack of relevance (watchdog reset is working)

Newer LP-8x4x devices have twice as much flash and a different
partition structure otherwise being the same. When each device
is provided with a correct device tree, all of them can be booted
using the same kernel.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
Acked-by: Rob Herring <robh@kernel.org>
CC: Daniel Mack <zonque@gmail.com>
CC: Robert Jarzmik <robert.jarzmik@free.fr>
CC: Arnd Bergmann <arnd@arndb.de>
---
   v4..v5
   fixes to apply Rob Herring's "Acked-by":
   * provide board compatible string
   * remove unused include directive in pxa27x-lp8x4x.dts

   v3..v4
   * support for newer flavor w/ 96Mb flash memory
   * use 'partitions' subnodes
   * move device-specific tweaking to device .dts file and drop
     patches to pxa27x.dtsi 

   v2..v3
   * added extbus which maps synchronous, static, and variable-latency
     I/O (VLIO) interfaces of PXA27x SoC as suggested by Arnd Bergmann
   * map is placed into platform include
   * configured existing kernel drivers to support:
     - front panel LED using gpio-leds
     - 64bit 1-wire system ID chip using w1-gpio
     - 16 kiB EEPROM using at24 over i2c-gpio
   * number change (06/16 -> 08/21)

   v1..v2
   * drop left-over extern declaration
   * use of_have_populated_dt() instead of a static variable
   * drop wildcards in compatible
   * drop machine-special machine description
   * number changed from 9 to 6 (dropped patches)

 .../devicetree/bindings/vendor-prefixes.txt        |   1 +
 arch/arm/boot/dts/Makefile                         |   3 +
 arch/arm/boot/dts/pxa27x-lp8x4x-i105.dts           |  50 ++++
 arch/arm/boot/dts/pxa27x-lp8x4x.dts                | 259 +++++++++++++++++++++
 arch/arm/configs/lp8x4x_defconfig                  | 176 ++++++++++++++
 5 files changed, 489 insertions(+)
 create mode 100644 arch/arm/boot/dts/pxa27x-lp8x4x-i105.dts
 create mode 100644 arch/arm/boot/dts/pxa27x-lp8x4x.dts
 create mode 100644 arch/arm/configs/lp8x4x_defconfig

diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index 55df1d4..2f1b078 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -109,6 +109,7 @@ honeywell	Honeywell
 hp	Hewlett Packard
 i2se	I2SE GmbH
 ibm	International Business Machines (IBM)
+icpdas	ICP DAS CO., LTD.
 idt	Integrated Device Technologies, Inc.
 iom	Iomega Corporation
 img	Imagination Technologies Ltd.
diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index 30bbc37..ed182ea 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -499,6 +499,9 @@ dtb-$(CONFIG_ARCH_ORION5X) += \
 	orion5x-rd88f5182-nas.dtb
 dtb-$(CONFIG_ARCH_PRIMA2) += \
 	prima2-evb.dtb
+dtb-$(CONFIG_MACH_PXA27X_DT) += \
+	pxa27x-lp8x4x.dtb \
+	pxa27x-lp8x4x-i105.dtb
 dtb-$(CONFIG_ARCH_QCOM) += \
 	qcom-apq8064-cm-qs600.dtb \
 	qcom-apq8064-ifc6410.dtb \
diff --git a/arch/arm/boot/dts/pxa27x-lp8x4x-i105.dts b/arch/arm/boot/dts/pxa27x-lp8x4x-i105.dts
new file mode 100644
index 0000000..903f5c7
--- /dev/null
+++ b/arch/arm/boot/dts/pxa27x-lp8x4x-i105.dts
@@ -0,0 +1,50 @@
+/* Device tree for ICP DAS LP-8x4x i105 flavor */
+
+#include "pxa27x-lp8x4x.dts"
+
+/ {
+	extbus {
+		flash at 0 {
+			compatible = "cfi-flash";
+			reg = <0 0 0x04000000>;
+			bank-width = <4>;
+			device-width = <2>;
+
+			partitions {
+				#address-cells = <1>;
+				#size-cells = <1>;
+				fs at 0 {
+					label = "u-boot";
+					reg = <0 0x40000>;
+				};
+				fs at 40000 {
+					label = "settings";
+					reg = <0x40000 0x40000>;
+				};
+				fs at 80000 {
+					label = "device_tree";
+					reg = <0x80000 0x40000>;
+				};
+				fs at c0000 {
+					label = "kernel";
+					reg = <0xc0000 0x2c0000>;
+				};
+				fs at 300000 {
+					label = "root_fs";
+					reg = <0x380000 0x3c80000>;
+				};
+			};
+		};
+
+		flash at 1 {
+			compatible = "cfi-flash";
+			reg = <1 0x0 0x02000000>;
+			bank-width = <2>;
+			device-width = <1>;
+			partitions {
+				#address-cells = <1>;
+				#size-cells = <1>;
+			};
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/pxa27x-lp8x4x.dts b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
new file mode 100644
index 0000000..7f33912c
--- /dev/null
+++ b/arch/arm/boot/dts/pxa27x-lp8x4x.dts
@@ -0,0 +1,259 @@
+/* Device tree for ICP DAS LP-8x4x */
+/dts-v1/;
+
+#include "pxa27x.dtsi"
+
+/ {
+	model = "ICP DAS LP-8x4x programmable automation controller";
+	compatible = "icpdas,lp8x4x", "marvell,pxa270";
+
+	aliases {
+		ethernet0 = &eth0;
+		ethernet1 = &eth1;
+	};
+
+	memory {
+		reg = <0xa0000000 0x08000000>;
+	};
+
+	regulators {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		vmmc: regulator at 0 {
+			compatible = "regulator-fixed";
+			reg = <0>;
+			regulator-name = "vmmc";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-always-on;
+		};
+	};
+
+	pxabus {
+		pxairq: interrupt-controller at 40d00000 {
+			marvell,intc-priority;
+			marvell,intc-nr-irqs = <34>;
+		};
+
+		gpio: gpio at 40e00000 {
+			interrupts = <8>, <9>, <10>;
+			interrupt-names = "gpio0", "gpio1", "gpio_mux";
+		};
+
+		uart at 40100000 {
+			status = "okay";
+		};
+
+		uart at 40200000 {
+			status = "okay";
+		};
+
+		uart at 40700000 {
+			status = "okay";
+		};
+
+		mmc0: mmc at 41100000 {
+			vmmc-supply = <&vmmc>;
+			status = "okay";
+		};
+
+		usb0: ohci at 4c000000 {
+			marvell,port-mode = <3>;
+			marvell,oc-mode-perport;
+			marvell,enable-port1;
+			status = "okay";
+		};
+
+		leds {
+			compatible = "gpio-leds";
+
+			status {
+				gpios = <&gpio 84 1>;
+				linux,default-trigger = "heartbeat";
+			};
+		};
+
+		i2c: i2c-gpio {
+			compatible = "i2c-gpio";
+			gpios = <&gpio 22 0 /* sda */
+				 &gpio 12 0 /* scl */>;
+			i2c-gpio,delay-us = <1>;
+			i2c-gpio,timeout-ms = <1>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			eeprom at 50 {
+				compatible = "atmel,24c128";
+				reg = <0x50>;
+				pagesize = <64>;
+			};
+		};
+
+		w1: w1-gpio {
+			compatible = "w1-gpio";
+			gpios = <&gpio 83 0>;
+		};
+	};
+
+	extbus {
+		/*
+		 * PXA27x synchrous, static and
+		 * variable-latency IO interfaces
+		 */
+		compatible = "simple-bus";
+
+		#address-cells = <2>; /* first cell is nCS, second is address */
+		#size-cells = <1>;
+		ranges = <0 0 0 0x04000000
+			  1 0 0x04000000 0x04000000
+			  2 0 0x08000000 0x04000000
+			  3 0 0x0c000000 0x04000000
+			  4 0 0x10000000 0x04000000
+			  5 0 0x14000000 0x04000000>;
+
+		flash at 0 {
+			compatible = "cfi-flash";
+			reg = <0 0 0x02000000>;
+			bank-width = <4>;
+			device-width = <2>;
+
+			partitions {
+				#address-cells = <1>;
+				#size-cells = <1>;
+				fs at 0 {
+					label = "u-boot";
+					reg = <0 0x40000>;
+				};
+				fs at 40000 {
+					label = "settings";
+					reg = <0x40000 0x40000>;
+				};
+				fs at 80000 {
+					label = "device_tree";
+					reg = <0x80000 0x40000>;
+				};
+				fs at c0000 {
+					label = "kernel";
+					reg = <0xc0000 0x240000>;
+				};
+				fs at 300000 {
+					label = "root_fs";
+					reg = <0x300000 0x1d00000>;
+				};
+			};
+		};
+
+		flash at 1 {
+			compatible = "cfi-flash";
+			reg = <1 0x0 0x01000000>;
+			bank-width = <2>;
+			device-width = <1>;
+			partitions {
+				#address-cells = <1>;
+				#size-cells = <1>;
+			};
+		};
+
+		netio at 3 {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0 3 0 0x02000000>;
+			interrupt-parent = <&gpio>;
+
+			eth0: eth at 0 {
+				compatible = "davicom,dm9000";
+				reg = <0x0 0x2
+				       0x4000 0x2>;
+				interrupts = <9 IRQ_TYPE_EDGE_RISING>;
+				status = "okay";
+			};
+
+			eth1: eth at 1000000 {
+				compatible = "davicom,dm9000";
+				reg = <0x1000000 0x2
+				       0x1004000 0x2>;
+				interrupts = <82 IRQ_TYPE_EDGE_RISING>;
+				status = "okay";
+			};
+		};
+
+		fpga at 5 {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0 5 0x3000000 0x10000>;
+			interrupt-parent = <&fpgairq>;
+
+			rtc at 901c {
+				compatible = "dallas,rtc-ds1302";
+				reg = <0x901c 0x1>;
+				status = "okay";
+			};
+
+			sram at a000 {
+				compatible = "icpdas,sram-lp8x4x";
+				reg = <0xa000 0x1000
+				       0x901e 0x1>;
+
+				partitions {
+					#address-cells = <1>;
+					#size-cells = <1>;
+				};
+			};
+
+			fpgairq: irq at 9006 {
+				compatible = "icpdas,irq-lp8x4x";
+				reg = <0x9006 0x16>;
+				interrupt-parent = <&gpio>;
+				interrupts = <3 IRQ_TYPE_EDGE_FALLING>;
+				#interrupt-cells = <1>;
+				interrupt-controller;
+				status = "okay";
+			};
+
+			uart at 9050 {
+				compatible = "icpdas,uart-lp8x4x";
+				reg = <0x9050 0x10
+				       0x9030 0x02>;
+				interrupts = <13>;
+				status = "okay";
+			};
+
+			uart at 9060 {
+				compatible = "icpdas,uart-lp8x4x";
+				reg = <0x9060 0x10
+				       0x9032 0x02>;
+				interrupts = <14>;
+				status = "okay";
+			};
+
+			uart at 9070 {
+				compatible = "icpdas,uart-lp8x4x";
+				reg = <0x9070 0x10
+				       0x9034 0x02>;
+				interrupts = <15>;
+				status = "okay";
+			};
+
+			backplane {
+				compatible = "icpdas,backplane-lp8x4x";
+				reg = <0x0 0x2
+				       0x1000 0x10
+				       0x2000 0x10
+				       0x3000 0x10
+				       0x4000 0x10
+				       0x5000 0x10
+				       0x6000 0x10
+				       0x7000 0x10
+				       0x8000 0x10
+				       0x9002 0x2
+				       0x9004 0x2
+				       0x9046 0x2>;
+				eeprom-gpios = <&gpio 4 0>;
+			};
+		};
+	};
+};
diff --git a/arch/arm/configs/lp8x4x_defconfig b/arch/arm/configs/lp8x4x_defconfig
new file mode 100644
index 0000000..0eb87df
--- /dev/null
+++ b/arch/arm/configs/lp8x4x_defconfig
@@ -0,0 +1,176 @@
+# CONFIG_LOCALVERSION_AUTO is not set
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_RCU_BOOST=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_NS is not set
+# CONFIG_IPC_NS is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+# CONFIG_UID16 is not set
+# CONFIG_SHMEM is not set
+CONFIG_EMBEDDED=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_SLOB=y
+CONFIG_JUMP_LABEL=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+# CONFIG_LBDAF is not set
+CONFIG_BLK_CMDLINE_PARSER=y
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_ARCH_PXA=y
+CONFIG_MACH_PXA27X_DT=y
+# CONFIG_ARM_THUMB is not set
+CONFIG_PREEMPT=y
+CONFIG_AEABI=y
+# CONFIG_COMPACTION is not set
+# CONFIG_CROSS_MEMORY_ATTACH is not set
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="init=/sbin/init root=/dev/mmcblk0p1 rw rootfstype=ext4 console=ttyS0,115200 mem=128M rootwait"
+# CONFIG_SUSPEND is not set
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_BRIDGE=m
+CONFIG_BRIDGE_VLAN_FILTERING=y
+CONFIG_VLAN_8021Q=m
+CONFIG_VLAN_8021Q_GVRP=y
+CONFIG_VLAN_8021Q_MVRP=y
+# CONFIG_WIRELESS is not set
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+# CONFIG_FW_LOADER is not set
+CONFIG_MTD=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_CFI_GEOMETRY=y
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_PHYSMAP_OF=y
+CONFIG_MTD_SRAM_LP8X4X=y
+CONFIG_PROC_DEVICETREE=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_LOOP_MIN_COUNT=2
+CONFIG_EEPROM_AT24=m
+CONFIG_LP8X4X_BUS=m
+CONFIG_SCSI=y
+# CONFIG_SCSI_PROC_FS is not set
+CONFIG_BLK_DEV_SD=y
+# CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_NETDEVICES=y
+CONFIG_BONDING=m
+CONFIG_MACVLAN=m
+CONFIG_MACVTAP=m
+CONFIG_TUN=m
+# CONFIG_NET_VENDOR_ARC is not set
+# CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_CIRRUS is not set
+CONFIG_DM9000=y
+CONFIG_DM9000_FORCE_SIMPLE_PHY_POLL=y
+# CONFIG_NET_VENDOR_FARADAY is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+CONFIG_PPP=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPPOE=m
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_SLIP=m
+CONFIG_SLIP_COMPRESSED=y
+# CONFIG_WLAN is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=800
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=600
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_SERIO is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_8250=y
+# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=40
+CONFIG_SERIAL_8250_RUNTIME_UARTS=40
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_8250_PXA=y
+CONFIG_SERIAL_8250_LP8X4X=m
+CONFIG_HW_RANDOM=y
+CONFIG_I2C=m
+# CONFIG_I2C_COMPAT is not set
+CONFIG_I2C_GPIO=m
+CONFIG_W1=m
+CONFIG_W1_MASTER_GPIO=m
+CONFIG_W1_SLAVE_SMEM=m
+# CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_SA1100_WATCHDOG=m
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_FB=y
+CONFIG_FB_PXA=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_LOGO=y
+CONFIG_USB=m
+CONFIG_USB_OHCI_HCD=m
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+CONFIG_USB_STORAGE=m
+CONFIG_USB_SERIAL=m
+CONFIG_MMC=y
+CONFIG_MMC_PXA=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_DS1302=y
+CONFIG_RTC_DRV_PXA=m
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_DMA_ENGINE=y
+CONFIG_DMA_VIRTUAL_CHANNELS=y
+CONFIG_DMA_OF=y
+CONFIG_PXA_DMA=y
+CONFIG_EXT2_FS=m
+CONFIG_EXT3_FS=y
+CONFIG_EXT4_FS=y
+CONFIG_REISERFS_FS=m
+CONFIG_ISO9660_FS=m
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_NTFS_FS=m
+CONFIG_NTFS_RW=y
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V4=y
+CONFIG_ROOT_NFS=y
+CONFIG_CIFS=m
+CONFIG_CIFS_STATS=y
+CONFIG_CODA_FS=m
+CONFIG_NLS_DEFAULT="cp855"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_855=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_UTF8=y
+CONFIG_PRINTK_TIME=y
-- 
2.6.2

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

* Re: [PATCH v5 2/2] arm: pxa27x: support for ICP DAS LP-8x4x w/ DT
  2015-12-15 16:27                 ` Sergei Ianovich
  (?)
@ 2015-12-15 16:32                   ` Arnd Bergmann
  -1 siblings, 0 replies; 700+ messages in thread
From: Arnd Bergmann @ 2015-12-15 16:32 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: linux-kernel, Daniel Mack, Robert Jarzmik, Rob Herring,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala, Russell King,
	Thierry Reding, Jonathan Cameron, Dmitry Torokhov, Philipp Zabel,
	Arnaud Ebalard, Kuninori Morimoto,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	moderated list:ARM PORT

On Tuesday 15 December 2015 19:27:50 Sergei Ianovich wrote:
>  .../devicetree/bindings/vendor-prefixes.txt        |   1 +
>  arch/arm/boot/dts/Makefile                         |   3 +
>  arch/arm/boot/dts/pxa27x-lp8x4x-i105.dts           |  50 ++++
>  arch/arm/boot/dts/pxa27x-lp8x4x.dts                | 259 +++++++++++++++++++++
>  arch/arm/configs/lp8x4x_defconfig                  | 176 ++++++++++++++
> 

I had not noticed earlier that you are adding a new defconfig file. PXA is
already the platform with the most defconfig files, and I'd rather like
to see that reduced than increased.

Is there a chance you could merge this one with some of the existing files
into one configuration that handles them all?

	Arnd

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

* Re: [PATCH v5 2/2] arm: pxa27x: support for ICP DAS LP-8x4x w/ DT
@ 2015-12-15 16:32                   ` Arnd Bergmann
  0 siblings, 0 replies; 700+ messages in thread
From: Arnd Bergmann @ 2015-12-15 16:32 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: linux-kernel, Daniel Mack, Robert Jarzmik, Rob Herring,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala, Russell King,
	Thierry Reding, Jonathan Cameron, Dmitry Torokhov, Philipp Zabel,
	Arnaud Ebalard, Kuninori Morimoto,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	moderated list:ARM PORT

On Tuesday 15 December 2015 19:27:50 Sergei Ianovich wrote:
>  .../devicetree/bindings/vendor-prefixes.txt        |   1 +
>  arch/arm/boot/dts/Makefile                         |   3 +
>  arch/arm/boot/dts/pxa27x-lp8x4x-i105.dts           |  50 ++++
>  arch/arm/boot/dts/pxa27x-lp8x4x.dts                | 259 +++++++++++++++++++++
>  arch/arm/configs/lp8x4x_defconfig                  | 176 ++++++++++++++
> 

I had not noticed earlier that you are adding a new defconfig file. PXA is
already the platform with the most defconfig files, and I'd rather like
to see that reduced than increased.

Is there a chance you could merge this one with some of the existing files
into one configuration that handles them all?

	Arnd

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

* [PATCH v5 2/2] arm: pxa27x: support for ICP DAS LP-8x4x w/ DT
@ 2015-12-15 16:32                   ` Arnd Bergmann
  0 siblings, 0 replies; 700+ messages in thread
From: Arnd Bergmann @ 2015-12-15 16:32 UTC (permalink / raw)
  To: linux-arm-kernel

On Tuesday 15 December 2015 19:27:50 Sergei Ianovich wrote:
>  .../devicetree/bindings/vendor-prefixes.txt        |   1 +
>  arch/arm/boot/dts/Makefile                         |   3 +
>  arch/arm/boot/dts/pxa27x-lp8x4x-i105.dts           |  50 ++++
>  arch/arm/boot/dts/pxa27x-lp8x4x.dts                | 259 +++++++++++++++++++++
>  arch/arm/configs/lp8x4x_defconfig                  | 176 ++++++++++++++
> 

I had not noticed earlier that you are adding a new defconfig file. PXA is
already the platform with the most defconfig files, and I'd rather like
to see that reduced than increased.

Is there a chance you could merge this one with some of the existing files
into one configuration that handles them all?

	Arnd

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

* Re: [PATCH v5 2/2] arm: pxa27x: support for ICP DAS LP-8x4x w/ DT
  2015-12-15 16:32                   ` Arnd Bergmann
  (?)
@ 2015-12-15 16:42                     ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2015-12-15 16:42 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: linux-kernel, Daniel Mack, Robert Jarzmik, Rob Herring,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala, Russell King,
	Thierry Reding, Jonathan Cameron, Dmitry Torokhov, Philipp Zabel,
	Arnaud Ebalard, Kuninori Morimoto,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	moderated list:ARM PORT

On Tue, 2015-12-15 at 17:32 +0100, Arnd Bergmann wrote:
> On Tuesday 15 December 2015 19:27:50 Sergei Ianovich wrote:
> >  .../devicetree/bindings/vendor-prefixes.txt        |   1 +
> >  arch/arm/boot/dts/Makefile                         |   3 +
> >  arch/arm/boot/dts/pxa27x-lp8x4x-i105.dts           |  50 ++++
> >  arch/arm/boot/dts/pxa27x-lp8x4x.dts                | 259
> > +++++++++++++++++++++
> >  arch/arm/configs/lp8x4x_defconfig                  | 176
> > ++++++++++++++
> > 
> 
> I had not noticed earlier that you are adding a new defconfig file.
> PXA is
> already the platform with the most defconfig files, and I'd rather
> like
> to see that reduced than increased.
> 
> Is there a chance you could merge this one with some of the existing
> files
> into one configuration that handles them all?

There are several board-specific devices on LP8x4x: custom FPGA, custom
UART, custom IRQ on FPGA, custom parallel bus for industrial IO. The
defconfig file could alert potential users to this fact. If this is not
a sufficient reason to have a defconfig file, it can be dropped.

I use the full .config anyway :)

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

* Re: [PATCH v5 2/2] arm: pxa27x: support for ICP DAS LP-8x4x w/ DT
@ 2015-12-15 16:42                     ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2015-12-15 16:42 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: linux-kernel, Daniel Mack, Robert Jarzmik, Rob Herring,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala, Russell King,
	Thierry Reding, Jonathan Cameron, Dmitry Torokhov, Philipp Zabel,
	Arnaud Ebalard, Kuninori Morimoto,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	moderated list:ARM PORT

On Tue, 2015-12-15 at 17:32 +0100, Arnd Bergmann wrote:
> On Tuesday 15 December 2015 19:27:50 Sergei Ianovich wrote:
> >  .../devicetree/bindings/vendor-prefixes.txt        |   1 +
> >  arch/arm/boot/dts/Makefile                         |   3 +
> >  arch/arm/boot/dts/pxa27x-lp8x4x-i105.dts           |  50 ++++
> >  arch/arm/boot/dts/pxa27x-lp8x4x.dts                | 259
> > +++++++++++++++++++++
> >  arch/arm/configs/lp8x4x_defconfig                  | 176
> > ++++++++++++++
> > 
> 
> I had not noticed earlier that you are adding a new defconfig file.
> PXA is
> already the platform with the most defconfig files, and I'd rather
> like
> to see that reduced than increased.
> 
> Is there a chance you could merge this one with some of the existing
> files
> into one configuration that handles them all?

There are several board-specific devices on LP8x4x: custom FPGA, custom
UART, custom IRQ on FPGA, custom parallel bus for industrial IO. The
defconfig file could alert potential users to this fact. If this is not
a sufficient reason to have a defconfig file, it can be dropped.

I use the full .config anyway :)

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

* [PATCH v5 2/2] arm: pxa27x: support for ICP DAS LP-8x4x w/ DT
@ 2015-12-15 16:42                     ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2015-12-15 16:42 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, 2015-12-15 at 17:32 +0100, Arnd Bergmann wrote:
> On Tuesday 15 December 2015 19:27:50 Sergei Ianovich wrote:
> > ?.../devicetree/bindings/vendor-prefixes.txt????????|???1 +
> > ?arch/arm/boot/dts/Makefile?????????????????????????|???3 +
> > ?arch/arm/boot/dts/pxa27x-lp8x4x-i105.dts???????????|??50 ++++
> > ?arch/arm/boot/dts/pxa27x-lp8x4x.dts????????????????| 259
> > +++++++++++++++++++++
> > ?arch/arm/configs/lp8x4x_defconfig??????????????????| 176
> > ++++++++++++++
> > 
> 
> I had not noticed earlier that you are adding a new defconfig file.
> PXA is
> already the platform with the most defconfig files, and I'd rather
> like
> to see that reduced than increased.
> 
> Is there a chance you could merge this one with some of the existing
> files
> into one configuration that handles them all?

There are several board-specific devices on LP8x4x: custom FPGA, custom
UART, custom IRQ on FPGA, custom parallel bus for industrial IO. The
defconfig file could alert potential users to this fact. If this is not
a sufficient reason to have a defconfig file, it can be dropped.

I use the full .config anyway :)

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

* Re: [PATCH v5 2/2] arm: pxa27x: support for ICP DAS LP-8x4x w/ DT
  2015-12-15 16:42                     ` Sergei Ianovich
  (?)
@ 2015-12-15 17:02                       ` Arnd Bergmann
  -1 siblings, 0 replies; 700+ messages in thread
From: Arnd Bergmann @ 2015-12-15 17:02 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: linux-kernel, Daniel Mack, Robert Jarzmik, Rob Herring,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala, Russell King,
	Thierry Reding, Jonathan Cameron, Dmitry Torokhov, Philipp Zabel,
	Arnaud Ebalard, Kuninori Morimoto,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	moderated list:ARM PORT

On Tuesday 15 December 2015 19:42:07 Sergei Ianovich wrote:
> On Tue, 2015-12-15 at 17:32 +0100, Arnd Bergmann wrote:
> > On Tuesday 15 December 2015 19:27:50 Sergei Ianovich wrote:
> > >  .../devicetree/bindings/vendor-prefixes.txt        |   1 +
> > >  arch/arm/boot/dts/Makefile                         |   3 +
> > >  arch/arm/boot/dts/pxa27x-lp8x4x-i105.dts           |  50 ++++
> > >  arch/arm/boot/dts/pxa27x-lp8x4x.dts                | 259
> > > +++++++++++++++++++++
> > >  arch/arm/configs/lp8x4x_defconfig                  | 176
> > > ++++++++++++++
> > > 
> > 
> > I had not noticed earlier that you are adding a new defconfig file.
> > PXA is
> > already the platform with the most defconfig files, and I'd rather
> > like
> > to see that reduced than increased.
> > 
> > Is there a chance you could merge this one with some of the existing
> > files
> > into one configuration that handles them all?
> 
> There are several board-specific devices on LP8x4x: custom FPGA, custom
> UART, custom IRQ on FPGA, custom parallel bus for industrial IO. The
> defconfig file could alert potential users to this fact. If this is not
> a sufficient reason to have a defconfig file, it can be dropped.
> 
> I use the full .config anyway 

I would like those drivers to be enabled in some defconfig, so we get
compile-time coverage, but we generally stopped having one-config-per-board
files.

Maybe we can have a pxa_defconfig file that enables lots of boards
and then we remove the individual configs? We don't have to remove
them all at once, but it would make me very happy if we could at
least kill off some of the ones that are not used regularly.

	Arnd

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

* Re: [PATCH v5 2/2] arm: pxa27x: support for ICP DAS LP-8x4x w/ DT
@ 2015-12-15 17:02                       ` Arnd Bergmann
  0 siblings, 0 replies; 700+ messages in thread
From: Arnd Bergmann @ 2015-12-15 17:02 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: linux-kernel, Daniel Mack, Robert Jarzmik, Rob Herring,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala, Russell King,
	Thierry Reding, Jonathan Cameron, Dmitry Torokhov, Philipp Zabel,
	Arnaud Ebalard, Kuninori Morimoto,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	moderated list:ARM PORT

On Tuesday 15 December 2015 19:42:07 Sergei Ianovich wrote:
> On Tue, 2015-12-15 at 17:32 +0100, Arnd Bergmann wrote:
> > On Tuesday 15 December 2015 19:27:50 Sergei Ianovich wrote:
> > >  .../devicetree/bindings/vendor-prefixes.txt        |   1 +
> > >  arch/arm/boot/dts/Makefile                         |   3 +
> > >  arch/arm/boot/dts/pxa27x-lp8x4x-i105.dts           |  50 ++++
> > >  arch/arm/boot/dts/pxa27x-lp8x4x.dts                | 259
> > > +++++++++++++++++++++
> > >  arch/arm/configs/lp8x4x_defconfig                  | 176
> > > ++++++++++++++
> > > 
> > 
> > I had not noticed earlier that you are adding a new defconfig file.
> > PXA is
> > already the platform with the most defconfig files, and I'd rather
> > like
> > to see that reduced than increased.
> > 
> > Is there a chance you could merge this one with some of the existing
> > files
> > into one configuration that handles them all?
> 
> There are several board-specific devices on LP8x4x: custom FPGA, custom
> UART, custom IRQ on FPGA, custom parallel bus for industrial IO. The
> defconfig file could alert potential users to this fact. If this is not
> a sufficient reason to have a defconfig file, it can be dropped.
> 
> I use the full .config anyway 

I would like those drivers to be enabled in some defconfig, so we get
compile-time coverage, but we generally stopped having one-config-per-board
files.

Maybe we can have a pxa_defconfig file that enables lots of boards
and then we remove the individual configs? We don't have to remove
them all at once, but it would make me very happy if we could at
least kill off some of the ones that are not used regularly.

	Arnd

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

* [PATCH v5 2/2] arm: pxa27x: support for ICP DAS LP-8x4x w/ DT
@ 2015-12-15 17:02                       ` Arnd Bergmann
  0 siblings, 0 replies; 700+ messages in thread
From: Arnd Bergmann @ 2015-12-15 17:02 UTC (permalink / raw)
  To: linux-arm-kernel

On Tuesday 15 December 2015 19:42:07 Sergei Ianovich wrote:
> On Tue, 2015-12-15 at 17:32 +0100, Arnd Bergmann wrote:
> > On Tuesday 15 December 2015 19:27:50 Sergei Ianovich wrote:
> > >  .../devicetree/bindings/vendor-prefixes.txt        |   1 +
> > >  arch/arm/boot/dts/Makefile                         |   3 +
> > >  arch/arm/boot/dts/pxa27x-lp8x4x-i105.dts           |  50 ++++
> > >  arch/arm/boot/dts/pxa27x-lp8x4x.dts                | 259
> > > +++++++++++++++++++++
> > >  arch/arm/configs/lp8x4x_defconfig                  | 176
> > > ++++++++++++++
> > > 
> > 
> > I had not noticed earlier that you are adding a new defconfig file.
> > PXA is
> > already the platform with the most defconfig files, and I'd rather
> > like
> > to see that reduced than increased.
> > 
> > Is there a chance you could merge this one with some of the existing
> > files
> > into one configuration that handles them all?
> 
> There are several board-specific devices on LP8x4x: custom FPGA, custom
> UART, custom IRQ on FPGA, custom parallel bus for industrial IO. The
> defconfig file could alert potential users to this fact. If this is not
> a sufficient reason to have a defconfig file, it can be dropped.
> 
> I use the full .config anyway 

I would like those drivers to be enabled in some defconfig, so we get
compile-time coverage, but we generally stopped having one-config-per-board
files.

Maybe we can have a pxa_defconfig file that enables lots of boards
and then we remove the individual configs? We don't have to remove
them all at once, but it would make me very happy if we could at
least kill off some of the ones that are not used regularly.

	Arnd

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

* Re: [PATCH v5 2/2] arm: pxa27x: support for ICP DAS LP-8x4x w/ DT
  2015-12-15 17:02                       ` Arnd Bergmann
  (?)
@ 2015-12-15 17:24                         ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2015-12-15 17:24 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: linux-kernel, Daniel Mack, Robert Jarzmik, Rob Herring,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala, Russell King,
	Thierry Reding, Jonathan Cameron, Dmitry Torokhov, Philipp Zabel,
	Arnaud Ebalard, Kuninori Morimoto,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	moderated list:ARM PORT

On Tue, 2015-12-15 at 18:02 +0100, Arnd Bergmann wrote:
> On Tuesday 15 December 2015 19:42:07 Sergei Ianovich wrote:
> > There are several board-specific devices on LP8x4x: custom FPGA,
> > custom
> > UART, custom IRQ on FPGA, custom parallel bus for industrial IO. The
> > defconfig file could alert potential users to this fact. If this is
> > not
> > a sufficient reason to have a defconfig file, it can be dropped.
> > 
> > I use the full .config anyway 
> 
> I would like those drivers to be enabled in some defconfig, so we get
> compile-time coverage, but we generally stopped having one-config-per-
> board
> files.
> 
> Maybe we can have a pxa_defconfig file that enables lots of boards
> and then we remove the individual configs? We don't have to remove
> them all at once, but it would make me very happy if we could at
> least kill off some of the ones that are not used regularly.

lp8x4x seems to be the first pxa board which requires DT.

We can create pxa27x-dt_defconfig which selects:
1. PXA27X_DT
2. PXA_FB and 8250_PXA to enable console
3. MMC, MMC_PXA and EXT4_FS to enable boot from MMC
4. all optional pxa stuff as modules
5. all stuff on supported pxa boards as modules

If #5 is extended when support for new boards is added, it should be
possible to run any supported pxa27x board with pxa27x_defconfig.

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

* Re: [PATCH v5 2/2] arm: pxa27x: support for ICP DAS LP-8x4x w/ DT
@ 2015-12-15 17:24                         ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2015-12-15 17:24 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA, Daniel Mack, Robert Jarzmik,
	Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	Russell King, Thierry Reding, Jonathan Cameron, Dmitry Torokhov,
	Philipp Zabel, Arnaud Ebalard, Kuninori Morimoto,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	moderated list:ARM PORT

On Tue, 2015-12-15 at 18:02 +0100, Arnd Bergmann wrote:
> On Tuesday 15 December 2015 19:42:07 Sergei Ianovich wrote:
> > There are several board-specific devices on LP8x4x: custom FPGA,
> > custom
> > UART, custom IRQ on FPGA, custom parallel bus for industrial IO. The
> > defconfig file could alert potential users to this fact. If this is
> > not
> > a sufficient reason to have a defconfig file, it can be dropped.
> > 
> > I use the full .config anyway 
> 
> I would like those drivers to be enabled in some defconfig, so we get
> compile-time coverage, but we generally stopped having one-config-per-
> board
> files.
> 
> Maybe we can have a pxa_defconfig file that enables lots of boards
> and then we remove the individual configs? We don't have to remove
> them all at once, but it would make me very happy if we could at
> least kill off some of the ones that are not used regularly.

lp8x4x seems to be the first pxa board which requires DT.

We can create pxa27x-dt_defconfig which selects:
1. PXA27X_DT
2. PXA_FB and 8250_PXA to enable console
3. MMC, MMC_PXA and EXT4_FS to enable boot from MMC
4. all optional pxa stuff as modules
5. all stuff on supported pxa boards as modules

If #5 is extended when support for new boards is added, it should be
possible to run any supported pxa27x board with pxa27x_defconfig.
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH v5 2/2] arm: pxa27x: support for ICP DAS LP-8x4x w/ DT
@ 2015-12-15 17:24                         ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2015-12-15 17:24 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, 2015-12-15 at 18:02 +0100, Arnd Bergmann wrote:
> On Tuesday 15 December 2015 19:42:07 Sergei Ianovich wrote:
> > There are several board-specific devices on LP8x4x: custom FPGA,
> > custom
> > UART, custom IRQ on FPGA, custom parallel bus for industrial IO. The
> > defconfig file could alert potential users to this fact. If this is
> > not
> > a sufficient reason to have a defconfig file, it can be dropped.
> > 
> > I use the full .config anyway 
> 
> I would like those drivers to be enabled in some defconfig, so we get
> compile-time coverage, but we generally stopped having one-config-per-
> board
> files.
> 
> Maybe we can have a pxa_defconfig file that enables lots of boards
> and then we remove the individual configs? We don't have to remove
> them all at once, but it would make me very happy if we could at
> least kill off some of the ones that are not used regularly.

lp8x4x seems to be the first pxa board which requires DT.

We can create pxa27x-dt_defconfig which selects:
1. PXA27X_DT
2. PXA_FB and 8250_PXA to enable console
3. MMC, MMC_PXA and EXT4_FS to enable boot from MMC
4. all optional pxa stuff as modules
5. all stuff on supported pxa boards as modules

If #5 is extended when support for new boards is added, it should be
possible to run any supported pxa27x board with pxa27x_defconfig.

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

* Re: [PATCH v5 2/2] arm: pxa27x: support for ICP DAS LP-8x4x w/ DT
  2015-12-15 17:24                         ` Sergei Ianovich
  (?)
@ 2015-12-15 18:06                           ` Robert Jarzmik
  -1 siblings, 0 replies; 700+ messages in thread
From: Robert Jarzmik @ 2015-12-15 18:06 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: Arnd Bergmann, linux-kernel, Daniel Mack, Rob Herring,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala, Russell King,
	Thierry Reding, Jonathan Cameron, Dmitry Torokhov, Philipp Zabel,
	Arnaud Ebalard, Kuninori Morimoto,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	moderated list:ARM PORT

Sergei Ianovich <ynvich@gmail.com> writes:

> On Tue, 2015-12-15 at 18:02 +0100, Arnd Bergmann wrote:
>> On Tuesday 15 December 2015 19:42:07 Sergei Ianovich wrote:
>> > There are several board-specific devices on LP8x4x: custom FPGA,
>> > custom
>> > UART, custom IRQ on FPGA, custom parallel bus for industrial IO. The
>> > defconfig file could alert potential users to this fact. If this is
>> > not
>> > a sufficient reason to have a defconfig file, it can be dropped.
>> > 
>> > I use the full .config anyway 
>> 
>> I would like those drivers to be enabled in some defconfig, so we get
>> compile-time coverage, but we generally stopped having one-config-per-
>> board
>> files.
>> 
>> Maybe we can have a pxa_defconfig file that enables lots of boards
>> and then we remove the individual configs? We don't have to remove
>> them all at once, but it would make me very happy if we could at
>> least kill off some of the ones that are not used regularly.
Yeah, I'd be happy too, that would simplify also my life.

Actually I was thinking of 2 defconfigs :
 - one for platform_data based boards pxa2xx
 - one for DT only boards pxa2xx

> lp8x4x seems to be the first pxa board which requires DT.
Most probably AFAIK.

> We can create pxa27x-dt_defconfig which selects:
> 1. PXA27X_DT
> 2. PXA_FB and 8250_PXA to enable console
> 3. MMC, MMC_PXA and EXT4_FS to enable boot from MMC
If you put MMC_PXA, one can argue why not any MTD device used on pxa devices,
such as pxa2xx-flash or docg3/docg4, etc ... I won't argue, I'm just pondering
about the right choice.

> 4. all optional pxa stuff as modules
> 5. all stuff on supported pxa boards as modules

> If #5 is extended when support for new boards is added, it should be
> possible to run any supported pxa27x board with pxa27x_defconfig.

I'm very eager to see a patch on that. I can feed my Jenkins with it, it would
greatly help me catch issues earlier. Moreover it would for free test it on
lubbock, mainstone and mioa701. If there was one also for pxa3xx, I would launch
it on zylonite cm-x300 ... (that's a bonus, I know :))

Cheers.

-- 
Robert

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

* Re: [PATCH v5 2/2] arm: pxa27x: support for ICP DAS LP-8x4x w/ DT
@ 2015-12-15 18:06                           ` Robert Jarzmik
  0 siblings, 0 replies; 700+ messages in thread
From: Robert Jarzmik @ 2015-12-15 18:06 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: Arnd Bergmann, linux-kernel, Daniel Mack, Rob Herring,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala, Russell King,
	Thierry Reding, Jonathan Cameron, Dmitry Torokhov, Philipp Zabel,
	Arnaud Ebalard, Kuninori Morimoto,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	moderated list:ARM PORT

Sergei Ianovich <ynvich@gmail.com> writes:

> On Tue, 2015-12-15 at 18:02 +0100, Arnd Bergmann wrote:
>> On Tuesday 15 December 2015 19:42:07 Sergei Ianovich wrote:
>> > There are several board-specific devices on LP8x4x: custom FPGA,
>> > custom
>> > UART, custom IRQ on FPGA, custom parallel bus for industrial IO. The
>> > defconfig file could alert potential users to this fact. If this is
>> > not
>> > a sufficient reason to have a defconfig file, it can be dropped.
>> > 
>> > I use the full .config anyway 
>> 
>> I would like those drivers to be enabled in some defconfig, so we get
>> compile-time coverage, but we generally stopped having one-config-per-
>> board
>> files.
>> 
>> Maybe we can have a pxa_defconfig file that enables lots of boards
>> and then we remove the individual configs? We don't have to remove
>> them all at once, but it would make me very happy if we could at
>> least kill off some of the ones that are not used regularly.
Yeah, I'd be happy too, that would simplify also my life.

Actually I was thinking of 2 defconfigs :
 - one for platform_data based boards pxa2xx
 - one for DT only boards pxa2xx

> lp8x4x seems to be the first pxa board which requires DT.
Most probably AFAIK.

> We can create pxa27x-dt_defconfig which selects:
> 1. PXA27X_DT
> 2. PXA_FB and 8250_PXA to enable console
> 3. MMC, MMC_PXA and EXT4_FS to enable boot from MMC
If you put MMC_PXA, one can argue why not any MTD device used on pxa devices,
such as pxa2xx-flash or docg3/docg4, etc ... I won't argue, I'm just pondering
about the right choice.

> 4. all optional pxa stuff as modules
> 5. all stuff on supported pxa boards as modules

> If #5 is extended when support for new boards is added, it should be
> possible to run any supported pxa27x board with pxa27x_defconfig.

I'm very eager to see a patch on that. I can feed my Jenkins with it, it would
greatly help me catch issues earlier. Moreover it would for free test it on
lubbock, mainstone and mioa701. If there was one also for pxa3xx, I would launch
it on zylonite cm-x300 ... (that's a bonus, I know :))

Cheers.

-- 
Robert

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

* [PATCH v5 2/2] arm: pxa27x: support for ICP DAS LP-8x4x w/ DT
@ 2015-12-15 18:06                           ` Robert Jarzmik
  0 siblings, 0 replies; 700+ messages in thread
From: Robert Jarzmik @ 2015-12-15 18:06 UTC (permalink / raw)
  To: linux-arm-kernel

Sergei Ianovich <ynvich@gmail.com> writes:

> On Tue, 2015-12-15 at 18:02 +0100, Arnd Bergmann wrote:
>> On Tuesday 15 December 2015 19:42:07 Sergei Ianovich wrote:
>> > There are several board-specific devices on LP8x4x: custom FPGA,
>> > custom
>> > UART, custom IRQ on FPGA, custom parallel bus for industrial IO. The
>> > defconfig file could alert potential users to this fact. If this is
>> > not
>> > a sufficient reason to have a defconfig file, it can be dropped.
>> > 
>> > I use the full .config anyway 
>> 
>> I would like those drivers to be enabled in some defconfig, so we get
>> compile-time coverage, but we generally stopped having one-config-per-
>> board
>> files.
>> 
>> Maybe we can have a pxa_defconfig file that enables lots of boards
>> and then we remove the individual configs? We don't have to remove
>> them all at once, but it would make me very happy if we could at
>> least kill off some of the ones that are not used regularly.
Yeah, I'd be happy too, that would simplify also my life.

Actually I was thinking of 2 defconfigs :
 - one for platform_data based boards pxa2xx
 - one for DT only boards pxa2xx

> lp8x4x seems to be the first pxa board which requires DT.
Most probably AFAIK.

> We can create pxa27x-dt_defconfig which selects:
> 1. PXA27X_DT
> 2. PXA_FB and 8250_PXA to enable console
> 3. MMC, MMC_PXA and EXT4_FS to enable boot from MMC
If you put MMC_PXA, one can argue why not any MTD device used on pxa devices,
such as pxa2xx-flash or docg3/docg4, etc ... I won't argue, I'm just pondering
about the right choice.

> 4. all optional pxa stuff as modules
> 5. all stuff on supported pxa boards as modules

> If #5 is extended when support for new boards is added, it should be
> possible to run any supported pxa27x board with pxa27x_defconfig.

I'm very eager to see a patch on that. I can feed my Jenkins with it, it would
greatly help me catch issues earlier. Moreover it would for free test it on
lubbock, mainstone and mioa701. If there was one also for pxa3xx, I would launch
it on zylonite cm-x300 ... (that's a bonus, I know :))

Cheers.

-- 
Robert

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

* Re: [PATCH v5 2/2] arm: pxa27x: support for ICP DAS LP-8x4x w/ DT
  2015-12-15 18:06                           ` Robert Jarzmik
  (?)
@ 2015-12-15 18:50                             ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2015-12-15 18:50 UTC (permalink / raw)
  To: Robert Jarzmik
  Cc: Arnd Bergmann, linux-kernel, Daniel Mack, Rob Herring,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala, Russell King,
	Thierry Reding, Jonathan Cameron, Dmitry Torokhov, Philipp Zabel,
	Arnaud Ebalard, Kuninori Morimoto,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	moderated list:ARM PORT

On Tue, 2015-12-15 at 19:06 +0100, Robert Jarzmik wrote:
> 
> > > Maybe we can have a pxa_defconfig file that enables lots of boards
> > > and then we remove the individual configs? We don't have to remove
> > > them all at once, but it would make me very happy if we could at
> > > least kill off some of the ones that are not used regularly.
> Yeah, I'd be happy too, that would simplify also my life.
> 
> Actually I was thinking of 2 defconfigs :
>  - one for platform_data based boards pxa2xx
>  - one for DT only boards pxa2xx

I sincerely hope that dealing with ancient platform_data defconfigs is
out of the scope this patch.

> > lp8x4x seems to be the first pxa board which requires DT.
> Most probably AFAIK.
> 
> > We can create pxa27x-dt_defconfig which selects:
> > 1. PXA27X_DT
> > 2. PXA_FB and 8250_PXA to enable console
> > 3. MMC, MMC_PXA and EXT4_FS to enable boot from MMC
> If you put MMC_PXA, one can argue why not any MTD device used on pxa
> devices,
> such as pxa2xx-flash or docg3/docg4, etc ... I won't argue, I'm just
> pondering
> about the right choice.

Great point. We should enable MTD for sure. There is no PXA-specific MTD
drivers, however. That's why MTD failed the grep test.

> > 4. all optional pxa stuff as modules
> > 5. all stuff on supported pxa boards as modules
> 
> > If #5 is extended when support for new boards is added, it should be
> > possible to run any supported pxa27x board with pxa27x_defconfig.
> 
> I'm very eager to see a patch on that. I can feed my Jenkins with it,
> it would
> greatly help me catch issues earlier. Moreover it would for free test
> it on
> lubbock, mainstone and mioa701. If there was one also for pxa3xx, I
> would launch
> it on zylonite cm-x300 ... (that's a bonus, I know :))
> 

Updated plan:
1. MACH_PXA27X_DT
2. PXA_FB and 8250_PXA to enable console
3. MMC, MMC_PXA and EXT4_FS to enable boot from MMC
3.1. MTD, MTD_CFI, MTD_PHYSMAP_OF and JFFS2_FS to enable boot from MTD
4. all optional pxa stuff as modules
5. all stuff on supported pxa boards as modules
6. supported boards should boot the kernel built with
`pxa27x-dt_defconfig` after `make olddefconfig`

It is probably a good idea to put this plan somewhere in Documentation/
and to have a comment about that in the defconfig itself.

Is the plan acceptable?

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

* Re: [PATCH v5 2/2] arm: pxa27x: support for ICP DAS LP-8x4x w/ DT
@ 2015-12-15 18:50                             ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2015-12-15 18:50 UTC (permalink / raw)
  To: Robert Jarzmik
  Cc: Arnd Bergmann, linux-kernel, Daniel Mack, Rob Herring,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala, Russell King,
	Thierry Reding, Jonathan Cameron, Dmitry Torokhov, Philipp Zabel,
	Arnaud Ebalard, Kuninori Morimoto,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	moderated list:ARM PORT

On Tue, 2015-12-15 at 19:06 +0100, Robert Jarzmik wrote:
> 
> > > Maybe we can have a pxa_defconfig file that enables lots of boards
> > > and then we remove the individual configs? We don't have to remove
> > > them all at once, but it would make me very happy if we could at
> > > least kill off some of the ones that are not used regularly.
> Yeah, I'd be happy too, that would simplify also my life.
> 
> Actually I was thinking of 2 defconfigs :
>  - one for platform_data based boards pxa2xx
>  - one for DT only boards pxa2xx

I sincerely hope that dealing with ancient platform_data defconfigs is
out of the scope this patch.

> > lp8x4x seems to be the first pxa board which requires DT.
> Most probably AFAIK.
> 
> > We can create pxa27x-dt_defconfig which selects:
> > 1. PXA27X_DT
> > 2. PXA_FB and 8250_PXA to enable console
> > 3. MMC, MMC_PXA and EXT4_FS to enable boot from MMC
> If you put MMC_PXA, one can argue why not any MTD device used on pxa
> devices,
> such as pxa2xx-flash or docg3/docg4, etc ... I won't argue, I'm just
> pondering
> about the right choice.

Great point. We should enable MTD for sure. There is no PXA-specific MTD
drivers, however. That's why MTD failed the grep test.

> > 4. all optional pxa stuff as modules
> > 5. all stuff on supported pxa boards as modules
> 
> > If #5 is extended when support for new boards is added, it should be
> > possible to run any supported pxa27x board with pxa27x_defconfig.
> 
> I'm very eager to see a patch on that. I can feed my Jenkins with it,
> it would
> greatly help me catch issues earlier. Moreover it would for free test
> it on
> lubbock, mainstone and mioa701. If there was one also for pxa3xx, I
> would launch
> it on zylonite cm-x300 ... (that's a bonus, I know :))
> 

Updated plan:
1. MACH_PXA27X_DT
2. PXA_FB and 8250_PXA to enable console
3. MMC, MMC_PXA and EXT4_FS to enable boot from MMC
3.1. MTD, MTD_CFI, MTD_PHYSMAP_OF and JFFS2_FS to enable boot from MTD
4. all optional pxa stuff as modules
5. all stuff on supported pxa boards as modules
6. supported boards should boot the kernel built with
`pxa27x-dt_defconfig` after `make olddefconfig`

It is probably a good idea to put this plan somewhere in Documentation/
and to have a comment about that in the defconfig itself.

Is the plan acceptable?

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

* [PATCH v5 2/2] arm: pxa27x: support for ICP DAS LP-8x4x w/ DT
@ 2015-12-15 18:50                             ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2015-12-15 18:50 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, 2015-12-15 at 19:06 +0100, Robert Jarzmik wrote:
>?
> > > Maybe we can have a pxa_defconfig file that enables lots of boards
> > > and then we remove the individual configs? We don't have to remove
> > > them all at once, but it would make me very happy if we could at
> > > least kill off some of the ones that are not used regularly.
> Yeah, I'd be happy too, that would simplify also my life.
> 
> Actually I was thinking of 2 defconfigs :
> ?- one for platform_data based boards pxa2xx
> ?- one for DT only boards pxa2xx

I sincerely hope that dealing with ancient platform_data defconfigs is
out of the scope this patch.

> > lp8x4x seems to be the first pxa board which requires DT.
> Most probably AFAIK.
> 
> > We can create pxa27x-dt_defconfig which selects:
> > 1. PXA27X_DT
> > 2. PXA_FB and 8250_PXA to enable console
> > 3. MMC, MMC_PXA and EXT4_FS to enable boot from MMC
> If you put MMC_PXA, one can argue why not any MTD device used on pxa
> devices,
> such as pxa2xx-flash or docg3/docg4, etc ... I won't argue, I'm just
> pondering
> about the right choice.

Great point. We should enable MTD for sure. There is no PXA-specific MTD
drivers, however. That's why MTD failed the grep test.

> > 4. all optional pxa stuff as modules
> > 5. all stuff on supported pxa boards as modules
> 
> > If #5 is extended when support for new boards is added, it should be
> > possible to run any supported pxa27x board with pxa27x_defconfig.
> 
> I'm very eager to see a patch on that. I can feed my Jenkins with it,
> it would
> greatly help me catch issues earlier. Moreover it would for free test
> it on
> lubbock, mainstone and mioa701. If there was one also for pxa3xx, I
> would launch
> it on zylonite cm-x300 ... (that's a bonus, I know :))
> 

Updated plan:
1. MACH_PXA27X_DT
2. PXA_FB and 8250_PXA to enable console
3. MMC, MMC_PXA and EXT4_FS to enable boot from MMC
3.1. MTD, MTD_CFI, MTD_PHYSMAP_OF and JFFS2_FS to enable boot from MTD
4. all optional pxa stuff as modules
5. all stuff on supported pxa boards as modules
6. supported boards should boot the kernel built with
`pxa27x-dt_defconfig` after `make olddefconfig`

It is probably a good idea to put this plan somewhere in Documentation/
and to have a comment about that in the defconfig itself.

Is the plan acceptable?

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

* [PATCH v5] mtd: support BB SRAM on ICP DAS LP-8x4x
@ 2015-12-15 18:58                     ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2015-12-15 18:58 UTC (permalink / raw)
  To: linux-kernel
  Cc: Sergei Ianovich, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, David Woodhouse, Brian Norris,
	Jeremy Kerr, Cyril Bur, Neelesh Gupta, Michael Ellerman,
	Joel Stanley,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	open list:MEMORY TECHNOLOGY DEVICES (MTD)

This provides an MTD device driver for 512kB of battery backed up SRAM
on ICPDAS LP-8X4X programmable automation controllers.

SRAM chip is connected via FPGA and is not accessible without a driver,
unlike flash memory which is wired to CPU MMU.

This SRAM becomes an excellent persisent storage of volatile process
data like counter values and sensor statuses. Storing those data in
flash or mmc card is not a viable solution.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
Reviewed-by: Brian Norris <computersforpeace@gmail.com>
---
   v4..v5
   * remove .owner from struct platform_driver
   * constify struct of_device_id
    for further Brian Norris comments:
   * drop unused property from doc file
   * move defconfig update to a different file
   * drop extra match w/ of_match_device()

   v3..v4 for Brian Norris 'Reviewed-by'
   * add doc file for DT binding
   * move DTS binding to a different patch (8/21)
   * drop unused include directive
   * drop safely unused callback
   * drop non-default partion probe types
   * drop duplicate error checks
   * drop duplicate error reporting
   * fixed error message on MTD registeration
   * fixed module removal routine

   v2..v3
   * no changes (except number 08/16 -> 10/21)

   v0..v2
   * use device tree
   * use devm helpers where possible

 .../devicetree/bindings/mtd/sram-lp8x4x.txt        |  20 +++
 drivers/mtd/devices/Kconfig                        |  14 ++
 drivers/mtd/devices/Makefile                       |   1 +
 drivers/mtd/devices/sram_lp8x4x.c                  | 199 +++++++++++++++++++++
 4 files changed, 234 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mtd/sram-lp8x4x.txt
 create mode 100644 drivers/mtd/devices/sram_lp8x4x.c

diff --git a/Documentation/devicetree/bindings/mtd/sram-lp8x4x.txt b/Documentation/devicetree/bindings/mtd/sram-lp8x4x.txt
new file mode 100644
index 0000000..476934f
--- /dev/null
+++ b/Documentation/devicetree/bindings/mtd/sram-lp8x4x.txt
@@ -0,0 +1,20 @@
+512kB battery backed up SRAM on LP-8x4x industrial computers
+
+Required properties:
+- compatible : should be "icpdas,sram-lp8x4x"
+
+- reg: physical base addresses and region lengths of
+       * IO memory range
+       * SRAM page selector
+
+SRAM chip is connected via FPGA and is not accessible without a driver,
+unlike flash memory which is wired to CPU MMU. Driver is essentially
+an address translation routine.
+
+Example:
+
+	sram@a000 {
+		compatible = "icpdas,sram-lp8x4x";
+		reg = <0xa000 0x1000
+		       0x901e 0x1>;
+	};
diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig
index f73c416..a4573f6 100644
--- a/drivers/mtd/devices/Kconfig
+++ b/drivers/mtd/devices/Kconfig
@@ -233,4 +233,18 @@ config BCH_CONST_T
 	default 4
 endif
 
+config MTD_SRAM_LP8X4X
+	tristate "SRAM on ICPDAS LP-8X4X"
+	depends on OF && ARCH_PXA
+       ---help---
+	 This provides an MTD device driver for 512kiB of battery backed up SRAM
+	 on ICPDAS LP-8X4X programmable automation controllers.
+
+	 SRAM chip is connected via FPGA and is not accessible without a driver,
+	 unlike flash memory which is wired to CPU MMU.
+
+	 Say N, unless you plan to run this kernel on LP-8X4X.
+
+	 If you say M, the module will be called sram_lp8x4x.
+
 endmenu
diff --git a/drivers/mtd/devices/Makefile b/drivers/mtd/devices/Makefile
index 7912d3a..2fd5b7a 100644
--- a/drivers/mtd/devices/Makefile
+++ b/drivers/mtd/devices/Makefile
@@ -17,6 +17,7 @@ obj-$(CONFIG_MTD_SST25L)	+= sst25l.o
 obj-$(CONFIG_MTD_BCM47XXSFLASH)	+= bcm47xxsflash.o
 obj-$(CONFIG_MTD_ST_SPI_FSM)    += st_spi_fsm.o
 obj-$(CONFIG_MTD_POWERNV_FLASH)	+= powernv_flash.o
+obj-$(CONFIG_MTD_SRAM_LP8X4X)	+= sram_lp8x4x.o
 
 
 CFLAGS_docg3.o			+= -I$(src)
diff --git a/drivers/mtd/devices/sram_lp8x4x.c b/drivers/mtd/devices/sram_lp8x4x.c
new file mode 100644
index 0000000..e43c7a7
--- /dev/null
+++ b/drivers/mtd/devices/sram_lp8x4x.c
@@ -0,0 +1,199 @@
+/*
+ *  linux/drivers/mtd/devices/lp8x4x_sram.c
+ *
+ *  MTD Driver for SRAM on ICPDAS LP-8x4x
+ *  Copyright (C) 2013 Sergei Ianovich <ynvich@gmail.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation or any later version.
+ */
+
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mtd/map.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/platform_device.h>
+#include <linux/of_device.h>
+#include <linux/slab.h>
+#include <linux/string_helpers.h>
+#include <linux/types.h>
+
+struct lp8x4x_sram_info {
+	void __iomem	*bank;
+	void __iomem	*virt;
+	struct mutex	lock;
+	unsigned	active_bank;
+	struct mtd_info	mtd;
+};
+
+static int
+lp8x4x_sram_erase(struct mtd_info *mtd, struct erase_info *instr)
+{
+	struct lp8x4x_sram_info *info = mtd->priv;
+	unsigned bank = instr->addr >> 11;
+	unsigned offset = (instr->addr & 0x7ff) << 1;
+	loff_t i;
+
+	mutex_lock(&info->lock);
+	if (unlikely(bank != info->active_bank)) {
+		info->active_bank = bank;
+		iowrite8(bank, info->bank);
+	}
+	for (i = 0; i < instr->len; i++) {
+		iowrite8(0xff, info->virt + offset);
+		offset += 2;
+		if (unlikely(offset == 0)) {
+			info->active_bank++;
+			iowrite8(info->active_bank, info->bank);
+		}
+	}
+	mutex_unlock(&info->lock);
+	instr->state = MTD_ERASE_DONE;
+	mtd_erase_callback(instr);
+
+	return 0;
+}
+
+static int
+lp8x4x_sram_write(struct mtd_info *mtd, loff_t to, size_t len,
+		size_t *retlen, const u_char *b)
+{
+	struct lp8x4x_sram_info *info = mtd->priv;
+	unsigned bank = to >> 11;
+	unsigned offset = (to & 0x7ff) << 1;
+	loff_t i;
+
+	mutex_lock(&info->lock);
+	if (unlikely(bank != info->active_bank)) {
+		info->active_bank = bank;
+		iowrite8(bank, info->bank);
+	}
+	for (i = 0; i < len; i++) {
+		iowrite8(b[i], info->virt + offset);
+		offset += 2;
+		if (unlikely(offset == 0)) {
+			info->active_bank++;
+			iowrite8(info->active_bank, info->bank);
+		}
+	}
+	mutex_unlock(&info->lock);
+	*retlen = len;
+	return 0;
+}
+
+static int
+lp8x4x_sram_read(struct mtd_info *mtd, loff_t from, size_t len,
+		size_t *retlen, u_char *b)
+{
+	struct lp8x4x_sram_info *info = mtd->priv;
+	unsigned bank = from >> 11;
+	unsigned offset = (from & 0x7ff) << 1;
+	loff_t i;
+
+	mutex_lock(&info->lock);
+	if (unlikely(bank != info->active_bank)) {
+		info->active_bank = bank;
+		iowrite8(bank, info->bank);
+	}
+	for (i = 0; i < len; i++) {
+		b[i] = ioread8(info->virt + offset);
+		offset += 2;
+		if (unlikely(offset == 0)) {
+			info->active_bank++;
+			iowrite8(info->active_bank, info->bank);
+		}
+	}
+	mutex_unlock(&info->lock);
+	*retlen = len;
+	return 0;
+}
+
+static const struct of_device_id of_flash_match[] = {
+	{
+		.compatible	= "icpdas,sram-lp8x4x",
+	},
+	{ },
+};
+MODULE_DEVICE_TABLE(of, of_flash_match);
+
+static int
+lp8x4x_sram_probe(struct platform_device *pdev)
+{
+	struct lp8x4x_sram_info *info;
+	struct resource *res_virt, *res_bank;
+	char sz_str[16];
+	struct mtd_part_parser_data ppdata;
+	int err = 0;
+
+	info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
+	if (!info)
+		return -ENOMEM;
+
+	res_virt = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	info->virt =  devm_ioremap_resource(&pdev->dev, res_virt);
+	if (IS_ERR(info->virt))
+		return PTR_ERR(info->virt);
+
+	res_bank = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	info->bank = devm_ioremap_resource(&pdev->dev, res_bank);
+	if (IS_ERR(info->bank))
+		return PTR_ERR(info->bank);
+
+	info->mtd.priv = info;
+	info->mtd.name = "SRAM";
+	info->mtd.type = MTD_RAM;
+	info->mtd.flags = MTD_CAP_RAM;
+	info->mtd.size = resource_size(res_virt) << 7;
+	info->mtd.erasesize = 512;
+	info->mtd.writesize = 4;
+	info->mtd._erase = lp8x4x_sram_erase;
+	info->mtd._write = lp8x4x_sram_write;
+	info->mtd._read = lp8x4x_sram_read;
+	info->mtd.owner = THIS_MODULE;
+
+	mutex_init(&info->lock);
+	iowrite8(info->active_bank, info->bank);
+	platform_set_drvdata(pdev, info);
+
+	ppdata.of_node = pdev->dev.of_node;
+	err = mtd_device_parse_register(&info->mtd, NULL, &ppdata,
+			NULL, 0);
+
+	if (err < 0) {
+		dev_err(&pdev->dev, "failed to register MTD\n");
+		return err;
+	}
+
+	string_get_size(info->mtd.size, 1, STRING_UNITS_2, sz_str,
+			sizeof(sz_str));
+	dev_info(&pdev->dev, "using %s SRAM on LP-8X4X as %s\n", sz_str,
+			dev_name(&info->mtd.dev));
+	return 0;
+}
+
+static int
+lp8x4x_sram_remove(struct platform_device *dev)
+{
+	struct lp8x4x_sram_info *info = platform_get_drvdata(dev);
+
+	return mtd_device_unregister(&info->mtd);
+}
+
+static struct platform_driver lp8x4x_sram_driver = {
+	.driver = {
+		.name		= "sram-lp8x4x",
+		.of_match_table = of_flash_match,
+	},
+	.probe		= lp8x4x_sram_probe,
+	.remove		= lp8x4x_sram_remove,
+};
+
+module_platform_driver(lp8x4x_sram_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Sergei Ianovich <ynvich@gmail.com>");
+MODULE_DESCRIPTION("MTD driver for SRAM on ICPDAS LP-8x4x");
-- 
2.6.2


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

* [PATCH v5] mtd: support BB SRAM on ICP DAS LP-8x4x
@ 2015-12-15 18:58                     ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2015-12-15 18:58 UTC (permalink / raw)
  To: linux-kernel-u79uwXL29TY76Z2rM5mHXA
  Cc: Sergei Ianovich, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, David Woodhouse, Brian Norris,
	Jeremy Kerr, Cyril Bur, Neelesh Gupta, Michael Ellerman,
	Joel Stanley,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	open list:MEMORY TECHNOLOGY DEVICES MTD

This provides an MTD device driver for 512kB of battery backed up SRAM
on ICPDAS LP-8X4X programmable automation controllers.

SRAM chip is connected via FPGA and is not accessible without a driver,
unlike flash memory which is wired to CPU MMU.

This SRAM becomes an excellent persisent storage of volatile process
data like counter values and sensor statuses. Storing those data in
flash or mmc card is not a viable solution.

Signed-off-by: Sergei Ianovich <ynvich-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Reviewed-by: Brian Norris <computersforpeace-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
---
   v4..v5
   * remove .owner from struct platform_driver
   * constify struct of_device_id
    for further Brian Norris comments:
   * drop unused property from doc file
   * move defconfig update to a different file
   * drop extra match w/ of_match_device()

   v3..v4 for Brian Norris 'Reviewed-by'
   * add doc file for DT binding
   * move DTS binding to a different patch (8/21)
   * drop unused include directive
   * drop safely unused callback
   * drop non-default partion probe types
   * drop duplicate error checks
   * drop duplicate error reporting
   * fixed error message on MTD registeration
   * fixed module removal routine

   v2..v3
   * no changes (except number 08/16 -> 10/21)

   v0..v2
   * use device tree
   * use devm helpers where possible

 .../devicetree/bindings/mtd/sram-lp8x4x.txt        |  20 +++
 drivers/mtd/devices/Kconfig                        |  14 ++
 drivers/mtd/devices/Makefile                       |   1 +
 drivers/mtd/devices/sram_lp8x4x.c                  | 199 +++++++++++++++++++++
 4 files changed, 234 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mtd/sram-lp8x4x.txt
 create mode 100644 drivers/mtd/devices/sram_lp8x4x.c

diff --git a/Documentation/devicetree/bindings/mtd/sram-lp8x4x.txt b/Documentation/devicetree/bindings/mtd/sram-lp8x4x.txt
new file mode 100644
index 0000000..476934f
--- /dev/null
+++ b/Documentation/devicetree/bindings/mtd/sram-lp8x4x.txt
@@ -0,0 +1,20 @@
+512kB battery backed up SRAM on LP-8x4x industrial computers
+
+Required properties:
+- compatible : should be "icpdas,sram-lp8x4x"
+
+- reg: physical base addresses and region lengths of
+       * IO memory range
+       * SRAM page selector
+
+SRAM chip is connected via FPGA and is not accessible without a driver,
+unlike flash memory which is wired to CPU MMU. Driver is essentially
+an address translation routine.
+
+Example:
+
+	sram@a000 {
+		compatible = "icpdas,sram-lp8x4x";
+		reg = <0xa000 0x1000
+		       0x901e 0x1>;
+	};
diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig
index f73c416..a4573f6 100644
--- a/drivers/mtd/devices/Kconfig
+++ b/drivers/mtd/devices/Kconfig
@@ -233,4 +233,18 @@ config BCH_CONST_T
 	default 4
 endif
 
+config MTD_SRAM_LP8X4X
+	tristate "SRAM on ICPDAS LP-8X4X"
+	depends on OF && ARCH_PXA
+       ---help---
+	 This provides an MTD device driver for 512kiB of battery backed up SRAM
+	 on ICPDAS LP-8X4X programmable automation controllers.
+
+	 SRAM chip is connected via FPGA and is not accessible without a driver,
+	 unlike flash memory which is wired to CPU MMU.
+
+	 Say N, unless you plan to run this kernel on LP-8X4X.
+
+	 If you say M, the module will be called sram_lp8x4x.
+
 endmenu
diff --git a/drivers/mtd/devices/Makefile b/drivers/mtd/devices/Makefile
index 7912d3a..2fd5b7a 100644
--- a/drivers/mtd/devices/Makefile
+++ b/drivers/mtd/devices/Makefile
@@ -17,6 +17,7 @@ obj-$(CONFIG_MTD_SST25L)	+= sst25l.o
 obj-$(CONFIG_MTD_BCM47XXSFLASH)	+= bcm47xxsflash.o
 obj-$(CONFIG_MTD_ST_SPI_FSM)    += st_spi_fsm.o
 obj-$(CONFIG_MTD_POWERNV_FLASH)	+= powernv_flash.o
+obj-$(CONFIG_MTD_SRAM_LP8X4X)	+= sram_lp8x4x.o
 
 
 CFLAGS_docg3.o			+= -I$(src)
diff --git a/drivers/mtd/devices/sram_lp8x4x.c b/drivers/mtd/devices/sram_lp8x4x.c
new file mode 100644
index 0000000..e43c7a7
--- /dev/null
+++ b/drivers/mtd/devices/sram_lp8x4x.c
@@ -0,0 +1,199 @@
+/*
+ *  linux/drivers/mtd/devices/lp8x4x_sram.c
+ *
+ *  MTD Driver for SRAM on ICPDAS LP-8x4x
+ *  Copyright (C) 2013 Sergei Ianovich <ynvich-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation or any later version.
+ */
+
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mtd/map.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/platform_device.h>
+#include <linux/of_device.h>
+#include <linux/slab.h>
+#include <linux/string_helpers.h>
+#include <linux/types.h>
+
+struct lp8x4x_sram_info {
+	void __iomem	*bank;
+	void __iomem	*virt;
+	struct mutex	lock;
+	unsigned	active_bank;
+	struct mtd_info	mtd;
+};
+
+static int
+lp8x4x_sram_erase(struct mtd_info *mtd, struct erase_info *instr)
+{
+	struct lp8x4x_sram_info *info = mtd->priv;
+	unsigned bank = instr->addr >> 11;
+	unsigned offset = (instr->addr & 0x7ff) << 1;
+	loff_t i;
+
+	mutex_lock(&info->lock);
+	if (unlikely(bank != info->active_bank)) {
+		info->active_bank = bank;
+		iowrite8(bank, info->bank);
+	}
+	for (i = 0; i < instr->len; i++) {
+		iowrite8(0xff, info->virt + offset);
+		offset += 2;
+		if (unlikely(offset == 0)) {
+			info->active_bank++;
+			iowrite8(info->active_bank, info->bank);
+		}
+	}
+	mutex_unlock(&info->lock);
+	instr->state = MTD_ERASE_DONE;
+	mtd_erase_callback(instr);
+
+	return 0;
+}
+
+static int
+lp8x4x_sram_write(struct mtd_info *mtd, loff_t to, size_t len,
+		size_t *retlen, const u_char *b)
+{
+	struct lp8x4x_sram_info *info = mtd->priv;
+	unsigned bank = to >> 11;
+	unsigned offset = (to & 0x7ff) << 1;
+	loff_t i;
+
+	mutex_lock(&info->lock);
+	if (unlikely(bank != info->active_bank)) {
+		info->active_bank = bank;
+		iowrite8(bank, info->bank);
+	}
+	for (i = 0; i < len; i++) {
+		iowrite8(b[i], info->virt + offset);
+		offset += 2;
+		if (unlikely(offset == 0)) {
+			info->active_bank++;
+			iowrite8(info->active_bank, info->bank);
+		}
+	}
+	mutex_unlock(&info->lock);
+	*retlen = len;
+	return 0;
+}
+
+static int
+lp8x4x_sram_read(struct mtd_info *mtd, loff_t from, size_t len,
+		size_t *retlen, u_char *b)
+{
+	struct lp8x4x_sram_info *info = mtd->priv;
+	unsigned bank = from >> 11;
+	unsigned offset = (from & 0x7ff) << 1;
+	loff_t i;
+
+	mutex_lock(&info->lock);
+	if (unlikely(bank != info->active_bank)) {
+		info->active_bank = bank;
+		iowrite8(bank, info->bank);
+	}
+	for (i = 0; i < len; i++) {
+		b[i] = ioread8(info->virt + offset);
+		offset += 2;
+		if (unlikely(offset == 0)) {
+			info->active_bank++;
+			iowrite8(info->active_bank, info->bank);
+		}
+	}
+	mutex_unlock(&info->lock);
+	*retlen = len;
+	return 0;
+}
+
+static const struct of_device_id of_flash_match[] = {
+	{
+		.compatible	= "icpdas,sram-lp8x4x",
+	},
+	{ },
+};
+MODULE_DEVICE_TABLE(of, of_flash_match);
+
+static int
+lp8x4x_sram_probe(struct platform_device *pdev)
+{
+	struct lp8x4x_sram_info *info;
+	struct resource *res_virt, *res_bank;
+	char sz_str[16];
+	struct mtd_part_parser_data ppdata;
+	int err = 0;
+
+	info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
+	if (!info)
+		return -ENOMEM;
+
+	res_virt = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	info->virt =  devm_ioremap_resource(&pdev->dev, res_virt);
+	if (IS_ERR(info->virt))
+		return PTR_ERR(info->virt);
+
+	res_bank = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	info->bank = devm_ioremap_resource(&pdev->dev, res_bank);
+	if (IS_ERR(info->bank))
+		return PTR_ERR(info->bank);
+
+	info->mtd.priv = info;
+	info->mtd.name = "SRAM";
+	info->mtd.type = MTD_RAM;
+	info->mtd.flags = MTD_CAP_RAM;
+	info->mtd.size = resource_size(res_virt) << 7;
+	info->mtd.erasesize = 512;
+	info->mtd.writesize = 4;
+	info->mtd._erase = lp8x4x_sram_erase;
+	info->mtd._write = lp8x4x_sram_write;
+	info->mtd._read = lp8x4x_sram_read;
+	info->mtd.owner = THIS_MODULE;
+
+	mutex_init(&info->lock);
+	iowrite8(info->active_bank, info->bank);
+	platform_set_drvdata(pdev, info);
+
+	ppdata.of_node = pdev->dev.of_node;
+	err = mtd_device_parse_register(&info->mtd, NULL, &ppdata,
+			NULL, 0);
+
+	if (err < 0) {
+		dev_err(&pdev->dev, "failed to register MTD\n");
+		return err;
+	}
+
+	string_get_size(info->mtd.size, 1, STRING_UNITS_2, sz_str,
+			sizeof(sz_str));
+	dev_info(&pdev->dev, "using %s SRAM on LP-8X4X as %s\n", sz_str,
+			dev_name(&info->mtd.dev));
+	return 0;
+}
+
+static int
+lp8x4x_sram_remove(struct platform_device *dev)
+{
+	struct lp8x4x_sram_info *info = platform_get_drvdata(dev);
+
+	return mtd_device_unregister(&info->mtd);
+}
+
+static struct platform_driver lp8x4x_sram_driver = {
+	.driver = {
+		.name		= "sram-lp8x4x",
+		.of_match_table = of_flash_match,
+	},
+	.probe		= lp8x4x_sram_probe,
+	.remove		= lp8x4x_sram_remove,
+};
+
+module_platform_driver(lp8x4x_sram_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Sergei Ianovich <ynvich-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>");
+MODULE_DESCRIPTION("MTD driver for SRAM on ICPDAS LP-8x4x");
-- 
2.6.2

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH v5 2/2] arm: pxa27x: support for ICP DAS LP-8x4x w/ DT
@ 2015-12-15 19:21                               ` Arnd Bergmann
  0 siblings, 0 replies; 700+ messages in thread
From: Arnd Bergmann @ 2015-12-15 19:21 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: Robert Jarzmik, linux-kernel, Daniel Mack, Rob Herring,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala, Russell King,
	Thierry Reding, Jonathan Cameron, Dmitry Torokhov, Philipp Zabel,
	Arnaud Ebalard, Kuninori Morimoto,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	moderated list:ARM PORT

On Tuesday 15 December 2015 21:50:13 Sergei Ianovich wrote:
> On Tue, 2015-12-15 at 19:06 +0100, Robert Jarzmik wrote:


> > > 4. all optional pxa stuff as modules
> > > 5. all stuff on supported pxa boards as modules
> > 
> > > If #5 is extended when support for new boards is added, it should be
> > > possible to run any supported pxa27x board with pxa27x_defconfig.
> > 
> > I'm very eager to see a patch on that. I can feed my Jenkins with it,
> > it would
> > greatly help me catch issues earlier. Moreover it would for free test
> > it on
> > lubbock, mainstone and mioa701. If there was one also for pxa3xx, I
> > would launch
> > it on zylonite cm-x300 ... (that's a bonus, I know :))
> > 
> 
> Updated plan:
> 1. MACH_PXA27X_DT
> 2. PXA_FB and 8250_PXA to enable console
> 3. MMC, MMC_PXA and EXT4_FS to enable boot from MMC
> 3.1. MTD, MTD_CFI, MTD_PHYSMAP_OF and JFFS2_FS to enable boot from MTD
> 4. all optional pxa stuff as modules
> 5. all stuff on supported pxa boards as modules
> 6. supported boards should boot the kernel built with
> `pxa27x-dt_defconfig` after `make olddefconfig`
> 
> It is probably a good idea to put this plan somewhere in Documentation/
> and to have a comment about that in the defconfig itself.
> 
> Is the plan acceptable?

Sounds good to me.

	Arnd

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

* Re: [PATCH v5 2/2] arm: pxa27x: support for ICP DAS LP-8x4x w/ DT
@ 2015-12-15 19:21                               ` Arnd Bergmann
  0 siblings, 0 replies; 700+ messages in thread
From: Arnd Bergmann @ 2015-12-15 19:21 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: Robert Jarzmik, linux-kernel-u79uwXL29TY76Z2rM5mHXA, Daniel Mack,
	Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	Russell King, Thierry Reding, Jonathan Cameron, Dmitry Torokhov,
	Philipp Zabel, Arnaud Ebalard, Kuninori Morimoto,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	moderated list:ARM PORT

On Tuesday 15 December 2015 21:50:13 Sergei Ianovich wrote:
> On Tue, 2015-12-15 at 19:06 +0100, Robert Jarzmik wrote:


> > > 4. all optional pxa stuff as modules
> > > 5. all stuff on supported pxa boards as modules
> > 
> > > If #5 is extended when support for new boards is added, it should be
> > > possible to run any supported pxa27x board with pxa27x_defconfig.
> > 
> > I'm very eager to see a patch on that. I can feed my Jenkins with it,
> > it would
> > greatly help me catch issues earlier. Moreover it would for free test
> > it on
> > lubbock, mainstone and mioa701. If there was one also for pxa3xx, I
> > would launch
> > it on zylonite cm-x300 ... (that's a bonus, I know :))
> > 
> 
> Updated plan:
> 1. MACH_PXA27X_DT
> 2. PXA_FB and 8250_PXA to enable console
> 3. MMC, MMC_PXA and EXT4_FS to enable boot from MMC
> 3.1. MTD, MTD_CFI, MTD_PHYSMAP_OF and JFFS2_FS to enable boot from MTD
> 4. all optional pxa stuff as modules
> 5. all stuff on supported pxa boards as modules
> 6. supported boards should boot the kernel built with
> `pxa27x-dt_defconfig` after `make olddefconfig`
> 
> It is probably a good idea to put this plan somewhere in Documentation/
> and to have a comment about that in the defconfig itself.
> 
> Is the plan acceptable?

Sounds good to me.

	Arnd
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH v5 2/2] arm: pxa27x: support for ICP DAS LP-8x4x w/ DT
@ 2015-12-15 19:21                               ` Arnd Bergmann
  0 siblings, 0 replies; 700+ messages in thread
From: Arnd Bergmann @ 2015-12-15 19:21 UTC (permalink / raw)
  To: linux-arm-kernel

On Tuesday 15 December 2015 21:50:13 Sergei Ianovich wrote:
> On Tue, 2015-12-15 at 19:06 +0100, Robert Jarzmik wrote:


> > > 4. all optional pxa stuff as modules
> > > 5. all stuff on supported pxa boards as modules
> > 
> > > If #5 is extended when support for new boards is added, it should be
> > > possible to run any supported pxa27x board with pxa27x_defconfig.
> > 
> > I'm very eager to see a patch on that. I can feed my Jenkins with it,
> > it would
> > greatly help me catch issues earlier. Moreover it would for free test
> > it on
> > lubbock, mainstone and mioa701. If there was one also for pxa3xx, I
> > would launch
> > it on zylonite cm-x300 ... (that's a bonus, I know :))
> > 
> 
> Updated plan:
> 1. MACH_PXA27X_DT
> 2. PXA_FB and 8250_PXA to enable console
> 3. MMC, MMC_PXA and EXT4_FS to enable boot from MMC
> 3.1. MTD, MTD_CFI, MTD_PHYSMAP_OF and JFFS2_FS to enable boot from MTD
> 4. all optional pxa stuff as modules
> 5. all stuff on supported pxa boards as modules
> 6. supported boards should boot the kernel built with
> `pxa27x-dt_defconfig` after `make olddefconfig`
> 
> It is probably a good idea to put this plan somewhere in Documentation/
> and to have a comment about that in the defconfig itself.
> 
> Is the plan acceptable?

Sounds good to me.

	Arnd

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

* [PATCH v5] arm: pxa: support ICP DAS LP-8x4x FPGA irq
@ 2015-12-15 19:26                     ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2015-12-15 19:26 UTC (permalink / raw)
  To: linux-kernel
  Cc: Linus Walleij, Sergei Ianovich, Arnd Bergmann, Thomas Gleixner,
	Jason Cooper, Marc Zyngier, Rob Herring, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS

ICP DAS LP-8x4x contains FPGA chip. The chip functions as an interrupt
source providing 16 additional interrupts among other things. The
interrupt lines are muxed to a GPIO pin of a 2nd level PXA-GPIO
interrupt controller. GPIO pins of the 2nd level controller are in turn
muxed to a CPU interrupt line.

Until pxa is completely converted to device tree, it is impossible
to use IRQCHIP_DECLARE() and the irqdomain needs to added manually.
Drivers for the on-CPU IRQs and GPIO-IRQs are loaded using
postcore_initcall(). We need to have all irq domain drivers loaded prior
to DT parsing in order to allow normal initialization of IRQ resources
with DT.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
CC: Arnd Bergmann <arnd@arndb.de>
---
   v4..v5
   * constify struct of_device_id
   * drop irq number from handler signature

   v3.2..v4
   * move DTS binding to a different patch (8/21)

   v3.1..v3.2
   fixes to apply Linus Walleij's "Reviewed-by":
   * add kerneldoc comment for state container struct
   * rename irq -> hwirq for clarity
   * drop overzealous error checks from the hotpaths

   v3..v3.1
   fixes according to Linus Walleij review comments:
   * update commit message
   * use state container instead of global variables
   * get hardware irq nums from irq_data, don't calculate them
   * use BIT() macro
   * add defines for system irq register masks
   * replace cycle control variable with break
   * use better names for resource variables
   * add a linear domain instead of a legacy one
   * use irq_create_mapping() instead of irq_alloc_desc()

   v2..v3
   * no changes (except number 09/16 -> 11/21)

   v0..v2
   * extract irqchip and move to drivers/irqchip/
   * use device tree
   * use devm helpers where possible

 .../bindings/interrupt-controller/irq-lp8x4x.txt   |  49 +++++
 drivers/irqchip/Kconfig                            |   5 +
 drivers/irqchip/Makefile                           |   1 +
 drivers/irqchip/irq-lp8x4x.c                       | 227 +++++++++++++++++++++
 4 files changed, 282 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/interrupt-controller/irq-lp8x4x.txt
 create mode 100644 drivers/irqchip/irq-lp8x4x.c

diff --git a/Documentation/devicetree/bindings/interrupt-controller/irq-lp8x4x.txt b/Documentation/devicetree/bindings/interrupt-controller/irq-lp8x4x.txt
new file mode 100644
index 0000000..c8940d2
--- /dev/null
+++ b/Documentation/devicetree/bindings/interrupt-controller/irq-lp8x4x.txt
@@ -0,0 +1,49 @@
+ICP DAS LP-8x4x FPGA Interrupt Controller
+
+ICP DAS LP-8x4x contains FPGA chip. The chip functions as a interrupt
+source providing 16 additional interrupts among other things.
+
+Required properties:
+- compatible : should be "icpdas,irq-lp8x4x"
+
+- reg: physical base address of the controller and length of memory mapped
+  region.
+
+- interrupt-controller : identifies the node as an interrupt controller
+
+- #interrupt-cells : should be 1
+
+- interrupts : should provide interrupt
+
+- interrupt-parent : should provide a link to interrupt controller either
+		     explicitly and implicitly from a parent node
+
+Example:
+
+	fpga: fpga@17000006 {
+		compatible = "icpdas,irq-lp8x4x";
+		reg = <0x17000006 0x16>;
+		interrupt-parent = <&gpio>;
+		interrupts = <3 IRQ_TYPE_EDGE_RISING>;
+		#interrupt-cells = <1>;
+		interrupt-controller;
+		status = "okay";
+	};
+
+	uart@17009050 {
+		compatible = "icpdas,uart-lp8x4x";
+		reg = <0x17009050 0x10
+		       0x17009030 0x02>;
+		interrupt-parent = <&fpga>;
+		interrupts = <13>;
+		status = "okay";
+	};
+
+	uart@17009060 {
+		compatible = "icpdas,uart-lp8x4x";
+		reg = <0x17009060 0x10
+		       0x17009032 0x02>;
+		interrupt-parent = <&fpga>;
+		interrupts = <14>;
+		status = "okay";
+	};
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index 4d7294e..1de7361 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -193,3 +193,8 @@ config IRQ_MXS
 	def_bool y if MACH_ASM9260 || ARCH_MXS
 	select IRQ_DOMAIN
 	select STMP_DEVICE
+
+config LP8X4X_IRQ
+	bool
+	depends on OF && ARCH_PXA
+	select IRQ_DOMAIN
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index 177f78f..ab9ca67 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -55,3 +55,4 @@ obj-$(CONFIG_RENESAS_H8S_INTC)		+= irq-renesas-h8s.o
 obj-$(CONFIG_ARCH_SA1100)		+= irq-sa11x0.o
 obj-$(CONFIG_INGENIC_IRQ)		+= irq-ingenic.o
 obj-$(CONFIG_IMX_GPCV2)			+= irq-imx-gpcv2.o
+obj-$(CONFIG_LP8X4X_IRQ)		+= irq-lp8x4x.o
diff --git a/drivers/irqchip/irq-lp8x4x.c b/drivers/irqchip/irq-lp8x4x.c
new file mode 100644
index 0000000..a03d925
--- /dev/null
+++ b/drivers/irqchip/irq-lp8x4x.c
@@ -0,0 +1,227 @@
+/*
+ *  linux/drivers/irqchip/irq-lp8x4x.c
+ *
+ *  Support for ICP DAS LP-8x4x FPGA irq
+ *  Copyright (C) 2013 Sergei Ianovich <ynvich@gmail.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation or any later version.
+ */
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/irqchip/chained_irq.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+#define EOI			0x00000000
+#define INSINT			0x00000002
+#define ENSYSINT		0x00000004
+#define PRIMINT			0x00000006
+#define PRIMINT_MASK		0xe0
+#define SECOINT			0x00000008
+#define SECOINT_MASK		0x1f
+#define ENRISEINT		0x0000000A
+#define CLRRISEINT		0x0000000C
+#define ENHILVINT		0x0000000E
+#define CLRHILVINT		0x00000010
+#define ENFALLINT		0x00000012
+#define CLRFALLINT		0x00000014
+#define IRQ_MEM_SIZE		0x00000016
+#define LP8X4X_NUM_IRQ_DEFAULT	16
+
+/**
+ * struct lp8x4x_irq_data - LP8X4X custom irq controller state container
+ * @base:               base IO memory address
+ * @irq_domain:         Interrupt translation domain; responsible for mapping
+ *                      between hwirq number and linux irq number
+ * @irq_sys_enabled:    mask keeping track of interrupts enabled in the
+ *                      register which vendor calls 'system'
+ * @irq_high_enabled:   mask keeping track of interrupts enabled in the
+ *                      register which vendor calls 'high'
+ *
+ * The structure implements State Container from
+ * Documentation/driver-model/design-patterns.txt
+ */
+
+struct lp8x4x_irq_data {
+	void			*base;
+	struct irq_domain	*domain;
+	unsigned char		irq_sys_enabled;
+	unsigned char		irq_high_enabled;
+};
+
+static void lp8x4x_mask_irq(struct irq_data *d)
+{
+	unsigned mask;
+	unsigned long hwirq = d->hwirq;
+	struct lp8x4x_irq_data *host = irq_data_get_irq_chip_data(d);
+
+	if (hwirq < 8) {
+		host->irq_high_enabled &= ~BIT(hwirq);
+
+		mask = ioread8(host->base + ENHILVINT);
+		mask &= ~BIT(hwirq);
+		iowrite8(mask, host->base + ENHILVINT);
+	} else {
+		hwirq -= 8;
+		host->irq_sys_enabled &= ~BIT(hwirq);
+
+		mask = ioread8(host->base + ENSYSINT);
+		mask &= ~BIT(hwirq);
+		iowrite8(mask, host->base + ENSYSINT);
+	}
+}
+
+static void lp8x4x_unmask_irq(struct irq_data *d)
+{
+	unsigned mask;
+	unsigned long hwirq = d->hwirq;
+	struct lp8x4x_irq_data *host = irq_data_get_irq_chip_data(d);
+
+	if (hwirq < 8) {
+		host->irq_high_enabled |= BIT(hwirq);
+		mask = ioread8(host->base + CLRHILVINT);
+		mask |= BIT(hwirq);
+		iowrite8(mask, host->base + CLRHILVINT);
+
+		mask = ioread8(host->base + ENHILVINT);
+		mask |= BIT(hwirq);
+		iowrite8(mask, host->base + ENHILVINT);
+	} else {
+		hwirq -= 8;
+		host->irq_sys_enabled |= BIT(hwirq);
+
+		mask = ioread8(host->base + SECOINT);
+		mask |= BIT(hwirq);
+		iowrite8(mask, host->base + SECOINT);
+
+		mask = ioread8(host->base + ENSYSINT);
+		mask |= BIT(hwirq);
+		iowrite8(mask, host->base + ENSYSINT);
+	}
+}
+
+static struct irq_chip lp8x4x_irq_chip = {
+	.name			= "FPGA",
+	.irq_ack		= lp8x4x_mask_irq,
+	.irq_mask		= lp8x4x_mask_irq,
+	.irq_mask_ack		= lp8x4x_mask_irq,
+	.irq_unmask		= lp8x4x_unmask_irq,
+};
+
+static void lp8x4x_irq_handler(struct irq_desc *desc)
+{
+	int n;
+	unsigned long mask;
+	struct irq_chip *chip = irq_desc_get_chip(desc);
+	struct lp8x4x_irq_data *host = irq_desc_get_handler_data(desc);
+
+	chained_irq_enter(chip, desc);
+
+	for (;;) {
+		mask = ioread8(host->base + CLRHILVINT) & 0xff;
+		mask |= (ioread8(host->base + SECOINT) & SECOINT_MASK) << 8;
+		mask |= (ioread8(host->base + PRIMINT) & PRIMINT_MASK) << 8;
+		mask &= host->irq_high_enabled | (host->irq_sys_enabled << 8);
+		if (mask == 0)
+			break;
+		for_each_set_bit(n, &mask, BITS_PER_LONG)
+			generic_handle_irq(irq_find_mapping(host->domain, n));
+	}
+
+	iowrite8(0, host->base + EOI);
+	chained_irq_exit(chip, desc);
+}
+
+static int lp8x4x_irq_domain_map(struct irq_domain *d, unsigned int irq,
+				 irq_hw_number_t hw)
+{
+	struct lp8x4x_irq_data *host = d->host_data;
+	int err;
+
+	err = irq_set_chip_data(irq, host);
+	if (err < 0)
+		return err;
+
+	irq_set_chip_and_handler(irq, &lp8x4x_irq_chip, handle_level_irq);
+	irq_set_probe(irq);
+	return 0;
+}
+
+const struct irq_domain_ops lp8x4x_irq_domain_ops = {
+	.map	= lp8x4x_irq_domain_map,
+	.xlate	= irq_domain_xlate_onecell,
+};
+
+static const struct of_device_id lp8x4x_irq_dt_ids[] = {
+	{ .compatible = "icpdas,irq-lp8x4x", },
+	{}
+};
+
+static int lp8x4x_irq_probe(struct platform_device *pdev)
+{
+	struct resource *res_mem, *res_irq;
+	struct device_node *np = pdev->dev.of_node;
+	struct lp8x4x_irq_data *host;
+	int i, err;
+
+	res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!res_mem || !res_irq || resource_size(res_mem) < IRQ_MEM_SIZE)
+		return -ENODEV;
+
+	host = devm_kzalloc(&pdev->dev, sizeof(*host), GFP_KERNEL);
+	if (!host)
+		return -ENODEV;
+
+	host->base = devm_ioremap_resource(&pdev->dev, res_mem);
+	if (!host->base) {
+		dev_err(&pdev->dev, "Failed to ioremap %p\n", host->base);
+		return -EFAULT;
+	}
+
+	host->domain = irq_domain_add_linear(np, LP8X4X_NUM_IRQ_DEFAULT,
+				       &lp8x4x_irq_domain_ops, host);
+	if (!host->domain) {
+		dev_err(&pdev->dev, "Failed to add IRQ domain\n");
+		return -ENOMEM;
+	}
+
+	for (i = 0; i < LP8X4X_NUM_IRQ_DEFAULT; i++) {
+		err = irq_create_mapping(host->domain, i);
+		if (err < 0)
+			dev_err(&pdev->dev, "Failed to map IRQ %i\n", i);
+	}
+
+	/* Initialize chip registers */
+	iowrite8(0, host->base + CLRRISEINT);
+	iowrite8(0, host->base + ENRISEINT);
+	iowrite8(0, host->base + CLRFALLINT);
+	iowrite8(0, host->base + ENFALLINT);
+	iowrite8(0, host->base + CLRHILVINT);
+	iowrite8(0, host->base + ENHILVINT);
+	iowrite8(0, host->base + ENSYSINT);
+	iowrite8(0, host->base + SECOINT);
+
+	irq_set_handler_data(res_irq->start, host);
+	irq_set_chained_handler(res_irq->start, lp8x4x_irq_handler);
+
+	return 0;
+}
+
+static struct platform_driver lp8x4x_irq_driver = {
+	.probe		= lp8x4x_irq_probe,
+	.driver		= {
+		.name	= "irq-lp8x4x",
+		.of_match_table = lp8x4x_irq_dt_ids,
+	},
+};
+
+static int __init lp8x4x_irq_init(void)
+{
+	return platform_driver_register(&lp8x4x_irq_driver);
+}
+postcore_initcall(lp8x4x_irq_init);
-- 
2.6.2


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

* [PATCH v5] arm: pxa: support ICP DAS LP-8x4x FPGA irq
@ 2015-12-15 19:26                     ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2015-12-15 19:26 UTC (permalink / raw)
  To: linux-kernel-u79uwXL29TY76Z2rM5mHXA
  Cc: Linus Walleij, Sergei Ianovich, Arnd Bergmann, Thomas Gleixner,
	Jason Cooper, Marc Zyngier, Rob Herring, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS

ICP DAS LP-8x4x contains FPGA chip. The chip functions as an interrupt
source providing 16 additional interrupts among other things. The
interrupt lines are muxed to a GPIO pin of a 2nd level PXA-GPIO
interrupt controller. GPIO pins of the 2nd level controller are in turn
muxed to a CPU interrupt line.

Until pxa is completely converted to device tree, it is impossible
to use IRQCHIP_DECLARE() and the irqdomain needs to added manually.
Drivers for the on-CPU IRQs and GPIO-IRQs are loaded using
postcore_initcall(). We need to have all irq domain drivers loaded prior
to DT parsing in order to allow normal initialization of IRQ resources
with DT.

Signed-off-by: Sergei Ianovich <ynvich-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Reviewed-by: Linus Walleij <linus.walleij-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
CC: Arnd Bergmann <arnd-r2nGTMty4D4@public.gmane.org>
---
   v4..v5
   * constify struct of_device_id
   * drop irq number from handler signature

   v3.2..v4
   * move DTS binding to a different patch (8/21)

   v3.1..v3.2
   fixes to apply Linus Walleij's "Reviewed-by":
   * add kerneldoc comment for state container struct
   * rename irq -> hwirq for clarity
   * drop overzealous error checks from the hotpaths

   v3..v3.1
   fixes according to Linus Walleij review comments:
   * update commit message
   * use state container instead of global variables
   * get hardware irq nums from irq_data, don't calculate them
   * use BIT() macro
   * add defines for system irq register masks
   * replace cycle control variable with break
   * use better names for resource variables
   * add a linear domain instead of a legacy one
   * use irq_create_mapping() instead of irq_alloc_desc()

   v2..v3
   * no changes (except number 09/16 -> 11/21)

   v0..v2
   * extract irqchip and move to drivers/irqchip/
   * use device tree
   * use devm helpers where possible

 .../bindings/interrupt-controller/irq-lp8x4x.txt   |  49 +++++
 drivers/irqchip/Kconfig                            |   5 +
 drivers/irqchip/Makefile                           |   1 +
 drivers/irqchip/irq-lp8x4x.c                       | 227 +++++++++++++++++++++
 4 files changed, 282 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/interrupt-controller/irq-lp8x4x.txt
 create mode 100644 drivers/irqchip/irq-lp8x4x.c

diff --git a/Documentation/devicetree/bindings/interrupt-controller/irq-lp8x4x.txt b/Documentation/devicetree/bindings/interrupt-controller/irq-lp8x4x.txt
new file mode 100644
index 0000000..c8940d2
--- /dev/null
+++ b/Documentation/devicetree/bindings/interrupt-controller/irq-lp8x4x.txt
@@ -0,0 +1,49 @@
+ICP DAS LP-8x4x FPGA Interrupt Controller
+
+ICP DAS LP-8x4x contains FPGA chip. The chip functions as a interrupt
+source providing 16 additional interrupts among other things.
+
+Required properties:
+- compatible : should be "icpdas,irq-lp8x4x"
+
+- reg: physical base address of the controller and length of memory mapped
+  region.
+
+- interrupt-controller : identifies the node as an interrupt controller
+
+- #interrupt-cells : should be 1
+
+- interrupts : should provide interrupt
+
+- interrupt-parent : should provide a link to interrupt controller either
+		     explicitly and implicitly from a parent node
+
+Example:
+
+	fpga: fpga@17000006 {
+		compatible = "icpdas,irq-lp8x4x";
+		reg = <0x17000006 0x16>;
+		interrupt-parent = <&gpio>;
+		interrupts = <3 IRQ_TYPE_EDGE_RISING>;
+		#interrupt-cells = <1>;
+		interrupt-controller;
+		status = "okay";
+	};
+
+	uart@17009050 {
+		compatible = "icpdas,uart-lp8x4x";
+		reg = <0x17009050 0x10
+		       0x17009030 0x02>;
+		interrupt-parent = <&fpga>;
+		interrupts = <13>;
+		status = "okay";
+	};
+
+	uart@17009060 {
+		compatible = "icpdas,uart-lp8x4x";
+		reg = <0x17009060 0x10
+		       0x17009032 0x02>;
+		interrupt-parent = <&fpga>;
+		interrupts = <14>;
+		status = "okay";
+	};
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index 4d7294e..1de7361 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -193,3 +193,8 @@ config IRQ_MXS
 	def_bool y if MACH_ASM9260 || ARCH_MXS
 	select IRQ_DOMAIN
 	select STMP_DEVICE
+
+config LP8X4X_IRQ
+	bool
+	depends on OF && ARCH_PXA
+	select IRQ_DOMAIN
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index 177f78f..ab9ca67 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -55,3 +55,4 @@ obj-$(CONFIG_RENESAS_H8S_INTC)		+= irq-renesas-h8s.o
 obj-$(CONFIG_ARCH_SA1100)		+= irq-sa11x0.o
 obj-$(CONFIG_INGENIC_IRQ)		+= irq-ingenic.o
 obj-$(CONFIG_IMX_GPCV2)			+= irq-imx-gpcv2.o
+obj-$(CONFIG_LP8X4X_IRQ)		+= irq-lp8x4x.o
diff --git a/drivers/irqchip/irq-lp8x4x.c b/drivers/irqchip/irq-lp8x4x.c
new file mode 100644
index 0000000..a03d925
--- /dev/null
+++ b/drivers/irqchip/irq-lp8x4x.c
@@ -0,0 +1,227 @@
+/*
+ *  linux/drivers/irqchip/irq-lp8x4x.c
+ *
+ *  Support for ICP DAS LP-8x4x FPGA irq
+ *  Copyright (C) 2013 Sergei Ianovich <ynvich-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation or any later version.
+ */
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/irqchip/chained_irq.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+#define EOI			0x00000000
+#define INSINT			0x00000002
+#define ENSYSINT		0x00000004
+#define PRIMINT			0x00000006
+#define PRIMINT_MASK		0xe0
+#define SECOINT			0x00000008
+#define SECOINT_MASK		0x1f
+#define ENRISEINT		0x0000000A
+#define CLRRISEINT		0x0000000C
+#define ENHILVINT		0x0000000E
+#define CLRHILVINT		0x00000010
+#define ENFALLINT		0x00000012
+#define CLRFALLINT		0x00000014
+#define IRQ_MEM_SIZE		0x00000016
+#define LP8X4X_NUM_IRQ_DEFAULT	16
+
+/**
+ * struct lp8x4x_irq_data - LP8X4X custom irq controller state container
+ * @base:               base IO memory address
+ * @irq_domain:         Interrupt translation domain; responsible for mapping
+ *                      between hwirq number and linux irq number
+ * @irq_sys_enabled:    mask keeping track of interrupts enabled in the
+ *                      register which vendor calls 'system'
+ * @irq_high_enabled:   mask keeping track of interrupts enabled in the
+ *                      register which vendor calls 'high'
+ *
+ * The structure implements State Container from
+ * Documentation/driver-model/design-patterns.txt
+ */
+
+struct lp8x4x_irq_data {
+	void			*base;
+	struct irq_domain	*domain;
+	unsigned char		irq_sys_enabled;
+	unsigned char		irq_high_enabled;
+};
+
+static void lp8x4x_mask_irq(struct irq_data *d)
+{
+	unsigned mask;
+	unsigned long hwirq = d->hwirq;
+	struct lp8x4x_irq_data *host = irq_data_get_irq_chip_data(d);
+
+	if (hwirq < 8) {
+		host->irq_high_enabled &= ~BIT(hwirq);
+
+		mask = ioread8(host->base + ENHILVINT);
+		mask &= ~BIT(hwirq);
+		iowrite8(mask, host->base + ENHILVINT);
+	} else {
+		hwirq -= 8;
+		host->irq_sys_enabled &= ~BIT(hwirq);
+
+		mask = ioread8(host->base + ENSYSINT);
+		mask &= ~BIT(hwirq);
+		iowrite8(mask, host->base + ENSYSINT);
+	}
+}
+
+static void lp8x4x_unmask_irq(struct irq_data *d)
+{
+	unsigned mask;
+	unsigned long hwirq = d->hwirq;
+	struct lp8x4x_irq_data *host = irq_data_get_irq_chip_data(d);
+
+	if (hwirq < 8) {
+		host->irq_high_enabled |= BIT(hwirq);
+		mask = ioread8(host->base + CLRHILVINT);
+		mask |= BIT(hwirq);
+		iowrite8(mask, host->base + CLRHILVINT);
+
+		mask = ioread8(host->base + ENHILVINT);
+		mask |= BIT(hwirq);
+		iowrite8(mask, host->base + ENHILVINT);
+	} else {
+		hwirq -= 8;
+		host->irq_sys_enabled |= BIT(hwirq);
+
+		mask = ioread8(host->base + SECOINT);
+		mask |= BIT(hwirq);
+		iowrite8(mask, host->base + SECOINT);
+
+		mask = ioread8(host->base + ENSYSINT);
+		mask |= BIT(hwirq);
+		iowrite8(mask, host->base + ENSYSINT);
+	}
+}
+
+static struct irq_chip lp8x4x_irq_chip = {
+	.name			= "FPGA",
+	.irq_ack		= lp8x4x_mask_irq,
+	.irq_mask		= lp8x4x_mask_irq,
+	.irq_mask_ack		= lp8x4x_mask_irq,
+	.irq_unmask		= lp8x4x_unmask_irq,
+};
+
+static void lp8x4x_irq_handler(struct irq_desc *desc)
+{
+	int n;
+	unsigned long mask;
+	struct irq_chip *chip = irq_desc_get_chip(desc);
+	struct lp8x4x_irq_data *host = irq_desc_get_handler_data(desc);
+
+	chained_irq_enter(chip, desc);
+
+	for (;;) {
+		mask = ioread8(host->base + CLRHILVINT) & 0xff;
+		mask |= (ioread8(host->base + SECOINT) & SECOINT_MASK) << 8;
+		mask |= (ioread8(host->base + PRIMINT) & PRIMINT_MASK) << 8;
+		mask &= host->irq_high_enabled | (host->irq_sys_enabled << 8);
+		if (mask == 0)
+			break;
+		for_each_set_bit(n, &mask, BITS_PER_LONG)
+			generic_handle_irq(irq_find_mapping(host->domain, n));
+	}
+
+	iowrite8(0, host->base + EOI);
+	chained_irq_exit(chip, desc);
+}
+
+static int lp8x4x_irq_domain_map(struct irq_domain *d, unsigned int irq,
+				 irq_hw_number_t hw)
+{
+	struct lp8x4x_irq_data *host = d->host_data;
+	int err;
+
+	err = irq_set_chip_data(irq, host);
+	if (err < 0)
+		return err;
+
+	irq_set_chip_and_handler(irq, &lp8x4x_irq_chip, handle_level_irq);
+	irq_set_probe(irq);
+	return 0;
+}
+
+const struct irq_domain_ops lp8x4x_irq_domain_ops = {
+	.map	= lp8x4x_irq_domain_map,
+	.xlate	= irq_domain_xlate_onecell,
+};
+
+static const struct of_device_id lp8x4x_irq_dt_ids[] = {
+	{ .compatible = "icpdas,irq-lp8x4x", },
+	{}
+};
+
+static int lp8x4x_irq_probe(struct platform_device *pdev)
+{
+	struct resource *res_mem, *res_irq;
+	struct device_node *np = pdev->dev.of_node;
+	struct lp8x4x_irq_data *host;
+	int i, err;
+
+	res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!res_mem || !res_irq || resource_size(res_mem) < IRQ_MEM_SIZE)
+		return -ENODEV;
+
+	host = devm_kzalloc(&pdev->dev, sizeof(*host), GFP_KERNEL);
+	if (!host)
+		return -ENODEV;
+
+	host->base = devm_ioremap_resource(&pdev->dev, res_mem);
+	if (!host->base) {
+		dev_err(&pdev->dev, "Failed to ioremap %p\n", host->base);
+		return -EFAULT;
+	}
+
+	host->domain = irq_domain_add_linear(np, LP8X4X_NUM_IRQ_DEFAULT,
+				       &lp8x4x_irq_domain_ops, host);
+	if (!host->domain) {
+		dev_err(&pdev->dev, "Failed to add IRQ domain\n");
+		return -ENOMEM;
+	}
+
+	for (i = 0; i < LP8X4X_NUM_IRQ_DEFAULT; i++) {
+		err = irq_create_mapping(host->domain, i);
+		if (err < 0)
+			dev_err(&pdev->dev, "Failed to map IRQ %i\n", i);
+	}
+
+	/* Initialize chip registers */
+	iowrite8(0, host->base + CLRRISEINT);
+	iowrite8(0, host->base + ENRISEINT);
+	iowrite8(0, host->base + CLRFALLINT);
+	iowrite8(0, host->base + ENFALLINT);
+	iowrite8(0, host->base + CLRHILVINT);
+	iowrite8(0, host->base + ENHILVINT);
+	iowrite8(0, host->base + ENSYSINT);
+	iowrite8(0, host->base + SECOINT);
+
+	irq_set_handler_data(res_irq->start, host);
+	irq_set_chained_handler(res_irq->start, lp8x4x_irq_handler);
+
+	return 0;
+}
+
+static struct platform_driver lp8x4x_irq_driver = {
+	.probe		= lp8x4x_irq_probe,
+	.driver		= {
+		.name	= "irq-lp8x4x",
+		.of_match_table = lp8x4x_irq_dt_ids,
+	},
+};
+
+static int __init lp8x4x_irq_init(void)
+{
+	return platform_driver_register(&lp8x4x_irq_driver);
+}
+postcore_initcall(lp8x4x_irq_init);
-- 
2.6.2

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH v5 2/2] arm: pxa27x: support for ICP DAS LP-8x4x w/ DT
  2015-12-15 19:21                               ` Arnd Bergmann
  (?)
@ 2015-12-15 20:01                                 ` Robert Jarzmik
  -1 siblings, 0 replies; 700+ messages in thread
From: Robert Jarzmik @ 2015-12-15 20:01 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Sergei Ianovich, linux-kernel, Daniel Mack, Rob Herring,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala, Russell King,
	Thierry Reding, Jonathan Cameron, Dmitry Torokhov, Philipp Zabel,
	Arnaud Ebalard, Kuninori Morimoto,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	moderated list:ARM PORT

Arnd Bergmann <arnd@arndb.de> writes:

> On Tuesday 15 December 2015 21:50:13 Sergei Ianovich wrote:
>> On Tue, 2015-12-15 at 19:06 +0100, Robert Jarzmik wrote:
>> Updated plan:
>> 1. MACH_PXA27X_DT
>> 2. PXA_FB and 8250_PXA to enable console
What about gpio-pxa ? And maybe pinctrl-pxa27x (only in linux-next by now) ? Can
a pxafb work without gpio-pxa ? Also usually for pxafb you have pwm and pwm_bl
to see something.

>> 3. MMC, MMC_PXA and EXT4_FS to enable boot from MMC
>> 3.1. MTD, MTD_CFI, MTD_PHYSMAP_OF and JFFS2_FS to enable boot from MTD
Ok. Is pxa2xx-pcmcia out of scope ? I seem to remember we have several boards
where pcmcia is the rootfs (even if that is a small mess right now I still have
to work on). Or do we consider pcmcia as obsolete ?

>> 4. all optional pxa stuff as modules
>> 5. all stuff on supported pxa boards as modules
>> 6. supported boards should boot the kernel built with
>> `pxa27x-dt_defconfig` after `make olddefconfig`
>> 
>> It is probably a good idea to put this plan somewhere in Documentation/
>> and to have a comment about that in the defconfig itself.
>> 
>> Is the plan acceptable?
>
> Sounds good to me.
Sounds good to me too.

Cheers.

-- 
Robert

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

* Re: [PATCH v5 2/2] arm: pxa27x: support for ICP DAS LP-8x4x w/ DT
@ 2015-12-15 20:01                                 ` Robert Jarzmik
  0 siblings, 0 replies; 700+ messages in thread
From: Robert Jarzmik @ 2015-12-15 20:01 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Sergei Ianovich, linux-kernel, Daniel Mack, Rob Herring,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala, Russell King,
	Thierry Reding, Jonathan Cameron, Dmitry Torokhov, Philipp Zabel,
	Arnaud Ebalard, Kuninori Morimoto,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	moderated list:ARM PORT

Arnd Bergmann <arnd@arndb.de> writes:

> On Tuesday 15 December 2015 21:50:13 Sergei Ianovich wrote:
>> On Tue, 2015-12-15 at 19:06 +0100, Robert Jarzmik wrote:
>> Updated plan:
>> 1. MACH_PXA27X_DT
>> 2. PXA_FB and 8250_PXA to enable console
What about gpio-pxa ? And maybe pinctrl-pxa27x (only in linux-next by now) ? Can
a pxafb work without gpio-pxa ? Also usually for pxafb you have pwm and pwm_bl
to see something.

>> 3. MMC, MMC_PXA and EXT4_FS to enable boot from MMC
>> 3.1. MTD, MTD_CFI, MTD_PHYSMAP_OF and JFFS2_FS to enable boot from MTD
Ok. Is pxa2xx-pcmcia out of scope ? I seem to remember we have several boards
where pcmcia is the rootfs (even if that is a small mess right now I still have
to work on). Or do we consider pcmcia as obsolete ?

>> 4. all optional pxa stuff as modules
>> 5. all stuff on supported pxa boards as modules
>> 6. supported boards should boot the kernel built with
>> `pxa27x-dt_defconfig` after `make olddefconfig`
>> 
>> It is probably a good idea to put this plan somewhere in Documentation/
>> and to have a comment about that in the defconfig itself.
>> 
>> Is the plan acceptable?
>
> Sounds good to me.
Sounds good to me too.

Cheers.

-- 
Robert

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

* [PATCH v5 2/2] arm: pxa27x: support for ICP DAS LP-8x4x w/ DT
@ 2015-12-15 20:01                                 ` Robert Jarzmik
  0 siblings, 0 replies; 700+ messages in thread
From: Robert Jarzmik @ 2015-12-15 20:01 UTC (permalink / raw)
  To: linux-arm-kernel

Arnd Bergmann <arnd@arndb.de> writes:

> On Tuesday 15 December 2015 21:50:13 Sergei Ianovich wrote:
>> On Tue, 2015-12-15 at 19:06 +0100, Robert Jarzmik wrote:
>> Updated plan:
>> 1. MACH_PXA27X_DT
>> 2. PXA_FB and 8250_PXA to enable console
What about gpio-pxa ? And maybe pinctrl-pxa27x (only in linux-next by now) ? Can
a pxafb work without gpio-pxa ? Also usually for pxafb you have pwm and pwm_bl
to see something.

>> 3. MMC, MMC_PXA and EXT4_FS to enable boot from MMC
>> 3.1. MTD, MTD_CFI, MTD_PHYSMAP_OF and JFFS2_FS to enable boot from MTD
Ok. Is pxa2xx-pcmcia out of scope ? I seem to remember we have several boards
where pcmcia is the rootfs (even if that is a small mess right now I still have
to work on). Or do we consider pcmcia as obsolete ?

>> 4. all optional pxa stuff as modules
>> 5. all stuff on supported pxa boards as modules
>> 6. supported boards should boot the kernel built with
>> `pxa27x-dt_defconfig` after `make olddefconfig`
>> 
>> It is probably a good idea to put this plan somewhere in Documentation/
>> and to have a comment about that in the defconfig itself.
>> 
>> Is the plan acceptable?
>
> Sounds good to me.
Sounds good to me too.

Cheers.

-- 
Robert

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

* Re: [PATCH v5 2/2] arm: pxa27x: support for ICP DAS LP-8x4x w/ DT
  2015-12-15 20:01                                 ` Robert Jarzmik
  (?)
@ 2015-12-15 20:40                                   ` Arnd Bergmann
  -1 siblings, 0 replies; 700+ messages in thread
From: Arnd Bergmann @ 2015-12-15 20:40 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Robert Jarzmik, Mark Rutland,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	Arnaud Ebalard, Russell King, Kuninori Morimoto, Pawel Moll,
	Ian Campbell, Dmitry Torokhov, linux-kernel, Daniel Mack,
	Sergei Ianovich, Rob Herring, Philipp Zabel, Kumar Gala,
	Thierry Reding, Jonathan Cameron

On Tuesday 15 December 2015 21:01:35 Robert Jarzmik wrote:
> Arnd Bergmann <arnd@arndb.de> writes:
> 
> > On Tuesday 15 December 2015 21:50:13 Sergei Ianovich wrote:
> >> On Tue, 2015-12-15 at 19:06 +0100, Robert Jarzmik wrote:
> >> Updated plan:
> >> 1. MACH_PXA27X_DT
> >> 2. PXA_FB and 8250_PXA to enable console
> What about gpio-pxa ? And maybe pinctrl-pxa27x (only in linux-next by now) ? Can
> a pxafb work without gpio-pxa ? Also usually for pxafb you have pwm and pwm_bl
> to see something.
> 
> >> 3. MMC, MMC_PXA and EXT4_FS to enable boot from MMC
> >> 3.1. MTD, MTD_CFI, MTD_PHYSMAP_OF and JFFS2_FS to enable boot from MTD
> Ok. Is pxa2xx-pcmcia out of scope ? I seem to remember we have several boards
> where pcmcia is the rootfs (even if that is a small mess right now I still have
> to work on). Or do we consider pcmcia as obsolete ?

I'm definitely fine with tossing in everything that is PXA specific,
even if it's rarely used.

If someone wants a smaller kernel, they can still start out with the
defconfig and disable stuff they don't need, which tends to be easier
than the opposite, and it gives us compile-time coverage with the
autobuilders that compile every defconfig.

	Arnd

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

* Re: [PATCH v5 2/2] arm: pxa27x: support for ICP DAS LP-8x4x w/ DT
@ 2015-12-15 20:40                                   ` Arnd Bergmann
  0 siblings, 0 replies; 700+ messages in thread
From: Arnd Bergmann @ 2015-12-15 20:40 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Robert Jarzmik, Mark Rutland,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	Arnaud Ebalard, Russell King, Kuninori Morimoto, Pawel Moll,
	Ian Campbell, Dmitry Torokhov, linux-kernel, Daniel Mack,
	Sergei Ianovich, Rob Herring, Philipp Zabel, Kumar Gala,
	Thierry Reding, Jonathan Cameron

On Tuesday 15 December 2015 21:01:35 Robert Jarzmik wrote:
> Arnd Bergmann <arnd@arndb.de> writes:
> 
> > On Tuesday 15 December 2015 21:50:13 Sergei Ianovich wrote:
> >> On Tue, 2015-12-15 at 19:06 +0100, Robert Jarzmik wrote:
> >> Updated plan:
> >> 1. MACH_PXA27X_DT
> >> 2. PXA_FB and 8250_PXA to enable console
> What about gpio-pxa ? And maybe pinctrl-pxa27x (only in linux-next by now) ? Can
> a pxafb work without gpio-pxa ? Also usually for pxafb you have pwm and pwm_bl
> to see something.
> 
> >> 3. MMC, MMC_PXA and EXT4_FS to enable boot from MMC
> >> 3.1. MTD, MTD_CFI, MTD_PHYSMAP_OF and JFFS2_FS to enable boot from MTD
> Ok. Is pxa2xx-pcmcia out of scope ? I seem to remember we have several boards
> where pcmcia is the rootfs (even if that is a small mess right now I still have
> to work on). Or do we consider pcmcia as obsolete ?

I'm definitely fine with tossing in everything that is PXA specific,
even if it's rarely used.

If someone wants a smaller kernel, they can still start out with the
defconfig and disable stuff they don't need, which tends to be easier
than the opposite, and it gives us compile-time coverage with the
autobuilders that compile every defconfig.

	Arnd

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

* [PATCH v5 2/2] arm: pxa27x: support for ICP DAS LP-8x4x w/ DT
@ 2015-12-15 20:40                                   ` Arnd Bergmann
  0 siblings, 0 replies; 700+ messages in thread
From: Arnd Bergmann @ 2015-12-15 20:40 UTC (permalink / raw)
  To: linux-arm-kernel

On Tuesday 15 December 2015 21:01:35 Robert Jarzmik wrote:
> Arnd Bergmann <arnd@arndb.de> writes:
> 
> > On Tuesday 15 December 2015 21:50:13 Sergei Ianovich wrote:
> >> On Tue, 2015-12-15 at 19:06 +0100, Robert Jarzmik wrote:
> >> Updated plan:
> >> 1. MACH_PXA27X_DT
> >> 2. PXA_FB and 8250_PXA to enable console
> What about gpio-pxa ? And maybe pinctrl-pxa27x (only in linux-next by now) ? Can
> a pxafb work without gpio-pxa ? Also usually for pxafb you have pwm and pwm_bl
> to see something.
> 
> >> 3. MMC, MMC_PXA and EXT4_FS to enable boot from MMC
> >> 3.1. MTD, MTD_CFI, MTD_PHYSMAP_OF and JFFS2_FS to enable boot from MTD
> Ok. Is pxa2xx-pcmcia out of scope ? I seem to remember we have several boards
> where pcmcia is the rootfs (even if that is a small mess right now I still have
> to work on). Or do we consider pcmcia as obsolete ?

I'm definitely fine with tossing in everything that is PXA specific,
even if it's rarely used.

If someone wants a smaller kernel, they can still start out with the
defconfig and disable stuff they don't need, which tends to be easier
than the opposite, and it gives us compile-time coverage with the
autobuilders that compile every defconfig.

	Arnd

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

* [PATCH v5] serial: support for 16550A serial ports on LP-8x4x
@ 2015-12-15 21:04                   ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2015-12-15 21:04 UTC (permalink / raw)
  To: linux-kernel
  Cc: Sergei Ianovich, Alan Cox, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Greg Kroah-Hartman, Jiri Slaby,
	Heikki Krogerus, Andy Shevchenko, Arnd Bergmann, Scott Wood,
	Masahiro Yamada, Sebastian Andrzej Siewior, Paul Burton,
	Joachim Eastwood, Mans Rullgard, Paul Gortmaker, Peter Hurley,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	open list:SERIAL DRIVERS

The patch adds support for 3 additional LP-8x4x built-in serial
ports.

The device can also host up to 8 extension cards with 4 serial ports
on each card for a total of 35 ports. However, I don't have
the hardware to test extension cards, so they are not supported, yet.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
CC: Alan Cox <gnomes@lxorguk.ukuu.org.uk>
---
   v4..v5
   * constify struct of_device_id
   * drop .owner from struct platform_driver
   * rewrite set_termios() baud rate hadnling as suggested by Alan Cox

   v3..v4
   * move DTS bindings to a different patch (8/21) as suggested by
     Heikki Krogerus

   v2..v3
   * no changes (except number 10/16 -> 12/21)

   v0..v2
   * register platform driver instead of platform device
   * use device tree
   * use devm helpers where possible

 .../devicetree/bindings/serial/lp8x4x-serial.txt   |  35 +++++
 drivers/tty/serial/8250/8250_lp8x4x.c              | 168 +++++++++++++++++++++
 drivers/tty/serial/8250/Kconfig                    |  12 ++
 drivers/tty/serial/8250/Makefile                   |   1 +
 4 files changed, 216 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/serial/lp8x4x-serial.txt
 create mode 100644 drivers/tty/serial/8250/8250_lp8x4x.c

diff --git a/Documentation/devicetree/bindings/serial/lp8x4x-serial.txt b/Documentation/devicetree/bindings/serial/lp8x4x-serial.txt
new file mode 100644
index 0000000..5f9a4c1
--- /dev/null
+++ b/Documentation/devicetree/bindings/serial/lp8x4x-serial.txt
@@ -0,0 +1,35 @@
+UART ports on ICP DAS LP-8x4x
+
+ICP DAS LP-8x4x contains three additional serial ports interfaced via
+Analog Devices ADM213EA chips in addition to 3 serial ports on PXA CPU.
+
+Required properties:
+- compatible : should be "icpdas,uart-lp8x4x"
+
+- reg : should provide 16 byte man IO memory region and 1 byte region for
+	termios
+
+- interrupts : should provide interrupt
+
+- interrupt-parent : should provide a link to interrupt controller either
+		     explicitly or implicitly from a parent node
+
+Examples (from pxa27x-lp8x4x.dts):
+
+		uart@9050 {
+			compatible = "icpdas,uart-lp8x4x";
+			reg = <0x9050 0x10
+			       0x9030 0x02>;
+			interrupt-parent = <&fpgairg>;
+			interrupts = <13>;
+			status = "okay";
+		};
+
+		uart@9060 {
+			compatible = "icpdas,uart-lp8x4x";
+			reg = <0x9060 0x10
+			       0x9032 0x02>;
+			interrupt-parent = <&fpgairg>;
+			interrupts = <14>;
+			status = "okay";
+		};
diff --git a/drivers/tty/serial/8250/8250_lp8x4x.c b/drivers/tty/serial/8250/8250_lp8x4x.c
new file mode 100644
index 0000000..0e07220
--- /dev/null
+++ b/drivers/tty/serial/8250/8250_lp8x4x.c
@@ -0,0 +1,168 @@
+/*  linux/drivers/tty/serial/8250/8250_lp8x4x.c
+ *
+ *  Support for 16550A serial ports on ICP DAS LP-8x4x
+ *
+ *  Copyright (C) 2013 Sergei Ianovich <ynvich@gmail.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/module.h>
+#include <linux/serial_8250.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+struct lp8x4x_serial_data {
+	int			line;
+	void			*ios_mem;
+};
+
+static void lp8x4x_serial_set_termios(struct uart_port *port,
+		struct ktermios *termios, struct ktermios *old)
+{
+	unsigned int len;
+	unsigned int baud;
+	struct lp8x4x_serial_data *data = port->private_data;
+
+	serial8250_do_set_termios(port, termios, old);
+
+	switch (termios->c_cflag & CSIZE) {
+	case CS5:
+		len = 7;
+		break;
+	case CS6:
+		len = 8;
+		break;
+	case CS7:
+		len = 9;
+		break;
+	default:
+	case CS8:
+		len = 10;
+		break;
+	}
+
+	if (termios->c_cflag & CSTOPB)
+		len++;
+	if (termios->c_cflag & PARENB)
+		len++;
+	if (!(termios->c_cflag & PARODD))
+		len++;
+#ifdef CMSPAR
+	if (termios->c_cflag & CMSPAR)
+		len++;
+#endif
+
+	len -= 9;
+	len &= 3;
+	len <<= 3;
+	/*
+	 * Ask the core to calculate the divisor for us.
+	 */
+	baud = tty_termios_baud_rate(termios);
+
+	switch (baud) {
+	case 115200:
+		len |= 7;
+		break;
+	case 57600:
+		len |= 6;
+		break;
+	case 38400:
+		len |= 5;
+		break;
+	case 19200:
+		len |= 4;
+		break;
+	case 9600:
+		len |= 3;
+		break;
+	case 4800:
+		len |= 2;
+		break;
+	case 2400:
+	default:
+		len |= 1;
+		break;
+	};
+	iowrite8(len, data->ios_mem);
+
+}
+
+static const struct of_device_id lp8x4x_serial_dt_ids[] = {
+	{ .compatible = "icpdas,uart-lp8x4x", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, lp8x4x_serial_dt_ids);
+
+static int lp8x4x_serial_probe(struct platform_device *pdev)
+{
+	struct uart_8250_port uart = {};
+	struct lp8x4x_serial_data *data;
+	struct resource *mmres, *mires, *irqres;
+	int ret;
+
+	mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	mires = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	irqres = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!mmres || !mires || !irqres)
+		return -ENODEV;
+
+	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->ios_mem = devm_ioremap_resource(&pdev->dev, mires);
+	if (!data->ios_mem)
+		return -EFAULT;
+
+	uart.port.iotype = UPIO_MEM;
+	uart.port.mapbase = mmres->start;
+	uart.port.iobase = mmres->start;
+	uart.port.regshift = 1;
+	uart.port.irq = irqres->start;
+	uart.port.flags = UPF_IOREMAP;
+	uart.port.dev = &pdev->dev;
+	uart.port.uartclk = 14745600;
+	uart.port.set_termios = lp8x4x_serial_set_termios;
+	uart.port.private_data = data;
+
+	ret = serial8250_register_8250_port(&uart);
+	if (ret < 0)
+		return ret;
+
+	data->line = ret;
+
+	platform_set_drvdata(pdev, data);
+
+	return 0;
+}
+
+static int lp8x4x_serial_remove(struct platform_device *pdev)
+{
+	struct lp8x4x_serial_data *data = platform_get_drvdata(pdev);
+
+	serial8250_unregister_port(data->line);
+
+	return 0;
+}
+
+static struct platform_driver lp8x4x_serial_driver = {
+	.probe          = lp8x4x_serial_probe,
+	.remove         = lp8x4x_serial_remove,
+
+	.driver		= {
+		.name	= "uart-lp8x4x",
+		.of_match_table = lp8x4x_serial_dt_ids,
+	},
+};
+
+module_platform_driver(lp8x4x_serial_driver);
+
+MODULE_AUTHOR("Sergei Ianovich");
+MODULE_DESCRIPTION("8250 serial port module for LP-8x4x");
+MODULE_LICENSE("GPL");
diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
index 48b6253..00eb6b0 100644
--- a/drivers/tty/serial/8250/Kconfig
+++ b/drivers/tty/serial/8250/Kconfig
@@ -387,3 +387,15 @@ config SERIAL_8250_PXA
 	  can enable its onboard serial ports by enabling this option.
 
 	  If you choose M here, the module name will be 8250_pxa.
+
+config SERIAL_8250_LP8X4X
+	tristate "Support 16550A ports on ICP DAS LP-8x4x"
+	depends on OF && SERIAL_8250 && SERIAL_8250_MANY_PORTS && ARCH_PXA
+	select LP8X4X_IRQ
+	help
+	  In addition to serial ports on PXA270 SoC, LP-8x4x has 1 dual
+	  RS232/RS485 port, 1 RS485 port and 1 RS232 port.
+
+	  Say N here, unless you plan to run this kernel on a LP-8x4x system.
+
+	  If you choose M here, the module name will be 8250_lp8x4x.
diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile
index 7e54413..8bdbf40 100644
--- a/drivers/tty/serial/8250/Makefile
+++ b/drivers/tty/serial/8250/Makefile
@@ -18,6 +18,7 @@ obj-$(CONFIG_SERIAL_8250_ACCENT)	+= 8250_accent.o
 obj-$(CONFIG_SERIAL_8250_BOCA)		+= 8250_boca.o
 obj-$(CONFIG_SERIAL_8250_EXAR_ST16C554)	+= 8250_exar_st16c554.o
 obj-$(CONFIG_SERIAL_8250_HUB6)		+= 8250_hub6.o
+obj-$(CONFIG_SERIAL_8250_LP8X4X)	+= 8250_lp8x4x.o
 obj-$(CONFIG_SERIAL_8250_FSL)		+= 8250_fsl.o
 obj-$(CONFIG_SERIAL_8250_DW)		+= 8250_dw.o
 obj-$(CONFIG_SERIAL_8250_EM)		+= 8250_em.o
-- 
2.6.2


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

* [PATCH v5] serial: support for 16550A serial ports on LP-8x4x
@ 2015-12-15 21:04                   ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2015-12-15 21:04 UTC (permalink / raw)
  To: linux-kernel-u79uwXL29TY76Z2rM5mHXA
  Cc: Sergei Ianovich, Alan Cox, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Greg Kroah-Hartman, Jiri Slaby,
	Heikki Krogerus, Andy Shevchenko, Arnd Bergmann, Scott Wood,
	Masahiro Yamada, Sebastian Andrzej Siewior, Paul Burton,
	Joachim Eastwood, Mans Rullgard, Paul Gortmaker, Peter Hurley,
	open list:OPEN FIRMWARE AND FLATTENED

The patch adds support for 3 additional LP-8x4x built-in serial
ports.

The device can also host up to 8 extension cards with 4 serial ports
on each card for a total of 35 ports. However, I don't have
the hardware to test extension cards, so they are not supported, yet.

Signed-off-by: Sergei Ianovich <ynvich-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Reviewed-by: Heikki Krogerus <heikki.krogerus-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
CC: Alan Cox <gnomes-qBU/x9rampVanCEyBjwyrvXRex20P6io@public.gmane.org>
---
   v4..v5
   * constify struct of_device_id
   * drop .owner from struct platform_driver
   * rewrite set_termios() baud rate hadnling as suggested by Alan Cox

   v3..v4
   * move DTS bindings to a different patch (8/21) as suggested by
     Heikki Krogerus

   v2..v3
   * no changes (except number 10/16 -> 12/21)

   v0..v2
   * register platform driver instead of platform device
   * use device tree
   * use devm helpers where possible

 .../devicetree/bindings/serial/lp8x4x-serial.txt   |  35 +++++
 drivers/tty/serial/8250/8250_lp8x4x.c              | 168 +++++++++++++++++++++
 drivers/tty/serial/8250/Kconfig                    |  12 ++
 drivers/tty/serial/8250/Makefile                   |   1 +
 4 files changed, 216 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/serial/lp8x4x-serial.txt
 create mode 100644 drivers/tty/serial/8250/8250_lp8x4x.c

diff --git a/Documentation/devicetree/bindings/serial/lp8x4x-serial.txt b/Documentation/devicetree/bindings/serial/lp8x4x-serial.txt
new file mode 100644
index 0000000..5f9a4c1
--- /dev/null
+++ b/Documentation/devicetree/bindings/serial/lp8x4x-serial.txt
@@ -0,0 +1,35 @@
+UART ports on ICP DAS LP-8x4x
+
+ICP DAS LP-8x4x contains three additional serial ports interfaced via
+Analog Devices ADM213EA chips in addition to 3 serial ports on PXA CPU.
+
+Required properties:
+- compatible : should be "icpdas,uart-lp8x4x"
+
+- reg : should provide 16 byte man IO memory region and 1 byte region for
+	termios
+
+- interrupts : should provide interrupt
+
+- interrupt-parent : should provide a link to interrupt controller either
+		     explicitly or implicitly from a parent node
+
+Examples (from pxa27x-lp8x4x.dts):
+
+		uart@9050 {
+			compatible = "icpdas,uart-lp8x4x";
+			reg = <0x9050 0x10
+			       0x9030 0x02>;
+			interrupt-parent = <&fpgairg>;
+			interrupts = <13>;
+			status = "okay";
+		};
+
+		uart@9060 {
+			compatible = "icpdas,uart-lp8x4x";
+			reg = <0x9060 0x10
+			       0x9032 0x02>;
+			interrupt-parent = <&fpgairg>;
+			interrupts = <14>;
+			status = "okay";
+		};
diff --git a/drivers/tty/serial/8250/8250_lp8x4x.c b/drivers/tty/serial/8250/8250_lp8x4x.c
new file mode 100644
index 0000000..0e07220
--- /dev/null
+++ b/drivers/tty/serial/8250/8250_lp8x4x.c
@@ -0,0 +1,168 @@
+/*  linux/drivers/tty/serial/8250/8250_lp8x4x.c
+ *
+ *  Support for 16550A serial ports on ICP DAS LP-8x4x
+ *
+ *  Copyright (C) 2013 Sergei Ianovich <ynvich-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/module.h>
+#include <linux/serial_8250.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+struct lp8x4x_serial_data {
+	int			line;
+	void			*ios_mem;
+};
+
+static void lp8x4x_serial_set_termios(struct uart_port *port,
+		struct ktermios *termios, struct ktermios *old)
+{
+	unsigned int len;
+	unsigned int baud;
+	struct lp8x4x_serial_data *data = port->private_data;
+
+	serial8250_do_set_termios(port, termios, old);
+
+	switch (termios->c_cflag & CSIZE) {
+	case CS5:
+		len = 7;
+		break;
+	case CS6:
+		len = 8;
+		break;
+	case CS7:
+		len = 9;
+		break;
+	default:
+	case CS8:
+		len = 10;
+		break;
+	}
+
+	if (termios->c_cflag & CSTOPB)
+		len++;
+	if (termios->c_cflag & PARENB)
+		len++;
+	if (!(termios->c_cflag & PARODD))
+		len++;
+#ifdef CMSPAR
+	if (termios->c_cflag & CMSPAR)
+		len++;
+#endif
+
+	len -= 9;
+	len &= 3;
+	len <<= 3;
+	/*
+	 * Ask the core to calculate the divisor for us.
+	 */
+	baud = tty_termios_baud_rate(termios);
+
+	switch (baud) {
+	case 115200:
+		len |= 7;
+		break;
+	case 57600:
+		len |= 6;
+		break;
+	case 38400:
+		len |= 5;
+		break;
+	case 19200:
+		len |= 4;
+		break;
+	case 9600:
+		len |= 3;
+		break;
+	case 4800:
+		len |= 2;
+		break;
+	case 2400:
+	default:
+		len |= 1;
+		break;
+	};
+	iowrite8(len, data->ios_mem);
+
+}
+
+static const struct of_device_id lp8x4x_serial_dt_ids[] = {
+	{ .compatible = "icpdas,uart-lp8x4x", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, lp8x4x_serial_dt_ids);
+
+static int lp8x4x_serial_probe(struct platform_device *pdev)
+{
+	struct uart_8250_port uart = {};
+	struct lp8x4x_serial_data *data;
+	struct resource *mmres, *mires, *irqres;
+	int ret;
+
+	mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	mires = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	irqres = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!mmres || !mires || !irqres)
+		return -ENODEV;
+
+	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->ios_mem = devm_ioremap_resource(&pdev->dev, mires);
+	if (!data->ios_mem)
+		return -EFAULT;
+
+	uart.port.iotype = UPIO_MEM;
+	uart.port.mapbase = mmres->start;
+	uart.port.iobase = mmres->start;
+	uart.port.regshift = 1;
+	uart.port.irq = irqres->start;
+	uart.port.flags = UPF_IOREMAP;
+	uart.port.dev = &pdev->dev;
+	uart.port.uartclk = 14745600;
+	uart.port.set_termios = lp8x4x_serial_set_termios;
+	uart.port.private_data = data;
+
+	ret = serial8250_register_8250_port(&uart);
+	if (ret < 0)
+		return ret;
+
+	data->line = ret;
+
+	platform_set_drvdata(pdev, data);
+
+	return 0;
+}
+
+static int lp8x4x_serial_remove(struct platform_device *pdev)
+{
+	struct lp8x4x_serial_data *data = platform_get_drvdata(pdev);
+
+	serial8250_unregister_port(data->line);
+
+	return 0;
+}
+
+static struct platform_driver lp8x4x_serial_driver = {
+	.probe          = lp8x4x_serial_probe,
+	.remove         = lp8x4x_serial_remove,
+
+	.driver		= {
+		.name	= "uart-lp8x4x",
+		.of_match_table = lp8x4x_serial_dt_ids,
+	},
+};
+
+module_platform_driver(lp8x4x_serial_driver);
+
+MODULE_AUTHOR("Sergei Ianovich");
+MODULE_DESCRIPTION("8250 serial port module for LP-8x4x");
+MODULE_LICENSE("GPL");
diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
index 48b6253..00eb6b0 100644
--- a/drivers/tty/serial/8250/Kconfig
+++ b/drivers/tty/serial/8250/Kconfig
@@ -387,3 +387,15 @@ config SERIAL_8250_PXA
 	  can enable its onboard serial ports by enabling this option.
 
 	  If you choose M here, the module name will be 8250_pxa.
+
+config SERIAL_8250_LP8X4X
+	tristate "Support 16550A ports on ICP DAS LP-8x4x"
+	depends on OF && SERIAL_8250 && SERIAL_8250_MANY_PORTS && ARCH_PXA
+	select LP8X4X_IRQ
+	help
+	  In addition to serial ports on PXA270 SoC, LP-8x4x has 1 dual
+	  RS232/RS485 port, 1 RS485 port and 1 RS232 port.
+
+	  Say N here, unless you plan to run this kernel on a LP-8x4x system.
+
+	  If you choose M here, the module name will be 8250_lp8x4x.
diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile
index 7e54413..8bdbf40 100644
--- a/drivers/tty/serial/8250/Makefile
+++ b/drivers/tty/serial/8250/Makefile
@@ -18,6 +18,7 @@ obj-$(CONFIG_SERIAL_8250_ACCENT)	+= 8250_accent.o
 obj-$(CONFIG_SERIAL_8250_BOCA)		+= 8250_boca.o
 obj-$(CONFIG_SERIAL_8250_EXAR_ST16C554)	+= 8250_exar_st16c554.o
 obj-$(CONFIG_SERIAL_8250_HUB6)		+= 8250_hub6.o
+obj-$(CONFIG_SERIAL_8250_LP8X4X)	+= 8250_lp8x4x.o
 obj-$(CONFIG_SERIAL_8250_FSL)		+= 8250_fsl.o
 obj-$(CONFIG_SERIAL_8250_DW)		+= 8250_dw.o
 obj-$(CONFIG_SERIAL_8250_EM)		+= 8250_em.o
-- 
2.6.2

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH v5] serial: support for 16550A serial ports on LP-8x4x
  2015-12-15 21:04                   ` Sergei Ianovich
@ 2015-12-15 21:51                     ` Arnd Bergmann
  -1 siblings, 0 replies; 700+ messages in thread
From: Arnd Bergmann @ 2015-12-15 21:51 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: linux-kernel, Alan Cox, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Greg Kroah-Hartman, Jiri Slaby,
	Heikki Krogerus, Andy Shevchenko, Scott Wood, Masahiro Yamada,
	Sebastian Andrzej Siewior, Paul Burton, Joachim Eastwood,
	Mans Rullgard, Paul Gortmaker, Peter Hurley,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	open list:SERIAL DRIVERS

On Wednesday 16 December 2015 00:04:45 Sergei Ianovich wrote:
> index 0000000..5f9a4c1
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/serial/lp8x4x-serial.txt
> @@ -0,0 +1,35 @@
> +UART ports on ICP DAS LP-8x4x
> +
> +ICP DAS LP-8x4x contains three additional serial ports interfaced via
> +Analog Devices ADM213EA chips in addition to 3 serial ports on PXA CPU.
> +
> +Required properties:
> +- compatible : should be "icpdas,uart-lp8x4x"

Compatible strings should not include a 'x' wildcard like this, better use
the specific chip name.

Also, it sounds like you named them after the board vendor, which sounds
wrong as the vendor part of the compatible string should be the whoever
made that part (analog?)

> +- reg : should provide 16 byte man IO memory region and 1 byte region for
> +       termios
> +
> +- interrupts : should provide interrupt
> +
> +- interrupt-parent : should provide a link to interrupt controller either
> +                    explicitly or implicitly from a parent node

interrupt-parent should be an optional property, or you can leave it out,
as this is a standard property that can always be there when there is 
interrupts.

> +Examples (from pxa27x-lp8x4x.dts):
> +
> +               uart@9050 {

By convention, the name should be 'serial', not 'uart'.

	Arnd.

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

* Re: [PATCH v5] serial: support for 16550A serial ports on LP-8x4x
@ 2015-12-15 21:51                     ` Arnd Bergmann
  0 siblings, 0 replies; 700+ messages in thread
From: Arnd Bergmann @ 2015-12-15 21:51 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: linux-kernel, Alan Cox, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Greg Kroah-Hartman, Jiri Slaby,
	Heikki Krogerus, Andy Shevchenko, Scott Wood, Masahiro Yamada,
	Sebastian Andrzej Siewior, Paul Burton, Joachim Eastwood,
	Mans Rullgard, Paul Gortmaker, Peter Hurley,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS

On Wednesday 16 December 2015 00:04:45 Sergei Ianovich wrote:
> index 0000000..5f9a4c1
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/serial/lp8x4x-serial.txt
> @@ -0,0 +1,35 @@
> +UART ports on ICP DAS LP-8x4x
> +
> +ICP DAS LP-8x4x contains three additional serial ports interfaced via
> +Analog Devices ADM213EA chips in addition to 3 serial ports on PXA CPU.
> +
> +Required properties:
> +- compatible : should be "icpdas,uart-lp8x4x"

Compatible strings should not include a 'x' wildcard like this, better use
the specific chip name.

Also, it sounds like you named them after the board vendor, which sounds
wrong as the vendor part of the compatible string should be the whoever
made that part (analog?)

> +- reg : should provide 16 byte man IO memory region and 1 byte region for
> +       termios
> +
> +- interrupts : should provide interrupt
> +
> +- interrupt-parent : should provide a link to interrupt controller either
> +                    explicitly or implicitly from a parent node

interrupt-parent should be an optional property, or you can leave it out,
as this is a standard property that can always be there when there is 
interrupts.

> +Examples (from pxa27x-lp8x4x.dts):
> +
> +               uart@9050 {

By convention, the name should be 'serial', not 'uart'.

	Arnd.

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

* Re: [PATCH v5] serial: support for 16550A serial ports on LP-8x4x
  2015-12-15 21:51                     ` Arnd Bergmann
@ 2015-12-16  8:04                       ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2015-12-16  8:04 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: linux-kernel, Alan Cox, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Greg Kroah-Hartman, Jiri Slaby,
	Heikki Krogerus, Andy Shevchenko, Scott Wood, Masahiro Yamada,
	Sebastian Andrzej Siewior, Paul Burton, Joachim Eastwood,
	Mans Rullgard, Paul Gortmaker, Peter Hurley,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	open list:SERIAL DRIVERS

On Tue, 2015-12-15 at 22:51 +0100, Arnd Bergmann wrote:
> On Wednesday 16 December 2015 00:04:45 Sergei Ianovich wrote:
> > index 0000000..5f9a4c1
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/serial/lp8x4x-serial.txt
> > @@ -0,0 +1,35 @@
> > +UART ports on ICP DAS LP-8x4x
> > +
> > +ICP DAS LP-8x4x contains three additional serial ports interfaced
> > via
> > +Analog Devices ADM213EA chips in addition to 3 serial ports on PXA
> > CPU.
> > +
> > +Required properties:
> > +- compatible : should be "icpdas,uart-lp8x4x"
> 
> Compatible strings should not include a 'x' wildcard like this, better
> use
> the specific chip name.
> 
> Also, it sounds like you named them after the board vendor, which
> sounds
> wrong as the vendor part of the compatible string should be the
> whoever
> made that part (analog?)

The chips themselves are standard, they would work with 8250_core if
properly connected. However, they are not connected normally. Al least
some of their config pins are wired to a different address region. So
the driver is board-specific.

'x' wildcards in the name of the board seem important. There are devices
made by the same vendor without 8 or 4 in their name. Those devices
either are not shipped with linux or are base on a x86 platform.

Does this justify the choice of the compatible string?

> > +- reg : should provide 16 byte man IO memory region and 1 byte
> > region for
> > +       termios
> > +
> > +- interrupts : should provide interrupt
> > +
> > +- interrupt-parent : should provide a link to interrupt controller
> > either
> > +                    explicitly or implicitly from a parent node
> 
> interrupt-parent should be an optional property, or you can leave it
> out,
> as this is a standard property that can always be there when there is 
> interrupts.

ok

> > +Examples (from pxa27x-lp8x4x.dts):
> > +
> > +               uart@9050 {
> 
> By convention, the name should be 'serial', not 'uart'.

ok

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

* Re: [PATCH v5] serial: support for 16550A serial ports on LP-8x4x
@ 2015-12-16  8:04                       ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2015-12-16  8:04 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA, Alan Cox, Rob Herring,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	Greg Kroah-Hartman, Jiri Slaby, Heikki Krogerus, Andy Shevchenko,
	Scott Wood, Masahiro Yamada, Sebastian Andrzej Siewior,
	Paul Burton, Joachim Eastwood, Mans Rullgard, Paul Gortmaker,
	Peter Hurley,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS

On Tue, 2015-12-15 at 22:51 +0100, Arnd Bergmann wrote:
> On Wednesday 16 December 2015 00:04:45 Sergei Ianovich wrote:
> > index 0000000..5f9a4c1
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/serial/lp8x4x-serial.txt
> > @@ -0,0 +1,35 @@
> > +UART ports on ICP DAS LP-8x4x
> > +
> > +ICP DAS LP-8x4x contains three additional serial ports interfaced
> > via
> > +Analog Devices ADM213EA chips in addition to 3 serial ports on PXA
> > CPU.
> > +
> > +Required properties:
> > +- compatible : should be "icpdas,uart-lp8x4x"
> 
> Compatible strings should not include a 'x' wildcard like this, better
> use
> the specific chip name.
> 
> Also, it sounds like you named them after the board vendor, which
> sounds
> wrong as the vendor part of the compatible string should be the
> whoever
> made that part (analog?)

The chips themselves are standard, they would work with 8250_core if
properly connected. However, they are not connected normally. Al least
some of their config pins are wired to a different address region. So
the driver is board-specific.

'x' wildcards in the name of the board seem important. There are devices
made by the same vendor without 8 or 4 in their name. Those devices
either are not shipped with linux or are base on a x86 platform.

Does this justify the choice of the compatible string?

> > +- reg : should provide 16 byte man IO memory region and 1 byte
> > region for
> > +       termios
> > +
> > +- interrupts : should provide interrupt
> > +
> > +- interrupt-parent : should provide a link to interrupt controller
> > either
> > +                    explicitly or implicitly from a parent node
> 
> interrupt-parent should be an optional property, or you can leave it
> out,
> as this is a standard property that can always be there when there is 
> interrupts.

ok

> > +Examples (from pxa27x-lp8x4x.dts):
> > +
> > +               uart@9050 {
> 
> By convention, the name should be 'serial', not 'uart'.

ok
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH v5] serial: support for 16550A serial ports on LP-8x4x
  2015-12-16  8:04                       ` Sergei Ianovich
@ 2015-12-16 10:26                         ` Arnd Bergmann
  -1 siblings, 0 replies; 700+ messages in thread
From: Arnd Bergmann @ 2015-12-16 10:26 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: linux-kernel, Alan Cox, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Greg Kroah-Hartman, Jiri Slaby,
	Heikki Krogerus, Andy Shevchenko, Scott Wood, Masahiro Yamada,
	Sebastian Andrzej Siewior, Paul Burton, Joachim Eastwood,
	Mans Rullgard, Paul Gortmaker, Peter Hurley,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	open list:SERIAL DRIVERS

On Wednesday 16 December 2015 11:04:57 Sergei Ianovich wrote:
> On Tue, 2015-12-15 at 22:51 +0100, Arnd Bergmann wrote:
> > On Wednesday 16 December 2015 00:04:45 Sergei Ianovich wrote:
> > > index 0000000..5f9a4c1
> > > --- /dev/null
> > > +++ b/Documentation/devicetree/bindings/serial/lp8x4x-serial.txt
> > > @@ -0,0 +1,35 @@
> > > +UART ports on ICP DAS LP-8x4x
> > > +
> > > +ICP DAS LP-8x4x contains three additional serial ports interfaced
> > > via
> > > +Analog Devices ADM213EA chips in addition to 3 serial ports on PXA
> > > CPU.
> > > +
> > > +Required properties:
> > > +- compatible : should be "icpdas,uart-lp8x4x"
> > 
> > Compatible strings should not include a 'x' wildcard like this, better
> > use
> > the specific chip name.
> > 
> > Also, it sounds like you named them after the board vendor, which
> > sounds
> > wrong as the vendor part of the compatible string should be the
> > whoever
> > made that part (analog?)
> 
> The chips themselves are standard, they would work with 8250_core if
> properly connected. However, they are not connected normally. Al least
> some of their config pins are wired to a different address region. So
> the driver is board-specific.

Ok, I see.

> 'x' wildcards in the name of the board seem important. There are devices
> made by the same vendor without 8 or 4 in their name. Those devices
> either are not shipped with linux or are base on a x86 platform.
> 
> Does this justify the choice of the compatible string?

What I meant was that you should use the specific numbers of one machine,
precisely for the reason you list above.

If there is e.g. a LP-8040 and a LP-8141 today, and you use lp8x4x in
the compatible string to cover both, this will no longer work when the
vendor comes out with a LP8047 that is completely different.

Instead, what you should do is to use the compatible string to identify
one particular board (e.g. the first one that used this setup), and
then list the other ones as compatible with this. You can also add the
other board names in addition, e.g.

compatible = "icpdas,uart-lp8041", "icpdas,uart-lp8040";

for a lp8041 that is compatible with the lp8040. If it turns out later
that they are not entirely compatible, we can work around this in the
driver by checking for the lp8041 string that will be matched first, while
the lp8040 can be used by the driver to match the entire family of
compatible machines (no need to list every one in the driver).

	Arnd

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

* Re: [PATCH v5] serial: support for 16550A serial ports on LP-8x4x
@ 2015-12-16 10:26                         ` Arnd Bergmann
  0 siblings, 0 replies; 700+ messages in thread
From: Arnd Bergmann @ 2015-12-16 10:26 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: linux-kernel, Alan Cox, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Greg Kroah-Hartman, Jiri Slaby,
	Heikki Krogerus, Andy Shevchenko, Scott Wood, Masahiro Yamada,
	Sebastian Andrzej Siewior, Paul Burton, Joachim Eastwood,
	Mans Rullgard, Paul Gortmaker, Peter Hurley,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS

On Wednesday 16 December 2015 11:04:57 Sergei Ianovich wrote:
> On Tue, 2015-12-15 at 22:51 +0100, Arnd Bergmann wrote:
> > On Wednesday 16 December 2015 00:04:45 Sergei Ianovich wrote:
> > > index 0000000..5f9a4c1
> > > --- /dev/null
> > > +++ b/Documentation/devicetree/bindings/serial/lp8x4x-serial.txt
> > > @@ -0,0 +1,35 @@
> > > +UART ports on ICP DAS LP-8x4x
> > > +
> > > +ICP DAS LP-8x4x contains three additional serial ports interfaced
> > > via
> > > +Analog Devices ADM213EA chips in addition to 3 serial ports on PXA
> > > CPU.
> > > +
> > > +Required properties:
> > > +- compatible : should be "icpdas,uart-lp8x4x"
> > 
> > Compatible strings should not include a 'x' wildcard like this, better
> > use
> > the specific chip name.
> > 
> > Also, it sounds like you named them after the board vendor, which
> > sounds
> > wrong as the vendor part of the compatible string should be the
> > whoever
> > made that part (analog?)
> 
> The chips themselves are standard, they would work with 8250_core if
> properly connected. However, they are not connected normally. Al least
> some of their config pins are wired to a different address region. So
> the driver is board-specific.

Ok, I see.

> 'x' wildcards in the name of the board seem important. There are devices
> made by the same vendor without 8 or 4 in their name. Those devices
> either are not shipped with linux or are base on a x86 platform.
> 
> Does this justify the choice of the compatible string?

What I meant was that you should use the specific numbers of one machine,
precisely for the reason you list above.

If there is e.g. a LP-8040 and a LP-8141 today, and you use lp8x4x in
the compatible string to cover both, this will no longer work when the
vendor comes out with a LP8047 that is completely different.

Instead, what you should do is to use the compatible string to identify
one particular board (e.g. the first one that used this setup), and
then list the other ones as compatible with this. You can also add the
other board names in addition, e.g.

compatible = "icpdas,uart-lp8041", "icpdas,uart-lp8040";

for a lp8041 that is compatible with the lp8040. If it turns out later
that they are not entirely compatible, we can work around this in the
driver by checking for the lp8041 string that will be matched first, while
the lp8040 can be used by the driver to match the entire family of
compatible machines (no need to list every one in the driver).

	Arnd

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

* Re: [PATCH v5] arm: pxa: support ICP DAS LP-8x4x FPGA irq
  2015-12-15 19:26                     ` Sergei Ianovich
  (?)
@ 2015-12-16 11:54                     ` Marc Zyngier
  -1 siblings, 0 replies; 700+ messages in thread
From: Marc Zyngier @ 2015-12-16 11:54 UTC (permalink / raw)
  To: Sergei Ianovich, linux-kernel
  Cc: Linus Walleij, Arnd Bergmann, Thomas Gleixner, Jason Cooper,
	Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	open, list, OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS

On 15/12/15 19:26, Sergei Ianovich wrote:
> ICP DAS LP-8x4x contains FPGA chip. The chip functions as an interrupt
> source providing 16 additional interrupts among other things. The
> interrupt lines are muxed to a GPIO pin of a 2nd level PXA-GPIO
> interrupt controller. GPIO pins of the 2nd level controller are in turn
> muxed to a CPU interrupt line.
> 
> Until pxa is completely converted to device tree, it is impossible
> to use IRQCHIP_DECLARE() and the irqdomain needs to added manually.
> Drivers for the on-CPU IRQs and GPIO-IRQs are loaded using
> postcore_initcall(). We need to have all irq domain drivers loaded prior
> to DT parsing in order to allow normal initialization of IRQ resources
> with DT.
> 
> Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
> Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
> CC: Arnd Bergmann <arnd@arndb.de>
> ---
>    v4..v5
>    * constify struct of_device_id
>    * drop irq number from handler signature
> 
>    v3.2..v4
>    * move DTS binding to a different patch (8/21)
> 
>    v3.1..v3.2
>    fixes to apply Linus Walleij's "Reviewed-by":
>    * add kerneldoc comment for state container struct
>    * rename irq -> hwirq for clarity
>    * drop overzealous error checks from the hotpaths
> 
>    v3..v3.1
>    fixes according to Linus Walleij review comments:
>    * update commit message
>    * use state container instead of global variables
>    * get hardware irq nums from irq_data, don't calculate them
>    * use BIT() macro
>    * add defines for system irq register masks
>    * replace cycle control variable with break
>    * use better names for resource variables
>    * add a linear domain instead of a legacy one
>    * use irq_create_mapping() instead of irq_alloc_desc()
> 
>    v2..v3
>    * no changes (except number 09/16 -> 11/21)
> 
>    v0..v2
>    * extract irqchip and move to drivers/irqchip/
>    * use device tree
>    * use devm helpers where possible
> 
>  .../bindings/interrupt-controller/irq-lp8x4x.txt   |  49 +++++
>  drivers/irqchip/Kconfig                            |   5 +
>  drivers/irqchip/Makefile                           |   1 +
>  drivers/irqchip/irq-lp8x4x.c                       | 227 +++++++++++++++++++++
>  4 files changed, 282 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/interrupt-controller/irq-lp8x4x.txt
>  create mode 100644 drivers/irqchip/irq-lp8x4x.c
> 
> diff --git a/Documentation/devicetree/bindings/interrupt-controller/irq-lp8x4x.txt b/Documentation/devicetree/bindings/interrupt-controller/irq-lp8x4x.txt
> new file mode 100644
> index 0000000..c8940d2
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/interrupt-controller/irq-lp8x4x.txt
> @@ -0,0 +1,49 @@
> +ICP DAS LP-8x4x FPGA Interrupt Controller
> +
> +ICP DAS LP-8x4x contains FPGA chip. The chip functions as a interrupt
> +source providing 16 additional interrupts among other things.
> +
> +Required properties:
> +- compatible : should be "icpdas,irq-lp8x4x"
> +
> +- reg: physical base address of the controller and length of memory mapped
> +  region.
> +
> +- interrupt-controller : identifies the node as an interrupt controller
> +
> +- #interrupt-cells : should be 1
> +
> +- interrupts : should provide interrupt
> +
> +- interrupt-parent : should provide a link to interrupt controller either
> +		     explicitly and implicitly from a parent node
> +
> +Example:
> +
> +	fpga: fpga@17000006 {
> +		compatible = "icpdas,irq-lp8x4x";
> +		reg = <0x17000006 0x16>;
> +		interrupt-parent = <&gpio>;
> +		interrupts = <3 IRQ_TYPE_EDGE_RISING>;
> +		#interrupt-cells = <1>;
> +		interrupt-controller;
> +		status = "okay";
> +	};
> +
> +	uart@17009050 {
> +		compatible = "icpdas,uart-lp8x4x";
> +		reg = <0x17009050 0x10
> +		       0x17009030 0x02>;
> +		interrupt-parent = <&fpga>;
> +		interrupts = <13>;
> +		status = "okay";
> +	};
> +
> +	uart@17009060 {
> +		compatible = "icpdas,uart-lp8x4x";
> +		reg = <0x17009060 0x10
> +		       0x17009032 0x02>;
> +		interrupt-parent = <&fpga>;
> +		interrupts = <14>;
> +		status = "okay";
> +	};
> diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
> index 4d7294e..1de7361 100644
> --- a/drivers/irqchip/Kconfig
> +++ b/drivers/irqchip/Kconfig
> @@ -193,3 +193,8 @@ config IRQ_MXS
>  	def_bool y if MACH_ASM9260 || ARCH_MXS
>  	select IRQ_DOMAIN
>  	select STMP_DEVICE
> +
> +config LP8X4X_IRQ
> +	bool
> +	depends on OF && ARCH_PXA
> +	select IRQ_DOMAIN
> diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
> index 177f78f..ab9ca67 100644
> --- a/drivers/irqchip/Makefile
> +++ b/drivers/irqchip/Makefile
> @@ -55,3 +55,4 @@ obj-$(CONFIG_RENESAS_H8S_INTC)		+= irq-renesas-h8s.o
>  obj-$(CONFIG_ARCH_SA1100)		+= irq-sa11x0.o
>  obj-$(CONFIG_INGENIC_IRQ)		+= irq-ingenic.o
>  obj-$(CONFIG_IMX_GPCV2)			+= irq-imx-gpcv2.o
> +obj-$(CONFIG_LP8X4X_IRQ)		+= irq-lp8x4x.o
> diff --git a/drivers/irqchip/irq-lp8x4x.c b/drivers/irqchip/irq-lp8x4x.c
> new file mode 100644
> index 0000000..a03d925
> --- /dev/null
> +++ b/drivers/irqchip/irq-lp8x4x.c
> @@ -0,0 +1,227 @@
> +/*
> + *  linux/drivers/irqchip/irq-lp8x4x.c
> + *
> + *  Support for ICP DAS LP-8x4x FPGA irq
> + *  Copyright (C) 2013 Sergei Ianovich <ynvich@gmail.com>
> + *
> + *  This program is free software; you can redistribute it and/or modify
> + *  it under the terms of the GNU General Public License version 2 as
> + *  published by the Free Software Foundation or any later version.
> + */
> +#include <linux/interrupt.h>
> +#include <linux/io.h>
> +#include <linux/irq.h>
> +#include <linux/irqdomain.h>
> +#include <linux/irqchip/chained_irq.h>
> +#include <linux/of.h>
> +#include <linux/platform_device.h>
> +
> +#define EOI			0x00000000
> +#define INSINT			0x00000002
> +#define ENSYSINT		0x00000004
> +#define PRIMINT			0x00000006
> +#define PRIMINT_MASK		0xe0
> +#define SECOINT			0x00000008
> +#define SECOINT_MASK		0x1f
> +#define ENRISEINT		0x0000000A
> +#define CLRRISEINT		0x0000000C
> +#define ENHILVINT		0x0000000E
> +#define CLRHILVINT		0x00000010
> +#define ENFALLINT		0x00000012
> +#define CLRFALLINT		0x00000014
> +#define IRQ_MEM_SIZE		0x00000016
> +#define LP8X4X_NUM_IRQ_DEFAULT	16
> +
> +/**
> + * struct lp8x4x_irq_data - LP8X4X custom irq controller state container
> + * @base:               base IO memory address
> + * @irq_domain:         Interrupt translation domain; responsible for mapping
> + *                      between hwirq number and linux irq number
> + * @irq_sys_enabled:    mask keeping track of interrupts enabled in the
> + *                      register which vendor calls 'system'
> + * @irq_high_enabled:   mask keeping track of interrupts enabled in the
> + *                      register which vendor calls 'high'
> + *
> + * The structure implements State Container from
> + * Documentation/driver-model/design-patterns.txt
> + */
> +
> +struct lp8x4x_irq_data {
> +	void			*base;
> +	struct irq_domain	*domain;
> +	unsigned char		irq_sys_enabled;
> +	unsigned char		irq_high_enabled;
> +};
> +
> +static void lp8x4x_mask_irq(struct irq_data *d)
> +{
> +	unsigned mask;
> +	unsigned long hwirq = d->hwirq;
> +	struct lp8x4x_irq_data *host = irq_data_get_irq_chip_data(d);
> +
> +	if (hwirq < 8) {
> +		host->irq_high_enabled &= ~BIT(hwirq);
> +
> +		mask = ioread8(host->base + ENHILVINT);
> +		mask &= ~BIT(hwirq);
> +		iowrite8(mask, host->base + ENHILVINT);
> +	} else {
> +		hwirq -= 8;
> +		host->irq_sys_enabled &= ~BIT(hwirq);
> +
> +		mask = ioread8(host->base + ENSYSINT);
> +		mask &= ~BIT(hwirq);
> +		iowrite8(mask, host->base + ENSYSINT);

Any reason why this is using iowrite8/ioread8 instead of writeb/readb,
which are much more common on ARM?

> +	}
> +}
> +
> +static void lp8x4x_unmask_irq(struct irq_data *d)
> +{
> +	unsigned mask;
> +	unsigned long hwirq = d->hwirq;
> +	struct lp8x4x_irq_data *host = irq_data_get_irq_chip_data(d);
> +
> +	if (hwirq < 8) {
> +		host->irq_high_enabled |= BIT(hwirq);
> +		mask = ioread8(host->base + CLRHILVINT);
> +		mask |= BIT(hwirq);
> +		iowrite8(mask, host->base + CLRHILVINT);
> +
> +		mask = ioread8(host->base + ENHILVINT);
> +		mask |= BIT(hwirq);
> +		iowrite8(mask, host->base + ENHILVINT);
> +	} else {
> +		hwirq -= 8;
> +		host->irq_sys_enabled |= BIT(hwirq);
> +
> +		mask = ioread8(host->base + SECOINT);
> +		mask |= BIT(hwirq);
> +		iowrite8(mask, host->base + SECOINT);
> +
> +		mask = ioread8(host->base + ENSYSINT);
> +		mask |= BIT(hwirq);
> +		iowrite8(mask, host->base + ENSYSINT);
> +	}
> +}
> +
> +static struct irq_chip lp8x4x_irq_chip = {
> +	.name			= "FPGA",
> +	.irq_ack		= lp8x4x_mask_irq,
> +	.irq_mask		= lp8x4x_mask_irq,
> +	.irq_mask_ack		= lp8x4x_mask_irq,
> +	.irq_unmask		= lp8x4x_unmask_irq,
> +};
> +
> +static void lp8x4x_irq_handler(struct irq_desc *desc)
> +{
> +	int n;
> +	unsigned long mask;
> +	struct irq_chip *chip = irq_desc_get_chip(desc);
> +	struct lp8x4x_irq_data *host = irq_desc_get_handler_data(desc);
> +
> +	chained_irq_enter(chip, desc);
> +
> +	for (;;) {
> +		mask = ioread8(host->base + CLRHILVINT) & 0xff;
> +		mask |= (ioread8(host->base + SECOINT) & SECOINT_MASK) << 8;
> +		mask |= (ioread8(host->base + PRIMINT) & PRIMINT_MASK) << 8;

Huh. Fancy. It would be nice if one of PRIMINT_MASK and SECOINT_MASK was
defined in terms of the other. Something like

#define SECOINT_MASK	(~(u8)PRIMINT_MASK)

and a short comment so that I don't jump at seeing two  "<< 8" in a row.

> +		mask &= host->irq_high_enabled | (host->irq_sys_enabled << 8);

Is there any case where this actually filters pending interrupts? mask
and unmask seem to program a similar state in the HW...

> +		if (mask == 0)
> +			break;
> +		for_each_set_bit(n, &mask, BITS_PER_LONG)
> +			generic_handle_irq(irq_find_mapping(host->domain, n));
> +	}
> +
> +	iowrite8(0, host->base + EOI);
> +	chained_irq_exit(chip, desc);
> +}
> +
> +static int lp8x4x_irq_domain_map(struct irq_domain *d, unsigned int irq,
> +				 irq_hw_number_t hw)
> +{
> +	struct lp8x4x_irq_data *host = d->host_data;
> +	int err;
> +
> +	err = irq_set_chip_data(irq, host);
> +	if (err < 0)
> +		return err;
> +
> +	irq_set_chip_and_handler(irq, &lp8x4x_irq_chip, handle_level_irq);
> +	irq_set_probe(irq);
> +	return 0;
> +}
> +
> +const struct irq_domain_ops lp8x4x_irq_domain_ops = {
> +	.map	= lp8x4x_irq_domain_map,
> +	.xlate	= irq_domain_xlate_onecell,
> +};
> +
> +static const struct of_device_id lp8x4x_irq_dt_ids[] = {
> +	{ .compatible = "icpdas,irq-lp8x4x", },
> +	{}
> +};
> +
> +static int lp8x4x_irq_probe(struct platform_device *pdev)
> +{
> +	struct resource *res_mem, *res_irq;
> +	struct device_node *np = pdev->dev.of_node;
> +	struct lp8x4x_irq_data *host;
> +	int i, err;
> +
> +	res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
> +	if (!res_mem || !res_irq || resource_size(res_mem) < IRQ_MEM_SIZE)
> +		return -ENODEV;
> +
> +	host = devm_kzalloc(&pdev->dev, sizeof(*host), GFP_KERNEL);
> +	if (!host)
> +		return -ENODEV;
> +
> +	host->base = devm_ioremap_resource(&pdev->dev, res_mem);
> +	if (!host->base) {
> +		dev_err(&pdev->dev, "Failed to ioremap %p\n", host->base);
> +		return -EFAULT;
> +	}
> +
> +	host->domain = irq_domain_add_linear(np, LP8X4X_NUM_IRQ_DEFAULT,
> +				       &lp8x4x_irq_domain_ops, host);
> +	if (!host->domain) {
> +		dev_err(&pdev->dev, "Failed to add IRQ domain\n");
> +		return -ENOMEM;
> +	}
> +
> +	for (i = 0; i < LP8X4X_NUM_IRQ_DEFAULT; i++) {
> +		err = irq_create_mapping(host->domain, i);
> +		if (err < 0)
> +			dev_err(&pdev->dev, "Failed to map IRQ %i\n", i);
> +	}

I'd expect a comment here, stating that this will need to be removed
once PXA is converted to DT.

> +
> +	/* Initialize chip registers */
> +	iowrite8(0, host->base + CLRRISEINT);
> +	iowrite8(0, host->base + ENRISEINT);
> +	iowrite8(0, host->base + CLRFALLINT);
> +	iowrite8(0, host->base + ENFALLINT);
> +	iowrite8(0, host->base + CLRHILVINT);
> +	iowrite8(0, host->base + ENHILVINT);
> +	iowrite8(0, host->base + ENSYSINT);
> +	iowrite8(0, host->base + SECOINT);
> +
> +	irq_set_handler_data(res_irq->start, host);
> +	irq_set_chained_handler(res_irq->start, lp8x4x_irq_handler);
> +
> +	return 0;
> +}
> +
> +static struct platform_driver lp8x4x_irq_driver = {
> +	.probe		= lp8x4x_irq_probe,
> +	.driver		= {
> +		.name	= "irq-lp8x4x",
> +		.of_match_table = lp8x4x_irq_dt_ids,
> +	},
> +};
> +
> +static int __init lp8x4x_irq_init(void)
> +{
> +	return platform_driver_register(&lp8x4x_irq_driver);
> +}
> +postcore_initcall(lp8x4x_irq_init);
> 

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...

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

* Re: [PATCH v5] serial: support for 16550A serial ports on LP-8x4x
  2015-12-15 21:04                   ` Sergei Ianovich
@ 2015-12-17 14:50                     ` Andy Shevchenko
  -1 siblings, 0 replies; 700+ messages in thread
From: Andy Shevchenko @ 2015-12-17 14:50 UTC (permalink / raw)
  To: Sergei Ianovich, linux-kernel
  Cc: Alan Cox, Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell,
	Kumar Gala, Greg Kroah-Hartman, Jiri Slaby, Heikki Krogerus,
	Arnd Bergmann, Scott Wood, Masahiro Yamada,
	Sebastian Andrzej Siewior, Paul Burton, Joachim Eastwood,
	Mans Rullgard, Paul Gortmaker, Peter Hurley,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	open list:SERIAL DRIVERS

On Wed, 2015-12-16 at 00:04 +0300, Sergei Ianovich wrote:
> The patch adds support for 3 additional LP-8x4x built-in serial
> ports.
> 
> The device can also host up to 8 extension cards with 4 serial ports
> on each card for a total of 35 ports. However, I don't have
> the hardware to test extension cards, so they are not supported, yet.
> 

Few nitpicks, though everything looks okay.

> Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
> Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
> CC: Alan Cox <gnomes@lxorguk.ukuu.org.uk>
> ---
>    v4..v5
>    * constify struct of_device_id
>    * drop .owner from struct platform_driver
>    * rewrite set_termios() baud rate hadnling as suggested by Alan
> Cox
> 
>    v3..v4
>    * move DTS bindings to a different patch (8/21) as suggested by
>      Heikki Krogerus
> 
>    v2..v3
>    * no changes (except number 10/16 -> 12/21)
> 
>    v0..v2
>    * register platform driver instead of platform device
>    * use device tree
>    * use devm helpers where possible
> 
>  .../devicetree/bindings/serial/lp8x4x-serial.txt   |  35 +++++
>  drivers/tty/serial/8250/8250_lp8x4x.c              | 168
> +++++++++++++++++++++
>  drivers/tty/serial/8250/Kconfig                    |  12 ++
>  drivers/tty/serial/8250/Makefile                   |   1 +
>  4 files changed, 216 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/serial/lp8x4x-
> serial.txt
>  create mode 100644 drivers/tty/serial/8250/8250_lp8x4x.c
> 
> diff --git a/Documentation/devicetree/bindings/serial/lp8x4x-
> serial.txt b/Documentation/devicetree/bindings/serial/lp8x4x-
> serial.txt
> new file mode 100644
> index 0000000..5f9a4c1
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/serial/lp8x4x-serial.txt
> @@ -0,0 +1,35 @@
> +UART ports on ICP DAS LP-8x4x
> +
> +ICP DAS LP-8x4x contains three additional serial ports interfaced
> via
> +Analog Devices ADM213EA chips in addition to 3 serial ports on PXA
> CPU.
> +
> +Required properties:
> +- compatible : should be "icpdas,uart-lp8x4x"
> +
> +- reg : should provide 16 byte man IO memory region and 1 byte
> region for
> +	termios
> +
> +- interrupts : should provide interrupt
> +
> +- interrupt-parent : should provide a link to interrupt controller
> either
> +		     explicitly or implicitly from a parent node
> +
> +Examples (from pxa27x-lp8x4x.dts):
> +
> +		uart@9050 {
> +			compatible = "icpdas,uart-lp8x4x";
> +			reg = <0x9050 0x10
> +			       0x9030 0x02>;
> +			interrupt-parent = <&fpgairg>;
> +			interrupts = <13>;
> +			status = "okay";
> +		};
> +
> +		uart@9060 {
> +			compatible = "icpdas,uart-lp8x4x";
> +			reg = <0x9060 0x10
> +			       0x9032 0x02>;
> +			interrupt-parent = <&fpgairg>;
> +			interrupts = <14>;
> +			status = "okay";
> +		};
> diff --git a/drivers/tty/serial/8250/8250_lp8x4x.c
> b/drivers/tty/serial/8250/8250_lp8x4x.c
> new file mode 100644
> index 0000000..0e07220
> --- /dev/null
> +++ b/drivers/tty/serial/8250/8250_lp8x4x.c
> @@ -0,0 +1,168 @@
> +/*  linux/drivers/tty/serial/8250/8250_lp8x4x.c
> + *
> + *  Support for 16550A serial ports on ICP DAS LP-8x4x
> + *
> + *  Copyright (C) 2013 Sergei Ianovich <ynvich@gmail.com>
> + *
> + *  This program is free software; you can redistribute it and/or
> modify
> + *  it under the terms of the GNU General Public License version 2
> as
> + *  published by the Free Software Foundation.
> + */
> +#include <linux/init.h>
> +#include <linux/io.h>
> +#include <linux/irq.h>
> +#include <linux/module.h>
> +#include <linux/serial_8250.h>
> +#include <linux/of.h>
> +#include <linux/platform_device.h>
> +
> +struct lp8x4x_serial_data {
> +	int			line;
> +	void			*ios_mem;
> +};
> +
> +static void lp8x4x_serial_set_termios(struct uart_port *port,
> +		struct ktermios *termios, struct ktermios *old)
> +{
> +	unsigned int len;
> +	unsigned int baud;
> +	struct lp8x4x_serial_data *data = port->private_data;
> +
> +	serial8250_do_set_termios(port, termios, old);
> +
> +	switch (termios->c_cflag & CSIZE) {
> +	case CS5:
> +		len = 7;
> +		break;
> +	case CS6:
> +		len = 8;
> +		break;
> +	case CS7:
> +		len = 9;
> +		break;

> +	default:
> +	case CS8:

I would suggest to exchange those lines.

> +		len = 10;
> +		break;
> +	}
> +
> +	if (termios->c_cflag & CSTOPB)
> +		len++;
> +	if (termios->c_cflag & PARENB)
> +		len++;
> +	if (!(termios->c_cflag & PARODD))
> +		len++;
> +#ifdef CMSPAR
> +	if (termios->c_cflag & CMSPAR)
> +		len++;
> +#endif
> +
> +	len -= 9;
> +	len &= 3;
> +	len <<= 3;

> +	/*
> +	 * Ask the core to calculate the divisor for us.
> +	 */

Can it be one line?

> +	baud = tty_termios_baud_rate(termios);
> +
> +	switch (baud) {
> +	case 115200:
> +		len |= 7;
> +		break;
> +	case 57600:
> +		len |= 6;
> +		break;
> +	case 38400:
> +		len |= 5;
> +		break;
> +	case 19200:
> +		len |= 4;
> +		break;
> +	case 9600:
> +		len |= 3;
> +		break;
> +	case 4800:
> +		len |= 2;
> +		break;
> +	case 2400:
> +	default:
> +		len |= 1;
> +		break;
> +	};
> +	iowrite8(len, data->ios_mem);

writeb() ?

> +
> +}
> +
> +static const struct of_device_id lp8x4x_serial_dt_ids[] = {
> +	{ .compatible = "icpdas,uart-lp8x4x", },
> +	{}
> +};
> +MODULE_DEVICE_TABLE(of, lp8x4x_serial_dt_ids);
> +
> +static int lp8x4x_serial_probe(struct platform_device *pdev)
> +{
> +	struct uart_8250_port uart = {};
> +	struct lp8x4x_serial_data *data;
> +	struct resource *mmres, *mires, *irqres;
> +	int ret;
> +
> +	mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	mires = platform_get_resource(pdev, IORESOURCE_MEM, 1);
> +	irqres = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
> +	if (!mmres || !mires || !irqres)
> +		return -ENODEV;
> +
> +	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
> +	if (!data)
> +		return -ENOMEM;
> +
> +	data->ios_mem = devm_ioremap_resource(&pdev->dev, mires);
> +	if (!data->ios_mem)
> +		return -EFAULT;
> +
> +	uart.port.iotype = UPIO_MEM;
> +	uart.port.mapbase = mmres->start;
> +	uart.port.iobase = mmres->start;
> +	uart.port.regshift = 1;
> +	uart.port.irq = irqres->start;
> +	uart.port.flags = UPF_IOREMAP;
> +	uart.port.dev = &pdev->dev;
> +	uart.port.uartclk = 14745600;
> +	uart.port.set_termios = lp8x4x_serial_set_termios;
> +	uart.port.private_data = data;
> +
> +	ret = serial8250_register_8250_port(&uart);
> +	if (ret < 0)
> +		return ret;
> +
> +	data->line = ret;
> +
> +	platform_set_drvdata(pdev, data);
> +
> +	return 0;
> +}
> +
> +static int lp8x4x_serial_remove(struct platform_device *pdev)
> +{
> +	struct lp8x4x_serial_data *data =
> platform_get_drvdata(pdev);
> +
> +	serial8250_unregister_port(data->line);
> +
> +	return 0;
> +}
> +
> +static struct platform_driver lp8x4x_serial_driver = {
> +	.probe          = lp8x4x_serial_probe,
> +	.remove         = lp8x4x_serial_remove,
> +
> +	.driver		= {
> +		.name	= "uart-lp8x4x",
> +		.of_match_table = lp8x4x_serial_dt_ids,
> +	},
> +};
> +
> +module_platform_driver(lp8x4x_serial_driver);
> +
> +MODULE_AUTHOR("Sergei Ianovich");
> +MODULE_DESCRIPTION("8250 serial port module for LP-8x4x");
> +MODULE_LICENSE("GPL");
> diff --git a/drivers/tty/serial/8250/Kconfig
> b/drivers/tty/serial/8250/Kconfig
> index 48b6253..00eb6b0 100644
> --- a/drivers/tty/serial/8250/Kconfig
> +++ b/drivers/tty/serial/8250/Kconfig
> @@ -387,3 +387,15 @@ config SERIAL_8250_PXA
>  	  can enable its onboard serial ports by enabling this
> option.
>  
>  	  If you choose M here, the module name will be 8250_pxa.
> +
> +config SERIAL_8250_LP8X4X
> +	tristate "Support 16550A ports on ICP DAS LP-8x4x"
> +	depends on OF && SERIAL_8250 && SERIAL_8250_MANY_PORTS &&
> ARCH_PXA
> +	select LP8X4X_IRQ
> +	help
> +	  In addition to serial ports on PXA270 SoC, LP-8x4x has 1
> dual
> +	  RS232/RS485 port, 1 RS485 port and 1 RS232 port.
> +
> +	  Say N here, unless you plan to run this kernel on a LP-
> 8x4x system.
> +
> +	  If you choose M here, the module name will be 8250_lp8x4x.
> diff --git a/drivers/tty/serial/8250/Makefile
> b/drivers/tty/serial/8250/Makefile
> index 7e54413..8bdbf40 100644
> --- a/drivers/tty/serial/8250/Makefile
> +++ b/drivers/tty/serial/8250/Makefile
> @@ -18,6 +18,7 @@ obj-$(CONFIG_SERIAL_8250_ACCENT)	+=
> 8250_accent.o
>  obj-$(CONFIG_SERIAL_8250_BOCA)		+= 8250_boca.o
>  obj-$(CONFIG_SERIAL_8250_EXAR_ST16C554)	+=
> 8250_exar_st16c554.o
>  obj-$(CONFIG_SERIAL_8250_HUB6)		+= 8250_hub6.o
> +obj-$(CONFIG_SERIAL_8250_LP8X4X)	+= 8250_lp8x4x.o
>  obj-$(CONFIG_SERIAL_8250_FSL)		+= 8250_fsl.o
>  obj-$(CONFIG_SERIAL_8250_DW)		+= 8250_dw.o
>  obj-$(CONFIG_SERIAL_8250_EM)		+= 8250_em.o

-- 
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Intel Finland Oy


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

* Re: [PATCH v5] serial: support for 16550A serial ports on LP-8x4x
@ 2015-12-17 14:50                     ` Andy Shevchenko
  0 siblings, 0 replies; 700+ messages in thread
From: Andy Shevchenko @ 2015-12-17 14:50 UTC (permalink / raw)
  To: Sergei Ianovich, linux-kernel
  Cc: Alan Cox, Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell,
	Kumar Gala, Greg Kroah-Hartman, Jiri Slaby, Heikki Krogerus,
	Arnd Bergmann, Scott Wood, Masahiro Yamada,
	Sebastian Andrzej Siewior, Paul Burton, Joachim Eastwood,
	Mans Rullgard, Paul Gortmaker, Peter Hurley,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	open list:SERIAL DRIVERS

On Wed, 2015-12-16 at 00:04 +0300, Sergei Ianovich wrote:
> The patch adds support for 3 additional LP-8x4x built-in serial
> ports.
> 
> The device can also host up to 8 extension cards with 4 serial ports
> on each card for a total of 35 ports. However, I don't have
> the hardware to test extension cards, so they are not supported, yet.
> 

Few nitpicks, though everything looks okay.

> Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
> Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
> CC: Alan Cox <gnomes@lxorguk.ukuu.org.uk>
> ---
>    v4..v5
>    * constify struct of_device_id
>    * drop .owner from struct platform_driver
>    * rewrite set_termios() baud rate hadnling as suggested by Alan
> Cox
> 
>    v3..v4
>    * move DTS bindings to a different patch (8/21) as suggested by
>      Heikki Krogerus
> 
>    v2..v3
>    * no changes (except number 10/16 -> 12/21)
> 
>    v0..v2
>    * register platform driver instead of platform device
>    * use device tree
>    * use devm helpers where possible
> 
>  .../devicetree/bindings/serial/lp8x4x-serial.txt   |  35 +++++
>  drivers/tty/serial/8250/8250_lp8x4x.c              | 168
> +++++++++++++++++++++
>  drivers/tty/serial/8250/Kconfig                    |  12 ++
>  drivers/tty/serial/8250/Makefile                   |   1 +
>  4 files changed, 216 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/serial/lp8x4x-
> serial.txt
>  create mode 100644 drivers/tty/serial/8250/8250_lp8x4x.c
> 
> diff --git a/Documentation/devicetree/bindings/serial/lp8x4x-
> serial.txt b/Documentation/devicetree/bindings/serial/lp8x4x-
> serial.txt
> new file mode 100644
> index 0000000..5f9a4c1
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/serial/lp8x4x-serial.txt
> @@ -0,0 +1,35 @@
> +UART ports on ICP DAS LP-8x4x
> +
> +ICP DAS LP-8x4x contains three additional serial ports interfaced
> via
> +Analog Devices ADM213EA chips in addition to 3 serial ports on PXA
> CPU.
> +
> +Required properties:
> +- compatible : should be "icpdas,uart-lp8x4x"
> +
> +- reg : should provide 16 byte man IO memory region and 1 byte
> region for
> +	termios
> +
> +- interrupts : should provide interrupt
> +
> +- interrupt-parent : should provide a link to interrupt controller
> either
> +		     explicitly or implicitly from a parent node
> +
> +Examples (from pxa27x-lp8x4x.dts):
> +
> +		uart@9050 {
> +			compatible = "icpdas,uart-lp8x4x";
> +			reg = <0x9050 0x10
> +			       0x9030 0x02>;
> +			interrupt-parent = <&fpgairg>;
> +			interrupts = <13>;
> +			status = "okay";
> +		};
> +
> +		uart@9060 {
> +			compatible = "icpdas,uart-lp8x4x";
> +			reg = <0x9060 0x10
> +			       0x9032 0x02>;
> +			interrupt-parent = <&fpgairg>;
> +			interrupts = <14>;
> +			status = "okay";
> +		};
> diff --git a/drivers/tty/serial/8250/8250_lp8x4x.c
> b/drivers/tty/serial/8250/8250_lp8x4x.c
> new file mode 100644
> index 0000000..0e07220
> --- /dev/null
> +++ b/drivers/tty/serial/8250/8250_lp8x4x.c
> @@ -0,0 +1,168 @@
> +/*  linux/drivers/tty/serial/8250/8250_lp8x4x.c
> + *
> + *  Support for 16550A serial ports on ICP DAS LP-8x4x
> + *
> + *  Copyright (C) 2013 Sergei Ianovich <ynvich@gmail.com>
> + *
> + *  This program is free software; you can redistribute it and/or
> modify
> + *  it under the terms of the GNU General Public License version 2
> as
> + *  published by the Free Software Foundation.
> + */
> +#include <linux/init.h>
> +#include <linux/io.h>
> +#include <linux/irq.h>
> +#include <linux/module.h>
> +#include <linux/serial_8250.h>
> +#include <linux/of.h>
> +#include <linux/platform_device.h>
> +
> +struct lp8x4x_serial_data {
> +	int			line;
> +	void			*ios_mem;
> +};
> +
> +static void lp8x4x_serial_set_termios(struct uart_port *port,
> +		struct ktermios *termios, struct ktermios *old)
> +{
> +	unsigned int len;
> +	unsigned int baud;
> +	struct lp8x4x_serial_data *data = port->private_data;
> +
> +	serial8250_do_set_termios(port, termios, old);
> +
> +	switch (termios->c_cflag & CSIZE) {
> +	case CS5:
> +		len = 7;
> +		break;
> +	case CS6:
> +		len = 8;
> +		break;
> +	case CS7:
> +		len = 9;
> +		break;

> +	default:
> +	case CS8:

I would suggest to exchange those lines.

> +		len = 10;
> +		break;
> +	}
> +
> +	if (termios->c_cflag & CSTOPB)
> +		len++;
> +	if (termios->c_cflag & PARENB)
> +		len++;
> +	if (!(termios->c_cflag & PARODD))
> +		len++;
> +#ifdef CMSPAR
> +	if (termios->c_cflag & CMSPAR)
> +		len++;
> +#endif
> +
> +	len -= 9;
> +	len &= 3;
> +	len <<= 3;

> +	/*
> +	 * Ask the core to calculate the divisor for us.
> +	 */

Can it be one line?

> +	baud = tty_termios_baud_rate(termios);
> +
> +	switch (baud) {
> +	case 115200:
> +		len |= 7;
> +		break;
> +	case 57600:
> +		len |= 6;
> +		break;
> +	case 38400:
> +		len |= 5;
> +		break;
> +	case 19200:
> +		len |= 4;
> +		break;
> +	case 9600:
> +		len |= 3;
> +		break;
> +	case 4800:
> +		len |= 2;
> +		break;
> +	case 2400:
> +	default:
> +		len |= 1;
> +		break;
> +	};
> +	iowrite8(len, data->ios_mem);

writeb() ?

> +
> +}
> +
> +static const struct of_device_id lp8x4x_serial_dt_ids[] = {
> +	{ .compatible = "icpdas,uart-lp8x4x", },
> +	{}
> +};
> +MODULE_DEVICE_TABLE(of, lp8x4x_serial_dt_ids);
> +
> +static int lp8x4x_serial_probe(struct platform_device *pdev)
> +{
> +	struct uart_8250_port uart = {};
> +	struct lp8x4x_serial_data *data;
> +	struct resource *mmres, *mires, *irqres;
> +	int ret;
> +
> +	mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	mires = platform_get_resource(pdev, IORESOURCE_MEM, 1);
> +	irqres = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
> +	if (!mmres || !mires || !irqres)
> +		return -ENODEV;
> +
> +	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
> +	if (!data)
> +		return -ENOMEM;
> +
> +	data->ios_mem = devm_ioremap_resource(&pdev->dev, mires);
> +	if (!data->ios_mem)
> +		return -EFAULT;
> +
> +	uart.port.iotype = UPIO_MEM;
> +	uart.port.mapbase = mmres->start;
> +	uart.port.iobase = mmres->start;
> +	uart.port.regshift = 1;
> +	uart.port.irq = irqres->start;
> +	uart.port.flags = UPF_IOREMAP;
> +	uart.port.dev = &pdev->dev;
> +	uart.port.uartclk = 14745600;
> +	uart.port.set_termios = lp8x4x_serial_set_termios;
> +	uart.port.private_data = data;
> +
> +	ret = serial8250_register_8250_port(&uart);
> +	if (ret < 0)
> +		return ret;
> +
> +	data->line = ret;
> +
> +	platform_set_drvdata(pdev, data);
> +
> +	return 0;
> +}
> +
> +static int lp8x4x_serial_remove(struct platform_device *pdev)
> +{
> +	struct lp8x4x_serial_data *data =
> platform_get_drvdata(pdev);
> +
> +	serial8250_unregister_port(data->line);
> +
> +	return 0;
> +}
> +
> +static struct platform_driver lp8x4x_serial_driver = {
> +	.probe          = lp8x4x_serial_probe,
> +	.remove         = lp8x4x_serial_remove,
> +
> +	.driver		= {
> +		.name	= "uart-lp8x4x",
> +		.of_match_table = lp8x4x_serial_dt_ids,
> +	},
> +};
> +
> +module_platform_driver(lp8x4x_serial_driver);
> +
> +MODULE_AUTHOR("Sergei Ianovich");
> +MODULE_DESCRIPTION("8250 serial port module for LP-8x4x");
> +MODULE_LICENSE("GPL");
> diff --git a/drivers/tty/serial/8250/Kconfig
> b/drivers/tty/serial/8250/Kconfig
> index 48b6253..00eb6b0 100644
> --- a/drivers/tty/serial/8250/Kconfig
> +++ b/drivers/tty/serial/8250/Kconfig
> @@ -387,3 +387,15 @@ config SERIAL_8250_PXA
>  	  can enable its onboard serial ports by enabling this
> option.
>  
>  	  If you choose M here, the module name will be 8250_pxa.
> +
> +config SERIAL_8250_LP8X4X
> +	tristate "Support 16550A ports on ICP DAS LP-8x4x"
> +	depends on OF && SERIAL_8250 && SERIAL_8250_MANY_PORTS &&
> ARCH_PXA
> +	select LP8X4X_IRQ
> +	help
> +	  In addition to serial ports on PXA270 SoC, LP-8x4x has 1
> dual
> +	  RS232/RS485 port, 1 RS485 port and 1 RS232 port.
> +
> +	  Say N here, unless you plan to run this kernel on a LP-
> 8x4x system.
> +
> +	  If you choose M here, the module name will be 8250_lp8x4x.
> diff --git a/drivers/tty/serial/8250/Makefile
> b/drivers/tty/serial/8250/Makefile
> index 7e54413..8bdbf40 100644
> --- a/drivers/tty/serial/8250/Makefile
> +++ b/drivers/tty/serial/8250/Makefile
> @@ -18,6 +18,7 @@ obj-$(CONFIG_SERIAL_8250_ACCENT)	+=
> 8250_accent.o
>  obj-$(CONFIG_SERIAL_8250_BOCA)		+= 8250_boca.o
>  obj-$(CONFIG_SERIAL_8250_EXAR_ST16C554)	+=
> 8250_exar_st16c554.o
>  obj-$(CONFIG_SERIAL_8250_HUB6)		+= 8250_hub6.o
> +obj-$(CONFIG_SERIAL_8250_LP8X4X)	+= 8250_lp8x4x.o
>  obj-$(CONFIG_SERIAL_8250_FSL)		+= 8250_fsl.o
>  obj-$(CONFIG_SERIAL_8250_DW)		+= 8250_dw.o
>  obj-$(CONFIG_SERIAL_8250_EM)		+= 8250_em.o

-- 
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Intel Finland Oy

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

* Re: [PATCH v5] arm: pxa: support ICP DAS LP-8x4x FPGA irq
  2015-12-15 19:26                     ` Sergei Ianovich
@ 2015-12-19  4:20                       ` Rob Herring
  -1 siblings, 0 replies; 700+ messages in thread
From: Rob Herring @ 2015-12-19  4:20 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: linux-kernel, Linus Walleij, Arnd Bergmann, Thomas Gleixner,
	Jason Cooper, Marc Zyngier, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS

On Tue, Dec 15, 2015 at 10:26:21PM +0300, Sergei Ianovich wrote:
> ICP DAS LP-8x4x contains FPGA chip. The chip functions as an interrupt
> source providing 16 additional interrupts among other things. The
> interrupt lines are muxed to a GPIO pin of a 2nd level PXA-GPIO
> interrupt controller. GPIO pins of the 2nd level controller are in turn
> muxed to a CPU interrupt line.
> 
> Until pxa is completely converted to device tree, it is impossible
> to use IRQCHIP_DECLARE() and the irqdomain needs to added manually.
> Drivers for the on-CPU IRQs and GPIO-IRQs are loaded using
> postcore_initcall(). We need to have all irq domain drivers loaded prior
> to DT parsing in order to allow normal initialization of IRQ resources
> with DT.
> 
> Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
> Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
> CC: Arnd Bergmann <arnd@arndb.de>
> ---
>    v4..v5
>    * constify struct of_device_id
>    * drop irq number from handler signature
> 
>    v3.2..v4
>    * move DTS binding to a different patch (8/21)
> 
>    v3.1..v3.2
>    fixes to apply Linus Walleij's "Reviewed-by":
>    * add kerneldoc comment for state container struct
>    * rename irq -> hwirq for clarity
>    * drop overzealous error checks from the hotpaths
> 
>    v3..v3.1
>    fixes according to Linus Walleij review comments:
>    * update commit message
>    * use state container instead of global variables
>    * get hardware irq nums from irq_data, don't calculate them
>    * use BIT() macro
>    * add defines for system irq register masks
>    * replace cycle control variable with break
>    * use better names for resource variables
>    * add a linear domain instead of a legacy one
>    * use irq_create_mapping() instead of irq_alloc_desc()
> 
>    v2..v3
>    * no changes (except number 09/16 -> 11/21)
> 
>    v0..v2
>    * extract irqchip and move to drivers/irqchip/
>    * use device tree
>    * use devm helpers where possible
> 
>  .../bindings/interrupt-controller/irq-lp8x4x.txt   |  49 +++++
>  drivers/irqchip/Kconfig                            |   5 +
>  drivers/irqchip/Makefile                           |   1 +
>  drivers/irqchip/irq-lp8x4x.c                       | 227 +++++++++++++++++++++
>  4 files changed, 282 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/interrupt-controller/irq-lp8x4x.txt
>  create mode 100644 drivers/irqchip/irq-lp8x4x.c
> 
> diff --git a/Documentation/devicetree/bindings/interrupt-controller/irq-lp8x4x.txt b/Documentation/devicetree/bindings/interrupt-controller/irq-lp8x4x.txt
> new file mode 100644
> index 0000000..c8940d2
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/interrupt-controller/irq-lp8x4x.txt
> @@ -0,0 +1,49 @@
> +ICP DAS LP-8x4x FPGA Interrupt Controller
> +
> +ICP DAS LP-8x4x contains FPGA chip. The chip functions as a interrupt
> +source providing 16 additional interrupts among other things.
> +
> +Required properties:
> +- compatible : should be "icpdas,irq-lp8x4x"
> +
> +- reg: physical base address of the controller and length of memory mapped
> +  region.
> +
> +- interrupt-controller : identifies the node as an interrupt controller
> +
> +- #interrupt-cells : should be 1
> +
> +- interrupts : should provide interrupt
> +
> +- interrupt-parent : should provide a link to interrupt controller either
> +		     explicitly and implicitly from a parent node
> +
> +Example:
> +
> +	fpga: fpga@17000006 {

Nothing else in the fpga? In any case, this node should be named 
interrupt-controller@17000006.

> +		compatible = "icpdas,irq-lp8x4x";

As pointed out in the uart binding, don't use wildcards here.

> +		reg = <0x17000006 0x16>;
> +		interrupt-parent = <&gpio>;
> +		interrupts = <3 IRQ_TYPE_EDGE_RISING>;
> +		#interrupt-cells = <1>;
> +		interrupt-controller;
> +		status = "okay";
> +	};
> +
> +	uart@17009050 {
> +		compatible = "icpdas,uart-lp8x4x";
> +		reg = <0x17009050 0x10
> +		       0x17009030 0x02>;
> +		interrupt-parent = <&fpga>;
> +		interrupts = <13>;
> +		status = "okay";
> +	};

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

* Re: [PATCH v5] arm: pxa: support ICP DAS LP-8x4x FPGA irq
@ 2015-12-19  4:20                       ` Rob Herring
  0 siblings, 0 replies; 700+ messages in thread
From: Rob Herring @ 2015-12-19  4:20 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: linux-kernel, Linus Walleij, Arnd Bergmann, Thomas Gleixner,
	Jason Cooper, Marc Zyngier, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS

On Tue, Dec 15, 2015 at 10:26:21PM +0300, Sergei Ianovich wrote:
> ICP DAS LP-8x4x contains FPGA chip. The chip functions as an interrupt
> source providing 16 additional interrupts among other things. The
> interrupt lines are muxed to a GPIO pin of a 2nd level PXA-GPIO
> interrupt controller. GPIO pins of the 2nd level controller are in turn
> muxed to a CPU interrupt line.
> 
> Until pxa is completely converted to device tree, it is impossible
> to use IRQCHIP_DECLARE() and the irqdomain needs to added manually.
> Drivers for the on-CPU IRQs and GPIO-IRQs are loaded using
> postcore_initcall(). We need to have all irq domain drivers loaded prior
> to DT parsing in order to allow normal initialization of IRQ resources
> with DT.
> 
> Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
> Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
> CC: Arnd Bergmann <arnd@arndb.de>
> ---
>    v4..v5
>    * constify struct of_device_id
>    * drop irq number from handler signature
> 
>    v3.2..v4
>    * move DTS binding to a different patch (8/21)
> 
>    v3.1..v3.2
>    fixes to apply Linus Walleij's "Reviewed-by":
>    * add kerneldoc comment for state container struct
>    * rename irq -> hwirq for clarity
>    * drop overzealous error checks from the hotpaths
> 
>    v3..v3.1
>    fixes according to Linus Walleij review comments:
>    * update commit message
>    * use state container instead of global variables
>    * get hardware irq nums from irq_data, don't calculate them
>    * use BIT() macro
>    * add defines for system irq register masks
>    * replace cycle control variable with break
>    * use better names for resource variables
>    * add a linear domain instead of a legacy one
>    * use irq_create_mapping() instead of irq_alloc_desc()
> 
>    v2..v3
>    * no changes (except number 09/16 -> 11/21)
> 
>    v0..v2
>    * extract irqchip and move to drivers/irqchip/
>    * use device tree
>    * use devm helpers where possible
> 
>  .../bindings/interrupt-controller/irq-lp8x4x.txt   |  49 +++++
>  drivers/irqchip/Kconfig                            |   5 +
>  drivers/irqchip/Makefile                           |   1 +
>  drivers/irqchip/irq-lp8x4x.c                       | 227 +++++++++++++++++++++
>  4 files changed, 282 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/interrupt-controller/irq-lp8x4x.txt
>  create mode 100644 drivers/irqchip/irq-lp8x4x.c
> 
> diff --git a/Documentation/devicetree/bindings/interrupt-controller/irq-lp8x4x.txt b/Documentation/devicetree/bindings/interrupt-controller/irq-lp8x4x.txt
> new file mode 100644
> index 0000000..c8940d2
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/interrupt-controller/irq-lp8x4x.txt
> @@ -0,0 +1,49 @@
> +ICP DAS LP-8x4x FPGA Interrupt Controller
> +
> +ICP DAS LP-8x4x contains FPGA chip. The chip functions as a interrupt
> +source providing 16 additional interrupts among other things.
> +
> +Required properties:
> +- compatible : should be "icpdas,irq-lp8x4x"
> +
> +- reg: physical base address of the controller and length of memory mapped
> +  region.
> +
> +- interrupt-controller : identifies the node as an interrupt controller
> +
> +- #interrupt-cells : should be 1
> +
> +- interrupts : should provide interrupt
> +
> +- interrupt-parent : should provide a link to interrupt controller either
> +		     explicitly and implicitly from a parent node
> +
> +Example:
> +
> +	fpga: fpga@17000006 {

Nothing else in the fpga? In any case, this node should be named 
interrupt-controller@17000006.

> +		compatible = "icpdas,irq-lp8x4x";

As pointed out in the uart binding, don't use wildcards here.

> +		reg = <0x17000006 0x16>;
> +		interrupt-parent = <&gpio>;
> +		interrupts = <3 IRQ_TYPE_EDGE_RISING>;
> +		#interrupt-cells = <1>;
> +		interrupt-controller;
> +		status = "okay";
> +	};
> +
> +	uart@17009050 {
> +		compatible = "icpdas,uart-lp8x4x";
> +		reg = <0x17009050 0x10
> +		       0x17009030 0x02>;
> +		interrupt-parent = <&fpga>;
> +		interrupts = <13>;
> +		status = "okay";
> +	};

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

* Re: [PATCH v5] arm: pxa: support ICP DAS LP-8x4x FPGA irq
       [not found]                     ` <20151219035802.GA28424@rob-hp-laptop>
@ 2015-12-19  7:03                         ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2015-12-19  7:03 UTC (permalink / raw)
  To: Rob Herring
  Cc: linux-kernel, Linus Walleij, Arnd Bergmann, Thomas Gleixner,
	Jason Cooper, Marc Zyngier, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS

On Fri, 2015-12-18 at 21:58 -0600, Rob Herring wrote:
> On Tue, Dec 15, 2015 at 10:26:21PM +0300, Sergei Ianovich wrote:
> > +Example:
> > +
> > +	fpga: fpga@17000006 {
> 
> Nothing else in the fpga? In any case, this node should be named 
> interrupt-controller@17000006.
> 
> > +		compatible = "icpdas,irq-lp8x4x";
> 
> As pointed out in the uart binding, don't use wildcards here.
> 
> > +		reg = <0x17000006 0x16>;
> > +		interrupt-parent = <&gpio>;
> > +		interrupts = <3 IRQ_TYPE_EDGE_RISING>;
> > +		#interrupt-cells = <1>;
> > +		interrupt-controller;
> > +		status = "okay";
> > +	};
> > +
> > +	uart@17009050 {
> > +		compatible = "icpdas,uart-lp8x4x";
> > +		reg = <0x17009050 0x10
> > +		       0x17009030 0x02>;
> > +		interrupt-parent = <&fpga>;
> > +		interrupts = <13>;
> > +		status = "okay";
> > +	};

That was just an example. The actual binding in LP-8x4x is bigger:
                fpga@5 {
                        compatible = "simple-bus";
                        #address-cells = <1>;
                        #size-cells = <1>;
                        ranges = <0 5 0x3000000 0x10000>;
                        interrupt-parent = <&fpgairq>;

                        rtc@901c {
                                compatible = "dallas,rtc-ds1302";
                                reg = <0x901c 0x1>;
                                status = "okay";
                        };

                        sram@a000 {
                                compatible = "icpdas,sram-lp8x4x";
                                reg = <0xa000 0x1000
                                       0x901e 0x1>;

                                partitions {
                                        #address-cells = <1>;
                                        #size-cells = <1>;
                                };
                        };

                        fpgairq: irq@9006 {
                                compatible = "icpdas,irq-lp8x4x";
                                reg = <0x9006 0x16>;
                                interrupt-parent = <&gpio>;
                                interrupts = <3 IRQ_TYPE_EDGE_FALLING>;
                                #interrupt-cells = <1>;
                                interrupt-controller;
                                status = "okay";
                        };

                        uart@9050 {
                                compatible = "icpdas,uart-lp8x4x";
                                reg = <0x9050 0x10
                                       0x9030 0x02>;
                                interrupts = <13>;
                                status = "okay";
                        };

                        uart@9060 {
                                compatible = "icpdas,uart-lp8x4x";
                                reg = <0x9060 0x10
                                       0x9032 0x02>;
                                interrupts = <14>;
                                status = "okay";
                        };

                        uart@9070 {
                                compatible = "icpdas,uart-lp8x4x";
                                reg = <0x9070 0x10
                                       0x9034 0x02>;
                                interrupts = <15>;
                                status = "okay";
                        };

                        backplane {
                                compatible = "icpdas,backplane-lp8x4x";
                                reg = <0x0 0x2
                                       0x1000 0x10
                                       0x2000 0x10
                                       0x3000 0x10
                                       0x4000 0x10
                                       0x5000 0x10
                                       0x6000 0x10
                                       0x7000 0x10
                                       0x8000 0x10
                                       0x9002 0x2
                                       0x9004 0x2
                                       0x9046 0x2>;
                                eeprom-gpios = <&gpio 4 0>;
                        };
                };

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

* Re: [PATCH v5] arm: pxa: support ICP DAS LP-8x4x FPGA irq
@ 2015-12-19  7:03                         ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2015-12-19  7:03 UTC (permalink / raw)
  To: Rob Herring
  Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA, Linus Walleij,
	Arnd Bergmann, Thomas Gleixner, Jason Cooper, Marc Zyngier,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS

On Fri, 2015-12-18 at 21:58 -0600, Rob Herring wrote:
> On Tue, Dec 15, 2015 at 10:26:21PM +0300, Sergei Ianovich wrote:
> > +Example:
> > +
> > +	fpga: fpga@17000006 {
> 
> Nothing else in the fpga? In any case, this node should be named 
> interrupt-controller@17000006.
> 
> > +		compatible = "icpdas,irq-lp8x4x";
> 
> As pointed out in the uart binding, don't use wildcards here.
> 
> > +		reg = <0x17000006 0x16>;
> > +		interrupt-parent = <&gpio>;
> > +		interrupts = <3 IRQ_TYPE_EDGE_RISING>;
> > +		#interrupt-cells = <1>;
> > +		interrupt-controller;
> > +		status = "okay";
> > +	};
> > +
> > +	uart@17009050 {
> > +		compatible = "icpdas,uart-lp8x4x";
> > +		reg = <0x17009050 0x10
> > +		       0x17009030 0x02>;
> > +		interrupt-parent = <&fpga>;
> > +		interrupts = <13>;
> > +		status = "okay";
> > +	};

That was just an example. The actual binding in LP-8x4x is bigger:
                fpga@5 {
                        compatible = "simple-bus";
                        #address-cells = <1>;
                        #size-cells = <1>;
                        ranges = <0 5 0x3000000 0x10000>;
                        interrupt-parent = <&fpgairq>;

                        rtc@901c {
                                compatible = "dallas,rtc-ds1302";
                                reg = <0x901c 0x1>;
                                status = "okay";
                        };

                        sram@a000 {
                                compatible = "icpdas,sram-lp8x4x";
                                reg = <0xa000 0x1000
                                       0x901e 0x1>;

                                partitions {
                                        #address-cells = <1>;
                                        #size-cells = <1>;
                                };
                        };

                        fpgairq: irq@9006 {
                                compatible = "icpdas,irq-lp8x4x";
                                reg = <0x9006 0x16>;
                                interrupt-parent = <&gpio>;
                                interrupts = <3 IRQ_TYPE_EDGE_FALLING>;
                                #interrupt-cells = <1>;
                                interrupt-controller;
                                status = "okay";
                        };

                        uart@9050 {
                                compatible = "icpdas,uart-lp8x4x";
                                reg = <0x9050 0x10
                                       0x9030 0x02>;
                                interrupts = <13>;
                                status = "okay";
                        };

                        uart@9060 {
                                compatible = "icpdas,uart-lp8x4x";
                                reg = <0x9060 0x10
                                       0x9032 0x02>;
                                interrupts = <14>;
                                status = "okay";
                        };

                        uart@9070 {
                                compatible = "icpdas,uart-lp8x4x";
                                reg = <0x9070 0x10
                                       0x9034 0x02>;
                                interrupts = <15>;
                                status = "okay";
                        };

                        backplane {
                                compatible = "icpdas,backplane-lp8x4x";
                                reg = <0x0 0x2
                                       0x1000 0x10
                                       0x2000 0x10
                                       0x3000 0x10
                                       0x4000 0x10
                                       0x5000 0x10
                                       0x6000 0x10
                                       0x7000 0x10
                                       0x8000 0x10
                                       0x9002 0x2
                                       0x9004 0x2
                                       0x9046 0x2>;
                                eeprom-gpios = <&gpio 4 0>;
                        };
                };
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH] arm: pxa: create a unified defconfig for PXA27X-DT
  2015-12-15 16:27                 ` Sergei Ianovich
@ 2015-12-19  7:53                   ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2015-12-19  7:53 UTC (permalink / raw)
  To: linux-kernel
  Cc: Sergei Ianovich, Robert Jarzmik, Arnd Bergmann, Jonathan Corbet,
	Russell King, open list:DOCUMENTATION, moderated list:ARM PORT

Instead of one defconfig file per board, pxa27x-dt_defconfig
is expected to provide a configuration for kernel which can test any
PXA27X-DT compatible board

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Robert Jarzmik <robert.jarzmik@free.fr>
CC: Arnd Bergmann <arnd@arndb.de>
---
 Documentation/arm/pxa/pxa27x_defconfig.txt |   7 ++
 arch/arm/configs/pxa27x-dt_defconfig       | 102 +++++++++++++++++++++++++++++
 2 files changed, 109 insertions(+)
 create mode 100644 Documentation/arm/pxa/pxa27x_defconfig.txt
 create mode 100644 arch/arm/configs/pxa27x-dt_defconfig

diff --git a/Documentation/arm/pxa/pxa27x_defconfig.txt b/Documentation/arm/pxa/pxa27x_defconfig.txt
new file mode 100644
index 0000000..fc4e164
--- /dev/null
+++ b/Documentation/arm/pxa/pxa27x_defconfig.txt
@@ -0,0 +1,7 @@
+If you are reading this, because you are adding support for a new
+PXA27X board, please note that you should not create an additional
+defconfig in arch/arm/configs.
+
+Instead, please update arch/arm/configs/pxa27x-dt_defconfig so that
+a kernel built with this config after `make olddefconfig` boots your
+board.
diff --git a/arch/arm/configs/pxa27x-dt_defconfig b/arch/arm/configs/pxa27x-dt_defconfig
new file mode 100644
index 0000000..003be48
--- /dev/null
+++ b/arch/arm/configs/pxa27x-dt_defconfig
@@ -0,0 +1,102 @@
+## Kernel built with this config should boot any supported PXA27X-DT board
+## Please see Documentation/arm/pxa/pxa27x_defconfig.txt for details
+##
+CONFIG_ARM=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_EMBEDDED=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_BLK_CMDLINE_PARSER=y
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_ARCH_PXA=y
+CONFIG_MACH_PXA27X_DT=y
+CONFIG_PXA_SYSTEMS_CPLDS=y
+CONFIG_PXA_SSP=y
+CONFIG_CPU_FREQ=y
+CONFIG_ARM_PXA2xx_CPUFREQ=y
+CONFIG_NET=y
+CONFIG_IRDA=y
+CONFIG_PXA_FICP=y
+CONFIG_MTD=y
+CONFIG_MTD_OF_PARTS=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_CFI_GEOMETRY=y
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_PHYSMAP_OF=y
+CONFIG_MTD_PXA2XX=y
+CONFIG_OF=y
+CONFIG_OF_FLATTREE=y
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_ATA=y
+CONFIG_SATA_PMP=y
+CONFIG_ATA_SFF=y
+CONFIG_ATA_BMDMA=y
+CONFIG_PATA_PXA=y
+CONFIG_NETDEVICES=y
+CONFIG_DM9000=y
+CONFIG_INPUT=y
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_PXA27x=y
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_NAVPOINT_PXA27x=y
+CONFIG_TTY=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=40
+CONFIG_SERIAL_8250_RUNTIME_UARTS=40
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_8250_PXA=y
+CONFIG_I2C=y
+CONFIG_I2C_GPIO=y
+CONFIG_I2C_PXA=y
+CONFIG_SPI=y
+CONFIG_SPI_PXA2XX=y
+CONFIG_WATCHDOG=y
+CONFIG_SA1100_WATCHDOG=y
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_MEDIA_SUPPORT=y
+CONFIG_MEDIA_CAMERA_SUPPORT=y
+CONFIG_VIDEO_DEV=y
+CONFIG_V4L_PLATFORM_DRIVERS=y
+CONFIG_SOC_CAMERA=y
+CONFIG_VIDEO_PXA27x=y
+CONFIG_FB=y
+CONFIG_FB_PXA=y
+CONFIG_FB_PXA_OVERLAY=y
+CONFIG_FB_PXA_SMARTPANEL=y
+CONFIG_FB_PXA_PARAMETERS=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_ARM=y
+CONFIG_SND_PXA2XX_AC97=y
+CONFIG_SND_SOC=y
+CONFIG_SND_PXA2XX_SOC=y
+CONFIG_USB_SUPPORT=y
+CONFIG_USB=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_OHCI_HCD_PXA27X=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_SERIAL=y
+CONFIG_MMC=y
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_PXA=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_PXA=y
+CONFIG_DMADEVICES=y
+CONFIG_DMA_OF=y
+CONFIG_PXA_DMA=y
+CONFIG_PWM=y
+CONFIG_PWM_PXA=y
+CONFIG_EXT4_FS=y
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
-- 
2.6.3


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

* [PATCH] arm: pxa: create a unified defconfig for PXA27X-DT
@ 2015-12-19  7:53                   ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2015-12-19  7:53 UTC (permalink / raw)
  To: linux-arm-kernel

Instead of one defconfig file per board, pxa27x-dt_defconfig
is expected to provide a configuration for kernel which can test any
PXA27X-DT compatible board

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Robert Jarzmik <robert.jarzmik@free.fr>
CC: Arnd Bergmann <arnd@arndb.de>
---
 Documentation/arm/pxa/pxa27x_defconfig.txt |   7 ++
 arch/arm/configs/pxa27x-dt_defconfig       | 102 +++++++++++++++++++++++++++++
 2 files changed, 109 insertions(+)
 create mode 100644 Documentation/arm/pxa/pxa27x_defconfig.txt
 create mode 100644 arch/arm/configs/pxa27x-dt_defconfig

diff --git a/Documentation/arm/pxa/pxa27x_defconfig.txt b/Documentation/arm/pxa/pxa27x_defconfig.txt
new file mode 100644
index 0000000..fc4e164
--- /dev/null
+++ b/Documentation/arm/pxa/pxa27x_defconfig.txt
@@ -0,0 +1,7 @@
+If you are reading this, because you are adding support for a new
+PXA27X board, please note that you should not create an additional
+defconfig in arch/arm/configs.
+
+Instead, please update arch/arm/configs/pxa27x-dt_defconfig so that
+a kernel built with this config after `make olddefconfig` boots your
+board.
diff --git a/arch/arm/configs/pxa27x-dt_defconfig b/arch/arm/configs/pxa27x-dt_defconfig
new file mode 100644
index 0000000..003be48
--- /dev/null
+++ b/arch/arm/configs/pxa27x-dt_defconfig
@@ -0,0 +1,102 @@
+## Kernel built with this config should boot any supported PXA27X-DT board
+## Please see Documentation/arm/pxa/pxa27x_defconfig.txt for details
+##
+CONFIG_ARM=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_EMBEDDED=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_BLK_CMDLINE_PARSER=y
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_ARCH_PXA=y
+CONFIG_MACH_PXA27X_DT=y
+CONFIG_PXA_SYSTEMS_CPLDS=y
+CONFIG_PXA_SSP=y
+CONFIG_CPU_FREQ=y
+CONFIG_ARM_PXA2xx_CPUFREQ=y
+CONFIG_NET=y
+CONFIG_IRDA=y
+CONFIG_PXA_FICP=y
+CONFIG_MTD=y
+CONFIG_MTD_OF_PARTS=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_CFI_GEOMETRY=y
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_PHYSMAP_OF=y
+CONFIG_MTD_PXA2XX=y
+CONFIG_OF=y
+CONFIG_OF_FLATTREE=y
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_ATA=y
+CONFIG_SATA_PMP=y
+CONFIG_ATA_SFF=y
+CONFIG_ATA_BMDMA=y
+CONFIG_PATA_PXA=y
+CONFIG_NETDEVICES=y
+CONFIG_DM9000=y
+CONFIG_INPUT=y
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_PXA27x=y
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_NAVPOINT_PXA27x=y
+CONFIG_TTY=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=40
+CONFIG_SERIAL_8250_RUNTIME_UARTS=40
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_8250_PXA=y
+CONFIG_I2C=y
+CONFIG_I2C_GPIO=y
+CONFIG_I2C_PXA=y
+CONFIG_SPI=y
+CONFIG_SPI_PXA2XX=y
+CONFIG_WATCHDOG=y
+CONFIG_SA1100_WATCHDOG=y
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_MEDIA_SUPPORT=y
+CONFIG_MEDIA_CAMERA_SUPPORT=y
+CONFIG_VIDEO_DEV=y
+CONFIG_V4L_PLATFORM_DRIVERS=y
+CONFIG_SOC_CAMERA=y
+CONFIG_VIDEO_PXA27x=y
+CONFIG_FB=y
+CONFIG_FB_PXA=y
+CONFIG_FB_PXA_OVERLAY=y
+CONFIG_FB_PXA_SMARTPANEL=y
+CONFIG_FB_PXA_PARAMETERS=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_ARM=y
+CONFIG_SND_PXA2XX_AC97=y
+CONFIG_SND_SOC=y
+CONFIG_SND_PXA2XX_SOC=y
+CONFIG_USB_SUPPORT=y
+CONFIG_USB=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_OHCI_HCD_PXA27X=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_SERIAL=y
+CONFIG_MMC=y
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_PXA=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_PXA=y
+CONFIG_DMADEVICES=y
+CONFIG_DMA_OF=y
+CONFIG_PXA_DMA=y
+CONFIG_PWM=y
+CONFIG_PWM_PXA=y
+CONFIG_EXT4_FS=y
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
-- 
2.6.3

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

* Re: [PATCH v5] serial: support for 16550A serial ports on LP-8x4x
  2015-12-16 10:26                         ` Arnd Bergmann
@ 2015-12-19  8:11                           ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2015-12-19  8:11 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: linux-kernel, Alan Cox, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Greg Kroah-Hartman, Jiri Slaby,
	Heikki Krogerus, Andy Shevchenko, Scott Wood, Masahiro Yamada,
	Sebastian Andrzej Siewior, Paul Burton, Joachim Eastwood,
	Mans Rullgard, Paul Gortmaker, Peter Hurley,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	open list:SERIAL DRIVERS

On Wed, 2015-12-16 at 11:26 +0100, Arnd Bergmann wrote:
> On Wednesday 16 December 2015 11:04:57 Sergei Ianovich wrote:
> > On Tue, 2015-12-15 at 22:51 +0100, Arnd Bergmann wrote:
> > > 'x' wildcards in the name of the board seem important. There are
> > devices
> > made by the same vendor without 8 or 4 in their name. Those devices
> > either are not shipped with linux or are base on a x86 platform.
> > 
> > Does this justify the choice of the compatible string?
> 
> What I meant was that you should use the specific numbers of one
> machine,
> precisely for the reason you list above.
> 
> If there is e.g. a LP-8040 and a LP-8141 today, and you use lp8x4x in
> the compatible string to cover both, this will no longer work when the
> vendor comes out with a LP8047 that is completely different.
> 
> Instead, what you should do is to use the compatible string to
> identify
> one particular board (e.g. the first one that used this setup), and
> then list the other ones as compatible with this. You can also add the
> other board names in addition, e.g.
> 
> compatible = "icpdas,uart-lp8041", "icpdas,uart-lp8040";
> 
> for a lp8041 that is compatible with the lp8040. If it turns out later
> that they are not entirely compatible, we can work around this in the
> driver by checking for the lp8041 string that will be matched first,
> while
> the lp8040 can be used by the driver to match the entire family of
> compatible machines (no need to list every one in the driver).

I'll try to be more specific. This driver will support ports on LP-8081, 
LP-8141, LP-8441, LP-8841. Last time I checked the vendor was announcing
a series with 3 as the last digit. They use lp8x4x name, eg. in
documentation like `LP-8x4x_ChangeLog.txt`. They ship their proprietary
SDK in `lp8x4x_sdk_for_linux.tar`. All of this implies that it is a
single board.

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

* Re: [PATCH v5] serial: support for 16550A serial ports on LP-8x4x
@ 2015-12-19  8:11                           ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2015-12-19  8:11 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: linux-kernel, Alan Cox, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Greg Kroah-Hartman, Jiri Slaby,
	Heikki Krogerus, Andy Shevchenko, Scott Wood, Masahiro Yamada,
	Sebastian Andrzej Siewior, Paul Burton, Joachim Eastwood,
	Mans Rullgard, Paul Gortmaker, Peter Hurley,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS

On Wed, 2015-12-16 at 11:26 +0100, Arnd Bergmann wrote:
> On Wednesday 16 December 2015 11:04:57 Sergei Ianovich wrote:
> > On Tue, 2015-12-15 at 22:51 +0100, Arnd Bergmann wrote:
> > > 'x' wildcards in the name of the board seem important. There are
> > devices
> > made by the same vendor without 8 or 4 in their name. Those devices
> > either are not shipped with linux or are base on a x86 platform.
> > 
> > Does this justify the choice of the compatible string?
> 
> What I meant was that you should use the specific numbers of one
> machine,
> precisely for the reason you list above.
> 
> If there is e.g. a LP-8040 and a LP-8141 today, and you use lp8x4x in
> the compatible string to cover both, this will no longer work when the
> vendor comes out with a LP8047 that is completely different.
> 
> Instead, what you should do is to use the compatible string to
> identify
> one particular board (e.g. the first one that used this setup), and
> then list the other ones as compatible with this. You can also add the
> other board names in addition, e.g.
> 
> compatible = "icpdas,uart-lp8041", "icpdas,uart-lp8040";
> 
> for a lp8041 that is compatible with the lp8040. If it turns out later
> that they are not entirely compatible, we can work around this in the
> driver by checking for the lp8041 string that will be matched first,
> while
> the lp8040 can be used by the driver to match the entire family of
> compatible machines (no need to list every one in the driver).

I'll try to be more specific. This driver will support ports on LP-8081, 
LP-8141, LP-8441, LP-8841. Last time I checked the vendor was announcing
a series with 3 as the last digit. They use lp8x4x name, eg. in
documentation like `LP-8x4x_ChangeLog.txt`. They ship their proprietary
SDK in `lp8x4x_sdk_for_linux.tar`. All of this implies that it is a
single board.

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

* Re: [PATCH v5 2/2] arm: pxa27x: support for ICP DAS LP-8x4x w/ DT
  2015-12-15 17:02                       ` Arnd Bergmann
  (?)
@ 2015-12-19 12:27                         ` Robert Jarzmik
  -1 siblings, 0 replies; 700+ messages in thread
From: Robert Jarzmik @ 2015-12-19 12:27 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Sergei Ianovich, linux-kernel, Daniel Mack, Rob Herring,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala, Russell King,
	Thierry Reding, Jonathan Cameron, Dmitry Torokhov, Philipp Zabel,
	Arnaud Ebalard, Kuninori Morimoto,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	moderated list:ARM PORT

Arnd Bergmann <arnd@arndb.de> writes:

> I would like those drivers to be enabled in some defconfig, so we get
> compile-time coverage, but we generally stopped having one-config-per-board
> files.
>
> Maybe we can have a pxa_defconfig file that enables lots of boards
> and then we remove the individual configs? We don't have to remove
> them all at once, but it would make me very happy if we could at
> least kill off some of the ones that are not used regularly.

I'll take that part, the pxa_defconfig which covers all pxa boards in
arch/arm/mach-pxa. I have a prototype, which of course doesn't boot on any of my
pxa platforms (breaks in the very early bootstrap code I think, DEBUG_LL is the
next stage).

Actually I've not even looked if a single kernel covering pxa2xx and pxa3xx is
possible (since recently clock handling was a blocker).

Once I have something that at least shows me a sign of life, I'll submit an RFC
patch. This work will be orthogonal to Sergei's one, as it is aimed at having
one defconfig compiling all mach-pxa/*.c files and the drivers referenced by
them. This won't allow removing defconfig files until I have a good idea why my
boards are not booting (lubbock, mainstone, mioa701, zylonite, cm-x300).

Cheers.

-- 
Robert

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

* Re: [PATCH v5 2/2] arm: pxa27x: support for ICP DAS LP-8x4x w/ DT
@ 2015-12-19 12:27                         ` Robert Jarzmik
  0 siblings, 0 replies; 700+ messages in thread
From: Robert Jarzmik @ 2015-12-19 12:27 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Sergei Ianovich, linux-kernel, Daniel Mack, Rob Herring,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala, Russell King,
	Thierry Reding, Jonathan Cameron, Dmitry Torokhov, Philipp Zabel,
	Arnaud Ebalard, Kuninori Morimoto,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	moderated list:ARM PORT

Arnd Bergmann <arnd@arndb.de> writes:

> I would like those drivers to be enabled in some defconfig, so we get
> compile-time coverage, but we generally stopped having one-config-per-board
> files.
>
> Maybe we can have a pxa_defconfig file that enables lots of boards
> and then we remove the individual configs? We don't have to remove
> them all at once, but it would make me very happy if we could at
> least kill off some of the ones that are not used regularly.

I'll take that part, the pxa_defconfig which covers all pxa boards in
arch/arm/mach-pxa. I have a prototype, which of course doesn't boot on any of my
pxa platforms (breaks in the very early bootstrap code I think, DEBUG_LL is the
next stage).

Actually I've not even looked if a single kernel covering pxa2xx and pxa3xx is
possible (since recently clock handling was a blocker).

Once I have something that at least shows me a sign of life, I'll submit an RFC
patch. This work will be orthogonal to Sergei's one, as it is aimed at having
one defconfig compiling all mach-pxa/*.c files and the drivers referenced by
them. This won't allow removing defconfig files until I have a good idea why my
boards are not booting (lubbock, mainstone, mioa701, zylonite, cm-x300).

Cheers.

-- 
Robert

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

* [PATCH v5 2/2] arm: pxa27x: support for ICP DAS LP-8x4x w/ DT
@ 2015-12-19 12:27                         ` Robert Jarzmik
  0 siblings, 0 replies; 700+ messages in thread
From: Robert Jarzmik @ 2015-12-19 12:27 UTC (permalink / raw)
  To: linux-arm-kernel

Arnd Bergmann <arnd@arndb.de> writes:

> I would like those drivers to be enabled in some defconfig, so we get
> compile-time coverage, but we generally stopped having one-config-per-board
> files.
>
> Maybe we can have a pxa_defconfig file that enables lots of boards
> and then we remove the individual configs? We don't have to remove
> them all at once, but it would make me very happy if we could at
> least kill off some of the ones that are not used regularly.

I'll take that part, the pxa_defconfig which covers all pxa boards in
arch/arm/mach-pxa. I have a prototype, which of course doesn't boot on any of my
pxa platforms (breaks in the very early bootstrap code I think, DEBUG_LL is the
next stage).

Actually I've not even looked if a single kernel covering pxa2xx and pxa3xx is
possible (since recently clock handling was a blocker).

Once I have something that at least shows me a sign of life, I'll submit an RFC
patch. This work will be orthogonal to Sergei's one, as it is aimed at having
one defconfig compiling all mach-pxa/*.c files and the drivers referenced by
them. This won't allow removing defconfig files until I have a good idea why my
boards are not booting (lubbock, mainstone, mioa701, zylonite, cm-x300).

Cheers.

-- 
Robert

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

* Re: [PATCH v4 1/2] serial: rewrite pxa2xx-uart to use 8250_core
  2015-12-09 22:28               ` Sergei Ianovich
  (?)
@ 2015-12-19 12:45                 ` Robert Jarzmik
  -1 siblings, 0 replies; 700+ messages in thread
From: Robert Jarzmik @ 2015-12-19 12:45 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: linux-kernel, Russell King, Greg Kroah-Hartman, Jiri Slaby,
	Heikki Krogerus, James Cameron, Alexandre Belloni, Rob Herring,
	Ulf Hansson, Rafael J. Wysocki, Kevin Hilman, Andy Shevchenko,
	Arnd Bergmann, Paul Gortmaker, Scott Wood,
	Sebastian Andrzej Siewior, Paul Burton, Joachim Eastwood,
	Mans Rullgard, Masahiro Yamada, Peter Hurley,
	moderated list:ARM PORT, open list:SERIAL DRIVERS

Sergei Ianovich <ynvich@gmail.com> writes:

> pxa2xx-uart was a separate uart platform driver. It was declaring
> the same device names and numbers as 8250 driver. As a result,
> it was impossible to use 8250 driver on PXA SoCs.
>
> Upon closer examination pxa2xx-uart turned out to be a clone of
> 8250_core driver.
>
> Workaround for Erratum #19 according to Marvel(R) PXA270M Processor
> Specification Update (April 19, 2010) is dropped. 8250_core reads
> from FIFO immediately after checking DR bit in LSR.
>
> Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
> Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
> Reviewed-by: James Cameron <quozl@laptop.org>
> Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Tested-by: Robert Jarzmik <robert.jarzmik@free.fr>

I was wondering if this should go through pxa tree, or through serial tree ?

Cheers.

--
Robert

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

* Re: [PATCH v4 1/2] serial: rewrite pxa2xx-uart to use 8250_core
@ 2015-12-19 12:45                 ` Robert Jarzmik
  0 siblings, 0 replies; 700+ messages in thread
From: Robert Jarzmik @ 2015-12-19 12:45 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: linux-kernel, Russell King, Greg Kroah-Hartman, Jiri Slaby,
	Heikki Krogerus, James Cameron, Alexandre Belloni, Rob Herring,
	Ulf Hansson, Rafael J. Wysocki, Kevin Hilman, Andy Shevchenko,
	Arnd Bergmann, Paul Gortmaker, Scott Wood,
	Sebastian Andrzej Siewior, Paul Burton, Joachim Eastwood,
	Mans Rullgard, Masahiro Yamada, Peter Hurley, linux-arm-k

Sergei Ianovich <ynvich@gmail.com> writes:

> pxa2xx-uart was a separate uart platform driver. It was declaring
> the same device names and numbers as 8250 driver. As a result,
> it was impossible to use 8250 driver on PXA SoCs.
>
> Upon closer examination pxa2xx-uart turned out to be a clone of
> 8250_core driver.
>
> Workaround for Erratum #19 according to Marvel(R) PXA270M Processor
> Specification Update (April 19, 2010) is dropped. 8250_core reads
> from FIFO immediately after checking DR bit in LSR.
>
> Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
> Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
> Reviewed-by: James Cameron <quozl@laptop.org>
> Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Tested-by: Robert Jarzmik <robert.jarzmik@free.fr>

I was wondering if this should go through pxa tree, or through serial tree ?

Cheers.

--
Robert

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

* [PATCH v4 1/2] serial: rewrite pxa2xx-uart to use 8250_core
@ 2015-12-19 12:45                 ` Robert Jarzmik
  0 siblings, 0 replies; 700+ messages in thread
From: Robert Jarzmik @ 2015-12-19 12:45 UTC (permalink / raw)
  To: linux-arm-kernel

Sergei Ianovich <ynvich@gmail.com> writes:

> pxa2xx-uart was a separate uart platform driver. It was declaring
> the same device names and numbers as 8250 driver. As a result,
> it was impossible to use 8250 driver on PXA SoCs.
>
> Upon closer examination pxa2xx-uart turned out to be a clone of
> 8250_core driver.
>
> Workaround for Erratum #19 according to Marvel(R) PXA270M Processor
> Specification Update (April 19, 2010) is dropped. 8250_core reads
> from FIFO immediately after checking DR bit in LSR.
>
> Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
> Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
> Reviewed-by: James Cameron <quozl@laptop.org>
> Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Tested-by: Robert Jarzmik <robert.jarzmik@free.fr>

I was wondering if this should go through pxa tree, or through serial tree ?

Cheers.

--
Robert

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

* Re: [PATCH v4 1/2] serial: rewrite pxa2xx-uart to use 8250_core
  2015-12-19 12:45                 ` Robert Jarzmik
  (?)
@ 2015-12-19 13:26                   ` Robert Jarzmik
  -1 siblings, 0 replies; 700+ messages in thread
From: Robert Jarzmik @ 2015-12-19 13:26 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: linux-kernel, Kevin Hilman, Arnd Bergmann,
	moderated list:ARM PORT, open list:SERIAL DRIVERS

Robert Jarzmik <robert.jarzmik@free.fr> writes:

> Sergei Ianovich <ynvich@gmail.com> writes:
>
>> pxa2xx-uart was a separate uart platform driver. It was declaring
>> the same device names and numbers as 8250 driver. As a result,
>> it was impossible to use 8250 driver on PXA SoCs.
>>
>> Upon closer examination pxa2xx-uart turned out to be a clone of
>> 8250_core driver.
>>
>> Workaround for Erratum #19 according to Marvel(R) PXA270M Processor
>> Specification Update (April 19, 2010) is dropped. 8250_core reads
>> from FIFO immediately after checking DR bit in LSR.
>>
>> Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
>> Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
>> Reviewed-by: James Cameron <quozl@laptop.org>
>> Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> Tested-by: Robert Jarzmik <robert.jarzmik@free.fr>

Shrunk the list, the following is rather mach-pxa specific.

Actually there is a small glitch ...
Have a look at arch/arm/mach-pxa/viper.c, line 490:
	#ifndef CONFIG_SERIAL_PXA
	...

But that can be handled in an subsequent patch to keep your acks and reviews.

Cheers.

-- 
Robert

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

* Re: [PATCH v4 1/2] serial: rewrite pxa2xx-uart to use 8250_core
@ 2015-12-19 13:26                   ` Robert Jarzmik
  0 siblings, 0 replies; 700+ messages in thread
From: Robert Jarzmik @ 2015-12-19 13:26 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: linux-kernel, Kevin Hilman, Arnd Bergmann,
	moderated list:ARM PORT, open list:SERIAL DRIVERS

Robert Jarzmik <robert.jarzmik@free.fr> writes:

> Sergei Ianovich <ynvich@gmail.com> writes:
>
>> pxa2xx-uart was a separate uart platform driver. It was declaring
>> the same device names and numbers as 8250 driver. As a result,
>> it was impossible to use 8250 driver on PXA SoCs.
>>
>> Upon closer examination pxa2xx-uart turned out to be a clone of
>> 8250_core driver.
>>
>> Workaround for Erratum #19 according to Marvel(R) PXA270M Processor
>> Specification Update (April 19, 2010) is dropped. 8250_core reads
>> from FIFO immediately after checking DR bit in LSR.
>>
>> Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
>> Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
>> Reviewed-by: James Cameron <quozl@laptop.org>
>> Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> Tested-by: Robert Jarzmik <robert.jarzmik@free.fr>

Shrunk the list, the following is rather mach-pxa specific.

Actually there is a small glitch ...
Have a look at arch/arm/mach-pxa/viper.c, line 490:
	#ifndef CONFIG_SERIAL_PXA
	...

But that can be handled in an subsequent patch to keep your acks and reviews.

Cheers.

-- 
Robert

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

* [PATCH v4 1/2] serial: rewrite pxa2xx-uart to use 8250_core
@ 2015-12-19 13:26                   ` Robert Jarzmik
  0 siblings, 0 replies; 700+ messages in thread
From: Robert Jarzmik @ 2015-12-19 13:26 UTC (permalink / raw)
  To: linux-arm-kernel

Robert Jarzmik <robert.jarzmik@free.fr> writes:

> Sergei Ianovich <ynvich@gmail.com> writes:
>
>> pxa2xx-uart was a separate uart platform driver. It was declaring
>> the same device names and numbers as 8250 driver. As a result,
>> it was impossible to use 8250 driver on PXA SoCs.
>>
>> Upon closer examination pxa2xx-uart turned out to be a clone of
>> 8250_core driver.
>>
>> Workaround for Erratum #19 according to Marvel(R) PXA270M Processor
>> Specification Update (April 19, 2010) is dropped. 8250_core reads
>> from FIFO immediately after checking DR bit in LSR.
>>
>> Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
>> Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
>> Reviewed-by: James Cameron <quozl@laptop.org>
>> Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> Tested-by: Robert Jarzmik <robert.jarzmik@free.fr>

Shrunk the list, the following is rather mach-pxa specific.

Actually there is a small glitch ...
Have a look at arch/arm/mach-pxa/viper.c, line 490:
	#ifndef CONFIG_SERIAL_PXA
	...

But that can be handled in an subsequent patch to keep your acks and reviews.

Cheers.

-- 
Robert

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

* Re: [PATCH v4 1/2] serial: rewrite pxa2xx-uart to use 8250_core
  2015-12-19 13:26                   ` Robert Jarzmik
@ 2015-12-19 18:46                     ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2015-12-19 18:46 UTC (permalink / raw)
  To: Robert Jarzmik
  Cc: linux-kernel, Kevin Hilman, Arnd Bergmann,
	moderated list:ARM PORT, open list:SERIAL DRIVERS

On Sat, 2015-12-19 at 14:26 +0100, Robert Jarzmik wrote:
> Robert Jarzmik <robert.jarzmik@free.fr> writes:
> 
> > Sergei Ianovich <ynvich@gmail.com> writes:
> > 
> > > pxa2xx-uart was a separate uart platform driver. It was declaring
> > > the same device names and numbers as 8250 driver. As a result,
> > > it was impossible to use 8250 driver on PXA SoCs.
> > > 
> > > Upon closer examination pxa2xx-uart turned out to be a clone of
> > > 8250_core driver.
> > > 
> > > Workaround for Erratum #19 according to Marvel(R) PXA270M
> > > Processor
> > > Specification Update (April 19, 2010) is dropped. 8250_core reads
> > > from FIFO immediately after checking DR bit in LSR.
> > > 
> > > Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
> > > Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
> > > Reviewed-by: James Cameron <quozl@laptop.org>
> > > Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> > Tested-by: Robert Jarzmik <robert.jarzmik@free.fr>
> 
> Shrunk the list, the following is rather mach-pxa specific.
> 
> Actually there is a small glitch ...
> Have a look at arch/arm/mach-pxa/viper.c, line 490:
> 	#ifndef CONFIG_SERIAL_PXA
> 	...

Thanks for spotting this. This is caused by a change in the latest
version of the patch (SERIAL_8250_PXA instead of SERIAL_PXA). This
change could be reverted.

> But that can be handled in an subsequent patch to keep your acks and
> reviews.
> 

I will respin the patch. Please comment on the acks and reviews. They
were made at an earlier version of the patch. That version no longer
applies. Can the updated version carry on the flags?

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

* [PATCH v4 1/2] serial: rewrite pxa2xx-uart to use 8250_core
@ 2015-12-19 18:46                     ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2015-12-19 18:46 UTC (permalink / raw)
  To: linux-arm-kernel

On Sat, 2015-12-19 at 14:26 +0100, Robert Jarzmik wrote:
> Robert Jarzmik <robert.jarzmik@free.fr> writes:
> 
> > Sergei Ianovich <ynvich@gmail.com> writes:
> > 
> > > pxa2xx-uart was a separate uart platform driver. It was declaring
> > > the same device names and numbers as 8250 driver. As a result,
> > > it was impossible to use 8250 driver on PXA SoCs.
> > > 
> > > Upon closer examination pxa2xx-uart turned out to be a clone of
> > > 8250_core driver.
> > > 
> > > Workaround for Erratum #19 according to Marvel(R) PXA270M
> > > Processor
> > > Specification Update (April 19, 2010) is dropped. 8250_core reads
> > > from FIFO immediately after checking DR bit in LSR.
> > > 
> > > Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
> > > Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
> > > Reviewed-by: James Cameron <quozl@laptop.org>
> > > Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> > Tested-by: Robert Jarzmik <robert.jarzmik@free.fr>
> 
> Shrunk the list, the following is rather mach-pxa specific.
> 
> Actually there is a small glitch ...
> Have a look at arch/arm/mach-pxa/viper.c, line 490:
> 	#ifndef CONFIG_SERIAL_PXA
> 	...

Thanks for spotting this. This is caused by a change in the latest
version of the patch (SERIAL_8250_PXA instead of SERIAL_PXA). This
change could be reverted.

> But that can be handled in an subsequent patch to keep your acks and
> reviews.
> 

I will respin the patch. Please comment on the acks and reviews. They
were made at an earlier version of the patch. That version no longer
applies. Can the updated version carry on the flags?

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

* Re: [PATCH v4 1/2] serial: rewrite pxa2xx-uart to use 8250_core
  2015-12-19 18:46                     ` Sergei Ianovich
  (?)
@ 2015-12-19 19:31                       ` Robert Jarzmik
  -1 siblings, 0 replies; 700+ messages in thread
From: Robert Jarzmik @ 2015-12-19 19:31 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: linux-kernel, Kevin Hilman, Arnd Bergmann,
	moderated list:ARM PORT, open list:SERIAL DRIVERS

Sergei Ianovich <ynvich@gmail.com> writes:

> On Sat, 2015-12-19 at 14:26 +0100, Robert Jarzmik wrote:
>> Robert Jarzmik <robert.jarzmik@free.fr> writes:
>> 
>> > Sergei Ianovich <ynvich@gmail.com> writes:
>> > 
>> > > pxa2xx-uart was a separate uart platform driver. It was declaring
>> > > the same device names and numbers as 8250 driver. As a result,
>> > > it was impossible to use 8250 driver on PXA SoCs.
>> > > 
>> > > Upon closer examination pxa2xx-uart turned out to be a clone of
>> > > 8250_core driver.
>> > > 
>> > > Workaround for Erratum #19 according to Marvel(R) PXA270M
>> > > Processor
>> > > Specification Update (April 19, 2010) is dropped. 8250_core reads
>> > > from FIFO immediately after checking DR bit in LSR.
>> > > 
>> > > Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
>> > > Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
>> > > Reviewed-by: James Cameron <quozl@laptop.org>
>> > > Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
>> > Tested-by: Robert Jarzmik <robert.jarzmik@free.fr>
>> 
>> Shrunk the list, the following is rather mach-pxa specific.
>> 
>> Actually there is a small glitch ...
>> Have a look at arch/arm/mach-pxa/viper.c, line 490:
>> 	#ifndef CONFIG_SERIAL_PXA
>> 	...
>
> Thanks for spotting this. This is caused by a change in the latest
> version of the patch (SERIAL_8250_PXA instead of SERIAL_PXA). This
> change could be reverted.
Actually I'm against the revert.
The name change looks very good to me, please keep it.

>> But that can be handled in an subsequent patch to keep your acks and
>> reviews.
> I will respin the patch. Please comment on the acks and reviews. They
> were made at an earlier version of the patch. That version no longer
> applies. Can the updated version carry on the flags?
I don't get you. If you mean keeping CONFIG_SERIAL_8250_PXA, then yes, please
keep it.

Cheers.
-- 
Robert

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

* Re: [PATCH v4 1/2] serial: rewrite pxa2xx-uart to use 8250_core
@ 2015-12-19 19:31                       ` Robert Jarzmik
  0 siblings, 0 replies; 700+ messages in thread
From: Robert Jarzmik @ 2015-12-19 19:31 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: linux-kernel, Kevin Hilman, Arnd Bergmann,
	moderated list:ARM PORT, open list:SERIAL DRIVERS

Sergei Ianovich <ynvich@gmail.com> writes:

> On Sat, 2015-12-19 at 14:26 +0100, Robert Jarzmik wrote:
>> Robert Jarzmik <robert.jarzmik@free.fr> writes:
>> 
>> > Sergei Ianovich <ynvich@gmail.com> writes:
>> > 
>> > > pxa2xx-uart was a separate uart platform driver. It was declaring
>> > > the same device names and numbers as 8250 driver. As a result,
>> > > it was impossible to use 8250 driver on PXA SoCs.
>> > > 
>> > > Upon closer examination pxa2xx-uart turned out to be a clone of
>> > > 8250_core driver.
>> > > 
>> > > Workaround for Erratum #19 according to Marvel(R) PXA270M
>> > > Processor
>> > > Specification Update (April 19, 2010) is dropped. 8250_core reads
>> > > from FIFO immediately after checking DR bit in LSR.
>> > > 
>> > > Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
>> > > Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
>> > > Reviewed-by: James Cameron <quozl@laptop.org>
>> > > Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
>> > Tested-by: Robert Jarzmik <robert.jarzmik@free.fr>
>> 
>> Shrunk the list, the following is rather mach-pxa specific.
>> 
>> Actually there is a small glitch ...
>> Have a look at arch/arm/mach-pxa/viper.c, line 490:
>> 	#ifndef CONFIG_SERIAL_PXA
>> 	...
>
> Thanks for spotting this. This is caused by a change in the latest
> version of the patch (SERIAL_8250_PXA instead of SERIAL_PXA). This
> change could be reverted.
Actually I'm against the revert.
The name change looks very good to me, please keep it.

>> But that can be handled in an subsequent patch to keep your acks and
>> reviews.
> I will respin the patch. Please comment on the acks and reviews. They
> were made at an earlier version of the patch. That version no longer
> applies. Can the updated version carry on the flags?
I don't get you. If you mean keeping CONFIG_SERIAL_8250_PXA, then yes, please
keep it.

Cheers.
-- 
Robert

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

* [PATCH v4 1/2] serial: rewrite pxa2xx-uart to use 8250_core
@ 2015-12-19 19:31                       ` Robert Jarzmik
  0 siblings, 0 replies; 700+ messages in thread
From: Robert Jarzmik @ 2015-12-19 19:31 UTC (permalink / raw)
  To: linux-arm-kernel

Sergei Ianovich <ynvich@gmail.com> writes:

> On Sat, 2015-12-19 at 14:26 +0100, Robert Jarzmik wrote:
>> Robert Jarzmik <robert.jarzmik@free.fr> writes:
>> 
>> > Sergei Ianovich <ynvich@gmail.com> writes:
>> > 
>> > > pxa2xx-uart was a separate uart platform driver. It was declaring
>> > > the same device names and numbers as 8250 driver. As a result,
>> > > it was impossible to use 8250 driver on PXA SoCs.
>> > > 
>> > > Upon closer examination pxa2xx-uart turned out to be a clone of
>> > > 8250_core driver.
>> > > 
>> > > Workaround for Erratum #19 according to Marvel(R) PXA270M
>> > > Processor
>> > > Specification Update (April 19, 2010) is dropped. 8250_core reads
>> > > from FIFO immediately after checking DR bit in LSR.
>> > > 
>> > > Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
>> > > Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
>> > > Reviewed-by: James Cameron <quozl@laptop.org>
>> > > Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
>> > Tested-by: Robert Jarzmik <robert.jarzmik@free.fr>
>> 
>> Shrunk the list, the following is rather mach-pxa specific.
>> 
>> Actually there is a small glitch ...
>> Have a look at arch/arm/mach-pxa/viper.c, line 490:
>> 	#ifndef CONFIG_SERIAL_PXA
>> 	...
>
> Thanks for spotting this. This is caused by a change in the latest
> version of the patch (SERIAL_8250_PXA instead of SERIAL_PXA). This
> change could be reverted.
Actually I'm against the revert.
The name change looks very good to me, please keep it.

>> But that can be handled in an subsequent patch to keep your acks and
>> reviews.
> I will respin the patch. Please comment on the acks and reviews. They
> were made at an earlier version of the patch. That version no longer
> applies. Can the updated version carry on the flags?
I don't get you. If you mean keeping CONFIG_SERIAL_8250_PXA, then yes, please
keep it.

Cheers.
-- 
Robert

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

* Re: [PATCH v4 1/2] serial: rewrite pxa2xx-uart to use 8250_core
  2015-12-19 19:31                       ` Robert Jarzmik
@ 2015-12-19 20:12                         ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2015-12-19 20:12 UTC (permalink / raw)
  To: Robert Jarzmik
  Cc: linux-kernel, Kevin Hilman, Arnd Bergmann,
	moderated list:ARM PORT, open list:SERIAL DRIVERS

On Sat, 2015-12-19 at 20:31 +0100, Robert Jarzmik wrote:
> Sergei Ianovich <ynvich@gmail.com> writes:
> Thanks for spotting this. This is caused by a change in the latest
> > version of the patch (SERIAL_8250_PXA instead of SERIAL_PXA). This
> > change could be reverted.
> Actually I'm against the revert.
> The name change looks very good to me, please keep it.

Is it worth adding an error if CONFIG_SERIAL_PXA is defined? Or is there
any other way of preventing this patch launching Linus' "flag days" as
Russel King named it?

I understand that people are afraid of taking this patch. If it starts
causing troubles at runtime, it will be difficult to diagnose. There
will be no console for most people. So it is probably good idea to fail
at boot time.

> > > But that can be handled in an subsequent patch to keep your acks
> > > and
> > > reviews.
> > I will respin the patch. Please comment on the acks and reviews.
> > They
> > were made at an earlier version of the patch. That version no longer
> > applies. Can the updated version carry on the flags?
> I don't get you. If you mean keeping CONFIG_SERIAL_8250_PXA, then yes,
> please
> keep it.

I mean should the patch be re-revied and re-acked?

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

* [PATCH v4 1/2] serial: rewrite pxa2xx-uart to use 8250_core
@ 2015-12-19 20:12                         ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2015-12-19 20:12 UTC (permalink / raw)
  To: linux-arm-kernel

On Sat, 2015-12-19 at 20:31 +0100, Robert Jarzmik wrote:
> Sergei Ianovich <ynvich@gmail.com> writes:
> Thanks for spotting this. This is caused by a change in the latest
> > version of the patch (SERIAL_8250_PXA instead of SERIAL_PXA). This
> > change could be reverted.
> Actually I'm against the revert.
> The name change looks very good to me, please keep it.

Is it worth adding an error if CONFIG_SERIAL_PXA is defined? Or is there
any other way of preventing this patch launching Linus' "flag days" as
Russel King named it?

I understand that people are afraid of taking this patch. If it starts
causing troubles at runtime, it will be difficult to diagnose. There
will be no console for most people. So it is probably good idea to fail
at boot time.

> > > But that can be handled in an subsequent patch to keep your acks
> > > and
> > > reviews.
> > I will respin the patch. Please comment on the acks and reviews.
> > They
> > were made at an earlier version of the patch. That version no longer
> > applies. Can the updated version carry on the flags?
> I don't get you. If you mean keeping CONFIG_SERIAL_8250_PXA, then yes,
> please
> keep it.

I mean should the patch be re-revied and re-acked?

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

* Re: [PATCH v5] serial: support for 16550A serial ports on LP-8x4x
  2015-12-15 21:51                     ` Arnd Bergmann
@ 2015-12-19 21:42                       ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2015-12-19 21:42 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: linux-kernel, Alan Cox, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Greg Kroah-Hartman, Jiri Slaby,
	Heikki Krogerus, Andy Shevchenko, Scott Wood, Masahiro Yamada,
	Sebastian Andrzej Siewior, Paul Burton, Joachim Eastwood,
	Mans Rullgard, Paul Gortmaker, Peter Hurley,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	open list:SERIAL DRIVERS

On Tue, 2015-12-15 at 22:51 +0100, Arnd Bergmann wrote:
> On Wednesday 16 December 2015 00:04:45 Sergei Ianovich wrote:
> > +Examples (from pxa27x-lp8x4x.dts):
> > +
> > +               uart@9050 {
> 
> By convention, the name should be 'serial', not 'uart'.
> 

arch/arm/boot/dts/pxa2xx.dtsi uses 'uart'. Should I change the names in
the patch with dts file for LP-8xx?

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

* Re: [PATCH v5] serial: support for 16550A serial ports on LP-8x4x
@ 2015-12-19 21:42                       ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2015-12-19 21:42 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: linux-kernel, Alan Cox, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Greg Kroah-Hartman, Jiri Slaby,
	Heikki Krogerus, Andy Shevchenko, Scott Wood, Masahiro Yamada,
	Sebastian Andrzej Siewior, Paul Burton, Joachim Eastwood,
	Mans Rullgard, Paul Gortmaker, Peter Hurley,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS

On Tue, 2015-12-15 at 22:51 +0100, Arnd Bergmann wrote:
> On Wednesday 16 December 2015 00:04:45 Sergei Ianovich wrote:
> > +Examples (from pxa27x-lp8x4x.dts):
> > +
> > +               uart@9050 {
> 
> By convention, the name should be 'serial', not 'uart'.
> 

arch/arm/boot/dts/pxa2xx.dtsi uses 'uart'. Should I change the names in
the patch with dts file for LP-8xx?

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

* Re: [PATCH v4 1/2] serial: rewrite pxa2xx-uart to use 8250_core
  2015-12-19 20:12                         ` Sergei Ianovich
  (?)
@ 2015-12-19 23:12                           ` Robert Jarzmik
  -1 siblings, 0 replies; 700+ messages in thread
From: Robert Jarzmik @ 2015-12-19 23:12 UTC (permalink / raw)
  To: Sergei Ianovich, Kevin Hilman, Arnd Bergmann
  Cc: linux-kernel, moderated list:ARM PORT, open list:SERIAL DRIVERS

Sergei Ianovich <ynvich@gmail.com> writes:

> On Sat, 2015-12-19 at 20:31 +0100, Robert Jarzmik wrote:
>> Sergei Ianovich <ynvich@gmail.com> writes:
>> Thanks for spotting this. This is caused by a change in the latest
>> > version of the patch (SERIAL_8250_PXA instead of SERIAL_PXA). This
>> > change could be reverted.
>> Actually I'm against the revert.
>> The name change looks very good to me, please keep it.
>
> Is it worth adding an error if CONFIG_SERIAL_PXA is defined?
I don't think so.

> Or is there any other way of preventing this patch launching Linus' "flag
> days" as Russel King named it?
I must think about it, and test a bit more.
Ah and a small hint : if you include back Russell in the conversation, don't
forget the double "ll" if you wish him to answer.

> I understand that people are afraid of taking this patch. If it starts
> causing troubles at runtime, it will be difficult to diagnose. There
> will be no console for most people. So it is probably good idea to fail
> at boot time.
Who are "the people" ? If it's about something already written in a mailing
list, please point me to it so that it can help me think about it.

>> > > But that can be handled in an subsequent patch to keep your acks
>> > > and
>> > > reviews.
>> > I will respin the patch. Please comment on the acks and reviews.
>> > They
>> > were made at an earlier version of the patch. That version no longer
>> > applies. Can the updated version carry on the flags?
>> I don't get you. If you mean keeping CONFIG_SERIAL_8250_PXA, then yes,
>> please
>> keep it.
>
> I mean should the patch be re-revied and re-acked?
Well it depends on what was since then. If it's a trivial commit message fix or
a typo, I don't think it's necessary. If it's the algorithm, the code logic, or
even I think you should ask again.

For a name change in CONFIG_SERIAL_PXA into CONFIG_SERIAL_8250_PXA (change from
v3 to v4), I must admit I don't know. Maybe Kevin or Arnd might give a clue.

Cheers.

-- 
Robert

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

* Re: [PATCH v4 1/2] serial: rewrite pxa2xx-uart to use 8250_core
@ 2015-12-19 23:12                           ` Robert Jarzmik
  0 siblings, 0 replies; 700+ messages in thread
From: Robert Jarzmik @ 2015-12-19 23:12 UTC (permalink / raw)
  To: Sergei Ianovich, Kevin Hilman, Arnd Bergmann
  Cc: linux-kernel, moderated list:ARM PORT, open list:SERIAL DRIVERS

Sergei Ianovich <ynvich@gmail.com> writes:

> On Sat, 2015-12-19 at 20:31 +0100, Robert Jarzmik wrote:
>> Sergei Ianovich <ynvich@gmail.com> writes:
>> Thanks for spotting this. This is caused by a change in the latest
>> > version of the patch (SERIAL_8250_PXA instead of SERIAL_PXA). This
>> > change could be reverted.
>> Actually I'm against the revert.
>> The name change looks very good to me, please keep it.
>
> Is it worth adding an error if CONFIG_SERIAL_PXA is defined?
I don't think so.

> Or is there any other way of preventing this patch launching Linus' "flag
> days" as Russel King named it?
I must think about it, and test a bit more.
Ah and a small hint : if you include back Russell in the conversation, don't
forget the double "ll" if you wish him to answer.

> I understand that people are afraid of taking this patch. If it starts
> causing troubles at runtime, it will be difficult to diagnose. There
> will be no console for most people. So it is probably good idea to fail
> at boot time.
Who are "the people" ? If it's about something already written in a mailing
list, please point me to it so that it can help me think about it.

>> > > But that can be handled in an subsequent patch to keep your acks
>> > > and
>> > > reviews.
>> > I will respin the patch. Please comment on the acks and reviews.
>> > They
>> > were made at an earlier version of the patch. That version no longer
>> > applies. Can the updated version carry on the flags?
>> I don't get you. If you mean keeping CONFIG_SERIAL_8250_PXA, then yes,
>> please
>> keep it.
>
> I mean should the patch be re-revied and re-acked?
Well it depends on what was since then. If it's a trivial commit message fix or
a typo, I don't think it's necessary. If it's the algorithm, the code logic, or
even I think you should ask again.

For a name change in CONFIG_SERIAL_PXA into CONFIG_SERIAL_8250_PXA (change from
v3 to v4), I must admit I don't know. Maybe Kevin or Arnd might give a clue.

Cheers.

-- 
Robert

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

* [PATCH v4 1/2] serial: rewrite pxa2xx-uart to use 8250_core
@ 2015-12-19 23:12                           ` Robert Jarzmik
  0 siblings, 0 replies; 700+ messages in thread
From: Robert Jarzmik @ 2015-12-19 23:12 UTC (permalink / raw)
  To: linux-arm-kernel

Sergei Ianovich <ynvich@gmail.com> writes:

> On Sat, 2015-12-19 at 20:31 +0100, Robert Jarzmik wrote:
>> Sergei Ianovich <ynvich@gmail.com> writes:
>> Thanks for spotting this. This is caused by a change in the latest
>> > version of the patch (SERIAL_8250_PXA instead of SERIAL_PXA). This
>> > change could be reverted.
>> Actually I'm against the revert.
>> The name change looks very good to me, please keep it.
>
> Is it worth adding an error if CONFIG_SERIAL_PXA is defined?
I don't think so.

> Or is there any other way of preventing this patch launching Linus' "flag
> days" as Russel King named it?
I must think about it, and test a bit more.
Ah and a small hint : if you include back Russell in the conversation, don't
forget the double "ll" if you wish him to answer.

> I understand that people are afraid of taking this patch. If it starts
> causing troubles at runtime, it will be difficult to diagnose. There
> will be no console for most people. So it is probably good idea to fail
> at boot time.
Who are "the people" ? If it's about something already written in a mailing
list, please point me to it so that it can help me think about it.

>> > > But that can be handled in an subsequent patch to keep your acks
>> > > and
>> > > reviews.
>> > I will respin the patch. Please comment on the acks and reviews.
>> > They
>> > were made at an earlier version of the patch. That version no longer
>> > applies. Can the updated version carry on the flags?
>> I don't get you. If you mean keeping CONFIG_SERIAL_8250_PXA, then yes,
>> please
>> keep it.
>
> I mean should the patch be re-revied and re-acked?
Well it depends on what was since then. If it's a trivial commit message fix or
a typo, I don't think it's necessary. If it's the algorithm, the code logic, or
even I think you should ask again.

For a name change in CONFIG_SERIAL_PXA into CONFIG_SERIAL_8250_PXA (change from
v3 to v4), I must admit I don't know. Maybe Kevin or Arnd might give a clue.

Cheers.

-- 
Robert

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

* Re: [PATCH v5] mtd: support BB SRAM on ICP DAS LP-8x4x
  2015-12-15 18:58                     ` Sergei Ianovich
@ 2015-12-20  3:38                       ` Rob Herring
  -1 siblings, 0 replies; 700+ messages in thread
From: Rob Herring @ 2015-12-20  3:38 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: linux-kernel, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	David Woodhouse, Brian Norris, Jeremy Kerr, Cyril Bur,
	Neelesh Gupta, Michael Ellerman, Joel Stanley,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	open list:MEMORY TECHNOLOGY DEVICES (MTD)

On Tue, Dec 15, 2015 at 09:58:53PM +0300, Sergei Ianovich wrote:
> This provides an MTD device driver for 512kB of battery backed up SRAM
> on ICPDAS LP-8X4X programmable automation controllers.
> 
> SRAM chip is connected via FPGA and is not accessible without a driver,
> unlike flash memory which is wired to CPU MMU.
> 
> This SRAM becomes an excellent persisent storage of volatile process
> data like counter values and sensor statuses. Storing those data in
> flash or mmc card is not a viable solution.
> 
> Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
> Reviewed-by: Brian Norris <computersforpeace@gmail.com>
> ---
>    v4..v5
>    * remove .owner from struct platform_driver
>    * constify struct of_device_id
>     for further Brian Norris comments:
>    * drop unused property from doc file
>    * move defconfig update to a different file
>    * drop extra match w/ of_match_device()
> 
>    v3..v4 for Brian Norris 'Reviewed-by'
>    * add doc file for DT binding
>    * move DTS binding to a different patch (8/21)
>    * drop unused include directive
>    * drop safely unused callback
>    * drop non-default partion probe types
>    * drop duplicate error checks
>    * drop duplicate error reporting
>    * fixed error message on MTD registeration
>    * fixed module removal routine
> 
>    v2..v3
>    * no changes (except number 08/16 -> 10/21)
> 
>    v0..v2
>    * use device tree
>    * use devm helpers where possible
> 
>  .../devicetree/bindings/mtd/sram-lp8x4x.txt        |  20 +++
>  drivers/mtd/devices/Kconfig                        |  14 ++
>  drivers/mtd/devices/Makefile                       |   1 +
>  drivers/mtd/devices/sram_lp8x4x.c                  | 199 +++++++++++++++++++++
>  4 files changed, 234 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/mtd/sram-lp8x4x.txt
>  create mode 100644 drivers/mtd/devices/sram_lp8x4x.c
> 
> diff --git a/Documentation/devicetree/bindings/mtd/sram-lp8x4x.txt b/Documentation/devicetree/bindings/mtd/sram-lp8x4x.txt
> new file mode 100644
> index 0000000..476934f
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/mtd/sram-lp8x4x.txt
> @@ -0,0 +1,20 @@
> +512kB battery backed up SRAM on LP-8x4x industrial computers
> +
> +Required properties:
> +- compatible : should be "icpdas,sram-lp8x4x"

No wildcards please. Otherwise looks fine.

> +
> +- reg: physical base addresses and region lengths of
> +       * IO memory range
> +       * SRAM page selector
> +
> +SRAM chip is connected via FPGA and is not accessible without a driver,
> +unlike flash memory which is wired to CPU MMU. Driver is essentially
> +an address translation routine.
> +
> +Example:
> +
> +	sram@a000 {
> +		compatible = "icpdas,sram-lp8x4x";
> +		reg = <0xa000 0x1000
> +		       0x901e 0x1>;
> +	};

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

* Re: [PATCH v5] mtd: support BB SRAM on ICP DAS LP-8x4x
@ 2015-12-20  3:38                       ` Rob Herring
  0 siblings, 0 replies; 700+ messages in thread
From: Rob Herring @ 2015-12-20  3:38 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: linux-kernel, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	David Woodhouse, Brian Norris, Jeremy Kerr, Cyril Bur,
	Neelesh Gupta, Michael Ellerman, Joel Stanley,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	open list:MEMORY TECHNOLOGY DEVICES (MTD)

On Tue, Dec 15, 2015 at 09:58:53PM +0300, Sergei Ianovich wrote:
> This provides an MTD device driver for 512kB of battery backed up SRAM
> on ICPDAS LP-8X4X programmable automation controllers.
> 
> SRAM chip is connected via FPGA and is not accessible without a driver,
> unlike flash memory which is wired to CPU MMU.
> 
> This SRAM becomes an excellent persisent storage of volatile process
> data like counter values and sensor statuses. Storing those data in
> flash or mmc card is not a viable solution.
> 
> Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
> Reviewed-by: Brian Norris <computersforpeace@gmail.com>
> ---
>    v4..v5
>    * remove .owner from struct platform_driver
>    * constify struct of_device_id
>     for further Brian Norris comments:
>    * drop unused property from doc file
>    * move defconfig update to a different file
>    * drop extra match w/ of_match_device()
> 
>    v3..v4 for Brian Norris 'Reviewed-by'
>    * add doc file for DT binding
>    * move DTS binding to a different patch (8/21)
>    * drop unused include directive
>    * drop safely unused callback
>    * drop non-default partion probe types
>    * drop duplicate error checks
>    * drop duplicate error reporting
>    * fixed error message on MTD registeration
>    * fixed module removal routine
> 
>    v2..v3
>    * no changes (except number 08/16 -> 10/21)
> 
>    v0..v2
>    * use device tree
>    * use devm helpers where possible
> 
>  .../devicetree/bindings/mtd/sram-lp8x4x.txt        |  20 +++
>  drivers/mtd/devices/Kconfig                        |  14 ++
>  drivers/mtd/devices/Makefile                       |   1 +
>  drivers/mtd/devices/sram_lp8x4x.c                  | 199 +++++++++++++++++++++
>  4 files changed, 234 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/mtd/sram-lp8x4x.txt
>  create mode 100644 drivers/mtd/devices/sram_lp8x4x.c
> 
> diff --git a/Documentation/devicetree/bindings/mtd/sram-lp8x4x.txt b/Documentation/devicetree/bindings/mtd/sram-lp8x4x.txt
> new file mode 100644
> index 0000000..476934f
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/mtd/sram-lp8x4x.txt
> @@ -0,0 +1,20 @@
> +512kB battery backed up SRAM on LP-8x4x industrial computers
> +
> +Required properties:
> +- compatible : should be "icpdas,sram-lp8x4x"

No wildcards please. Otherwise looks fine.

> +
> +- reg: physical base addresses and region lengths of
> +       * IO memory range
> +       * SRAM page selector
> +
> +SRAM chip is connected via FPGA and is not accessible without a driver,
> +unlike flash memory which is wired to CPU MMU. Driver is essentially
> +an address translation routine.
> +
> +Example:
> +
> +	sram@a000 {
> +		compatible = "icpdas,sram-lp8x4x";
> +		reg = <0xa000 0x1000
> +		       0x901e 0x1>;
> +	};

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

* Re: [PATCH v5] mtd: support BB SRAM on ICP DAS LP-8x4x
  2015-12-20  3:38                       ` Rob Herring
  (?)
@ 2015-12-20 10:43                         ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2015-12-20 10:43 UTC (permalink / raw)
  To: Rob Herring
  Cc: linux-kernel, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	David Woodhouse, Brian Norris, Jeremy Kerr, Cyril Bur,
	Neelesh Gupta, Michael Ellerman, Joel Stanley,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	open list:MEMORY TECHNOLOGY DEVICES (MTD),
	Arnd Bergmann

On Sat, 2015-12-19 at 21:38 -0600, Rob Herring wrote:
> On Tue, Dec 15, 2015 at 09:58:53PM +0300, Sergei Ianovich wrote:
> > This provides an MTD device driver for 512kB of battery backed up
> > SRAM
> > on ICPDAS LP-8X4X programmable automation controllers.
> > 
> > SRAM chip is connected via FPGA and is not accessible without a
> > driver,
> > unlike flash memory which is wired to CPU MMU.
> > 
> > This SRAM becomes an excellent persisent storage of volatile process
> > data like counter values and sensor statuses. Storing those data in
> > flash or mmc card is not a viable solution.
> > 
> > Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
> > Reviewed-by: Brian Norris <computersforpeace@gmail.com>
> > ---
> >    v4..v5
> >    * remove .owner from struct platform_driver
> >    * constify struct of_device_id
> >     for further Brian Norris comments:
> >    * drop unused property from doc file
> >    * move defconfig update to a different file
> >    * drop extra match w/ of_match_device()
> > 
> >    v3..v4 for Brian Norris 'Reviewed-by'
> >    * add doc file for DT binding
> >    * move DTS binding to a different patch (8/21)
> >    * drop unused include directive
> >    * drop safely unused callback
> >    * drop non-default partion probe types
> >    * drop duplicate error checks
> >    * drop duplicate error reporting
> >    * fixed error message on MTD registeration
> >    * fixed module removal routine
> > 
> >    v2..v3
> >    * no changes (except number 08/16 -> 10/21)
> > 
> >    v0..v2
> >    * use device tree
> >    * use devm helpers where possible
> > 
> >  .../devicetree/bindings/mtd/sram-lp8x4x.txt        |  20 +++
> >  drivers/mtd/devices/Kconfig                        |  14 ++
> >  drivers/mtd/devices/Makefile                       |   1 +
> >  drivers/mtd/devices/sram_lp8x4x.c                  | 199
> > +++++++++++++++++++++
> >  4 files changed, 234 insertions(+)
> >  create mode 100644 Documentation/devicetree/bindings/mtd/sram-
> > lp8x4x.txt
> >  create mode 100644 drivers/mtd/devices/sram_lp8x4x.c
> > 
> > diff --git a/Documentation/devicetree/bindings/mtd/sram-lp8x4x.txt
> > b/Documentation/devicetree/bindings/mtd/sram-lp8x4x.txt
> > new file mode 100644
> > index 0000000..476934f
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/mtd/sram-lp8x4x.txt
> > @@ -0,0 +1,20 @@
> > +512kB battery backed up SRAM on LP-8x4x industrial computers
> > +
> > +Required properties:
> > +- compatible : should be "icpdas,sram-lp8x4x"
> 
> No wildcards please. Otherwise looks fine.

There is a similar review comment from Arnd Bergmann in the discussion
of `[PATCH v5] serial: support for 16550A serial ports on LP-8x4x`.

I'll quote my latest clarification:
> ... This driver will support ports on LP-8081, 
> LP-8141, LP-8441, LP-8841. Last time I checked the vendor was announcing
> a series with 3 as the last digit. They use lp8x4x name, eg. in
> documentation like `LP-8x4x_ChangeLog.txt`. They ship their proprietary
> SDK in `lp8x4x_sdk_for_linux.tar`. All of this implies that it is a
> single board.

I think the solution should be the same for all LP-8x4x drivers (IRQ,
SRAM, SERIAL, IIO).

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

* Re: [PATCH v5] mtd: support BB SRAM on ICP DAS LP-8x4x
@ 2015-12-20 10:43                         ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2015-12-20 10:43 UTC (permalink / raw)
  To: Rob Herring
  Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, David Woodhouse, Brian Norris,
	Jeremy Kerr, Cyril Bur, Neelesh Gupta, Michael Ellerman,
	Joel Stanley,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	open list:MEMORY TECHNOLOGY DEVICES (MTD),
	Arnd Bergmann

On Sat, 2015-12-19 at 21:38 -0600, Rob Herring wrote:
> On Tue, Dec 15, 2015 at 09:58:53PM +0300, Sergei Ianovich wrote:
> > This provides an MTD device driver for 512kB of battery backed up
> > SRAM
> > on ICPDAS LP-8X4X programmable automation controllers.
> > 
> > SRAM chip is connected via FPGA and is not accessible without a
> > driver,
> > unlike flash memory which is wired to CPU MMU.
> > 
> > This SRAM becomes an excellent persisent storage of volatile process
> > data like counter values and sensor statuses. Storing those data in
> > flash or mmc card is not a viable solution.
> > 
> > Signed-off-by: Sergei Ianovich <ynvich-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> > Reviewed-by: Brian Norris <computersforpeace-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> > ---
> >    v4..v5
> >    * remove .owner from struct platform_driver
> >    * constify struct of_device_id
> >     for further Brian Norris comments:
> >    * drop unused property from doc file
> >    * move defconfig update to a different file
> >    * drop extra match w/ of_match_device()
> > 
> >    v3..v4 for Brian Norris 'Reviewed-by'
> >    * add doc file for DT binding
> >    * move DTS binding to a different patch (8/21)
> >    * drop unused include directive
> >    * drop safely unused callback
> >    * drop non-default partion probe types
> >    * drop duplicate error checks
> >    * drop duplicate error reporting
> >    * fixed error message on MTD registeration
> >    * fixed module removal routine
> > 
> >    v2..v3
> >    * no changes (except number 08/16 -> 10/21)
> > 
> >    v0..v2
> >    * use device tree
> >    * use devm helpers where possible
> > 
> >  .../devicetree/bindings/mtd/sram-lp8x4x.txt        |  20 +++
> >  drivers/mtd/devices/Kconfig                        |  14 ++
> >  drivers/mtd/devices/Makefile                       |   1 +
> >  drivers/mtd/devices/sram_lp8x4x.c                  | 199
> > +++++++++++++++++++++
> >  4 files changed, 234 insertions(+)
> >  create mode 100644 Documentation/devicetree/bindings/mtd/sram-
> > lp8x4x.txt
> >  create mode 100644 drivers/mtd/devices/sram_lp8x4x.c
> > 
> > diff --git a/Documentation/devicetree/bindings/mtd/sram-lp8x4x.txt
> > b/Documentation/devicetree/bindings/mtd/sram-lp8x4x.txt
> > new file mode 100644
> > index 0000000..476934f
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/mtd/sram-lp8x4x.txt
> > @@ -0,0 +1,20 @@
> > +512kB battery backed up SRAM on LP-8x4x industrial computers
> > +
> > +Required properties:
> > +- compatible : should be "icpdas,sram-lp8x4x"
> 
> No wildcards please. Otherwise looks fine.

There is a similar review comment from Arnd Bergmann in the discussion
of `[PATCH v5] serial: support for 16550A serial ports on LP-8x4x`.

I'll quote my latest clarification:
> ... This driver will support ports on LP-8081, 
> LP-8141, LP-8441, LP-8841. Last time I checked the vendor was announcing
> a series with 3 as the last digit. They use lp8x4x name, eg. in
> documentation like `LP-8x4x_ChangeLog.txt`. They ship their proprietary
> SDK in `lp8x4x_sdk_for_linux.tar`. All of this implies that it is a
> single board.

I think the solution should be the same for all LP-8x4x drivers (IRQ,
SRAM, SERIAL, IIO).
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH v5] mtd: support BB SRAM on ICP DAS LP-8x4x
@ 2015-12-20 10:43                         ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2015-12-20 10:43 UTC (permalink / raw)
  To: Rob Herring
  Cc: linux-kernel, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	David Woodhouse, Brian Norris, Jeremy Kerr, Cyril Bur,
	Neelesh Gupta, Michael Ellerman, Joel Stanley,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	open list:MEMORY TECHNOLOGY DEVICES (MTD),
	Arnd Bergmann

On Sat, 2015-12-19 at 21:38 -0600, Rob Herring wrote:
> On Tue, Dec 15, 2015 at 09:58:53PM +0300, Sergei Ianovich wrote:
> > This provides an MTD device driver for 512kB of battery backed up
> > SRAM
> > on ICPDAS LP-8X4X programmable automation controllers.
> > 
> > SRAM chip is connected via FPGA and is not accessible without a
> > driver,
> > unlike flash memory which is wired to CPU MMU.
> > 
> > This SRAM becomes an excellent persisent storage of volatile process
> > data like counter values and sensor statuses. Storing those data in
> > flash or mmc card is not a viable solution.
> > 
> > Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
> > Reviewed-by: Brian Norris <computersforpeace@gmail.com>
> > ---
> >    v4..v5
> >    * remove .owner from struct platform_driver
> >    * constify struct of_device_id
> >     for further Brian Norris comments:
> >    * drop unused property from doc file
> >    * move defconfig update to a different file
> >    * drop extra match w/ of_match_device()
> > 
> >    v3..v4 for Brian Norris 'Reviewed-by'
> >    * add doc file for DT binding
> >    * move DTS binding to a different patch (8/21)
> >    * drop unused include directive
> >    * drop safely unused callback
> >    * drop non-default partion probe types
> >    * drop duplicate error checks
> >    * drop duplicate error reporting
> >    * fixed error message on MTD registeration
> >    * fixed module removal routine
> > 
> >    v2..v3
> >    * no changes (except number 08/16 -> 10/21)
> > 
> >    v0..v2
> >    * use device tree
> >    * use devm helpers where possible
> > 
> >  .../devicetree/bindings/mtd/sram-lp8x4x.txt        |  20 +++
> >  drivers/mtd/devices/Kconfig                        |  14 ++
> >  drivers/mtd/devices/Makefile                       |   1 +
> >  drivers/mtd/devices/sram_lp8x4x.c                  | 199
> > +++++++++++++++++++++
> >  4 files changed, 234 insertions(+)
> >  create mode 100644 Documentation/devicetree/bindings/mtd/sram-
> > lp8x4x.txt
> >  create mode 100644 drivers/mtd/devices/sram_lp8x4x.c
> > 
> > diff --git a/Documentation/devicetree/bindings/mtd/sram-lp8x4x.txt
> > b/Documentation/devicetree/bindings/mtd/sram-lp8x4x.txt
> > new file mode 100644
> > index 0000000..476934f
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/mtd/sram-lp8x4x.txt
> > @@ -0,0 +1,20 @@
> > +512kB battery backed up SRAM on LP-8x4x industrial computers
> > +
> > +Required properties:
> > +- compatible : should be "icpdas,sram-lp8x4x"
> 
> No wildcards please. Otherwise looks fine.

There is a similar review comment from Arnd Bergmann in the discussion
of `[PATCH v5] serial: support for 16550A serial ports on LP-8x4x`.

I'll quote my latest clarification:
> ... This driver will support ports on LP-8081, 
> LP-8141, LP-8441, LP-8841. Last time I checked the vendor was announcing
> a series with 3 as the last digit. They use lp8x4x name, eg. in
> documentation like `LP-8x4x_ChangeLog.txt`. They ship their proprietary
> SDK in `lp8x4x_sdk_for_linux.tar`. All of this implies that it is a
> single board.

I think the solution should be the same for all LP-8x4x drivers (IRQ,
SRAM, SERIAL, IIO).

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

* Re: [PATCH v4 1/2] serial: rewrite pxa2xx-uart to use 8250_core
  2015-12-19 23:12                           ` Robert Jarzmik
@ 2015-12-20 11:24                             ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2015-12-20 11:24 UTC (permalink / raw)
  To: Robert Jarzmik, Kevin Hilman, Arnd Bergmann
  Cc: Greg Kroah-Hartman, Russell King - ARM Linux, linux-kernel,
	moderated list:ARM PORT, open list:SERIAL DRIVERS

On Sun, 2015-12-20 at 00:12 +0100, Robert Jarzmik wrote:
> Sergei Ianovich <ynvich@gmail.com> writes:
> 
> > On Sat, 2015-12-19 at 20:31 +0100, Robert Jarzmik wrote:
> > > Sergei Ianovich <ynvich@gmail.com> writes:
> > > Thanks for spotting this. This is caused by a change in the latest
> > > > version of the patch (SERIAL_8250_PXA instead of SERIAL_PXA).
> > > > This
> > > > change could be reverted.
> > > Actually I'm against the revert.
> > > The name change looks very good to me, please keep it.
> > 
> > Is it worth adding an error if CONFIG_SERIAL_PXA is defined?
> I don't think so.

...

> 
> > I understand that people are afraid of taking this patch. If it
> > starts
> > causing troubles at runtime, it will be difficult to diagnose. There
> > will be no console for most people. So it is probably good idea to
> > fail
> > at boot time.
> Who are "the people" ? 

I think "the people" are at least Greg Kroah-Hartman and Russell King.

> If it's about something already written in a mailing
> list, please point me to it so that it can help me think about it.

http://lists.infradead.org/pipermail/linux-arm-kernel/2013-December/2167
73.html

I can explain why I think so. Greg acked the patch, but hasn't merged it
since then. He has good reasons for this most probably. Russell's
comment pointed by the link seems to be the reason.

I think the problem raised by Russell could be addressed. My best guess
is compile time error, despite your comment above.

I have one more plan. For transition period, we can introduce a
temporary Kconfig option SERIAL_8250_PXA_OFF, and fail at build time if
neither SERIAL_8250_PXA nor SERIAL_8250_PXA_OFF is set. This way all
interested parties will be notified of this driver update.

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

* [PATCH v4 1/2] serial: rewrite pxa2xx-uart to use 8250_core
@ 2015-12-20 11:24                             ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2015-12-20 11:24 UTC (permalink / raw)
  To: linux-arm-kernel

On Sun, 2015-12-20 at 00:12 +0100, Robert Jarzmik wrote:
> Sergei Ianovich <ynvich@gmail.com> writes:
> 
> > On Sat, 2015-12-19 at 20:31 +0100, Robert Jarzmik wrote:
> > > Sergei Ianovich <ynvich@gmail.com> writes:
> > > Thanks for spotting this. This is caused by a change in the latest
> > > > version of the patch (SERIAL_8250_PXA instead of SERIAL_PXA).
> > > > This
> > > > change could be reverted.
> > > Actually I'm against the revert.
> > > The name change looks very good to me, please keep it.
> > 
> > Is it worth adding an error if CONFIG_SERIAL_PXA is defined?
> I don't think so.

...

> 
> > I understand that people are afraid of taking this patch. If it
> > starts
> > causing troubles at runtime, it will be difficult to diagnose. There
> > will be no console for most people. So it is probably good idea to
> > fail
> > at boot time.
> Who are "the people" ? 

I think "the people" are at least Greg Kroah-Hartman and?Russell King.

> If it's about something already written in a mailing
> list, please point me to it so that it can help me think about it.

http://lists.infradead.org/pipermail/linux-arm-kernel/2013-December/2167
73.html

I can explain why I think so. Greg acked the patch, but hasn't merged it
since then. He has good reasons for this most probably. Russell's
comment pointed by the link seems to be the reason.

I think the problem raised by Russell could be addressed. My best guess
is compile time error, despite your comment above.

I have one more plan. For transition period, we can introduce a
temporary Kconfig option SERIAL_8250_PXA_OFF, and fail at build time if
neither SERIAL_8250_PXA nor SERIAL_8250_PXA_OFF is set. This way all
interested parties will be notified of this driver update.

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

* Re: [PATCH v4 1/2] serial: rewrite pxa2xx-uart to use 8250_core
  2015-12-20 11:24                             ` Sergei Ianovich
  (?)
@ 2015-12-22 19:27                               ` Robert Jarzmik
  -1 siblings, 0 replies; 700+ messages in thread
From: Robert Jarzmik @ 2015-12-22 19:27 UTC (permalink / raw)
  To: Sergei Ianovich, Russell King - ARM Linux, Greg Kroah-Hartman
  Cc: Kevin Hilman, Arnd Bergmann, linux-kernel,
	moderated list:ARM PORT, open list:SERIAL DRIVERS

Sergei Ianovich <ynvich@gmail.com> writes:

> On Sun, 2015-12-20 at 00:12 +0100, Robert Jarzmik wrote:
>> Sergei Ianovich <ynvich@gmail.com> writes:
>> 
>> > On Sat, 2015-12-19 at 20:31 +0100, Robert Jarzmik wrote:
>> > I understand that people are afraid of taking this patch. If it
>> > starts
>> > causing troubles at runtime, it will be difficult to diagnose. There
>> > will be no console for most people. So it is probably good idea to
>> > fail
>> > at boot time.
>> If it's about something already written in a mailing
>> list, please point me to it so that it can help me think about it.
>
> http://lists.infradead.org/pipermail/linux-arm-kernel/2013-December/2167
> 73.html
>
> I can explain why I think so. Greg acked the patch, but hasn't merged it
> since then. He has good reasons for this most probably. Russell's
> comment pointed by the link seems to be the reason.

> I think the problem raised by Russell could be addressed. My best guess
> is compile time error, despite your comment above.
I re-read carefully Russell's answer in [1].

What Russell asked is that for a period of time, the old pxa serial code and the
new will be in the kernel, so that maintainers have the option to switch over to
the old drivers/tty/serial/pxa.c if the new 8250 based version breaks their
userspace getty.

Then, once the transition is done, and that for a period (let's say 1 year) no
maintainer had complained while its defconfig was switched over to the new 8520
version, then and only then you will remove drivers/tty/serial/pxa.c.

> I have one more plan. For transition period, we can introduce a
> temporary Kconfig option SERIAL_8250_PXA_OFF, and fail at build time if
> neither SERIAL_8250_PXA nor SERIAL_8250_PXA_OFF is set. This way all
> interested parties will be notified of this driver update.
No, I'd like to stick with Russell's original plan :
 - phase 1: both SERIAL_8250_PXA and SERIAL_PXA exist in KConfig
            both are selectable
            This lasts one year or something like that
 - phase 2: remove SERIAL_PXA from KConfig and drivers/tty/serial/pxa.c

This means a different patch from the one acked by Greg, and a new serie of
acks. The diffstat will be way worse (as you won't have the -970 for pxa.c), but
in the end it will end up on that -970.

That sounds like a good transition plan to me.

Cheers.

-- 
Robert

[1]
http://lists.infradead.org/pipermail/linux-arm-kernel/2013-December/216773.html

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

* Re: [PATCH v4 1/2] serial: rewrite pxa2xx-uart to use 8250_core
@ 2015-12-22 19:27                               ` Robert Jarzmik
  0 siblings, 0 replies; 700+ messages in thread
From: Robert Jarzmik @ 2015-12-22 19:27 UTC (permalink / raw)
  To: Sergei Ianovich, Russell King - ARM Linux, Greg Kroah-Hartman
  Cc: Kevin Hilman, Arnd Bergmann, linux-kernel,
	moderated list:ARM PORT, open list:SERIAL DRIVERS

Sergei Ianovich <ynvich@gmail.com> writes:

> On Sun, 2015-12-20 at 00:12 +0100, Robert Jarzmik wrote:
>> Sergei Ianovich <ynvich@gmail.com> writes:
>> 
>> > On Sat, 2015-12-19 at 20:31 +0100, Robert Jarzmik wrote:
>> > I understand that people are afraid of taking this patch. If it
>> > starts
>> > causing troubles at runtime, it will be difficult to diagnose. There
>> > will be no console for most people. So it is probably good idea to
>> > fail
>> > at boot time.
>> If it's about something already written in a mailing
>> list, please point me to it so that it can help me think about it.
>
> http://lists.infradead.org/pipermail/linux-arm-kernel/2013-December/2167
> 73.html
>
> I can explain why I think so. Greg acked the patch, but hasn't merged it
> since then. He has good reasons for this most probably. Russell's
> comment pointed by the link seems to be the reason.

> I think the problem raised by Russell could be addressed. My best guess
> is compile time error, despite your comment above.
I re-read carefully Russell's answer in [1].

What Russell asked is that for a period of time, the old pxa serial code and the
new will be in the kernel, so that maintainers have the option to switch over to
the old drivers/tty/serial/pxa.c if the new 8250 based version breaks their
userspace getty.

Then, once the transition is done, and that for a period (let's say 1 year) no
maintainer had complained while its defconfig was switched over to the new 8520
version, then and only then you will remove drivers/tty/serial/pxa.c.

> I have one more plan. For transition period, we can introduce a
> temporary Kconfig option SERIAL_8250_PXA_OFF, and fail at build time if
> neither SERIAL_8250_PXA nor SERIAL_8250_PXA_OFF is set. This way all
> interested parties will be notified of this driver update.
No, I'd like to stick with Russell's original plan :
 - phase 1: both SERIAL_8250_PXA and SERIAL_PXA exist in KConfig
            both are selectable
            This lasts one year or something like that
 - phase 2: remove SERIAL_PXA from KConfig and drivers/tty/serial/pxa.c

This means a different patch from the one acked by Greg, and a new serie of
acks. The diffstat will be way worse (as you won't have the -970 for pxa.c), but
in the end it will end up on that -970.

That sounds like a good transition plan to me.

Cheers.

-- 
Robert

[1]
http://lists.infradead.org/pipermail/linux-arm-kernel/2013-December/216773.html

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

* [PATCH v4 1/2] serial: rewrite pxa2xx-uart to use 8250_core
@ 2015-12-22 19:27                               ` Robert Jarzmik
  0 siblings, 0 replies; 700+ messages in thread
From: Robert Jarzmik @ 2015-12-22 19:27 UTC (permalink / raw)
  To: linux-arm-kernel

Sergei Ianovich <ynvich@gmail.com> writes:

> On Sun, 2015-12-20 at 00:12 +0100, Robert Jarzmik wrote:
>> Sergei Ianovich <ynvich@gmail.com> writes:
>> 
>> > On Sat, 2015-12-19 at 20:31 +0100, Robert Jarzmik wrote:
>> > I understand that people are afraid of taking this patch. If it
>> > starts
>> > causing troubles at runtime, it will be difficult to diagnose. There
>> > will be no console for most people. So it is probably good idea to
>> > fail
>> > at boot time.
>> If it's about something already written in a mailing
>> list, please point me to it so that it can help me think about it.
>
> http://lists.infradead.org/pipermail/linux-arm-kernel/2013-December/2167
> 73.html
>
> I can explain why I think so. Greg acked the patch, but hasn't merged it
> since then. He has good reasons for this most probably. Russell's
> comment pointed by the link seems to be the reason.

> I think the problem raised by Russell could be addressed. My best guess
> is compile time error, despite your comment above.
I re-read carefully Russell's answer in [1].

What Russell asked is that for a period of time, the old pxa serial code and the
new will be in the kernel, so that maintainers have the option to switch over to
the old drivers/tty/serial/pxa.c if the new 8250 based version breaks their
userspace getty.

Then, once the transition is done, and that for a period (let's say 1 year) no
maintainer had complained while its defconfig was switched over to the new 8520
version, then and only then you will remove drivers/tty/serial/pxa.c.

> I have one more plan. For transition period, we can introduce a
> temporary Kconfig option SERIAL_8250_PXA_OFF, and fail at build time if
> neither SERIAL_8250_PXA nor SERIAL_8250_PXA_OFF is set. This way all
> interested parties will be notified of this driver update.
No, I'd like to stick with Russell's original plan :
 - phase 1: both SERIAL_8250_PXA and SERIAL_PXA exist in KConfig
            both are selectable
            This lasts one year or something like that
 - phase 2: remove SERIAL_PXA from KConfig and drivers/tty/serial/pxa.c

This means a different patch from the one acked by Greg, and a new serie of
acks. The diffstat will be way worse (as you won't have the -970 for pxa.c), but
in the end it will end up on that -970.

That sounds like a good transition plan to me.

Cheers.

-- 
Robert

[1]
http://lists.infradead.org/pipermail/linux-arm-kernel/2013-December/216773.html

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

* [PATCH v5] serial: rewrite pxa2xx-uart to use 8250_core
  2015-12-09 22:28               ` Sergei Ianovich
@ 2015-12-23 18:59                 ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2015-12-23 18:59 UTC (permalink / raw)
  To: linux-kernel
  Cc: Sergei Ianovich, Heikki Krogerus, James Cameron,
	Greg Kroah-Hartman, Robert Jarzmik, Russell King, Jiri Slaby,
	Andy Shevchenko, Arnd Bergmann, Joachim Eastwood, Paul Burton,
	Mans Rullgard, Scott Wood, Sebastian Andrzej Siewior,
	Paul Gortmaker, Matthias Brugger, Peter Hurley,
	open list:SERIAL DRIVERS

pxa2xx-uart was a separate uart platform driver. It was declaring
the same device names and numbers as 8250 driver. As a result,
it was impossible to use 8250 driver on PXA SoCs.

Upon closer examination pxa2xx-uart turned out to be a clone of
8250_core driver.

Workaround for Erratum #19 according to Marvel(R) PXA270M Processor
Specification Update (April 19, 2010) is dropped. 8250_core reads
from FIFO immediately after checking DR bit in LSR.

The patch leaves the original SERIAL_PXA driver around. The original
driver is just marked DEPRECATED in Kconfig and C source. When
the original driver is considered safe to remove, no changes
to SERIAL_8250 will be necessary.

Compiling SERIAL_8250_CONSOLE and SERIAL_PXA_CONSOLE even without
SERIAL_8250_PXA breaks console for SERIAL_PXA. For this reasons, the new
and the original drivers are made mutually exclusive.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Heikki Krogerus <heikki.krogerus@linux.intel.com>
CC: James Cameron <quozl@laptop.org>
CC: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
CC: Robert Jarzmik <robert.jarzmik@free.fr>
CC: Russell King <linux@arm.linux.org.uk>

  The patch was reviewed/acked at version 3. Changes in version 4
  are simple unbitrotting. Changes in version 5 require re-review
  according to Robert Jarzmik comment.

  changes v4..v5 as suggested by Robert Jarzmik
  * keep pxa.c until it is considered safe to remove
  * keep SERIAL_PXA and SERIAL_PXA_CONSOLE Kconfig options,
    but deprecate them
  * allow selection of either the new or the original driver
    by Kconfig
  * ensure SERIAL_PXA_CONSOLE is respected with either driver

  changes v3..v4
  * remove owner field from platform_driver structure
  * make of_device_id structure constant
  * use CONFIG_SERIAL_8250_PXA instead of CONFIG_SERIAL_PXA

  changes v2..v3
  * remove devm_free/put as suggested by Heikki Krogerus
  * use SET_SYSTEM_SLEEP_PM_OPS macro to set pm ops as suggested
    by Heikki Krogerus

  changes v1..v2
  * actually implement workaround for E74 in dl_write as spooted
    by James Cameron
  * added comment about E19 in commit message
---
 drivers/tty/serial/8250/8250_pxa.c | 177 +++++++++++++++++++++++++++++++++++++
 drivers/tty/serial/8250/Kconfig    |   8 ++
 drivers/tty/serial/8250/Makefile   |   1 +
 drivers/tty/serial/Kconfig         |  17 +++-
 drivers/tty/serial/Makefile        |   2 +-
 drivers/tty/serial/pxa.c           |   4 +-
 6 files changed, 205 insertions(+), 4 deletions(-)
 create mode 100644 drivers/tty/serial/8250/8250_pxa.c

diff --git a/drivers/tty/serial/8250/8250_pxa.c b/drivers/tty/serial/8250/8250_pxa.c
new file mode 100644
index 0000000..6a14df0
--- /dev/null
+++ b/drivers/tty/serial/8250/8250_pxa.c
@@ -0,0 +1,177 @@
+/*
+ *  drivers/tty/serial/8250/8250_pxa.c -- driver for PXA on-board UARTS
+ *  Copyright:	(C) 2013 Sergei Ianovich <ynvich@gmail.com>
+ *
+ *  replaces drivers/serial/pxa.c by Nicolas Pitre
+ *  Created:	Feb 20, 2003
+ *  Copyright:	(C) 2003 Monta Vista Software, Inc.
+ *
+ *  Based on drivers/serial/8250.c by Russell King.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/serial_8250.h>
+#include <linux/serial_core.h>
+#include <linux/serial_reg.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
+#include <linux/pm_runtime.h>
+
+#include "8250.h"
+
+struct pxa8250_data {
+	int			line;
+	struct clk		*clk;
+};
+
+#ifdef CONFIG_PM
+static int serial_pxa_suspend(struct device *dev)
+{
+	struct pxa8250_data *data = dev_get_drvdata(dev);
+
+	serial8250_suspend_port(data->line);
+
+	return 0;
+}
+
+static int serial_pxa_resume(struct device *dev)
+{
+	struct pxa8250_data *data = dev_get_drvdata(dev);
+
+	serial8250_resume_port(data->line);
+
+	return 0;
+}
+#endif
+
+static const struct dev_pm_ops serial_pxa_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(serial_pxa_suspend, serial_pxa_resume)
+};
+
+static const struct of_device_id serial_pxa_dt_ids[] = {
+	{ .compatible = "mrvl,pxa-uart", },
+	{ .compatible = "mrvl,mmp-uart", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, serial_pxa_dt_ids);
+
+/* Uart divisor latch write */
+static void serial_pxa_dl_write(struct uart_8250_port *up, int value)
+{
+	unsigned int dll;
+
+	serial_out(up, UART_DLL, value & 0xff);
+	/*
+	 * work around Erratum #74 according to Marvel(R) PXA270M Processor
+	 * Specification Update (April 19, 2010)
+	 */
+	dll = serial_in(up, UART_DLL);
+	WARN_ON(dll != (value & 0xff));
+
+	serial_out(up, UART_DLM, value >> 8 & 0xff);
+}
+
+
+static void serial_pxa_pm(struct uart_port *port, unsigned int state,
+	      unsigned int oldstate)
+{
+	struct pxa8250_data *data = port->private_data;
+
+	if (!state)
+		clk_prepare_enable(data->clk);
+	else
+		clk_disable_unprepare(data->clk);
+}
+
+static int serial_pxa_probe(struct platform_device *pdev)
+{
+	struct uart_8250_port uart = {};
+	struct pxa8250_data *data;
+	struct resource *mmres, *irqres;
+	int ret;
+
+	mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	irqres = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!mmres || !irqres)
+		return -ENODEV;
+
+	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(data->clk))
+		return PTR_ERR(data->clk);
+
+	ret = clk_prepare(data->clk);
+	if (ret)
+		return ret;
+
+	uart.port.type = PORT_XSCALE;
+	uart.port.iotype = UPIO_MEM32;
+	uart.port.mapbase = mmres->start;
+	uart.port.regshift = 2;
+	uart.port.irq = irqres->start;
+	uart.port.fifosize = 64;
+	uart.port.flags = UPF_IOREMAP | UPF_SKIP_TEST;
+	uart.port.dev = &pdev->dev;
+	uart.port.uartclk = clk_get_rate(data->clk);
+	uart.port.pm = serial_pxa_pm;
+	uart.port.private_data = data;
+	uart.dl_write = serial_pxa_dl_write;
+
+	ret = serial8250_register_8250_port(&uart);
+	if (ret < 0)
+		goto err_clk;
+
+	data->line = ret;
+
+	platform_set_drvdata(pdev, data);
+
+	return 0;
+
+ err_clk:
+	clk_unprepare(data->clk);
+	return ret;
+}
+
+static int serial_pxa_remove(struct platform_device *pdev)
+{
+	struct pxa8250_data *data = platform_get_drvdata(pdev);
+
+	serial8250_unregister_port(data->line);
+
+	clk_unprepare(data->clk);
+
+	return 0;
+}
+
+static struct platform_driver serial_pxa_driver = {
+	.probe          = serial_pxa_probe,
+	.remove         = serial_pxa_remove,
+
+	.driver		= {
+		.name	= "pxa2xx-uart",
+		.pm	= &serial_pxa_pm_ops,
+		.of_match_table = serial_pxa_dt_ids,
+	},
+};
+
+module_platform_driver(serial_pxa_driver);
+
+MODULE_AUTHOR("Sergei Ianovich");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:pxa2xx-uart");
diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
index 6412f14..4dc45ff 100644
--- a/drivers/tty/serial/8250/Kconfig
+++ b/drivers/tty/serial/8250/Kconfig
@@ -378,3 +378,11 @@ config SERIAL_8250_MID
 	  Selecting this option will enable handling of the extra features
 	  present on the UART found on Intel Medfield SOC and various other
 	  Intel platforms.
+
+config SERIAL_8250_PXA
+	tristate "PXA serial port support"
+	depends on SERIAL_8250
+	depends on ARCH_PXA || ARCH_MMP
+	help
+	  If you have a machine based on an Intel XScale PXA2xx CPU you
+	  can enable its onboard serial ports by enabling this option.
diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile
index e177f86..7e54413 100644
--- a/drivers/tty/serial/8250/Makefile
+++ b/drivers/tty/serial/8250/Makefile
@@ -28,5 +28,6 @@ obj-$(CONFIG_SERIAL_8250_MT6577)	+= 8250_mtk.o
 obj-$(CONFIG_SERIAL_8250_UNIPHIER)	+= 8250_uniphier.o
 obj-$(CONFIG_SERIAL_8250_INGENIC)	+= 8250_ingenic.o
 obj-$(CONFIG_SERIAL_8250_MID)		+= 8250_mid.o
+obj-$(CONFIG_SERIAL_8250_PXA)		+= 8250_pxa.o
 
 CFLAGS_8250_ingenic.o += -I$(srctree)/scripts/dtc/libfdt
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index f38beb2..e477ff5 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -436,17 +436,27 @@ config SERIAL_MPSC_CONSOLE
 	  Say Y here if you want to support a serial console on a Marvell MPSC.
 
 config SERIAL_PXA
-	bool "PXA serial port support"
+	bool "PXA serial port support (DEPRECATED)"
 	depends on ARCH_PXA || ARCH_MMP
 	select SERIAL_CORE
+	select SERIAL_8250_PXA if SERIAL_8250
+	select SERIAL_PXA_NON8250 if !SERIAL_8250
 	help
 	  If you have a machine based on an Intel XScale PXA2xx CPU you
 	  can enable its onboard serial ports by enabling this option.
 
+	  Unless you have a specific need, you should use SERIAL_8250_PXA
+	  instead of this.
+
+config SERIAL_PXA_NON8250
+	bool
+	depends on !SERIAL_8250
+
 config SERIAL_PXA_CONSOLE
-	bool "Console on PXA serial port"
+	bool "Console on PXA serial port (DEPRECATED)"
 	depends on SERIAL_PXA
 	select SERIAL_CORE_CONSOLE
+	select SERIAL_8250_CONSOLE if SERIAL_8250
 	help
 	  If you have enabled the serial port on the Intel XScale PXA
 	  CPU you can make it the console by answering Y to this option.
@@ -458,6 +468,9 @@ config SERIAL_PXA_CONSOLE
 	  your boot loader (lilo or loadlin) about how to pass options to the
 	  kernel at boot time.)
 
+	  Unless you have a specific need, you should use SERIAL_8250_PXA
+	  and SERIAL_8250_CONSOLE instead of this.
+
 config SERIAL_SA1100
 	bool "SA1100 serial port support"
 	depends on ARCH_SA1100
diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile
index 5ab4111..96741d5 100644
--- a/drivers/tty/serial/Makefile
+++ b/drivers/tty/serial/Makefile
@@ -23,7 +23,7 @@ obj-$(CONFIG_SERIAL_8250) += 8250/
 obj-$(CONFIG_SERIAL_AMBA_PL010) += amba-pl010.o
 obj-$(CONFIG_SERIAL_AMBA_PL011) += amba-pl011.o
 obj-$(CONFIG_SERIAL_CLPS711X) += clps711x.o
-obj-$(CONFIG_SERIAL_PXA) += pxa.o
+obj-$(CONFIG_SERIAL_PXA_NON8250) += pxa.o
 obj-$(CONFIG_SERIAL_PNX8XXX) += pnx8xxx_uart.o
 obj-$(CONFIG_SERIAL_SA1100) += sa1100.o
 obj-$(CONFIG_SERIAL_BCM63XX) += bcm63xx_uart.o
diff --git a/drivers/tty/serial/pxa.c b/drivers/tty/serial/pxa.c
index 9becba6..74aac45 100644
--- a/drivers/tty/serial/pxa.c
+++ b/drivers/tty/serial/pxa.c
@@ -940,7 +940,9 @@ static struct platform_driver serial_pxa_driver = {
 	},
 };
 
-static int __init serial_pxa_init(void)
+
+/* 8250 driver for PXA serial ports should be used */
+static int __deprecated __init serial_pxa_init(void)
 {
 	int ret;
 
-- 
2.6.3


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

* [PATCH v5] serial: rewrite pxa2xx-uart to use 8250_core
@ 2015-12-23 18:59                 ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2015-12-23 18:59 UTC (permalink / raw)
  To: linux-kernel
  Cc: Sergei Ianovich, Heikki Krogerus, James Cameron,
	Greg Kroah-Hartman, Robert Jarzmik, Russell King, Jiri Slaby,
	Andy Shevchenko, Arnd Bergmann, Joachim Eastwood, Paul Burton,
	Mans Rullgard, Scott Wood, Sebastian Andrzej Siewior,
	Paul Gortmaker, Matthias Brugger, Peter Hurley,
	open list:SERIAL DRIVERS

pxa2xx-uart was a separate uart platform driver. It was declaring
the same device names and numbers as 8250 driver. As a result,
it was impossible to use 8250 driver on PXA SoCs.

Upon closer examination pxa2xx-uart turned out to be a clone of
8250_core driver.

Workaround for Erratum #19 according to Marvel(R) PXA270M Processor
Specification Update (April 19, 2010) is dropped. 8250_core reads
from FIFO immediately after checking DR bit in LSR.

The patch leaves the original SERIAL_PXA driver around. The original
driver is just marked DEPRECATED in Kconfig and C source. When
the original driver is considered safe to remove, no changes
to SERIAL_8250 will be necessary.

Compiling SERIAL_8250_CONSOLE and SERIAL_PXA_CONSOLE even without
SERIAL_8250_PXA breaks console for SERIAL_PXA. For this reasons, the new
and the original drivers are made mutually exclusive.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Heikki Krogerus <heikki.krogerus@linux.intel.com>
CC: James Cameron <quozl@laptop.org>
CC: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
CC: Robert Jarzmik <robert.jarzmik@free.fr>
CC: Russell King <linux@arm.linux.org.uk>

  The patch was reviewed/acked at version 3. Changes in version 4
  are simple unbitrotting. Changes in version 5 require re-review
  according to Robert Jarzmik comment.

  changes v4..v5 as suggested by Robert Jarzmik
  * keep pxa.c until it is considered safe to remove
  * keep SERIAL_PXA and SERIAL_PXA_CONSOLE Kconfig options,
    but deprecate them
  * allow selection of either the new or the original driver
    by Kconfig
  * ensure SERIAL_PXA_CONSOLE is respected with either driver

  changes v3..v4
  * remove owner field from platform_driver structure
  * make of_device_id structure constant
  * use CONFIG_SERIAL_8250_PXA instead of CONFIG_SERIAL_PXA

  changes v2..v3
  * remove devm_free/put as suggested by Heikki Krogerus
  * use SET_SYSTEM_SLEEP_PM_OPS macro to set pm ops as suggested
    by Heikki Krogerus

  changes v1..v2
  * actually implement workaround for E74 in dl_write as spooted
    by James Cameron
  * added comment about E19 in commit message
---
 drivers/tty/serial/8250/8250_pxa.c | 177 +++++++++++++++++++++++++++++++++++++
 drivers/tty/serial/8250/Kconfig    |   8 ++
 drivers/tty/serial/8250/Makefile   |   1 +
 drivers/tty/serial/Kconfig         |  17 +++-
 drivers/tty/serial/Makefile        |   2 +-
 drivers/tty/serial/pxa.c           |   4 +-
 6 files changed, 205 insertions(+), 4 deletions(-)
 create mode 100644 drivers/tty/serial/8250/8250_pxa.c

diff --git a/drivers/tty/serial/8250/8250_pxa.c b/drivers/tty/serial/8250/8250_pxa.c
new file mode 100644
index 0000000..6a14df0
--- /dev/null
+++ b/drivers/tty/serial/8250/8250_pxa.c
@@ -0,0 +1,177 @@
+/*
+ *  drivers/tty/serial/8250/8250_pxa.c -- driver for PXA on-board UARTS
+ *  Copyright:	(C) 2013 Sergei Ianovich <ynvich@gmail.com>
+ *
+ *  replaces drivers/serial/pxa.c by Nicolas Pitre
+ *  Created:	Feb 20, 2003
+ *  Copyright:	(C) 2003 Monta Vista Software, Inc.
+ *
+ *  Based on drivers/serial/8250.c by Russell King.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/serial_8250.h>
+#include <linux/serial_core.h>
+#include <linux/serial_reg.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
+#include <linux/pm_runtime.h>
+
+#include "8250.h"
+
+struct pxa8250_data {
+	int			line;
+	struct clk		*clk;
+};
+
+#ifdef CONFIG_PM
+static int serial_pxa_suspend(struct device *dev)
+{
+	struct pxa8250_data *data = dev_get_drvdata(dev);
+
+	serial8250_suspend_port(data->line);
+
+	return 0;
+}
+
+static int serial_pxa_resume(struct device *dev)
+{
+	struct pxa8250_data *data = dev_get_drvdata(dev);
+
+	serial8250_resume_port(data->line);
+
+	return 0;
+}
+#endif
+
+static const struct dev_pm_ops serial_pxa_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(serial_pxa_suspend, serial_pxa_resume)
+};
+
+static const struct of_device_id serial_pxa_dt_ids[] = {
+	{ .compatible = "mrvl,pxa-uart", },
+	{ .compatible = "mrvl,mmp-uart", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, serial_pxa_dt_ids);
+
+/* Uart divisor latch write */
+static void serial_pxa_dl_write(struct uart_8250_port *up, int value)
+{
+	unsigned int dll;
+
+	serial_out(up, UART_DLL, value & 0xff);
+	/*
+	 * work around Erratum #74 according to Marvel(R) PXA270M Processor
+	 * Specification Update (April 19, 2010)
+	 */
+	dll = serial_in(up, UART_DLL);
+	WARN_ON(dll != (value & 0xff));
+
+	serial_out(up, UART_DLM, value >> 8 & 0xff);
+}
+
+
+static void serial_pxa_pm(struct uart_port *port, unsigned int state,
+	      unsigned int oldstate)
+{
+	struct pxa8250_data *data = port->private_data;
+
+	if (!state)
+		clk_prepare_enable(data->clk);
+	else
+		clk_disable_unprepare(data->clk);
+}
+
+static int serial_pxa_probe(struct platform_device *pdev)
+{
+	struct uart_8250_port uart = {};
+	struct pxa8250_data *data;
+	struct resource *mmres, *irqres;
+	int ret;
+
+	mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	irqres = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!mmres || !irqres)
+		return -ENODEV;
+
+	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(data->clk))
+		return PTR_ERR(data->clk);
+
+	ret = clk_prepare(data->clk);
+	if (ret)
+		return ret;
+
+	uart.port.type = PORT_XSCALE;
+	uart.port.iotype = UPIO_MEM32;
+	uart.port.mapbase = mmres->start;
+	uart.port.regshift = 2;
+	uart.port.irq = irqres->start;
+	uart.port.fifosize = 64;
+	uart.port.flags = UPF_IOREMAP | UPF_SKIP_TEST;
+	uart.port.dev = &pdev->dev;
+	uart.port.uartclk = clk_get_rate(data->clk);
+	uart.port.pm = serial_pxa_pm;
+	uart.port.private_data = data;
+	uart.dl_write = serial_pxa_dl_write;
+
+	ret = serial8250_register_8250_port(&uart);
+	if (ret < 0)
+		goto err_clk;
+
+	data->line = ret;
+
+	platform_set_drvdata(pdev, data);
+
+	return 0;
+
+ err_clk:
+	clk_unprepare(data->clk);
+	return ret;
+}
+
+static int serial_pxa_remove(struct platform_device *pdev)
+{
+	struct pxa8250_data *data = platform_get_drvdata(pdev);
+
+	serial8250_unregister_port(data->line);
+
+	clk_unprepare(data->clk);
+
+	return 0;
+}
+
+static struct platform_driver serial_pxa_driver = {
+	.probe          = serial_pxa_probe,
+	.remove         = serial_pxa_remove,
+
+	.driver		= {
+		.name	= "pxa2xx-uart",
+		.pm	= &serial_pxa_pm_ops,
+		.of_match_table = serial_pxa_dt_ids,
+	},
+};
+
+module_platform_driver(serial_pxa_driver);
+
+MODULE_AUTHOR("Sergei Ianovich");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:pxa2xx-uart");
diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
index 6412f14..4dc45ff 100644
--- a/drivers/tty/serial/8250/Kconfig
+++ b/drivers/tty/serial/8250/Kconfig
@@ -378,3 +378,11 @@ config SERIAL_8250_MID
 	  Selecting this option will enable handling of the extra features
 	  present on the UART found on Intel Medfield SOC and various other
 	  Intel platforms.
+
+config SERIAL_8250_PXA
+	tristate "PXA serial port support"
+	depends on SERIAL_8250
+	depends on ARCH_PXA || ARCH_MMP
+	help
+	  If you have a machine based on an Intel XScale PXA2xx CPU you
+	  can enable its onboard serial ports by enabling this option.
diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile
index e177f86..7e54413 100644
--- a/drivers/tty/serial/8250/Makefile
+++ b/drivers/tty/serial/8250/Makefile
@@ -28,5 +28,6 @@ obj-$(CONFIG_SERIAL_8250_MT6577)	+= 8250_mtk.o
 obj-$(CONFIG_SERIAL_8250_UNIPHIER)	+= 8250_uniphier.o
 obj-$(CONFIG_SERIAL_8250_INGENIC)	+= 8250_ingenic.o
 obj-$(CONFIG_SERIAL_8250_MID)		+= 8250_mid.o
+obj-$(CONFIG_SERIAL_8250_PXA)		+= 8250_pxa.o
 
 CFLAGS_8250_ingenic.o += -I$(srctree)/scripts/dtc/libfdt
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index f38beb2..e477ff5 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -436,17 +436,27 @@ config SERIAL_MPSC_CONSOLE
 	  Say Y here if you want to support a serial console on a Marvell MPSC.
 
 config SERIAL_PXA
-	bool "PXA serial port support"
+	bool "PXA serial port support (DEPRECATED)"
 	depends on ARCH_PXA || ARCH_MMP
 	select SERIAL_CORE
+	select SERIAL_8250_PXA if SERIAL_8250
+	select SERIAL_PXA_NON8250 if !SERIAL_8250
 	help
 	  If you have a machine based on an Intel XScale PXA2xx CPU you
 	  can enable its onboard serial ports by enabling this option.
 
+	  Unless you have a specific need, you should use SERIAL_8250_PXA
+	  instead of this.
+
+config SERIAL_PXA_NON8250
+	bool
+	depends on !SERIAL_8250
+
 config SERIAL_PXA_CONSOLE
-	bool "Console on PXA serial port"
+	bool "Console on PXA serial port (DEPRECATED)"
 	depends on SERIAL_PXA
 	select SERIAL_CORE_CONSOLE
+	select SERIAL_8250_CONSOLE if SERIAL_8250
 	help
 	  If you have enabled the serial port on the Intel XScale PXA
 	  CPU you can make it the console by answering Y to this option.
@@ -458,6 +468,9 @@ config SERIAL_PXA_CONSOLE
 	  your boot loader (lilo or loadlin) about how to pass options to the
 	  kernel at boot time.)
 
+	  Unless you have a specific need, you should use SERIAL_8250_PXA
+	  and SERIAL_8250_CONSOLE instead of this.
+
 config SERIAL_SA1100
 	bool "SA1100 serial port support"
 	depends on ARCH_SA1100
diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile
index 5ab4111..96741d5 100644
--- a/drivers/tty/serial/Makefile
+++ b/drivers/tty/serial/Makefile
@@ -23,7 +23,7 @@ obj-$(CONFIG_SERIAL_8250) += 8250/
 obj-$(CONFIG_SERIAL_AMBA_PL010) += amba-pl010.o
 obj-$(CONFIG_SERIAL_AMBA_PL011) += amba-pl011.o
 obj-$(CONFIG_SERIAL_CLPS711X) += clps711x.o
-obj-$(CONFIG_SERIAL_PXA) += pxa.o
+obj-$(CONFIG_SERIAL_PXA_NON8250) += pxa.o
 obj-$(CONFIG_SERIAL_PNX8XXX) += pnx8xxx_uart.o
 obj-$(CONFIG_SERIAL_SA1100) += sa1100.o
 obj-$(CONFIG_SERIAL_BCM63XX) += bcm63xx_uart.o
diff --git a/drivers/tty/serial/pxa.c b/drivers/tty/serial/pxa.c
index 9becba6..74aac45 100644
--- a/drivers/tty/serial/pxa.c
+++ b/drivers/tty/serial/pxa.c
@@ -940,7 +940,9 @@ static struct platform_driver serial_pxa_driver = {
 	},
 };
 
-static int __init serial_pxa_init(void)
+
+/* 8250 driver for PXA serial ports should be used */
+static int __deprecated __init serial_pxa_init(void)
 {
 	int ret;
 
-- 
2.6.3

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

* Re: [PATCH v5] serial: rewrite pxa2xx-uart to use 8250_core
  2015-12-23 18:59                 ` Sergei Ianovich
@ 2015-12-23 22:50                   ` kbuild test robot
  -1 siblings, 0 replies; 700+ messages in thread
From: kbuild test robot @ 2015-12-23 22:50 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: kbuild-all, linux-kernel, Sergei Ianovich, Heikki Krogerus,
	James Cameron, Greg Kroah-Hartman, Robert Jarzmik, Russell King,
	Jiri Slaby, Andy Shevchenko, Arnd Bergmann, Joachim Eastwood,
	Paul Burton, Mans Rullgard, Scott Wood,
	Sebastian Andrzej Siewior, Paul Gortmaker, Matthias Brugger,
	Peter Hurley, open list:SERIAL DRIVERS

[-- Attachment #1: Type: text/plain, Size: 5809 bytes --]

Hi Sergei,

[auto build test ERROR on v4.4-rc6]
[cannot apply to tty/tty-testing next-20151223]

url:    https://github.com/0day-ci/linux/commits/Sergei-Ianovich/serial-rewrite-pxa2xx-uart-to-use-8250_core/20151224-030409
config: arm-spitz_defconfig (attached as .config)
reproduce:
        wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=arm 

All error/warnings (new ones prefixed by >>):

warning: (SERIAL_PXA_CONSOLE) selects SERIAL_8250_CONSOLE which has unmet direct dependencies (TTY && HAS_IOMEM && SERIAL_8250=y)
   In file included from drivers/tty/serial//8250/8250_core.c:21:0:
>> include/linux/module.h:128:27: error: redefinition of '__inittest'
     static inline initcall_t __inittest(void)  \
                              ^
>> drivers/tty/serial//8250/8250_core.c:1167:1: note: in expansion of macro 'module_init'
    module_init(serial8250_init);
    ^
   include/linux/module.h:128:27: note: previous definition of '__inittest' was here
     static inline initcall_t __inittest(void)  \
                              ^
>> include/linux/module.h:123:31: note: in expansion of macro 'module_init'
    #define console_initcall(fn)  module_init(fn)
                                  ^
>> drivers/tty/serial//8250/8250_core.c:687:1: note: in expansion of macro 'console_initcall'
    console_initcall(univ8250_console_init);
    ^
>> include/linux/module.h:130:6: error: redefinition of 'init_module'
     int init_module(void) __attribute__((alias(#initfn)));
         ^
>> drivers/tty/serial//8250/8250_core.c:1167:1: note: in expansion of macro 'module_init'
    module_init(serial8250_init);
    ^
   include/linux/module.h:130:6: note: previous definition of 'init_module' was here
     int init_module(void) __attribute__((alias(#initfn)));
         ^
>> include/linux/module.h:123:31: note: in expansion of macro 'module_init'
    #define console_initcall(fn)  module_init(fn)
                                  ^
>> drivers/tty/serial//8250/8250_core.c:687:1: note: in expansion of macro 'console_initcall'
    console_initcall(univ8250_console_init);
    ^
--
>> drivers/tty/serial/pxa.c:966:1: warning: 'serial_pxa_init' is deprecated (declared at drivers/tty/serial/pxa.c:945) [-Wdeprecated-declarations]
    module_init(serial_pxa_init);
    ^
--
   In file included from drivers/tty/serial/8250/8250_core.c:21:0:
>> include/linux/module.h:128:27: error: redefinition of '__inittest'
     static inline initcall_t __inittest(void)  \
                              ^
   drivers/tty/serial/8250/8250_core.c:1167:1: note: in expansion of macro 'module_init'
    module_init(serial8250_init);
    ^
   include/linux/module.h:128:27: note: previous definition of '__inittest' was here
     static inline initcall_t __inittest(void)  \
                              ^
>> include/linux/module.h:123:31: note: in expansion of macro 'module_init'
    #define console_initcall(fn)  module_init(fn)
                                  ^
   drivers/tty/serial/8250/8250_core.c:687:1: note: in expansion of macro 'console_initcall'
    console_initcall(univ8250_console_init);
    ^
>> include/linux/module.h:130:6: error: redefinition of 'init_module'
     int init_module(void) __attribute__((alias(#initfn)));
         ^
   drivers/tty/serial/8250/8250_core.c:1167:1: note: in expansion of macro 'module_init'
    module_init(serial8250_init);
    ^
   include/linux/module.h:130:6: note: previous definition of 'init_module' was here
     int init_module(void) __attribute__((alias(#initfn)));
         ^
>> include/linux/module.h:123:31: note: in expansion of macro 'module_init'
    #define console_initcall(fn)  module_init(fn)
                                  ^
   drivers/tty/serial/8250/8250_core.c:687:1: note: in expansion of macro 'console_initcall'
    console_initcall(univ8250_console_init);
    ^

vim +/__inittest +128 include/linux/module.h

0fd972a7 Paul Gortmaker 2015-05-01  117  #define rootfs_initcall(fn)		module_init(fn)
0fd972a7 Paul Gortmaker 2015-05-01  118  #define device_initcall(fn)		module_init(fn)
0fd972a7 Paul Gortmaker 2015-05-01  119  #define device_initcall_sync(fn)	module_init(fn)
0fd972a7 Paul Gortmaker 2015-05-01  120  #define late_initcall(fn)		module_init(fn)
0fd972a7 Paul Gortmaker 2015-05-01  121  #define late_initcall_sync(fn)		module_init(fn)
0fd972a7 Paul Gortmaker 2015-05-01  122  
0fd972a7 Paul Gortmaker 2015-05-01 @123  #define console_initcall(fn)		module_init(fn)
0fd972a7 Paul Gortmaker 2015-05-01  124  #define security_initcall(fn)		module_init(fn)
0fd972a7 Paul Gortmaker 2015-05-01  125  
0fd972a7 Paul Gortmaker 2015-05-01  126  /* Each module must use one module_init(). */
0fd972a7 Paul Gortmaker 2015-05-01  127  #define module_init(initfn)					\
0fd972a7 Paul Gortmaker 2015-05-01 @128  	static inline initcall_t __inittest(void)		\
0fd972a7 Paul Gortmaker 2015-05-01  129  	{ return initfn; }					\
0fd972a7 Paul Gortmaker 2015-05-01 @130  	int init_module(void) __attribute__((alias(#initfn)));
0fd972a7 Paul Gortmaker 2015-05-01  131  
0fd972a7 Paul Gortmaker 2015-05-01  132  /* This is only required if you want to be unloadable. */
0fd972a7 Paul Gortmaker 2015-05-01  133  #define module_exit(exitfn)					\

:::::: The code at line 128 was first introduced by commit
:::::: 0fd972a7d91d6e15393c449492a04d94c0b89351 module: relocate module_init from init.h to module.h

:::::: TO: Paul Gortmaker <paul.gortmaker@windriver.com>
:::::: CC: Paul Gortmaker <paul.gortmaker@windriver.com>

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/octet-stream, Size: 18440 bytes --]

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

* Re: [PATCH v5] serial: rewrite pxa2xx-uart to use 8250_core
@ 2015-12-23 22:50                   ` kbuild test robot
  0 siblings, 0 replies; 700+ messages in thread
From: kbuild test robot @ 2015-12-23 22:50 UTC (permalink / raw)
  Cc: kbuild-all, linux-kernel, Sergei Ianovich, Heikki Krogerus,
	James Cameron, Greg Kroah-Hartman, Robert Jarzmik, Russell King,
	Jiri Slaby, Andy Shevchenko, Arnd Bergmann, Joachim Eastwood,
	Paul Burton, Mans Rullgard, Scott Wood,
	Sebastian Andrzej Siewior, Paul Gortmaker, Matthias Brugger,
	Peter Hurley, open list:SERIAL DRIVERS

[-- Attachment #1: Type: text/plain, Size: 5809 bytes --]

Hi Sergei,

[auto build test ERROR on v4.4-rc6]
[cannot apply to tty/tty-testing next-20151223]

url:    https://github.com/0day-ci/linux/commits/Sergei-Ianovich/serial-rewrite-pxa2xx-uart-to-use-8250_core/20151224-030409
config: arm-spitz_defconfig (attached as .config)
reproduce:
        wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=arm 

All error/warnings (new ones prefixed by >>):

warning: (SERIAL_PXA_CONSOLE) selects SERIAL_8250_CONSOLE which has unmet direct dependencies (TTY && HAS_IOMEM && SERIAL_8250=y)
   In file included from drivers/tty/serial//8250/8250_core.c:21:0:
>> include/linux/module.h:128:27: error: redefinition of '__inittest'
     static inline initcall_t __inittest(void)  \
                              ^
>> drivers/tty/serial//8250/8250_core.c:1167:1: note: in expansion of macro 'module_init'
    module_init(serial8250_init);
    ^
   include/linux/module.h:128:27: note: previous definition of '__inittest' was here
     static inline initcall_t __inittest(void)  \
                              ^
>> include/linux/module.h:123:31: note: in expansion of macro 'module_init'
    #define console_initcall(fn)  module_init(fn)
                                  ^
>> drivers/tty/serial//8250/8250_core.c:687:1: note: in expansion of macro 'console_initcall'
    console_initcall(univ8250_console_init);
    ^
>> include/linux/module.h:130:6: error: redefinition of 'init_module'
     int init_module(void) __attribute__((alias(#initfn)));
         ^
>> drivers/tty/serial//8250/8250_core.c:1167:1: note: in expansion of macro 'module_init'
    module_init(serial8250_init);
    ^
   include/linux/module.h:130:6: note: previous definition of 'init_module' was here
     int init_module(void) __attribute__((alias(#initfn)));
         ^
>> include/linux/module.h:123:31: note: in expansion of macro 'module_init'
    #define console_initcall(fn)  module_init(fn)
                                  ^
>> drivers/tty/serial//8250/8250_core.c:687:1: note: in expansion of macro 'console_initcall'
    console_initcall(univ8250_console_init);
    ^
--
>> drivers/tty/serial/pxa.c:966:1: warning: 'serial_pxa_init' is deprecated (declared at drivers/tty/serial/pxa.c:945) [-Wdeprecated-declarations]
    module_init(serial_pxa_init);
    ^
--
   In file included from drivers/tty/serial/8250/8250_core.c:21:0:
>> include/linux/module.h:128:27: error: redefinition of '__inittest'
     static inline initcall_t __inittest(void)  \
                              ^
   drivers/tty/serial/8250/8250_core.c:1167:1: note: in expansion of macro 'module_init'
    module_init(serial8250_init);
    ^
   include/linux/module.h:128:27: note: previous definition of '__inittest' was here
     static inline initcall_t __inittest(void)  \
                              ^
>> include/linux/module.h:123:31: note: in expansion of macro 'module_init'
    #define console_initcall(fn)  module_init(fn)
                                  ^
   drivers/tty/serial/8250/8250_core.c:687:1: note: in expansion of macro 'console_initcall'
    console_initcall(univ8250_console_init);
    ^
>> include/linux/module.h:130:6: error: redefinition of 'init_module'
     int init_module(void) __attribute__((alias(#initfn)));
         ^
   drivers/tty/serial/8250/8250_core.c:1167:1: note: in expansion of macro 'module_init'
    module_init(serial8250_init);
    ^
   include/linux/module.h:130:6: note: previous definition of 'init_module' was here
     int init_module(void) __attribute__((alias(#initfn)));
         ^
>> include/linux/module.h:123:31: note: in expansion of macro 'module_init'
    #define console_initcall(fn)  module_init(fn)
                                  ^
   drivers/tty/serial/8250/8250_core.c:687:1: note: in expansion of macro 'console_initcall'
    console_initcall(univ8250_console_init);
    ^

vim +/__inittest +128 include/linux/module.h

0fd972a7 Paul Gortmaker 2015-05-01  117  #define rootfs_initcall(fn)		module_init(fn)
0fd972a7 Paul Gortmaker 2015-05-01  118  #define device_initcall(fn)		module_init(fn)
0fd972a7 Paul Gortmaker 2015-05-01  119  #define device_initcall_sync(fn)	module_init(fn)
0fd972a7 Paul Gortmaker 2015-05-01  120  #define late_initcall(fn)		module_init(fn)
0fd972a7 Paul Gortmaker 2015-05-01  121  #define late_initcall_sync(fn)		module_init(fn)
0fd972a7 Paul Gortmaker 2015-05-01  122  
0fd972a7 Paul Gortmaker 2015-05-01 @123  #define console_initcall(fn)		module_init(fn)
0fd972a7 Paul Gortmaker 2015-05-01  124  #define security_initcall(fn)		module_init(fn)
0fd972a7 Paul Gortmaker 2015-05-01  125  
0fd972a7 Paul Gortmaker 2015-05-01  126  /* Each module must use one module_init(). */
0fd972a7 Paul Gortmaker 2015-05-01  127  #define module_init(initfn)					\
0fd972a7 Paul Gortmaker 2015-05-01 @128  	static inline initcall_t __inittest(void)		\
0fd972a7 Paul Gortmaker 2015-05-01  129  	{ return initfn; }					\
0fd972a7 Paul Gortmaker 2015-05-01 @130  	int init_module(void) __attribute__((alias(#initfn)));
0fd972a7 Paul Gortmaker 2015-05-01  131  
0fd972a7 Paul Gortmaker 2015-05-01  132  /* This is only required if you want to be unloadable. */
0fd972a7 Paul Gortmaker 2015-05-01  133  #define module_exit(exitfn)					\

:::::: The code at line 128 was first introduced by commit
:::::: 0fd972a7d91d6e15393c449492a04d94c0b89351 module: relocate module_init from init.h to module.h

:::::: TO: Paul Gortmaker <paul.gortmaker@windriver.com>
:::::: CC: Paul Gortmaker <paul.gortmaker@windriver.com>

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/octet-stream, Size: 18440 bytes --]

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

* [PATCH v6] serial: rewrite pxa2xx-uart to use 8250_core
  2015-12-23 18:59                 ` Sergei Ianovich
@ 2015-12-24 15:15                   ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2015-12-24 15:15 UTC (permalink / raw)
  To: linux-kernel
  Cc: Sergei Ianovich, Heikki Krogerus, James Cameron,
	Greg Kroah-Hartman, Robert Jarzmik, Russell King, Jiri Slaby,
	Andy Shevchenko, Arnd Bergmann, Joachim Eastwood,
	Sebastian Andrzej Siewior, Scott Wood, Paul Gortmaker,
	Paul Burton, Mans Rullgard, Ralf Baechle, Masahiro Yamada,
	Peter Hurley, open list:SERIAL DRIVERS

pxa2xx-uart was a separate uart platform driver. It was declaring
the same device names and numbers as 8250 driver. As a result,
it was impossible to use 8250 driver on PXA SoCs.

Upon closer examination pxa2xx-uart turned out to be a clone of
8250_core driver.

Workaround for Erratum #19 according to Marvel(R) PXA270M Processor
Specification Update (April 19, 2010) is dropped. 8250_core reads
from FIFO immediately after checking DR bit in LSR.

The patch leaves the original SERIAL_PXA driver around. The original
driver is just marked DEPRECATED in Kconfig and C source. When
the original driver is considered safe to remove, no changes
to SERIAL_8250 will be necessary.

Compiling SERIAL_8250_CONSOLE and SERIAL_PXA_CONSOLE even without
SERIAL_8250_PXA breaks console for SERIAL_PXA. For this reasons, the new
and the original drivers are made mutually exclusive.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Heikki Krogerus <heikki.krogerus@linux.intel.com>
CC: James Cameron <quozl@laptop.org>
CC: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
CC: Robert Jarzmik <robert.jarzmik@free.fr>
CC: Russell King <linux@arm.linux.org.uk>

---
  The patch was reviewed/acked at version 3. Changes in version 4
  are simple unbitrotting. Changes in version 5 require re-review
  according to Robert Jarzmik comment.

  changes v5..v6 suggest by kbuild test robot
  * narrow SERIAL_8250 to SERIAL_8250=y in Kconfig dependencies

  changes v4..v5 as suggested by Robert Jarzmik
  * keep pxa.c until it is considered safe to remove
  * keep SERIAL_PXA and SERIAL_PXA_CONSOLE Kconfig options,
    but deprecate them
  * allow selection of either the new or the original driver
    by Kconfig
  * ensure SERIAL_PXA_CONSOLE is respected with either driver

  changes v3..v4
  * remove owner field from platform_driver structure
  * make of_device_id structure constant
  * use CONFIG_SERIAL_8250_PXA instead of CONFIG_SERIAL_PXA

  changes v2..v3
  * remove devm_free/put as suggested by Heikki Krogerus
  * use SET_SYSTEM_SLEEP_PM_OPS macro to set pm ops as suggested
    by Heikki Krogerus

  changes v1..v2
  * actually implement workaround for E74 in dl_write as spooted
    by James Cameron
  * added comment about E19 in commit message

 drivers/tty/serial/8250/8250_pxa.c | 177 +++++++++++++++++++++++++++++++++++++
 drivers/tty/serial/8250/Kconfig    |   8 ++
 drivers/tty/serial/8250/Makefile   |   1 +
 drivers/tty/serial/Kconfig         |  17 +++-
 drivers/tty/serial/Makefile        |   2 +-
 drivers/tty/serial/pxa.c           |   4 +-
 6 files changed, 205 insertions(+), 4 deletions(-)
 create mode 100644 drivers/tty/serial/8250/8250_pxa.c

diff --git a/drivers/tty/serial/8250/8250_pxa.c b/drivers/tty/serial/8250/8250_pxa.c
new file mode 100644
index 0000000..6a14df0
--- /dev/null
+++ b/drivers/tty/serial/8250/8250_pxa.c
@@ -0,0 +1,177 @@
+/*
+ *  drivers/tty/serial/8250/8250_pxa.c -- driver for PXA on-board UARTS
+ *  Copyright:	(C) 2013 Sergei Ianovich <ynvich@gmail.com>
+ *
+ *  replaces drivers/serial/pxa.c by Nicolas Pitre
+ *  Created:	Feb 20, 2003
+ *  Copyright:	(C) 2003 Monta Vista Software, Inc.
+ *
+ *  Based on drivers/serial/8250.c by Russell King.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/serial_8250.h>
+#include <linux/serial_core.h>
+#include <linux/serial_reg.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
+#include <linux/pm_runtime.h>
+
+#include "8250.h"
+
+struct pxa8250_data {
+	int			line;
+	struct clk		*clk;
+};
+
+#ifdef CONFIG_PM
+static int serial_pxa_suspend(struct device *dev)
+{
+	struct pxa8250_data *data = dev_get_drvdata(dev);
+
+	serial8250_suspend_port(data->line);
+
+	return 0;
+}
+
+static int serial_pxa_resume(struct device *dev)
+{
+	struct pxa8250_data *data = dev_get_drvdata(dev);
+
+	serial8250_resume_port(data->line);
+
+	return 0;
+}
+#endif
+
+static const struct dev_pm_ops serial_pxa_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(serial_pxa_suspend, serial_pxa_resume)
+};
+
+static const struct of_device_id serial_pxa_dt_ids[] = {
+	{ .compatible = "mrvl,pxa-uart", },
+	{ .compatible = "mrvl,mmp-uart", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, serial_pxa_dt_ids);
+
+/* Uart divisor latch write */
+static void serial_pxa_dl_write(struct uart_8250_port *up, int value)
+{
+	unsigned int dll;
+
+	serial_out(up, UART_DLL, value & 0xff);
+	/*
+	 * work around Erratum #74 according to Marvel(R) PXA270M Processor
+	 * Specification Update (April 19, 2010)
+	 */
+	dll = serial_in(up, UART_DLL);
+	WARN_ON(dll != (value & 0xff));
+
+	serial_out(up, UART_DLM, value >> 8 & 0xff);
+}
+
+
+static void serial_pxa_pm(struct uart_port *port, unsigned int state,
+	      unsigned int oldstate)
+{
+	struct pxa8250_data *data = port->private_data;
+
+	if (!state)
+		clk_prepare_enable(data->clk);
+	else
+		clk_disable_unprepare(data->clk);
+}
+
+static int serial_pxa_probe(struct platform_device *pdev)
+{
+	struct uart_8250_port uart = {};
+	struct pxa8250_data *data;
+	struct resource *mmres, *irqres;
+	int ret;
+
+	mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	irqres = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!mmres || !irqres)
+		return -ENODEV;
+
+	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(data->clk))
+		return PTR_ERR(data->clk);
+
+	ret = clk_prepare(data->clk);
+	if (ret)
+		return ret;
+
+	uart.port.type = PORT_XSCALE;
+	uart.port.iotype = UPIO_MEM32;
+	uart.port.mapbase = mmres->start;
+	uart.port.regshift = 2;
+	uart.port.irq = irqres->start;
+	uart.port.fifosize = 64;
+	uart.port.flags = UPF_IOREMAP | UPF_SKIP_TEST;
+	uart.port.dev = &pdev->dev;
+	uart.port.uartclk = clk_get_rate(data->clk);
+	uart.port.pm = serial_pxa_pm;
+	uart.port.private_data = data;
+	uart.dl_write = serial_pxa_dl_write;
+
+	ret = serial8250_register_8250_port(&uart);
+	if (ret < 0)
+		goto err_clk;
+
+	data->line = ret;
+
+	platform_set_drvdata(pdev, data);
+
+	return 0;
+
+ err_clk:
+	clk_unprepare(data->clk);
+	return ret;
+}
+
+static int serial_pxa_remove(struct platform_device *pdev)
+{
+	struct pxa8250_data *data = platform_get_drvdata(pdev);
+
+	serial8250_unregister_port(data->line);
+
+	clk_unprepare(data->clk);
+
+	return 0;
+}
+
+static struct platform_driver serial_pxa_driver = {
+	.probe          = serial_pxa_probe,
+	.remove         = serial_pxa_remove,
+
+	.driver		= {
+		.name	= "pxa2xx-uart",
+		.pm	= &serial_pxa_pm_ops,
+		.of_match_table = serial_pxa_dt_ids,
+	},
+};
+
+module_platform_driver(serial_pxa_driver);
+
+MODULE_AUTHOR("Sergei Ianovich");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:pxa2xx-uart");
diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
index 6412f14..4dc45ff 100644
--- a/drivers/tty/serial/8250/Kconfig
+++ b/drivers/tty/serial/8250/Kconfig
@@ -378,3 +378,11 @@ config SERIAL_8250_MID
 	  Selecting this option will enable handling of the extra features
 	  present on the UART found on Intel Medfield SOC and various other
 	  Intel platforms.
+
+config SERIAL_8250_PXA
+	tristate "PXA serial port support"
+	depends on SERIAL_8250
+	depends on ARCH_PXA || ARCH_MMP
+	help
+	  If you have a machine based on an Intel XScale PXA2xx CPU you
+	  can enable its onboard serial ports by enabling this option.
diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile
index e177f86..7e54413 100644
--- a/drivers/tty/serial/8250/Makefile
+++ b/drivers/tty/serial/8250/Makefile
@@ -28,5 +28,6 @@ obj-$(CONFIG_SERIAL_8250_MT6577)	+= 8250_mtk.o
 obj-$(CONFIG_SERIAL_8250_UNIPHIER)	+= 8250_uniphier.o
 obj-$(CONFIG_SERIAL_8250_INGENIC)	+= 8250_ingenic.o
 obj-$(CONFIG_SERIAL_8250_MID)		+= 8250_mid.o
+obj-$(CONFIG_SERIAL_8250_PXA)		+= 8250_pxa.o
 
 CFLAGS_8250_ingenic.o += -I$(srctree)/scripts/dtc/libfdt
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index f38beb2..161f33f 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -436,17 +436,27 @@ config SERIAL_MPSC_CONSOLE
 	  Say Y here if you want to support a serial console on a Marvell MPSC.
 
 config SERIAL_PXA
-	bool "PXA serial port support"
+	bool "PXA serial port support (DEPRECATED)"
 	depends on ARCH_PXA || ARCH_MMP
 	select SERIAL_CORE
+	select SERIAL_8250_PXA if SERIAL_8250=y
+	select SERIAL_PXA_NON8250 if !SERIAL_8250=y
 	help
 	  If you have a machine based on an Intel XScale PXA2xx CPU you
 	  can enable its onboard serial ports by enabling this option.
 
+	  Unless you have a specific need, you should use SERIAL_8250_PXA
+	  instead of this.
+
+config SERIAL_PXA_NON8250
+	bool
+	depends on !SERIAL_8250
+
 config SERIAL_PXA_CONSOLE
-	bool "Console on PXA serial port"
+	bool "Console on PXA serial port (DEPRECATED)"
 	depends on SERIAL_PXA
 	select SERIAL_CORE_CONSOLE
+	select SERIAL_8250_CONSOLE if SERIAL_8250=y
 	help
 	  If you have enabled the serial port on the Intel XScale PXA
 	  CPU you can make it the console by answering Y to this option.
@@ -458,6 +468,9 @@ config SERIAL_PXA_CONSOLE
 	  your boot loader (lilo or loadlin) about how to pass options to the
 	  kernel at boot time.)
 
+	  Unless you have a specific need, you should use SERIAL_8250_PXA
+	  and SERIAL_8250_CONSOLE instead of this.
+
 config SERIAL_SA1100
 	bool "SA1100 serial port support"
 	depends on ARCH_SA1100
diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile
index 5ab4111..96741d5 100644
--- a/drivers/tty/serial/Makefile
+++ b/drivers/tty/serial/Makefile
@@ -23,7 +23,7 @@ obj-$(CONFIG_SERIAL_8250) += 8250/
 obj-$(CONFIG_SERIAL_AMBA_PL010) += amba-pl010.o
 obj-$(CONFIG_SERIAL_AMBA_PL011) += amba-pl011.o
 obj-$(CONFIG_SERIAL_CLPS711X) += clps711x.o
-obj-$(CONFIG_SERIAL_PXA) += pxa.o
+obj-$(CONFIG_SERIAL_PXA_NON8250) += pxa.o
 obj-$(CONFIG_SERIAL_PNX8XXX) += pnx8xxx_uart.o
 obj-$(CONFIG_SERIAL_SA1100) += sa1100.o
 obj-$(CONFIG_SERIAL_BCM63XX) += bcm63xx_uart.o
diff --git a/drivers/tty/serial/pxa.c b/drivers/tty/serial/pxa.c
index 9becba6..74aac45 100644
--- a/drivers/tty/serial/pxa.c
+++ b/drivers/tty/serial/pxa.c
@@ -940,7 +940,9 @@ static struct platform_driver serial_pxa_driver = {
 	},
 };
 
-static int __init serial_pxa_init(void)
+
+/* 8250 driver for PXA serial ports should be used */
+static int __deprecated __init serial_pxa_init(void)
 {
 	int ret;
 
-- 
2.6.3


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

* [PATCH v6] serial: rewrite pxa2xx-uart to use 8250_core
@ 2015-12-24 15:15                   ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2015-12-24 15:15 UTC (permalink / raw)
  To: linux-kernel
  Cc: Sergei Ianovich, Heikki Krogerus, James Cameron,
	Greg Kroah-Hartman, Robert Jarzmik, Russell King, Jiri Slaby,
	Andy Shevchenko, Arnd Bergmann, Joachim Eastwood,
	Sebastian Andrzej Siewior, Scott Wood, Paul Gortmaker,
	Paul Burton, Mans Rullgard, Ralf Baechle, Masahiro Yamada,
	Peter Hurley, open list:SERIAL DRIVERS

pxa2xx-uart was a separate uart platform driver. It was declaring
the same device names and numbers as 8250 driver. As a result,
it was impossible to use 8250 driver on PXA SoCs.

Upon closer examination pxa2xx-uart turned out to be a clone of
8250_core driver.

Workaround for Erratum #19 according to Marvel(R) PXA270M Processor
Specification Update (April 19, 2010) is dropped. 8250_core reads
from FIFO immediately after checking DR bit in LSR.

The patch leaves the original SERIAL_PXA driver around. The original
driver is just marked DEPRECATED in Kconfig and C source. When
the original driver is considered safe to remove, no changes
to SERIAL_8250 will be necessary.

Compiling SERIAL_8250_CONSOLE and SERIAL_PXA_CONSOLE even without
SERIAL_8250_PXA breaks console for SERIAL_PXA. For this reasons, the new
and the original drivers are made mutually exclusive.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Heikki Krogerus <heikki.krogerus@linux.intel.com>
CC: James Cameron <quozl@laptop.org>
CC: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
CC: Robert Jarzmik <robert.jarzmik@free.fr>
CC: Russell King <linux@arm.linux.org.uk>

---
  The patch was reviewed/acked at version 3. Changes in version 4
  are simple unbitrotting. Changes in version 5 require re-review
  according to Robert Jarzmik comment.

  changes v5..v6 suggest by kbuild test robot
  * narrow SERIAL_8250 to SERIAL_8250=y in Kconfig dependencies

  changes v4..v5 as suggested by Robert Jarzmik
  * keep pxa.c until it is considered safe to remove
  * keep SERIAL_PXA and SERIAL_PXA_CONSOLE Kconfig options,
    but deprecate them
  * allow selection of either the new or the original driver
    by Kconfig
  * ensure SERIAL_PXA_CONSOLE is respected with either driver

  changes v3..v4
  * remove owner field from platform_driver structure
  * make of_device_id structure constant
  * use CONFIG_SERIAL_8250_PXA instead of CONFIG_SERIAL_PXA

  changes v2..v3
  * remove devm_free/put as suggested by Heikki Krogerus
  * use SET_SYSTEM_SLEEP_PM_OPS macro to set pm ops as suggested
    by Heikki Krogerus

  changes v1..v2
  * actually implement workaround for E74 in dl_write as spooted
    by James Cameron
  * added comment about E19 in commit message

 drivers/tty/serial/8250/8250_pxa.c | 177 +++++++++++++++++++++++++++++++++++++
 drivers/tty/serial/8250/Kconfig    |   8 ++
 drivers/tty/serial/8250/Makefile   |   1 +
 drivers/tty/serial/Kconfig         |  17 +++-
 drivers/tty/serial/Makefile        |   2 +-
 drivers/tty/serial/pxa.c           |   4 +-
 6 files changed, 205 insertions(+), 4 deletions(-)
 create mode 100644 drivers/tty/serial/8250/8250_pxa.c

diff --git a/drivers/tty/serial/8250/8250_pxa.c b/drivers/tty/serial/8250/8250_pxa.c
new file mode 100644
index 0000000..6a14df0
--- /dev/null
+++ b/drivers/tty/serial/8250/8250_pxa.c
@@ -0,0 +1,177 @@
+/*
+ *  drivers/tty/serial/8250/8250_pxa.c -- driver for PXA on-board UARTS
+ *  Copyright:	(C) 2013 Sergei Ianovich <ynvich@gmail.com>
+ *
+ *  replaces drivers/serial/pxa.c by Nicolas Pitre
+ *  Created:	Feb 20, 2003
+ *  Copyright:	(C) 2003 Monta Vista Software, Inc.
+ *
+ *  Based on drivers/serial/8250.c by Russell King.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/serial_8250.h>
+#include <linux/serial_core.h>
+#include <linux/serial_reg.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
+#include <linux/pm_runtime.h>
+
+#include "8250.h"
+
+struct pxa8250_data {
+	int			line;
+	struct clk		*clk;
+};
+
+#ifdef CONFIG_PM
+static int serial_pxa_suspend(struct device *dev)
+{
+	struct pxa8250_data *data = dev_get_drvdata(dev);
+
+	serial8250_suspend_port(data->line);
+
+	return 0;
+}
+
+static int serial_pxa_resume(struct device *dev)
+{
+	struct pxa8250_data *data = dev_get_drvdata(dev);
+
+	serial8250_resume_port(data->line);
+
+	return 0;
+}
+#endif
+
+static const struct dev_pm_ops serial_pxa_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(serial_pxa_suspend, serial_pxa_resume)
+};
+
+static const struct of_device_id serial_pxa_dt_ids[] = {
+	{ .compatible = "mrvl,pxa-uart", },
+	{ .compatible = "mrvl,mmp-uart", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, serial_pxa_dt_ids);
+
+/* Uart divisor latch write */
+static void serial_pxa_dl_write(struct uart_8250_port *up, int value)
+{
+	unsigned int dll;
+
+	serial_out(up, UART_DLL, value & 0xff);
+	/*
+	 * work around Erratum #74 according to Marvel(R) PXA270M Processor
+	 * Specification Update (April 19, 2010)
+	 */
+	dll = serial_in(up, UART_DLL);
+	WARN_ON(dll != (value & 0xff));
+
+	serial_out(up, UART_DLM, value >> 8 & 0xff);
+}
+
+
+static void serial_pxa_pm(struct uart_port *port, unsigned int state,
+	      unsigned int oldstate)
+{
+	struct pxa8250_data *data = port->private_data;
+
+	if (!state)
+		clk_prepare_enable(data->clk);
+	else
+		clk_disable_unprepare(data->clk);
+}
+
+static int serial_pxa_probe(struct platform_device *pdev)
+{
+	struct uart_8250_port uart = {};
+	struct pxa8250_data *data;
+	struct resource *mmres, *irqres;
+	int ret;
+
+	mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	irqres = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!mmres || !irqres)
+		return -ENODEV;
+
+	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(data->clk))
+		return PTR_ERR(data->clk);
+
+	ret = clk_prepare(data->clk);
+	if (ret)
+		return ret;
+
+	uart.port.type = PORT_XSCALE;
+	uart.port.iotype = UPIO_MEM32;
+	uart.port.mapbase = mmres->start;
+	uart.port.regshift = 2;
+	uart.port.irq = irqres->start;
+	uart.port.fifosize = 64;
+	uart.port.flags = UPF_IOREMAP | UPF_SKIP_TEST;
+	uart.port.dev = &pdev->dev;
+	uart.port.uartclk = clk_get_rate(data->clk);
+	uart.port.pm = serial_pxa_pm;
+	uart.port.private_data = data;
+	uart.dl_write = serial_pxa_dl_write;
+
+	ret = serial8250_register_8250_port(&uart);
+	if (ret < 0)
+		goto err_clk;
+
+	data->line = ret;
+
+	platform_set_drvdata(pdev, data);
+
+	return 0;
+
+ err_clk:
+	clk_unprepare(data->clk);
+	return ret;
+}
+
+static int serial_pxa_remove(struct platform_device *pdev)
+{
+	struct pxa8250_data *data = platform_get_drvdata(pdev);
+
+	serial8250_unregister_port(data->line);
+
+	clk_unprepare(data->clk);
+
+	return 0;
+}
+
+static struct platform_driver serial_pxa_driver = {
+	.probe          = serial_pxa_probe,
+	.remove         = serial_pxa_remove,
+
+	.driver		= {
+		.name	= "pxa2xx-uart",
+		.pm	= &serial_pxa_pm_ops,
+		.of_match_table = serial_pxa_dt_ids,
+	},
+};
+
+module_platform_driver(serial_pxa_driver);
+
+MODULE_AUTHOR("Sergei Ianovich");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:pxa2xx-uart");
diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
index 6412f14..4dc45ff 100644
--- a/drivers/tty/serial/8250/Kconfig
+++ b/drivers/tty/serial/8250/Kconfig
@@ -378,3 +378,11 @@ config SERIAL_8250_MID
 	  Selecting this option will enable handling of the extra features
 	  present on the UART found on Intel Medfield SOC and various other
 	  Intel platforms.
+
+config SERIAL_8250_PXA
+	tristate "PXA serial port support"
+	depends on SERIAL_8250
+	depends on ARCH_PXA || ARCH_MMP
+	help
+	  If you have a machine based on an Intel XScale PXA2xx CPU you
+	  can enable its onboard serial ports by enabling this option.
diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile
index e177f86..7e54413 100644
--- a/drivers/tty/serial/8250/Makefile
+++ b/drivers/tty/serial/8250/Makefile
@@ -28,5 +28,6 @@ obj-$(CONFIG_SERIAL_8250_MT6577)	+= 8250_mtk.o
 obj-$(CONFIG_SERIAL_8250_UNIPHIER)	+= 8250_uniphier.o
 obj-$(CONFIG_SERIAL_8250_INGENIC)	+= 8250_ingenic.o
 obj-$(CONFIG_SERIAL_8250_MID)		+= 8250_mid.o
+obj-$(CONFIG_SERIAL_8250_PXA)		+= 8250_pxa.o
 
 CFLAGS_8250_ingenic.o += -I$(srctree)/scripts/dtc/libfdt
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index f38beb2..161f33f 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -436,17 +436,27 @@ config SERIAL_MPSC_CONSOLE
 	  Say Y here if you want to support a serial console on a Marvell MPSC.
 
 config SERIAL_PXA
-	bool "PXA serial port support"
+	bool "PXA serial port support (DEPRECATED)"
 	depends on ARCH_PXA || ARCH_MMP
 	select SERIAL_CORE
+	select SERIAL_8250_PXA if SERIAL_8250=y
+	select SERIAL_PXA_NON8250 if !SERIAL_8250=y
 	help
 	  If you have a machine based on an Intel XScale PXA2xx CPU you
 	  can enable its onboard serial ports by enabling this option.
 
+	  Unless you have a specific need, you should use SERIAL_8250_PXA
+	  instead of this.
+
+config SERIAL_PXA_NON8250
+	bool
+	depends on !SERIAL_8250
+
 config SERIAL_PXA_CONSOLE
-	bool "Console on PXA serial port"
+	bool "Console on PXA serial port (DEPRECATED)"
 	depends on SERIAL_PXA
 	select SERIAL_CORE_CONSOLE
+	select SERIAL_8250_CONSOLE if SERIAL_8250=y
 	help
 	  If you have enabled the serial port on the Intel XScale PXA
 	  CPU you can make it the console by answering Y to this option.
@@ -458,6 +468,9 @@ config SERIAL_PXA_CONSOLE
 	  your boot loader (lilo or loadlin) about how to pass options to the
 	  kernel at boot time.)
 
+	  Unless you have a specific need, you should use SERIAL_8250_PXA
+	  and SERIAL_8250_CONSOLE instead of this.
+
 config SERIAL_SA1100
 	bool "SA1100 serial port support"
 	depends on ARCH_SA1100
diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile
index 5ab4111..96741d5 100644
--- a/drivers/tty/serial/Makefile
+++ b/drivers/tty/serial/Makefile
@@ -23,7 +23,7 @@ obj-$(CONFIG_SERIAL_8250) += 8250/
 obj-$(CONFIG_SERIAL_AMBA_PL010) += amba-pl010.o
 obj-$(CONFIG_SERIAL_AMBA_PL011) += amba-pl011.o
 obj-$(CONFIG_SERIAL_CLPS711X) += clps711x.o
-obj-$(CONFIG_SERIAL_PXA) += pxa.o
+obj-$(CONFIG_SERIAL_PXA_NON8250) += pxa.o
 obj-$(CONFIG_SERIAL_PNX8XXX) += pnx8xxx_uart.o
 obj-$(CONFIG_SERIAL_SA1100) += sa1100.o
 obj-$(CONFIG_SERIAL_BCM63XX) += bcm63xx_uart.o
diff --git a/drivers/tty/serial/pxa.c b/drivers/tty/serial/pxa.c
index 9becba6..74aac45 100644
--- a/drivers/tty/serial/pxa.c
+++ b/drivers/tty/serial/pxa.c
@@ -940,7 +940,9 @@ static struct platform_driver serial_pxa_driver = {
 	},
 };
 
-static int __init serial_pxa_init(void)
+
+/* 8250 driver for PXA serial ports should be used */
+static int __deprecated __init serial_pxa_init(void)
 {
 	int ret;
 
-- 
2.6.3

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

* Re: [PATCH v6] serial: rewrite pxa2xx-uart to use 8250_core
  2015-12-24 15:15                   ` Sergei Ianovich
  (?)
@ 2015-12-29 11:06                   ` Heikki Krogerus
  2015-12-29 16:50                       ` Robert Jarzmik
  -1 siblings, 1 reply; 700+ messages in thread
From: Heikki Krogerus @ 2015-12-29 11:06 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: linux-kernel, James Cameron, Greg Kroah-Hartman, Robert Jarzmik,
	Russell King, Jiri Slaby, Andy Shevchenko, Arnd Bergmann,
	Joachim Eastwood, Sebastian Andrzej Siewior, Scott Wood,
	Paul Gortmaker, Paul Burton, Mans Rullgard, Ralf Baechle,
	Masahiro Yamada, Peter Hurley, open list:SERIAL DRIVERS

On Thu, Dec 24, 2015 at 06:15:14PM +0300, Sergei Ianovich wrote:
> pxa2xx-uart was a separate uart platform driver. It was declaring
> the same device names and numbers as 8250 driver. As a result,
> it was impossible to use 8250 driver on PXA SoCs.
> 
> Upon closer examination pxa2xx-uart turned out to be a clone of
> 8250_core driver.
> 
> Workaround for Erratum #19 according to Marvel(R) PXA270M Processor
> Specification Update (April 19, 2010) is dropped. 8250_core reads
> from FIFO immediately after checking DR bit in LSR.
> 
> The patch leaves the original SERIAL_PXA driver around. The original
> driver is just marked DEPRECATED in Kconfig and C source. When
> the original driver is considered safe to remove, no changes
> to SERIAL_8250 will be necessary.
> 
> Compiling SERIAL_8250_CONSOLE and SERIAL_PXA_CONSOLE even without
> SERIAL_8250_PXA breaks console for SERIAL_PXA. For this reasons, the new
> and the original drivers are made mutually exclusive.
> 
> Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
> CC: Heikki Krogerus <heikki.krogerus@linux.intel.com>

Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>

Thanks,

-- 
heikki

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

* Re: [PATCH v6] serial: rewrite pxa2xx-uart to use 8250_core
  2015-12-29 11:06                   ` Heikki Krogerus
@ 2015-12-29 16:50                       ` Robert Jarzmik
  0 siblings, 0 replies; 700+ messages in thread
From: Robert Jarzmik @ 2015-12-29 16:50 UTC (permalink / raw)
  To: Heikki Krogerus, Sergei Ianovich
  Cc: linux-kernel, James Cameron, Greg Kroah-Hartman, Russell King,
	Jiri Slaby, Andy Shevchenko, Arnd Bergmann, Joachim Eastwood,
	Sebastian Andrzej Siewior, Scott Wood, Paul Gortmaker,
	Paul Burton, Mans Rullgard, Ralf Baechle, Masahiro Yamada,
	Peter Hurley, open list:SERIAL DRIVERS

Heikki Krogerus <heikki.krogerus@linux.intel.com> writes:

> On Thu, Dec 24, 2015 at 06:15:14PM +0300, Sergei Ianovich wrote:
>> pxa2xx-uart was a separate uart platform driver. It was declaring
>> the same device names and numbers as 8250 driver. As a result,
>> it was impossible to use 8250 driver on PXA SoCs.
>> 
>> Upon closer examination pxa2xx-uart turned out to be a clone of
>> 8250_core driver.
>> 
>> Workaround for Erratum #19 according to Marvel(R) PXA270M Processor
>> Specification Update (April 19, 2010) is dropped. 8250_core reads
>> from FIFO immediately after checking DR bit in LSR.
>> 
>> The patch leaves the original SERIAL_PXA driver around. The original
>> driver is just marked DEPRECATED in Kconfig and C source. When
>> the original driver is considered safe to remove, no changes
>> to SERIAL_8250 will be necessary.
>> 
>> Compiling SERIAL_8250_CONSOLE and SERIAL_PXA_CONSOLE even without
>> SERIAL_8250_PXA breaks console for SERIAL_PXA. For this reasons, the new
>> and the original drivers are made mutually exclusive.
>> 
>> Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
>> CC: Heikki Krogerus <heikki.krogerus@linux.intel.com>
>
> Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Tested-by: Robert Jarzmik <robert.jarzmik@free.fr>

The tests were done on lubbock(pxa25x), mainstone(pxa27x) and zylonite(pxa3xx)
boards.

I don't expect any breakage in PXA architecture. There might be issues with :
 - arch/arm/mach-pxa/capc7117.c
 - arch/arm/mach-pxa/viper.c
  -arch/arm/mach-pxa/zeus.c (very small probability for this one)
The mitigation plan if any concern arises is to fallback on the
CONFIG_SERIAL_PXA configuration.

I find a bit misleading this chunk, but I'm not very good at KConfig :
 config SERIAL_PXA
-       bool "PXA serial port support"
+       bool "PXA serial port support (DEPRECATED)"
        depends on ARCH_PXA || ARCH_MMP
        select SERIAL_CORE
+       select SERIAL_8250_PXA if SERIAL_8250=y
+       select SERIAL_PXA_NON8250 if !SERIAL_8250=y

What bothers me a bit is that selecting this option has a different effect
whether SERIAL_8250 is set or not. Somebody selecting the deprecated option
obviously wants the old driver, but will be provided the new one if his config
has SERIAL_8250 set. Maybe someone else can comment on this ...

This apart, from pxa perspective, it's good to go.

Cheers.

-- 
Robert

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

* Re: [PATCH v6] serial: rewrite pxa2xx-uart to use 8250_core
@ 2015-12-29 16:50                       ` Robert Jarzmik
  0 siblings, 0 replies; 700+ messages in thread
From: Robert Jarzmik @ 2015-12-29 16:50 UTC (permalink / raw)
  To: Heikki Krogerus, Sergei Ianovich
  Cc: linux-kernel, James Cameron, Greg Kroah-Hartman, Russell King,
	Jiri Slaby, Andy Shevchenko, Arnd Bergmann, Joachim Eastwood,
	Sebastian Andrzej Siewior, Scott Wood, Paul Gortmaker,
	Paul Burton, Mans Rullgard, Ralf Baechle, Masahiro Yamada,
	Peter Hurley, open list:SERIAL DRIVERS

Heikki Krogerus <heikki.krogerus@linux.intel.com> writes:

> On Thu, Dec 24, 2015 at 06:15:14PM +0300, Sergei Ianovich wrote:
>> pxa2xx-uart was a separate uart platform driver. It was declaring
>> the same device names and numbers as 8250 driver. As a result,
>> it was impossible to use 8250 driver on PXA SoCs.
>> 
>> Upon closer examination pxa2xx-uart turned out to be a clone of
>> 8250_core driver.
>> 
>> Workaround for Erratum #19 according to Marvel(R) PXA270M Processor
>> Specification Update (April 19, 2010) is dropped. 8250_core reads
>> from FIFO immediately after checking DR bit in LSR.
>> 
>> The patch leaves the original SERIAL_PXA driver around. The original
>> driver is just marked DEPRECATED in Kconfig and C source. When
>> the original driver is considered safe to remove, no changes
>> to SERIAL_8250 will be necessary.
>> 
>> Compiling SERIAL_8250_CONSOLE and SERIAL_PXA_CONSOLE even without
>> SERIAL_8250_PXA breaks console for SERIAL_PXA. For this reasons, the new
>> and the original drivers are made mutually exclusive.
>> 
>> Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
>> CC: Heikki Krogerus <heikki.krogerus@linux.intel.com>
>
> Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Tested-by: Robert Jarzmik <robert.jarzmik@free.fr>

The tests were done on lubbock(pxa25x), mainstone(pxa27x) and zylonite(pxa3xx)
boards.

I don't expect any breakage in PXA architecture. There might be issues with :
 - arch/arm/mach-pxa/capc7117.c
 - arch/arm/mach-pxa/viper.c
  -arch/arm/mach-pxa/zeus.c (very small probability for this one)
The mitigation plan if any concern arises is to fallback on the
CONFIG_SERIAL_PXA configuration.

I find a bit misleading this chunk, but I'm not very good at KConfig :
 config SERIAL_PXA
-       bool "PXA serial port support"
+       bool "PXA serial port support (DEPRECATED)"
        depends on ARCH_PXA || ARCH_MMP
        select SERIAL_CORE
+       select SERIAL_8250_PXA if SERIAL_8250=y
+       select SERIAL_PXA_NON8250 if !SERIAL_8250=y

What bothers me a bit is that selecting this option has a different effect
whether SERIAL_8250 is set or not. Somebody selecting the deprecated option
obviously wants the old driver, but will be provided the new one if his config
has SERIAL_8250 set. Maybe someone else can comment on this ...

This apart, from pxa perspective, it's good to go.

Cheers.

-- 
Robert

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

* Re: [PATCH v5] mtd: support BB SRAM on ICP DAS LP-8x4x
@ 2016-01-06 23:25                           ` Brian Norris
  0 siblings, 0 replies; 700+ messages in thread
From: Brian Norris @ 2016-01-06 23:25 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: Rob Herring, linux-kernel, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, David Woodhouse, Jeremy Kerr,
	Cyril Bur, Neelesh Gupta, Michael Ellerman, Joel Stanley,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	open list:MEMORY TECHNOLOGY DEVICES (MTD),
	Arnd Bergmann

On Sun, Dec 20, 2015 at 01:43:58PM +0300, Sergei Ianovich wrote:
> On Sat, 2015-12-19 at 21:38 -0600, Rob Herring wrote:
> > On Tue, Dec 15, 2015 at 09:58:53PM +0300, Sergei Ianovich wrote:
> > > +Required properties:
> > > +- compatible : should be "icpdas,sram-lp8x4x"
> > 
> > No wildcards please. Otherwise looks fine.
> 
> There is a similar review comment from Arnd Bergmann in the discussion
> of `[PATCH v5] serial: support for 16550A serial ports on LP-8x4x`.
> 
> I'll quote my latest clarification:
> > ... This driver will support ports on LP-8081, 

^^ So 8081 doesn't even match the wildcard scheme you give in the
compatible string, proving the point of the Conventional Wisdom
suggestion Rob gave...

> > LP-8141, LP-8441, LP-8841. Last time I checked the vendor was announcing
> > a series with 3 as the last digit. They use lp8x4x name, eg. in
> > documentation like `LP-8x4x_ChangeLog.txt`. They ship their proprietary
> > SDK in `lp8x4x_sdk_for_linux.tar`. All of this implies that it is a
> > single board.
> 
> I think the solution should be the same for all LP-8x4x drivers (IRQ,
> SRAM, SERIAL, IIO).

The rationale is described here:

http://devicetree.org/Device_Tree_Usage#Understanding_the_compatible_Property

Quote:
> Warning: Don't use wildcard compatible values, like "fsl,mpc83xx-uart"
> or similar. Silicon vendors will invariably make a change that breaks
> your wildcard assumptions the moment it is too late to change it.
> Instead, choose a specific silicon implementations and make all
> subsequent silicon compatible with it.

I don't think your circumstance is anything unique.

Regards,
Brian

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

* Re: [PATCH v5] mtd: support BB SRAM on ICP DAS LP-8x4x
@ 2016-01-06 23:25                           ` Brian Norris
  0 siblings, 0 replies; 700+ messages in thread
From: Brian Norris @ 2016-01-06 23:25 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: Rob Herring, linux-kernel-u79uwXL29TY76Z2rM5mHXA, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala, David Woodhouse,
	Jeremy Kerr, Cyril Bur, Neelesh Gupta, Michael Ellerman,
	Joel Stanley,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	open list:MEMORY TECHNOLOGY DEVICES (MTD),
	Arnd Bergmann

On Sun, Dec 20, 2015 at 01:43:58PM +0300, Sergei Ianovich wrote:
> On Sat, 2015-12-19 at 21:38 -0600, Rob Herring wrote:
> > On Tue, Dec 15, 2015 at 09:58:53PM +0300, Sergei Ianovich wrote:
> > > +Required properties:
> > > +- compatible : should be "icpdas,sram-lp8x4x"
> > 
> > No wildcards please. Otherwise looks fine.
> 
> There is a similar review comment from Arnd Bergmann in the discussion
> of `[PATCH v5] serial: support for 16550A serial ports on LP-8x4x`.
> 
> I'll quote my latest clarification:
> > ... This driver will support ports on LP-8081, 

^^ So 8081 doesn't even match the wildcard scheme you give in the
compatible string, proving the point of the Conventional Wisdom
suggestion Rob gave...

> > LP-8141, LP-8441, LP-8841. Last time I checked the vendor was announcing
> > a series with 3 as the last digit. They use lp8x4x name, eg. in
> > documentation like `LP-8x4x_ChangeLog.txt`. They ship their proprietary
> > SDK in `lp8x4x_sdk_for_linux.tar`. All of this implies that it is a
> > single board.
> 
> I think the solution should be the same for all LP-8x4x drivers (IRQ,
> SRAM, SERIAL, IIO).

The rationale is described here:

http://devicetree.org/Device_Tree_Usage#Understanding_the_compatible_Property

Quote:
> Warning: Don't use wildcard compatible values, like "fsl,mpc83xx-uart"
> or similar. Silicon vendors will invariably make a change that breaks
> your wildcard assumptions the moment it is too late to change it.
> Instead, choose a specific silicon implementations and make all
> subsequent silicon compatible with it.

I don't think your circumstance is anything unique.

Regards,
Brian
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH v5] mtd: support BB SRAM on ICP DAS LP-8x4x
@ 2016-01-06 23:25                           ` Brian Norris
  0 siblings, 0 replies; 700+ messages in thread
From: Brian Norris @ 2016-01-06 23:25 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: Rob Herring, linux-kernel, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, David Woodhouse, Jeremy Kerr,
	Cyril Bur, Neelesh Gupta, Michael Ellerman, Joel Stanley,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	open list:MEMORY TECHNOLOGY DEVICES (MTD),
	Arnd Bergmann

On Sun, Dec 20, 2015 at 01:43:58PM +0300, Sergei Ianovich wrote:
> On Sat, 2015-12-19 at 21:38 -0600, Rob Herring wrote:
> > On Tue, Dec 15, 2015 at 09:58:53PM +0300, Sergei Ianovich wrote:
> > > +Required properties:
> > > +- compatible : should be "icpdas,sram-lp8x4x"
> > 
> > No wildcards please. Otherwise looks fine.
> 
> There is a similar review comment from Arnd Bergmann in the discussion
> of `[PATCH v5] serial: support for 16550A serial ports on LP-8x4x`.
> 
> I'll quote my latest clarification:
> > ... This driver will support ports on LP-8081, 

^^ So 8081 doesn't even match the wildcard scheme you give in the
compatible string, proving the point of the Conventional Wisdom
suggestion Rob gave...

> > LP-8141, LP-8441, LP-8841. Last time I checked the vendor was announcing
> > a series with 3 as the last digit. They use lp8x4x name, eg. in
> > documentation like `LP-8x4x_ChangeLog.txt`. They ship their proprietary
> > SDK in `lp8x4x_sdk_for_linux.tar`. All of this implies that it is a
> > single board.
> 
> I think the solution should be the same for all LP-8x4x drivers (IRQ,
> SRAM, SERIAL, IIO).

The rationale is described here:

http://devicetree.org/Device_Tree_Usage#Understanding_the_compatible_Property

Quote:
> Warning: Don't use wildcard compatible values, like "fsl,mpc83xx-uart"
> or similar. Silicon vendors will invariably make a change that breaks
> your wildcard assumptions the moment it is too late to change it.
> Instead, choose a specific silicon implementations and make all
> subsequent silicon compatible with it.

I don't think your circumstance is anything unique.

Regards,
Brian

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

* Re: [PATCH v6] serial: rewrite pxa2xx-uart to use 8250_core
  2015-12-24 15:15                   ` Sergei Ianovich
  (?)
  (?)
@ 2016-02-07  6:22                   ` Greg Kroah-Hartman
  2016-02-22  1:56                     ` Sergei Ianovich
  -1 siblings, 1 reply; 700+ messages in thread
From: Greg Kroah-Hartman @ 2016-02-07  6:22 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: linux-kernel, Heikki Krogerus, James Cameron, Robert Jarzmik,
	Russell King, Jiri Slaby, Andy Shevchenko, Arnd Bergmann,
	Joachim Eastwood, Sebastian Andrzej Siewior, Scott Wood,
	Paul Gortmaker, Paul Burton, Mans Rullgard, Ralf Baechle,
	Masahiro Yamada, Peter Hurley, open list:SERIAL DRIVERS

On Thu, Dec 24, 2015 at 06:15:14PM +0300, Sergei Ianovich wrote:
> pxa2xx-uart was a separate uart platform driver. It was declaring
> the same device names and numbers as 8250 driver. As a result,
> it was impossible to use 8250 driver on PXA SoCs.
> 
> Upon closer examination pxa2xx-uart turned out to be a clone of
> 8250_core driver.
> 
> Workaround for Erratum #19 according to Marvel(R) PXA270M Processor
> Specification Update (April 19, 2010) is dropped. 8250_core reads
> from FIFO immediately after checking DR bit in LSR.
> 
> The patch leaves the original SERIAL_PXA driver around. The original
> driver is just marked DEPRECATED in Kconfig and C source. When
> the original driver is considered safe to remove, no changes
> to SERIAL_8250 will be necessary.

But, you just broke existing configurations, right?  The serial port is
a different name now, are you willing to handle the angry users?

If so, great, get the platform maintainer to sign off on this please and
then resend it.

thanks,

greg k-h

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

* Re: [PATCH v6] serial: rewrite pxa2xx-uart to use 8250_core
  2016-02-07  6:22                   ` Greg Kroah-Hartman
@ 2016-02-22  1:56                     ` Sergei Ianovich
  2016-02-22  7:17                         ` Robert Jarzmik
  0 siblings, 1 reply; 700+ messages in thread
From: Sergei Ianovich @ 2016-02-22  1:56 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: linux-kernel, Heikki Krogerus, James Cameron, Robert Jarzmik,
	Russell King, Jiri Slaby, Andy Shevchenko, Arnd Bergmann,
	Joachim Eastwood, Sebastian Andrzej Siewior, Scott Wood,
	Paul Gortmaker, Paul Burton, Mans Rullgard, Ralf Baechle,
	Masahiro Yamada, Peter Hurley, open list:SERIAL DRIVERS

On Sat, 2016-02-06 at 22:22 -0800, Greg Kroah-Hartman wrote:
> On Thu, Dec 24, 2015 at 06:15:14PM +0300, Sergei Ianovich wrote:
> > pxa2xx-uart was a separate uart platform driver. It was declaring
> > the same device names and numbers as 8250 driver. As a result,
> > it was impossible to use 8250 driver on PXA SoCs.
> > 
> > Upon closer examination pxa2xx-uart turned out to be a clone of
> > 8250_core driver.
> > 
> > Workaround for Erratum #19 according to Marvel(R) PXA270M Processor
> > Specification Update (April 19, 2010) is dropped. 8250_core reads
> > from FIFO immediately after checking DR bit in LSR.
> > 
> > The patch leaves the original SERIAL_PXA driver around. The
> > original
> > driver is just marked DEPRECATED in Kconfig and C source. When
> > the original driver is considered safe to remove, no changes
> > to SERIAL_8250 will be necessary.
> 
> But, you just broke existing configurations, right?  The serial port is
> a different name now, are you willing to handle the angry users?

No, the port name remains /dev/ttyS0. In fact, this conflict (both
drivers use the same name and char major) is the reason for the patch.
Noone should notice the change at runtime. There will be a warning at
compile time which should make the transition to the new driver faster.

> If so, great, get the platform maintainer to sign off on this please and
> then resend it.

The previous version of the patch has been around for 2 years with half
a dozen of Acks and Reviews, but it hasn't landed. Could you suggest a
better approach?

-- 
Sergei Ianovich <ynvich@gmail.com>

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

* Re: [PATCH v6] serial: rewrite pxa2xx-uart to use 8250_core
  2016-02-22  1:56                     ` Sergei Ianovich
@ 2016-02-22  7:17                         ` Robert Jarzmik
  0 siblings, 0 replies; 700+ messages in thread
From: Robert Jarzmik @ 2016-02-22  7:17 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Sergei Ianovich
  Cc: linux-kernel, Heikki Krogerus, James Cameron, Russell King,
	Jiri Slaby, Andy Shevchenko, Arnd Bergmann, Joachim Eastwood,
	Sebastian Andrzej Siewior, Scott Wood, Paul Gortmaker,
	Paul Burton, Mans Rullgard, Ralf Baechle, Masahiro Yamada,
	Peter Hurley, open list:SERIAL DRIVERS

Sergei Ianovich <ynvich@gmail.com> writes:

> On Sat, 2016-02-06 at 22:22 -0800, Greg Kroah-Hartman wrote:
>> On Thu, Dec 24, 2015 at 06:15:14PM +0300, Sergei Ianovich wrote:
>> > pxa2xx-uart was a separate uart platform driver. It was declaring
>> > the same device names and numbers as 8250 driver. As a result,
>> > it was impossible to use 8250 driver on PXA SoCs.
>> > 
>> > Upon closer examination pxa2xx-uart turned out to be a clone of
>> > 8250_core driver.
>> > 
>> > Workaround for Erratum #19 according to Marvel(R) PXA270M Processor
>> > Specification Update (April 19, 2010) is dropped. 8250_core reads
>> > from FIFO immediately after checking DR bit in LSR.
>> > 
>> > The patch leaves the original SERIAL_PXA driver around. The
>> > original
>> > driver is just marked DEPRECATED in Kconfig and C source. When
>> > the original driver is considered safe to remove, no changes
>> > to SERIAL_8250 will be necessary.
>> 
>> But, you just broke existing configurations, right?  The serial port is
>> a different name now, are you willing to handle the angry users?
>
> No, the port name remains /dev/ttyS0. In fact, this conflict (both
> drivers use the same name and char major) is the reason for the patch.
> Noone should notice the change at runtime. There will be a warning at
> compile time which should make the transition to the new driver faster.
>
>> If so, great, get the platform maintainer to sign off on this please and
>> then resend it.

If you're talking about the PXA maintainer, then :
Acked-by: Robert Jarzmik <robert.jarzmik@free.fr>

I'm happy with the patch, all pxa board maintainers have been warned, and there
exists a fallback solution.

So let's go forward, and if people complain, let them complain and forward them
to me.

Cheers.

-- 
Robert

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

* Re: [PATCH v6] serial: rewrite pxa2xx-uart to use 8250_core
@ 2016-02-22  7:17                         ` Robert Jarzmik
  0 siblings, 0 replies; 700+ messages in thread
From: Robert Jarzmik @ 2016-02-22  7:17 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Sergei Ianovich
  Cc: linux-kernel, Heikki Krogerus, James Cameron, Russell King,
	Jiri Slaby, Andy Shevchenko, Arnd Bergmann, Joachim Eastwood,
	Sebastian Andrzej Siewior, Scott Wood, Paul Gortmaker,
	Paul Burton, Mans Rullgard, Ralf Baechle, Masahiro Yamada,
	Peter Hurley, open list:SERIAL DRIVERS

Sergei Ianovich <ynvich@gmail.com> writes:

> On Sat, 2016-02-06 at 22:22 -0800, Greg Kroah-Hartman wrote:
>> On Thu, Dec 24, 2015 at 06:15:14PM +0300, Sergei Ianovich wrote:
>> > pxa2xx-uart was a separate uart platform driver. It was declaring
>> > the same device names and numbers as 8250 driver. As a result,
>> > it was impossible to use 8250 driver on PXA SoCs.
>> > 
>> > Upon closer examination pxa2xx-uart turned out to be a clone of
>> > 8250_core driver.
>> > 
>> > Workaround for Erratum #19 according to Marvel(R) PXA270M Processor
>> > Specification Update (April 19, 2010) is dropped. 8250_core reads
>> > from FIFO immediately after checking DR bit in LSR.
>> > 
>> > The patch leaves the original SERIAL_PXA driver around. The
>> > original
>> > driver is just marked DEPRECATED in Kconfig and C source. When
>> > the original driver is considered safe to remove, no changes
>> > to SERIAL_8250 will be necessary.
>> 
>> But, you just broke existing configurations, right?  The serial port is
>> a different name now, are you willing to handle the angry users?
>
> No, the port name remains /dev/ttyS0. In fact, this conflict (both
> drivers use the same name and char major) is the reason for the patch.
> Noone should notice the change at runtime. There will be a warning at
> compile time which should make the transition to the new driver faster.
>
>> If so, great, get the platform maintainer to sign off on this please and
>> then resend it.

If you're talking about the PXA maintainer, then :
Acked-by: Robert Jarzmik <robert.jarzmik@free.fr>

I'm happy with the patch, all pxa board maintainers have been warned, and there
exists a fallback solution.

So let's go forward, and if people complain, let them complain and forward them
to me.

Cheers.

-- 
Robert

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

* [PATCH v6] mtd: support BB SRAM on ICP DAS LP-8x4x
@ 2016-02-23 18:58                       ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2016-02-23 18:58 UTC (permalink / raw)
  To: linux-kernel
  Cc: Sergei Ianovich, Rob Herring, Rob Herring, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala, David Woodhouse,
	Brian Norris, Jeremy Kerr, Neelesh Gupta, Michael Ellerman,
	Cyril Bur, Joel Stanley,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	open list:MEMORY TECHNOLOGY DEVICES [MTD]

This provides an MTD device driver for 512kB of battery backed up SRAM
on ICPDAS LP-8X4X programmable automation controllers.

SRAM chip is connected via FPGA and is not accessible without a driver,
unlike flash memory which is wired to CPU MMU.

This SRAM becomes an excellent persisent storage of volatile process
data like counter values and sensor statuses. Storing those data in
flash or mmc card is not a viable solution.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
Reviewed-by: Brian Norris <computersforpeace@gmail.com>
CC: Rob Herring <robh@kernel.org>

   v5..v6
   * replace wildcards in compatible and module name
   * drop obsolete mtd_part_parser_data.of_node

   v4..v5
   * remove .owner from struct platform_driver
   * constify struct of_device_id
    for further Brian Norris comments:
   * drop unused property from doc file
   * move defconfig update to a different file
   * drop extra match w/ of_match_device()

   v3..v4 for Brian Norris 'Reviewed-by'
   * add doc file for DT binding
   * move DTS binding to a different patch (8/21)
   * drop unused include directive
   * drop safely unused callback
   * drop non-default partion probe types
   * drop duplicate error checks
   * drop duplicate error reporting
   * fixed error message on MTD registeration
   * fixed module removal routine

   v2..v3
   * no changes (except number 08/16 -> 10/21)

   v0..v2
   * use device tree
   * use devm helpers where possible
---
 .../devicetree/bindings/mtd/icpdas-lp8841-sram.txt |  23 +++
 drivers/mtd/devices/Kconfig                        |  14 ++
 drivers/mtd/devices/Makefile                       |   1 +
 drivers/mtd/devices/sram_lp8841.c                  | 198 +++++++++++++++++++++
 4 files changed, 236 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mtd/icpdas-lp8841-sram.txt
 create mode 100644 drivers/mtd/devices/sram_lp8841.c

diff --git a/Documentation/devicetree/bindings/mtd/icpdas-lp8841-sram.txt b/Documentation/devicetree/bindings/mtd/icpdas-lp8841-sram.txt
new file mode 100644
index 0000000..3c1007a
--- /dev/null
+++ b/Documentation/devicetree/bindings/mtd/icpdas-lp8841-sram.txt
@@ -0,0 +1,23 @@
+512kB battery backed up SRAM on ICP DAS LP-8841 industrial computers
+
+LP-8441, LP-8141, and LP-8041 differ from LP-8841 only in expansion
+slot count.
+
+Required properties:
+- compatible : should be "icpdas,lp8841-sram"
+
+- reg: physical base addresses and region lengths of
+       * IO memory range
+       * SRAM page selector
+
+SRAM chip is connected via FPGA and is not accessible without a driver,
+unlike flash memory which is wired to CPU MMU. Driver is essentially
+an address translation routine.
+
+Example:
+
+	sram@a000 {
+		compatible = "icpdas,lp8841-sram";
+		reg = <0xa000 0x1000
+		       0x901e 0x1>;
+	};
diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig
index f73c416..ecf5733 100644
--- a/drivers/mtd/devices/Kconfig
+++ b/drivers/mtd/devices/Kconfig
@@ -233,4 +233,18 @@ config BCH_CONST_T
 	default 4
 endif
 
+config MTD_SRAM_LP8841
+	tristate "SRAM on ICP DAS LP-8841"
+	depends on OF && ARCH_PXA
+       ---help---
+	 This provides an MTD device driver for 512kiB of battery backed up SRAM
+	 on ICPDAS LP-8X41 programmable automation controllers.
+
+	 SRAM chip is connected via FPGA and is not accessible without a driver,
+	 unlike flash memory which is wired to CPU MMU.
+
+	 Say N, unless you plan to run this kernel on LP-8X41.
+
+	 If you say M, the module will be called sram_lp8841.
+
 endmenu
diff --git a/drivers/mtd/devices/Makefile b/drivers/mtd/devices/Makefile
index 7912d3a..46df5d6 100644
--- a/drivers/mtd/devices/Makefile
+++ b/drivers/mtd/devices/Makefile
@@ -17,6 +17,7 @@ obj-$(CONFIG_MTD_SST25L)	+= sst25l.o
 obj-$(CONFIG_MTD_BCM47XXSFLASH)	+= bcm47xxsflash.o
 obj-$(CONFIG_MTD_ST_SPI_FSM)    += st_spi_fsm.o
 obj-$(CONFIG_MTD_POWERNV_FLASH)	+= powernv_flash.o
+obj-$(CONFIG_MTD_SRAM_LP8841)	+= sram_lp8841.o
 
 
 CFLAGS_docg3.o			+= -I$(src)
diff --git a/drivers/mtd/devices/sram_lp8841.c b/drivers/mtd/devices/sram_lp8841.c
new file mode 100644
index 0000000..5d5d942
--- /dev/null
+++ b/drivers/mtd/devices/sram_lp8841.c
@@ -0,0 +1,198 @@
+/*
+ *  linux/drivers/mtd/devices/sram_lp8841.c
+ *
+ *  MTD Driver for SRAM on ICP DAS LP-8841
+ *  Copyright (C) 2013 Sergei Ianovich <ynvich@gmail.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation or any later version.
+ */
+
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mtd/map.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/platform_device.h>
+#include <linux/of_device.h>
+#include <linux/slab.h>
+#include <linux/string_helpers.h>
+#include <linux/types.h>
+
+struct lp8841_sram_info {
+	void __iomem	*bank;
+	void __iomem	*virt;
+	struct mutex	lock;
+	unsigned	active_bank;
+	struct mtd_info	mtd;
+};
+
+static int
+lp8841_sram_erase(struct mtd_info *mtd, struct erase_info *instr)
+{
+	struct lp8841_sram_info *info = mtd->priv;
+	unsigned bank = instr->addr >> 11;
+	unsigned offset = (instr->addr & 0x7ff) << 1;
+	loff_t i;
+
+	mutex_lock(&info->lock);
+	if (unlikely(bank != info->active_bank)) {
+		info->active_bank = bank;
+		iowrite8(bank, info->bank);
+	}
+	for (i = 0; i < instr->len; i++) {
+		iowrite8(0xff, info->virt + offset);
+		offset += 2;
+		if (unlikely(offset == 0)) {
+			info->active_bank++;
+			iowrite8(info->active_bank, info->bank);
+		}
+	}
+	mutex_unlock(&info->lock);
+	instr->state = MTD_ERASE_DONE;
+	mtd_erase_callback(instr);
+
+	return 0;
+}
+
+static int
+lp8841_sram_write(struct mtd_info *mtd, loff_t to, size_t len,
+		size_t *retlen, const u_char *b)
+{
+	struct lp8841_sram_info *info = mtd->priv;
+	unsigned bank = to >> 11;
+	unsigned offset = (to & 0x7ff) << 1;
+	loff_t i;
+
+	mutex_lock(&info->lock);
+	if (unlikely(bank != info->active_bank)) {
+		info->active_bank = bank;
+		iowrite8(bank, info->bank);
+	}
+	for (i = 0; i < len; i++) {
+		iowrite8(b[i], info->virt + offset);
+		offset += 2;
+		if (unlikely(offset == 0)) {
+			info->active_bank++;
+			iowrite8(info->active_bank, info->bank);
+		}
+	}
+	mutex_unlock(&info->lock);
+	*retlen = len;
+	return 0;
+}
+
+static int
+lp8841_sram_read(struct mtd_info *mtd, loff_t from, size_t len,
+		size_t *retlen, u_char *b)
+{
+	struct lp8841_sram_info *info = mtd->priv;
+	unsigned bank = from >> 11;
+	unsigned offset = (from & 0x7ff) << 1;
+	loff_t i;
+
+	mutex_lock(&info->lock);
+	if (unlikely(bank != info->active_bank)) {
+		info->active_bank = bank;
+		iowrite8(bank, info->bank);
+	}
+	for (i = 0; i < len; i++) {
+		b[i] = ioread8(info->virt + offset);
+		offset += 2;
+		if (unlikely(offset == 0)) {
+			info->active_bank++;
+			iowrite8(info->active_bank, info->bank);
+		}
+	}
+	mutex_unlock(&info->lock);
+	*retlen = len;
+	return 0;
+}
+
+static const struct of_device_id of_flash_match[] = {
+	{
+		.compatible	= "icpdas,lp8841-sram",
+	},
+	{ },
+};
+MODULE_DEVICE_TABLE(of, of_flash_match);
+
+static int
+lp8841_sram_probe(struct platform_device *pdev)
+{
+	struct lp8841_sram_info *info;
+	struct resource *res_virt, *res_bank;
+	char sz_str[16];
+	struct mtd_part_parser_data ppdata;
+	int err = 0;
+
+	info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
+	if (!info)
+		return -ENOMEM;
+
+	res_virt = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	info->virt =  devm_ioremap_resource(&pdev->dev, res_virt);
+	if (IS_ERR(info->virt))
+		return PTR_ERR(info->virt);
+
+	res_bank = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	info->bank = devm_ioremap_resource(&pdev->dev, res_bank);
+	if (IS_ERR(info->bank))
+		return PTR_ERR(info->bank);
+
+	info->mtd.priv = info;
+	info->mtd.name = "SRAM";
+	info->mtd.type = MTD_RAM;
+	info->mtd.flags = MTD_CAP_RAM;
+	info->mtd.size = resource_size(res_virt) << 7;
+	info->mtd.erasesize = 512;
+	info->mtd.writesize = 4;
+	info->mtd._erase = lp8841_sram_erase;
+	info->mtd._write = lp8841_sram_write;
+	info->mtd._read = lp8841_sram_read;
+	info->mtd.owner = THIS_MODULE;
+
+	mutex_init(&info->lock);
+	iowrite8(info->active_bank, info->bank);
+	platform_set_drvdata(pdev, info);
+
+	err = mtd_device_parse_register(&info->mtd, NULL, &ppdata,
+			NULL, 0);
+
+	if (err < 0) {
+		dev_err(&pdev->dev, "failed to register MTD\n");
+		return err;
+	}
+
+	string_get_size(info->mtd.size, 1, STRING_UNITS_2, sz_str,
+			sizeof(sz_str));
+	dev_info(&pdev->dev, "using %s SRAM on LP-8X4X as %s\n", sz_str,
+			dev_name(&info->mtd.dev));
+	return 0;
+}
+
+static int
+lp8841_sram_remove(struct platform_device *dev)
+{
+	struct lp8841_sram_info *info = platform_get_drvdata(dev);
+
+	return mtd_device_unregister(&info->mtd);
+}
+
+static struct platform_driver lp8841_sram_driver = {
+	.driver = {
+		.name		= "sram-lp8841",
+		.of_match_table = of_flash_match,
+	},
+	.probe		= lp8841_sram_probe,
+	.remove		= lp8841_sram_remove,
+};
+
+module_platform_driver(lp8841_sram_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Sergei Ianovich");
+MODULE_DESCRIPTION("MTD driver for SRAM on ICPDAS LP-8841");
-- 
2.7.0

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

* [PATCH v6] mtd: support BB SRAM on ICP DAS LP-8x4x
@ 2016-02-23 18:58                       ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2016-02-23 18:58 UTC (permalink / raw)
  To: linux-kernel-u79uwXL29TY76Z2rM5mHXA
  Cc: Sergei Ianovich, Rob Herring, Rob Herring, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala, David Woodhouse,
	Brian Norris, Jeremy Kerr, Neelesh Gupta, Michael Ellerman,
	Cyril Bur, Joel Stanley,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	open list:MEMORY TECHNOLOGY DEVICES [MTD]

This provides an MTD device driver for 512kB of battery backed up SRAM
on ICPDAS LP-8X4X programmable automation controllers.

SRAM chip is connected via FPGA and is not accessible without a driver,
unlike flash memory which is wired to CPU MMU.

This SRAM becomes an excellent persisent storage of volatile process
data like counter values and sensor statuses. Storing those data in
flash or mmc card is not a viable solution.

Signed-off-by: Sergei Ianovich <ynvich-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Reviewed-by: Brian Norris <computersforpeace-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
CC: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>

   v5..v6
   * replace wildcards in compatible and module name
   * drop obsolete mtd_part_parser_data.of_node

   v4..v5
   * remove .owner from struct platform_driver
   * constify struct of_device_id
    for further Brian Norris comments:
   * drop unused property from doc file
   * move defconfig update to a different file
   * drop extra match w/ of_match_device()

   v3..v4 for Brian Norris 'Reviewed-by'
   * add doc file for DT binding
   * move DTS binding to a different patch (8/21)
   * drop unused include directive
   * drop safely unused callback
   * drop non-default partion probe types
   * drop duplicate error checks
   * drop duplicate error reporting
   * fixed error message on MTD registeration
   * fixed module removal routine

   v2..v3
   * no changes (except number 08/16 -> 10/21)

   v0..v2
   * use device tree
   * use devm helpers where possible
---
 .../devicetree/bindings/mtd/icpdas-lp8841-sram.txt |  23 +++
 drivers/mtd/devices/Kconfig                        |  14 ++
 drivers/mtd/devices/Makefile                       |   1 +
 drivers/mtd/devices/sram_lp8841.c                  | 198 +++++++++++++++++++++
 4 files changed, 236 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mtd/icpdas-lp8841-sram.txt
 create mode 100644 drivers/mtd/devices/sram_lp8841.c

diff --git a/Documentation/devicetree/bindings/mtd/icpdas-lp8841-sram.txt b/Documentation/devicetree/bindings/mtd/icpdas-lp8841-sram.txt
new file mode 100644
index 0000000..3c1007a
--- /dev/null
+++ b/Documentation/devicetree/bindings/mtd/icpdas-lp8841-sram.txt
@@ -0,0 +1,23 @@
+512kB battery backed up SRAM on ICP DAS LP-8841 industrial computers
+
+LP-8441, LP-8141, and LP-8041 differ from LP-8841 only in expansion
+slot count.
+
+Required properties:
+- compatible : should be "icpdas,lp8841-sram"
+
+- reg: physical base addresses and region lengths of
+       * IO memory range
+       * SRAM page selector
+
+SRAM chip is connected via FPGA and is not accessible without a driver,
+unlike flash memory which is wired to CPU MMU. Driver is essentially
+an address translation routine.
+
+Example:
+
+	sram@a000 {
+		compatible = "icpdas,lp8841-sram";
+		reg = <0xa000 0x1000
+		       0x901e 0x1>;
+	};
diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig
index f73c416..ecf5733 100644
--- a/drivers/mtd/devices/Kconfig
+++ b/drivers/mtd/devices/Kconfig
@@ -233,4 +233,18 @@ config BCH_CONST_T
 	default 4
 endif
 
+config MTD_SRAM_LP8841
+	tristate "SRAM on ICP DAS LP-8841"
+	depends on OF && ARCH_PXA
+       ---help---
+	 This provides an MTD device driver for 512kiB of battery backed up SRAM
+	 on ICPDAS LP-8X41 programmable automation controllers.
+
+	 SRAM chip is connected via FPGA and is not accessible without a driver,
+	 unlike flash memory which is wired to CPU MMU.
+
+	 Say N, unless you plan to run this kernel on LP-8X41.
+
+	 If you say M, the module will be called sram_lp8841.
+
 endmenu
diff --git a/drivers/mtd/devices/Makefile b/drivers/mtd/devices/Makefile
index 7912d3a..46df5d6 100644
--- a/drivers/mtd/devices/Makefile
+++ b/drivers/mtd/devices/Makefile
@@ -17,6 +17,7 @@ obj-$(CONFIG_MTD_SST25L)	+= sst25l.o
 obj-$(CONFIG_MTD_BCM47XXSFLASH)	+= bcm47xxsflash.o
 obj-$(CONFIG_MTD_ST_SPI_FSM)    += st_spi_fsm.o
 obj-$(CONFIG_MTD_POWERNV_FLASH)	+= powernv_flash.o
+obj-$(CONFIG_MTD_SRAM_LP8841)	+= sram_lp8841.o
 
 
 CFLAGS_docg3.o			+= -I$(src)
diff --git a/drivers/mtd/devices/sram_lp8841.c b/drivers/mtd/devices/sram_lp8841.c
new file mode 100644
index 0000000..5d5d942
--- /dev/null
+++ b/drivers/mtd/devices/sram_lp8841.c
@@ -0,0 +1,198 @@
+/*
+ *  linux/drivers/mtd/devices/sram_lp8841.c
+ *
+ *  MTD Driver for SRAM on ICP DAS LP-8841
+ *  Copyright (C) 2013 Sergei Ianovich <ynvich-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation or any later version.
+ */
+
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mtd/map.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/platform_device.h>
+#include <linux/of_device.h>
+#include <linux/slab.h>
+#include <linux/string_helpers.h>
+#include <linux/types.h>
+
+struct lp8841_sram_info {
+	void __iomem	*bank;
+	void __iomem	*virt;
+	struct mutex	lock;
+	unsigned	active_bank;
+	struct mtd_info	mtd;
+};
+
+static int
+lp8841_sram_erase(struct mtd_info *mtd, struct erase_info *instr)
+{
+	struct lp8841_sram_info *info = mtd->priv;
+	unsigned bank = instr->addr >> 11;
+	unsigned offset = (instr->addr & 0x7ff) << 1;
+	loff_t i;
+
+	mutex_lock(&info->lock);
+	if (unlikely(bank != info->active_bank)) {
+		info->active_bank = bank;
+		iowrite8(bank, info->bank);
+	}
+	for (i = 0; i < instr->len; i++) {
+		iowrite8(0xff, info->virt + offset);
+		offset += 2;
+		if (unlikely(offset == 0)) {
+			info->active_bank++;
+			iowrite8(info->active_bank, info->bank);
+		}
+	}
+	mutex_unlock(&info->lock);
+	instr->state = MTD_ERASE_DONE;
+	mtd_erase_callback(instr);
+
+	return 0;
+}
+
+static int
+lp8841_sram_write(struct mtd_info *mtd, loff_t to, size_t len,
+		size_t *retlen, const u_char *b)
+{
+	struct lp8841_sram_info *info = mtd->priv;
+	unsigned bank = to >> 11;
+	unsigned offset = (to & 0x7ff) << 1;
+	loff_t i;
+
+	mutex_lock(&info->lock);
+	if (unlikely(bank != info->active_bank)) {
+		info->active_bank = bank;
+		iowrite8(bank, info->bank);
+	}
+	for (i = 0; i < len; i++) {
+		iowrite8(b[i], info->virt + offset);
+		offset += 2;
+		if (unlikely(offset == 0)) {
+			info->active_bank++;
+			iowrite8(info->active_bank, info->bank);
+		}
+	}
+	mutex_unlock(&info->lock);
+	*retlen = len;
+	return 0;
+}
+
+static int
+lp8841_sram_read(struct mtd_info *mtd, loff_t from, size_t len,
+		size_t *retlen, u_char *b)
+{
+	struct lp8841_sram_info *info = mtd->priv;
+	unsigned bank = from >> 11;
+	unsigned offset = (from & 0x7ff) << 1;
+	loff_t i;
+
+	mutex_lock(&info->lock);
+	if (unlikely(bank != info->active_bank)) {
+		info->active_bank = bank;
+		iowrite8(bank, info->bank);
+	}
+	for (i = 0; i < len; i++) {
+		b[i] = ioread8(info->virt + offset);
+		offset += 2;
+		if (unlikely(offset == 0)) {
+			info->active_bank++;
+			iowrite8(info->active_bank, info->bank);
+		}
+	}
+	mutex_unlock(&info->lock);
+	*retlen = len;
+	return 0;
+}
+
+static const struct of_device_id of_flash_match[] = {
+	{
+		.compatible	= "icpdas,lp8841-sram",
+	},
+	{ },
+};
+MODULE_DEVICE_TABLE(of, of_flash_match);
+
+static int
+lp8841_sram_probe(struct platform_device *pdev)
+{
+	struct lp8841_sram_info *info;
+	struct resource *res_virt, *res_bank;
+	char sz_str[16];
+	struct mtd_part_parser_data ppdata;
+	int err = 0;
+
+	info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
+	if (!info)
+		return -ENOMEM;
+
+	res_virt = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	info->virt =  devm_ioremap_resource(&pdev->dev, res_virt);
+	if (IS_ERR(info->virt))
+		return PTR_ERR(info->virt);
+
+	res_bank = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	info->bank = devm_ioremap_resource(&pdev->dev, res_bank);
+	if (IS_ERR(info->bank))
+		return PTR_ERR(info->bank);
+
+	info->mtd.priv = info;
+	info->mtd.name = "SRAM";
+	info->mtd.type = MTD_RAM;
+	info->mtd.flags = MTD_CAP_RAM;
+	info->mtd.size = resource_size(res_virt) << 7;
+	info->mtd.erasesize = 512;
+	info->mtd.writesize = 4;
+	info->mtd._erase = lp8841_sram_erase;
+	info->mtd._write = lp8841_sram_write;
+	info->mtd._read = lp8841_sram_read;
+	info->mtd.owner = THIS_MODULE;
+
+	mutex_init(&info->lock);
+	iowrite8(info->active_bank, info->bank);
+	platform_set_drvdata(pdev, info);
+
+	err = mtd_device_parse_register(&info->mtd, NULL, &ppdata,
+			NULL, 0);
+
+	if (err < 0) {
+		dev_err(&pdev->dev, "failed to register MTD\n");
+		return err;
+	}
+
+	string_get_size(info->mtd.size, 1, STRING_UNITS_2, sz_str,
+			sizeof(sz_str));
+	dev_info(&pdev->dev, "using %s SRAM on LP-8X4X as %s\n", sz_str,
+			dev_name(&info->mtd.dev));
+	return 0;
+}
+
+static int
+lp8841_sram_remove(struct platform_device *dev)
+{
+	struct lp8841_sram_info *info = platform_get_drvdata(dev);
+
+	return mtd_device_unregister(&info->mtd);
+}
+
+static struct platform_driver lp8841_sram_driver = {
+	.driver = {
+		.name		= "sram-lp8841",
+		.of_match_table = of_flash_match,
+	},
+	.probe		= lp8841_sram_probe,
+	.remove		= lp8841_sram_remove,
+};
+
+module_platform_driver(lp8841_sram_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Sergei Ianovich");
+MODULE_DESCRIPTION("MTD driver for SRAM on ICPDAS LP-8841");
-- 
2.7.0

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH v6] mtd: support BB SRAM on ICP DAS LP-8x4x
@ 2016-02-23 19:48                         ` Rob Herring
  0 siblings, 0 replies; 700+ messages in thread
From: Rob Herring @ 2016-02-23 19:48 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: linux-kernel, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	David Woodhouse, Brian Norris, Jeremy Kerr, Neelesh Gupta,
	Michael Ellerman, Cyril Bur, Joel Stanley,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	open list:MEMORY TECHNOLOGY DEVICES [MTD]

On Tue, Feb 23, 2016 at 09:58:01PM +0300, Sergei Ianovich wrote:
> This provides an MTD device driver for 512kB of battery backed up SRAM
> on ICPDAS LP-8X4X programmable automation controllers.
> 
> SRAM chip is connected via FPGA and is not accessible without a driver,
> unlike flash memory which is wired to CPU MMU.
> 
> This SRAM becomes an excellent persisent storage of volatile process
> data like counter values and sensor statuses. Storing those data in
> flash or mmc card is not a viable solution.
> 
> Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
> Reviewed-by: Brian Norris <computersforpeace@gmail.com>
> CC: Rob Herring <robh@kernel.org>
> 
>    v5..v6
>    * replace wildcards in compatible and module name
>    * drop obsolete mtd_part_parser_data.of_node
> 
>    v4..v5
>    * remove .owner from struct platform_driver
>    * constify struct of_device_id
>     for further Brian Norris comments:
>    * drop unused property from doc file
>    * move defconfig update to a different file
>    * drop extra match w/ of_match_device()
> 
>    v3..v4 for Brian Norris 'Reviewed-by'
>    * add doc file for DT binding
>    * move DTS binding to a different patch (8/21)
>    * drop unused include directive
>    * drop safely unused callback
>    * drop non-default partion probe types
>    * drop duplicate error checks
>    * drop duplicate error reporting
>    * fixed error message on MTD registeration
>    * fixed module removal routine
> 
>    v2..v3
>    * no changes (except number 08/16 -> 10/21)
> 
>    v0..v2
>    * use device tree
>    * use devm helpers where possible
> ---
>  .../devicetree/bindings/mtd/icpdas-lp8841-sram.txt |  23 +++

Acked-by: Rob Herring <robh@kernel.org>

>  drivers/mtd/devices/Kconfig                        |  14 ++
>  drivers/mtd/devices/Makefile                       |   1 +
>  drivers/mtd/devices/sram_lp8841.c                  | 198 +++++++++++++++++++++
>  4 files changed, 236 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/mtd/icpdas-lp8841-sram.txt
>  create mode 100644 drivers/mtd/devices/sram_lp8841.c

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

* Re: [PATCH v6] mtd: support BB SRAM on ICP DAS LP-8x4x
@ 2016-02-23 19:48                         ` Rob Herring
  0 siblings, 0 replies; 700+ messages in thread
From: Rob Herring @ 2016-02-23 19:48 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, David Woodhouse, Brian Norris,
	Jeremy Kerr, Neelesh Gupta, Michael Ellerman, Cyril Bur,
	Joel Stanley,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	open list:MEMORY TECHNOLOGY DEVICES [MTD]

On Tue, Feb 23, 2016 at 09:58:01PM +0300, Sergei Ianovich wrote:
> This provides an MTD device driver for 512kB of battery backed up SRAM
> on ICPDAS LP-8X4X programmable automation controllers.
> 
> SRAM chip is connected via FPGA and is not accessible without a driver,
> unlike flash memory which is wired to CPU MMU.
> 
> This SRAM becomes an excellent persisent storage of volatile process
> data like counter values and sensor statuses. Storing those data in
> flash or mmc card is not a viable solution.
> 
> Signed-off-by: Sergei Ianovich <ynvich-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> Reviewed-by: Brian Norris <computersforpeace-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> CC: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
> 
>    v5..v6
>    * replace wildcards in compatible and module name
>    * drop obsolete mtd_part_parser_data.of_node
> 
>    v4..v5
>    * remove .owner from struct platform_driver
>    * constify struct of_device_id
>     for further Brian Norris comments:
>    * drop unused property from doc file
>    * move defconfig update to a different file
>    * drop extra match w/ of_match_device()
> 
>    v3..v4 for Brian Norris 'Reviewed-by'
>    * add doc file for DT binding
>    * move DTS binding to a different patch (8/21)
>    * drop unused include directive
>    * drop safely unused callback
>    * drop non-default partion probe types
>    * drop duplicate error checks
>    * drop duplicate error reporting
>    * fixed error message on MTD registeration
>    * fixed module removal routine
> 
>    v2..v3
>    * no changes (except number 08/16 -> 10/21)
> 
>    v0..v2
>    * use device tree
>    * use devm helpers where possible
> ---
>  .../devicetree/bindings/mtd/icpdas-lp8841-sram.txt |  23 +++

Acked-by: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>

>  drivers/mtd/devices/Kconfig                        |  14 ++
>  drivers/mtd/devices/Makefile                       |   1 +
>  drivers/mtd/devices/sram_lp8841.c                  | 198 +++++++++++++++++++++
>  4 files changed, 236 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/mtd/icpdas-lp8841-sram.txt
>  create mode 100644 drivers/mtd/devices/sram_lp8841.c
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH v6] mtd: support BB SRAM on ICP DAS LP-8x4x
@ 2016-02-23 19:48                         ` Rob Herring
  0 siblings, 0 replies; 700+ messages in thread
From: Rob Herring @ 2016-02-23 19:48 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: linux-kernel, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	David Woodhouse, Brian Norris, Jeremy Kerr, Neelesh Gupta,
	Michael Ellerman, Cyril Bur, Joel Stanley,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	open list:MEMORY TECHNOLOGY DEVICES [MTD]

On Tue, Feb 23, 2016 at 09:58:01PM +0300, Sergei Ianovich wrote:
> This provides an MTD device driver for 512kB of battery backed up SRAM
> on ICPDAS LP-8X4X programmable automation controllers.
> 
> SRAM chip is connected via FPGA and is not accessible without a driver,
> unlike flash memory which is wired to CPU MMU.
> 
> This SRAM becomes an excellent persisent storage of volatile process
> data like counter values and sensor statuses. Storing those data in
> flash or mmc card is not a viable solution.
> 
> Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
> Reviewed-by: Brian Norris <computersforpeace@gmail.com>
> CC: Rob Herring <robh@kernel.org>
> 
>    v5..v6
>    * replace wildcards in compatible and module name
>    * drop obsolete mtd_part_parser_data.of_node
> 
>    v4..v5
>    * remove .owner from struct platform_driver
>    * constify struct of_device_id
>     for further Brian Norris comments:
>    * drop unused property from doc file
>    * move defconfig update to a different file
>    * drop extra match w/ of_match_device()
> 
>    v3..v4 for Brian Norris 'Reviewed-by'
>    * add doc file for DT binding
>    * move DTS binding to a different patch (8/21)
>    * drop unused include directive
>    * drop safely unused callback
>    * drop non-default partion probe types
>    * drop duplicate error checks
>    * drop duplicate error reporting
>    * fixed error message on MTD registeration
>    * fixed module removal routine
> 
>    v2..v3
>    * no changes (except number 08/16 -> 10/21)
> 
>    v0..v2
>    * use device tree
>    * use devm helpers where possible
> ---
>  .../devicetree/bindings/mtd/icpdas-lp8841-sram.txt |  23 +++

Acked-by: Rob Herring <robh@kernel.org>

>  drivers/mtd/devices/Kconfig                        |  14 ++
>  drivers/mtd/devices/Makefile                       |   1 +
>  drivers/mtd/devices/sram_lp8841.c                  | 198 +++++++++++++++++++++
>  4 files changed, 236 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/mtd/icpdas-lp8841-sram.txt
>  create mode 100644 drivers/mtd/devices/sram_lp8841.c

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

* [PATCH v6] arm: pxa: support ICP DAS LP-8x4x FPGA irq
  2015-12-15 19:26                     ` Sergei Ianovich
@ 2016-02-27 15:56                       ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2016-02-27 15:56 UTC (permalink / raw)
  To: linux-kernel
  Cc: Sergei Ianovich, Arnd Bergmann, Rob Herring, Marc Zyngier,
	Thomas Gleixner, Jason Cooper, Rob Herring, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS

ICP DAS LP-8x4x contains FPGA chip. The chip functions as an interrupt
source providing 16 additional interrupts among other things. The
interrupt lines are muxed to a GPIO pin of a 2nd level PXA-GPIO
interrupt controller. GPIO pins of the 2nd level controller are in turn
muxed to a CPU interrupt line.

Until pxa is completely converted to device tree, it is impossible
to use IRQCHIP_DECLARE() and the irqdomain needs to added manually.
Drivers for the on-CPU IRQs and GPIO-IRQs are loaded using
postcore_initcall(). We need to have all irq domain drivers loaded prior
to DT parsing in order to allow normal initialization of IRQ resources
with DT.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
CC: Arnd Bergmann <arnd@arndb.de>
CC: Rob Herring <robh@kernel.org>
CC: Marc Zyngier <marc.zyngier@arm.com>

   v5..v6
   fixes according to Rob Herring review comments:
   * drop wildcards in binding and file names
   * rename alias 'fpga'->'fpga_irq'

   fixes according to Marc Zyngier review comments:
   * use writeb/readb not iowrite8/ioread8
   * redefine 2nd mask using inversion on 1st
   * add comments

   v4..v5
   * constify struct of_device_id
   * drop irq number from handler signature

   v3.2..v4
   * move DTS binding to a different patch (8/21)

   v3.1..v3.2
   fixes to apply Linus Walleij's "Reviewed-by":
   * add kerneldoc comment for state container struct
   * rename irq -> hwirq for clarity
   * drop overzealous error checks from the hotpaths

   v3..v3.1
   fixes according to Linus Walleij review comments:
   * update commit message
   * use state container instead of global variables
   * get hardware irq nums from irq_data, don't calculate them
   * use BIT() macro
   * add defines for system irq register masks
   * replace cycle control variable with break
   * use better names for resource variables
   * add a linear domain instead of a legacy one
   * use irq_create_mapping() instead of irq_alloc_desc()

   v2..v3
   * no changes (except number 09/16 -> 11/21)

   v0..v2
   * extract irqchip and move to drivers/irqchip/
   * use device tree
   * use devm helpers where possible
---
 .../interrupt-controller/icpdas-lp8x4x-irq.txt     |  49 ++++
 drivers/irqchip/Kconfig                            |   5 +
 drivers/irqchip/Makefile                           |   1 +
 drivers/irqchip/irq-lp8841.c                       | 246 +++++++++++++++++++++
 4 files changed, 301 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/interrupt-controller/icpdas-lp8x4x-irq.txt
 create mode 100644 drivers/irqchip/irq-lp8841.c

diff --git a/Documentation/devicetree/bindings/interrupt-controller/icpdas-lp8x4x-irq.txt b/Documentation/devicetree/bindings/interrupt-controller/icpdas-lp8x4x-irq.txt
new file mode 100644
index 0000000..a72109b
--- /dev/null
+++ b/Documentation/devicetree/bindings/interrupt-controller/icpdas-lp8x4x-irq.txt
@@ -0,0 +1,49 @@
+ICP DAS LP-8841 FPGA Interrupt Controller
+
+ICP DAS LP-8841 contains FPGA chip. The chip functions as a interrupt
+source providing 16 additional interrupts among other things.
+
+Required properties:
+- compatible : should be "icpdas,lp8x4x-irq"
+
+- reg: physical base address of the controller and length of memory mapped
+  region.
+
+- interrupt-controller : identifies the node as an interrupt controller
+
+- #interrupt-cells : should be 1
+
+- interrupts : should provide interrupt
+
+Optional properties:
+
+- interrupt-parent : should provide a link to interrupt controller either
+		     explicitly and implicitly from a parent node
+
+Example:
+
+fpgairq: irq@9006 {
+	compatible = "icpdas,lp8841-irq";
+	reg = <0x9006 0x16>;
+	interrupt-parent = <&gpio>;
+	interrupts = <3 IRQ_TYPE_EDGE_FALLING>;
+	#interrupt-cells = <1>;
+	interrupt-controller;
+	status = "okay";
+};
+
+serial@9050 {
+	compatible = "icpdas,lp8841-uart";
+	reg =  <0x9050 0x10
+		0x9030 0x02>;
+	interrupts = <13>;
+	status = "okay";
+};
+
+serial@9060 {
+	compatible = "icpdas,lp8841-uart";
+	reg =  <0x9060 0x10
+		0x9032 0x02>;
+	interrupts = <14>;
+	status = "okay";
+};
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index fb50911..786073b 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -218,3 +218,8 @@ config IRQ_MXS
 	def_bool y if MACH_ASM9260 || ARCH_MXS
 	select IRQ_DOMAIN
 	select STMP_DEVICE
+
+config LP8841_IRQ
+	bool
+	def_bool y if MACH_PXA27X_DT
+	select IRQ_DOMAIN
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index 18caacb..05313d1 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -59,3 +59,4 @@ obj-$(CONFIG_ARCH_SA1100)		+= irq-sa11x0.o
 obj-$(CONFIG_INGENIC_IRQ)		+= irq-ingenic.o
 obj-$(CONFIG_IMX_GPCV2)			+= irq-imx-gpcv2.o
 obj-$(CONFIG_PIC32_EVIC)		+= irq-pic32-evic.o
+obj-$(CONFIG_LP8841_IRQ)		+= irq-lp8841.o
diff --git a/drivers/irqchip/irq-lp8841.c b/drivers/irqchip/irq-lp8841.c
new file mode 100644
index 0000000..6a019f0
--- /dev/null
+++ b/drivers/irqchip/irq-lp8841.c
@@ -0,0 +1,246 @@
+/*
+ *  linux/drivers/irqchip/irq-lp8841.c
+ *
+ *  Support for ICP DAS LP-8841 FPGA irq
+ *  Copyright (C) 2013 Sergei Ianovich <ynvich@gmail.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation or any later version.
+ */
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/irqchip/chained_irq.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+#define MODULE_NAME		"irq-lp8841"
+
+#define EOI			0x00000000
+#define INSINT			0x00000002
+#define ENSYSINT		0x00000004
+#define PRIMINT			0x00000006
+#define PRIMINT_MASK		0xe0
+#define SECOINT			0x00000008
+#define SECOINT_MASK		(~(u8)PRIMINT_MASK)
+#define ENRISEINT		0x0000000A
+#define CLRRISEINT		0x0000000C
+#define ENHILVINT		0x0000000E
+#define CLRHILVINT		0x00000010
+#define ENFALLINT		0x00000012
+#define CLRFALLINT		0x00000014
+#define IRQ_MEM_SIZE		0x00000016
+#define LP8841_NUM_IRQ_DEFAULT	16
+
+/**
+ * struct lp8841_irq_data - LP8841 custom irq controller state container
+ * @base:               base IO memory address
+ * @irq_domain:         Interrupt translation domain; responsible for mapping
+ *                      between hwirq number and linux irq number
+ * @irq_sys_enabled:    mask keeping track of interrupts enabled in the
+ *                      register which vendor calls 'system'
+ * @irq_high_enabled:   mask keeping track of interrupts enabled in the
+ *                      register which vendor calls 'high'
+ *
+ * The structure implements State Container from
+ * Documentation/driver-model/design-patterns.txt
+ */
+
+struct lp8841_irq_data {
+	void			*base;
+	struct irq_domain	*domain;
+	unsigned char		irq_sys_enabled;
+	unsigned char		irq_high_enabled;
+};
+
+static void lp8841_mask_irq(struct irq_data *d)
+{
+	unsigned mask;
+	unsigned long hwirq = d->hwirq;
+	struct lp8841_irq_data *host = irq_data_get_irq_chip_data(d);
+
+	if (hwirq < 8) {
+		host->irq_high_enabled &= ~BIT(hwirq);
+
+		mask = readb(host->base + ENHILVINT);
+		mask &= ~BIT(hwirq);
+		writeb(mask, host->base + ENHILVINT);
+	} else {
+		hwirq -= 8;
+		host->irq_sys_enabled &= ~BIT(hwirq);
+
+		mask = readb(host->base + ENSYSINT);
+		mask &= ~BIT(hwirq);
+		writeb(mask, host->base + ENSYSINT);
+	}
+}
+
+static void lp8841_unmask_irq(struct irq_data *d)
+{
+	unsigned mask;
+	unsigned long hwirq = d->hwirq;
+	struct lp8841_irq_data *host = irq_data_get_irq_chip_data(d);
+
+	if (hwirq < 8) {
+		host->irq_high_enabled |= BIT(hwirq);
+		mask = readb(host->base + CLRHILVINT);
+		mask |= BIT(hwirq);
+		writeb(mask, host->base + CLRHILVINT);
+
+		mask = readb(host->base + ENHILVINT);
+		mask |= BIT(hwirq);
+		writeb(mask, host->base + ENHILVINT);
+	} else {
+		hwirq -= 8;
+		host->irq_sys_enabled |= BIT(hwirq);
+
+		mask = readb(host->base + SECOINT);
+		mask |= BIT(hwirq);
+		writeb(mask, host->base + SECOINT);
+
+		mask = readb(host->base + ENSYSINT);
+		mask |= BIT(hwirq);
+		writeb(mask, host->base + ENSYSINT);
+	}
+}
+
+static struct irq_chip lp8841_irq_chip = {
+	.name			= "FPGA",
+	.irq_ack		= lp8841_mask_irq,
+	.irq_mask		= lp8841_mask_irq,
+	.irq_mask_ack		= lp8841_mask_irq,
+	.irq_unmask		= lp8841_unmask_irq,
+};
+
+static void lp8841_irq_handler(struct irq_desc *desc)
+{
+	int n;
+	unsigned long mask;
+	struct irq_chip *chip = irq_desc_get_chip(desc);
+	struct lp8841_irq_data *host = irq_desc_get_handler_data(desc);
+
+	chained_irq_enter(chip, desc);
+
+	for (;;) {
+		mask = readb(host->base + CLRHILVINT) & 0xff;
+		/* load two registers into a single byte */
+		mask |= (readb(host->base + SECOINT) & SECOINT_MASK) << 8;
+		mask |= (readb(host->base + PRIMINT) & PRIMINT_MASK) << 8;
+		if (mask == 0)
+			break;
+		for_each_set_bit(n, &mask, BITS_PER_LONG)
+			generic_handle_irq(irq_find_mapping(host->domain, n));
+	}
+
+	writeb(0, host->base + EOI);
+	chained_irq_exit(chip, desc);
+}
+
+static int lp8841_irq_domain_map(struct irq_domain *d, unsigned int irq,
+				 irq_hw_number_t hw)
+{
+	struct lp8841_irq_data *host = d->host_data;
+	int err;
+
+	err = irq_set_chip_data(irq, host);
+	if (err < 0)
+		return err;
+
+	irq_set_chip_and_handler(irq, &lp8841_irq_chip, handle_level_irq);
+	irq_set_probe(irq);
+	return 0;
+}
+
+const struct irq_domain_ops lp8841_irq_domain_ops = {
+	.map	= lp8841_irq_domain_map,
+	.xlate	= irq_domain_xlate_onecell,
+};
+
+static const struct of_device_id lp8841_irq_dt_ids[] = {
+	{ .compatible = "icpdas,lp8841-irq", },
+	{}
+};
+
+/*
+ * REVISIT probing will need to rewritten when PXA is converted to DT
+ */
+
+static int lp8841_irq_probe(struct platform_device *pdev)
+{
+	struct resource *res_mem;
+	int irq;
+	struct device_node *np = pdev->dev.of_node;
+	struct lp8841_irq_data *host;
+	int i, err;
+
+	irq = platform_get_irq(pdev, 0);
+	if (IS_ERR_VALUE(irq)) {
+		dev_err(&pdev->dev, "bad irq %i\n", irq);
+		return irq;
+	}
+
+	res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res_mem || resource_size(res_mem) < IRQ_MEM_SIZE) {
+		dev_err(&pdev->dev, "bad IOmem %p\n", res_mem);
+		if (res_mem)
+			dev_err(&pdev->dev, "bad start %p or size %u\n",
+					(void *) res_mem->start,
+					resource_size(res_mem));
+		return -ENODEV;
+	}
+
+	host = devm_kzalloc(&pdev->dev, sizeof(*host), GFP_KERNEL);
+	if (!host)
+		return -ENOMEM;
+
+	host->base = devm_ioremap_resource(&pdev->dev, res_mem);
+	if (!host->base) {
+		dev_err(&pdev->dev, "Failed to ioremap %p\n", host->base);
+		return -EFAULT;
+	}
+
+	host->domain = irq_domain_add_linear(np, LP8841_NUM_IRQ_DEFAULT,
+				       &lp8841_irq_domain_ops, host);
+	if (!host->domain) {
+		dev_err(&pdev->dev, "Failed to add IRQ domain\n");
+		return -ENOMEM;
+	}
+
+	for (i = 0; i < LP8841_NUM_IRQ_DEFAULT; i++) {
+		err = irq_create_mapping(host->domain, i);
+		if (err < 0)
+			dev_err(&pdev->dev, "Failed to map IRQ %i\n", i);
+	}
+
+	/* Initialize chip registers */
+	writeb(0, host->base + CLRRISEINT);
+	writeb(0, host->base + ENRISEINT);
+	writeb(0, host->base + CLRFALLINT);
+	writeb(0, host->base + ENFALLINT);
+	writeb(0, host->base + CLRHILVINT);
+	writeb(0, host->base + ENHILVINT);
+	writeb(0, host->base + ENSYSINT);
+	writeb(0, host->base + SECOINT);
+
+	irq_set_handler_data(irq, host);
+	irq_set_chained_handler(irq, lp8841_irq_handler);
+
+	pr_info(MODULE_NAME ": %i IRQs\n", LP8841_NUM_IRQ_DEFAULT);
+	return 0;
+}
+
+static struct platform_driver lp8841_irq_driver = {
+	.probe		= lp8841_irq_probe,
+	.driver		= {
+		.name	= MODULE_NAME,
+		.of_match_table = lp8841_irq_dt_ids,
+	},
+};
+
+static int __init lp8841_irq_init(void)
+{
+	return platform_driver_register(&lp8841_irq_driver);
+}
+device_initcall(lp8841_irq_init);
-- 
2.7.0

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

* [PATCH v6] arm: pxa: support ICP DAS LP-8x4x FPGA irq
@ 2016-02-27 15:56                       ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2016-02-27 15:56 UTC (permalink / raw)
  To: linux-kernel
  Cc: Sergei Ianovich, Arnd Bergmann, Rob Herring, Marc Zyngier,
	Thomas Gleixner, Jason Cooper, Rob Herring, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS

ICP DAS LP-8x4x contains FPGA chip. The chip functions as an interrupt
source providing 16 additional interrupts among other things. The
interrupt lines are muxed to a GPIO pin of a 2nd level PXA-GPIO
interrupt controller. GPIO pins of the 2nd level controller are in turn
muxed to a CPU interrupt line.

Until pxa is completely converted to device tree, it is impossible
to use IRQCHIP_DECLARE() and the irqdomain needs to added manually.
Drivers for the on-CPU IRQs and GPIO-IRQs are loaded using
postcore_initcall(). We need to have all irq domain drivers loaded prior
to DT parsing in order to allow normal initialization of IRQ resources
with DT.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
CC: Arnd Bergmann <arnd@arndb.de>
CC: Rob Herring <robh@kernel.org>
CC: Marc Zyngier <marc.zyngier@arm.com>

   v5..v6
   fixes according to Rob Herring review comments:
   * drop wildcards in binding and file names
   * rename alias 'fpga'->'fpga_irq'

   fixes according to Marc Zyngier review comments:
   * use writeb/readb not iowrite8/ioread8
   * redefine 2nd mask using inversion on 1st
   * add comments

   v4..v5
   * constify struct of_device_id
   * drop irq number from handler signature

   v3.2..v4
   * move DTS binding to a different patch (8/21)

   v3.1..v3.2
   fixes to apply Linus Walleij's "Reviewed-by":
   * add kerneldoc comment for state container struct
   * rename irq -> hwirq for clarity
   * drop overzealous error checks from the hotpaths

   v3..v3.1
   fixes according to Linus Walleij review comments:
   * update commit message
   * use state container instead of global variables
   * get hardware irq nums from irq_data, don't calculate them
   * use BIT() macro
   * add defines for system irq register masks
   * replace cycle control variable with break
   * use better names for resource variables
   * add a linear domain instead of a legacy one
   * use irq_create_mapping() instead of irq_alloc_desc()

   v2..v3
   * no changes (except number 09/16 -> 11/21)

   v0..v2
   * extract irqchip and move to drivers/irqchip/
   * use device tree
   * use devm helpers where possible
---
 .../interrupt-controller/icpdas-lp8x4x-irq.txt     |  49 ++++
 drivers/irqchip/Kconfig                            |   5 +
 drivers/irqchip/Makefile                           |   1 +
 drivers/irqchip/irq-lp8841.c                       | 246 +++++++++++++++++++++
 4 files changed, 301 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/interrupt-controller/icpdas-lp8x4x-irq.txt
 create mode 100644 drivers/irqchip/irq-lp8841.c

diff --git a/Documentation/devicetree/bindings/interrupt-controller/icpdas-lp8x4x-irq.txt b/Documentation/devicetree/bindings/interrupt-controller/icpdas-lp8x4x-irq.txt
new file mode 100644
index 0000000..a72109b
--- /dev/null
+++ b/Documentation/devicetree/bindings/interrupt-controller/icpdas-lp8x4x-irq.txt
@@ -0,0 +1,49 @@
+ICP DAS LP-8841 FPGA Interrupt Controller
+
+ICP DAS LP-8841 contains FPGA chip. The chip functions as a interrupt
+source providing 16 additional interrupts among other things.
+
+Required properties:
+- compatible : should be "icpdas,lp8x4x-irq"
+
+- reg: physical base address of the controller and length of memory mapped
+  region.
+
+- interrupt-controller : identifies the node as an interrupt controller
+
+- #interrupt-cells : should be 1
+
+- interrupts : should provide interrupt
+
+Optional properties:
+
+- interrupt-parent : should provide a link to interrupt controller either
+		     explicitly and implicitly from a parent node
+
+Example:
+
+fpgairq: irq@9006 {
+	compatible = "icpdas,lp8841-irq";
+	reg = <0x9006 0x16>;
+	interrupt-parent = <&gpio>;
+	interrupts = <3 IRQ_TYPE_EDGE_FALLING>;
+	#interrupt-cells = <1>;
+	interrupt-controller;
+	status = "okay";
+};
+
+serial@9050 {
+	compatible = "icpdas,lp8841-uart";
+	reg =  <0x9050 0x10
+		0x9030 0x02>;
+	interrupts = <13>;
+	status = "okay";
+};
+
+serial@9060 {
+	compatible = "icpdas,lp8841-uart";
+	reg =  <0x9060 0x10
+		0x9032 0x02>;
+	interrupts = <14>;
+	status = "okay";
+};
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index fb50911..786073b 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -218,3 +218,8 @@ config IRQ_MXS
 	def_bool y if MACH_ASM9260 || ARCH_MXS
 	select IRQ_DOMAIN
 	select STMP_DEVICE
+
+config LP8841_IRQ
+	bool
+	def_bool y if MACH_PXA27X_DT
+	select IRQ_DOMAIN
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index 18caacb..05313d1 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -59,3 +59,4 @@ obj-$(CONFIG_ARCH_SA1100)		+= irq-sa11x0.o
 obj-$(CONFIG_INGENIC_IRQ)		+= irq-ingenic.o
 obj-$(CONFIG_IMX_GPCV2)			+= irq-imx-gpcv2.o
 obj-$(CONFIG_PIC32_EVIC)		+= irq-pic32-evic.o
+obj-$(CONFIG_LP8841_IRQ)		+= irq-lp8841.o
diff --git a/drivers/irqchip/irq-lp8841.c b/drivers/irqchip/irq-lp8841.c
new file mode 100644
index 0000000..6a019f0
--- /dev/null
+++ b/drivers/irqchip/irq-lp8841.c
@@ -0,0 +1,246 @@
+/*
+ *  linux/drivers/irqchip/irq-lp8841.c
+ *
+ *  Support for ICP DAS LP-8841 FPGA irq
+ *  Copyright (C) 2013 Sergei Ianovich <ynvich@gmail.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation or any later version.
+ */
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/irqchip/chained_irq.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+#define MODULE_NAME		"irq-lp8841"
+
+#define EOI			0x00000000
+#define INSINT			0x00000002
+#define ENSYSINT		0x00000004
+#define PRIMINT			0x00000006
+#define PRIMINT_MASK		0xe0
+#define SECOINT			0x00000008
+#define SECOINT_MASK		(~(u8)PRIMINT_MASK)
+#define ENRISEINT		0x0000000A
+#define CLRRISEINT		0x0000000C
+#define ENHILVINT		0x0000000E
+#define CLRHILVINT		0x00000010
+#define ENFALLINT		0x00000012
+#define CLRFALLINT		0x00000014
+#define IRQ_MEM_SIZE		0x00000016
+#define LP8841_NUM_IRQ_DEFAULT	16
+
+/**
+ * struct lp8841_irq_data - LP8841 custom irq controller state container
+ * @base:               base IO memory address
+ * @irq_domain:         Interrupt translation domain; responsible for mapping
+ *                      between hwirq number and linux irq number
+ * @irq_sys_enabled:    mask keeping track of interrupts enabled in the
+ *                      register which vendor calls 'system'
+ * @irq_high_enabled:   mask keeping track of interrupts enabled in the
+ *                      register which vendor calls 'high'
+ *
+ * The structure implements State Container from
+ * Documentation/driver-model/design-patterns.txt
+ */
+
+struct lp8841_irq_data {
+	void			*base;
+	struct irq_domain	*domain;
+	unsigned char		irq_sys_enabled;
+	unsigned char		irq_high_enabled;
+};
+
+static void lp8841_mask_irq(struct irq_data *d)
+{
+	unsigned mask;
+	unsigned long hwirq = d->hwirq;
+	struct lp8841_irq_data *host = irq_data_get_irq_chip_data(d);
+
+	if (hwirq < 8) {
+		host->irq_high_enabled &= ~BIT(hwirq);
+
+		mask = readb(host->base + ENHILVINT);
+		mask &= ~BIT(hwirq);
+		writeb(mask, host->base + ENHILVINT);
+	} else {
+		hwirq -= 8;
+		host->irq_sys_enabled &= ~BIT(hwirq);
+
+		mask = readb(host->base + ENSYSINT);
+		mask &= ~BIT(hwirq);
+		writeb(mask, host->base + ENSYSINT);
+	}
+}
+
+static void lp8841_unmask_irq(struct irq_data *d)
+{
+	unsigned mask;
+	unsigned long hwirq = d->hwirq;
+	struct lp8841_irq_data *host = irq_data_get_irq_chip_data(d);
+
+	if (hwirq < 8) {
+		host->irq_high_enabled |= BIT(hwirq);
+		mask = readb(host->base + CLRHILVINT);
+		mask |= BIT(hwirq);
+		writeb(mask, host->base + CLRHILVINT);
+
+		mask = readb(host->base + ENHILVINT);
+		mask |= BIT(hwirq);
+		writeb(mask, host->base + ENHILVINT);
+	} else {
+		hwirq -= 8;
+		host->irq_sys_enabled |= BIT(hwirq);
+
+		mask = readb(host->base + SECOINT);
+		mask |= BIT(hwirq);
+		writeb(mask, host->base + SECOINT);
+
+		mask = readb(host->base + ENSYSINT);
+		mask |= BIT(hwirq);
+		writeb(mask, host->base + ENSYSINT);
+	}
+}
+
+static struct irq_chip lp8841_irq_chip = {
+	.name			= "FPGA",
+	.irq_ack		= lp8841_mask_irq,
+	.irq_mask		= lp8841_mask_irq,
+	.irq_mask_ack		= lp8841_mask_irq,
+	.irq_unmask		= lp8841_unmask_irq,
+};
+
+static void lp8841_irq_handler(struct irq_desc *desc)
+{
+	int n;
+	unsigned long mask;
+	struct irq_chip *chip = irq_desc_get_chip(desc);
+	struct lp8841_irq_data *host = irq_desc_get_handler_data(desc);
+
+	chained_irq_enter(chip, desc);
+
+	for (;;) {
+		mask = readb(host->base + CLRHILVINT) & 0xff;
+		/* load two registers into a single byte */
+		mask |= (readb(host->base + SECOINT) & SECOINT_MASK) << 8;
+		mask |= (readb(host->base + PRIMINT) & PRIMINT_MASK) << 8;
+		if (mask == 0)
+			break;
+		for_each_set_bit(n, &mask, BITS_PER_LONG)
+			generic_handle_irq(irq_find_mapping(host->domain, n));
+	}
+
+	writeb(0, host->base + EOI);
+	chained_irq_exit(chip, desc);
+}
+
+static int lp8841_irq_domain_map(struct irq_domain *d, unsigned int irq,
+				 irq_hw_number_t hw)
+{
+	struct lp8841_irq_data *host = d->host_data;
+	int err;
+
+	err = irq_set_chip_data(irq, host);
+	if (err < 0)
+		return err;
+
+	irq_set_chip_and_handler(irq, &lp8841_irq_chip, handle_level_irq);
+	irq_set_probe(irq);
+	return 0;
+}
+
+const struct irq_domain_ops lp8841_irq_domain_ops = {
+	.map	= lp8841_irq_domain_map,
+	.xlate	= irq_domain_xlate_onecell,
+};
+
+static const struct of_device_id lp8841_irq_dt_ids[] = {
+	{ .compatible = "icpdas,lp8841-irq", },
+	{}
+};
+
+/*
+ * REVISIT probing will need to rewritten when PXA is converted to DT
+ */
+
+static int lp8841_irq_probe(struct platform_device *pdev)
+{
+	struct resource *res_mem;
+	int irq;
+	struct device_node *np = pdev->dev.of_node;
+	struct lp8841_irq_data *host;
+	int i, err;
+
+	irq = platform_get_irq(pdev, 0);
+	if (IS_ERR_VALUE(irq)) {
+		dev_err(&pdev->dev, "bad irq %i\n", irq);
+		return irq;
+	}
+
+	res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res_mem || resource_size(res_mem) < IRQ_MEM_SIZE) {
+		dev_err(&pdev->dev, "bad IOmem %p\n", res_mem);
+		if (res_mem)
+			dev_err(&pdev->dev, "bad start %p or size %u\n",
+					(void *) res_mem->start,
+					resource_size(res_mem));
+		return -ENODEV;
+	}
+
+	host = devm_kzalloc(&pdev->dev, sizeof(*host), GFP_KERNEL);
+	if (!host)
+		return -ENOMEM;
+
+	host->base = devm_ioremap_resource(&pdev->dev, res_mem);
+	if (!host->base) {
+		dev_err(&pdev->dev, "Failed to ioremap %p\n", host->base);
+		return -EFAULT;
+	}
+
+	host->domain = irq_domain_add_linear(np, LP8841_NUM_IRQ_DEFAULT,
+				       &lp8841_irq_domain_ops, host);
+	if (!host->domain) {
+		dev_err(&pdev->dev, "Failed to add IRQ domain\n");
+		return -ENOMEM;
+	}
+
+	for (i = 0; i < LP8841_NUM_IRQ_DEFAULT; i++) {
+		err = irq_create_mapping(host->domain, i);
+		if (err < 0)
+			dev_err(&pdev->dev, "Failed to map IRQ %i\n", i);
+	}
+
+	/* Initialize chip registers */
+	writeb(0, host->base + CLRRISEINT);
+	writeb(0, host->base + ENRISEINT);
+	writeb(0, host->base + CLRFALLINT);
+	writeb(0, host->base + ENFALLINT);
+	writeb(0, host->base + CLRHILVINT);
+	writeb(0, host->base + ENHILVINT);
+	writeb(0, host->base + ENSYSINT);
+	writeb(0, host->base + SECOINT);
+
+	irq_set_handler_data(irq, host);
+	irq_set_chained_handler(irq, lp8841_irq_handler);
+
+	pr_info(MODULE_NAME ": %i IRQs\n", LP8841_NUM_IRQ_DEFAULT);
+	return 0;
+}
+
+static struct platform_driver lp8841_irq_driver = {
+	.probe		= lp8841_irq_probe,
+	.driver		= {
+		.name	= MODULE_NAME,
+		.of_match_table = lp8841_irq_dt_ids,
+	},
+};
+
+static int __init lp8841_irq_init(void)
+{
+	return platform_driver_register(&lp8841_irq_driver);
+}
+device_initcall(lp8841_irq_init);
-- 
2.7.0

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

* [PATCH v6] serial: support for 16550A serial ports on LP-8x4x
@ 2016-02-27 16:14                     ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2016-02-27 16:14 UTC (permalink / raw)
  To: linux-kernel
  Cc: Sergei Ianovich, Alan Cox, Andy Shevchenko, Arnd Bergmann,
	Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	Greg Kroah-Hartman, Jiri Slaby, Heikki Krogerus, Masahiro Yamada,
	Paul Burton, Paul Gortmaker, Mans Rullgard, Scott Wood,
	Joachim Eastwood, Peter Ujfalusi, Peter Hurley,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	open list:SERIAL DRIVERS

The patch adds support for 3 additional LP-8x4x built-in serial
ports.

The device can also host up to 8 extension cards with 4 serial ports
on each card for a total of 35 ports. However, I don't have
the hardware to test extension cards, so they are not supported, yet.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
CC: Alan Cox <gnomes@lxorguk.ukuu.org.uk>
CC: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
CC: Arnd Bergmann <arnd@arndb.de>
---
   v5..v6
   fix review comments by Arnd Bergmann
   * remove wildcards from compatible
   * update doc file
   * drop interrupt parent from doc file
   * replace uart w/ serial in device names in doc file

   fix review comments by Andy Shevchenko
   * exchange labels in switch block
   * replace iowrite8() with writeb()
   * compact comment to one line

   v4..v5
   * constify struct of_device_id
   * drop .owner from struct platform_driver
   * rewrite set_termios() baud rate hadnling as suggested by Alan Cox

   v3..v4
   * move DTS bindings to a different patch (8/21) as suggested by
     Heikki Krogerus

   v2..v3
   * no changes (except number 10/16 -> 12/21)

   v0..v2
   * register platform driver instead of platform device
   * use device tree
   * use devm helpers where possible

 .../bindings/serial/icpdas-lp8841-uart.txt         |  41 +++++
 drivers/tty/serial/8250/8250_lp8841.c              | 166 +++++++++++++++++++++
 drivers/tty/serial/8250/Kconfig                    |  14 ++
 drivers/tty/serial/8250/Makefile                   |   2 +
 4 files changed, 223 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/serial/icpdas-lp8841-uart.txt
 create mode 100644 drivers/tty/serial/8250/8250_lp8841.c

diff --git a/Documentation/devicetree/bindings/serial/icpdas-lp8841-uart.txt b/Documentation/devicetree/bindings/serial/icpdas-lp8841-uart.txt
new file mode 100644
index 0000000..d6acd22
--- /dev/null
+++ b/Documentation/devicetree/bindings/serial/icpdas-lp8841-uart.txt
@@ -0,0 +1,41 @@
+* UART ports on ICP DAS LP-8841
+
+LP-8441, LP-8141 and LP-8041 are fully compatible.
+
+ICP DAS LP-8841 contains three additional serial ports interfaced via
+Analog Devices ADM213EA chips in addition to 3 serial ports on PXA CPU.
+
+The chips themselves are standard, they would work with 8250_core if
+properly connected. However, they are not connected normally. Al least
+some of their config pins are wired to a different address region. So
+the driver is board-specific.
+
+Required properties:
+- compatible : should be "icpdas,uart-lp8841"
+
+- reg : should provide 16 byte man IO memory region and 1 byte region for
+	termios
+
+- interrupts : should provide interrupt
+
+Optional property:
+- interrupt-parent : should provide a link to interrupt controller either
+		     explicitly or implicitly from a parent node
+
+Examples (from pxa27x-lp8x4x.dts):
+
+		serial@9050 {
+			compatible = "icpdas,uart-lp8841";
+			reg = <0x9050 0x10
+			       0x9030 0x02>;
+			interrupts = <13>;
+			status = "okay";
+		};
+
+		serial@9060 {
+			compatible = "icpdas,uart-lp8841";
+			reg = <0x9060 0x10
+			       0x9032 0x02>;
+			interrupts = <14>;
+			status = "okay";
+		};
diff --git a/drivers/tty/serial/8250/8250_lp8841.c b/drivers/tty/serial/8250/8250_lp8841.c
new file mode 100644
index 0000000..6fef37f
--- /dev/null
+++ b/drivers/tty/serial/8250/8250_lp8841.c
@@ -0,0 +1,166 @@
+/*  linux/drivers/tty/serial/8250/8250_lp8841.c
+ *
+ *  Support for 16550A serial ports on ICP DAS LP-8841
+ *
+ *  Copyright (C) 2013 Sergei Ianovich <ynvich@gmail.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/module.h>
+#include <linux/serial_8250.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+struct lp8841_serial_data {
+	int			line;
+	void			*ios_mem;
+};
+
+static void lp8841_serial_set_termios(struct uart_port *port,
+		struct ktermios *termios, struct ktermios *old)
+{
+	unsigned int len;
+	unsigned int baud;
+	struct lp8841_serial_data *data = port->private_data;
+
+	serial8250_do_set_termios(port, termios, old);
+
+	switch (termios->c_cflag & CSIZE) {
+	case CS5:
+		len = 7;
+		break;
+	case CS6:
+		len = 8;
+		break;
+	case CS7:
+		len = 9;
+		break;
+	case CS8:
+	default:
+		len = 10;
+		break;
+	}
+
+	if (termios->c_cflag & CSTOPB)
+		len++;
+	if (termios->c_cflag & PARENB)
+		len++;
+	if (!(termios->c_cflag & PARODD))
+		len++;
+#ifdef CMSPAR
+	if (termios->c_cflag & CMSPAR)
+		len++;
+#endif
+
+	len -= 9;
+	len &= 3;
+	len <<= 3;
+
+	/* Ask the core to calculate the divisor for us. */
+	baud = tty_termios_baud_rate(termios);
+
+	switch (baud) {
+	case 115200:
+		len |= 7;
+		break;
+	case 57600:
+		len |= 6;
+		break;
+	case 38400:
+		len |= 5;
+		break;
+	case 19200:
+		len |= 4;
+		break;
+	case 9600:
+		len |= 3;
+		break;
+	case 4800:
+		len |= 2;
+		break;
+	case 2400:
+	default:
+		len |= 1;
+		break;
+	};
+	writeb(len, data->ios_mem);
+
+}
+
+static const struct of_device_id lp8841_serial_dt_ids[] = {
+	{ .compatible = "icpdas,lp8841-uart", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, lp8841_serial_dt_ids);
+
+static int lp8841_serial_probe(struct platform_device *pdev)
+{
+	struct uart_8250_port uart = {};
+	struct lp8841_serial_data *data;
+	struct resource *mmres, *mires;
+	int ret;
+
+	mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	mires = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	if (!mmres || !mires)
+		return -ENODEV;
+
+	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->ios_mem = devm_ioremap_resource(&pdev->dev, mires);
+	if (!data->ios_mem)
+		return -EFAULT;
+
+	uart.port.iotype = UPIO_MEM;
+	uart.port.mapbase = mmres->start;
+	uart.port.iobase = mmres->start;
+	uart.port.regshift = 1;
+	uart.port.irq = platform_get_irq(pdev, 0);
+	uart.port.flags = UPF_IOREMAP;
+	uart.port.dev = &pdev->dev;
+	uart.port.uartclk = 14745600;
+	uart.port.set_termios = lp8841_serial_set_termios;
+	uart.port.private_data = data;
+
+	ret = serial8250_register_8250_port(&uart);
+	if (ret < 0)
+		return ret;
+
+	data->line = ret;
+
+	platform_set_drvdata(pdev, data);
+
+	return 0;
+}
+
+static int lp8841_serial_remove(struct platform_device *pdev)
+{
+	struct lp8841_serial_data *data = platform_get_drvdata(pdev);
+
+	serial8250_unregister_port(data->line);
+
+	return 0;
+}
+
+static struct platform_driver lp8841_serial_driver = {
+	.probe          = lp8841_serial_probe,
+	.remove         = lp8841_serial_remove,
+
+	.driver		= {
+		.name	= "uart-lp8841",
+		.of_match_table = lp8841_serial_dt_ids,
+	},
+};
+
+module_platform_driver(lp8841_serial_driver);
+
+MODULE_AUTHOR("Sergei Ianovich");
+MODULE_DESCRIPTION("8250 serial port module for LP-8841");
+MODULE_LICENSE("GPL");
diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
index 3b5cf9c..68640c1 100644
--- a/drivers/tty/serial/8250/Kconfig
+++ b/drivers/tty/serial/8250/Kconfig
@@ -394,3 +394,17 @@ config SERIAL_8250_PXA
 	help
 	  If you have a machine based on an Intel XScale PXA2xx CPU you
 	  can enable its onboard serial ports by enabling this option.
+
+	  If you choose M here, the module name will be 8250_pxa.
+
+config SERIAL_8250_LP8841
+	tristate "Support 16550A ports on ICP DAS LP-8841"
+	depends on SERIAL_8250 && MACH_PXA27X_DT
+	select LP8841_IRQ
+	help
+	  In addition to serial ports on PXA270 SoC, LP-8841 has 1 dual
+	  RS232/RS485 port, 1 RS485 port and 1 RS232 port.
+
+	  Say N here, unless you plan to run this kernel on a LP-8841 system.
+
+	  If you choose M here, the module name will be 8250_lp8841.
diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile
index d1e2f2d..10b4bf0 100644
--- a/drivers/tty/serial/8250/Makefile
+++ b/drivers/tty/serial/8250/Makefile
@@ -18,6 +18,7 @@ obj-$(CONFIG_SERIAL_8250_ACCENT)	+= 8250_accent.o
 obj-$(CONFIG_SERIAL_8250_BOCA)		+= 8250_boca.o
 obj-$(CONFIG_SERIAL_8250_EXAR_ST16C554)	+= 8250_exar_st16c554.o
 obj-$(CONFIG_SERIAL_8250_HUB6)		+= 8250_hub6.o
+obj-$(CONFIG_SERIAL_8250_LP8X4X)	+= 8250_lp8x4x.o
 obj-$(CONFIG_SERIAL_8250_FSL)		+= 8250_fsl.o
 obj-$(CONFIG_SERIAL_8250_DW)		+= 8250_dw.o
 obj-$(CONFIG_SERIAL_8250_EM)		+= 8250_em.o
@@ -30,5 +31,6 @@ obj-$(CONFIG_SERIAL_8250_INGENIC)	+= 8250_ingenic.o
 obj-$(CONFIG_SERIAL_8250_MID)		+= 8250_mid.o
 obj-$(CONFIG_SERIAL_OF_PLATFORM)	+= 8250_of.o
 obj-$(CONFIG_SERIAL_8250_PXA)		+= 8250_pxa.o
+obj-$(CONFIG_SERIAL_8250_LP8841)	+= 8250_lp8841.o
 
 CFLAGS_8250_ingenic.o += -I$(srctree)/scripts/dtc/libfdt
-- 
2.7.0

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

* [PATCH v6] serial: support for 16550A serial ports on LP-8x4x
@ 2016-02-27 16:14                     ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2016-02-27 16:14 UTC (permalink / raw)
  To: linux-kernel-u79uwXL29TY76Z2rM5mHXA
  Cc: Sergei Ianovich, Alan Cox, Andy Shevchenko, Arnd Bergmann,
	Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	Greg Kroah-Hartman, Jiri Slaby, Heikki Krogerus, Masahiro Yamada,
	Paul Burton, Paul Gortmaker, Mans Rullgard, Scott Wood,
	Joachim Eastwood, Peter Ujfalusi, Peter Hurley,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE

The patch adds support for 3 additional LP-8x4x built-in serial
ports.

The device can also host up to 8 extension cards with 4 serial ports
on each card for a total of 35 ports. However, I don't have
the hardware to test extension cards, so they are not supported, yet.

Signed-off-by: Sergei Ianovich <ynvich-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Reviewed-by: Heikki Krogerus <heikki.krogerus-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
CC: Alan Cox <gnomes-qBU/x9rampVanCEyBjwyrvXRex20P6io@public.gmane.org>
CC: Andy Shevchenko <andriy.shevchenko-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
CC: Arnd Bergmann <arnd-r2nGTMty4D4@public.gmane.org>
---
   v5..v6
   fix review comments by Arnd Bergmann
   * remove wildcards from compatible
   * update doc file
   * drop interrupt parent from doc file
   * replace uart w/ serial in device names in doc file

   fix review comments by Andy Shevchenko
   * exchange labels in switch block
   * replace iowrite8() with writeb()
   * compact comment to one line

   v4..v5
   * constify struct of_device_id
   * drop .owner from struct platform_driver
   * rewrite set_termios() baud rate hadnling as suggested by Alan Cox

   v3..v4
   * move DTS bindings to a different patch (8/21) as suggested by
     Heikki Krogerus

   v2..v3
   * no changes (except number 10/16 -> 12/21)

   v0..v2
   * register platform driver instead of platform device
   * use device tree
   * use devm helpers where possible

 .../bindings/serial/icpdas-lp8841-uart.txt         |  41 +++++
 drivers/tty/serial/8250/8250_lp8841.c              | 166 +++++++++++++++++++++
 drivers/tty/serial/8250/Kconfig                    |  14 ++
 drivers/tty/serial/8250/Makefile                   |   2 +
 4 files changed, 223 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/serial/icpdas-lp8841-uart.txt
 create mode 100644 drivers/tty/serial/8250/8250_lp8841.c

diff --git a/Documentation/devicetree/bindings/serial/icpdas-lp8841-uart.txt b/Documentation/devicetree/bindings/serial/icpdas-lp8841-uart.txt
new file mode 100644
index 0000000..d6acd22
--- /dev/null
+++ b/Documentation/devicetree/bindings/serial/icpdas-lp8841-uart.txt
@@ -0,0 +1,41 @@
+* UART ports on ICP DAS LP-8841
+
+LP-8441, LP-8141 and LP-8041 are fully compatible.
+
+ICP DAS LP-8841 contains three additional serial ports interfaced via
+Analog Devices ADM213EA chips in addition to 3 serial ports on PXA CPU.
+
+The chips themselves are standard, they would work with 8250_core if
+properly connected. However, they are not connected normally. Al least
+some of their config pins are wired to a different address region. So
+the driver is board-specific.
+
+Required properties:
+- compatible : should be "icpdas,uart-lp8841"
+
+- reg : should provide 16 byte man IO memory region and 1 byte region for
+	termios
+
+- interrupts : should provide interrupt
+
+Optional property:
+- interrupt-parent : should provide a link to interrupt controller either
+		     explicitly or implicitly from a parent node
+
+Examples (from pxa27x-lp8x4x.dts):
+
+		serial@9050 {
+			compatible = "icpdas,uart-lp8841";
+			reg = <0x9050 0x10
+			       0x9030 0x02>;
+			interrupts = <13>;
+			status = "okay";
+		};
+
+		serial@9060 {
+			compatible = "icpdas,uart-lp8841";
+			reg = <0x9060 0x10
+			       0x9032 0x02>;
+			interrupts = <14>;
+			status = "okay";
+		};
diff --git a/drivers/tty/serial/8250/8250_lp8841.c b/drivers/tty/serial/8250/8250_lp8841.c
new file mode 100644
index 0000000..6fef37f
--- /dev/null
+++ b/drivers/tty/serial/8250/8250_lp8841.c
@@ -0,0 +1,166 @@
+/*  linux/drivers/tty/serial/8250/8250_lp8841.c
+ *
+ *  Support for 16550A serial ports on ICP DAS LP-8841
+ *
+ *  Copyright (C) 2013 Sergei Ianovich <ynvich-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/module.h>
+#include <linux/serial_8250.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+struct lp8841_serial_data {
+	int			line;
+	void			*ios_mem;
+};
+
+static void lp8841_serial_set_termios(struct uart_port *port,
+		struct ktermios *termios, struct ktermios *old)
+{
+	unsigned int len;
+	unsigned int baud;
+	struct lp8841_serial_data *data = port->private_data;
+
+	serial8250_do_set_termios(port, termios, old);
+
+	switch (termios->c_cflag & CSIZE) {
+	case CS5:
+		len = 7;
+		break;
+	case CS6:
+		len = 8;
+		break;
+	case CS7:
+		len = 9;
+		break;
+	case CS8:
+	default:
+		len = 10;
+		break;
+	}
+
+	if (termios->c_cflag & CSTOPB)
+		len++;
+	if (termios->c_cflag & PARENB)
+		len++;
+	if (!(termios->c_cflag & PARODD))
+		len++;
+#ifdef CMSPAR
+	if (termios->c_cflag & CMSPAR)
+		len++;
+#endif
+
+	len -= 9;
+	len &= 3;
+	len <<= 3;
+
+	/* Ask the core to calculate the divisor for us. */
+	baud = tty_termios_baud_rate(termios);
+
+	switch (baud) {
+	case 115200:
+		len |= 7;
+		break;
+	case 57600:
+		len |= 6;
+		break;
+	case 38400:
+		len |= 5;
+		break;
+	case 19200:
+		len |= 4;
+		break;
+	case 9600:
+		len |= 3;
+		break;
+	case 4800:
+		len |= 2;
+		break;
+	case 2400:
+	default:
+		len |= 1;
+		break;
+	};
+	writeb(len, data->ios_mem);
+
+}
+
+static const struct of_device_id lp8841_serial_dt_ids[] = {
+	{ .compatible = "icpdas,lp8841-uart", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, lp8841_serial_dt_ids);
+
+static int lp8841_serial_probe(struct platform_device *pdev)
+{
+	struct uart_8250_port uart = {};
+	struct lp8841_serial_data *data;
+	struct resource *mmres, *mires;
+	int ret;
+
+	mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	mires = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	if (!mmres || !mires)
+		return -ENODEV;
+
+	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->ios_mem = devm_ioremap_resource(&pdev->dev, mires);
+	if (!data->ios_mem)
+		return -EFAULT;
+
+	uart.port.iotype = UPIO_MEM;
+	uart.port.mapbase = mmres->start;
+	uart.port.iobase = mmres->start;
+	uart.port.regshift = 1;
+	uart.port.irq = platform_get_irq(pdev, 0);
+	uart.port.flags = UPF_IOREMAP;
+	uart.port.dev = &pdev->dev;
+	uart.port.uartclk = 14745600;
+	uart.port.set_termios = lp8841_serial_set_termios;
+	uart.port.private_data = data;
+
+	ret = serial8250_register_8250_port(&uart);
+	if (ret < 0)
+		return ret;
+
+	data->line = ret;
+
+	platform_set_drvdata(pdev, data);
+
+	return 0;
+}
+
+static int lp8841_serial_remove(struct platform_device *pdev)
+{
+	struct lp8841_serial_data *data = platform_get_drvdata(pdev);
+
+	serial8250_unregister_port(data->line);
+
+	return 0;
+}
+
+static struct platform_driver lp8841_serial_driver = {
+	.probe          = lp8841_serial_probe,
+	.remove         = lp8841_serial_remove,
+
+	.driver		= {
+		.name	= "uart-lp8841",
+		.of_match_table = lp8841_serial_dt_ids,
+	},
+};
+
+module_platform_driver(lp8841_serial_driver);
+
+MODULE_AUTHOR("Sergei Ianovich");
+MODULE_DESCRIPTION("8250 serial port module for LP-8841");
+MODULE_LICENSE("GPL");
diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
index 3b5cf9c..68640c1 100644
--- a/drivers/tty/serial/8250/Kconfig
+++ b/drivers/tty/serial/8250/Kconfig
@@ -394,3 +394,17 @@ config SERIAL_8250_PXA
 	help
 	  If you have a machine based on an Intel XScale PXA2xx CPU you
 	  can enable its onboard serial ports by enabling this option.
+
+	  If you choose M here, the module name will be 8250_pxa.
+
+config SERIAL_8250_LP8841
+	tristate "Support 16550A ports on ICP DAS LP-8841"
+	depends on SERIAL_8250 && MACH_PXA27X_DT
+	select LP8841_IRQ
+	help
+	  In addition to serial ports on PXA270 SoC, LP-8841 has 1 dual
+	  RS232/RS485 port, 1 RS485 port and 1 RS232 port.
+
+	  Say N here, unless you plan to run this kernel on a LP-8841 system.
+
+	  If you choose M here, the module name will be 8250_lp8841.
diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile
index d1e2f2d..10b4bf0 100644
--- a/drivers/tty/serial/8250/Makefile
+++ b/drivers/tty/serial/8250/Makefile
@@ -18,6 +18,7 @@ obj-$(CONFIG_SERIAL_8250_ACCENT)	+= 8250_accent.o
 obj-$(CONFIG_SERIAL_8250_BOCA)		+= 8250_boca.o
 obj-$(CONFIG_SERIAL_8250_EXAR_ST16C554)	+= 8250_exar_st16c554.o
 obj-$(CONFIG_SERIAL_8250_HUB6)		+= 8250_hub6.o
+obj-$(CONFIG_SERIAL_8250_LP8X4X)	+= 8250_lp8x4x.o
 obj-$(CONFIG_SERIAL_8250_FSL)		+= 8250_fsl.o
 obj-$(CONFIG_SERIAL_8250_DW)		+= 8250_dw.o
 obj-$(CONFIG_SERIAL_8250_EM)		+= 8250_em.o
@@ -30,5 +31,6 @@ obj-$(CONFIG_SERIAL_8250_INGENIC)	+= 8250_ingenic.o
 obj-$(CONFIG_SERIAL_8250_MID)		+= 8250_mid.o
 obj-$(CONFIG_SERIAL_OF_PLATFORM)	+= 8250_of.o
 obj-$(CONFIG_SERIAL_8250_PXA)		+= 8250_pxa.o
+obj-$(CONFIG_SERIAL_8250_LP8841)	+= 8250_lp8841.o
 
 CFLAGS_8250_ingenic.o += -I$(srctree)/scripts/dtc/libfdt
-- 
2.7.0

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH v6] arm: pxa: support ICP DAS LP-8x4x FPGA irq
@ 2016-02-27 17:41                         ` Jason Cooper
  0 siblings, 0 replies; 700+ messages in thread
From: Jason Cooper @ 2016-02-27 17:41 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: linux-kernel, Arnd Bergmann, Rob Herring, Marc Zyngier,
	Thomas Gleixner, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS

Hi Sergei,

Marc, Rob, please see below.

On Sat, Feb 27, 2016 at 06:56:01PM +0300, Sergei Ianovich wrote:
> 

nit: Subject line of the patch should match 'irqchip/lp8841: [A-Z].*'

> ICP DAS LP-8x4x contains FPGA chip. The chip functions as an interrupt
> source providing 16 additional interrupts among other things. The
> interrupt lines are muxed to a GPIO pin of a 2nd level PXA-GPIO
> interrupt controller. GPIO pins of the 2nd level controller are in turn
> muxed to a CPU interrupt line.
> 
> Until pxa is completely converted to device tree, it is impossible
> to use IRQCHIP_DECLARE() and the irqdomain needs to added manually.
> Drivers for the on-CPU IRQs and GPIO-IRQs are loaded using
> postcore_initcall(). We need to have all irq domain drivers loaded prior
> to DT parsing in order to allow normal initialization of IRQ resources
> with DT.
> 
> Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
> Reviewed-by: Linus Walleij <linus.walleij@linaro.org>

nit:  From here, down should be below the '---' so that it isn't a part
of the commit log.  We add a link to the commit log that points to the
patch submission in the mailinglist archives.  So curious folks have
quick access to this info.

> CC: Arnd Bergmann <arnd@arndb.de>
> CC: Rob Herring <robh@kernel.org>
> CC: Marc Zyngier <marc.zyngier@arm.com>
> 
>    v5..v6
>    fixes according to Rob Herring review comments:
>    * drop wildcards in binding and file names
>    * rename alias 'fpga'->'fpga_irq'
> 
>    fixes according to Marc Zyngier review comments:
>    * use writeb/readb not iowrite8/ioread8
>    * redefine 2nd mask using inversion on 1st
>    * add comments
> 
>    v4..v5
>    * constify struct of_device_id
>    * drop irq number from handler signature
> 
>    v3.2..v4
>    * move DTS binding to a different patch (8/21)
> 
>    v3.1..v3.2
>    fixes to apply Linus Walleij's "Reviewed-by":
>    * add kerneldoc comment for state container struct
>    * rename irq -> hwirq for clarity
>    * drop overzealous error checks from the hotpaths
> 
>    v3..v3.1
>    fixes according to Linus Walleij review comments:
>    * update commit message
>    * use state container instead of global variables
>    * get hardware irq nums from irq_data, don't calculate them
>    * use BIT() macro
>    * add defines for system irq register masks
>    * replace cycle control variable with break
>    * use better names for resource variables
>    * add a linear domain instead of a legacy one
>    * use irq_create_mapping() instead of irq_alloc_desc()
> 
>    v2..v3
>    * no changes (except number 09/16 -> 11/21)
> 
>    v0..v2
>    * extract irqchip and move to drivers/irqchip/
>    * use device tree
>    * use devm helpers where possible


> ---

iow, it should be moved here.

>  .../interrupt-controller/icpdas-lp8x4x-irq.txt     |  49 ++++
>  drivers/irqchip/Kconfig                            |   5 +
>  drivers/irqchip/Makefile                           |   1 +
>  drivers/irqchip/irq-lp8841.c                       | 246 +++++++++++++++++++++
>  4 files changed, 301 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/interrupt-controller/icpdas-lp8x4x-irq.txt
>  create mode 100644 drivers/irqchip/irq-lp8841.c

I don't seem to have the previous versions, and their threads, in my
email archive.  From the changelog, it looks like Marc and Rob have been
reviewing this most recently.

If you guys could give me an Acked-by/Reviewed-by, I'll go ahead and
queue this up for v4.6.

I'll fix up the Subject line and the commit log when I bring it in.
I'll be adding the tags anyway.  No need to resubmit.

thx,

Jason.

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

* Re: [PATCH v6] arm: pxa: support ICP DAS LP-8x4x FPGA irq
@ 2016-02-27 17:41                         ` Jason Cooper
  0 siblings, 0 replies; 700+ messages in thread
From: Jason Cooper @ 2016-02-27 17:41 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA, Arnd Bergmann, Rob Herring,
	Marc Zyngier, Thomas Gleixner, Rob Herring, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS

Hi Sergei,

Marc, Rob, please see below.

On Sat, Feb 27, 2016 at 06:56:01PM +0300, Sergei Ianovich wrote:
> 

nit: Subject line of the patch should match 'irqchip/lp8841: [A-Z].*'

> ICP DAS LP-8x4x contains FPGA chip. The chip functions as an interrupt
> source providing 16 additional interrupts among other things. The
> interrupt lines are muxed to a GPIO pin of a 2nd level PXA-GPIO
> interrupt controller. GPIO pins of the 2nd level controller are in turn
> muxed to a CPU interrupt line.
> 
> Until pxa is completely converted to device tree, it is impossible
> to use IRQCHIP_DECLARE() and the irqdomain needs to added manually.
> Drivers for the on-CPU IRQs and GPIO-IRQs are loaded using
> postcore_initcall(). We need to have all irq domain drivers loaded prior
> to DT parsing in order to allow normal initialization of IRQ resources
> with DT.
> 
> Signed-off-by: Sergei Ianovich <ynvich-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> Reviewed-by: Linus Walleij <linus.walleij-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>

nit:  From here, down should be below the '---' so that it isn't a part
of the commit log.  We add a link to the commit log that points to the
patch submission in the mailinglist archives.  So curious folks have
quick access to this info.

> CC: Arnd Bergmann <arnd-r2nGTMty4D4@public.gmane.org>
> CC: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
> CC: Marc Zyngier <marc.zyngier-5wv7dgnIgG8@public.gmane.org>
> 
>    v5..v6
>    fixes according to Rob Herring review comments:
>    * drop wildcards in binding and file names
>    * rename alias 'fpga'->'fpga_irq'
> 
>    fixes according to Marc Zyngier review comments:
>    * use writeb/readb not iowrite8/ioread8
>    * redefine 2nd mask using inversion on 1st
>    * add comments
> 
>    v4..v5
>    * constify struct of_device_id
>    * drop irq number from handler signature
> 
>    v3.2..v4
>    * move DTS binding to a different patch (8/21)
> 
>    v3.1..v3.2
>    fixes to apply Linus Walleij's "Reviewed-by":
>    * add kerneldoc comment for state container struct
>    * rename irq -> hwirq for clarity
>    * drop overzealous error checks from the hotpaths
> 
>    v3..v3.1
>    fixes according to Linus Walleij review comments:
>    * update commit message
>    * use state container instead of global variables
>    * get hardware irq nums from irq_data, don't calculate them
>    * use BIT() macro
>    * add defines for system irq register masks
>    * replace cycle control variable with break
>    * use better names for resource variables
>    * add a linear domain instead of a legacy one
>    * use irq_create_mapping() instead of irq_alloc_desc()
> 
>    v2..v3
>    * no changes (except number 09/16 -> 11/21)
> 
>    v0..v2
>    * extract irqchip and move to drivers/irqchip/
>    * use device tree
>    * use devm helpers where possible


> ---

iow, it should be moved here.

>  .../interrupt-controller/icpdas-lp8x4x-irq.txt     |  49 ++++
>  drivers/irqchip/Kconfig                            |   5 +
>  drivers/irqchip/Makefile                           |   1 +
>  drivers/irqchip/irq-lp8841.c                       | 246 +++++++++++++++++++++
>  4 files changed, 301 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/interrupt-controller/icpdas-lp8x4x-irq.txt
>  create mode 100644 drivers/irqchip/irq-lp8841.c

I don't seem to have the previous versions, and their threads, in my
email archive.  From the changelog, it looks like Marc and Rob have been
reviewing this most recently.

If you guys could give me an Acked-by/Reviewed-by, I'll go ahead and
queue this up for v4.6.

I'll fix up the Subject line and the commit log when I bring it in.
I'll be adding the tags anyway.  No need to resubmit.

thx,

Jason.
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH v6] arm: pxa: support ICP DAS LP-8x4x FPGA irq
@ 2016-02-29  8:29                           ` Marc Zyngier
  0 siblings, 0 replies; 700+ messages in thread
From: Marc Zyngier @ 2016-02-29  8:29 UTC (permalink / raw)
  To: Jason Cooper, Sergei Ianovich
  Cc: linux-kernel, Arnd Bergmann, Rob Herring, Thomas Gleixner,
	Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS

On 27/02/16 17:41, Jason Cooper wrote:
> Hi Sergei,
> 
> Marc, Rob, please see below.
> 
> On Sat, Feb 27, 2016 at 06:56:01PM +0300, Sergei Ianovich wrote:
>>
> 
> nit: Subject line of the patch should match 'irqchip/lp8841: [A-Z].*'
> 
>> ICP DAS LP-8x4x contains FPGA chip. The chip functions as an interrupt
>> source providing 16 additional interrupts among other things. The
>> interrupt lines are muxed to a GPIO pin of a 2nd level PXA-GPIO
>> interrupt controller. GPIO pins of the 2nd level controller are in turn
>> muxed to a CPU interrupt line.
>>
>> Until pxa is completely converted to device tree, it is impossible
>> to use IRQCHIP_DECLARE() and the irqdomain needs to added manually.
>> Drivers for the on-CPU IRQs and GPIO-IRQs are loaded using
>> postcore_initcall(). We need to have all irq domain drivers loaded prior
>> to DT parsing in order to allow normal initialization of IRQ resources
>> with DT.
>>
>> Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
>> Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
> 
> nit:  From here, down should be below the '---' so that it isn't a part
> of the commit log.  We add a link to the commit log that points to the
> patch submission in the mailinglist archives.  So curious folks have
> quick access to this info.
> 
>> CC: Arnd Bergmann <arnd@arndb.de>
>> CC: Rob Herring <robh@kernel.org>
>> CC: Marc Zyngier <marc.zyngier@arm.com>
>>
>>    v5..v6
>>    fixes according to Rob Herring review comments:
>>    * drop wildcards in binding and file names
>>    * rename alias 'fpga'->'fpga_irq'
>>
>>    fixes according to Marc Zyngier review comments:
>>    * use writeb/readb not iowrite8/ioread8
>>    * redefine 2nd mask using inversion on 1st
>>    * add comments
>>
>>    v4..v5
>>    * constify struct of_device_id
>>    * drop irq number from handler signature
>>
>>    v3.2..v4
>>    * move DTS binding to a different patch (8/21)
>>
>>    v3.1..v3.2
>>    fixes to apply Linus Walleij's "Reviewed-by":
>>    * add kerneldoc comment for state container struct
>>    * rename irq -> hwirq for clarity
>>    * drop overzealous error checks from the hotpaths
>>
>>    v3..v3.1
>>    fixes according to Linus Walleij review comments:
>>    * update commit message
>>    * use state container instead of global variables
>>    * get hardware irq nums from irq_data, don't calculate them
>>    * use BIT() macro
>>    * add defines for system irq register masks
>>    * replace cycle control variable with break
>>    * use better names for resource variables
>>    * add a linear domain instead of a legacy one
>>    * use irq_create_mapping() instead of irq_alloc_desc()
>>
>>    v2..v3
>>    * no changes (except number 09/16 -> 11/21)
>>
>>    v0..v2
>>    * extract irqchip and move to drivers/irqchip/
>>    * use device tree
>>    * use devm helpers where possible
> 
> 
>> ---
> 
> iow, it should be moved here.
> 
>>  .../interrupt-controller/icpdas-lp8x4x-irq.txt     |  49 ++++
>>  drivers/irqchip/Kconfig                            |   5 +
>>  drivers/irqchip/Makefile                           |   1 +
>>  drivers/irqchip/irq-lp8841.c                       | 246 +++++++++++++++++++++
>>  4 files changed, 301 insertions(+)
>>  create mode 100644 Documentation/devicetree/bindings/interrupt-controller/icpdas-lp8x4x-irq.txt
>>  create mode 100644 drivers/irqchip/irq-lp8841.c
> 
> I don't seem to have the previous versions, and their threads, in my
> email archive.  From the changelog, it looks like Marc and Rob have been
> reviewing this most recently.
> 
> If you guys could give me an Acked-by/Reviewed-by, I'll go ahead and
> queue this up for v4.6.
> 
> I'll fix up the Subject line and the commit log when I bring it in.
> I'll be adding the tags anyway.  No need to resubmit.

Looks OK to me:

Acked-by: Marc Zyngier <marc.zyngier@arm.com>

	M.
-- 
Jazz is not dead. It just smells funny...

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

* Re: [PATCH v6] arm: pxa: support ICP DAS LP-8x4x FPGA irq
@ 2016-02-29  8:29                           ` Marc Zyngier
  0 siblings, 0 replies; 700+ messages in thread
From: Marc Zyngier @ 2016-02-29  8:29 UTC (permalink / raw)
  To: Jason Cooper, Sergei Ianovich
  Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA, Arnd Bergmann, Rob Herring,
	Thomas Gleixner, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS

On 27/02/16 17:41, Jason Cooper wrote:
> Hi Sergei,
> 
> Marc, Rob, please see below.
> 
> On Sat, Feb 27, 2016 at 06:56:01PM +0300, Sergei Ianovich wrote:
>>
> 
> nit: Subject line of the patch should match 'irqchip/lp8841: [A-Z].*'
> 
>> ICP DAS LP-8x4x contains FPGA chip. The chip functions as an interrupt
>> source providing 16 additional interrupts among other things. The
>> interrupt lines are muxed to a GPIO pin of a 2nd level PXA-GPIO
>> interrupt controller. GPIO pins of the 2nd level controller are in turn
>> muxed to a CPU interrupt line.
>>
>> Until pxa is completely converted to device tree, it is impossible
>> to use IRQCHIP_DECLARE() and the irqdomain needs to added manually.
>> Drivers for the on-CPU IRQs and GPIO-IRQs are loaded using
>> postcore_initcall(). We need to have all irq domain drivers loaded prior
>> to DT parsing in order to allow normal initialization of IRQ resources
>> with DT.
>>
>> Signed-off-by: Sergei Ianovich <ynvich-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
>> Reviewed-by: Linus Walleij <linus.walleij-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> 
> nit:  From here, down should be below the '---' so that it isn't a part
> of the commit log.  We add a link to the commit log that points to the
> patch submission in the mailinglist archives.  So curious folks have
> quick access to this info.
> 
>> CC: Arnd Bergmann <arnd-r2nGTMty4D4@public.gmane.org>
>> CC: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
>> CC: Marc Zyngier <marc.zyngier-5wv7dgnIgG8@public.gmane.org>
>>
>>    v5..v6
>>    fixes according to Rob Herring review comments:
>>    * drop wildcards in binding and file names
>>    * rename alias 'fpga'->'fpga_irq'
>>
>>    fixes according to Marc Zyngier review comments:
>>    * use writeb/readb not iowrite8/ioread8
>>    * redefine 2nd mask using inversion on 1st
>>    * add comments
>>
>>    v4..v5
>>    * constify struct of_device_id
>>    * drop irq number from handler signature
>>
>>    v3.2..v4
>>    * move DTS binding to a different patch (8/21)
>>
>>    v3.1..v3.2
>>    fixes to apply Linus Walleij's "Reviewed-by":
>>    * add kerneldoc comment for state container struct
>>    * rename irq -> hwirq for clarity
>>    * drop overzealous error checks from the hotpaths
>>
>>    v3..v3.1
>>    fixes according to Linus Walleij review comments:
>>    * update commit message
>>    * use state container instead of global variables
>>    * get hardware irq nums from irq_data, don't calculate them
>>    * use BIT() macro
>>    * add defines for system irq register masks
>>    * replace cycle control variable with break
>>    * use better names for resource variables
>>    * add a linear domain instead of a legacy one
>>    * use irq_create_mapping() instead of irq_alloc_desc()
>>
>>    v2..v3
>>    * no changes (except number 09/16 -> 11/21)
>>
>>    v0..v2
>>    * extract irqchip and move to drivers/irqchip/
>>    * use device tree
>>    * use devm helpers where possible
> 
> 
>> ---
> 
> iow, it should be moved here.
> 
>>  .../interrupt-controller/icpdas-lp8x4x-irq.txt     |  49 ++++
>>  drivers/irqchip/Kconfig                            |   5 +
>>  drivers/irqchip/Makefile                           |   1 +
>>  drivers/irqchip/irq-lp8841.c                       | 246 +++++++++++++++++++++
>>  4 files changed, 301 insertions(+)
>>  create mode 100644 Documentation/devicetree/bindings/interrupt-controller/icpdas-lp8x4x-irq.txt
>>  create mode 100644 drivers/irqchip/irq-lp8841.c
> 
> I don't seem to have the previous versions, and their threads, in my
> email archive.  From the changelog, it looks like Marc and Rob have been
> reviewing this most recently.
> 
> If you guys could give me an Acked-by/Reviewed-by, I'll go ahead and
> queue this up for v4.6.
> 
> I'll fix up the Subject line and the commit log when I bring it in.
> I'll be adding the tags anyway.  No need to resubmit.

Looks OK to me:

Acked-by: Marc Zyngier <marc.zyngier-5wv7dgnIgG8@public.gmane.org>

	M.
-- 
Jazz is not dead. It just smells funny...
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH v6] serial: support for 16550A serial ports on LP-8x4x
@ 2016-02-29 10:29                       ` Andy Shevchenko
  0 siblings, 0 replies; 700+ messages in thread
From: Andy Shevchenko @ 2016-02-29 10:29 UTC (permalink / raw)
  To: Sergei Ianovich, linux-kernel
  Cc: Alan Cox, Arnd Bergmann, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Greg Kroah-Hartman, Jiri Slaby,
	Heikki Krogerus, Masahiro Yamada, Paul Burton, Paul Gortmaker,
	Mans Rullgard, Scott Wood, Joachim Eastwood, Peter Ujfalusi,
	Peter Hurley,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	open list:SERIAL DRIVERS

On Sat, 2016-02-27 at 19:14 +0300, Sergei Ianovich wrote:
> The patch adds support for 3 additional LP-8x4x built-in serial
> ports.
> 
> The device can also host up to 8 extension cards with 4 serial ports
> on each card for a total of 35 ports. However, I don't have
> the hardware to test extension cards, so they are not supported, yet.

My comments below.
After addressing them:
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>

> +++ b/drivers/tty/serial/8250/8250_lp8841.c
> @@ -0,0 +1,166 @@
> +/*  linux/drivers/tty/serial/8250/8250_lp8841.c
> + *
> + *  Support for 16550A serial ports on ICP DAS LP-8841
> + *
> + *  Copyright (C) 2013 Sergei Ianovich <ynvich@gmail.com>
> + *
> + *  This program is free software; you can redistribute it and/or
> modify
> + *  it under the terms of the GNU General Public License version 2
> as
> + *  published by the Free Software Foundation.
> + */
> +#include <linux/init.h>
> +#include <linux/io.h>
> +#include <linux/irq.h>
> +#include <linux/module.h>
> +#include <linux/serial_8250.h>
> +#include <linux/of.h>
> +#include <linux/platform_device.h>
> +
> +struct lp8841_serial_data {
> +	int			line;
> +	void			*ios_mem;

__iomem

> +};

> +	if (termios->c_cflag & CSTOPB)
> +		len++;
> +	if (termios->c_cflag & PARENB)
> +		len++;
> +	if (!(termios->c_cflag & PARODD))
> +		len++;
> +#ifdef CMSPAR
> +	if (termios->c_cflag & CMSPAR)
> +		len++;
> +#endif
> +
> +	len -= 9;

If you have 5 bit mode, no parity, 1/1.5 stop bits, you may end up with
negative value here. Am I right? If so, is it expected?

> +	len &= 3;
> +	len <<= 3;

> +	writeb(len, data->ios_mem);
> +
> +}


> +static int lp8841_serial_probe(struct platform_device *pdev)
> +{
> +	struct uart_8250_port uart = {};
> +	struct lp8841_serial_data *data;
> +	struct resource *mmres, *mires;
> +	int ret;
> +
> +	mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	mires = platform_get_resource(pdev, IORESOURCE_MEM, 1);
> +	if (!mmres || !mires)
> +		return -ENODEV;

No need to check mires here, devm_ioremap_resource() will take care
about.

> +
> +	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
> +	if (!data)
> +		return -ENOMEM;
> +
> +	data->ios_mem = devm_ioremap_resource(&pdev->dev, mires);
> +	if (!data->ios_mem)
> +		return -EFAULT;

You have to propagate the actual error code from
devm_ioremap_resource().

> +
> +	uart.port.iotype = UPIO_MEM;
> 

> +	uart.port.mapbase = mmres->start;
> +	uart.port.iobase = mmres->start;

I'm not sure about this. If you ask for UPIO_MEM why do you need to
fill iobase?
And I suppose iobase can't hold (at the end inb/outb calls) big port
numbers anyway (16 bit on x86, for example).

> +	uart.port.regshift = 1;
> +	uart.port.irq = platform_get_irq(pdev, 0);
> +	uart.port.flags = UPF_IOREMAP;
> +	uart.port.dev = &pdev->dev;
> +	uart.port.uartclk = 14745600;
> +	uart.port.set_termios = lp8841_serial_set_termios;
> +	uart.port.private_data = data;
> +
> +	ret = serial8250_register_8250_port(&uart);
> +	if (ret < 0)
> +		return ret;
> +
> +	data->line = ret;
> +
> +	platform_set_drvdata(pdev, data);
> +
> +	return 0;
> +}
> +
> +static int lp8841_serial_remove(struct platform_device *pdev)
> +{
> +	struct lp8841_serial_data *data =
> platform_get_drvdata(pdev);
> +
> +	serial8250_unregister_port(data->line);
> +
> +	return 0;
> +}
> +
> +static struct platform_driver lp8841_serial_driver = {
> +	.probe          = lp8841_serial_probe,
> +	.remove         = lp8841_serial_remove,
> +
> +	.driver		= {
> +		.name	= "uart-lp8841",
> +		.of_match_table = lp8841_serial_dt_ids,
> +	},
> +};

-- 
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Intel Finland Oy

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

* Re: [PATCH v6] serial: support for 16550A serial ports on LP-8x4x
@ 2016-02-29 10:29                       ` Andy Shevchenko
  0 siblings, 0 replies; 700+ messages in thread
From: Andy Shevchenko @ 2016-02-29 10:29 UTC (permalink / raw)
  To: Sergei Ianovich, linux-kernel-u79uwXL29TY76Z2rM5mHXA
  Cc: Alan Cox, Arnd Bergmann, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Greg Kroah-Hartman, Jiri Slaby,
	Heikki Krogerus, Masahiro Yamada, Paul Burton, Paul Gortmaker,
	Mans Rullgard, Scott Wood, Joachim Eastwood, Peter Ujfalusi,
	Peter Hurley,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	open list:SERIAL DRIVERS

On Sat, 2016-02-27 at 19:14 +0300, Sergei Ianovich wrote:
> The patch adds support for 3 additional LP-8x4x built-in serial
> ports.
> 
> The device can also host up to 8 extension cards with 4 serial ports
> on each card for a total of 35 ports. However, I don't have
> the hardware to test extension cards, so they are not supported, yet.

My comments below.
After addressing them:
Reviewed-by: Andy Shevchenko <andriy.shevchenko-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>

> +++ b/drivers/tty/serial/8250/8250_lp8841.c
> @@ -0,0 +1,166 @@
> +/*  linux/drivers/tty/serial/8250/8250_lp8841.c
> + *
> + *  Support for 16550A serial ports on ICP DAS LP-8841
> + *
> + *  Copyright (C) 2013 Sergei Ianovich <ynvich-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> + *
> + *  This program is free software; you can redistribute it and/or
> modify
> + *  it under the terms of the GNU General Public License version 2
> as
> + *  published by the Free Software Foundation.
> + */
> +#include <linux/init.h>
> +#include <linux/io.h>
> +#include <linux/irq.h>
> +#include <linux/module.h>
> +#include <linux/serial_8250.h>
> +#include <linux/of.h>
> +#include <linux/platform_device.h>
> +
> +struct lp8841_serial_data {
> +	int			line;
> +	void			*ios_mem;

__iomem

> +};

> +	if (termios->c_cflag & CSTOPB)
> +		len++;
> +	if (termios->c_cflag & PARENB)
> +		len++;
> +	if (!(termios->c_cflag & PARODD))
> +		len++;
> +#ifdef CMSPAR
> +	if (termios->c_cflag & CMSPAR)
> +		len++;
> +#endif
> +
> +	len -= 9;

If you have 5 bit mode, no parity, 1/1.5 stop bits, you may end up with
negative value here. Am I right? If so, is it expected?

> +	len &= 3;
> +	len <<= 3;

> +	writeb(len, data->ios_mem);
> +
> +}


> +static int lp8841_serial_probe(struct platform_device *pdev)
> +{
> +	struct uart_8250_port uart = {};
> +	struct lp8841_serial_data *data;
> +	struct resource *mmres, *mires;
> +	int ret;
> +
> +	mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	mires = platform_get_resource(pdev, IORESOURCE_MEM, 1);
> +	if (!mmres || !mires)
> +		return -ENODEV;

No need to check mires here, devm_ioremap_resource() will take care
about.

> +
> +	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
> +	if (!data)
> +		return -ENOMEM;
> +
> +	data->ios_mem = devm_ioremap_resource(&pdev->dev, mires);
> +	if (!data->ios_mem)
> +		return -EFAULT;

You have to propagate the actual error code from
devm_ioremap_resource().

> +
> +	uart.port.iotype = UPIO_MEM;
> 

> +	uart.port.mapbase = mmres->start;
> +	uart.port.iobase = mmres->start;

I'm not sure about this. If you ask for UPIO_MEM why do you need to
fill iobase?
And I suppose iobase can't hold (at the end inb/outb calls) big port
numbers anyway (16 bit on x86, for example).

> +	uart.port.regshift = 1;
> +	uart.port.irq = platform_get_irq(pdev, 0);
> +	uart.port.flags = UPF_IOREMAP;
> +	uart.port.dev = &pdev->dev;
> +	uart.port.uartclk = 14745600;
> +	uart.port.set_termios = lp8841_serial_set_termios;
> +	uart.port.private_data = data;
> +
> +	ret = serial8250_register_8250_port(&uart);
> +	if (ret < 0)
> +		return ret;
> +
> +	data->line = ret;
> +
> +	platform_set_drvdata(pdev, data);
> +
> +	return 0;
> +}
> +
> +static int lp8841_serial_remove(struct platform_device *pdev)
> +{
> +	struct lp8841_serial_data *data =
> platform_get_drvdata(pdev);
> +
> +	serial8250_unregister_port(data->line);
> +
> +	return 0;
> +}
> +
> +static struct platform_driver lp8841_serial_driver = {
> +	.probe          = lp8841_serial_probe,
> +	.remove         = lp8841_serial_remove,
> +
> +	.driver		= {
> +		.name	= "uart-lp8841",
> +		.of_match_table = lp8841_serial_dt_ids,
> +	},
> +};

-- 
Andy Shevchenko <andriy.shevchenko-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
Intel Finland Oy

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH v6] serial: support for 16550A serial ports on LP-8x4x
  2016-02-29 10:29                       ` Andy Shevchenko
@ 2016-02-29 13:03                         ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2016-02-29 13:03 UTC (permalink / raw)
  To: Andy Shevchenko, linux-kernel
  Cc: Alan Cox, Arnd Bergmann, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Greg Kroah-Hartman, Jiri Slaby,
	Heikki Krogerus, Masahiro Yamada, Paul Burton, Paul Gortmaker,
	Mans Rullgard, Scott Wood, Joachim Eastwood, Peter Ujfalusi,
	Peter Hurley,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	open list:SERIAL DRIVERS

On Mon, 2016-02-29 at 12:29 +0200, Andy Shevchenko wrote:
> On Sat, 2016-02-27 at 19:14 +0300, Sergei Ianovich wrote:
> > +struct lp8841_serial_data {
> > +	int			line;
> > +	void			*ios_mem;
> 
> __iomem

OK

> > +};
> 
> > +	if (termios->c_cflag & CSTOPB)
> > +		len++;
> > +	if (termios->c_cflag & PARENB)
> > +		len++;
> > +	if (!(termios->c_cflag & PARODD))
> > +		len++;
> > +#ifdef CMSPAR
> > +	if (termios->c_cflag & CMSPAR)
> > +		len++;
> > +#endif
> > +
> > +	len -= 9;
> 
> If you have 5 bit mode, no parity, 1/1.5 stop bits, you may end up
> with
> negative value here. Am I right? If so, is it expected?
> 
> > +	len &= 3;
> > +	len <<= 3;

I haven't tested this mode. I am pretty sure it will fail. There is
also no support for speeds higher than 115200.

CS7 and CS8 at speeds up to 115200 work well.

However, there is no way to report errors from set_termios(). Should
anything be done about those limitations?

> +	mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > +	mires = platform_get_resource(pdev, IORESOURCE_MEM, 1);
> > +	if (!mmres || !mires)
> > +		return -ENODEV;
> 
> No need to check mires here, devm_ioremap_resource() will take care
> about.

OK

> > +	data->ios_mem = devm_ioremap_resource(&pdev->dev,
> > > > mires);
> > +	if (!data->ios_mem)
> > +		return -EFAULT;
> 
> You have to propagate the actual error code from
> devm_ioremap_resource().

OK

> > +
> > +	uart.port.iotype = UPIO_MEM;
> > 
> 
> > +	uart.port.mapbase = mmres->start;
> > +	uart.port.iobase = mmres->start;
> 
> I'm not sure about this. If you ask for UPIO_MEM why do you need to
> fill iobase?
> And I suppose iobase can't hold (at the end inb/outb calls) big port
> numbers anyway (16 bit on x86, for example).

There is no need for iobase. I'll remove that line.

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

* Re: [PATCH v6] serial: support for 16550A serial ports on LP-8x4x
@ 2016-02-29 13:03                         ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2016-02-29 13:03 UTC (permalink / raw)
  To: Andy Shevchenko, linux-kernel
  Cc: Alan Cox, Arnd Bergmann, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Greg Kroah-Hartman, Jiri Slaby,
	Heikki Krogerus, Masahiro Yamada, Paul Burton, Paul Gortmaker,
	Mans Rullgard, Scott Wood, Joachim Eastwood, Peter Ujfalusi,
	Peter Hurley,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	open list:SERIAL DRIVERS

On Mon, 2016-02-29 at 12:29 +0200, Andy Shevchenko wrote:
> On Sat, 2016-02-27 at 19:14 +0300, Sergei Ianovich wrote:
> > +struct lp8841_serial_data {
> > +	int			line;
> > +	void			*ios_mem;
> 
> __iomem

OK

> > +};
> 
> > +	if (termios->c_cflag & CSTOPB)
> > +		len++;
> > +	if (termios->c_cflag & PARENB)
> > +		len++;
> > +	if (!(termios->c_cflag & PARODD))
> > +		len++;
> > +#ifdef CMSPAR
> > +	if (termios->c_cflag & CMSPAR)
> > +		len++;
> > +#endif
> > +
> > +	len -= 9;
> 
> If you have 5 bit mode, no parity, 1/1.5 stop bits, you may end up
> with
> negative value here. Am I right? If so, is it expected?
> 
> > +	len &= 3;
> > +	len <<= 3;

I haven't tested this mode. I am pretty sure it will fail. There is
also no support for speeds higher than 115200.

CS7 and CS8 at speeds up to 115200 work well.

However, there is no way to report errors from set_termios(). Should
anything be done about those limitations?

> +	mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > +	mires = platform_get_resource(pdev, IORESOURCE_MEM, 1);
> > +	if (!mmres || !mires)
> > +		return -ENODEV;
> 
> No need to check mires here, devm_ioremap_resource() will take care
> about.

OK

> > +	data->ios_mem = devm_ioremap_resource(&pdev->dev,
> > > > mires);
> > +	if (!data->ios_mem)
> > +		return -EFAULT;
> 
> You have to propagate the actual error code from
> devm_ioremap_resource().

OK

> > +
> > +	uart.port.iotype = UPIO_MEM;
> > 
> 
> > +	uart.port.mapbase = mmres->start;
> > +	uart.port.iobase = mmres->start;
> 
> I'm not sure about this. If you ask for UPIO_MEM why do you need to
> fill iobase?
> And I suppose iobase can't hold (at the end inb/outb calls) big port
> numbers anyway (16 bit on x86, for example).

There is no need for iobase. I'll remove that line.

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

* Re: [PATCH v6] serial: support for 16550A serial ports on LP-8x4x
@ 2016-02-29 14:45                           ` One Thousand Gnomes
  0 siblings, 0 replies; 700+ messages in thread
From: One Thousand Gnomes @ 2016-02-29 14:45 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: Andy Shevchenko, linux-kernel, Arnd Bergmann, Rob Herring,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	Greg Kroah-Hartman, Jiri Slaby, Heikki Krogerus, Masahiro Yamada,
	Paul Burton, Paul Gortmaker, Mans Rullgard, Scott Wood,
	Joachim Eastwood, Peter Ujfalusi, Peter Hurley,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	open list:SERIAL DRIVERS

> I haven't tested this mode. I am pretty sure it will fail. There is
> also no support for speeds higher than 115200.
> 
> CS7 and CS8 at speeds up to 115200 work well.
> 
> However, there is no way to report errors from set_termios(). Should
> anything be done about those limitations?

You report back by setting the termios fields to the values actually
selected. Eg if you can't do CS5/CS6 you'd pick CS7 or CS8 and write that
back into tty->termios so the caller knows what they actually got. Ditto
for speed (see the 16550A core driver for the speed write backs).

Alan

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

* Re: [PATCH v6] serial: support for 16550A serial ports on LP-8x4x
@ 2016-02-29 14:45                           ` One Thousand Gnomes
  0 siblings, 0 replies; 700+ messages in thread
From: One Thousand Gnomes @ 2016-02-29 14:45 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: Andy Shevchenko, linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	Arnd Bergmann, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Greg Kroah-Hartman, Jiri Slaby,
	Heikki Krogerus, Masahiro Yamada, Paul Burton, Paul Gortmaker,
	Mans Rullgard, Scott Wood, Joachim Eastwood, Peter Ujfalusi,
	Peter Hurley,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS

> I haven't tested this mode. I am pretty sure it will fail. There is
> also no support for speeds higher than 115200.
> 
> CS7 and CS8 at speeds up to 115200 work well.
> 
> However, there is no way to report errors from set_termios(). Should
> anything be done about those limitations?

You report back by setting the termios fields to the values actually
selected. Eg if you can't do CS5/CS6 you'd pick CS7 or CS8 and write that
back into tty->termios so the caller knows what they actually got. Ditto
for speed (see the 16550A core driver for the speed write backs).

Alan
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH v7] serial: support for 16550A serial ports on LP-8x4x
  2016-02-27 16:14                     ` Sergei Ianovich
@ 2016-02-29 21:26                       ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2016-02-29 21:26 UTC (permalink / raw)
  To: linux-kernel
  Cc: Sergei Ianovich, Alan Cox, Andy Shevchenko, Arnd Bergmann,
	Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	Greg Kroah-Hartman, Jiri Slaby, Heikki Krogerus, Peter Hurley,
	Masahiro Yamada, Paul Burton, Mans Rullgard, Joachim Eastwood,
	Scott Wood, Paul Gortmaker, Peter Ujfalusi,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	open list:SERIAL DRIVERS

The patch adds support for 3 additional LP-8x4x built-in serial
ports.

The device can also host up to 8 extension cards with 4 serial ports
on each card for a total of 35 ports. However, I don't have
the hardware to test extension cards, so they are not supported, yet.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
---
CC: Alan Cox <gnomes@lxorguk.ukuu.org.uk>
CC: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
CC: Arnd Bergmann <arnd@arndb.de>

   v6..v7
   fix review comments by Andy Shevchenko
   not applying Acked-by as the 1st change is big
   * handle unsupported tty modes correctly as suggested by Alan Cox
   * remove extra check of platform_get_resource() result
   * propagate error code from devm_ioremap_resource()
   * drop uart.port.iobase for UPIO_MEM device

   v5..v6
   fix review comments by Arnd Bergmann
   * remove wildcards from compatible
   * update doc file
   * drop interrupt parent from doc file
   * replace uart w/ serial in device names in doc file

   fix review comments by Andy Shevchenko
   * exchange labels in switch block
   * replace iowrite8() with writeb()
   * compact comment to one line

   v4..v5
   * constify struct of_device_id
   * drop .owner from struct platform_driver
   * rewrite set_termios() baud rate hadnling as suggested by Alan Cox

   v3..v4
   * move DTS bindings to a different patch (8/21) as suggested by
     Heikki Krogerus

   v2..v3
   * no changes (except number 10/16 -> 12/21)

   v0..v2
   * register platform driver instead of platform device
   * use device tree
   * use devm helpers where possible

 .../bindings/serial/icpdas-lp8841-uart.txt         |  41 +++++
 drivers/tty/serial/8250/8250_lp8841.c              | 193 +++++++++++++++++++++
 drivers/tty/serial/8250/Kconfig                    |  14 ++
 drivers/tty/serial/8250/Makefile                   |   2 +
 4 files changed, 250 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/serial/icpdas-lp8841-uart.txt
 create mode 100644 drivers/tty/serial/8250/8250_lp8841.c

diff --git a/Documentation/devicetree/bindings/serial/icpdas-lp8841-uart.txt b/Documentation/devicetree/bindings/serial/icpdas-lp8841-uart.txt
new file mode 100644
index 0000000..d6acd22
--- /dev/null
+++ b/Documentation/devicetree/bindings/serial/icpdas-lp8841-uart.txt
@@ -0,0 +1,41 @@
+* UART ports on ICP DAS LP-8841
+
+LP-8441, LP-8141 and LP-8041 are fully compatible.
+
+ICP DAS LP-8841 contains three additional serial ports interfaced via
+Analog Devices ADM213EA chips in addition to 3 serial ports on PXA CPU.
+
+The chips themselves are standard, they would work with 8250_core if
+properly connected. However, they are not connected normally. Al least
+some of their config pins are wired to a different address region. So
+the driver is board-specific.
+
+Required properties:
+- compatible : should be "icpdas,uart-lp8841"
+
+- reg : should provide 16 byte man IO memory region and 1 byte region for
+	termios
+
+- interrupts : should provide interrupt
+
+Optional property:
+- interrupt-parent : should provide a link to interrupt controller either
+		     explicitly or implicitly from a parent node
+
+Examples (from pxa27x-lp8x4x.dts):
+
+		serial@9050 {
+			compatible = "icpdas,uart-lp8841";
+			reg = <0x9050 0x10
+			       0x9030 0x02>;
+			interrupts = <13>;
+			status = "okay";
+		};
+
+		serial@9060 {
+			compatible = "icpdas,uart-lp8841";
+			reg = <0x9060 0x10
+			       0x9032 0x02>;
+			interrupts = <14>;
+			status = "okay";
+		};
diff --git a/drivers/tty/serial/8250/8250_lp8841.c b/drivers/tty/serial/8250/8250_lp8841.c
new file mode 100644
index 0000000..e92c01c
--- /dev/null
+++ b/drivers/tty/serial/8250/8250_lp8841.c
@@ -0,0 +1,193 @@
+/*  linux/drivers/tty/serial/8250/8250_lp8841.c
+ *
+ *  Support for 16550A serial ports on ICP DAS LP-8841
+ *
+ *  Copyright (C) 2013 Sergei Ianovich <ynvich@gmail.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/module.h>
+#include <linux/serial_8250.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+struct lp8841_serial_data {
+	int			line;
+	void __iomem		*ios_mem;
+};
+
+static void lp8841_serial_set_termios(struct uart_port *port,
+		struct ktermios *termios, struct ktermios *old)
+{
+#ifdef BOTHER
+	unsigned int cbaud;
+#endif
+	unsigned int baud;
+	unsigned int len;
+	unsigned int old_csize = old ? old->c_cflag & CSIZE : CS8;
+	struct lp8841_serial_data *data = port->private_data;
+
+	/* We only support CS7 and CS8 */
+	while ((termios->c_cflag & CSIZE) != CS7 &&
+	       (termios->c_cflag & CSIZE) != CS8) {
+		termios->c_cflag &= ~CSIZE;
+		termios->c_cflag |= old_csize;
+		old_csize = CS8;
+	}
+
+	serial8250_do_set_termios(port, termios, old);
+
+	if ((termios->c_cflag & CSIZE) == CS7)
+		len = 9;
+	else
+		len = 10;
+
+	if (termios->c_cflag & CSTOPB)
+		len++;
+	if (termios->c_cflag & PARENB)
+		len++;
+	if (!(termios->c_cflag & PARODD))
+		len++;
+#ifdef CMSPAR
+	if (termios->c_cflag & CMSPAR)
+		len++;
+#endif
+
+	len -= 9;
+	len &= 3;
+	len <<= 3;
+
+	baud = tty_termios_baud_rate(termios);
+
+#ifdef BOTHER
+	/* We only support fixed rates */
+	cbaud = termios->c_cflag & CBAUD;
+
+	if (cbaud == BOTHER) {
+		termios->c_cflag &= ~BOTHER;
+
+		/* Don't rewrite B0 */
+		if (baud) {
+			tty_termios_encode_baud_rate(termios, baud, baud);
+			baud = tty_termios_baud_rate(termios);
+
+			/* Set sane default speed if we get 0 */
+			if (!baud) {
+				baud = 9600;
+				tty_termios_encode_baud_rate(termios,
+						baud, baud);
+			}
+		}
+	}
+#endif
+
+	/* We only support up to 115200 */
+	if (baud > 115200) {
+		baud = 115200;
+		tty_termios_encode_baud_rate(termios, baud, baud);
+	}
+
+	switch (baud) {
+	case 115200:
+		len |= 7;
+		break;
+	case 57600:
+		len |= 6;
+		break;
+	case 38400:
+		len |= 5;
+		break;
+	case 19200:
+		len |= 4;
+		break;
+	case 9600:
+		len |= 3;
+		break;
+	case 4800:
+		len |= 2;
+		break;
+	case 2400:
+	default:
+		len |= 1;
+		break;
+	};
+	writeb(len, data->ios_mem);
+
+}
+
+static const struct of_device_id lp8841_serial_dt_ids[] = {
+	{ .compatible = "icpdas,lp8841-uart", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, lp8841_serial_dt_ids);
+
+static int lp8841_serial_probe(struct platform_device *pdev)
+{
+	struct uart_8250_port uart = {};
+	struct lp8841_serial_data *data;
+	struct resource *mmres, *mires;
+	int ret;
+
+	mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	mires = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	if (!mmres)
+		return -ENODEV;
+
+	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->ios_mem = devm_ioremap_resource(&pdev->dev, mires);
+	if (IS_ERR(data->ios_mem))
+		return PTR_ERR(data->ios_mem);
+
+	uart.port.iotype = UPIO_MEM;
+	uart.port.mapbase = mmres->start;
+	uart.port.regshift = 1;
+	uart.port.irq = platform_get_irq(pdev, 0);
+	uart.port.flags = UPF_IOREMAP;
+	uart.port.dev = &pdev->dev;
+	uart.port.uartclk = 14745600;
+	uart.port.set_termios = lp8841_serial_set_termios;
+	uart.port.private_data = data;
+
+	ret = serial8250_register_8250_port(&uart);
+	if (ret < 0)
+		return ret;
+
+	data->line = ret;
+
+	platform_set_drvdata(pdev, data);
+
+	return 0;
+}
+
+static int lp8841_serial_remove(struct platform_device *pdev)
+{
+	struct lp8841_serial_data *data = platform_get_drvdata(pdev);
+
+	serial8250_unregister_port(data->line);
+
+	return 0;
+}
+
+static struct platform_driver lp8841_serial_driver = {
+	.probe          = lp8841_serial_probe,
+	.remove         = lp8841_serial_remove,
+
+	.driver		= {
+		.name	= "uart-lp8841",
+		.of_match_table = lp8841_serial_dt_ids,
+	},
+};
+
+module_platform_driver(lp8841_serial_driver);
+
+MODULE_AUTHOR("Sergei Ianovich");
+MODULE_DESCRIPTION("8250 serial port module for LP-8841");
+MODULE_LICENSE("GPL");
diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
index 3b5cf9c..68640c1 100644
--- a/drivers/tty/serial/8250/Kconfig
+++ b/drivers/tty/serial/8250/Kconfig
@@ -394,3 +394,17 @@ config SERIAL_8250_PXA
 	help
 	  If you have a machine based on an Intel XScale PXA2xx CPU you
 	  can enable its onboard serial ports by enabling this option.
+
+	  If you choose M here, the module name will be 8250_pxa.
+
+config SERIAL_8250_LP8841
+	tristate "Support 16550A ports on ICP DAS LP-8841"
+	depends on SERIAL_8250 && MACH_PXA27X_DT
+	select LP8841_IRQ
+	help
+	  In addition to serial ports on PXA270 SoC, LP-8841 has 1 dual
+	  RS232/RS485 port, 1 RS485 port and 1 RS232 port.
+
+	  Say N here, unless you plan to run this kernel on a LP-8841 system.
+
+	  If you choose M here, the module name will be 8250_lp8841.
diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile
index d1e2f2d..10b4bf0 100644
--- a/drivers/tty/serial/8250/Makefile
+++ b/drivers/tty/serial/8250/Makefile
@@ -18,6 +18,7 @@ obj-$(CONFIG_SERIAL_8250_ACCENT)	+= 8250_accent.o
 obj-$(CONFIG_SERIAL_8250_BOCA)		+= 8250_boca.o
 obj-$(CONFIG_SERIAL_8250_EXAR_ST16C554)	+= 8250_exar_st16c554.o
 obj-$(CONFIG_SERIAL_8250_HUB6)		+= 8250_hub6.o
+obj-$(CONFIG_SERIAL_8250_LP8X4X)	+= 8250_lp8x4x.o
 obj-$(CONFIG_SERIAL_8250_FSL)		+= 8250_fsl.o
 obj-$(CONFIG_SERIAL_8250_DW)		+= 8250_dw.o
 obj-$(CONFIG_SERIAL_8250_EM)		+= 8250_em.o
@@ -30,5 +31,6 @@ obj-$(CONFIG_SERIAL_8250_INGENIC)	+= 8250_ingenic.o
 obj-$(CONFIG_SERIAL_8250_MID)		+= 8250_mid.o
 obj-$(CONFIG_SERIAL_OF_PLATFORM)	+= 8250_of.o
 obj-$(CONFIG_SERIAL_8250_PXA)		+= 8250_pxa.o
+obj-$(CONFIG_SERIAL_8250_LP8841)	+= 8250_lp8841.o
 
 CFLAGS_8250_ingenic.o += -I$(srctree)/scripts/dtc/libfdt
-- 
2.7.0

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

* [PATCH v7] serial: support for 16550A serial ports on LP-8x4x
@ 2016-02-29 21:26                       ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2016-02-29 21:26 UTC (permalink / raw)
  To: linux-kernel
  Cc: Sergei Ianovich, Alan Cox, Andy Shevchenko, Arnd Bergmann,
	Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	Greg Kroah-Hartman, Jiri Slaby, Heikki Krogerus, Peter Hurley,
	Masahiro Yamada, Paul Burton, Mans Rullgard, Joachim Eastwood,
	Scott Wood, Paul Gortmaker, Peter Ujfalusi,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE

The patch adds support for 3 additional LP-8x4x built-in serial
ports.

The device can also host up to 8 extension cards with 4 serial ports
on each card for a total of 35 ports. However, I don't have
the hardware to test extension cards, so they are not supported, yet.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
---
CC: Alan Cox <gnomes@lxorguk.ukuu.org.uk>
CC: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
CC: Arnd Bergmann <arnd@arndb.de>

   v6..v7
   fix review comments by Andy Shevchenko
   not applying Acked-by as the 1st change is big
   * handle unsupported tty modes correctly as suggested by Alan Cox
   * remove extra check of platform_get_resource() result
   * propagate error code from devm_ioremap_resource()
   * drop uart.port.iobase for UPIO_MEM device

   v5..v6
   fix review comments by Arnd Bergmann
   * remove wildcards from compatible
   * update doc file
   * drop interrupt parent from doc file
   * replace uart w/ serial in device names in doc file

   fix review comments by Andy Shevchenko
   * exchange labels in switch block
   * replace iowrite8() with writeb()
   * compact comment to one line

   v4..v5
   * constify struct of_device_id
   * drop .owner from struct platform_driver
   * rewrite set_termios() baud rate hadnling as suggested by Alan Cox

   v3..v4
   * move DTS bindings to a different patch (8/21) as suggested by
     Heikki Krogerus

   v2..v3
   * no changes (except number 10/16 -> 12/21)

   v0..v2
   * register platform driver instead of platform device
   * use device tree
   * use devm helpers where possible

 .../bindings/serial/icpdas-lp8841-uart.txt         |  41 +++++
 drivers/tty/serial/8250/8250_lp8841.c              | 193 +++++++++++++++++++++
 drivers/tty/serial/8250/Kconfig                    |  14 ++
 drivers/tty/serial/8250/Makefile                   |   2 +
 4 files changed, 250 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/serial/icpdas-lp8841-uart.txt
 create mode 100644 drivers/tty/serial/8250/8250_lp8841.c

diff --git a/Documentation/devicetree/bindings/serial/icpdas-lp8841-uart.txt b/Documentation/devicetree/bindings/serial/icpdas-lp8841-uart.txt
new file mode 100644
index 0000000..d6acd22
--- /dev/null
+++ b/Documentation/devicetree/bindings/serial/icpdas-lp8841-uart.txt
@@ -0,0 +1,41 @@
+* UART ports on ICP DAS LP-8841
+
+LP-8441, LP-8141 and LP-8041 are fully compatible.
+
+ICP DAS LP-8841 contains three additional serial ports interfaced via
+Analog Devices ADM213EA chips in addition to 3 serial ports on PXA CPU.
+
+The chips themselves are standard, they would work with 8250_core if
+properly connected. However, they are not connected normally. Al least
+some of their config pins are wired to a different address region. So
+the driver is board-specific.
+
+Required properties:
+- compatible : should be "icpdas,uart-lp8841"
+
+- reg : should provide 16 byte man IO memory region and 1 byte region for
+	termios
+
+- interrupts : should provide interrupt
+
+Optional property:
+- interrupt-parent : should provide a link to interrupt controller either
+		     explicitly or implicitly from a parent node
+
+Examples (from pxa27x-lp8x4x.dts):
+
+		serial@9050 {
+			compatible = "icpdas,uart-lp8841";
+			reg = <0x9050 0x10
+			       0x9030 0x02>;
+			interrupts = <13>;
+			status = "okay";
+		};
+
+		serial@9060 {
+			compatible = "icpdas,uart-lp8841";
+			reg = <0x9060 0x10
+			       0x9032 0x02>;
+			interrupts = <14>;
+			status = "okay";
+		};
diff --git a/drivers/tty/serial/8250/8250_lp8841.c b/drivers/tty/serial/8250/8250_lp8841.c
new file mode 100644
index 0000000..e92c01c
--- /dev/null
+++ b/drivers/tty/serial/8250/8250_lp8841.c
@@ -0,0 +1,193 @@
+/*  linux/drivers/tty/serial/8250/8250_lp8841.c
+ *
+ *  Support for 16550A serial ports on ICP DAS LP-8841
+ *
+ *  Copyright (C) 2013 Sergei Ianovich <ynvich@gmail.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/module.h>
+#include <linux/serial_8250.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+struct lp8841_serial_data {
+	int			line;
+	void __iomem		*ios_mem;
+};
+
+static void lp8841_serial_set_termios(struct uart_port *port,
+		struct ktermios *termios, struct ktermios *old)
+{
+#ifdef BOTHER
+	unsigned int cbaud;
+#endif
+	unsigned int baud;
+	unsigned int len;
+	unsigned int old_csize = old ? old->c_cflag & CSIZE : CS8;
+	struct lp8841_serial_data *data = port->private_data;
+
+	/* We only support CS7 and CS8 */
+	while ((termios->c_cflag & CSIZE) != CS7 &&
+	       (termios->c_cflag & CSIZE) != CS8) {
+		termios->c_cflag &= ~CSIZE;
+		termios->c_cflag |= old_csize;
+		old_csize = CS8;
+	}
+
+	serial8250_do_set_termios(port, termios, old);
+
+	if ((termios->c_cflag & CSIZE) == CS7)
+		len = 9;
+	else
+		len = 10;
+
+	if (termios->c_cflag & CSTOPB)
+		len++;
+	if (termios->c_cflag & PARENB)
+		len++;
+	if (!(termios->c_cflag & PARODD))
+		len++;
+#ifdef CMSPAR
+	if (termios->c_cflag & CMSPAR)
+		len++;
+#endif
+
+	len -= 9;
+	len &= 3;
+	len <<= 3;
+
+	baud = tty_termios_baud_rate(termios);
+
+#ifdef BOTHER
+	/* We only support fixed rates */
+	cbaud = termios->c_cflag & CBAUD;
+
+	if (cbaud == BOTHER) {
+		termios->c_cflag &= ~BOTHER;
+
+		/* Don't rewrite B0 */
+		if (baud) {
+			tty_termios_encode_baud_rate(termios, baud, baud);
+			baud = tty_termios_baud_rate(termios);
+
+			/* Set sane default speed if we get 0 */
+			if (!baud) {
+				baud = 9600;
+				tty_termios_encode_baud_rate(termios,
+						baud, baud);
+			}
+		}
+	}
+#endif
+
+	/* We only support up to 115200 */
+	if (baud > 115200) {
+		baud = 115200;
+		tty_termios_encode_baud_rate(termios, baud, baud);
+	}
+
+	switch (baud) {
+	case 115200:
+		len |= 7;
+		break;
+	case 57600:
+		len |= 6;
+		break;
+	case 38400:
+		len |= 5;
+		break;
+	case 19200:
+		len |= 4;
+		break;
+	case 9600:
+		len |= 3;
+		break;
+	case 4800:
+		len |= 2;
+		break;
+	case 2400:
+	default:
+		len |= 1;
+		break;
+	};
+	writeb(len, data->ios_mem);
+
+}
+
+static const struct of_device_id lp8841_serial_dt_ids[] = {
+	{ .compatible = "icpdas,lp8841-uart", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, lp8841_serial_dt_ids);
+
+static int lp8841_serial_probe(struct platform_device *pdev)
+{
+	struct uart_8250_port uart = {};
+	struct lp8841_serial_data *data;
+	struct resource *mmres, *mires;
+	int ret;
+
+	mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	mires = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	if (!mmres)
+		return -ENODEV;
+
+	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->ios_mem = devm_ioremap_resource(&pdev->dev, mires);
+	if (IS_ERR(data->ios_mem))
+		return PTR_ERR(data->ios_mem);
+
+	uart.port.iotype = UPIO_MEM;
+	uart.port.mapbase = mmres->start;
+	uart.port.regshift = 1;
+	uart.port.irq = platform_get_irq(pdev, 0);
+	uart.port.flags = UPF_IOREMAP;
+	uart.port.dev = &pdev->dev;
+	uart.port.uartclk = 14745600;
+	uart.port.set_termios = lp8841_serial_set_termios;
+	uart.port.private_data = data;
+
+	ret = serial8250_register_8250_port(&uart);
+	if (ret < 0)
+		return ret;
+
+	data->line = ret;
+
+	platform_set_drvdata(pdev, data);
+
+	return 0;
+}
+
+static int lp8841_serial_remove(struct platform_device *pdev)
+{
+	struct lp8841_serial_data *data = platform_get_drvdata(pdev);
+
+	serial8250_unregister_port(data->line);
+
+	return 0;
+}
+
+static struct platform_driver lp8841_serial_driver = {
+	.probe          = lp8841_serial_probe,
+	.remove         = lp8841_serial_remove,
+
+	.driver		= {
+		.name	= "uart-lp8841",
+		.of_match_table = lp8841_serial_dt_ids,
+	},
+};
+
+module_platform_driver(lp8841_serial_driver);
+
+MODULE_AUTHOR("Sergei Ianovich");
+MODULE_DESCRIPTION("8250 serial port module for LP-8841");
+MODULE_LICENSE("GPL");
diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
index 3b5cf9c..68640c1 100644
--- a/drivers/tty/serial/8250/Kconfig
+++ b/drivers/tty/serial/8250/Kconfig
@@ -394,3 +394,17 @@ config SERIAL_8250_PXA
 	help
 	  If you have a machine based on an Intel XScale PXA2xx CPU you
 	  can enable its onboard serial ports by enabling this option.
+
+	  If you choose M here, the module name will be 8250_pxa.
+
+config SERIAL_8250_LP8841
+	tristate "Support 16550A ports on ICP DAS LP-8841"
+	depends on SERIAL_8250 && MACH_PXA27X_DT
+	select LP8841_IRQ
+	help
+	  In addition to serial ports on PXA270 SoC, LP-8841 has 1 dual
+	  RS232/RS485 port, 1 RS485 port and 1 RS232 port.
+
+	  Say N here, unless you plan to run this kernel on a LP-8841 system.
+
+	  If you choose M here, the module name will be 8250_lp8841.
diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile
index d1e2f2d..10b4bf0 100644
--- a/drivers/tty/serial/8250/Makefile
+++ b/drivers/tty/serial/8250/Makefile
@@ -18,6 +18,7 @@ obj-$(CONFIG_SERIAL_8250_ACCENT)	+= 8250_accent.o
 obj-$(CONFIG_SERIAL_8250_BOCA)		+= 8250_boca.o
 obj-$(CONFIG_SERIAL_8250_EXAR_ST16C554)	+= 8250_exar_st16c554.o
 obj-$(CONFIG_SERIAL_8250_HUB6)		+= 8250_hub6.o
+obj-$(CONFIG_SERIAL_8250_LP8X4X)	+= 8250_lp8x4x.o
 obj-$(CONFIG_SERIAL_8250_FSL)		+= 8250_fsl.o
 obj-$(CONFIG_SERIAL_8250_DW)		+= 8250_dw.o
 obj-$(CONFIG_SERIAL_8250_EM)		+= 8250_em.o
@@ -30,5 +31,6 @@ obj-$(CONFIG_SERIAL_8250_INGENIC)	+= 8250_ingenic.o
 obj-$(CONFIG_SERIAL_8250_MID)		+= 8250_mid.o
 obj-$(CONFIG_SERIAL_OF_PLATFORM)	+= 8250_of.o
 obj-$(CONFIG_SERIAL_8250_PXA)		+= 8250_pxa.o
+obj-$(CONFIG_SERIAL_8250_LP8841)	+= 8250_lp8841.o
 
 CFLAGS_8250_ingenic.o += -I$(srctree)/scripts/dtc/libfdt
-- 
2.7.0

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

* Re: [PATCH v7] serial: support for 16550A serial ports on LP-8x4x
@ 2016-03-01 11:06                         ` Andy Shevchenko
  0 siblings, 0 replies; 700+ messages in thread
From: Andy Shevchenko @ 2016-03-01 11:06 UTC (permalink / raw)
  To: Sergei Ianovich, linux-kernel
  Cc: Alan Cox, Arnd Bergmann, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Greg Kroah-Hartman, Jiri Slaby,
	Heikki Krogerus, Peter Hurley, Masahiro Yamada, Paul Burton,
	Mans Rullgard, Joachim Eastwood, Scott Wood, Paul Gortmaker,
	Peter Ujfalusi,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	open list:SERIAL DRIVERS

On Tue, 2016-03-01 at 00:26 +0300, Sergei Ianovich wrote:
> The patch adds support for 3 additional LP-8x4x built-in serial
> ports.
> 
> The device can also host up to 8 extension cards with 4 serial ports
> on each card for a total of 35 ports. However, I don't have
> the hardware to test extension cards, so they are not supported, yet.
> 
> Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
> Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>

Few more comments, mostly about style.

> +static void lp8841_serial_set_termios(struct uart_port *port,
> +		struct ktermios *termios, struct ktermios *old)
> +{
> +#ifdef BOTHER
> +	unsigned int cbaud;
> +#endif
> +	unsigned int baud;
> +	unsigned int len;

Since you are writing this to the register at the end maybe 
 - unsigned int -> u8 (write*b* — exactly one byte)
 - len -> value (it's not only about data length)

> +	unsigned int old_csize = old ? old->c_cflag & CSIZE : CS8;
> +	struct lp8841_serial_data *data = port->private_data;
> +
> +	/* We only support CS7 and CS8 */
> +	while ((termios->c_cflag & CSIZE) != CS7 &&
> +	       (termios->c_cflag & CSIZE) != CS8) {
> +		termios->c_cflag &= ~CSIZE;
> +		termios->c_cflag |= old_csize;
> +		old_csize = CS8;
> +	}
> +
> +	serial8250_do_set_termios(port, termios, old);
> +
> +	if ((termios->c_cflag & CSIZE) == CS7)
> +		len = 9;
> +	else
> +		len = 10;
> +
> +	if (termios->c_cflag & CSTOPB)
> +		len++;

> +	if (termios->c_cflag & PARENB)
> +		len++;
> +	if (!(termios->c_cflag & PARODD))
> +		len++;
> +#ifdef CMSPAR
> +	if (termios->c_cflag & CMSPAR)
> +		len++;
> +#endif

I don't know if someone likes it or not (up to you), but for me looks
better to have ternary operators here:

value += (termios->c_cflag & CSTOPB) ? 1 : 0;
value += (termios->c_cflag & PARENB) ? 1 : 0;
value += (termios->c_cflag & PARODD) ? 0 : 1;

#ifdef CMSPAR
value += (termios->c_cflag & CMSPAR) ? 1 : 0;
#endif

> +	len -= 9;

This one could be part of previous evaluation:
 value = (termios->c_cflag & CSIZE) == CS7 ? 0 : 1;

> +	len &= 3;
> +	len <<= 3;

Perhaps to define magic number (e.g. LP8841_DATA_LEN_SHIFT).

> +
> +	baud = tty_termios_baud_rate(termios);
> +
> +#ifdef BOTHER
> +	/* We only support fixed rates */
> +	cbaud = termios->c_cflag & CBAUD;
> +
> +	if (cbaud == BOTHER) {
> +		termios->c_cflag &= ~BOTHER;
> +
> +		/* Don't rewrite B0 */
> +		if (baud) {
> +			tty_termios_encode_baud_rate(termios, baud,
> baud);
> +			baud = tty_termios_baud_rate(termios);
> +
> +			/* Set sane default speed if we get 0 */
> +			if (!baud) {
> +				baud = 9600;

> +				tty_termios_encode_baud_rate(termios
> ,
> +						baud, baud);

I think you can call this unconditionally together with case > 115200.

> +			}
> +		}
> +	}
> +#endif
> +
> +	/* We only support up to 115200 */
> +	if (baud > 115200) {
> +		baud = 115200;
> +		tty_termios_encode_baud_rate(termios, baud, baud);
> +	}

Btw, can we use uart_get_baud_rate() here?


> +	writeb(len, data->ios_mem);
> +
> +}


> +static int lp8841_serial_probe(struct platform_device *pdev)
> +{
> +	struct uart_8250_port uart = {};

{0}

> +	struct lp8841_serial_data *data;
> +	struct resource *mmres, *mires;
> +	int ret;
> +
> +	mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);

> +	mires = platform_get_resource(pdev, IORESOURCE_MEM, 1);

Perhaps move it down to be closer to devm_ioremap_resource() call.

> +	if (!mmres)
> +		return -ENODEV;
> +
> +	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
> +	if (!data)
> +		return -ENOMEM;
> +

+	mires = platform_get_resource(pdev, IORESOURCE_MEM, 1);

> +	data->ios_mem = devm_ioremap_resource(&pdev->dev, mires);
> +	if (IS_ERR(data->ios_mem))
> +		return PTR_ERR(data->ios_mem);

-- 
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Intel Finland Oy

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

* Re: [PATCH v7] serial: support for 16550A serial ports on LP-8x4x
@ 2016-03-01 11:06                         ` Andy Shevchenko
  0 siblings, 0 replies; 700+ messages in thread
From: Andy Shevchenko @ 2016-03-01 11:06 UTC (permalink / raw)
  To: Sergei Ianovich, linux-kernel-u79uwXL29TY76Z2rM5mHXA
  Cc: Alan Cox, Arnd Bergmann, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Greg Kroah-Hartman, Jiri Slaby,
	Heikki Krogerus, Peter Hurley, Masahiro Yamada, Paul Burton,
	Mans Rullgard, Joachim Eastwood, Scott Wood, Paul Gortmaker,
	Peter Ujfalusi,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	open list:SERIAL DRIVERS

On Tue, 2016-03-01 at 00:26 +0300, Sergei Ianovich wrote:
> The patch adds support for 3 additional LP-8x4x built-in serial
> ports.
> 
> The device can also host up to 8 extension cards with 4 serial ports
> on each card for a total of 35 ports. However, I don't have
> the hardware to test extension cards, so they are not supported, yet.
> 
> Signed-off-by: Sergei Ianovich <ynvich-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> Reviewed-by: Heikki Krogerus <heikki.krogerus-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>

Few more comments, mostly about style.

> +static void lp8841_serial_set_termios(struct uart_port *port,
> +		struct ktermios *termios, struct ktermios *old)
> +{
> +#ifdef BOTHER
> +	unsigned int cbaud;
> +#endif
> +	unsigned int baud;
> +	unsigned int len;

Since you are writing this to the register at the end maybe 
 - unsigned int -> u8 (write*b* — exactly one byte)
 - len -> value (it's not only about data length)

> +	unsigned int old_csize = old ? old->c_cflag & CSIZE : CS8;
> +	struct lp8841_serial_data *data = port->private_data;
> +
> +	/* We only support CS7 and CS8 */
> +	while ((termios->c_cflag & CSIZE) != CS7 &&
> +	       (termios->c_cflag & CSIZE) != CS8) {
> +		termios->c_cflag &= ~CSIZE;
> +		termios->c_cflag |= old_csize;
> +		old_csize = CS8;
> +	}
> +
> +	serial8250_do_set_termios(port, termios, old);
> +
> +	if ((termios->c_cflag & CSIZE) == CS7)
> +		len = 9;
> +	else
> +		len = 10;
> +
> +	if (termios->c_cflag & CSTOPB)
> +		len++;

> +	if (termios->c_cflag & PARENB)
> +		len++;
> +	if (!(termios->c_cflag & PARODD))
> +		len++;
> +#ifdef CMSPAR
> +	if (termios->c_cflag & CMSPAR)
> +		len++;
> +#endif

I don't know if someone likes it or not (up to you), but for me looks
better to have ternary operators here:

value += (termios->c_cflag & CSTOPB) ? 1 : 0;
value += (termios->c_cflag & PARENB) ? 1 : 0;
value += (termios->c_cflag & PARODD) ? 0 : 1;

#ifdef CMSPAR
value += (termios->c_cflag & CMSPAR) ? 1 : 0;
#endif

> +	len -= 9;

This one could be part of previous evaluation:
 value = (termios->c_cflag & CSIZE) == CS7 ? 0 : 1;

> +	len &= 3;
> +	len <<= 3;

Perhaps to define magic number (e.g. LP8841_DATA_LEN_SHIFT).

> +
> +	baud = tty_termios_baud_rate(termios);
> +
> +#ifdef BOTHER
> +	/* We only support fixed rates */
> +	cbaud = termios->c_cflag & CBAUD;
> +
> +	if (cbaud == BOTHER) {
> +		termios->c_cflag &= ~BOTHER;
> +
> +		/* Don't rewrite B0 */
> +		if (baud) {
> +			tty_termios_encode_baud_rate(termios, baud,
> baud);
> +			baud = tty_termios_baud_rate(termios);
> +
> +			/* Set sane default speed if we get 0 */
> +			if (!baud) {
> +				baud = 9600;

> +				tty_termios_encode_baud_rate(termios
> ,
> +						baud, baud);

I think you can call this unconditionally together with case > 115200.

> +			}
> +		}
> +	}
> +#endif
> +
> +	/* We only support up to 115200 */
> +	if (baud > 115200) {
> +		baud = 115200;
> +		tty_termios_encode_baud_rate(termios, baud, baud);
> +	}

Btw, can we use uart_get_baud_rate() here?


> +	writeb(len, data->ios_mem);
> +
> +}


> +static int lp8841_serial_probe(struct platform_device *pdev)
> +{
> +	struct uart_8250_port uart = {};

{0}

> +	struct lp8841_serial_data *data;
> +	struct resource *mmres, *mires;
> +	int ret;
> +
> +	mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);

> +	mires = platform_get_resource(pdev, IORESOURCE_MEM, 1);

Perhaps move it down to be closer to devm_ioremap_resource() call.

> +	if (!mmres)
> +		return -ENODEV;
> +
> +	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
> +	if (!data)
> +		return -ENOMEM;
> +

+	mires = platform_get_resource(pdev, IORESOURCE_MEM, 1);

> +	data->ios_mem = devm_ioremap_resource(&pdev->dev, mires);
> +	if (IS_ERR(data->ios_mem))
> +		return PTR_ERR(data->ios_mem);

-- 
Andy Shevchenko <andriy.shevchenko-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
Intel Finland Oy

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH v7] serial: support for 16550A serial ports on LP-8x4x
@ 2016-03-01 16:25                           ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2016-03-01 16:25 UTC (permalink / raw)
  To: Andy Shevchenko, linux-kernel
  Cc: Alan Cox, Arnd Bergmann, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Greg Kroah-Hartman, Jiri Slaby,
	Heikki Krogerus, Peter Hurley, Masahiro Yamada, Paul Burton,
	Mans Rullgard, Joachim Eastwood, Scott Wood, Paul Gortmaker,
	Peter Ujfalusi,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	open list:SERIAL DRIVERS

On Tue, 2016-03-01 at 13:06 +0200, Andy Shevchenko wrote:
> On Tue, 2016-03-01 at 00:26 +0300, Sergei Ianovich wrote:
> > The patch adds support for 3 additional LP-8x4x built-in serial
> > ports.
> > 
> > The device can also host up to 8 extension cards with 4 serial
> > ports
> > on each card for a total of 35 ports. However, I don't have
> > the hardware to test extension cards, so they are not supported,
> > yet.
> > 
> > Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
> > Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
> 
> Few more comments, mostly about style.
> 
> > +static void lp8841_serial_set_termios(struct uart_port *port,
> > +		struct ktermios *termios, struct ktermios *old)
> > +{
> > +#ifdef BOTHER
> > +	unsigned int cbaud;
> > +#endif
> > +	unsigned int baud;
> > +	unsigned int len;
> 
> Since you are writing this to the register at the end maybe 
>  - unsigned int -> u8 (write*b* — exactly one byte)
>  - len -> value (it's not only about data length)
> 
> > +	unsigned int old_csize = old ? old->c_cflag & CSIZE : CS8;
> > +	struct lp8841_serial_data *data = port->private_data;
> > +
> > +	/* We only support CS7 and CS8 */
> > +	while ((termios->c_cflag & CSIZE) != CS7 &&
> > +	       (termios->c_cflag & CSIZE) != CS8) {
> > +		termios->c_cflag &= ~CSIZE;
> > +		termios->c_cflag |= old_csize;
> > +		old_csize = CS8;
> > +	}
> > +
> > +	serial8250_do_set_termios(port, termios, old);
> > +
> > +	if ((termios->c_cflag & CSIZE) == CS7)
> > +		len = 9;
> > +	else
> > +		len = 10;
> > +
> > +	if (termios->c_cflag & CSTOPB)
> > +		len++;
> 
> > +	if (termios->c_cflag & PARENB)
> > +		len++;
> > +	if (!(termios->c_cflag & PARODD))
> > +		len++;
> > +#ifdef CMSPAR
> > +	if (termios->c_cflag & CMSPAR)
> > +		len++;
> > +#endif
> 
> I don't know if someone likes it or not (up to you), but for me looks
> better to have ternary operators here:
> 
> value += (termios->c_cflag & CSTOPB) ? 1 : 0;
> value += (termios->c_cflag & PARENB) ? 1 : 0;
> value += (termios->c_cflag & PARODD) ? 0 : 1;
> 
> #ifdef CMSPAR
> value += (termios->c_cflag & CMSPAR) ? 1 : 0;
> #endif
> 
> > +	len -= 9;
> 
> This one could be part of previous evaluation:
>  value = (termios->c_cflag & CSIZE) == CS7 ? 0 : 1;

Great point.

> > +	len &= 3;
> > +	len <<= 3;
> 
> Perhaps to define magic number (e.g. LP8841_DATA_LEN_SHIFT).

OK

> > +
> > +	baud = tty_termios_baud_rate(termios);
> > +
> > +#ifdef BOTHER
> > +	/* We only support fixed rates */
> > +	cbaud = termios->c_cflag & CBAUD;
> > +
> > +	if (cbaud == BOTHER) {
> > +		termios->c_cflag &= ~BOTHER;
> > +
> > +		/* Don't rewrite B0 */
> > +		if (baud) {
> > +			tty_termios_encode_baud_rate(termios,
> > baud,
> > baud);
> > +			baud = tty_termios_baud_rate(termios);
> > +
> > +			/* Set sane default speed if we get 0 */
> > +			if (!baud) {
> > +				baud = 9600;
> 
> > +				tty_termios_encode_baud_rate(termi
> > os
> > ,
> > +						baud, baud);
> 
> I think you can call this unconditionally together with case >
> 115200.

The calls are orthogonal. This one deals with the case when BOTHER is
defined and set, and we have non-zero rate with BOTHER, but we have
zero rate after BOTHER is cleared. So we set 9600 as a sane default
speed.

> > +			}
> > +		}
> > +	}
> > +#endif
> > +
> > +	/* We only support up to 115200 */
> > +	if (baud > 115200) {
> > +		baud = 115200;
> > +		tty_termios_encode_baud_rate(termios, baud, baud);
> > +	}

This one deals with the case when the rate is over 115200. If the
previous case has been triggered, this one won't be.

> Btw, can we use uart_get_baud_rate() here?

uart_get_baud_rate() has already been called
in serial8250_do_set_termios(). uart_get_baud_rate()
calls tty_termios_encode_baud_rate(). uart_get_baud_rate() won't help
us if BOTHER is set. Once BOTHER is cleared, we don't need any special
processing of uart_get_baud_rate().

> > +static int lp8841_serial_probe(struct platform_device *pdev)
> > +{
> > +     struct uart_8250_port uart = {};
> 
> {0}

---
drivers/tty/serial/8250/8250_lp8841.c: In function 'lp8841_serial_probe':
drivers/tty/serial/8250/8250_lp8841.c:124:32: warning: excess elements in struct initializer
  struct uart_8250_port uart = {0};
                                ^
drivers/tty/serial/8250/8250_lp8841.c:124:32: note: (near initialization for 'uart.port.lock.<anonymous>.rlock.raw_lock')
---

Zero triggers a warning. I'll use memset().

> > +     struct lp8841_serial_data *data;
> > +     struct resource *mmres, *mires;
> > +     int ret;
> > +
> > +     mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> 
> > +     mires = platform_get_resource(pdev, IORESOURCE_MEM, 1);
> 
> Perhaps move it down to be closer to devm_ioremap_resource() call.

OK

Thanks for lightning fast reviews. I'll resubmit v8 if there is no
objections to the points above.

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

* Re: [PATCH v7] serial: support for 16550A serial ports on LP-8x4x
@ 2016-03-01 16:25                           ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2016-03-01 16:25 UTC (permalink / raw)
  To: Andy Shevchenko, linux-kernel-u79uwXL29TY76Z2rM5mHXA
  Cc: Alan Cox, Arnd Bergmann, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Greg Kroah-Hartman, Jiri Slaby,
	Heikki Krogerus, Peter Hurley, Masahiro Yamada, Paul Burton,
	Mans Rullgard, Joachim Eastwood, Scott Wood, Paul Gortmaker,
	Peter Ujfalusi,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	open list:SERIAL DRIVERS

On Tue, 2016-03-01 at 13:06 +0200, Andy Shevchenko wrote:
> On Tue, 2016-03-01 at 00:26 +0300, Sergei Ianovich wrote:
> > The patch adds support for 3 additional LP-8x4x built-in serial
> > ports.
> > 
> > The device can also host up to 8 extension cards with 4 serial
> > ports
> > on each card for a total of 35 ports. However, I don't have
> > the hardware to test extension cards, so they are not supported,
> > yet.
> > 
> > Signed-off-by: Sergei Ianovich <ynvich-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> > Reviewed-by: Heikki Krogerus <heikki.krogerus-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
> 
> Few more comments, mostly about style.
> 
> > +static void lp8841_serial_set_termios(struct uart_port *port,
> > +		struct ktermios *termios, struct ktermios *old)
> > +{
> > +#ifdef BOTHER
> > +	unsigned int cbaud;
> > +#endif
> > +	unsigned int baud;
> > +	unsigned int len;
> 
> Since you are writing this to the register at the end maybe 
>  - unsigned int -> u8 (write*b* — exactly one byte)
>  - len -> value (it's not only about data length)
> 
> > +	unsigned int old_csize = old ? old->c_cflag & CSIZE : CS8;
> > +	struct lp8841_serial_data *data = port->private_data;
> > +
> > +	/* We only support CS7 and CS8 */
> > +	while ((termios->c_cflag & CSIZE) != CS7 &&
> > +	       (termios->c_cflag & CSIZE) != CS8) {
> > +		termios->c_cflag &= ~CSIZE;
> > +		termios->c_cflag |= old_csize;
> > +		old_csize = CS8;
> > +	}
> > +
> > +	serial8250_do_set_termios(port, termios, old);
> > +
> > +	if ((termios->c_cflag & CSIZE) == CS7)
> > +		len = 9;
> > +	else
> > +		len = 10;
> > +
> > +	if (termios->c_cflag & CSTOPB)
> > +		len++;
> 
> > +	if (termios->c_cflag & PARENB)
> > +		len++;
> > +	if (!(termios->c_cflag & PARODD))
> > +		len++;
> > +#ifdef CMSPAR
> > +	if (termios->c_cflag & CMSPAR)
> > +		len++;
> > +#endif
> 
> I don't know if someone likes it or not (up to you), but for me looks
> better to have ternary operators here:
> 
> value += (termios->c_cflag & CSTOPB) ? 1 : 0;
> value += (termios->c_cflag & PARENB) ? 1 : 0;
> value += (termios->c_cflag & PARODD) ? 0 : 1;
> 
> #ifdef CMSPAR
> value += (termios->c_cflag & CMSPAR) ? 1 : 0;
> #endif
> 
> > +	len -= 9;
> 
> This one could be part of previous evaluation:
>  value = (termios->c_cflag & CSIZE) == CS7 ? 0 : 1;

Great point.

> > +	len &= 3;
> > +	len <<= 3;
> 
> Perhaps to define magic number (e.g. LP8841_DATA_LEN_SHIFT).

OK

> > +
> > +	baud = tty_termios_baud_rate(termios);
> > +
> > +#ifdef BOTHER
> > +	/* We only support fixed rates */
> > +	cbaud = termios->c_cflag & CBAUD;
> > +
> > +	if (cbaud == BOTHER) {
> > +		termios->c_cflag &= ~BOTHER;
> > +
> > +		/* Don't rewrite B0 */
> > +		if (baud) {
> > +			tty_termios_encode_baud_rate(termios,
> > baud,
> > baud);
> > +			baud = tty_termios_baud_rate(termios);
> > +
> > +			/* Set sane default speed if we get 0 */
> > +			if (!baud) {
> > +				baud = 9600;
> 
> > +				tty_termios_encode_baud_rate(termi
> > os
> > ,
> > +						baud, baud);
> 
> I think you can call this unconditionally together with case >
> 115200.

The calls are orthogonal. This one deals with the case when BOTHER is
defined and set, and we have non-zero rate with BOTHER, but we have
zero rate after BOTHER is cleared. So we set 9600 as a sane default
speed.

> > +			}
> > +		}
> > +	}
> > +#endif
> > +
> > +	/* We only support up to 115200 */
> > +	if (baud > 115200) {
> > +		baud = 115200;
> > +		tty_termios_encode_baud_rate(termios, baud, baud);
> > +	}

This one deals with the case when the rate is over 115200. If the
previous case has been triggered, this one won't be.

> Btw, can we use uart_get_baud_rate() here?

uart_get_baud_rate() has already been called
in serial8250_do_set_termios(). uart_get_baud_rate()
calls tty_termios_encode_baud_rate(). uart_get_baud_rate() won't help
us if BOTHER is set. Once BOTHER is cleared, we don't need any special
processing of uart_get_baud_rate().

> > +static int lp8841_serial_probe(struct platform_device *pdev)
> > +{
> > +     struct uart_8250_port uart = {};
> 
> {0}

---
drivers/tty/serial/8250/8250_lp8841.c: In function 'lp8841_serial_probe':
drivers/tty/serial/8250/8250_lp8841.c:124:32: warning: excess elements in struct initializer
  struct uart_8250_port uart = {0};
                                ^
drivers/tty/serial/8250/8250_lp8841.c:124:32: note: (near initialization for 'uart.port.lock.<anonymous>.rlock.raw_lock')
---

Zero triggers a warning. I'll use memset().

> > +     struct lp8841_serial_data *data;
> > +     struct resource *mmres, *mires;
> > +     int ret;
> > +
> > +     mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> 
> > +     mires = platform_get_resource(pdev, IORESOURCE_MEM, 1);
> 
> Perhaps move it down to be closer to devm_ioremap_resource() call.

OK

Thanks for lightning fast reviews. I'll resubmit v8 if there is no
objections to the points above.
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH v7] serial: support for 16550A serial ports on LP-8x4x
  2016-03-01 16:25                           ` Sergei Ianovich
@ 2016-03-01 16:46                             ` Andy Shevchenko
  -1 siblings, 0 replies; 700+ messages in thread
From: Andy Shevchenko @ 2016-03-01 16:46 UTC (permalink / raw)
  To: Sergei Ianovich, linux-kernel
  Cc: Alan Cox, Arnd Bergmann, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Greg Kroah-Hartman, Jiri Slaby,
	Heikki Krogerus, Peter Hurley, Masahiro Yamada, Paul Burton,
	Mans Rullgard, Joachim Eastwood, Scott Wood, Paul Gortmaker,
	Peter Ujfalusi,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	open list:SERIAL DRIVERS

On Tue, 2016-03-01 at 19:25 +0300, Sergei Ianovich wrote:
> On Tue, 2016-03-01 at 13:06 +0200, Andy Shevchenko wrote:
> > On Tue, 2016-03-01 at 00:26 +0300, Sergei Ianovich wrote:

> > > +	len &= 3;

Mask as well to be defined.

> > > +	len <<= 3;
> > 
> > Perhaps to define magic number (e.g. LP8841_DATA_LEN_SHIFT).
> 
> OK


> +	baud = tty_termios_baud_rate(termios);
> > > +
> > > +#ifdef BOTHER
> > > +	/* We only support fixed rates */

So, but if you support only fixed rates, why do you care about BOTHER
at all?

> > > 
> > I think you can call this unconditionally together with case >
> > 115200.
> 
> The calls are orthogonal. This one deals with the case when BOTHER is
> defined and set, and we have non-zero rate with BOTHER, but we have
> zero rate after BOTHER is cleared. So we set 9600 as a sane default
> speed.

> +
> > > +	/* We only support up to 115200 */
> > > +	if (baud > 115200) {
> > > +		baud = 115200;
> > > +		tty_termios_encode_baud_rate(termios, baud,
> > > baud);
> > > +	}
> 
> This one deals with the case when the rate is over 115200. If the
> previous case has been triggered, this one won't be.

Yeah, but I meant to unconditionally call it just once here every time.
 tty_termios_encode_baud_rate(termios, baud, baud);

> +static int lp8841_serial_probe(struct platform_device *pdev)
> > > +{
> > > +     struct uart_8250_port uart = {};
> > 
> > {0}
> 
> ---
> drivers/tty/serial/8250/8250_lp8841.c: In function
> 'lp8841_serial_probe':
> drivers/tty/serial/8250/8250_lp8841.c:124:32: warning: excess
> elements in struct initializer
>   struct uart_8250_port uart = {0};
>                                 ^
> drivers/tty/serial/8250/8250_lp8841.c:124:32: note: (near
> initialization for 'uart.port.lock.<anonymous>.rlock.raw_lock')

Do you have any warning verbosity enabled? I see a lot of stuff like
this in the code

$ git grep -n 'struct .* = {0};' | wc -l
338

$ git grep -n 'struct .* = { \?0 \?};' | wc -l
550

( '… = { 0 };' included)

> ---
> 
> Zero triggers a warning. I'll use memset().

Either will work.

> Thanks for lightning fast reviews. I'll resubmit v8 if there is no
> objections to the points above.

See above.

-- 
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Intel Finland Oy

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

* Re: [PATCH v7] serial: support for 16550A serial ports on LP-8x4x
@ 2016-03-01 16:46                             ` Andy Shevchenko
  0 siblings, 0 replies; 700+ messages in thread
From: Andy Shevchenko @ 2016-03-01 16:46 UTC (permalink / raw)
  To: Sergei Ianovich, linux-kernel
  Cc: Alan Cox, Arnd Bergmann, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Greg Kroah-Hartman, Jiri Slaby,
	Heikki Krogerus, Peter Hurley, Masahiro Yamada, Paul Burton,
	Mans Rullgard, Joachim Eastwood, Scott Wood, Paul Gortmaker,
	Peter Ujfalusi,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	open list:SERIAL DRIVERS

On Tue, 2016-03-01 at 19:25 +0300, Sergei Ianovich wrote:
> On Tue, 2016-03-01 at 13:06 +0200, Andy Shevchenko wrote:
> > On Tue, 2016-03-01 at 00:26 +0300, Sergei Ianovich wrote:

> > > +	len &= 3;

Mask as well to be defined.

> > > +	len <<= 3;
> > 
> > Perhaps to define magic number (e.g. LP8841_DATA_LEN_SHIFT).
> 
> OK


> +	baud = tty_termios_baud_rate(termios);
> > > +
> > > +#ifdef BOTHER
> > > +	/* We only support fixed rates */

So, but if you support only fixed rates, why do you care about BOTHER
at all?

> > > 
> > I think you can call this unconditionally together with case >
> > 115200.
> 
> The calls are orthogonal. This one deals with the case when BOTHER is
> defined and set, and we have non-zero rate with BOTHER, but we have
> zero rate after BOTHER is cleared. So we set 9600 as a sane default
> speed.

> +
> > > +	/* We only support up to 115200 */
> > > +	if (baud > 115200) {
> > > +		baud = 115200;
> > > +		tty_termios_encode_baud_rate(termios, baud,
> > > baud);
> > > +	}
> 
> This one deals with the case when the rate is over 115200. If the
> previous case has been triggered, this one won't be.

Yeah, but I meant to unconditionally call it just once here every time.
 tty_termios_encode_baud_rate(termios, baud, baud);

> +static int lp8841_serial_probe(struct platform_device *pdev)
> > > +{
> > > +     struct uart_8250_port uart = {};
> > 
> > {0}
> 
> ---
> drivers/tty/serial/8250/8250_lp8841.c: In function
> 'lp8841_serial_probe':
> drivers/tty/serial/8250/8250_lp8841.c:124:32: warning: excess
> elements in struct initializer
>   struct uart_8250_port uart = {0};
>                                 ^
> drivers/tty/serial/8250/8250_lp8841.c:124:32: note: (near
> initialization for 'uart.port.lock.<anonymous>.rlock.raw_lock')

Do you have any warning verbosity enabled? I see a lot of stuff like
this in the code

$ git grep -n 'struct .* = {0};' | wc -l
338

$ git grep -n 'struct .* = { \?0 \?};' | wc -l
550

( '… = { 0 };' included)

> ---
> 
> Zero triggers a warning. I'll use memset().

Either will work.

> Thanks for lightning fast reviews. I'll resubmit v8 if there is no
> objections to the points above.

See above.

-- 
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Intel Finland Oy

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

* Re: [PATCH v7] serial: support for 16550A serial ports on LP-8x4x
@ 2016-03-01 17:14                               ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2016-03-01 17:14 UTC (permalink / raw)
  To: Andy Shevchenko, linux-kernel
  Cc: Alan Cox, Arnd Bergmann, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Greg Kroah-Hartman, Jiri Slaby,
	Heikki Krogerus, Peter Hurley, Masahiro Yamada, Paul Burton,
	Mans Rullgard, Joachim Eastwood, Scott Wood, Paul Gortmaker,
	Peter Ujfalusi,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	open list:SERIAL DRIVERS

On Tue, 2016-03-01 at 18:46 +0200, Andy Shevchenko wrote:
> On Tue, 2016-03-01 at 19:25 +0300, Sergei Ianovich wrote:
> > On Tue, 2016-03-01 at 13:06 +0200, Andy Shevchenko wrote:
> > > On Tue, 2016-03-01 at 00:26 +0300, Sergei Ianovich wrote:
> 
> > > > +	len &= 3;
> 
> Mask as well to be defined.

Sure.

> So, but if you support only fixed rates, why do you care about BOTHER
> at all?

If BOTHER is defined, tty_termios_baud_rate()
and tty_termios_encode_baud_rate() allow non-standard baud rates. I
should clear it from c_cflag to indicate I don't support it.

> > > >  
> > > I think you can call this unconditionally together with case >
> > > 115200.
> > 
> > The calls are orthogonal. This one deals with the case when BOTHER
> > is
> > defined and set, and we have non-zero rate with BOTHER, but we have
> > zero rate after BOTHER is cleared. So we set 9600 as a sane default
> > speed.

> > 
> > This one deals with the case when the rate is over 115200. If the
> > previous case has been triggered, this one won't be.
> 
> Yeah, but I meant to unconditionally call it just once here every
> time.

I see. It saves a few lines.

> > ---
> > drivers/tty/serial/8250/8250_lp8841.c: In function
> > 'lp8841_serial_probe':
> > drivers/tty/serial/8250/8250_lp8841.c:124:32: warning: excess
> > elements in struct initializer
> >   struct uart_8250_port uart = {0};
> >                                 ^
> > drivers/tty/serial/8250/8250_lp8841.c:124:32: note: (near
> > initialization for 'uart.port.lock.<anonymous>.rlock.raw_lock')
> 
> Do you have any warning verbosity enabled? I see a lot of stuff like
> this in the code

Plain `make`.

The warning seems to be the result of initializing a spinlock with
zero. Spinlocks are intentionally obfuscated, but I didn't investigate
further.

> $ git grep -n 'struct .* = {0};' | wc -l
> 338
> 
> $ git grep -n 'struct .* = { \?0 \?};' | wc -l
> 550
> 
> ( '… = { 0 };' included)

The first structure member is most likely not a spinlock in those
cases.

> > ---
> > 
> > Zero triggers a warning. I'll use memset().
> 
> Either will work.

OK

The only remaining open point is BOTHER handling.

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

* Re: [PATCH v7] serial: support for 16550A serial ports on LP-8x4x
@ 2016-03-01 17:14                               ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2016-03-01 17:14 UTC (permalink / raw)
  To: Andy Shevchenko, linux-kernel-u79uwXL29TY76Z2rM5mHXA
  Cc: Alan Cox, Arnd Bergmann, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Greg Kroah-Hartman, Jiri Slaby,
	Heikki Krogerus, Peter Hurley, Masahiro Yamada, Paul Burton,
	Mans Rullgard, Joachim Eastwood, Scott Wood, Paul Gortmaker,
	Peter Ujfalusi,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	open list:SERIAL DRIVERS

On Tue, 2016-03-01 at 18:46 +0200, Andy Shevchenko wrote:
> On Tue, 2016-03-01 at 19:25 +0300, Sergei Ianovich wrote:
> > On Tue, 2016-03-01 at 13:06 +0200, Andy Shevchenko wrote:
> > > On Tue, 2016-03-01 at 00:26 +0300, Sergei Ianovich wrote:
> 
> > > > +	len &= 3;
> 
> Mask as well to be defined.

Sure.

> So, but if you support only fixed rates, why do you care about BOTHER
> at all?

If BOTHER is defined, tty_termios_baud_rate()
and tty_termios_encode_baud_rate() allow non-standard baud rates. I
should clear it from c_cflag to indicate I don't support it.

> > > >  
> > > I think you can call this unconditionally together with case >
> > > 115200.
> > 
> > The calls are orthogonal. This one deals with the case when BOTHER
> > is
> > defined and set, and we have non-zero rate with BOTHER, but we have
> > zero rate after BOTHER is cleared. So we set 9600 as a sane default
> > speed.

> > 
> > This one deals with the case when the rate is over 115200. If the
> > previous case has been triggered, this one won't be.
> 
> Yeah, but I meant to unconditionally call it just once here every
> time.

I see. It saves a few lines.

> > ---
> > drivers/tty/serial/8250/8250_lp8841.c: In function
> > 'lp8841_serial_probe':
> > drivers/tty/serial/8250/8250_lp8841.c:124:32: warning: excess
> > elements in struct initializer
> >   struct uart_8250_port uart = {0};
> >                                 ^
> > drivers/tty/serial/8250/8250_lp8841.c:124:32: note: (near
> > initialization for 'uart.port.lock.<anonymous>.rlock.raw_lock')
> 
> Do you have any warning verbosity enabled? I see a lot of stuff like
> this in the code

Plain `make`.

The warning seems to be the result of initializing a spinlock with
zero. Spinlocks are intentionally obfuscated, but I didn't investigate
further.

> $ git grep -n 'struct .* = {0};' | wc -l
> 338
> 
> $ git grep -n 'struct .* = { \?0 \?};' | wc -l
> 550
> 
> ( '… = { 0 };' included)

The first structure member is most likely not a spinlock in those
cases.

> > ---
> > 
> > Zero triggers a warning. I'll use memset().
> 
> Either will work.

OK

The only remaining open point is BOTHER handling.
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH v7] serial: support for 16550A serial ports on LP-8x4x
@ 2016-03-01 17:48                                 ` Andy Shevchenko
  0 siblings, 0 replies; 700+ messages in thread
From: Andy Shevchenko @ 2016-03-01 17:48 UTC (permalink / raw)
  To: Sergei Ianovich, linux-kernel
  Cc: Alan Cox, Arnd Bergmann, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Greg Kroah-Hartman, Jiri Slaby,
	Heikki Krogerus, Peter Hurley, Masahiro Yamada, Paul Burton,
	Mans Rullgard, Joachim Eastwood, Scott Wood, Paul Gortmaker,
	Peter Ujfalusi,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	open list:SERIAL DRIVERS

On Tue, 2016-03-01 at 20:14 +0300, Sergei Ianovich wrote:
> On Tue, 2016-03-01 at 18:46 +0200, Andy Shevchenko wrote:
> > On Tue, 2016-03-01 at 19:25 +0300, Sergei Ianovich wrote:
> > > On Tue, 2016-03-01 at 13:06 +0200, Andy Shevchenko wrote:
> > > > On Tue, 2016-03-01 at 00:26 +0300, Sergei Ianovich wrote:

> > So, but if you support only fixed rates, why do you care about
> > BOTHER
> > at all?
> 
> If BOTHER is defined, tty_termios_baud_rate()
> and tty_termios_encode_baud_rate() allow non-standard baud rates. I
> should clear it from c_cflag to indicate I don't support it.
> 
> > > > >  
> > > > I think you can call this unconditionally together with case >
> > > > 115200.
> > > 
> > > The calls are orthogonal. This one deals with the case when
> > > BOTHER
> > > is
> > > defined and set, and we have non-zero rate with BOTHER, but we
> > > have
> > > zero rate after BOTHER is cleared. So we set 9600 as a sane
> > > default
> > > speed.

Maybe you just set a baud rate nearest to the one from the table in
case of BOTHER?

In that case perhaps you have to supply +-1 to the range. That's why I
asked about uart_get_baud_rate(). 

Maybe this flow will work for you

if (BOTHER)
 clear BOTHER
 call uart_get_baud_rate()

?

> The warning seems to be the result of initializing a spinlock with
> zero. Spinlocks are intentionally obfuscated, but I didn't
> investigate
> further.
> 
> > $ git grep -n 'struct .* = {0};' | wc -l
> > 338
> > 
> > $ git grep -n 'struct .* = { \?0 \?};' | wc -l
> > 550
> > 
> > ( '… = { 0 };' included)
> 
> The first structure member is most likely not a spinlock in those
> cases.

Hmm... Interesting. On one hand the poison is reasonable, on the other
we often do a memset() or {0} on structures, i.o.w. assign 0 as initial
value until spinlock_init().

Arnd, what do you think about this (and similar) case(s)?

-- 
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Intel Finland Oy

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

* Re: [PATCH v7] serial: support for 16550A serial ports on LP-8x4x
@ 2016-03-01 17:48                                 ` Andy Shevchenko
  0 siblings, 0 replies; 700+ messages in thread
From: Andy Shevchenko @ 2016-03-01 17:48 UTC (permalink / raw)
  To: Sergei Ianovich, linux-kernel-u79uwXL29TY76Z2rM5mHXA
  Cc: Alan Cox, Arnd Bergmann, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Greg Kroah-Hartman, Jiri Slaby,
	Heikki Krogerus, Peter Hurley, Masahiro Yamada, Paul Burton,
	Mans Rullgard, Joachim Eastwood, Scott Wood, Paul Gortmaker,
	Peter Ujfalusi,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	open list:SERIAL DRIVERS

On Tue, 2016-03-01 at 20:14 +0300, Sergei Ianovich wrote:
> On Tue, 2016-03-01 at 18:46 +0200, Andy Shevchenko wrote:
> > On Tue, 2016-03-01 at 19:25 +0300, Sergei Ianovich wrote:
> > > On Tue, 2016-03-01 at 13:06 +0200, Andy Shevchenko wrote:
> > > > On Tue, 2016-03-01 at 00:26 +0300, Sergei Ianovich wrote:

> > So, but if you support only fixed rates, why do you care about
> > BOTHER
> > at all?
> 
> If BOTHER is defined, tty_termios_baud_rate()
> and tty_termios_encode_baud_rate() allow non-standard baud rates. I
> should clear it from c_cflag to indicate I don't support it.
> 
> > > > >  
> > > > I think you can call this unconditionally together with case >
> > > > 115200.
> > > 
> > > The calls are orthogonal. This one deals with the case when
> > > BOTHER
> > > is
> > > defined and set, and we have non-zero rate with BOTHER, but we
> > > have
> > > zero rate after BOTHER is cleared. So we set 9600 as a sane
> > > default
> > > speed.

Maybe you just set a baud rate nearest to the one from the table in
case of BOTHER?

In that case perhaps you have to supply +-1 to the range. That's why I
asked about uart_get_baud_rate(). 

Maybe this flow will work for you

if (BOTHER)
 clear BOTHER
 call uart_get_baud_rate()

?

> The warning seems to be the result of initializing a spinlock with
> zero. Spinlocks are intentionally obfuscated, but I didn't
> investigate
> further.
> 
> > $ git grep -n 'struct .* = {0};' | wc -l
> > 338
> > 
> > $ git grep -n 'struct .* = { \?0 \?};' | wc -l
> > 550
> > 
> > ( '… = { 0 };' included)
> 
> The first structure member is most likely not a spinlock in those
> cases.

Hmm... Interesting. On one hand the poison is reasonable, on the other
we often do a memset() or {0} on structures, i.o.w. assign 0 as initial
value until spinlock_init().

Arnd, what do you think about this (and similar) case(s)?

-- 
Andy Shevchenko <andriy.shevchenko-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
Intel Finland Oy

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH v7] serial: support for 16550A serial ports on LP-8x4x
  2016-03-01 17:48                                 ` Andy Shevchenko
@ 2016-03-01 18:43                                   ` One Thousand Gnomes
  -1 siblings, 0 replies; 700+ messages in thread
From: One Thousand Gnomes @ 2016-03-01 18:43 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Sergei Ianovich, linux-kernel, Arnd Bergmann, Rob Herring,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	Greg Kroah-Hartman, Jiri Slaby, Heikki Krogerus, Peter Hurley,
	Masahiro Yamada, Paul Burton, Mans Rullgard, Joachim Eastwood,
	Scott Wood, Paul Gortmaker, Peter Ujfalusi,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	open list:SERIAL DRIVERS

> Maybe you just set a baud rate nearest to the one from the table in
> case of BOTHER?

This is broken. BOTHER can be set with a perfectly valid baud rate that
could equally be represented by B9600 say.

If you are stuck with limited ranges then

	switch(baud) {
	case 9600:
	case 4800:

etc

and don't worry about BOTHER, it's entirely transparent to you. The core
kernel code will provide you with a baud rate number, the re-encoder will
always do the right thing.

A driver should never care about BOTHER or any of the baud bits in the
termios structure directly.

Alan

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

* Re: [PATCH v7] serial: support for 16550A serial ports on LP-8x4x
@ 2016-03-01 18:43                                   ` One Thousand Gnomes
  0 siblings, 0 replies; 700+ messages in thread
From: One Thousand Gnomes @ 2016-03-01 18:43 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Sergei Ianovich, linux-kernel, Arnd Bergmann, Rob Herring,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	Greg Kroah-Hartman, Jiri Slaby, Heikki Krogerus, Peter Hurley,
	Masahiro Yamada, Paul Burton, Mans Rullgard, Joachim Eastwood,
	Scott Wood, Paul Gortmaker, Peter Ujfalusi,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	open list:SERIAL DRIVERS

> Maybe you just set a baud rate nearest to the one from the table in
> case of BOTHER?

This is broken. BOTHER can be set with a perfectly valid baud rate that
could equally be represented by B9600 say.

If you are stuck with limited ranges then

	switch(baud) {
	case 9600:
	case 4800:

etc

and don't worry about BOTHER, it's entirely transparent to you. The core
kernel code will provide you with a baud rate number, the re-encoder will
always do the right thing.

A driver should never care about BOTHER or any of the baud bits in the
termios structure directly.

Alan

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

* Re: [PATCH v7] serial: support for 16550A serial ports on LP-8x4x
@ 2016-03-01 19:28                                   ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2016-03-01 19:28 UTC (permalink / raw)
  To: Andy Shevchenko, linux-kernel
  Cc: Alan Cox, Arnd Bergmann, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Greg Kroah-Hartman, Jiri Slaby,
	Heikki Krogerus, Peter Hurley, Masahiro Yamada, Paul Burton,
	Mans Rullgard, Joachim Eastwood, Scott Wood, Paul Gortmaker,
	Peter Ujfalusi,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	open list:SERIAL DRIVERS

On Tue, 2016-03-01 at 19:48 +0200, Andy Shevchenko wrote:
> On Tue, 2016-03-01 at 20:14 +0300, Sergei Ianovich wrote:
> > On Tue, 2016-03-01 at 18:46 +0200, Andy Shevchenko wrote:
> > > On Tue, 2016-03-01 at 19:25 +0300, Sergei Ianovich wrote:
> > > > On Tue, 2016-03-01 at 13:06 +0200, Andy Shevchenko wrote:
> > > > > On Tue, 2016-03-01 at 00:26 +0300, Sergei Ianovich wrote:
> 
> > > So, but if you support only fixed rates, why do you care about
> > > BOTHER
> > > at all?
> > 
> > If BOTHER is defined, tty_termios_baud_rate()
> > and tty_termios_encode_baud_rate() allow non-standard baud rates. I
> > should clear it from c_cflag to indicate I don't support it.
> > 
> > > > > >  
> > > > > I think you can call this unconditionally together with case
> > > > > >
> > > > > 115200.
> > > > 
> > > > The calls are orthogonal. This one deals with the case when
> > > > BOTHER
> > > > is
> > > > defined and set, and we have non-zero rate with BOTHER, but we
> > > > have
> > > > zero rate after BOTHER is cleared. So we set 9600 as a sane
> > > > default
> > > > speed.
> 
> Maybe you just set a baud rate nearest to the one from the table in
> case of BOTHER?
> 
> In that case perhaps you have to supply +-1 to the range. That's why
> I
> asked about uart_get_baud_rate(). 
> 
> Maybe this flow will work for you
> 
> if (BOTHER)
>  clear BOTHER
>  call uart_get_baud_rate()
> 
> ?

It works well for standard rates, let it be so. If there ever is a
problem, we can fix it.

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

* Re: [PATCH v7] serial: support for 16550A serial ports on LP-8x4x
@ 2016-03-01 19:28                                   ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2016-03-01 19:28 UTC (permalink / raw)
  To: Andy Shevchenko, linux-kernel-u79uwXL29TY76Z2rM5mHXA
  Cc: Alan Cox, Arnd Bergmann, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Greg Kroah-Hartman, Jiri Slaby,
	Heikki Krogerus, Peter Hurley, Masahiro Yamada, Paul Burton,
	Mans Rullgard, Joachim Eastwood, Scott Wood, Paul Gortmaker,
	Peter Ujfalusi,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	open list:SERIAL DRIVERS

On Tue, 2016-03-01 at 19:48 +0200, Andy Shevchenko wrote:
> On Tue, 2016-03-01 at 20:14 +0300, Sergei Ianovich wrote:
> > On Tue, 2016-03-01 at 18:46 +0200, Andy Shevchenko wrote:
> > > On Tue, 2016-03-01 at 19:25 +0300, Sergei Ianovich wrote:
> > > > On Tue, 2016-03-01 at 13:06 +0200, Andy Shevchenko wrote:
> > > > > On Tue, 2016-03-01 at 00:26 +0300, Sergei Ianovich wrote:
> 
> > > So, but if you support only fixed rates, why do you care about
> > > BOTHER
> > > at all?
> > 
> > If BOTHER is defined, tty_termios_baud_rate()
> > and tty_termios_encode_baud_rate() allow non-standard baud rates. I
> > should clear it from c_cflag to indicate I don't support it.
> > 
> > > > > >  
> > > > > I think you can call this unconditionally together with case
> > > > > >
> > > > > 115200.
> > > > 
> > > > The calls are orthogonal. This one deals with the case when
> > > > BOTHER
> > > > is
> > > > defined and set, and we have non-zero rate with BOTHER, but we
> > > > have
> > > > zero rate after BOTHER is cleared. So we set 9600 as a sane
> > > > default
> > > > speed.
> 
> Maybe you just set a baud rate nearest to the one from the table in
> case of BOTHER?
> 
> In that case perhaps you have to supply +-1 to the range. That's why
> I
> asked about uart_get_baud_rate(). 
> 
> Maybe this flow will work for you
> 
> if (BOTHER)
>  clear BOTHER
>  call uart_get_baud_rate()
> 
> ?

It works well for standard rates, let it be so. If there ever is a
problem, we can fix it.
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH v7] serial: support for 16550A serial ports on LP-8x4x
@ 2016-03-01 19:53                                     ` One Thousand Gnomes
  0 siblings, 0 replies; 700+ messages in thread
From: One Thousand Gnomes @ 2016-03-01 19:53 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: Andy Shevchenko, linux-kernel, Arnd Bergmann, Rob Herring,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	Greg Kroah-Hartman, Jiri Slaby, Heikki Krogerus, Peter Hurley,
	Masahiro Yamada, Paul Burton, Mans Rullgard, Joachim Eastwood,
	Scott Wood, Paul Gortmaker, Peter Ujfalusi,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	open list:SERIAL DRIVERS

> > Maybe this flow will work for you
> > 
> > if (BOTHER)
> >  clear BOTHER
> >  call uart_get_baud_rate()
> > 
> > ?  
> 
> It works well for standard rates, let it be so. If there ever is a
> problem, we can fix it.

I'm NAKking the v7 PATCH because we spent ages getting all the drivers to
use tty_termios_get_baud_rate() cleanly.

Get rid of everything in the ifdef BOTHER
Remove the if baud > 115200 stuff

For the default: entry in the case add

             tty_termios_encode_baud_rate(termios, 2400, 2400);

and all will be good. Anything not a standard rate will get 2400 baud and
reported back to the user properly as that rate.

You could do matches for "within 10%" but really I don't think it matters
and other drivers don't bother either when they have such fixed clocks.

Alan

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

* Re: [PATCH v7] serial: support for 16550A serial ports on LP-8x4x
@ 2016-03-01 19:53                                     ` One Thousand Gnomes
  0 siblings, 0 replies; 700+ messages in thread
From: One Thousand Gnomes @ 2016-03-01 19:53 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: Andy Shevchenko, linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	Arnd Bergmann, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Greg Kroah-Hartman, Jiri Slaby,
	Heikki Krogerus, Peter Hurley, Masahiro Yamada, Paul Burton,
	Mans Rullgard, Joachim Eastwood, Scott Wood, Paul Gortmaker,
	Peter Ujfalusi,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS

> > Maybe this flow will work for you
> > 
> > if (BOTHER)
> >  clear BOTHER
> >  call uart_get_baud_rate()
> > 
> > ?  
> 
> It works well for standard rates, let it be so. If there ever is a
> problem, we can fix it.

I'm NAKking the v7 PATCH because we spent ages getting all the drivers to
use tty_termios_get_baud_rate() cleanly.

Get rid of everything in the ifdef BOTHER
Remove the if baud > 115200 stuff

For the default: entry in the case add

             tty_termios_encode_baud_rate(termios, 2400, 2400);

and all will be good. Anything not a standard rate will get 2400 baud and
reported back to the user properly as that rate.

You could do matches for "within 10%" but really I don't think it matters
and other drivers don't bother either when they have such fixed clocks.

Alan
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH v8] serial: support for 16550A serial ports on LP-8x4x
  2016-02-29 21:26                       ` Sergei Ianovich
@ 2016-03-01 19:54                         ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2016-03-01 19:54 UTC (permalink / raw)
  To: linux-kernel
  Cc: Sergei Ianovich, Alan Cox, Andy Shevchenko, Arnd Bergmann,
	Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	Greg Kroah-Hartman, Jiri Slaby, Heikki Krogerus, Peter Hurley,
	Masahiro Yamada, Paul Gortmaker, Paul Burton, Joachim Eastwood,
	Mans Rullgard, Scott Wood, Matthias Brugger, Peter Ujfalusi,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	open list:SERIAL DRIVERS

The patch adds support for 3 additional LP-8x4x built-in serial
ports.

The device can also host up to 8 extension cards with 4 serial ports
on each card for a total of 35 ports. However, I don't have
the hardware to test extension cards, so they are not supported, yet.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
---
CC: Alan Cox <gnomes@lxorguk.ukuu.org.uk>
CC: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
CC: Arnd Bergmann <arnd@arndb.de>

   v7..v8
   * call serial8250_do_set_termios() after speed check, not before.
     This way clock divisor is properly inited for the new baud rate,
     if any
   fix review comments by Andy Shevchenko
   * change board variable name and type
   * use ternary operators
   * use #defines instead of magic numbers
   * simplify speed check and use uart_get_baud_rate()
   * zero-init uart structure
   * re-organized probing calls

   v6..v7
   fix review comments by Andy Shevchenko
   not applying Acked-by as the 1st change is big
   * handle unsupported tty modes correctly
   * remove extra check of platform_get_resource() result
   * propagate error code from devm_ioremap_resource()
   * drop uart.port.iobase for UPIO_MEM device

   v5..v6
   fix review comments by Arnd Bergmann
   * remove wildcards from compatible
   * update doc file
   * drop interrupt parent from doc file
   * replace uart w/ serial in device names in doc file

   fix review comments by Andy Shevchenko
   * exchange labels in switch block
   * replace iowrite8() with writeb()
   * compact comment to one line

   v4..v5
   * constify struct of_device_id
   * drop .owner from struct platform_driver
   * rewrite set_termios() baud rate hadnling as suggested by Alan Cox

   v3..v4
   * move DTS bindings to a different patch (8/21) as suggested by
     Heikki Krogerus

   v2..v3
   * no changes (except number 10/16 -> 12/21)

   v0..v2
   * register platform driver instead of platform device
   * use device tree
   * use devm helpers where possible

 .../bindings/serial/icpdas-lp8841-uart.txt         |  41 +++++
 drivers/tty/serial/8250/8250_lp8841.c              | 173 +++++++++++++++++++++
 drivers/tty/serial/8250/Kconfig                    |  14 ++
 drivers/tty/serial/8250/Makefile                   |   2 +
 4 files changed, 230 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/serial/icpdas-lp8841-uart.txt
 create mode 100644 drivers/tty/serial/8250/8250_lp8841.c

diff --git a/Documentation/devicetree/bindings/serial/icpdas-lp8841-uart.txt b/Documentation/devicetree/bindings/serial/icpdas-lp8841-uart.txt
new file mode 100644
index 0000000..d6acd22
--- /dev/null
+++ b/Documentation/devicetree/bindings/serial/icpdas-lp8841-uart.txt
@@ -0,0 +1,41 @@
+* UART ports on ICP DAS LP-8841
+
+LP-8441, LP-8141 and LP-8041 are fully compatible.
+
+ICP DAS LP-8841 contains three additional serial ports interfaced via
+Analog Devices ADM213EA chips in addition to 3 serial ports on PXA CPU.
+
+The chips themselves are standard, they would work with 8250_core if
+properly connected. However, they are not connected normally. Al least
+some of their config pins are wired to a different address region. So
+the driver is board-specific.
+
+Required properties:
+- compatible : should be "icpdas,uart-lp8841"
+
+- reg : should provide 16 byte man IO memory region and 1 byte region for
+	termios
+
+- interrupts : should provide interrupt
+
+Optional property:
+- interrupt-parent : should provide a link to interrupt controller either
+		     explicitly or implicitly from a parent node
+
+Examples (from pxa27x-lp8x4x.dts):
+
+		serial@9050 {
+			compatible = "icpdas,uart-lp8841";
+			reg = <0x9050 0x10
+			       0x9030 0x02>;
+			interrupts = <13>;
+			status = "okay";
+		};
+
+		serial@9060 {
+			compatible = "icpdas,uart-lp8841";
+			reg = <0x9060 0x10
+			       0x9032 0x02>;
+			interrupts = <14>;
+			status = "okay";
+		};
diff --git a/drivers/tty/serial/8250/8250_lp8841.c b/drivers/tty/serial/8250/8250_lp8841.c
new file mode 100644
index 0000000..d80e218
--- /dev/null
+++ b/drivers/tty/serial/8250/8250_lp8841.c
@@ -0,0 +1,173 @@
+/*  linux/drivers/tty/serial/8250/8250_lp8841.c
+ *
+ *  Support for 16550A serial ports on ICP DAS LP-8841
+ *
+ *  Copyright (C) 2013 Sergei Ianovich <ynvich@gmail.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/module.h>
+#include <linux/serial_8250.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+struct lp8841_serial_data {
+	int			line;
+	void __iomem		*ios_mem;
+};
+
+#define LP8841_DATA_LEN_MASK		0x3
+#define LP8841_DATA_LEN_SHIFT_OFFSET	3
+
+static void lp8841_serial_set_termios(struct uart_port *port,
+		struct ktermios *termios, struct ktermios *old)
+{
+#ifdef BOTHER
+	unsigned int cbaud;
+#endif
+	unsigned int baud;
+	u8 value;
+	unsigned int old_csize = old ? old->c_cflag & CSIZE : CS8;
+	struct lp8841_serial_data *data = port->private_data;
+
+	/* We only support CS7 and CS8 */
+	while ((termios->c_cflag & CSIZE) != CS7 &&
+	       (termios->c_cflag & CSIZE) != CS8) {
+		termios->c_cflag &= ~CSIZE;
+		termios->c_cflag |= old_csize;
+		old_csize = CS8;
+	}
+
+	value =  (termios->c_cflag & CSIZE) == CS7 ? 0 : 1;
+	value += (termios->c_cflag & CSTOPB) ? 1 : 0;
+	value += (termios->c_cflag & PARENB) ? 1 : 0;
+	value += (termios->c_cflag & PARODD) ? 0 : 1;
+#ifdef CMSPAR
+	value += (termios->c_cflag & CMSPAR) ? 1 : 0;
+#endif
+
+	value &=  LP8841_DATA_LEN_MASK;
+	value <<= LP8841_DATA_LEN_SHIFT_OFFSET;
+
+	baud = tty_termios_baud_rate(termios);
+
+#ifdef BOTHER
+	/* We only support fixed rates */
+	cbaud = termios->c_cflag & CBAUD;
+
+	if (cbaud == BOTHER)
+		termios->c_cflag &= ~BOTHER;
+#endif
+
+	/* We only support up to 115200 */
+	if (baud > 115200)
+		baud = 115200;
+
+	baud = uart_get_baud_rate(port, termios, old, baud, baud);
+
+	serial8250_do_set_termios(port, termios, old);
+
+	switch (baud) {
+	case 115200:
+		value |= 7;
+		break;
+	case 57600:
+		value |= 6;
+		break;
+	case 38400:
+		value |= 5;
+		break;
+	case 19200:
+		value |= 4;
+		break;
+	case 9600:
+		value |= 3;
+		break;
+	case 4800:
+		value |= 2;
+		break;
+	case 2400:
+	default:
+		value |= 1;
+		break;
+	};
+	writeb(value, data->ios_mem);
+}
+
+static const struct of_device_id lp8841_serial_dt_ids[] = {
+	{ .compatible = "icpdas,lp8841-uart", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, lp8841_serial_dt_ids);
+
+static int lp8841_serial_probe(struct platform_device *pdev)
+{
+	struct uart_8250_port uart = {};
+	struct lp8841_serial_data *data;
+	struct resource *mmres, *mires;
+	int ret;
+
+	memset(&uart, 0, sizeof(uart));
+
+	mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!mmres)
+		return -ENODEV;
+
+	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	mires = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	data->ios_mem = devm_ioremap_resource(&pdev->dev, mires);
+	if (IS_ERR(data->ios_mem))
+		return PTR_ERR(data->ios_mem);
+
+	uart.port.iotype = UPIO_MEM;
+	uart.port.mapbase = mmres->start;
+	uart.port.regshift = 1;
+	uart.port.irq = platform_get_irq(pdev, 0);
+	uart.port.flags = UPF_IOREMAP;
+	uart.port.dev = &pdev->dev;
+	uart.port.uartclk = 14745600;
+	uart.port.set_termios = lp8841_serial_set_termios;
+	uart.port.private_data = data;
+
+	ret = serial8250_register_8250_port(&uart);
+	if (ret < 0)
+		return ret;
+
+	data->line = ret;
+
+	platform_set_drvdata(pdev, data);
+
+	return 0;
+}
+
+static int lp8841_serial_remove(struct platform_device *pdev)
+{
+	struct lp8841_serial_data *data = platform_get_drvdata(pdev);
+
+	serial8250_unregister_port(data->line);
+
+	return 0;
+}
+
+static struct platform_driver lp8841_serial_driver = {
+	.probe          = lp8841_serial_probe,
+	.remove         = lp8841_serial_remove,
+	.driver		= {
+		.name	= "uart-lp8841",
+		.of_match_table = lp8841_serial_dt_ids,
+	},
+};
+
+module_platform_driver(lp8841_serial_driver);
+
+MODULE_AUTHOR("Sergei Ianovich");
+MODULE_DESCRIPTION("8250 serial port module for LP-8841");
+MODULE_LICENSE("GPL");
diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
index 3b5cf9c..68640c1 100644
--- a/drivers/tty/serial/8250/Kconfig
+++ b/drivers/tty/serial/8250/Kconfig
@@ -394,3 +394,17 @@ config SERIAL_8250_PXA
 	help
 	  If you have a machine based on an Intel XScale PXA2xx CPU you
 	  can enable its onboard serial ports by enabling this option.
+
+	  If you choose M here, the module name will be 8250_pxa.
+
+config SERIAL_8250_LP8841
+	tristate "Support 16550A ports on ICP DAS LP-8841"
+	depends on SERIAL_8250 && MACH_PXA27X_DT
+	select LP8841_IRQ
+	help
+	  In addition to serial ports on PXA270 SoC, LP-8841 has 1 dual
+	  RS232/RS485 port, 1 RS485 port and 1 RS232 port.
+
+	  Say N here, unless you plan to run this kernel on a LP-8841 system.
+
+	  If you choose M here, the module name will be 8250_lp8841.
diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile
index d1e2f2d..10b4bf0 100644
--- a/drivers/tty/serial/8250/Makefile
+++ b/drivers/tty/serial/8250/Makefile
@@ -18,6 +18,7 @@ obj-$(CONFIG_SERIAL_8250_ACCENT)	+= 8250_accent.o
 obj-$(CONFIG_SERIAL_8250_BOCA)		+= 8250_boca.o
 obj-$(CONFIG_SERIAL_8250_EXAR_ST16C554)	+= 8250_exar_st16c554.o
 obj-$(CONFIG_SERIAL_8250_HUB6)		+= 8250_hub6.o
+obj-$(CONFIG_SERIAL_8250_LP8X4X)	+= 8250_lp8x4x.o
 obj-$(CONFIG_SERIAL_8250_FSL)		+= 8250_fsl.o
 obj-$(CONFIG_SERIAL_8250_DW)		+= 8250_dw.o
 obj-$(CONFIG_SERIAL_8250_EM)		+= 8250_em.o
@@ -30,5 +31,6 @@ obj-$(CONFIG_SERIAL_8250_INGENIC)	+= 8250_ingenic.o
 obj-$(CONFIG_SERIAL_8250_MID)		+= 8250_mid.o
 obj-$(CONFIG_SERIAL_OF_PLATFORM)	+= 8250_of.o
 obj-$(CONFIG_SERIAL_8250_PXA)		+= 8250_pxa.o
+obj-$(CONFIG_SERIAL_8250_LP8841)	+= 8250_lp8841.o
 
 CFLAGS_8250_ingenic.o += -I$(srctree)/scripts/dtc/libfdt
-- 
2.7.0

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

* [PATCH v8] serial: support for 16550A serial ports on LP-8x4x
@ 2016-03-01 19:54                         ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2016-03-01 19:54 UTC (permalink / raw)
  To: linux-kernel
  Cc: Sergei Ianovich, Alan Cox, Andy Shevchenko, Arnd Bergmann,
	Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	Greg Kroah-Hartman, Jiri Slaby, Heikki Krogerus, Peter Hurley,
	Masahiro Yamada, Paul Gortmaker, Paul Burton, Joachim Eastwood,
	Mans Rullgard, Scott Wood, Matthias Brugger, Peter Ujfalusi,
	open l

The patch adds support for 3 additional LP-8x4x built-in serial
ports.

The device can also host up to 8 extension cards with 4 serial ports
on each card for a total of 35 ports. However, I don't have
the hardware to test extension cards, so they are not supported, yet.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
---
CC: Alan Cox <gnomes@lxorguk.ukuu.org.uk>
CC: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
CC: Arnd Bergmann <arnd@arndb.de>

   v7..v8
   * call serial8250_do_set_termios() after speed check, not before.
     This way clock divisor is properly inited for the new baud rate,
     if any
   fix review comments by Andy Shevchenko
   * change board variable name and type
   * use ternary operators
   * use #defines instead of magic numbers
   * simplify speed check and use uart_get_baud_rate()
   * zero-init uart structure
   * re-organized probing calls

   v6..v7
   fix review comments by Andy Shevchenko
   not applying Acked-by as the 1st change is big
   * handle unsupported tty modes correctly
   * remove extra check of platform_get_resource() result
   * propagate error code from devm_ioremap_resource()
   * drop uart.port.iobase for UPIO_MEM device

   v5..v6
   fix review comments by Arnd Bergmann
   * remove wildcards from compatible
   * update doc file
   * drop interrupt parent from doc file
   * replace uart w/ serial in device names in doc file

   fix review comments by Andy Shevchenko
   * exchange labels in switch block
   * replace iowrite8() with writeb()
   * compact comment to one line

   v4..v5
   * constify struct of_device_id
   * drop .owner from struct platform_driver
   * rewrite set_termios() baud rate hadnling as suggested by Alan Cox

   v3..v4
   * move DTS bindings to a different patch (8/21) as suggested by
     Heikki Krogerus

   v2..v3
   * no changes (except number 10/16 -> 12/21)

   v0..v2
   * register platform driver instead of platform device
   * use device tree
   * use devm helpers where possible

 .../bindings/serial/icpdas-lp8841-uart.txt         |  41 +++++
 drivers/tty/serial/8250/8250_lp8841.c              | 173 +++++++++++++++++++++
 drivers/tty/serial/8250/Kconfig                    |  14 ++
 drivers/tty/serial/8250/Makefile                   |   2 +
 4 files changed, 230 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/serial/icpdas-lp8841-uart.txt
 create mode 100644 drivers/tty/serial/8250/8250_lp8841.c

diff --git a/Documentation/devicetree/bindings/serial/icpdas-lp8841-uart.txt b/Documentation/devicetree/bindings/serial/icpdas-lp8841-uart.txt
new file mode 100644
index 0000000..d6acd22
--- /dev/null
+++ b/Documentation/devicetree/bindings/serial/icpdas-lp8841-uart.txt
@@ -0,0 +1,41 @@
+* UART ports on ICP DAS LP-8841
+
+LP-8441, LP-8141 and LP-8041 are fully compatible.
+
+ICP DAS LP-8841 contains three additional serial ports interfaced via
+Analog Devices ADM213EA chips in addition to 3 serial ports on PXA CPU.
+
+The chips themselves are standard, they would work with 8250_core if
+properly connected. However, they are not connected normally. Al least
+some of their config pins are wired to a different address region. So
+the driver is board-specific.
+
+Required properties:
+- compatible : should be "icpdas,uart-lp8841"
+
+- reg : should provide 16 byte man IO memory region and 1 byte region for
+	termios
+
+- interrupts : should provide interrupt
+
+Optional property:
+- interrupt-parent : should provide a link to interrupt controller either
+		     explicitly or implicitly from a parent node
+
+Examples (from pxa27x-lp8x4x.dts):
+
+		serial@9050 {
+			compatible = "icpdas,uart-lp8841";
+			reg = <0x9050 0x10
+			       0x9030 0x02>;
+			interrupts = <13>;
+			status = "okay";
+		};
+
+		serial@9060 {
+			compatible = "icpdas,uart-lp8841";
+			reg = <0x9060 0x10
+			       0x9032 0x02>;
+			interrupts = <14>;
+			status = "okay";
+		};
diff --git a/drivers/tty/serial/8250/8250_lp8841.c b/drivers/tty/serial/8250/8250_lp8841.c
new file mode 100644
index 0000000..d80e218
--- /dev/null
+++ b/drivers/tty/serial/8250/8250_lp8841.c
@@ -0,0 +1,173 @@
+/*  linux/drivers/tty/serial/8250/8250_lp8841.c
+ *
+ *  Support for 16550A serial ports on ICP DAS LP-8841
+ *
+ *  Copyright (C) 2013 Sergei Ianovich <ynvich@gmail.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/module.h>
+#include <linux/serial_8250.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+struct lp8841_serial_data {
+	int			line;
+	void __iomem		*ios_mem;
+};
+
+#define LP8841_DATA_LEN_MASK		0x3
+#define LP8841_DATA_LEN_SHIFT_OFFSET	3
+
+static void lp8841_serial_set_termios(struct uart_port *port,
+		struct ktermios *termios, struct ktermios *old)
+{
+#ifdef BOTHER
+	unsigned int cbaud;
+#endif
+	unsigned int baud;
+	u8 value;
+	unsigned int old_csize = old ? old->c_cflag & CSIZE : CS8;
+	struct lp8841_serial_data *data = port->private_data;
+
+	/* We only support CS7 and CS8 */
+	while ((termios->c_cflag & CSIZE) != CS7 &&
+	       (termios->c_cflag & CSIZE) != CS8) {
+		termios->c_cflag &= ~CSIZE;
+		termios->c_cflag |= old_csize;
+		old_csize = CS8;
+	}
+
+	value =  (termios->c_cflag & CSIZE) == CS7 ? 0 : 1;
+	value += (termios->c_cflag & CSTOPB) ? 1 : 0;
+	value += (termios->c_cflag & PARENB) ? 1 : 0;
+	value += (termios->c_cflag & PARODD) ? 0 : 1;
+#ifdef CMSPAR
+	value += (termios->c_cflag & CMSPAR) ? 1 : 0;
+#endif
+
+	value &=  LP8841_DATA_LEN_MASK;
+	value <<= LP8841_DATA_LEN_SHIFT_OFFSET;
+
+	baud = tty_termios_baud_rate(termios);
+
+#ifdef BOTHER
+	/* We only support fixed rates */
+	cbaud = termios->c_cflag & CBAUD;
+
+	if (cbaud == BOTHER)
+		termios->c_cflag &= ~BOTHER;
+#endif
+
+	/* We only support up to 115200 */
+	if (baud > 115200)
+		baud = 115200;
+
+	baud = uart_get_baud_rate(port, termios, old, baud, baud);
+
+	serial8250_do_set_termios(port, termios, old);
+
+	switch (baud) {
+	case 115200:
+		value |= 7;
+		break;
+	case 57600:
+		value |= 6;
+		break;
+	case 38400:
+		value |= 5;
+		break;
+	case 19200:
+		value |= 4;
+		break;
+	case 9600:
+		value |= 3;
+		break;
+	case 4800:
+		value |= 2;
+		break;
+	case 2400:
+	default:
+		value |= 1;
+		break;
+	};
+	writeb(value, data->ios_mem);
+}
+
+static const struct of_device_id lp8841_serial_dt_ids[] = {
+	{ .compatible = "icpdas,lp8841-uart", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, lp8841_serial_dt_ids);
+
+static int lp8841_serial_probe(struct platform_device *pdev)
+{
+	struct uart_8250_port uart = {};
+	struct lp8841_serial_data *data;
+	struct resource *mmres, *mires;
+	int ret;
+
+	memset(&uart, 0, sizeof(uart));
+
+	mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!mmres)
+		return -ENODEV;
+
+	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	mires = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	data->ios_mem = devm_ioremap_resource(&pdev->dev, mires);
+	if (IS_ERR(data->ios_mem))
+		return PTR_ERR(data->ios_mem);
+
+	uart.port.iotype = UPIO_MEM;
+	uart.port.mapbase = mmres->start;
+	uart.port.regshift = 1;
+	uart.port.irq = platform_get_irq(pdev, 0);
+	uart.port.flags = UPF_IOREMAP;
+	uart.port.dev = &pdev->dev;
+	uart.port.uartclk = 14745600;
+	uart.port.set_termios = lp8841_serial_set_termios;
+	uart.port.private_data = data;
+
+	ret = serial8250_register_8250_port(&uart);
+	if (ret < 0)
+		return ret;
+
+	data->line = ret;
+
+	platform_set_drvdata(pdev, data);
+
+	return 0;
+}
+
+static int lp8841_serial_remove(struct platform_device *pdev)
+{
+	struct lp8841_serial_data *data = platform_get_drvdata(pdev);
+
+	serial8250_unregister_port(data->line);
+
+	return 0;
+}
+
+static struct platform_driver lp8841_serial_driver = {
+	.probe          = lp8841_serial_probe,
+	.remove         = lp8841_serial_remove,
+	.driver		= {
+		.name	= "uart-lp8841",
+		.of_match_table = lp8841_serial_dt_ids,
+	},
+};
+
+module_platform_driver(lp8841_serial_driver);
+
+MODULE_AUTHOR("Sergei Ianovich");
+MODULE_DESCRIPTION("8250 serial port module for LP-8841");
+MODULE_LICENSE("GPL");
diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
index 3b5cf9c..68640c1 100644
--- a/drivers/tty/serial/8250/Kconfig
+++ b/drivers/tty/serial/8250/Kconfig
@@ -394,3 +394,17 @@ config SERIAL_8250_PXA
 	help
 	  If you have a machine based on an Intel XScale PXA2xx CPU you
 	  can enable its onboard serial ports by enabling this option.
+
+	  If you choose M here, the module name will be 8250_pxa.
+
+config SERIAL_8250_LP8841
+	tristate "Support 16550A ports on ICP DAS LP-8841"
+	depends on SERIAL_8250 && MACH_PXA27X_DT
+	select LP8841_IRQ
+	help
+	  In addition to serial ports on PXA270 SoC, LP-8841 has 1 dual
+	  RS232/RS485 port, 1 RS485 port and 1 RS232 port.
+
+	  Say N here, unless you plan to run this kernel on a LP-8841 system.
+
+	  If you choose M here, the module name will be 8250_lp8841.
diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile
index d1e2f2d..10b4bf0 100644
--- a/drivers/tty/serial/8250/Makefile
+++ b/drivers/tty/serial/8250/Makefile
@@ -18,6 +18,7 @@ obj-$(CONFIG_SERIAL_8250_ACCENT)	+= 8250_accent.o
 obj-$(CONFIG_SERIAL_8250_BOCA)		+= 8250_boca.o
 obj-$(CONFIG_SERIAL_8250_EXAR_ST16C554)	+= 8250_exar_st16c554.o
 obj-$(CONFIG_SERIAL_8250_HUB6)		+= 8250_hub6.o
+obj-$(CONFIG_SERIAL_8250_LP8X4X)	+= 8250_lp8x4x.o
 obj-$(CONFIG_SERIAL_8250_FSL)		+= 8250_fsl.o
 obj-$(CONFIG_SERIAL_8250_DW)		+= 8250_dw.o
 obj-$(CONFIG_SERIAL_8250_EM)		+= 8250_em.o
@@ -30,5 +31,6 @@ obj-$(CONFIG_SERIAL_8250_INGENIC)	+= 8250_ingenic.o
 obj-$(CONFIG_SERIAL_8250_MID)		+= 8250_mid.o
 obj-$(CONFIG_SERIAL_OF_PLATFORM)	+= 8250_of.o
 obj-$(CONFIG_SERIAL_8250_PXA)		+= 8250_pxa.o
+obj-$(CONFIG_SERIAL_8250_LP8841)	+= 8250_lp8841.o
 
 CFLAGS_8250_ingenic.o += -I$(srctree)/scripts/dtc/libfdt
-- 
2.7.0

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

* [PATCH v9] serial: support for 16550A serial ports on LP-8x4x
@ 2016-03-01 20:08                           ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2016-03-01 20:08 UTC (permalink / raw)
  To: linux-kernel
  Cc: Sergei Ianovich, Alan Cox, Andy Shevchenko, Arnd Bergmann,
	Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	Greg Kroah-Hartman, Jiri Slaby, Heikki Krogerus, Masahiro Yamada,
	Joachim Eastwood, Paul Burton, Mans Rullgard, Scott Wood,
	Paul Gortmaker, Peter Ujfalusi, Peter Hurley,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	open list:SERIAL DRIVERS

The patch adds support for 3 additional LP-8x4x built-in serial
ports.

The device can also host up to 8 extension cards with 4 serial ports
on each card for a total of 35 ports. However, I don't have
the hardware to test extension cards, so they are not supported, yet.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
---
CC: Alan Cox <gnomes@lxorguk.ukuu.org.uk>
CC: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
CC: Arnd Bergmann <arnd@arndb.de>

   v8..v9
   fix review comments by Alan Cox
   * further simplify speed check

   v7..v8
   * call serial8250_do_set_termios() after speed check, not before.
     This way clock divisor is properly inited for the new baud rate,
     if any
   fix review comments by Andy Shevchenko
   * change board variable name and type
   * use ternary operators
   * use #defines instead of magic numbers
   * simplify speed check and use uart_get_baud_rate()
   * zero-init uart structure
   * re-organized probing calls

   v6..v7
   fix review comments by Andy Shevchenko
   not applying Acked-by as the 1st change is big
   * handle unsupported tty modes correctly
   * remove extra check of platform_get_resource() result
   * propagate error code from devm_ioremap_resource()
   * drop uart.port.iobase for UPIO_MEM device

   v5..v6
   fix review comments by Arnd Bergmann
   * remove wildcards from compatible
   * update doc file
   * drop interrupt parent from doc file
   * replace uart w/ serial in device names in doc file

   fix review comments by Andy Shevchenko
   * exchange labels in switch block
   * replace iowrite8() with writeb()
   * compact comment to one line

   v4..v5
   * constify struct of_device_id
   * drop .owner from struct platform_driver
   * rewrite set_termios() baud rate hadnling as suggested by Alan Cox

   v3..v4
   * move DTS bindings to a different patch (8/21) as suggested by
     Heikki Krogerus

   v2..v3
   * no changes (except number 10/16 -> 12/21)

   v0..v2
   * register platform driver instead of platform device
   * use device tree
   * use devm helpers where possible

 .../bindings/serial/icpdas-lp8841-uart.txt         |  41 ++++++
 drivers/tty/serial/8250/8250_lp8841.c              | 159 +++++++++++++++++++++
 drivers/tty/serial/8250/Kconfig                    |  14 ++
 drivers/tty/serial/8250/Makefile                   |   2 +
 4 files changed, 216 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/serial/icpdas-lp8841-uart.txt
 create mode 100644 drivers/tty/serial/8250/8250_lp8841.c

diff --git a/Documentation/devicetree/bindings/serial/icpdas-lp8841-uart.txt b/Documentation/devicetree/bindings/serial/icpdas-lp8841-uart.txt
new file mode 100644
index 0000000..d6acd22
--- /dev/null
+++ b/Documentation/devicetree/bindings/serial/icpdas-lp8841-uart.txt
@@ -0,0 +1,41 @@
+* UART ports on ICP DAS LP-8841
+
+LP-8441, LP-8141 and LP-8041 are fully compatible.
+
+ICP DAS LP-8841 contains three additional serial ports interfaced via
+Analog Devices ADM213EA chips in addition to 3 serial ports on PXA CPU.
+
+The chips themselves are standard, they would work with 8250_core if
+properly connected. However, they are not connected normally. Al least
+some of their config pins are wired to a different address region. So
+the driver is board-specific.
+
+Required properties:
+- compatible : should be "icpdas,uart-lp8841"
+
+- reg : should provide 16 byte man IO memory region and 1 byte region for
+	termios
+
+- interrupts : should provide interrupt
+
+Optional property:
+- interrupt-parent : should provide a link to interrupt controller either
+		     explicitly or implicitly from a parent node
+
+Examples (from pxa27x-lp8x4x.dts):
+
+		serial@9050 {
+			compatible = "icpdas,uart-lp8841";
+			reg = <0x9050 0x10
+			       0x9030 0x02>;
+			interrupts = <13>;
+			status = "okay";
+		};
+
+		serial@9060 {
+			compatible = "icpdas,uart-lp8841";
+			reg = <0x9060 0x10
+			       0x9032 0x02>;
+			interrupts = <14>;
+			status = "okay";
+		};
diff --git a/drivers/tty/serial/8250/8250_lp8841.c b/drivers/tty/serial/8250/8250_lp8841.c
new file mode 100644
index 0000000..548f382
--- /dev/null
+++ b/drivers/tty/serial/8250/8250_lp8841.c
@@ -0,0 +1,159 @@
+/*  linux/drivers/tty/serial/8250/8250_lp8841.c
+ *
+ *  Support for 16550A serial ports on ICP DAS LP-8841
+ *
+ *  Copyright (C) 2013 Sergei Ianovich <ynvich@gmail.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/module.h>
+#include <linux/serial_8250.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+struct lp8841_serial_data {
+	int			line;
+	void __iomem		*ios_mem;
+};
+
+#define LP8841_DATA_LEN_MASK		0x3
+#define LP8841_DATA_LEN_SHIFT_OFFSET	3
+
+static void lp8841_serial_set_termios(struct uart_port *port,
+		struct ktermios *termios, struct ktermios *old)
+{
+	unsigned int baud;
+	u8 value;
+	unsigned int old_csize = old ? old->c_cflag & CSIZE : CS8;
+	struct lp8841_serial_data *data = port->private_data;
+
+	/* We only support CS7 and CS8 */
+	while ((termios->c_cflag & CSIZE) != CS7 &&
+	       (termios->c_cflag & CSIZE) != CS8) {
+		termios->c_cflag &= ~CSIZE;
+		termios->c_cflag |= old_csize;
+		old_csize = CS8;
+	}
+
+	value =  (termios->c_cflag & CSIZE) == CS7 ? 0 : 1;
+	value += (termios->c_cflag & CSTOPB) ? 1 : 0;
+	value += (termios->c_cflag & PARENB) ? 1 : 0;
+	value += (termios->c_cflag & PARODD) ? 0 : 1;
+#ifdef CMSPAR
+	value += (termios->c_cflag & CMSPAR) ? 1 : 0;
+#endif
+
+	value &=  LP8841_DATA_LEN_MASK;
+	value <<= LP8841_DATA_LEN_SHIFT_OFFSET;
+
+	baud = tty_termios_baud_rate(termios);
+
+	switch (baud) {
+	case 115200:
+		value |= 7;
+		break;
+	case 57600:
+		value |= 6;
+		break;
+	case 38400:
+		value |= 5;
+		break;
+	case 19200:
+		value |= 4;
+		break;
+	case 9600:
+		value |= 3;
+		break;
+	case 4800:
+		value |= 2;
+		break;
+	case 2400:
+		value |= 1;
+		break;
+	default:
+		value |= 1;
+		tty_termios_encode_baud_rate(termios, 2400, 2400);
+		break;
+	};
+	writeb(value, data->ios_mem);
+
+	serial8250_do_set_termios(port, termios, old);
+}
+
+static const struct of_device_id lp8841_serial_dt_ids[] = {
+	{ .compatible = "icpdas,lp8841-uart", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, lp8841_serial_dt_ids);
+
+static int lp8841_serial_probe(struct platform_device *pdev)
+{
+	struct uart_8250_port uart = {};
+	struct lp8841_serial_data *data;
+	struct resource *mmres, *mires;
+	int ret;
+
+	memset(&uart, 0, sizeof(uart));
+
+	mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!mmres)
+		return -ENODEV;
+
+	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	mires = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	data->ios_mem = devm_ioremap_resource(&pdev->dev, mires);
+	if (IS_ERR(data->ios_mem))
+		return PTR_ERR(data->ios_mem);
+
+	uart.port.iotype = UPIO_MEM;
+	uart.port.mapbase = mmres->start;
+	uart.port.regshift = 1;
+	uart.port.irq = platform_get_irq(pdev, 0);
+	uart.port.flags = UPF_IOREMAP;
+	uart.port.dev = &pdev->dev;
+	uart.port.uartclk = 14745600;
+	uart.port.set_termios = lp8841_serial_set_termios;
+	uart.port.private_data = data;
+
+	ret = serial8250_register_8250_port(&uart);
+	if (ret < 0)
+		return ret;
+
+	data->line = ret;
+
+	platform_set_drvdata(pdev, data);
+
+	return 0;
+}
+
+static int lp8841_serial_remove(struct platform_device *pdev)
+{
+	struct lp8841_serial_data *data = platform_get_drvdata(pdev);
+
+	serial8250_unregister_port(data->line);
+
+	return 0;
+}
+
+static struct platform_driver lp8841_serial_driver = {
+	.probe          = lp8841_serial_probe,
+	.remove         = lp8841_serial_remove,
+	.driver		= {
+		.name	= "uart-lp8841",
+		.of_match_table = lp8841_serial_dt_ids,
+	},
+};
+
+module_platform_driver(lp8841_serial_driver);
+
+MODULE_AUTHOR("Sergei Ianovich");
+MODULE_DESCRIPTION("8250 serial port module for LP-8841");
+MODULE_LICENSE("GPL");
diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
index 3b5cf9c..68640c1 100644
--- a/drivers/tty/serial/8250/Kconfig
+++ b/drivers/tty/serial/8250/Kconfig
@@ -394,3 +394,17 @@ config SERIAL_8250_PXA
 	help
 	  If you have a machine based on an Intel XScale PXA2xx CPU you
 	  can enable its onboard serial ports by enabling this option.
+
+	  If you choose M here, the module name will be 8250_pxa.
+
+config SERIAL_8250_LP8841
+	tristate "Support 16550A ports on ICP DAS LP-8841"
+	depends on SERIAL_8250 && MACH_PXA27X_DT
+	select LP8841_IRQ
+	help
+	  In addition to serial ports on PXA270 SoC, LP-8841 has 1 dual
+	  RS232/RS485 port, 1 RS485 port and 1 RS232 port.
+
+	  Say N here, unless you plan to run this kernel on a LP-8841 system.
+
+	  If you choose M here, the module name will be 8250_lp8841.
diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile
index d1e2f2d..10b4bf0 100644
--- a/drivers/tty/serial/8250/Makefile
+++ b/drivers/tty/serial/8250/Makefile
@@ -18,6 +18,7 @@ obj-$(CONFIG_SERIAL_8250_ACCENT)	+= 8250_accent.o
 obj-$(CONFIG_SERIAL_8250_BOCA)		+= 8250_boca.o
 obj-$(CONFIG_SERIAL_8250_EXAR_ST16C554)	+= 8250_exar_st16c554.o
 obj-$(CONFIG_SERIAL_8250_HUB6)		+= 8250_hub6.o
+obj-$(CONFIG_SERIAL_8250_LP8X4X)	+= 8250_lp8x4x.o
 obj-$(CONFIG_SERIAL_8250_FSL)		+= 8250_fsl.o
 obj-$(CONFIG_SERIAL_8250_DW)		+= 8250_dw.o
 obj-$(CONFIG_SERIAL_8250_EM)		+= 8250_em.o
@@ -30,5 +31,6 @@ obj-$(CONFIG_SERIAL_8250_INGENIC)	+= 8250_ingenic.o
 obj-$(CONFIG_SERIAL_8250_MID)		+= 8250_mid.o
 obj-$(CONFIG_SERIAL_OF_PLATFORM)	+= 8250_of.o
 obj-$(CONFIG_SERIAL_8250_PXA)		+= 8250_pxa.o
+obj-$(CONFIG_SERIAL_8250_LP8841)	+= 8250_lp8841.o
 
 CFLAGS_8250_ingenic.o += -I$(srctree)/scripts/dtc/libfdt
-- 
2.7.0

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

* [PATCH v9] serial: support for 16550A serial ports on LP-8x4x
@ 2016-03-01 20:08                           ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2016-03-01 20:08 UTC (permalink / raw)
  To: linux-kernel-u79uwXL29TY76Z2rM5mHXA
  Cc: Sergei Ianovich, Alan Cox, Andy Shevchenko, Arnd Bergmann,
	Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	Greg Kroah-Hartman, Jiri Slaby, Heikki Krogerus, Masahiro Yamada,
	Joachim Eastwood, Paul Burton, Mans Rullgard, Scott Wood,
	Paul Gortmaker, Peter Ujfalusi, Peter Hurley,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE

The patch adds support for 3 additional LP-8x4x built-in serial
ports.

The device can also host up to 8 extension cards with 4 serial ports
on each card for a total of 35 ports. However, I don't have
the hardware to test extension cards, so they are not supported, yet.

Signed-off-by: Sergei Ianovich <ynvich-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Reviewed-by: Heikki Krogerus <heikki.krogerus-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
---
CC: Alan Cox <gnomes-qBU/x9rampVanCEyBjwyrvXRex20P6io@public.gmane.org>
CC: Andy Shevchenko <andriy.shevchenko-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
CC: Arnd Bergmann <arnd-r2nGTMty4D4@public.gmane.org>

   v8..v9
   fix review comments by Alan Cox
   * further simplify speed check

   v7..v8
   * call serial8250_do_set_termios() after speed check, not before.
     This way clock divisor is properly inited for the new baud rate,
     if any
   fix review comments by Andy Shevchenko
   * change board variable name and type
   * use ternary operators
   * use #defines instead of magic numbers
   * simplify speed check and use uart_get_baud_rate()
   * zero-init uart structure
   * re-organized probing calls

   v6..v7
   fix review comments by Andy Shevchenko
   not applying Acked-by as the 1st change is big
   * handle unsupported tty modes correctly
   * remove extra check of platform_get_resource() result
   * propagate error code from devm_ioremap_resource()
   * drop uart.port.iobase for UPIO_MEM device

   v5..v6
   fix review comments by Arnd Bergmann
   * remove wildcards from compatible
   * update doc file
   * drop interrupt parent from doc file
   * replace uart w/ serial in device names in doc file

   fix review comments by Andy Shevchenko
   * exchange labels in switch block
   * replace iowrite8() with writeb()
   * compact comment to one line

   v4..v5
   * constify struct of_device_id
   * drop .owner from struct platform_driver
   * rewrite set_termios() baud rate hadnling as suggested by Alan Cox

   v3..v4
   * move DTS bindings to a different patch (8/21) as suggested by
     Heikki Krogerus

   v2..v3
   * no changes (except number 10/16 -> 12/21)

   v0..v2
   * register platform driver instead of platform device
   * use device tree
   * use devm helpers where possible

 .../bindings/serial/icpdas-lp8841-uart.txt         |  41 ++++++
 drivers/tty/serial/8250/8250_lp8841.c              | 159 +++++++++++++++++++++
 drivers/tty/serial/8250/Kconfig                    |  14 ++
 drivers/tty/serial/8250/Makefile                   |   2 +
 4 files changed, 216 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/serial/icpdas-lp8841-uart.txt
 create mode 100644 drivers/tty/serial/8250/8250_lp8841.c

diff --git a/Documentation/devicetree/bindings/serial/icpdas-lp8841-uart.txt b/Documentation/devicetree/bindings/serial/icpdas-lp8841-uart.txt
new file mode 100644
index 0000000..d6acd22
--- /dev/null
+++ b/Documentation/devicetree/bindings/serial/icpdas-lp8841-uart.txt
@@ -0,0 +1,41 @@
+* UART ports on ICP DAS LP-8841
+
+LP-8441, LP-8141 and LP-8041 are fully compatible.
+
+ICP DAS LP-8841 contains three additional serial ports interfaced via
+Analog Devices ADM213EA chips in addition to 3 serial ports on PXA CPU.
+
+The chips themselves are standard, they would work with 8250_core if
+properly connected. However, they are not connected normally. Al least
+some of their config pins are wired to a different address region. So
+the driver is board-specific.
+
+Required properties:
+- compatible : should be "icpdas,uart-lp8841"
+
+- reg : should provide 16 byte man IO memory region and 1 byte region for
+	termios
+
+- interrupts : should provide interrupt
+
+Optional property:
+- interrupt-parent : should provide a link to interrupt controller either
+		     explicitly or implicitly from a parent node
+
+Examples (from pxa27x-lp8x4x.dts):
+
+		serial@9050 {
+			compatible = "icpdas,uart-lp8841";
+			reg = <0x9050 0x10
+			       0x9030 0x02>;
+			interrupts = <13>;
+			status = "okay";
+		};
+
+		serial@9060 {
+			compatible = "icpdas,uart-lp8841";
+			reg = <0x9060 0x10
+			       0x9032 0x02>;
+			interrupts = <14>;
+			status = "okay";
+		};
diff --git a/drivers/tty/serial/8250/8250_lp8841.c b/drivers/tty/serial/8250/8250_lp8841.c
new file mode 100644
index 0000000..548f382
--- /dev/null
+++ b/drivers/tty/serial/8250/8250_lp8841.c
@@ -0,0 +1,159 @@
+/*  linux/drivers/tty/serial/8250/8250_lp8841.c
+ *
+ *  Support for 16550A serial ports on ICP DAS LP-8841
+ *
+ *  Copyright (C) 2013 Sergei Ianovich <ynvich-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/module.h>
+#include <linux/serial_8250.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+struct lp8841_serial_data {
+	int			line;
+	void __iomem		*ios_mem;
+};
+
+#define LP8841_DATA_LEN_MASK		0x3
+#define LP8841_DATA_LEN_SHIFT_OFFSET	3
+
+static void lp8841_serial_set_termios(struct uart_port *port,
+		struct ktermios *termios, struct ktermios *old)
+{
+	unsigned int baud;
+	u8 value;
+	unsigned int old_csize = old ? old->c_cflag & CSIZE : CS8;
+	struct lp8841_serial_data *data = port->private_data;
+
+	/* We only support CS7 and CS8 */
+	while ((termios->c_cflag & CSIZE) != CS7 &&
+	       (termios->c_cflag & CSIZE) != CS8) {
+		termios->c_cflag &= ~CSIZE;
+		termios->c_cflag |= old_csize;
+		old_csize = CS8;
+	}
+
+	value =  (termios->c_cflag & CSIZE) == CS7 ? 0 : 1;
+	value += (termios->c_cflag & CSTOPB) ? 1 : 0;
+	value += (termios->c_cflag & PARENB) ? 1 : 0;
+	value += (termios->c_cflag & PARODD) ? 0 : 1;
+#ifdef CMSPAR
+	value += (termios->c_cflag & CMSPAR) ? 1 : 0;
+#endif
+
+	value &=  LP8841_DATA_LEN_MASK;
+	value <<= LP8841_DATA_LEN_SHIFT_OFFSET;
+
+	baud = tty_termios_baud_rate(termios);
+
+	switch (baud) {
+	case 115200:
+		value |= 7;
+		break;
+	case 57600:
+		value |= 6;
+		break;
+	case 38400:
+		value |= 5;
+		break;
+	case 19200:
+		value |= 4;
+		break;
+	case 9600:
+		value |= 3;
+		break;
+	case 4800:
+		value |= 2;
+		break;
+	case 2400:
+		value |= 1;
+		break;
+	default:
+		value |= 1;
+		tty_termios_encode_baud_rate(termios, 2400, 2400);
+		break;
+	};
+	writeb(value, data->ios_mem);
+
+	serial8250_do_set_termios(port, termios, old);
+}
+
+static const struct of_device_id lp8841_serial_dt_ids[] = {
+	{ .compatible = "icpdas,lp8841-uart", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, lp8841_serial_dt_ids);
+
+static int lp8841_serial_probe(struct platform_device *pdev)
+{
+	struct uart_8250_port uart = {};
+	struct lp8841_serial_data *data;
+	struct resource *mmres, *mires;
+	int ret;
+
+	memset(&uart, 0, sizeof(uart));
+
+	mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!mmres)
+		return -ENODEV;
+
+	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	mires = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	data->ios_mem = devm_ioremap_resource(&pdev->dev, mires);
+	if (IS_ERR(data->ios_mem))
+		return PTR_ERR(data->ios_mem);
+
+	uart.port.iotype = UPIO_MEM;
+	uart.port.mapbase = mmres->start;
+	uart.port.regshift = 1;
+	uart.port.irq = platform_get_irq(pdev, 0);
+	uart.port.flags = UPF_IOREMAP;
+	uart.port.dev = &pdev->dev;
+	uart.port.uartclk = 14745600;
+	uart.port.set_termios = lp8841_serial_set_termios;
+	uart.port.private_data = data;
+
+	ret = serial8250_register_8250_port(&uart);
+	if (ret < 0)
+		return ret;
+
+	data->line = ret;
+
+	platform_set_drvdata(pdev, data);
+
+	return 0;
+}
+
+static int lp8841_serial_remove(struct platform_device *pdev)
+{
+	struct lp8841_serial_data *data = platform_get_drvdata(pdev);
+
+	serial8250_unregister_port(data->line);
+
+	return 0;
+}
+
+static struct platform_driver lp8841_serial_driver = {
+	.probe          = lp8841_serial_probe,
+	.remove         = lp8841_serial_remove,
+	.driver		= {
+		.name	= "uart-lp8841",
+		.of_match_table = lp8841_serial_dt_ids,
+	},
+};
+
+module_platform_driver(lp8841_serial_driver);
+
+MODULE_AUTHOR("Sergei Ianovich");
+MODULE_DESCRIPTION("8250 serial port module for LP-8841");
+MODULE_LICENSE("GPL");
diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
index 3b5cf9c..68640c1 100644
--- a/drivers/tty/serial/8250/Kconfig
+++ b/drivers/tty/serial/8250/Kconfig
@@ -394,3 +394,17 @@ config SERIAL_8250_PXA
 	help
 	  If you have a machine based on an Intel XScale PXA2xx CPU you
 	  can enable its onboard serial ports by enabling this option.
+
+	  If you choose M here, the module name will be 8250_pxa.
+
+config SERIAL_8250_LP8841
+	tristate "Support 16550A ports on ICP DAS LP-8841"
+	depends on SERIAL_8250 && MACH_PXA27X_DT
+	select LP8841_IRQ
+	help
+	  In addition to serial ports on PXA270 SoC, LP-8841 has 1 dual
+	  RS232/RS485 port, 1 RS485 port and 1 RS232 port.
+
+	  Say N here, unless you plan to run this kernel on a LP-8841 system.
+
+	  If you choose M here, the module name will be 8250_lp8841.
diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile
index d1e2f2d..10b4bf0 100644
--- a/drivers/tty/serial/8250/Makefile
+++ b/drivers/tty/serial/8250/Makefile
@@ -18,6 +18,7 @@ obj-$(CONFIG_SERIAL_8250_ACCENT)	+= 8250_accent.o
 obj-$(CONFIG_SERIAL_8250_BOCA)		+= 8250_boca.o
 obj-$(CONFIG_SERIAL_8250_EXAR_ST16C554)	+= 8250_exar_st16c554.o
 obj-$(CONFIG_SERIAL_8250_HUB6)		+= 8250_hub6.o
+obj-$(CONFIG_SERIAL_8250_LP8X4X)	+= 8250_lp8x4x.o
 obj-$(CONFIG_SERIAL_8250_FSL)		+= 8250_fsl.o
 obj-$(CONFIG_SERIAL_8250_DW)		+= 8250_dw.o
 obj-$(CONFIG_SERIAL_8250_EM)		+= 8250_em.o
@@ -30,5 +31,6 @@ obj-$(CONFIG_SERIAL_8250_INGENIC)	+= 8250_ingenic.o
 obj-$(CONFIG_SERIAL_8250_MID)		+= 8250_mid.o
 obj-$(CONFIG_SERIAL_OF_PLATFORM)	+= 8250_of.o
 obj-$(CONFIG_SERIAL_8250_PXA)		+= 8250_pxa.o
+obj-$(CONFIG_SERIAL_8250_LP8841)	+= 8250_lp8841.o
 
 CFLAGS_8250_ingenic.o += -I$(srctree)/scripts/dtc/libfdt
-- 
2.7.0

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH v9] serial: support for 16550A serial ports on LP-8x4x
@ 2016-03-01 20:23                             ` Andy Shevchenko
  0 siblings, 0 replies; 700+ messages in thread
From: Andy Shevchenko @ 2016-03-01 20:23 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: linux-kernel, Alan Cox, Andy Shevchenko, Arnd Bergmann,
	Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	Greg Kroah-Hartman, Jiri Slaby, Heikki Krogerus, Masahiro Yamada,
	Joachim Eastwood, Paul Burton, Mans Rullgard, Scott Wood,
	Paul Gortmaker, Peter Ujfalusi, Peter Hurley,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	open list:SERIAL DRIVERS

On Tue, Mar 1, 2016 at 10:08 PM, Sergei Ianovich <ynvich@gmail.com> wrote:
> The patch adds support for 3 additional LP-8x4x built-in serial
> ports.
>
> The device can also host up to 8 extension cards with 4 serial ports
> on each card for a total of 35 ports. However, I don't have
> the hardware to test extension cards, so they are not supported, yet.
>
> Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
> Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>

Sorry, but still few nitpicks and then
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>

> +#define LP8841_DATA_LEN_MASK           0x3
> +#define LP8841_DATA_LEN_SHIFT_OFFSET   3

No need to have _OFFSET suffix.

> +
> +static void lp8841_serial_set_termios(struct uart_port *port,
> +               struct ktermios *termios, struct ktermios *old)
> +{
> +       unsigned int baud;
> +       u8 value;

> +       unsigned int old_csize = old ? old->c_cflag & CSIZE : CS8;
> +       struct lp8841_serial_data *data = port->private_data;

I would rearrange to have assignments first in the definition block.

Code duplication (no idea if it worth to fix):

+       case 2400:
+               value |= 1;
+               break;
+       default:
+               value |= 1;
+               tty_termios_encode_baud_rate(termios, 2400, 2400);
+               break;

> +static int lp8841_serial_probe(struct platform_device *pdev)
> +{
> +       struct uart_8250_port uart = {};

No need {} since memset().

> +       struct lp8841_serial_data *data;
> +       struct resource *mmres, *mires;
> +       int ret;
> +
> +       memset(&uart, 0, sizeof(uart));

Move this closer to the first assignment of a field.

> +
> +       mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +       if (!mmres)
> +               return -ENODEV;
> +
> +       data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
> +       if (!data)
> +               return -ENOMEM;
> +
> +       mires = platform_get_resource(pdev, IORESOURCE_MEM, 1);
> +       data->ios_mem = devm_ioremap_resource(&pdev->dev, mires);
> +       if (IS_ERR(data->ios_mem))
> +               return PTR_ERR(data->ios_mem);
> +

+       memset(&uart, 0, sizeof(uart));

> +       uart.port.iotype = UPIO_MEM;
> +       uart.port.mapbase = mmres->start;
> +       uart.port.regshift = 1;
> +       uart.port.irq = platform_get_irq(pdev, 0);
> +       uart.port.flags = UPF_IOREMAP;
> +       uart.port.dev = &pdev->dev;
> +       uart.port.uartclk = 14745600;
> +       uart.port.set_termios = lp8841_serial_set_termios;
> +       uart.port.private_data = data;

-- 
With Best Regards,
Andy Shevchenko

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

* Re: [PATCH v9] serial: support for 16550A serial ports on LP-8x4x
@ 2016-03-01 20:23                             ` Andy Shevchenko
  0 siblings, 0 replies; 700+ messages in thread
From: Andy Shevchenko @ 2016-03-01 20:23 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA, Alan Cox, Andy Shevchenko,
	Arnd Bergmann, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Greg Kroah-Hartman, Jiri Slaby,
	Heikki Krogerus, Masahiro Yamada, Joachim Eastwood, Paul Burton,
	Mans Rullgard, Scott Wood, Paul Gortmaker, Peter Ujfalusi,
	Peter Hurley, OPEN

On Tue, Mar 1, 2016 at 10:08 PM, Sergei Ianovich <ynvich-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
> The patch adds support for 3 additional LP-8x4x built-in serial
> ports.
>
> The device can also host up to 8 extension cards with 4 serial ports
> on each card for a total of 35 ports. However, I don't have
> the hardware to test extension cards, so they are not supported, yet.
>
> Signed-off-by: Sergei Ianovich <ynvich-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> Reviewed-by: Heikki Krogerus <heikki.krogerus-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>

Sorry, but still few nitpicks and then
Reviewed-by: Andy Shevchenko <andriy.shevchenko-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>

> +#define LP8841_DATA_LEN_MASK           0x3
> +#define LP8841_DATA_LEN_SHIFT_OFFSET   3

No need to have _OFFSET suffix.

> +
> +static void lp8841_serial_set_termios(struct uart_port *port,
> +               struct ktermios *termios, struct ktermios *old)
> +{
> +       unsigned int baud;
> +       u8 value;

> +       unsigned int old_csize = old ? old->c_cflag & CSIZE : CS8;
> +       struct lp8841_serial_data *data = port->private_data;

I would rearrange to have assignments first in the definition block.

Code duplication (no idea if it worth to fix):

+       case 2400:
+               value |= 1;
+               break;
+       default:
+               value |= 1;
+               tty_termios_encode_baud_rate(termios, 2400, 2400);
+               break;

> +static int lp8841_serial_probe(struct platform_device *pdev)
> +{
> +       struct uart_8250_port uart = {};

No need {} since memset().

> +       struct lp8841_serial_data *data;
> +       struct resource *mmres, *mires;
> +       int ret;
> +
> +       memset(&uart, 0, sizeof(uart));

Move this closer to the first assignment of a field.

> +
> +       mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +       if (!mmres)
> +               return -ENODEV;
> +
> +       data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
> +       if (!data)
> +               return -ENOMEM;
> +
> +       mires = platform_get_resource(pdev, IORESOURCE_MEM, 1);
> +       data->ios_mem = devm_ioremap_resource(&pdev->dev, mires);
> +       if (IS_ERR(data->ios_mem))
> +               return PTR_ERR(data->ios_mem);
> +

+       memset(&uart, 0, sizeof(uart));

> +       uart.port.iotype = UPIO_MEM;
> +       uart.port.mapbase = mmres->start;
> +       uart.port.regshift = 1;
> +       uart.port.irq = platform_get_irq(pdev, 0);
> +       uart.port.flags = UPF_IOREMAP;
> +       uart.port.dev = &pdev->dev;
> +       uart.port.uartclk = 14745600;
> +       uart.port.set_termios = lp8841_serial_set_termios;
> +       uart.port.private_data = data;

-- 
With Best Regards,
Andy Shevchenko
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH v10] serial: support for 16550A serial ports on LP-8x4x
  2016-03-01 20:08                           ` Sergei Ianovich
@ 2016-03-01 21:25                             ` Sergei Ianovich
  -1 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2016-03-01 21:25 UTC (permalink / raw)
  To: linux-kernel
  Cc: Sergei Ianovich, Alan Cox, Arnd Bergmann, Rob Herring,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	Greg Kroah-Hartman, Jiri Slaby, Heikki Krogerus, Andy Shevchenko,
	Masahiro Yamada, Peter Hurley, Paul Burton, Mans Rullgard,
	Scott Wood, Paul Gortmaker, Joachim Eastwood, Peter Ujfalusi,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	open list:SERIAL DRIVERS

The patch adds support for 3 additional LP-8x4x built-in serial
ports.

The device can also host up to 8 extension cards with 4 serial ports
on each card for a total of 35 ports. However, I don't have
the hardware to test extension cards, so they are not supported, yet.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
---
CC: Alan Cox <gnomes@lxorguk.ukuu.org.uk>
CC: Arnd Bergmann <arnd@arndb.de>

   v9..v10
   fix review comments by Andy Shevchenko
   * fix code styling

   v8..v9
   fix review comments by Alan Cox
   * further simplify speed check

   v7..v8
   * call serial8250_do_set_termios() after speed check, not before.
     This way clock divisor is properly inited for the new baud rate,
     if any
   fix review comments by Andy Shevchenko
   * change board variable name and type
   * use ternary operators
   * use #defines instead of magic numbers
   * simplify speed check and use uart_get_baud_rate()
   * zero-init uart structure
   * re-organized probing calls

   v6..v7
   fix review comments by Andy Shevchenko
   not applying Acked-by as the 1st change is big
   * handle unsupported tty modes correctly
   * remove extra check of platform_get_resource() result
   * propagate error code from devm_ioremap_resource()
   * drop uart.port.iobase for UPIO_MEM device

   v5..v6
   fix review comments by Arnd Bergmann
   * remove wildcards from compatible
   * update doc file
   * drop interrupt parent from doc file
   * replace uart w/ serial in device names in doc file

   fix review comments by Andy Shevchenko
   * exchange labels in switch block
   * replace iowrite8() with writeb()
   * compact comment to one line

   v4..v5
   * constify struct of_device_id
   * drop .owner from struct platform_driver
   * rewrite set_termios() baud rate hadnling as suggested by Alan Cox

   v3..v4
   * move DTS bindings to a different patch (8/21) as suggested by
     Heikki Krogerus

   v2..v3
   * no changes (except number 10/16 -> 12/21)

   v0..v2
   * register platform driver instead of platform device
   * use device tree
   * use devm helpers where possible

 .../bindings/serial/icpdas-lp8841-uart.txt         |  41 ++++++
 drivers/tty/serial/8250/8250_lp8841.c              | 156 +++++++++++++++++++++
 drivers/tty/serial/8250/Kconfig                    |  14 ++
 drivers/tty/serial/8250/Makefile                   |   2 +
 4 files changed, 213 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/serial/icpdas-lp8841-uart.txt
 create mode 100644 drivers/tty/serial/8250/8250_lp8841.c

diff --git a/Documentation/devicetree/bindings/serial/icpdas-lp8841-uart.txt b/Documentation/devicetree/bindings/serial/icpdas-lp8841-uart.txt
new file mode 100644
index 0000000..d6acd22
--- /dev/null
+++ b/Documentation/devicetree/bindings/serial/icpdas-lp8841-uart.txt
@@ -0,0 +1,41 @@
+* UART ports on ICP DAS LP-8841
+
+LP-8441, LP-8141 and LP-8041 are fully compatible.
+
+ICP DAS LP-8841 contains three additional serial ports interfaced via
+Analog Devices ADM213EA chips in addition to 3 serial ports on PXA CPU.
+
+The chips themselves are standard, they would work with 8250_core if
+properly connected. However, they are not connected normally. Al least
+some of their config pins are wired to a different address region. So
+the driver is board-specific.
+
+Required properties:
+- compatible : should be "icpdas,uart-lp8841"
+
+- reg : should provide 16 byte man IO memory region and 1 byte region for
+	termios
+
+- interrupts : should provide interrupt
+
+Optional property:
+- interrupt-parent : should provide a link to interrupt controller either
+		     explicitly or implicitly from a parent node
+
+Examples (from pxa27x-lp8x4x.dts):
+
+		serial@9050 {
+			compatible = "icpdas,uart-lp8841";
+			reg = <0x9050 0x10
+			       0x9030 0x02>;
+			interrupts = <13>;
+			status = "okay";
+		};
+
+		serial@9060 {
+			compatible = "icpdas,uart-lp8841";
+			reg = <0x9060 0x10
+			       0x9032 0x02>;
+			interrupts = <14>;
+			status = "okay";
+		};
diff --git a/drivers/tty/serial/8250/8250_lp8841.c b/drivers/tty/serial/8250/8250_lp8841.c
new file mode 100644
index 0000000..d3a72da
--- /dev/null
+++ b/drivers/tty/serial/8250/8250_lp8841.c
@@ -0,0 +1,156 @@
+/*  linux/drivers/tty/serial/8250/8250_lp8841.c
+ *
+ *  Support for 16550A serial ports on ICP DAS LP-8841
+ *
+ *  Copyright (C) 2013 Sergei Ianovich <ynvich@gmail.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/module.h>
+#include <linux/serial_8250.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+struct lp8841_serial_data {
+	int			line;
+	void __iomem		*ios_mem;
+};
+
+#define LP8841_DATA_LEN_MASK		0x3
+#define LP8841_DATA_LEN_SHIFT		3
+
+static void lp8841_serial_set_termios(struct uart_port *port,
+		struct ktermios *termios, struct ktermios *old)
+{
+	struct lp8841_serial_data *data = port->private_data;
+	unsigned int old_csize = old ? old->c_cflag & CSIZE : CS8;
+	unsigned int baud;
+	u8 value;
+
+	/* We only support CS7 and CS8 */
+	while ((termios->c_cflag & CSIZE) != CS7 &&
+	       (termios->c_cflag & CSIZE) != CS8) {
+		termios->c_cflag &= ~CSIZE;
+		termios->c_cflag |= old_csize;
+		old_csize = CS8;
+	}
+
+	value =  (termios->c_cflag & CSIZE) == CS7 ? 0 : 1;
+	value += (termios->c_cflag & CSTOPB) ? 1 : 0;
+	value += (termios->c_cflag & PARENB) ? 1 : 0;
+	value += (termios->c_cflag & PARODD) ? 0 : 1;
+#ifdef CMSPAR
+	value += (termios->c_cflag & CMSPAR) ? 1 : 0;
+#endif
+
+	value &=  LP8841_DATA_LEN_MASK;
+	value <<= LP8841_DATA_LEN_SHIFT;
+
+	baud = tty_termios_baud_rate(termios);
+
+	switch (baud) {
+	case 115200:
+		value |= 7;
+		break;
+	case 57600:
+		value |= 6;
+		break;
+	case 38400:
+		value |= 5;
+		break;
+	case 19200:
+		value |= 4;
+		break;
+	case 9600:
+		value |= 3;
+		break;
+	case 4800:
+		value |= 2;
+		break;
+	default:
+		tty_termios_encode_baud_rate(termios, 2400, 2400);
+	case 2400:
+		value |= 1;
+		break;
+	};
+	writeb(value, data->ios_mem);
+
+	serial8250_do_set_termios(port, termios, old);
+}
+
+static const struct of_device_id lp8841_serial_dt_ids[] = {
+	{ .compatible = "icpdas,lp8841-uart", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, lp8841_serial_dt_ids);
+
+static int lp8841_serial_probe(struct platform_device *pdev)
+{
+	struct uart_8250_port uart;
+	struct lp8841_serial_data *data;
+	struct resource *mmres, *mires;
+	int ret;
+
+	mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!mmres)
+		return -ENODEV;
+
+	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	mires = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	data->ios_mem = devm_ioremap_resource(&pdev->dev, mires);
+	if (IS_ERR(data->ios_mem))
+		return PTR_ERR(data->ios_mem);
+
+	memset(&uart, 0, sizeof(uart));
+	uart.port.iotype = UPIO_MEM;
+	uart.port.mapbase = mmres->start;
+	uart.port.regshift = 1;
+	uart.port.irq = platform_get_irq(pdev, 0);
+	uart.port.flags = UPF_IOREMAP;
+	uart.port.dev = &pdev->dev;
+	uart.port.uartclk = 14745600;
+	uart.port.set_termios = lp8841_serial_set_termios;
+	uart.port.private_data = data;
+
+	ret = serial8250_register_8250_port(&uart);
+	if (ret < 0)
+		return ret;
+
+	data->line = ret;
+
+	platform_set_drvdata(pdev, data);
+
+	return 0;
+}
+
+static int lp8841_serial_remove(struct platform_device *pdev)
+{
+	struct lp8841_serial_data *data = platform_get_drvdata(pdev);
+
+	serial8250_unregister_port(data->line);
+
+	return 0;
+}
+
+static struct platform_driver lp8841_serial_driver = {
+	.probe          = lp8841_serial_probe,
+	.remove         = lp8841_serial_remove,
+	.driver		= {
+		.name	= "uart-lp8841",
+		.of_match_table = lp8841_serial_dt_ids,
+	},
+};
+
+module_platform_driver(lp8841_serial_driver);
+
+MODULE_AUTHOR("Sergei Ianovich");
+MODULE_DESCRIPTION("8250 serial port module for LP-8841");
+MODULE_LICENSE("GPL");
diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
index 3b5cf9c..68640c1 100644
--- a/drivers/tty/serial/8250/Kconfig
+++ b/drivers/tty/serial/8250/Kconfig
@@ -394,3 +394,17 @@ config SERIAL_8250_PXA
 	help
 	  If you have a machine based on an Intel XScale PXA2xx CPU you
 	  can enable its onboard serial ports by enabling this option.
+
+	  If you choose M here, the module name will be 8250_pxa.
+
+config SERIAL_8250_LP8841
+	tristate "Support 16550A ports on ICP DAS LP-8841"
+	depends on SERIAL_8250 && MACH_PXA27X_DT
+	select LP8841_IRQ
+	help
+	  In addition to serial ports on PXA270 SoC, LP-8841 has 1 dual
+	  RS232/RS485 port, 1 RS485 port and 1 RS232 port.
+
+	  Say N here, unless you plan to run this kernel on a LP-8841 system.
+
+	  If you choose M here, the module name will be 8250_lp8841.
diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile
index d1e2f2d..10b4bf0 100644
--- a/drivers/tty/serial/8250/Makefile
+++ b/drivers/tty/serial/8250/Makefile
@@ -18,6 +18,7 @@ obj-$(CONFIG_SERIAL_8250_ACCENT)	+= 8250_accent.o
 obj-$(CONFIG_SERIAL_8250_BOCA)		+= 8250_boca.o
 obj-$(CONFIG_SERIAL_8250_EXAR_ST16C554)	+= 8250_exar_st16c554.o
 obj-$(CONFIG_SERIAL_8250_HUB6)		+= 8250_hub6.o
+obj-$(CONFIG_SERIAL_8250_LP8X4X)	+= 8250_lp8x4x.o
 obj-$(CONFIG_SERIAL_8250_FSL)		+= 8250_fsl.o
 obj-$(CONFIG_SERIAL_8250_DW)		+= 8250_dw.o
 obj-$(CONFIG_SERIAL_8250_EM)		+= 8250_em.o
@@ -30,5 +31,6 @@ obj-$(CONFIG_SERIAL_8250_INGENIC)	+= 8250_ingenic.o
 obj-$(CONFIG_SERIAL_8250_MID)		+= 8250_mid.o
 obj-$(CONFIG_SERIAL_OF_PLATFORM)	+= 8250_of.o
 obj-$(CONFIG_SERIAL_8250_PXA)		+= 8250_pxa.o
+obj-$(CONFIG_SERIAL_8250_LP8841)	+= 8250_lp8841.o
 
 CFLAGS_8250_ingenic.o += -I$(srctree)/scripts/dtc/libfdt
-- 
2.7.0

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

* [PATCH v10] serial: support for 16550A serial ports on LP-8x4x
@ 2016-03-01 21:25                             ` Sergei Ianovich
  0 siblings, 0 replies; 700+ messages in thread
From: Sergei Ianovich @ 2016-03-01 21:25 UTC (permalink / raw)
  To: linux-kernel
  Cc: Sergei Ianovich, Alan Cox, Arnd Bergmann, Rob Herring,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	Greg Kroah-Hartman, Jiri Slaby, Heikki Krogerus, Andy Shevchenko,
	Masahiro Yamada, Peter Hurley, Paul Burton, Mans Rullgard,
	Scott Wood, Paul Gortmaker, Joachim Eastwood, Peter Ujfalusi,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE

The patch adds support for 3 additional LP-8x4x built-in serial
ports.

The device can also host up to 8 extension cards with 4 serial ports
on each card for a total of 35 ports. However, I don't have
the hardware to test extension cards, so they are not supported, yet.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
---
CC: Alan Cox <gnomes@lxorguk.ukuu.org.uk>
CC: Arnd Bergmann <arnd@arndb.de>

   v9..v10
   fix review comments by Andy Shevchenko
   * fix code styling

   v8..v9
   fix review comments by Alan Cox
   * further simplify speed check

   v7..v8
   * call serial8250_do_set_termios() after speed check, not before.
     This way clock divisor is properly inited for the new baud rate,
     if any
   fix review comments by Andy Shevchenko
   * change board variable name and type
   * use ternary operators
   * use #defines instead of magic numbers
   * simplify speed check and use uart_get_baud_rate()
   * zero-init uart structure
   * re-organized probing calls

   v6..v7
   fix review comments by Andy Shevchenko
   not applying Acked-by as the 1st change is big
   * handle unsupported tty modes correctly
   * remove extra check of platform_get_resource() result
   * propagate error code from devm_ioremap_resource()
   * drop uart.port.iobase for UPIO_MEM device

   v5..v6
   fix review comments by Arnd Bergmann
   * remove wildcards from compatible
   * update doc file
   * drop interrupt parent from doc file
   * replace uart w/ serial in device names in doc file

   fix review comments by Andy Shevchenko
   * exchange labels in switch block
   * replace iowrite8() with writeb()
   * compact comment to one line

   v4..v5
   * constify struct of_device_id
   * drop .owner from struct platform_driver
   * rewrite set_termios() baud rate hadnling as suggested by Alan Cox

   v3..v4
   * move DTS bindings to a different patch (8/21) as suggested by
     Heikki Krogerus

   v2..v3
   * no changes (except number 10/16 -> 12/21)

   v0..v2
   * register platform driver instead of platform device
   * use device tree
   * use devm helpers where possible

 .../bindings/serial/icpdas-lp8841-uart.txt         |  41 ++++++
 drivers/tty/serial/8250/8250_lp8841.c              | 156 +++++++++++++++++++++
 drivers/tty/serial/8250/Kconfig                    |  14 ++
 drivers/tty/serial/8250/Makefile                   |   2 +
 4 files changed, 213 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/serial/icpdas-lp8841-uart.txt
 create mode 100644 drivers/tty/serial/8250/8250_lp8841.c

diff --git a/Documentation/devicetree/bindings/serial/icpdas-lp8841-uart.txt b/Documentation/devicetree/bindings/serial/icpdas-lp8841-uart.txt
new file mode 100644
index 0000000..d6acd22
--- /dev/null
+++ b/Documentation/devicetree/bindings/serial/icpdas-lp8841-uart.txt
@@ -0,0 +1,41 @@
+* UART ports on ICP DAS LP-8841
+
+LP-8441, LP-8141 and LP-8041 are fully compatible.
+
+ICP DAS LP-8841 contains three additional serial ports interfaced via
+Analog Devices ADM213EA chips in addition to 3 serial ports on PXA CPU.
+
+The chips themselves are standard, they would work with 8250_core if
+properly connected. However, they are not connected normally. Al least
+some of their config pins are wired to a different address region. So
+the driver is board-specific.
+
+Required properties:
+- compatible : should be "icpdas,uart-lp8841"
+
+- reg : should provide 16 byte man IO memory region and 1 byte region for
+	termios
+
+- interrupts : should provide interrupt
+
+Optional property:
+- interrupt-parent : should provide a link to interrupt controller either
+		     explicitly or implicitly from a parent node
+
+Examples (from pxa27x-lp8x4x.dts):
+
+		serial@9050 {
+			compatible = "icpdas,uart-lp8841";
+			reg = <0x9050 0x10
+			       0x9030 0x02>;
+			interrupts = <13>;
+			status = "okay";
+		};
+
+		serial@9060 {
+			compatible = "icpdas,uart-lp8841";
+			reg = <0x9060 0x10
+			       0x9032 0x02>;
+			interrupts = <14>;
+			status = "okay";
+		};
diff --git a/drivers/tty/serial/8250/8250_lp8841.c b/drivers/tty/serial/8250/8250_lp8841.c
new file mode 100644
index 0000000..d3a72da
--- /dev/null
+++ b/drivers/tty/serial/8250/8250_lp8841.c
@@ -0,0 +1,156 @@
+/*  linux/drivers/tty/serial/8250/8250_lp8841.c
+ *
+ *  Support for 16550A serial ports on ICP DAS LP-8841
+ *
+ *  Copyright (C) 2013 Sergei Ianovich <ynvich@gmail.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/module.h>
+#include <linux/serial_8250.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+struct lp8841_serial_data {
+	int			line;
+	void __iomem		*ios_mem;
+};
+
+#define LP8841_DATA_LEN_MASK		0x3
+#define LP8841_DATA_LEN_SHIFT		3
+
+static void lp8841_serial_set_termios(struct uart_port *port,
+		struct ktermios *termios, struct ktermios *old)
+{
+	struct lp8841_serial_data *data = port->private_data;
+	unsigned int old_csize = old ? old->c_cflag & CSIZE : CS8;
+	unsigned int baud;
+	u8 value;
+
+	/* We only support CS7 and CS8 */
+	while ((termios->c_cflag & CSIZE) != CS7 &&
+	       (termios->c_cflag & CSIZE) != CS8) {
+		termios->c_cflag &= ~CSIZE;
+		termios->c_cflag |= old_csize;
+		old_csize = CS8;
+	}
+
+	value =  (termios->c_cflag & CSIZE) == CS7 ? 0 : 1;
+	value += (termios->c_cflag & CSTOPB) ? 1 : 0;
+	value += (termios->c_cflag & PARENB) ? 1 : 0;
+	value += (termios->c_cflag & PARODD) ? 0 : 1;
+#ifdef CMSPAR
+	value += (termios->c_cflag & CMSPAR) ? 1 : 0;
+#endif
+
+	value &=  LP8841_DATA_LEN_MASK;
+	value <<= LP8841_DATA_LEN_SHIFT;
+
+	baud = tty_termios_baud_rate(termios);
+
+	switch (baud) {
+	case 115200:
+		value |= 7;
+		break;
+	case 57600:
+		value |= 6;
+		break;
+	case 38400:
+		value |= 5;
+		break;
+	case 19200:
+		value |= 4;
+		break;
+	case 9600:
+		value |= 3;
+		break;
+	case 4800:
+		value |= 2;
+		break;
+	default:
+		tty_termios_encode_baud_rate(termios, 2400, 2400);
+	case 2400:
+		value |= 1;
+		break;
+	};
+	writeb(value, data->ios_mem);
+
+	serial8250_do_set_termios(port, termios, old);
+}
+
+static const struct of_device_id lp8841_serial_dt_ids[] = {
+	{ .compatible = "icpdas,lp8841-uart", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, lp8841_serial_dt_ids);
+
+static int lp8841_serial_probe(struct platform_device *pdev)
+{
+	struct uart_8250_port uart;
+	struct lp8841_serial_data *data;
+	struct resource *mmres, *mires;
+	int ret;
+
+	mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!mmres)
+		return -ENODEV;
+
+	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	mires = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	data->ios_mem = devm_ioremap_resource(&pdev->dev, mires);
+	if (IS_ERR(data->ios_mem))
+		return PTR_ERR(data->ios_mem);
+
+	memset(&uart, 0, sizeof(uart));
+	uart.port.iotype = UPIO_MEM;
+	uart.port.mapbase = mmres->start;
+	uart.port.regshift = 1;
+	uart.port.irq = platform_get_irq(pdev, 0);
+	uart.port.flags = UPF_IOREMAP;
+	uart.port.dev = &pdev->dev;
+	uart.port.uartclk = 14745600;
+	uart.port.set_termios = lp8841_serial_set_termios;
+	uart.port.private_data = data;
+
+	ret = serial8250_register_8250_port(&uart);
+	if (ret < 0)
+		return ret;
+
+	data->line = ret;
+
+	platform_set_drvdata(pdev, data);
+
+	return 0;
+}
+
+static int lp8841_serial_remove(struct platform_device *pdev)
+{
+	struct lp8841_serial_data *data = platform_get_drvdata(pdev);
+
+	serial8250_unregister_port(data->line);
+
+	return 0;
+}
+
+static struct platform_driver lp8841_serial_driver = {
+	.probe          = lp8841_serial_probe,
+	.remove         = lp8841_serial_remove,
+	.driver		= {
+		.name	= "uart-lp8841",
+		.of_match_table = lp8841_serial_dt_ids,
+	},
+};
+
+module_platform_driver(lp8841_serial_driver);
+
+MODULE_AUTHOR("Sergei Ianovich");
+MODULE_DESCRIPTION("8250 serial port module for LP-8841");
+MODULE_LICENSE("GPL");
diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
index 3b5cf9c..68640c1 100644
--- a/drivers/tty/serial/8250/Kconfig
+++ b/drivers/tty/serial/8250/Kconfig
@@ -394,3 +394,17 @@ config SERIAL_8250_PXA
 	help
 	  If you have a machine based on an Intel XScale PXA2xx CPU you
 	  can enable its onboard serial ports by enabling this option.
+
+	  If you choose M here, the module name will be 8250_pxa.
+
+config SERIAL_8250_LP8841
+	tristate "Support 16550A ports on ICP DAS LP-8841"
+	depends on SERIAL_8250 && MACH_PXA27X_DT
+	select LP8841_IRQ
+	help
+	  In addition to serial ports on PXA270 SoC, LP-8841 has 1 dual
+	  RS232/RS485 port, 1 RS485 port and 1 RS232 port.
+
+	  Say N here, unless you plan to run this kernel on a LP-8841 system.
+
+	  If you choose M here, the module name will be 8250_lp8841.
diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile
index d1e2f2d..10b4bf0 100644
--- a/drivers/tty/serial/8250/Makefile
+++ b/drivers/tty/serial/8250/Makefile
@@ -18,6 +18,7 @@ obj-$(CONFIG_SERIAL_8250_ACCENT)	+= 8250_accent.o
 obj-$(CONFIG_SERIAL_8250_BOCA)		+= 8250_boca.o
 obj-$(CONFIG_SERIAL_8250_EXAR_ST16C554)	+= 8250_exar_st16c554.o
 obj-$(CONFIG_SERIAL_8250_HUB6)		+= 8250_hub6.o
+obj-$(CONFIG_SERIAL_8250_LP8X4X)	+= 8250_lp8x4x.o
 obj-$(CONFIG_SERIAL_8250_FSL)		+= 8250_fsl.o
 obj-$(CONFIG_SERIAL_8250_DW)		+= 8250_dw.o
 obj-$(CONFIG_SERIAL_8250_EM)		+= 8250_em.o
@@ -30,5 +31,6 @@ obj-$(CONFIG_SERIAL_8250_INGENIC)	+= 8250_ingenic.o
 obj-$(CONFIG_SERIAL_8250_MID)		+= 8250_mid.o
 obj-$(CONFIG_SERIAL_OF_PLATFORM)	+= 8250_of.o
 obj-$(CONFIG_SERIAL_8250_PXA)		+= 8250_pxa.o
+obj-$(CONFIG_SERIAL_8250_LP8841)	+= 8250_lp8841.o
 
 CFLAGS_8250_ingenic.o += -I$(srctree)/scripts/dtc/libfdt
-- 
2.7.0

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

* Re: [PATCH v6] arm: pxa: support ICP DAS LP-8x4x FPGA irq
@ 2016-03-03 22:12                         ` Rob Herring
  0 siblings, 0 replies; 700+ messages in thread
From: Rob Herring @ 2016-03-03 22:12 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: linux-kernel, Arnd Bergmann, Marc Zyngier, Thomas Gleixner,
	Jason Cooper, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS

On Sat, Feb 27, 2016 at 06:56:01PM +0300, Sergei Ianovich wrote:
> ICP DAS LP-8x4x contains FPGA chip. The chip functions as an interrupt
> source providing 16 additional interrupts among other things. The
> interrupt lines are muxed to a GPIO pin of a 2nd level PXA-GPIO
> interrupt controller. GPIO pins of the 2nd level controller are in turn
> muxed to a CPU interrupt line.
> 
> Until pxa is completely converted to device tree, it is impossible
> to use IRQCHIP_DECLARE() and the irqdomain needs to added manually.
> Drivers for the on-CPU IRQs and GPIO-IRQs are loaded using
> postcore_initcall(). We need to have all irq domain drivers loaded prior
> to DT parsing in order to allow normal initialization of IRQ resources
> with DT.
> 
> Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
> Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
> CC: Arnd Bergmann <arnd@arndb.de>
> CC: Rob Herring <robh@kernel.org>
> CC: Marc Zyngier <marc.zyngier@arm.com>
> 
>    v5..v6
>    fixes according to Rob Herring review comments:
>    * drop wildcards in binding and file names
>    * rename alias 'fpga'->'fpga_irq'
> 
>    fixes according to Marc Zyngier review comments:
>    * use writeb/readb not iowrite8/ioread8
>    * redefine 2nd mask using inversion on 1st
>    * add comments
> 
>    v4..v5
>    * constify struct of_device_id
>    * drop irq number from handler signature
> 
>    v3.2..v4
>    * move DTS binding to a different patch (8/21)
> 
>    v3.1..v3.2
>    fixes to apply Linus Walleij's "Reviewed-by":
>    * add kerneldoc comment for state container struct
>    * rename irq -> hwirq for clarity
>    * drop overzealous error checks from the hotpaths
> 
>    v3..v3.1
>    fixes according to Linus Walleij review comments:
>    * update commit message
>    * use state container instead of global variables
>    * get hardware irq nums from irq_data, don't calculate them
>    * use BIT() macro
>    * add defines for system irq register masks
>    * replace cycle control variable with break
>    * use better names for resource variables
>    * add a linear domain instead of a legacy one
>    * use irq_create_mapping() instead of irq_alloc_desc()
> 
>    v2..v3
>    * no changes (except number 09/16 -> 11/21)
> 
>    v0..v2
>    * extract irqchip and move to drivers/irqchip/
>    * use device tree
>    * use devm helpers where possible
> ---
>  .../interrupt-controller/icpdas-lp8x4x-irq.txt     |  49 ++++
>  drivers/irqchip/Kconfig                            |   5 +
>  drivers/irqchip/Makefile                           |   1 +
>  drivers/irqchip/irq-lp8841.c                       | 246 +++++++++++++++++++++
>  4 files changed, 301 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/interrupt-controller/icpdas-lp8x4x-irq.txt
>  create mode 100644 drivers/irqchip/irq-lp8841.c
> 
> diff --git a/Documentation/devicetree/bindings/interrupt-controller/icpdas-lp8x4x-irq.txt b/Documentation/devicetree/bindings/interrupt-controller/icpdas-lp8x4x-irq.txt
> new file mode 100644
> index 0000000..a72109b
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/interrupt-controller/icpdas-lp8x4x-irq.txt
> @@ -0,0 +1,49 @@
> +ICP DAS LP-8841 FPGA Interrupt Controller
> +
> +ICP DAS LP-8841 contains FPGA chip. The chip functions as a interrupt
> +source providing 16 additional interrupts among other things.
> +
> +Required properties:
> +- compatible : should be "icpdas,lp8x4x-irq"

You've still got wildcards here. Seems to be an oversight as the example 
and code have "icpdas,lp8841-irq".

> +
> +- reg: physical base address of the controller and length of memory mapped
> +  region.
> +
> +- interrupt-controller : identifies the node as an interrupt controller
> +
> +- #interrupt-cells : should be 1
> +
> +- interrupts : should provide interrupt
> +
> +Optional properties:
> +
> +- interrupt-parent : should provide a link to interrupt controller either
> +		     explicitly and implicitly from a parent node
> +
> +Example:
> +
> +fpgairq: irq@9006 {

Still not right... interrupt-controller@9006

> +	compatible = "icpdas,lp8841-irq";
> +	reg = <0x9006 0x16>;
> +	interrupt-parent = <&gpio>;
> +	interrupts = <3 IRQ_TYPE_EDGE_FALLING>;
> +	#interrupt-cells = <1>;
> +	interrupt-controller;
> +	status = "okay";
> +};
> +
> +serial@9050 {
> +	compatible = "icpdas,lp8841-uart";
> +	reg =  <0x9050 0x10
> +		0x9030 0x02>;
> +	interrupts = <13>;
> +	status = "okay";
> +};
> +
> +serial@9060 {
> +	compatible = "icpdas,lp8841-uart";
> +	reg =  <0x9060 0x10
> +		0x9032 0x02>;
> +	interrupts = <14>;
> +	status = "okay";
> +};

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

* Re: [PATCH v6] arm: pxa: support ICP DAS LP-8x4x FPGA irq
@ 2016-03-03 22:12                         ` Rob Herring
  0 siblings, 0 replies; 700+ messages in thread
From: Rob Herring @ 2016-03-03 22:12 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA, Arnd Bergmann, Marc Zyngier,
	Thomas Gleixner, Jason Cooper, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS

On Sat, Feb 27, 2016 at 06:56:01PM +0300, Sergei Ianovich wrote:
> ICP DAS LP-8x4x contains FPGA chip. The chip functions as an interrupt
> source providing 16 additional interrupts among other things. The
> interrupt lines are muxed to a GPIO pin of a 2nd level PXA-GPIO
> interrupt controller. GPIO pins of the 2nd level controller are in turn
> muxed to a CPU interrupt line.
> 
> Until pxa is completely converted to device tree, it is impossible
> to use IRQCHIP_DECLARE() and the irqdomain needs to added manually.
> Drivers for the on-CPU IRQs and GPIO-IRQs are loaded using
> postcore_initcall(). We need to have all irq domain drivers loaded prior
> to DT parsing in order to allow normal initialization of IRQ resources
> with DT.
> 
> Signed-off-by: Sergei Ianovich <ynvich-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> Reviewed-by: Linus Walleij <linus.walleij-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> CC: Arnd Bergmann <arnd-r2nGTMty4D4@public.gmane.org>
> CC: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
> CC: Marc Zyngier <marc.zyngier-5wv7dgnIgG8@public.gmane.org>
> 
>    v5..v6
>    fixes according to Rob Herring review comments:
>    * drop wildcards in binding and file names
>    * rename alias 'fpga'->'fpga_irq'
> 
>    fixes according to Marc Zyngier review comments:
>    * use writeb/readb not iowrite8/ioread8
>    * redefine 2nd mask using inversion on 1st
>    * add comments
> 
>    v4..v5
>    * constify struct of_device_id
>    * drop irq number from handler signature
> 
>    v3.2..v4
>    * move DTS binding to a different patch (8/21)
> 
>    v3.1..v3.2
>    fixes to apply Linus Walleij's "Reviewed-by":
>    * add kerneldoc comment for state container struct
>    * rename irq -> hwirq for clarity
>    * drop overzealous error checks from the hotpaths
> 
>    v3..v3.1
>    fixes according to Linus Walleij review comments:
>    * update commit message
>    * use state container instead of global variables
>    * get hardware irq nums from irq_data, don't calculate them
>    * use BIT() macro
>    * add defines for system irq register masks
>    * replace cycle control variable with break
>    * use better names for resource variables
>    * add a linear domain instead of a legacy one
>    * use irq_create_mapping() instead of irq_alloc_desc()
> 
>    v2..v3
>    * no changes (except number 09/16 -> 11/21)
> 
>    v0..v2
>    * extract irqchip and move to drivers/irqchip/
>    * use device tree
>    * use devm helpers where possible
> ---
>  .../interrupt-controller/icpdas-lp8x4x-irq.txt     |  49 ++++
>  drivers/irqchip/Kconfig                            |   5 +
>  drivers/irqchip/Makefile                           |   1 +
>  drivers/irqchip/irq-lp8841.c                       | 246 +++++++++++++++++++++
>  4 files changed, 301 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/interrupt-controller/icpdas-lp8x4x-irq.txt
>  create mode 100644 drivers/irqchip/irq-lp8841.c
> 
> diff --git a/Documentation/devicetree/bindings/interrupt-controller/icpdas-lp8x4x-irq.txt b/Documentation/devicetree/bindings/interrupt-controller/icpdas-lp8x4x-irq.txt
> new file mode 100644
> index 0000000..a72109b
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/interrupt-controller/icpdas-lp8x4x-irq.txt
> @@ -0,0 +1,49 @@
> +ICP DAS LP-8841 FPGA Interrupt Controller
> +
> +ICP DAS LP-8841 contains FPGA chip. The chip functions as a interrupt
> +source providing 16 additional interrupts among other things.
> +
> +Required properties:
> +- compatible : should be "icpdas,lp8x4x-irq"

You've still got wildcards here. Seems to be an oversight as the example 
and code have "icpdas,lp8841-irq".

> +
> +- reg: physical base address of the controller and length of memory mapped
> +  region.
> +
> +- interrupt-controller : identifies the node as an interrupt controller
> +
> +- #interrupt-cells : should be 1
> +
> +- interrupts : should provide interrupt
> +
> +Optional properties:
> +
> +- interrupt-parent : should provide a link to interrupt controller either
> +		     explicitly and implicitly from a parent node
> +
> +Example:
> +
> +fpgairq: irq@9006 {

Still not right... interrupt-controller@9006

> +	compatible = "icpdas,lp8841-irq";
> +	reg = <0x9006 0x16>;
> +	interrupt-parent = <&gpio>;
> +	interrupts = <3 IRQ_TYPE_EDGE_FALLING>;
> +	#interrupt-cells = <1>;
> +	interrupt-controller;
> +	status = "okay";
> +};
> +
> +serial@9050 {
> +	compatible = "icpdas,lp8841-uart";
> +	reg =  <0x9050 0x10
> +		0x9030 0x02>;
> +	interrupts = <13>;
> +	status = "okay";
> +};
> +
> +serial@9060 {
> +	compatible = "icpdas,lp8841-uart";
> +	reg =  <0x9060 0x10
> +		0x9032 0x02>;
> +	interrupts = <14>;
> +	status = "okay";
> +};
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH v10] serial: support for 16550A serial ports on LP-8x4x
  2016-03-01 21:25                             ` Sergei Ianovich
@ 2016-03-05  4:26                               ` Rob Herring
  -1 siblings, 0 replies; 700+ messages in thread
From: Rob Herring @ 2016-03-05  4:26 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: linux-kernel, Alan Cox, Arnd Bergmann, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Greg Kroah-Hartman, Jiri Slaby,
	Heikki Krogerus, Andy Shevchenko, Masahiro Yamada, Peter Hurley,
	Paul Burton, Mans Rullgard, Scott Wood, Paul Gortmaker,
	Joachim Eastwood, Peter Ujfalusi,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	open list:SERIAL DRIVERS

On Wed, Mar 02, 2016 at 12:25:35AM +0300, Sergei Ianovich wrote:
> The patch adds support for 3 additional LP-8x4x built-in serial
> ports.
> 
> The device can also host up to 8 extension cards with 4 serial ports
> on each card for a total of 35 ports. However, I don't have
> the hardware to test extension cards, so they are not supported, yet.

That's a lot of serial ports...

[...]

> diff --git a/Documentation/devicetree/bindings/serial/icpdas-lp8841-uart.txt b/Documentation/devicetree/bindings/serial/icpdas-lp8841-uart.txt
> new file mode 100644
> index 0000000..d6acd22
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/serial/icpdas-lp8841-uart.txt
> @@ -0,0 +1,41 @@
> +* UART ports on ICP DAS LP-8841
> +
> +LP-8441, LP-8141 and LP-8041 are fully compatible.
> +
> +ICP DAS LP-8841 contains three additional serial ports interfaced via
> +Analog Devices ADM213EA chips in addition to 3 serial ports on PXA CPU.
> +
> +The chips themselves are standard, they would work with 8250_core if

Describe in h/w terms how they are different, not what Linux driver 
won't work.

> +properly connected. However, they are not connected normally. Al least

s/Al/At/

> +some of their config pins are wired to a different address region. So
> +the driver is board-specific.
> +
> +Required properties:
> +- compatible : should be "icpdas,uart-lp8841"
> +
> +- reg : should provide 16 byte man IO memory region and 1 byte region for

What is "man IO"?

> +	termios

termios is a Linux term.

> +
> +- interrupts : should provide interrupt

Perhaps you should include other properties standard for 8250 such as 
access size or shift. Possibly if the non-standard bits are already 
configured, the UART could be used for earlycon?

> +
> +Optional property:
> +- interrupt-parent : should provide a link to interrupt controller either
> +		     explicitly or implicitly from a parent node
> +
> +Examples (from pxa27x-lp8x4x.dts):
> +
> +		serial@9050 {
> +			compatible = "icpdas,uart-lp8841";
> +			reg = <0x9050 0x10
> +			       0x9030 0x02>;
> +			interrupts = <13>;
> +			status = "okay";
> +		};
> +
> +		serial@9060 {
> +			compatible = "icpdas,uart-lp8841";
> +			reg = <0x9060 0x10
> +			       0x9032 0x02>;
> +			interrupts = <14>;
> +			status = "okay";
> +		};

[...]

> diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
> index 3b5cf9c..68640c1 100644
> --- a/drivers/tty/serial/8250/Kconfig
> +++ b/drivers/tty/serial/8250/Kconfig
> @@ -394,3 +394,17 @@ config SERIAL_8250_PXA
>  	help
>  	  If you have a machine based on an Intel XScale PXA2xx CPU you
>  	  can enable its onboard serial ports by enabling this option.
> +
> +	  If you choose M here, the module name will be 8250_pxa.
> +
> +config SERIAL_8250_LP8841
> +	tristate "Support 16550A ports on ICP DAS LP-8841"
> +	depends on SERIAL_8250 && MACH_PXA27X_DT
> +	select LP8841_IRQ

Generally, drivers don't select their interrupt controller.

> +	help
> +	  In addition to serial ports on PXA270 SoC, LP-8841 has 1 dual
> +	  RS232/RS485 port, 1 RS485 port and 1 RS232 port.
> +
> +	  Say N here, unless you plan to run this kernel on a LP-8841 system.
> +
> +	  If you choose M here, the module name will be 8250_lp8841.

> diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile
> index d1e2f2d..10b4bf0 100644
> --- a/drivers/tty/serial/8250/Makefile
> +++ b/drivers/tty/serial/8250/Makefile
> @@ -18,6 +18,7 @@ obj-$(CONFIG_SERIAL_8250_ACCENT)	+= 8250_accent.o

>  obj-$(CONFIG_SERIAL_8250_BOCA)		+= 8250_boca.o
>  obj-$(CONFIG_SERIAL_8250_EXAR_ST16C554)	+= 8250_exar_st16c554.o
>  obj-$(CONFIG_SERIAL_8250_HUB6)		+= 8250_hub6.o
> +obj-$(CONFIG_SERIAL_8250_LP8X4X)	+= 8250_lp8x4x.o

This should be dropped.

>  obj-$(CONFIG_SERIAL_8250_FSL)		+= 8250_fsl.o
>  obj-$(CONFIG_SERIAL_8250_DW)		+= 8250_dw.o
>  obj-$(CONFIG_SERIAL_8250_EM)		+= 8250_em.o
> @@ -30,5 +31,6 @@ obj-$(CONFIG_SERIAL_8250_INGENIC)	+= 8250_ingenic.o
>  obj-$(CONFIG_SERIAL_8250_MID)		+= 8250_mid.o
>  obj-$(CONFIG_SERIAL_OF_PLATFORM)	+= 8250_of.o
>  obj-$(CONFIG_SERIAL_8250_PXA)		+= 8250_pxa.o
> +obj-$(CONFIG_SERIAL_8250_LP8841)	+= 8250_lp8841.o

This should be in alphabetical order. OF_PLATFORM is not for legacy 
reasons I think.

>  
>  CFLAGS_8250_ingenic.o += -I$(srctree)/scripts/dtc/libfdt
> -- 
> 2.7.0
> 

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

* Re: [PATCH v10] serial: support for 16550A serial ports on LP-8x4x
@ 2016-03-05  4:26                               ` Rob Herring
  0 siblings, 0 replies; 700+ messages in thread
From: Rob Herring @ 2016-03-05  4:26 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: linux-kernel, Alan Cox, Arnd Bergmann, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Greg Kroah-Hartman, Jiri Slaby,
	Heikki Krogerus, Andy Shevchenko, Masahiro Yamada, Peter Hurley,
	Paul Burton, Mans Rullgard, Scott Wood, Paul Gortmaker,
	Joachim Eastwood, Peter Ujfalusi,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	SERIAL

On Wed, Mar 02, 2016 at 12:25:35AM +0300, Sergei Ianovich wrote:
> The patch adds support for 3 additional LP-8x4x built-in serial
> ports.
> 
> The device can also host up to 8 extension cards with 4 serial ports
> on each card for a total of 35 ports. However, I don't have
> the hardware to test extension cards, so they are not supported, yet.

That's a lot of serial ports...

[...]

> diff --git a/Documentation/devicetree/bindings/serial/icpdas-lp8841-uart.txt b/Documentation/devicetree/bindings/serial/icpdas-lp8841-uart.txt
> new file mode 100644
> index 0000000..d6acd22
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/serial/icpdas-lp8841-uart.txt
> @@ -0,0 +1,41 @@
> +* UART ports on ICP DAS LP-8841
> +
> +LP-8441, LP-8141 and LP-8041 are fully compatible.
> +
> +ICP DAS LP-8841 contains three additional serial ports interfaced via
> +Analog Devices ADM213EA chips in addition to 3 serial ports on PXA CPU.
> +
> +The chips themselves are standard, they would work with 8250_core if

Describe in h/w terms how they are different, not what Linux driver 
won't work.

> +properly connected. However, they are not connected normally. Al least

s/Al/At/

> +some of their config pins are wired to a different address region. So
> +the driver is board-specific.
> +
> +Required properties:
> +- compatible : should be "icpdas,uart-lp8841"
> +
> +- reg : should provide 16 byte man IO memory region and 1 byte region for

What is "man IO"?

> +	termios

termios is a Linux term.

> +
> +- interrupts : should provide interrupt

Perhaps you should include other properties standard for 8250 such as 
access size or shift. Possibly if the non-standard bits are already 
configured, the UART could be used for earlycon?

> +
> +Optional property:
> +- interrupt-parent : should provide a link to interrupt controller either
> +		     explicitly or implicitly from a parent node
> +
> +Examples (from pxa27x-lp8x4x.dts):
> +
> +		serial@9050 {
> +			compatible = "icpdas,uart-lp8841";
> +			reg = <0x9050 0x10
> +			       0x9030 0x02>;
> +			interrupts = <13>;
> +			status = "okay";
> +		};
> +
> +		serial@9060 {
> +			compatible = "icpdas,uart-lp8841";
> +			reg = <0x9060 0x10
> +			       0x9032 0x02>;
> +			interrupts = <14>;
> +			status = "okay";
> +		};

[...]

> diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
> index 3b5cf9c..68640c1 100644
> --- a/drivers/tty/serial/8250/Kconfig
> +++ b/drivers/tty/serial/8250/Kconfig
> @@ -394,3 +394,17 @@ config SERIAL_8250_PXA
>  	help
>  	  If you have a machine based on an Intel XScale PXA2xx CPU you
>  	  can enable its onboard serial ports by enabling this option.
> +
> +	  If you choose M here, the module name will be 8250_pxa.
> +
> +config SERIAL_8250_LP8841
> +	tristate "Support 16550A ports on ICP DAS LP-8841"
> +	depends on SERIAL_8250 && MACH_PXA27X_DT
> +	select LP8841_IRQ

Generally, drivers don't select their interrupt controller.

> +	help
> +	  In addition to serial ports on PXA270 SoC, LP-8841 has 1 dual
> +	  RS232/RS485 port, 1 RS485 port and 1 RS232 port.
> +
> +	  Say N here, unless you plan to run this kernel on a LP-8841 system.
> +
> +	  If you choose M here, the module name will be 8250_lp8841.

> diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile
> index d1e2f2d..10b4bf0 100644
> --- a/drivers/tty/serial/8250/Makefile
> +++ b/drivers/tty/serial/8250/Makefile
> @@ -18,6 +18,7 @@ obj-$(CONFIG_SERIAL_8250_ACCENT)	+= 8250_accent.o

>  obj-$(CONFIG_SERIAL_8250_BOCA)		+= 8250_boca.o
>  obj-$(CONFIG_SERIAL_8250_EXAR_ST16C554)	+= 8250_exar_st16c554.o
>  obj-$(CONFIG_SERIAL_8250_HUB6)		+= 8250_hub6.o
> +obj-$(CONFIG_SERIAL_8250_LP8X4X)	+= 8250_lp8x4x.o

This should be dropped.

>  obj-$(CONFIG_SERIAL_8250_FSL)		+= 8250_fsl.o
>  obj-$(CONFIG_SERIAL_8250_DW)		+= 8250_dw.o
>  obj-$(CONFIG_SERIAL_8250_EM)		+= 8250_em.o
> @@ -30,5 +31,6 @@ obj-$(CONFIG_SERIAL_8250_INGENIC)	+= 8250_ingenic.o
>  obj-$(CONFIG_SERIAL_8250_MID)		+= 8250_mid.o
>  obj-$(CONFIG_SERIAL_OF_PLATFORM)	+= 8250_of.o
>  obj-$(CONFIG_SERIAL_8250_PXA)		+= 8250_pxa.o
> +obj-$(CONFIG_SERIAL_8250_LP8841)	+= 8250_lp8841.o

This should be in alphabetical order. OF_PLATFORM is not for legacy 
reasons I think.

>  
>  CFLAGS_8250_ingenic.o += -I$(srctree)/scripts/dtc/libfdt
> -- 
> 2.7.0
> 

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

* Re: [PATCH v6] mtd: support BB SRAM on ICP DAS LP-8x4x
@ 2016-03-08  0:19                         ` Brian Norris
  0 siblings, 0 replies; 700+ messages in thread
From: Brian Norris @ 2016-03-08  0:19 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: linux-kernel, Rob Herring, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, David Woodhouse, Jeremy Kerr,
	Neelesh Gupta, Michael Ellerman, Cyril Bur, Joel Stanley,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	open list:MEMORY TECHNOLOGY DEVICES [MTD]

Hi Sergei,

A few more issues...

On Tue, Feb 23, 2016 at 09:58:01PM +0300, Sergei Ianovich wrote:
> This provides an MTD device driver for 512kB of battery backed up SRAM
> on ICPDAS LP-8X4X programmable automation controllers.
> 
> SRAM chip is connected via FPGA and is not accessible without a driver,
> unlike flash memory which is wired to CPU MMU.
> 
> This SRAM becomes an excellent persisent storage of volatile process
> data like counter values and sensor statuses. Storing those data in
> flash or mmc card is not a viable solution.
> 
> Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
> Reviewed-by: Brian Norris <computersforpeace@gmail.com>
> CC: Rob Herring <robh@kernel.org>
> 
>    v5..v6
>    * replace wildcards in compatible and module name
>    * drop obsolete mtd_part_parser_data.of_node
> 
>    v4..v5
>    * remove .owner from struct platform_driver
>    * constify struct of_device_id
>     for further Brian Norris comments:
>    * drop unused property from doc file
>    * move defconfig update to a different file
>    * drop extra match w/ of_match_device()
> 
>    v3..v4 for Brian Norris 'Reviewed-by'
>    * add doc file for DT binding
>    * move DTS binding to a different patch (8/21)
>    * drop unused include directive
>    * drop safely unused callback
>    * drop non-default partion probe types
>    * drop duplicate error checks
>    * drop duplicate error reporting
>    * fixed error message on MTD registeration
>    * fixed module removal routine
> 
>    v2..v3
>    * no changes (except number 08/16 -> 10/21)
> 
>    v0..v2
>    * use device tree
>    * use devm helpers where possible
> ---
>  .../devicetree/bindings/mtd/icpdas-lp8841-sram.txt |  23 +++
>  drivers/mtd/devices/Kconfig                        |  14 ++
>  drivers/mtd/devices/Makefile                       |   1 +
>  drivers/mtd/devices/sram_lp8841.c                  | 198 +++++++++++++++++++++
>  4 files changed, 236 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/mtd/icpdas-lp8841-sram.txt
>  create mode 100644 drivers/mtd/devices/sram_lp8841.c
> 
> diff --git a/Documentation/devicetree/bindings/mtd/icpdas-lp8841-sram.txt b/Documentation/devicetree/bindings/mtd/icpdas-lp8841-sram.txt
> new file mode 100644
> index 0000000..3c1007a
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/mtd/icpdas-lp8841-sram.txt
> @@ -0,0 +1,23 @@
> +512kB battery backed up SRAM on ICP DAS LP-8841 industrial computers
> +
> +LP-8441, LP-8141, and LP-8041 differ from LP-8841 only in expansion
> +slot count.
> +
> +Required properties:
> +- compatible : should be "icpdas,lp8841-sram"
> +
> +- reg: physical base addresses and region lengths of
> +       * IO memory range
> +       * SRAM page selector
> +
> +SRAM chip is connected via FPGA and is not accessible without a driver,
> +unlike flash memory which is wired to CPU MMU. Driver is essentially
> +an address translation routine.
> +
> +Example:
> +
> +	sram@a000 {
> +		compatible = "icpdas,lp8841-sram";
> +		reg = <0xa000 0x1000
> +		       0x901e 0x1>;
> +	};
> diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig
> index f73c416..ecf5733 100644
> --- a/drivers/mtd/devices/Kconfig
> +++ b/drivers/mtd/devices/Kconfig
> @@ -233,4 +233,18 @@ config BCH_CONST_T
>  	default 4
>  endif
>  
> +config MTD_SRAM_LP8841
> +	tristate "SRAM on ICP DAS LP-8841"
> +	depends on OF && ARCH_PXA
> +       ---help---
> +	 This provides an MTD device driver for 512kiB of battery backed up SRAM
> +	 on ICPDAS LP-8X41 programmable automation controllers.
> +
> +	 SRAM chip is connected via FPGA and is not accessible without a driver,
> +	 unlike flash memory which is wired to CPU MMU.
> +
> +	 Say N, unless you plan to run this kernel on LP-8X41.
> +
> +	 If you say M, the module will be called sram_lp8841.
> +
>  endmenu
> diff --git a/drivers/mtd/devices/Makefile b/drivers/mtd/devices/Makefile
> index 7912d3a..46df5d6 100644
> --- a/drivers/mtd/devices/Makefile
> +++ b/drivers/mtd/devices/Makefile
> @@ -17,6 +17,7 @@ obj-$(CONFIG_MTD_SST25L)	+= sst25l.o
>  obj-$(CONFIG_MTD_BCM47XXSFLASH)	+= bcm47xxsflash.o
>  obj-$(CONFIG_MTD_ST_SPI_FSM)    += st_spi_fsm.o
>  obj-$(CONFIG_MTD_POWERNV_FLASH)	+= powernv_flash.o
> +obj-$(CONFIG_MTD_SRAM_LP8841)	+= sram_lp8841.o
>  
>  
>  CFLAGS_docg3.o			+= -I$(src)
> diff --git a/drivers/mtd/devices/sram_lp8841.c b/drivers/mtd/devices/sram_lp8841.c
> new file mode 100644
> index 0000000..5d5d942
> --- /dev/null
> +++ b/drivers/mtd/devices/sram_lp8841.c
> @@ -0,0 +1,198 @@
> +/*
> + *  linux/drivers/mtd/devices/sram_lp8841.c
> + *
> + *  MTD Driver for SRAM on ICP DAS LP-8841
> + *  Copyright (C) 2013 Sergei Ianovich <ynvich@gmail.com>
> + *
> + *  This program is free software; you can redistribute it and/or modify
> + *  it under the terms of the GNU General Public License version 2 as
> + *  published by the Free Software Foundation or any later version.
> + */
> +
> +#include <linux/init.h>
> +#include <linux/io.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/mtd/map.h>
> +#include <linux/mtd/mtd.h>
> +#include <linux/mtd/partitions.h>
> +#include <linux/platform_device.h>
> +#include <linux/of_device.h>
> +#include <linux/slab.h>
> +#include <linux/string_helpers.h>
> +#include <linux/types.h>
> +
> +struct lp8841_sram_info {
> +	void __iomem	*bank;
> +	void __iomem	*virt;
> +	struct mutex	lock;
> +	unsigned	active_bank;
> +	struct mtd_info	mtd;
> +};
> +
> +static int
> +lp8841_sram_erase(struct mtd_info *mtd, struct erase_info *instr)
> +{
> +	struct lp8841_sram_info *info = mtd->priv;
> +	unsigned bank = instr->addr >> 11;
> +	unsigned offset = (instr->addr & 0x7ff) << 1;
> +	loff_t i;
> +
> +	mutex_lock(&info->lock);
> +	if (unlikely(bank != info->active_bank)) {
> +		info->active_bank = bank;
> +		iowrite8(bank, info->bank);
> +	}
> +	for (i = 0; i < instr->len; i++) {
> +		iowrite8(0xff, info->virt + offset);
> +		offset += 2;
> +		if (unlikely(offset == 0)) {
> +			info->active_bank++;
> +			iowrite8(info->active_bank, info->bank);
> +		}
> +	}
> +	mutex_unlock(&info->lock);
> +	instr->state = MTD_ERASE_DONE;
> +	mtd_erase_callback(instr);
> +
> +	return 0;
> +}
> +
> +static int
> +lp8841_sram_write(struct mtd_info *mtd, loff_t to, size_t len,
> +		size_t *retlen, const u_char *b)
> +{
> +	struct lp8841_sram_info *info = mtd->priv;
> +	unsigned bank = to >> 11;
> +	unsigned offset = (to & 0x7ff) << 1;
> +	loff_t i;
> +
> +	mutex_lock(&info->lock);
> +	if (unlikely(bank != info->active_bank)) {
> +		info->active_bank = bank;
> +		iowrite8(bank, info->bank);
> +	}
> +	for (i = 0; i < len; i++) {
> +		iowrite8(b[i], info->virt + offset);
> +		offset += 2;
> +		if (unlikely(offset == 0)) {
> +			info->active_bank++;
> +			iowrite8(info->active_bank, info->bank);
> +		}
> +	}
> +	mutex_unlock(&info->lock);
> +	*retlen = len;
> +	return 0;
> +}
> +
> +static int
> +lp8841_sram_read(struct mtd_info *mtd, loff_t from, size_t len,
> +		size_t *retlen, u_char *b)
> +{
> +	struct lp8841_sram_info *info = mtd->priv;
> +	unsigned bank = from >> 11;
> +	unsigned offset = (from & 0x7ff) << 1;
> +	loff_t i;
> +
> +	mutex_lock(&info->lock);
> +	if (unlikely(bank != info->active_bank)) {
> +		info->active_bank = bank;
> +		iowrite8(bank, info->bank);
> +	}
> +	for (i = 0; i < len; i++) {
> +		b[i] = ioread8(info->virt + offset);
> +		offset += 2;
> +		if (unlikely(offset == 0)) {
> +			info->active_bank++;
> +			iowrite8(info->active_bank, info->bank);
> +		}
> +	}
> +	mutex_unlock(&info->lock);
> +	*retlen = len;
> +	return 0;
> +}
> +
> +static const struct of_device_id of_flash_match[] = {
> +	{
> +		.compatible	= "icpdas,lp8841-sram",
> +	},
> +	{ },
> +};
> +MODULE_DEVICE_TABLE(of, of_flash_match);
> +
> +static int
> +lp8841_sram_probe(struct platform_device *pdev)
> +{
> +	struct lp8841_sram_info *info;
> +	struct resource *res_virt, *res_bank;
> +	char sz_str[16];
> +	struct mtd_part_parser_data ppdata;

You don't need this struct any more.

> +	int err = 0;
> +
> +	info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
> +	if (!info)
> +		return -ENOMEM;
> +
> +	res_virt = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	info->virt =  devm_ioremap_resource(&pdev->dev, res_virt);
> +	if (IS_ERR(info->virt))
> +		return PTR_ERR(info->virt);
> +
> +	res_bank = platform_get_resource(pdev, IORESOURCE_MEM, 1);
> +	info->bank = devm_ioremap_resource(&pdev->dev, res_bank);
> +	if (IS_ERR(info->bank))
> +		return PTR_ERR(info->bank);
> +
> +	info->mtd.priv = info;
> +	info->mtd.name = "SRAM";
> +	info->mtd.type = MTD_RAM;
> +	info->mtd.flags = MTD_CAP_RAM;
> +	info->mtd.size = resource_size(res_virt) << 7;
> +	info->mtd.erasesize = 512;
> +	info->mtd.writesize = 4;

Can you please set mtd.writebufsize to an appropriate value too? Maybe
it's just the same as writesize.

> +	info->mtd._erase = lp8841_sram_erase;
> +	info->mtd._write = lp8841_sram_write;
> +	info->mtd._read = lp8841_sram_read;
> +	info->mtd.owner = THIS_MODULE;

If you set info->mtd.dev.parent (please do), you don't need the above
line.

> +
> +	mutex_init(&info->lock);
> +	iowrite8(info->active_bank, info->bank);
> +	platform_set_drvdata(pdev, info);
> +
> +	err = mtd_device_parse_register(&info->mtd, NULL, &ppdata,
> +			NULL, 0);

This can just be:

	err = mtd_device_register(&info->mtd, NULL, 0);

> +
> +	if (err < 0) {
> +		dev_err(&pdev->dev, "failed to register MTD\n");
> +		return err;
> +	}
> +
> +	string_get_size(info->mtd.size, 1, STRING_UNITS_2, sz_str,
> +			sizeof(sz_str));
> +	dev_info(&pdev->dev, "using %s SRAM on LP-8X4X as %s\n", sz_str,
> +			dev_name(&info->mtd.dev));
> +	return 0;
> +}
> +
> +static int
> +lp8841_sram_remove(struct platform_device *dev)
> +{
> +	struct lp8841_sram_info *info = platform_get_drvdata(dev);
> +
> +	return mtd_device_unregister(&info->mtd);
> +}
> +
> +static struct platform_driver lp8841_sram_driver = {
> +	.driver = {
> +		.name		= "sram-lp8841",
> +		.of_match_table = of_flash_match,
> +	},
> +	.probe		= lp8841_sram_probe,
> +	.remove		= lp8841_sram_remove,
> +};
> +
> +module_platform_driver(lp8841_sram_driver);
> +
> +MODULE_LICENSE("GPL");
> +MODULE_AUTHOR("Sergei Ianovich");
> +MODULE_DESCRIPTION("MTD driver for SRAM on ICPDAS LP-8841");

Brian

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

* Re: [PATCH v6] mtd: support BB SRAM on ICP DAS LP-8x4x
@ 2016-03-08  0:19                         ` Brian Norris
  0 siblings, 0 replies; 700+ messages in thread
From: Brian Norris @ 2016-03-08  0:19 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA, Rob Herring, Rob Herring,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	David Woodhouse, Jeremy Kerr, Neelesh Gupta, Michael Ellerman,
	Cyril Bur, Joel Stanley,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	open list:MEMORY TECHNOLOGY DEVICES [MTD]

Hi Sergei,

A few more issues...

On Tue, Feb 23, 2016 at 09:58:01PM +0300, Sergei Ianovich wrote:
> This provides an MTD device driver for 512kB of battery backed up SRAM
> on ICPDAS LP-8X4X programmable automation controllers.
> 
> SRAM chip is connected via FPGA and is not accessible without a driver,
> unlike flash memory which is wired to CPU MMU.
> 
> This SRAM becomes an excellent persisent storage of volatile process
> data like counter values and sensor statuses. Storing those data in
> flash or mmc card is not a viable solution.
> 
> Signed-off-by: Sergei Ianovich <ynvich-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> Reviewed-by: Brian Norris <computersforpeace-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> CC: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
> 
>    v5..v6
>    * replace wildcards in compatible and module name
>    * drop obsolete mtd_part_parser_data.of_node
> 
>    v4..v5
>    * remove .owner from struct platform_driver
>    * constify struct of_device_id
>     for further Brian Norris comments:
>    * drop unused property from doc file
>    * move defconfig update to a different file
>    * drop extra match w/ of_match_device()
> 
>    v3..v4 for Brian Norris 'Reviewed-by'
>    * add doc file for DT binding
>    * move DTS binding to a different patch (8/21)
>    * drop unused include directive
>    * drop safely unused callback
>    * drop non-default partion probe types
>    * drop duplicate error checks
>    * drop duplicate error reporting
>    * fixed error message on MTD registeration
>    * fixed module removal routine
> 
>    v2..v3
>    * no changes (except number 08/16 -> 10/21)
> 
>    v0..v2
>    * use device tree
>    * use devm helpers where possible
> ---
>  .../devicetree/bindings/mtd/icpdas-lp8841-sram.txt |  23 +++
>  drivers/mtd/devices/Kconfig                        |  14 ++
>  drivers/mtd/devices/Makefile                       |   1 +
>  drivers/mtd/devices/sram_lp8841.c                  | 198 +++++++++++++++++++++
>  4 files changed, 236 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/mtd/icpdas-lp8841-sram.txt
>  create mode 100644 drivers/mtd/devices/sram_lp8841.c
> 
> diff --git a/Documentation/devicetree/bindings/mtd/icpdas-lp8841-sram.txt b/Documentation/devicetree/bindings/mtd/icpdas-lp8841-sram.txt
> new file mode 100644
> index 0000000..3c1007a
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/mtd/icpdas-lp8841-sram.txt
> @@ -0,0 +1,23 @@
> +512kB battery backed up SRAM on ICP DAS LP-8841 industrial computers
> +
> +LP-8441, LP-8141, and LP-8041 differ from LP-8841 only in expansion
> +slot count.
> +
> +Required properties:
> +- compatible : should be "icpdas,lp8841-sram"
> +
> +- reg: physical base addresses and region lengths of
> +       * IO memory range
> +       * SRAM page selector
> +
> +SRAM chip is connected via FPGA and is not accessible without a driver,
> +unlike flash memory which is wired to CPU MMU. Driver is essentially
> +an address translation routine.
> +
> +Example:
> +
> +	sram@a000 {
> +		compatible = "icpdas,lp8841-sram";
> +		reg = <0xa000 0x1000
> +		       0x901e 0x1>;
> +	};
> diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig
> index f73c416..ecf5733 100644
> --- a/drivers/mtd/devices/Kconfig
> +++ b/drivers/mtd/devices/Kconfig
> @@ -233,4 +233,18 @@ config BCH_CONST_T
>  	default 4
>  endif
>  
> +config MTD_SRAM_LP8841
> +	tristate "SRAM on ICP DAS LP-8841"
> +	depends on OF && ARCH_PXA
> +       ---help---
> +	 This provides an MTD device driver for 512kiB of battery backed up SRAM
> +	 on ICPDAS LP-8X41 programmable automation controllers.
> +
> +	 SRAM chip is connected via FPGA and is not accessible without a driver,
> +	 unlike flash memory which is wired to CPU MMU.
> +
> +	 Say N, unless you plan to run this kernel on LP-8X41.
> +
> +	 If you say M, the module will be called sram_lp8841.
> +
>  endmenu
> diff --git a/drivers/mtd/devices/Makefile b/drivers/mtd/devices/Makefile
> index 7912d3a..46df5d6 100644
> --- a/drivers/mtd/devices/Makefile
> +++ b/drivers/mtd/devices/Makefile
> @@ -17,6 +17,7 @@ obj-$(CONFIG_MTD_SST25L)	+= sst25l.o
>  obj-$(CONFIG_MTD_BCM47XXSFLASH)	+= bcm47xxsflash.o
>  obj-$(CONFIG_MTD_ST_SPI_FSM)    += st_spi_fsm.o
>  obj-$(CONFIG_MTD_POWERNV_FLASH)	+= powernv_flash.o
> +obj-$(CONFIG_MTD_SRAM_LP8841)	+= sram_lp8841.o
>  
>  
>  CFLAGS_docg3.o			+= -I$(src)
> diff --git a/drivers/mtd/devices/sram_lp8841.c b/drivers/mtd/devices/sram_lp8841.c
> new file mode 100644
> index 0000000..5d5d942
> --- /dev/null
> +++ b/drivers/mtd/devices/sram_lp8841.c
> @@ -0,0 +1,198 @@
> +/*
> + *  linux/drivers/mtd/devices/sram_lp8841.c
> + *
> + *  MTD Driver for SRAM on ICP DAS LP-8841
> + *  Copyright (C) 2013 Sergei Ianovich <ynvich-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> + *
> + *  This program is free software; you can redistribute it and/or modify
> + *  it under the terms of the GNU General Public License version 2 as
> + *  published by the Free Software Foundation or any later version.
> + */
> +
> +#include <linux/init.h>
> +#include <linux/io.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/mtd/map.h>
> +#include <linux/mtd/mtd.h>
> +#include <linux/mtd/partitions.h>
> +#include <linux/platform_device.h>
> +#include <linux/of_device.h>
> +#include <linux/slab.h>
> +#include <linux/string_helpers.h>
> +#include <linux/types.h>
> +
> +struct lp8841_sram_info {
> +	void __iomem	*bank;
> +	void __iomem	*virt;
> +	struct mutex	lock;
> +	unsigned	active_bank;
> +	struct mtd_info	mtd;
> +};
> +
> +static int
> +lp8841_sram_erase(struct mtd_info *mtd, struct erase_info *instr)
> +{
> +	struct lp8841_sram_info *info = mtd->priv;
> +	unsigned bank = instr->addr >> 11;
> +	unsigned offset = (instr->addr & 0x7ff) << 1;
> +	loff_t i;
> +
> +	mutex_lock(&info->lock);
> +	if (unlikely(bank != info->active_bank)) {
> +		info->active_bank = bank;
> +		iowrite8(bank, info->bank);
> +	}
> +	for (i = 0; i < instr->len; i++) {
> +		iowrite8(0xff, info->virt + offset);
> +		offset += 2;
> +		if (unlikely(offset == 0)) {
> +			info->active_bank++;
> +			iowrite8(info->active_bank, info->bank);
> +		}
> +	}
> +	mutex_unlock(&info->lock);
> +	instr->state = MTD_ERASE_DONE;
> +	mtd_erase_callback(instr);
> +
> +	return 0;
> +}
> +
> +static int
> +lp8841_sram_write(struct mtd_info *mtd, loff_t to, size_t len,
> +		size_t *retlen, const u_char *b)
> +{
> +	struct lp8841_sram_info *info = mtd->priv;
> +	unsigned bank = to >> 11;
> +	unsigned offset = (to & 0x7ff) << 1;
> +	loff_t i;
> +
> +	mutex_lock(&info->lock);
> +	if (unlikely(bank != info->active_bank)) {
> +		info->active_bank = bank;
> +		iowrite8(bank, info->bank);
> +	}
> +	for (i = 0; i < len; i++) {
> +		iowrite8(b[i], info->virt + offset);
> +		offset += 2;
> +		if (unlikely(offset == 0)) {
> +			info->active_bank++;
> +			iowrite8(info->active_bank, info->bank);
> +		}
> +	}
> +	mutex_unlock(&info->lock);
> +	*retlen = len;
> +	return 0;
> +}
> +
> +static int
> +lp8841_sram_read(struct mtd_info *mtd, loff_t from, size_t len,
> +		size_t *retlen, u_char *b)
> +{
> +	struct lp8841_sram_info *info = mtd->priv;
> +	unsigned bank = from >> 11;
> +	unsigned offset = (from & 0x7ff) << 1;
> +	loff_t i;
> +
> +	mutex_lock(&info->lock);
> +	if (unlikely(bank != info->active_bank)) {
> +		info->active_bank = bank;
> +		iowrite8(bank, info->bank);
> +	}
> +	for (i = 0; i < len; i++) {
> +		b[i] = ioread8(info->virt + offset);
> +		offset += 2;
> +		if (unlikely(offset == 0)) {
> +			info->active_bank++;
> +			iowrite8(info->active_bank, info->bank);
> +		}
> +	}
> +	mutex_unlock(&info->lock);
> +	*retlen = len;
> +	return 0;
> +}
> +
> +static const struct of_device_id of_flash_match[] = {
> +	{
> +		.compatible	= "icpdas,lp8841-sram",
> +	},
> +	{ },
> +};
> +MODULE_DEVICE_TABLE(of, of_flash_match);
> +
> +static int
> +lp8841_sram_probe(struct platform_device *pdev)
> +{
> +	struct lp8841_sram_info *info;
> +	struct resource *res_virt, *res_bank;
> +	char sz_str[16];
> +	struct mtd_part_parser_data ppdata;

You don't need this struct any more.

> +	int err = 0;
> +
> +	info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
> +	if (!info)
> +		return -ENOMEM;
> +
> +	res_virt = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	info->virt =  devm_ioremap_resource(&pdev->dev, res_virt);
> +	if (IS_ERR(info->virt))
> +		return PTR_ERR(info->virt);
> +
> +	res_bank = platform_get_resource(pdev, IORESOURCE_MEM, 1);
> +	info->bank = devm_ioremap_resource(&pdev->dev, res_bank);
> +	if (IS_ERR(info->bank))
> +		return PTR_ERR(info->bank);
> +
> +	info->mtd.priv = info;
> +	info->mtd.name = "SRAM";
> +	info->mtd.type = MTD_RAM;
> +	info->mtd.flags = MTD_CAP_RAM;
> +	info->mtd.size = resource_size(res_virt) << 7;
> +	info->mtd.erasesize = 512;
> +	info->mtd.writesize = 4;

Can you please set mtd.writebufsize to an appropriate value too? Maybe
it's just the same as writesize.

> +	info->mtd._erase = lp8841_sram_erase;
> +	info->mtd._write = lp8841_sram_write;
> +	info->mtd._read = lp8841_sram_read;
> +	info->mtd.owner = THIS_MODULE;

If you set info->mtd.dev.parent (please do), you don't need the above
line.

> +
> +	mutex_init(&info->lock);
> +	iowrite8(info->active_bank, info->bank);
> +	platform_set_drvdata(pdev, info);
> +
> +	err = mtd_device_parse_register(&info->mtd, NULL, &ppdata,
> +			NULL, 0);

This can just be:

	err = mtd_device_register(&info->mtd, NULL, 0);

> +
> +	if (err < 0) {
> +		dev_err(&pdev->dev, "failed to register MTD\n");
> +		return err;
> +	}
> +
> +	string_get_size(info->mtd.size, 1, STRING_UNITS_2, sz_str,
> +			sizeof(sz_str));
> +	dev_info(&pdev->dev, "using %s SRAM on LP-8X4X as %s\n", sz_str,
> +			dev_name(&info->mtd.dev));
> +	return 0;
> +}
> +
> +static int
> +lp8841_sram_remove(struct platform_device *dev)
> +{
> +	struct lp8841_sram_info *info = platform_get_drvdata(dev);
> +
> +	return mtd_device_unregister(&info->mtd);
> +}
> +
> +static struct platform_driver lp8841_sram_driver = {
> +	.driver = {
> +		.name		= "sram-lp8841",
> +		.of_match_table = of_flash_match,
> +	},
> +	.probe		= lp8841_sram_probe,
> +	.remove		= lp8841_sram_remove,
> +};
> +
> +module_platform_driver(lp8841_sram_driver);
> +
> +MODULE_LICENSE("GPL");
> +MODULE_AUTHOR("Sergei Ianovich");
> +MODULE_DESCRIPTION("MTD driver for SRAM on ICPDAS LP-8841");

Brian
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH v6] mtd: support BB SRAM on ICP DAS LP-8x4x
@ 2016-03-08  0:19                         ` Brian Norris
  0 siblings, 0 replies; 700+ messages in thread
From: Brian Norris @ 2016-03-08  0:19 UTC (permalink / raw)
  To: Sergei Ianovich
  Cc: linux-kernel, Rob Herring, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, David Woodhouse, Jeremy Kerr,
	Neelesh Gupta, Michael Ellerman, Cyril Bur, Joel Stanley,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	open list:MEMORY TECHNOLOGY DEVICES [MTD]

Hi Sergei,

A few more issues...

On Tue, Feb 23, 2016 at 09:58:01PM +0300, Sergei Ianovich wrote:
> This provides an MTD device driver for 512kB of battery backed up SRAM
> on ICPDAS LP-8X4X programmable automation controllers.
> 
> SRAM chip is connected via FPGA and is not accessible without a driver,
> unlike flash memory which is wired to CPU MMU.
> 
> This SRAM becomes an excellent persisent storage of volatile process
> data like counter values and sensor statuses. Storing those data in
> flash or mmc card is not a viable solution.
> 
> Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
> Reviewed-by: Brian Norris <computersforpeace@gmail.com>
> CC: Rob Herring <robh@kernel.org>
> 
>    v5..v6
>    * replace wildcards in compatible and module name
>    * drop obsolete mtd_part_parser_data.of_node
> 
>    v4..v5
>    * remove .owner from struct platform_driver
>    * constify struct of_device_id
>     for further Brian Norris comments:
>    * drop unused property from doc file
>    * move defconfig update to a different file
>    * drop extra match w/ of_match_device()
> 
>    v3..v4 for Brian Norris 'Reviewed-by'
>    * add doc file for DT binding
>    * move DTS binding to a different patch (8/21)
>    * drop unused include directive
>    * drop safely unused callback
>    * drop non-default partion probe types
>    * drop duplicate error checks
>    * drop duplicate error reporting
>    * fixed error message on MTD registeration
>    * fixed module removal routine
> 
>    v2..v3
>    * no changes (except number 08/16 -> 10/21)
> 
>    v0..v2
>    * use device tree
>    * use devm helpers where possible
> ---
>  .../devicetree/bindings/mtd/icpdas-lp8841-sram.txt |  23 +++
>  drivers/mtd/devices/Kconfig                        |  14 ++
>  drivers/mtd/devices/Makefile                       |   1 +
>  drivers/mtd/devices/sram_lp8841.c                  | 198 +++++++++++++++++++++
>  4 files changed, 236 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/mtd/icpdas-lp8841-sram.txt
>  create mode 100644 drivers/mtd/devices/sram_lp8841.c
> 
> diff --git a/Documentation/devicetree/bindings/mtd/icpdas-lp8841-sram.txt b/Documentation/devicetree/bindings/mtd/icpdas-lp8841-sram.txt
> new file mode 100644
> index 0000000..3c1007a
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/mtd/icpdas-lp8841-sram.txt
> @@ -0,0 +1,23 @@
> +512kB battery backed up SRAM on ICP DAS LP-8841 industrial computers
> +
> +LP-8441, LP-8141, and LP-8041 differ from LP-8841 only in expansion
> +slot count.
> +
> +Required properties:
> +- compatible : should be "icpdas,lp8841-sram"
> +
> +- reg: physical base addresses and region lengths of
> +       * IO memory range
> +       * SRAM page selector
> +
> +SRAM chip is connected via FPGA and is not accessible without a driver,
> +unlike flash memory which is wired to CPU MMU. Driver is essentially
> +an address translation routine.
> +
> +Example:
> +
> +	sram@a000 {
> +		compatible = "icpdas,lp8841-sram";
> +		reg = <0xa000 0x1000
> +		       0x901e 0x1>;
> +	};
> diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig
> index f73c416..ecf5733 100644
> --- a/drivers/mtd/devices/Kconfig
> +++ b/drivers/mtd/devices/Kconfig
> @@ -233,4 +233,18 @@ config BCH_CONST_T
>  	default 4
>  endif
>  
> +config MTD_SRAM_LP8841
> +	tristate "SRAM on ICP DAS LP-8841"
> +	depends on OF && ARCH_PXA
> +       ---help---
> +	 This provides an MTD device driver for 512kiB of battery backed up SRAM
> +	 on ICPDAS LP-8X41 programmable automation controllers.
> +
> +	 SRAM chip is connected via FPGA and is not accessible without a driver,
> +	 unlike flash memory which is wired to CPU MMU.
> +
> +	 Say N, unless you plan to run this kernel on LP-8X41.
> +
> +	 If you say M, the module will be called sram_lp8841.
> +
>  endmenu
> diff --git a/drivers/mtd/devices/Makefile b/drivers/mtd/devices/Makefile
> index 7912d3a..46df5d6 100644
> --- a/drivers/mtd/devices/Makefile
> +++ b/drivers/mtd/devices/Makefile
> @@ -17,6 +17,7 @@ obj-$(CONFIG_MTD_SST25L)	+= sst25l.o
>  obj-$(CONFIG_MTD_BCM47XXSFLASH)	+= bcm47xxsflash.o
>  obj-$(CONFIG_MTD_ST_SPI_FSM)    += st_spi_fsm.o
>  obj-$(CONFIG_MTD_POWERNV_FLASH)	+= powernv_flash.o
> +obj-$(CONFIG_MTD_SRAM_LP8841)	+= sram_lp8841.o
>  
>  
>  CFLAGS_docg3.o			+= -I$(src)
> diff --git a/drivers/mtd/devices/sram_lp8841.c b/drivers/mtd/devices/sram_lp8841.c
> new file mode 100644
> index 0000000..5d5d942
> --- /dev/null
> +++ b/drivers/mtd/devices/sram_lp8841.c
> @@ -0,0 +1,198 @@
> +/*
> + *  linux/drivers/mtd/devices/sram_lp8841.c
> + *
> + *  MTD Driver for SRAM on ICP DAS LP-8841
> + *  Copyright (C) 2013 Sergei Ianovich <ynvich@gmail.com>
> + *
> + *  This program is free software; you can redistribute it and/or modify
> + *  it under the terms of the GNU General Public License version 2 as
> + *  published by the Free Software Foundation or any later version.
> + */
> +
> +#include <linux/init.h>
> +#include <linux/io.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/mtd/map.h>
> +#include <linux/mtd/mtd.h>
> +#include <linux/mtd/partitions.h>
> +#include <linux/platform_device.h>
> +#include <linux/of_device.h>
> +#include <linux/slab.h>
> +#include <linux/string_helpers.h>
> +#include <linux/types.h>
> +
> +struct lp8841_sram_info {
> +	void __iomem	*bank;
> +	void __iomem	*virt;
> +	struct mutex	lock;
> +	unsigned	active_bank;
> +	struct mtd_info	mtd;
> +};
> +
> +static int
> +lp8841_sram_erase(struct mtd_info *mtd, struct erase_info *instr)
> +{
> +	struct lp8841_sram_info *info = mtd->priv;
> +	unsigned bank = instr->addr >> 11;
> +	unsigned offset = (instr->addr & 0x7ff) << 1;
> +	loff_t i;
> +
> +	mutex_lock(&info->lock);
> +	if (unlikely(bank != info->active_bank)) {
> +		info->active_bank = bank;
> +		iowrite8(bank, info->bank);
> +	}
> +	for (i = 0; i < instr->len; i++) {
> +		iowrite8(0xff, info->virt + offset);
> +		offset += 2;
> +		if (unlikely(offset == 0)) {
> +			info->active_bank++;
> +			iowrite8(info->active_bank, info->bank);
> +		}
> +	}
> +	mutex_unlock(&info->lock);
> +	instr->state = MTD_ERASE_DONE;
> +	mtd_erase_callback(instr);
> +
> +	return 0;
> +}
> +
> +static int
> +lp8841_sram_write(struct mtd_info *mtd, loff_t to, size_t len,
> +		size_t *retlen, const u_char *b)
> +{
> +	struct lp8841_sram_info *info = mtd->priv;
> +	unsigned bank = to >> 11;
> +	unsigned offset = (to & 0x7ff) << 1;
> +	loff_t i;
> +
> +	mutex_lock(&info->lock);
> +	if (unlikely(bank != info->active_bank)) {
> +		info->active_bank = bank;
> +		iowrite8(bank, info->bank);
> +	}
> +	for (i = 0; i < len; i++) {
> +		iowrite8(b[i], info->virt + offset);
> +		offset += 2;
> +		if (unlikely(offset == 0)) {
> +			info->active_bank++;
> +			iowrite8(info->active_bank, info->bank);
> +		}
> +	}
> +	mutex_unlock(&info->lock);
> +	*retlen = len;
> +	return 0;
> +}
> +
> +static int
> +lp8841_sram_read(struct mtd_info *mtd, loff_t from, size_t len,
> +		size_t *retlen, u_char *b)
> +{
> +	struct lp8841_sram_info *info = mtd->priv;
> +	unsigned bank = from >> 11;
> +	unsigned offset = (from & 0x7ff) << 1;
> +	loff_t i;
> +
> +	mutex_lock(&info->lock);
> +	if (unlikely(bank != info->active_bank)) {
> +		info->active_bank = bank;
> +		iowrite8(bank, info->bank);
> +	}
> +	for (i = 0; i < len; i++) {
> +		b[i] = ioread8(info->virt + offset);
> +		offset += 2;
> +		if (unlikely(offset == 0)) {
> +			info->active_bank++;
> +			iowrite8(info->active_bank, info->bank);
> +		}
> +	}
> +	mutex_unlock(&info->lock);
> +	*retlen = len;
> +	return 0;
> +}
> +
> +static const struct of_device_id of_flash_match[] = {
> +	{
> +		.compatible	= "icpdas,lp8841-sram",
> +	},
> +	{ },
> +};
> +MODULE_DEVICE_TABLE(of, of_flash_match);
> +
> +static int
> +lp8841_sram_probe(struct platform_device *pdev)
> +{
> +	struct lp8841_sram_info *info;
> +	struct resource *res_virt, *res_bank;
> +	char sz_str[16];
> +	struct mtd_part_parser_data ppdata;

You don't need this struct any more.

> +	int err = 0;
> +
> +	info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
> +	if (!info)
> +		return -ENOMEM;
> +
> +	res_virt = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	info->virt =  devm_ioremap_resource(&pdev->dev, res_virt);
> +	if (IS_ERR(info->virt))
> +		return PTR_ERR(info->virt);
> +
> +	res_bank = platform_get_resource(pdev, IORESOURCE_MEM, 1);
> +	info->bank = devm_ioremap_resource(&pdev->dev, res_bank);
> +	if (IS_ERR(info->bank))
> +		return PTR_ERR(info->bank);
> +
> +	info->mtd.priv = info;
> +	info->mtd.name = "SRAM";
> +	info->mtd.type = MTD_RAM;
> +	info->mtd.flags = MTD_CAP_RAM;
> +	info->mtd.size = resource_size(res_virt) << 7;
> +	info->mtd.erasesize = 512;
> +	info->mtd.writesize = 4;

Can you please set mtd.writebufsize to an appropriate value too? Maybe
it's just the same as writesize.

> +	info->mtd._erase = lp8841_sram_erase;
> +	info->mtd._write = lp8841_sram_write;
> +	info->mtd._read = lp8841_sram_read;
> +	info->mtd.owner = THIS_MODULE;

If you set info->mtd.dev.parent (please do), you don't need the above
line.

> +
> +	mutex_init(&info->lock);
> +	iowrite8(info->active_bank, info->bank);
> +	platform_set_drvdata(pdev, info);
> +
> +	err = mtd_device_parse_register(&info->mtd, NULL, &ppdata,
> +			NULL, 0);

This can just be:

	err = mtd_device_register(&info->mtd, NULL, 0);

> +
> +	if (err < 0) {
> +		dev_err(&pdev->dev, "failed to register MTD\n");
> +		return err;
> +	}
> +
> +	string_get_size(info->mtd.size, 1, STRING_UNITS_2, sz_str,
> +			sizeof(sz_str));
> +	dev_info(&pdev->dev, "using %s SRAM on LP-8X4X as %s\n", sz_str,
> +			dev_name(&info->mtd.dev));
> +	return 0;
> +}
> +
> +static int
> +lp8841_sram_remove(struct platform_device *dev)
> +{
> +	struct lp8841_sram_info *info = platform_get_drvdata(dev);
> +
> +	return mtd_device_unregister(&info->mtd);
> +}
> +
> +static struct platform_driver lp8841_sram_driver = {
> +	.driver = {
> +		.name		= "sram-lp8841",
> +		.of_match_table = of_flash_match,
> +	},
> +	.probe		= lp8841_sram_probe,
> +	.remove		= lp8841_sram_remove,
> +};
> +
> +module_platform_driver(lp8841_sram_driver);
> +
> +MODULE_LICENSE("GPL");
> +MODULE_AUTHOR("Sergei Ianovich");
> +MODULE_DESCRIPTION("MTD driver for SRAM on ICPDAS LP-8841");

Brian

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

* Re: [PATCH v6] serial: rewrite pxa2xx-uart to use 8250_core
  2016-02-22  7:17                         ` Robert Jarzmik
@ 2016-09-27 15:47                           ` Robert Jarzmik
  -1 siblings, 0 replies; 700+ messages in thread
From: Robert Jarzmik @ 2016-09-27 15:47 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: Sergei Ianovich, linux-kernel, Heikki Krogerus, James Cameron,
	Russell King, Jiri Slaby, Andy Shevchenko, Arnd Bergmann,
	Joachim Eastwood, Sebastian Andrzej Siewior, Scott Wood,
	Paul Gortmaker, Paul Burton, Mans Rullgard, Ralf Baechle,
	Masahiro Yamada, Peter Hurley, open list:SERIAL DRIVERS

Robert Jarzmik <robert.jarzmik@free.fr> writes:

>>> If so, great, get the platform maintainer to sign off on this please and
>>> then resend it.
>
> If you're talking about the PXA maintainer, then :
> Acked-by: Robert Jarzmik <robert.jarzmik@free.fr>
>
> I'm happy with the patch, all pxa board maintainers have been warned, and there
> exists a fallback solution.
>
> So let's go forward, and if people complain, let them complain and forward them
> to me.

Hi Greg,

I rebased and retested the patch (both devicetree and legacy boards, multiple
pxa variants, early console and standard console), and it does work. The
fallback on the old driver works as well.

I also signed it as the pxa maintainer, and I'm pushing it now, in [2].

If you want context, it's archived in [1].

If you're overburdened and feel there won't be a merge conflict in your serial
tree, I can take it through pxa tree provided you ack it, or you can take it,
just let me know.

Cheers.

-- 
Robert

[1] Original discussion
    https://patchwork.kernel.org/patch/7918421/

[2] The patch
---8>---
>From 6d9bd0c05c9c7bf42ee1655f3a50dcff959bc87d Mon Sep 17 00:00:00 2001
From: Sergey Yanovich <ynvich@gmail.com>
Date: Thu, 24 Dec 2015 18:15:14 +0300
Subject: [PATCH] serial: rewrite pxa2xx-uart to use 8250_core

pxa2xx-uart was a separate uart platform driver. It was declaring
the same device names and numbers as 8250 driver. As a result,
it was impossible to use 8250 driver on PXA SoCs.

Upon closer examination pxa2xx-uart turned out to be a clone of
8250_core driver.

Workaround for Erratum #19 according to Marvel(R) PXA270M Processor
Specification Update (April 19, 2010) is dropped. 8250_core reads
from FIFO immediately after checking DR bit in LSR.

The patch leaves the original SERIAL_PXA driver around. The original
driver is just marked DEPRECATED in Kconfig and C source. When
the original driver is considered safe to remove, no changes
to SERIAL_8250 will be necessary.

Compiling SERIAL_8250_CONSOLE and SERIAL_PXA_CONSOLE even without
SERIAL_8250_PXA breaks console for SERIAL_PXA. For this reasons, the new
and the original drivers are made mutually exclusive.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Heikki Krogerus <heikki.krogerus@linux.intel.com>
CC: James Cameron <quozl@laptop.org>
CC: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
CC: Robert Jarzmik <robert.jarzmik@free.fr>
CC: Russell King <linux@arm.linux.org.uk>
Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
[rebased on v4.8]
Tested-by: Robert Jarzmik <robert.jarzmik@free.fr>
Signed-off-by: Robert Jarzmik <robert.jarzmik@free.fr>
---
 drivers/tty/serial/8250/8250_pxa.c | 177 +++++++++++++++++++++++++++++++++++++
 drivers/tty/serial/8250/Kconfig    |  10 +++
 drivers/tty/serial/8250/Makefile   |   1 +
 drivers/tty/serial/Kconfig         |  17 +++-
 drivers/tty/serial/Makefile        |   2 +-
 drivers/tty/serial/pxa.c           |   4 +-
 6 files changed, 207 insertions(+), 4 deletions(-)
 create mode 100644 drivers/tty/serial/8250/8250_pxa.c

diff --git a/drivers/tty/serial/8250/8250_pxa.c b/drivers/tty/serial/8250/8250_pxa.c
new file mode 100644
index 000000000000..6a14df013754
--- /dev/null
+++ b/drivers/tty/serial/8250/8250_pxa.c
@@ -0,0 +1,177 @@
+/*
+ *  drivers/tty/serial/8250/8250_pxa.c -- driver for PXA on-board UARTS
+ *  Copyright:	(C) 2013 Sergei Ianovich <ynvich@gmail.com>
+ *
+ *  replaces drivers/serial/pxa.c by Nicolas Pitre
+ *  Created:	Feb 20, 2003
+ *  Copyright:	(C) 2003 Monta Vista Software, Inc.
+ *
+ *  Based on drivers/serial/8250.c by Russell King.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/serial_8250.h>
+#include <linux/serial_core.h>
+#include <linux/serial_reg.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
+#include <linux/pm_runtime.h>
+
+#include "8250.h"
+
+struct pxa8250_data {
+	int			line;
+	struct clk		*clk;
+};
+
+#ifdef CONFIG_PM
+static int serial_pxa_suspend(struct device *dev)
+{
+	struct pxa8250_data *data = dev_get_drvdata(dev);
+
+	serial8250_suspend_port(data->line);
+
+	return 0;
+}
+
+static int serial_pxa_resume(struct device *dev)
+{
+	struct pxa8250_data *data = dev_get_drvdata(dev);
+
+	serial8250_resume_port(data->line);
+
+	return 0;
+}
+#endif
+
+static const struct dev_pm_ops serial_pxa_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(serial_pxa_suspend, serial_pxa_resume)
+};
+
+static const struct of_device_id serial_pxa_dt_ids[] = {
+	{ .compatible = "mrvl,pxa-uart", },
+	{ .compatible = "mrvl,mmp-uart", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, serial_pxa_dt_ids);
+
+/* Uart divisor latch write */
+static void serial_pxa_dl_write(struct uart_8250_port *up, int value)
+{
+	unsigned int dll;
+
+	serial_out(up, UART_DLL, value & 0xff);
+	/*
+	 * work around Erratum #74 according to Marvel(R) PXA270M Processor
+	 * Specification Update (April 19, 2010)
+	 */
+	dll = serial_in(up, UART_DLL);
+	WARN_ON(dll != (value & 0xff));
+
+	serial_out(up, UART_DLM, value >> 8 & 0xff);
+}
+
+
+static void serial_pxa_pm(struct uart_port *port, unsigned int state,
+	      unsigned int oldstate)
+{
+	struct pxa8250_data *data = port->private_data;
+
+	if (!state)
+		clk_prepare_enable(data->clk);
+	else
+		clk_disable_unprepare(data->clk);
+}
+
+static int serial_pxa_probe(struct platform_device *pdev)
+{
+	struct uart_8250_port uart = {};
+	struct pxa8250_data *data;
+	struct resource *mmres, *irqres;
+	int ret;
+
+	mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	irqres = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!mmres || !irqres)
+		return -ENODEV;
+
+	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(data->clk))
+		return PTR_ERR(data->clk);
+
+	ret = clk_prepare(data->clk);
+	if (ret)
+		return ret;
+
+	uart.port.type = PORT_XSCALE;
+	uart.port.iotype = UPIO_MEM32;
+	uart.port.mapbase = mmres->start;
+	uart.port.regshift = 2;
+	uart.port.irq = irqres->start;
+	uart.port.fifosize = 64;
+	uart.port.flags = UPF_IOREMAP | UPF_SKIP_TEST;
+	uart.port.dev = &pdev->dev;
+	uart.port.uartclk = clk_get_rate(data->clk);
+	uart.port.pm = serial_pxa_pm;
+	uart.port.private_data = data;
+	uart.dl_write = serial_pxa_dl_write;
+
+	ret = serial8250_register_8250_port(&uart);
+	if (ret < 0)
+		goto err_clk;
+
+	data->line = ret;
+
+	platform_set_drvdata(pdev, data);
+
+	return 0;
+
+ err_clk:
+	clk_unprepare(data->clk);
+	return ret;
+}
+
+static int serial_pxa_remove(struct platform_device *pdev)
+{
+	struct pxa8250_data *data = platform_get_drvdata(pdev);
+
+	serial8250_unregister_port(data->line);
+
+	clk_unprepare(data->clk);
+
+	return 0;
+}
+
+static struct platform_driver serial_pxa_driver = {
+	.probe          = serial_pxa_probe,
+	.remove         = serial_pxa_remove,
+
+	.driver		= {
+		.name	= "pxa2xx-uart",
+		.pm	= &serial_pxa_pm_ops,
+		.of_match_table = serial_pxa_dt_ids,
+	},
+};
+
+module_platform_driver(serial_pxa_driver);
+
+MODULE_AUTHOR("Sergei Ianovich");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:pxa2xx-uart");
diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
index c9ec839a5ddf..a294e858e16b 100644
--- a/drivers/tty/serial/8250/Kconfig
+++ b/drivers/tty/serial/8250/Kconfig
@@ -426,6 +426,16 @@ config SERIAL_8250_MOXA
 	  This driver can also be built as a module. The module will be called
 	  8250_moxa. If you want to do that, say M here.
 
+config SERIAL_8250_PXA
+	tristate "PXA serial port support"
+	depends on SERIAL_8250
+	depends on ARCH_PXA || ARCH_MMP
+	help
+	  If you have a machine based on an Intel XScale PXA2xx CPU you can
+	  enable its onboard serial ports by enabling this option. The option is
+	  applicable to both devicetree and legacy boards, and early console is
+	  part of its support.
+
 config SERIAL_OF_PLATFORM
 	tristate "Devicetree based probing for 8250 ports"
 	depends on SERIAL_8250 && OF
diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile
index 367d403d28d5..30745c94ae45 100644
--- a/drivers/tty/serial/8250/Makefile
+++ b/drivers/tty/serial/8250/Makefile
@@ -30,6 +30,7 @@ obj-$(CONFIG_SERIAL_8250_UNIPHIER)	+= 8250_uniphier.o
 obj-$(CONFIG_SERIAL_8250_INGENIC)	+= 8250_ingenic.o
 obj-$(CONFIG_SERIAL_8250_MID)		+= 8250_mid.o
 obj-$(CONFIG_SERIAL_8250_MOXA)		+= 8250_moxa.o
+obj-$(CONFIG_SERIAL_8250_PXA)		+= 8250_pxa.o
 obj-$(CONFIG_SERIAL_OF_PLATFORM)	+= 8250_of.o
 
 CFLAGS_8250_ingenic.o += -I$(srctree)/scripts/dtc/libfdt
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index 518db24a5b36..543cdd58232d 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -438,17 +438,27 @@ config SERIAL_MPSC_CONSOLE
 	  Say Y here if you want to support a serial console on a Marvell MPSC.
 
 config SERIAL_PXA
-	bool "PXA serial port support"
+	bool "PXA serial port support (DEPRECATED)"
 	depends on ARCH_PXA || ARCH_MMP
 	select SERIAL_CORE
+	select SERIAL_8250_PXA if SERIAL_8250=y
+	select SERIAL_PXA_NON8250 if !SERIAL_8250=y
 	help
 	  If you have a machine based on an Intel XScale PXA2xx CPU you
 	  can enable its onboard serial ports by enabling this option.
 
+	  Unless you have a specific need, you should use SERIAL_8250_PXA
+	  instead of this.
+
+config SERIAL_PXA_NON8250
+	bool
+	depends on !SERIAL_8250
+
 config SERIAL_PXA_CONSOLE
-	bool "Console on PXA serial port"
+	bool "Console on PXA serial port (DEPRECATED)"
 	depends on SERIAL_PXA
 	select SERIAL_CORE_CONSOLE
+	select SERIAL_8250_CONSOLE if SERIAL_8250=y
 	help
 	  If you have enabled the serial port on the Intel XScale PXA
 	  CPU you can make it the console by answering Y to this option.
@@ -460,6 +470,9 @@ config SERIAL_PXA_CONSOLE
 	  your boot loader (lilo or loadlin) about how to pass options to the
 	  kernel at boot time.)
 
+	  Unless you have a specific need, you should use SERIAL_8250_PXA
+	  and SERIAL_8250_CONSOLE instead of this.
+
 config SERIAL_SA1100
 	bool "SA1100 serial port support"
 	depends on ARCH_SA1100
diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile
index 1278d376da50..1fa21ec616bd 100644
--- a/drivers/tty/serial/Makefile
+++ b/drivers/tty/serial/Makefile
@@ -23,7 +23,7 @@ obj-$(CONFIG_SERIAL_8250) += 8250/
 obj-$(CONFIG_SERIAL_AMBA_PL010) += amba-pl010.o
 obj-$(CONFIG_SERIAL_AMBA_PL011) += amba-pl011.o
 obj-$(CONFIG_SERIAL_CLPS711X) += clps711x.o
-obj-$(CONFIG_SERIAL_PXA) += pxa.o
+obj-$(CONFIG_SERIAL_PXA_NON8250) += pxa.o
 obj-$(CONFIG_SERIAL_PNX8XXX) += pnx8xxx_uart.o
 obj-$(CONFIG_SERIAL_SA1100) += sa1100.o
 obj-$(CONFIG_SERIAL_BCM63XX) += bcm63xx_uart.o
diff --git a/drivers/tty/serial/pxa.c b/drivers/tty/serial/pxa.c
index cd9d9e878475..b9dd787cb561 100644
--- a/drivers/tty/serial/pxa.c
+++ b/drivers/tty/serial/pxa.c
@@ -925,7 +925,9 @@ static struct platform_driver serial_pxa_driver = {
 	},
 };
 
-static int __init serial_pxa_init(void)
+
+/* 8250 driver for PXA serial ports should be used */
+static int __deprecated __init serial_pxa_init(void)
 {
 	int ret;
 
-- 
2.1.4

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

* Re: [PATCH v6] serial: rewrite pxa2xx-uart to use 8250_core
@ 2016-09-27 15:47                           ` Robert Jarzmik
  0 siblings, 0 replies; 700+ messages in thread
From: Robert Jarzmik @ 2016-09-27 15:47 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: Sergei Ianovich, linux-kernel, Heikki Krogerus, James Cameron,
	Russell King, Jiri Slaby, Andy Shevchenko, Arnd Bergmann,
	Joachim Eastwood, Sebastian Andrzej Siewior, Scott Wood,
	Paul Gortmaker, Paul Burton, Mans Rullgard, Ralf Baechle,
	Masahiro Yamada, Peter Hurley, open list:SERIAL DRIVERS

Robert Jarzmik <robert.jarzmik@free.fr> writes:

>>> If so, great, get the platform maintainer to sign off on this please and
>>> then resend it.
>
> If you're talking about the PXA maintainer, then :
> Acked-by: Robert Jarzmik <robert.jarzmik@free.fr>
>
> I'm happy with the patch, all pxa board maintainers have been warned, and there
> exists a fallback solution.
>
> So let's go forward, and if people complain, let them complain and forward them
> to me.

Hi Greg,

I rebased and retested the patch (both devicetree and legacy boards, multiple
pxa variants, early console and standard console), and it does work. The
fallback on the old driver works as well.

I also signed it as the pxa maintainer, and I'm pushing it now, in [2].

If you want context, it's archived in [1].

If you're overburdened and feel there won't be a merge conflict in your serial
tree, I can take it through pxa tree provided you ack it, or you can take it,
just let me know.

Cheers.

-- 
Robert

[1] Original discussion
    https://patchwork.kernel.org/patch/7918421/

[2] The patch
---8>---
>From 6d9bd0c05c9c7bf42ee1655f3a50dcff959bc87d Mon Sep 17 00:00:00 2001
From: Sergey Yanovich <ynvich@gmail.com>
Date: Thu, 24 Dec 2015 18:15:14 +0300
Subject: [PATCH] serial: rewrite pxa2xx-uart to use 8250_core

pxa2xx-uart was a separate uart platform driver. It was declaring
the same device names and numbers as 8250 driver. As a result,
it was impossible to use 8250 driver on PXA SoCs.

Upon closer examination pxa2xx-uart turned out to be a clone of
8250_core driver.

Workaround for Erratum #19 according to Marvel(R) PXA270M Processor
Specification Update (April 19, 2010) is dropped. 8250_core reads
from FIFO immediately after checking DR bit in LSR.

The patch leaves the original SERIAL_PXA driver around. The original
driver is just marked DEPRECATED in Kconfig and C source. When
the original driver is considered safe to remove, no changes
to SERIAL_8250 will be necessary.

Compiling SERIAL_8250_CONSOLE and SERIAL_PXA_CONSOLE even without
SERIAL_8250_PXA breaks console for SERIAL_PXA. For this reasons, the new
and the original drivers are made mutually exclusive.

Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
CC: Heikki Krogerus <heikki.krogerus@linux.intel.com>
CC: James Cameron <quozl@laptop.org>
CC: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
CC: Robert Jarzmik <robert.jarzmik@free.fr>
CC: Russell King <linux@arm.linux.org.uk>
Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
[rebased on v4.8]
Tested-by: Robert Jarzmik <robert.jarzmik@free.fr>
Signed-off-by: Robert Jarzmik <robert.jarzmik@free.fr>
---
 drivers/tty/serial/8250/8250_pxa.c | 177 +++++++++++++++++++++++++++++++++++++
 drivers/tty/serial/8250/Kconfig    |  10 +++
 drivers/tty/serial/8250/Makefile   |   1 +
 drivers/tty/serial/Kconfig         |  17 +++-
 drivers/tty/serial/Makefile        |   2 +-
 drivers/tty/serial/pxa.c           |   4 +-
 6 files changed, 207 insertions(+), 4 deletions(-)
 create mode 100644 drivers/tty/serial/8250/8250_pxa.c

diff --git a/drivers/tty/serial/8250/8250_pxa.c b/drivers/tty/serial/8250/8250_pxa.c
new file mode 100644
index 000000000000..6a14df013754
--- /dev/null
+++ b/drivers/tty/serial/8250/8250_pxa.c
@@ -0,0 +1,177 @@
+/*
+ *  drivers/tty/serial/8250/8250_pxa.c -- driver for PXA on-board UARTS
+ *  Copyright:	(C) 2013 Sergei Ianovich <ynvich@gmail.com>
+ *
+ *  replaces drivers/serial/pxa.c by Nicolas Pitre
+ *  Created:	Feb 20, 2003
+ *  Copyright:	(C) 2003 Monta Vista Software, Inc.
+ *
+ *  Based on drivers/serial/8250.c by Russell King.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/serial_8250.h>
+#include <linux/serial_core.h>
+#include <linux/serial_reg.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
+#include <linux/pm_runtime.h>
+
+#include "8250.h"
+
+struct pxa8250_data {
+	int			line;
+	struct clk		*clk;
+};
+
+#ifdef CONFIG_PM
+static int serial_pxa_suspend(struct device *dev)
+{
+	struct pxa8250_data *data = dev_get_drvdata(dev);
+
+	serial8250_suspend_port(data->line);
+
+	return 0;
+}
+
+static int serial_pxa_resume(struct device *dev)
+{
+	struct pxa8250_data *data = dev_get_drvdata(dev);
+
+	serial8250_resume_port(data->line);
+
+	return 0;
+}
+#endif
+
+static const struct dev_pm_ops serial_pxa_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(serial_pxa_suspend, serial_pxa_resume)
+};
+
+static const struct of_device_id serial_pxa_dt_ids[] = {
+	{ .compatible = "mrvl,pxa-uart", },
+	{ .compatible = "mrvl,mmp-uart", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, serial_pxa_dt_ids);
+
+/* Uart divisor latch write */
+static void serial_pxa_dl_write(struct uart_8250_port *up, int value)
+{
+	unsigned int dll;
+
+	serial_out(up, UART_DLL, value & 0xff);
+	/*
+	 * work around Erratum #74 according to Marvel(R) PXA270M Processor
+	 * Specification Update (April 19, 2010)
+	 */
+	dll = serial_in(up, UART_DLL);
+	WARN_ON(dll != (value & 0xff));
+
+	serial_out(up, UART_DLM, value >> 8 & 0xff);
+}
+
+
+static void serial_pxa_pm(struct uart_port *port, unsigned int state,
+	      unsigned int oldstate)
+{
+	struct pxa8250_data *data = port->private_data;
+
+	if (!state)
+		clk_prepare_enable(data->clk);
+	else
+		clk_disable_unprepare(data->clk);
+}
+
+static int serial_pxa_probe(struct platform_device *pdev)
+{
+	struct uart_8250_port uart = {};
+	struct pxa8250_data *data;
+	struct resource *mmres, *irqres;
+	int ret;
+
+	mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	irqres = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!mmres || !irqres)
+		return -ENODEV;
+
+	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(data->clk))
+		return PTR_ERR(data->clk);
+
+	ret = clk_prepare(data->clk);
+	if (ret)
+		return ret;
+
+	uart.port.type = PORT_XSCALE;
+	uart.port.iotype = UPIO_MEM32;
+	uart.port.mapbase = mmres->start;
+	uart.port.regshift = 2;
+	uart.port.irq = irqres->start;
+	uart.port.fifosize = 64;
+	uart.port.flags = UPF_IOREMAP | UPF_SKIP_TEST;
+	uart.port.dev = &pdev->dev;
+	uart.port.uartclk = clk_get_rate(data->clk);
+	uart.port.pm = serial_pxa_pm;
+	uart.port.private_data = data;
+	uart.dl_write = serial_pxa_dl_write;
+
+	ret = serial8250_register_8250_port(&uart);
+	if (ret < 0)
+		goto err_clk;
+
+	data->line = ret;
+
+	platform_set_drvdata(pdev, data);
+
+	return 0;
+
+ err_clk:
+	clk_unprepare(data->clk);
+	return ret;
+}
+
+static int serial_pxa_remove(struct platform_device *pdev)
+{
+	struct pxa8250_data *data = platform_get_drvdata(pdev);
+
+	serial8250_unregister_port(data->line);
+
+	clk_unprepare(data->clk);
+
+	return 0;
+}
+
+static struct platform_driver serial_pxa_driver = {
+	.probe          = serial_pxa_probe,
+	.remove         = serial_pxa_remove,
+
+	.driver		= {
+		.name	= "pxa2xx-uart",
+		.pm	= &serial_pxa_pm_ops,
+		.of_match_table = serial_pxa_dt_ids,
+	},
+};
+
+module_platform_driver(serial_pxa_driver);
+
+MODULE_AUTHOR("Sergei Ianovich");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:pxa2xx-uart");
diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
index c9ec839a5ddf..a294e858e16b 100644
--- a/drivers/tty/serial/8250/Kconfig
+++ b/drivers/tty/serial/8250/Kconfig
@@ -426,6 +426,16 @@ config SERIAL_8250_MOXA
 	  This driver can also be built as a module. The module will be called
 	  8250_moxa. If you want to do that, say M here.
 
+config SERIAL_8250_PXA
+	tristate "PXA serial port support"
+	depends on SERIAL_8250
+	depends on ARCH_PXA || ARCH_MMP
+	help
+	  If you have a machine based on an Intel XScale PXA2xx CPU you can
+	  enable its onboard serial ports by enabling this option. The option is
+	  applicable to both devicetree and legacy boards, and early console is
+	  part of its support.
+
 config SERIAL_OF_PLATFORM
 	tristate "Devicetree based probing for 8250 ports"
 	depends on SERIAL_8250 && OF
diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile
index 367d403d28d5..30745c94ae45 100644
--- a/drivers/tty/serial/8250/Makefile
+++ b/drivers/tty/serial/8250/Makefile
@@ -30,6 +30,7 @@ obj-$(CONFIG_SERIAL_8250_UNIPHIER)	+= 8250_uniphier.o
 obj-$(CONFIG_SERIAL_8250_INGENIC)	+= 8250_ingenic.o
 obj-$(CONFIG_SERIAL_8250_MID)		+= 8250_mid.o
 obj-$(CONFIG_SERIAL_8250_MOXA)		+= 8250_moxa.o
+obj-$(CONFIG_SERIAL_8250_PXA)		+= 8250_pxa.o
 obj-$(CONFIG_SERIAL_OF_PLATFORM)	+= 8250_of.o
 
 CFLAGS_8250_ingenic.o += -I$(srctree)/scripts/dtc/libfdt
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index 518db24a5b36..543cdd58232d 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -438,17 +438,27 @@ config SERIAL_MPSC_CONSOLE
 	  Say Y here if you want to support a serial console on a Marvell MPSC.
 
 config SERIAL_PXA
-	bool "PXA serial port support"
+	bool "PXA serial port support (DEPRECATED)"
 	depends on ARCH_PXA || ARCH_MMP
 	select SERIAL_CORE
+	select SERIAL_8250_PXA if SERIAL_8250=y
+	select SERIAL_PXA_NON8250 if !SERIAL_8250=y
 	help
 	  If you have a machine based on an Intel XScale PXA2xx CPU you
 	  can enable its onboard serial ports by enabling this option.
 
+	  Unless you have a specific need, you should use SERIAL_8250_PXA
+	  instead of this.
+
+config SERIAL_PXA_NON8250
+	bool
+	depends on !SERIAL_8250
+
 config SERIAL_PXA_CONSOLE
-	bool "Console on PXA serial port"
+	bool "Console on PXA serial port (DEPRECATED)"
 	depends on SERIAL_PXA
 	select SERIAL_CORE_CONSOLE
+	select SERIAL_8250_CONSOLE if SERIAL_8250=y
 	help
 	  If you have enabled the serial port on the Intel XScale PXA
 	  CPU you can make it the console by answering Y to this option.
@@ -460,6 +470,9 @@ config SERIAL_PXA_CONSOLE
 	  your boot loader (lilo or loadlin) about how to pass options to the
 	  kernel at boot time.)
 
+	  Unless you have a specific need, you should use SERIAL_8250_PXA
+	  and SERIAL_8250_CONSOLE instead of this.
+
 config SERIAL_SA1100
 	bool "SA1100 serial port support"
 	depends on ARCH_SA1100
diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile
index 1278d376da50..1fa21ec616bd 100644
--- a/drivers/tty/serial/Makefile
+++ b/drivers/tty/serial/Makefile
@@ -23,7 +23,7 @@ obj-$(CONFIG_SERIAL_8250) += 8250/
 obj-$(CONFIG_SERIAL_AMBA_PL010) += amba-pl010.o
 obj-$(CONFIG_SERIAL_AMBA_PL011) += amba-pl011.o
 obj-$(CONFIG_SERIAL_CLPS711X) += clps711x.o
-obj-$(CONFIG_SERIAL_PXA) += pxa.o
+obj-$(CONFIG_SERIAL_PXA_NON8250) += pxa.o
 obj-$(CONFIG_SERIAL_PNX8XXX) += pnx8xxx_uart.o
 obj-$(CONFIG_SERIAL_SA1100) += sa1100.o
 obj-$(CONFIG_SERIAL_BCM63XX) += bcm63xx_uart.o
diff --git a/drivers/tty/serial/pxa.c b/drivers/tty/serial/pxa.c
index cd9d9e878475..b9dd787cb561 100644
--- a/drivers/tty/serial/pxa.c
+++ b/drivers/tty/serial/pxa.c
@@ -925,7 +925,9 @@ static struct platform_driver serial_pxa_driver = {
 	},
 };
 
-static int __init serial_pxa_init(void)
+
+/* 8250 driver for PXA serial ports should be used */
+static int __deprecated __init serial_pxa_init(void)
 {
 	int ret;
 
-- 
2.1.4

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

* Re: [PATCH v6] serial: rewrite pxa2xx-uart to use 8250_core
  2016-09-27 15:47                           ` Robert Jarzmik
  (?)
@ 2016-09-27 16:12                           ` Greg Kroah-Hartman
  2016-09-27 16:24                               ` Robert Jarzmik
  -1 siblings, 1 reply; 700+ messages in thread
From: Greg Kroah-Hartman @ 2016-09-27 16:12 UTC (permalink / raw)
  To: Robert Jarzmik
  Cc: Sergei Ianovich, linux-kernel, Heikki Krogerus, James Cameron,
	Russell King, Jiri Slaby, Andy Shevchenko, Arnd Bergmann,
	Joachim Eastwood, Sebastian Andrzej Siewior, Scott Wood,
	Paul Gortmaker, Paul Burton, Mans Rullgard, Ralf Baechle,
	Masahiro Yamada, Peter Hurley, open list:SERIAL DRIVERS

On Tue, Sep 27, 2016 at 05:47:54PM +0200, Robert Jarzmik wrote:
> Robert Jarzmik <robert.jarzmik@free.fr> writes:
> 
> >>> If so, great, get the platform maintainer to sign off on this please and
> >>> then resend it.
> >
> > If you're talking about the PXA maintainer, then :
> > Acked-by: Robert Jarzmik <robert.jarzmik@free.fr>
> >
> > I'm happy with the patch, all pxa board maintainers have been warned, and there
> > exists a fallback solution.
> >
> > So let's go forward, and if people complain, let them complain and forward them
> > to me.
> 
> Hi Greg,
> 
> I rebased and retested the patch (both devicetree and legacy boards, multiple
> pxa variants, early console and standard console), and it does work. The
> fallback on the old driver works as well.
> 
> I also signed it as the pxa maintainer, and I'm pushing it now, in [2].
> 
> If you want context, it's archived in [1].
> 
> If you're overburdened and feel there won't be a merge conflict in your serial
> tree, I can take it through pxa tree provided you ack it, or you can take it,
> just let me know.

I'll be glad to take it, can you send it in a proper format?

thanks,

greg k-h

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

* Re: [PATCH v6] serial: rewrite pxa2xx-uart to use 8250_core
  2016-09-27 16:12                           ` Greg Kroah-Hartman
@ 2016-09-27 16:24                               ` Robert Jarzmik
  0 siblings, 0 replies; 700+ messages in thread
From: Robert Jarzmik @ 2016-09-27 16:24 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: Sergei Ianovich, linux-kernel, Heikki Krogerus, James Cameron,
	Russell King, Jiri Slaby, Andy Shevchenko, Arnd Bergmann,
	Joachim Eastwood, Sebastian Andrzej Siewior, Scott Wood,
	Paul Gortmaker, Paul Burton, Mans Rullgard, Ralf Baechle,
	Masahiro Yamada, Peter Hurley, open list:SERIAL DRIVERS

Greg Kroah-Hartman <gregkh@linuxfoundation.org> writes:

> On Tue, Sep 27, 2016 at 05:47:54PM +0200, Robert Jarzmik wrote:
>> If you're overburdened and feel there won't be a merge conflict in your serial
>> tree, I can take it through pxa tree provided you ack it, or you can take it,
>> just let me know.
>
> I'll be glad to take it, can you send it in a proper format?
Most certainly.

Done with the title "[PATCH v6 RESEND] serial: rewrite pxa2xx-uart to use
8250_core".

Thanks.

-- 
Robert

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

* Re: [PATCH v6] serial: rewrite pxa2xx-uart to use 8250_core
@ 2016-09-27 16:24                               ` Robert Jarzmik
  0 siblings, 0 replies; 700+ messages in thread
From: Robert Jarzmik @ 2016-09-27 16:24 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: Sergei Ianovich, linux-kernel, Heikki Krogerus, James Cameron,
	Russell King, Jiri Slaby, Andy Shevchenko, Arnd Bergmann,
	Joachim Eastwood, Sebastian Andrzej Siewior, Scott Wood,
	Paul Gortmaker, Paul Burton, Mans Rullgard, Ralf Baechle,
	Masahiro Yamada, Peter Hurley, open list:SERIAL DRIVERS

Greg Kroah-Hartman <gregkh@linuxfoundation.org> writes:

> On Tue, Sep 27, 2016 at 05:47:54PM +0200, Robert Jarzmik wrote:
>> If you're overburdened and feel there won't be a merge conflict in your serial
>> tree, I can take it through pxa tree provided you ack it, or you can take it,
>> just let me know.
>
> I'll be glad to take it, can you send it in a proper format?
Most certainly.

Done with the title "[PATCH v6 RESEND] serial: rewrite pxa2xx-uart to use
8250_core".

Thanks.

-- 
Robert

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

end of thread, other threads:[~2016-09-27 16:24 UTC | newest]

Thread overview: 700+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-12-01  6:26 [PATCH 00/11] ARM: support for ICP DAS LP-8x4x Sergei Ianovich
2013-12-01  6:26 ` Sergei Ianovich
2013-12-01  6:26 ` [PATCH 01/11] resolve PXA<->8250 serial device address conflict Sergei Ianovich
2013-12-01  6:26   ` Sergei Ianovich
2013-12-01  6:26   ` Sergei Ianovich
2013-12-02  9:02   ` Heikki Krogerus
2013-12-02  9:02     ` Heikki Krogerus
2013-12-02  9:23     ` Sergei Ianovich
2013-12-02  9:23       ` Sergei Ianovich
2013-12-02  9:49       ` Heikki Krogerus
2013-12-02  9:49         ` Heikki Krogerus
2013-12-02 10:26         ` Sergei Ianovich
2013-12-02 10:26           ` Sergei Ianovich
2013-12-02 14:10           ` Heikki Krogerus
2013-12-02 14:10             ` Heikki Krogerus
2013-12-05  4:12             ` Greg Kroah-Hartman
2013-12-05  4:12               ` Greg Kroah-Hartman
2013-12-05  4:31               ` Sergei Ianovich
2013-12-05  4:31                 ` Sergei Ianovich
2013-12-05  4:35                 ` Greg Kroah-Hartman
2013-12-05  4:35                   ` Greg Kroah-Hartman
2013-12-05  4:36                   ` Sergei Ianovich
2013-12-05  4:36                     ` Sergei Ianovich
2013-12-05 23:28                   ` [PATCH] serial: rewrite pxa2xx-uart to use 8250_core Sergei Ianovich
2013-12-05 23:28                     ` Sergei Ianovich
2013-12-05 23:28                     ` Sergei Ianovich
2013-12-06  0:02                     ` Greg Kroah-Hartman
2013-12-06  0:02                       ` Greg Kroah-Hartman
2013-12-06  0:02                       ` Greg Kroah-Hartman
2013-12-06  0:17                       ` Russell King - ARM Linux
2013-12-06  0:17                         ` Russell King - ARM Linux
2013-12-06  0:17                         ` Russell King - ARM Linux
2013-12-06  9:28                         ` Sergei Ianovich
2013-12-06  9:28                           ` Sergei Ianovich
2013-12-06  9:53                           ` James Cameron
2013-12-06  9:53                             ` James Cameron
2013-12-06 10:34                             ` Sergei Ianovich
2013-12-06 10:34                               ` Sergei Ianovich
2013-12-06 11:05                               ` James Cameron
2013-12-06 11:05                                 ` James Cameron
2013-12-06  0:38                     ` James Cameron
2013-12-06  0:38                       ` James Cameron
2013-12-06  0:38                       ` James Cameron
2013-12-06  2:55                       ` James Cameron
2013-12-06  2:55                         ` James Cameron
2013-12-06  2:42                     ` James Cameron
2013-12-06  2:42                       ` James Cameron
2013-12-06  9:16                       ` Sergei Ianovich
2013-12-06  9:16                         ` Sergei Ianovich
2013-12-06  9:09                     ` [PATCH v2] " Sergei Ianovich
2013-12-06  9:09                       ` Sergei Ianovich
2013-12-06  9:09                       ` Sergei Ianovich
2013-12-06  9:28                       ` James Cameron
2013-12-06  9:28                         ` James Cameron
2013-12-09  8:38                       ` Heikki Krogerus
2013-12-09  8:38                         ` Heikki Krogerus
2013-12-09  8:44                         ` Sascha Hauer
2013-12-09  8:44                           ` Sascha Hauer
2013-12-09 11:38                       ` [PATCH v3] " Sergei Ianovich
2013-12-09 11:38                         ` Sergei Ianovich
2013-12-09 11:38                         ` Sergei Ianovich
2014-01-28 14:14   ` [PATCH 01/11] resolve PXA<->8250 serial device address conflict Pavel Machek
2014-01-28 14:14     ` Pavel Machek
2014-01-28 14:20     ` Sergei Ianovich
2014-01-28 14:20       ` Sergei Ianovich
2013-12-01  6:26 ` [PATCH 02/11] arm: pxa27x: support ICP DAS LP-8x4x Sergei Ianovich
2013-12-01  6:26   ` Sergei Ianovich
2013-12-06  0:40   ` Arnd Bergmann
2013-12-06  0:40     ` Arnd Bergmann
2013-12-06 16:38     ` Sergei Ianovich
2013-12-06 16:38       ` Sergei Ianovich
2013-12-06 17:14       ` Arnd Bergmann
2013-12-06 17:14         ` Arnd Bergmann
2013-12-10 12:33         ` Linus Walleij
2013-12-10 12:33           ` Linus Walleij
2013-12-10 20:20           ` Sergei Ianovich
2013-12-10 20:20             ` Sergei Ianovich
2013-12-10 21:57             ` Arnd Bergmann
2013-12-10 21:57               ` Arnd Bergmann
2013-12-11  4:30               ` Sergei Ianovich
2013-12-11  4:30                 ` Sergei Ianovich
2013-12-11  5:11                 ` Arnd Bergmann
2013-12-11  5:11                   ` Arnd Bergmann
2013-12-11  5:41                   ` Sergei Ianovich
2013-12-11  5:41                     ` Sergei Ianovich
2013-12-11 14:53                     ` Arnd Bergmann
2013-12-11 14:53                       ` Arnd Bergmann
2013-12-06 16:48   ` [PATCH v2 " Sergei Ianovich
2013-12-06 16:48     ` Sergei Ianovich
2013-12-08  2:21     ` Arnd Bergmann
2013-12-08  2:21       ` Arnd Bergmann
2013-12-08  7:05       ` Sergei Ianovich
2013-12-08  7:05         ` Sergei Ianovich
2013-12-09  0:54         ` Arnd Bergmann
2013-12-09  0:54           ` Arnd Bergmann
2013-12-08 22:53     ` [PATCH 0/9] ARM: support for ICP DAS LP-8x4x (with dts) Sergei Ianovich
2013-12-08 22:53       ` Sergei Ianovich
2013-12-08 22:53       ` [PATCH 1/9] ARM: dts: pxa2xx fix compatible strings Sergei Ianovich
2013-12-08 22:53         ` Sergei Ianovich
2013-12-08 22:53         ` Sergei Ianovich
2013-12-08 22:53       ` [PATCH 2/9] ARM: dts: fix pxa27x-gpio interrupts Sergei Ianovich
2013-12-08 22:53         ` Sergei Ianovich
2013-12-08 22:53         ` Sergei Ianovich
2013-12-08 22:53       ` [PATCH 3/9] ARM: fix ohci-pxa27x build error with OF enabled Sergei Ianovich
2013-12-08 22:53         ` Sergei Ianovich
2013-12-09 14:26         ` Steve Cotton
2013-12-09 14:26           ` Steve Cotton
2013-12-09 14:42           ` Sergei Ianovich
2013-12-09 14:42             ` Sergei Ianovich
2013-12-08 22:53       ` [PATCH 4/9] ARM: pxa: remove unused variable Sergei Ianovich
2013-12-08 22:53         ` Sergei Ianovich
2013-12-09  8:56         ` Daniel Mack
2013-12-09  8:56           ` Daniel Mack
2013-12-09  9:42           ` Sergei Ianovich
2013-12-09  9:42             ` Sergei Ianovich
2013-12-09  9:49             ` Daniel Mack
2013-12-09  9:49               ` Daniel Mack
2013-12-08 22:53       ` [PATCH 5/9] ARM: dts: provide DMA config to pxamci Sergei Ianovich
2013-12-08 22:53         ` Sergei Ianovich
2013-12-08 22:53         ` Sergei Ianovich
2013-12-09  1:33         ` Arnd Bergmann
2013-12-09  1:33           ` Arnd Bergmann
2013-12-09  9:04           ` Daniel Mack
2013-12-09  9:04             ` Daniel Mack
2013-12-09  9:34             ` Sergei Ianovich
2013-12-09  9:34               ` Sergei Ianovich
2013-12-09  9:53               ` Sergei Ianovich
2013-12-09  9:53                 ` Sergei Ianovich
2013-12-09 10:21               ` Daniel Mack
2013-12-09 10:21                 ` Daniel Mack
2013-12-09 12:09                 ` Sergei Ianovich
2013-12-09 12:09                   ` Sergei Ianovich
2013-12-09 12:09                   ` Sergei Ianovich
2013-12-10  0:25                   ` Arnd Bergmann
2013-12-10  0:25                     ` Arnd Bergmann
2013-12-10  4:25                     ` Sergei Ianovich
2013-12-10  4:25                       ` Sergei Ianovich
2013-12-09 13:16                 ` Sergei Ianovich
2013-12-09 13:16                   ` Sergei Ianovich
2013-12-11  8:19             ` Robert Jarzmik
2013-12-11  8:19               ` Robert Jarzmik
2013-12-11  8:19               ` Robert Jarzmik
2013-12-08 22:53       ` [PATCH 6/9] ARM: dts: pxa3xx: move declaration to header Sergei Ianovich
2013-12-08 22:53         ` Sergei Ianovich
2013-12-09  1:13         ` Arnd Bergmann
2013-12-09  1:13           ` Arnd Bergmann
2013-12-08 22:53       ` [PATCH 7/9] ARM: dts: pxa27x: skip static platform devices Sergei Ianovich
2013-12-08 22:53         ` Sergei Ianovich
2013-12-09 15:26         ` Dmitry Eremin-Solenikov
2013-12-08 22:53       ` [PATCH 8/9] ARM: dts: pxa27x: device tree irq init Sergei Ianovich
2013-12-08 22:53         ` Sergei Ianovich
2013-12-08 22:53       ` [PATCH 9/9] ARM: pxa27x: device tree support ICP DAS LP-8x4x Sergei Ianovich
2013-12-08 22:53         ` Sergei Ianovich
2013-12-08 22:53         ` Sergei Ianovich
2013-12-09  1:47         ` Arnd Bergmann
2013-12-09  1:47           ` Arnd Bergmann
2013-12-09 15:16           ` Sergei Ianovich
2013-12-09 15:16             ` Sergei Ianovich
2013-12-09 15:55             ` Sergei Ianovich
2013-12-09 15:55               ` Sergei Ianovich
2013-12-09 16:39               ` Arnd Bergmann
2013-12-09 16:39                 ` Arnd Bergmann
2013-12-09 16:39                 ` Arnd Bergmann
2013-12-09 16:25             ` Arnd Bergmann
2013-12-09 16:25               ` Arnd Bergmann
2013-12-09  1:51       ` [PATCH 0/9] ARM: support for ICP DAS LP-8x4x (with dts) Arnd Bergmann
2013-12-09  1:51         ` Arnd Bergmann
2013-12-09 18:44         ` Sergei Ianovich
2013-12-09 18:44           ` Sergei Ianovich
2013-12-13  2:27       ` [PATCH v2 00/16] " Sergei Ianovich
2013-12-13  2:27         ` Sergei Ianovich
2013-12-13  2:27         ` [PATCH v2 01/16] ARM: dts: pxa2xx fix compatible strings Sergei Ianovich
2013-12-13  2:27           ` Sergei Ianovich
2013-12-13  2:27           ` Sergei Ianovich
2013-12-13  2:27         ` [PATCH v2 02/16] ARM: dts: fix pxa27x-gpio interrupts Sergei Ianovich
2013-12-13  2:27           ` Sergei Ianovich
2013-12-13  2:27           ` Sergei Ianovich
2013-12-13  2:27         ` [PATCH v2 03/16] ARM: dts: provide DMA config to pxamci Sergei Ianovich
2013-12-13  2:27           ` Sergei Ianovich
2013-12-13  2:27           ` Sergei Ianovich
2013-12-14 19:06           ` Arnd Bergmann
2013-12-14 19:06             ` Arnd Bergmann
2013-12-14 19:06             ` Arnd Bergmann
2013-12-14 19:34             ` Sergei Ianovich
2013-12-14 19:34               ` Sergei Ianovich
2013-12-14 23:39               ` Arnd Bergmann
2013-12-14 23:39                 ` Arnd Bergmann
2013-12-16  9:58               ` Daniel Mack
2013-12-16  9:58                 ` Daniel Mack
2013-12-16 11:47                 ` Sergei Ianovich
2013-12-16 11:47                   ` Sergei Ianovich
2013-12-16 11:58                   ` Lars-Peter Clausen
2013-12-16 11:58                     ` Lars-Peter Clausen
2013-12-16 11:58                     ` Lars-Peter Clausen
2013-12-16 12:03                     ` Sergei Ianovich
2013-12-16 12:03                       ` Sergei Ianovich
2013-12-13  2:27         ` [PATCH v2 04/16] ARM: dts: pxa3xx: move declaration to header Sergei Ianovich
2013-12-13  2:27           ` Sergei Ianovich
2013-12-13  2:27         ` [PATCH v2 05/16] ARM: dts: pxa27x: irq init using device tree Sergei Ianovich
2013-12-13  2:27           ` Sergei Ianovich
2013-12-13  2:27         ` [PATCH v2 06/16] ARM: pxa27x: device tree support ICP DAS LP-8x4x Sergei Ianovich
2013-12-13  2:27           ` Sergei Ianovich
2013-12-13  2:27           ` Sergei Ianovich
2013-12-13  2:27         ` [PATCH v2 07/16] rtc: support DS1302 RTC on " Sergei Ianovich
2013-12-13  2:27           ` Sergei Ianovich
2013-12-13  2:27           ` Sergei Ianovich
2013-12-13  2:27         ` [PATCH v2 08/16] mtd: support BB SRAM " Sergei Ianovich
2013-12-13  2:27           ` Sergei Ianovich
2013-12-13  2:27           ` Sergei Ianovich
2013-12-13  2:27           ` Sergei Ianovich
2013-12-13  2:27         ` [PATCH v2 09/16] ARM: pxa: support ICP DAS LP-8x4x FPGA irq Sergei Ianovich
2013-12-13  2:27           ` Sergei Ianovich
2013-12-13  2:27           ` Sergei Ianovich
2013-12-13  2:27         ` [PATCH v2 10/16] serial: support for 16550A serial ports on LP-8x4x Sergei Ianovich
2013-12-13  2:27           ` Sergei Ianovich
2013-12-13  2:27           ` Sergei Ianovich
2013-12-13  2:27         ` [PATCH v2 11/16] misc: support for LP-8x4x custom parallel bus Sergei Ianovich
2013-12-13  2:27           ` Sergei Ianovich
2013-12-13  2:27           ` Sergei Ianovich
2013-12-13  2:27         ` [PATCH v2 12/16] misc: support for serial slots in LP-8x4x Sergei Ianovich
2013-12-13  2:27           ` Sergei Ianovich
2013-12-13  2:27           ` Sergei Ianovich
2013-12-13  2:27         ` [PATCH v2 13/16] misc: support for parallel " Sergei Ianovich
2013-12-13  2:27           ` Sergei Ianovich
2013-12-13  2:27         ` [PATCH v2 14/16] misc: support for I-8041 " Sergei Ianovich
2013-12-13  2:27           ` Sergei Ianovich
2013-12-13  2:27         ` [PATCH v2 15/16] misc: support for I-8042 " Sergei Ianovich
2013-12-13  2:27           ` Sergei Ianovich
2013-12-13  2:27         ` [PATCH v2 16/16] misc: support for I-8024 " Sergei Ianovich
2013-12-13  2:27           ` Sergei Ianovich
2013-12-14 20:59           ` Arnd Bergmann
2013-12-14 20:59             ` Arnd Bergmann
2013-12-14 23:03             ` Sergei Ianovich
2013-12-14 23:03               ` Sergei Ianovich
2013-12-13  2:33         ` [PATCH v2 00/16] ARM: support for ICP DAS LP-8x4x (with dts) Sergei Ianovich
2013-12-13  2:33           ` Sergei Ianovich
2013-12-14 21:03         ` Arnd Bergmann
2013-12-14 21:03           ` Arnd Bergmann
2013-12-14 21:55           ` Sergei Ianovich
2013-12-14 21:55             ` Sergei Ianovich
2013-12-15  0:53             ` Arnd Bergmann
2013-12-15  0:53               ` Arnd Bergmann
2013-12-15  2:12               ` Sergei Ianovich
2013-12-15  2:12                 ` Sergei Ianovich
2013-12-15  2:55                 ` Arnd Bergmann
2013-12-15  2:55                   ` Arnd Bergmann
2013-12-16 13:01                   ` Sergei Ianovich
2013-12-16 13:01                     ` Sergei Ianovich
2013-12-16 17:56                     ` Arnd Bergmann
2013-12-16 17:56                       ` Arnd Bergmann
2013-12-16 20:38                       ` Sergei Ianovich
2013-12-16 20:38                         ` Sergei Ianovich
2013-12-18 20:50                         ` Arnd Bergmann
2013-12-18 20:50                           ` Arnd Bergmann
2013-12-18 20:56                           ` Sergei Ianovich
2013-12-18 20:56                             ` Sergei Ianovich
2013-12-18 21:10                             ` Arnd Bergmann
2013-12-18 21:10                               ` Arnd Bergmann
2013-12-18 21:20                               ` Sergei Ianovich
2013-12-18 21:20                                 ` Sergei Ianovich
2013-12-19  5:30                                 ` Arnd Bergmann
2013-12-19  5:30                                   ` Arnd Bergmann
2014-01-09 23:12                                   ` Sergei Ianovich
2014-01-09 23:12                                     ` Sergei Ianovich
2014-01-20 16:08                                     ` Sergei Ianovich
2014-01-20 16:08                                       ` Sergei Ianovich
2014-01-20 16:20                                       ` Daniel Mack
2014-01-20 16:20                                         ` Daniel Mack
2014-01-20 16:52                                         ` Sergei Ianovich
2014-01-20 16:52                                           ` Sergei Ianovich
2014-01-20 16:58                                           ` Daniel Mack
2014-01-20 16:58                                             ` Daniel Mack
2013-12-17 19:37         ` [PATCH v3 00/21] " Sergei Ianovich
2013-12-17 19:37           ` Sergei Ianovich
2013-12-17 19:37           ` [PATCH v3 01/21 resend] serial: rewrite pxa2xx-uart to use 8250_core Sergei Ianovich
2013-12-17 19:37             ` Sergei Ianovich
2013-12-17 19:37             ` Sergei Ianovich
2013-12-18 23:55             ` Greg Kroah-Hartman
2013-12-18 23:55               ` Greg Kroah-Hartman
2013-12-19  8:51             ` Heikki Krogerus
2013-12-19  8:51               ` Heikki Krogerus
2013-12-19  9:35               ` Sergei Ianovich
2013-12-19  9:35                 ` Sergei Ianovich
2013-12-19 10:01                 ` Sergei Ianovich
2013-12-19 10:01                   ` Sergei Ianovich
2013-12-19 11:05                   ` Heikki Krogerus
2013-12-19 11:05                     ` Heikki Krogerus
2013-12-17 19:37           ` [PATCH v3 02/21] ARM: dts: pxa2xx fix compatible strings Sergei Ianovich
2013-12-17 19:37             ` Sergei Ianovich
2013-12-17 19:37             ` Sergei Ianovich
2013-12-17 19:37           ` [PATCH v3 03/21] ARM: dts: fix pxa27x-gpio interrupts Sergei Ianovich
2013-12-17 19:37             ` Sergei Ianovich
2013-12-17 19:37             ` Sergei Ianovich
2013-12-17 19:37           ` [PATCH v3 04/21] ARM: dts: pxa3xx: move declaration to header Sergei Ianovich
2013-12-17 19:37             ` Sergei Ianovich
2013-12-17 19:37           ` [PATCH v3 05/21] ARM: dts: pxa27x: irq init using device tree Sergei Ianovich
2013-12-17 19:37             ` Sergei Ianovich
2013-12-17 19:37           ` [PATCH v3 06/21] ARM: dts: provide DMA config to pxamci on PXA27x Sergei Ianovich
2013-12-17 19:37             ` Sergei Ianovich
2013-12-17 19:37             ` Sergei Ianovich
2013-12-17 19:37           ` [PATCH v3 07/21] ARM: dts: parse DMA config in pxamci Sergei Ianovich
2013-12-17 19:37             ` Sergei Ianovich
2013-12-19  0:50             ` Sergei Ianovich
2013-12-19  0:50               ` Sergei Ianovich
2013-12-17 19:37           ` [PATCH v3 08/21] ARM: pxa27x: device tree support ICP DAS LP-8x4x Sergei Ianovich
2013-12-17 19:37             ` Sergei Ianovich
2013-12-17 19:37             ` Sergei Ianovich
2013-12-17 19:37           ` [PATCH v3 09/21] rtc: support DS1302 RTC on " Sergei Ianovich
2013-12-17 19:37             ` Sergei Ianovich
2013-12-17 19:37             ` Sergei Ianovich
2013-12-17 19:37           ` [PATCH v3 10/21] mtd: support BB SRAM " Sergei Ianovich
2013-12-17 19:37             ` Sergei Ianovich
2013-12-17 19:37             ` Sergei Ianovich
2013-12-17 19:37             ` Sergei Ianovich
2014-04-16  5:04             ` Brian Norris
2014-04-16  5:04               ` Brian Norris
2014-04-16  5:04               ` Brian Norris
2014-04-16  5:21               ` Sergei Ianovich
2014-04-16  5:21                 ` Sergei Ianovich
2014-04-16  5:21                 ` Sergei Ianovich
2013-12-17 19:37           ` [PATCH v3 11/21] ARM: pxa: support ICP DAS LP-8x4x FPGA irq Sergei Ianovich
2013-12-17 19:37             ` Sergei Ianovich
2013-12-17 19:37             ` Sergei Ianovich
2014-01-02 12:32             ` Linus Walleij
2014-01-02 12:32               ` Linus Walleij
2014-01-02 12:32               ` Linus Walleij
2014-01-08 19:01               ` Sergei Ianovich
2014-01-08 19:01                 ` Sergei Ianovich
2014-01-08 19:01                 ` Sergei Ianovich
2014-01-15  7:39                 ` Linus Walleij
2014-01-15  7:39                   ` Linus Walleij
2014-01-15  7:39                   ` Linus Walleij
2014-01-15 13:17                   ` Sergei Ianovich
2014-01-15 13:17                     ` Sergei Ianovich
2014-01-15 13:17                     ` Sergei Ianovich
2014-01-09 23:07             ` [PATCH v3.1 " Sergei Ianovich
2014-01-09 23:07               ` Sergei Ianovich
2014-01-09 23:07               ` Sergei Ianovich
2014-01-15  7:46               ` Linus Walleij
2014-01-15  7:46                 ` Linus Walleij
2014-01-15  7:46                 ` Linus Walleij
2014-01-15 13:12               ` [PATCH v3.2 " Sergei Ianovich
2014-01-15 13:12                 ` Sergei Ianovich
2014-01-15 13:12                 ` Sergei Ianovich
2013-12-17 19:37           ` [PATCH v3 12/21] serial: support for 16550A serial ports on LP-8x4x Sergei Ianovich
2013-12-17 19:37             ` Sergei Ianovich
2013-12-17 19:37             ` Sergei Ianovich
2013-12-19 11:18             ` Heikki Krogerus
2013-12-19 11:18               ` Heikki Krogerus
2013-12-17 19:37           ` [PATCH v3 13/21] misc: support for LP-8x4x custom parallel bus Sergei Ianovich
2013-12-17 19:37             ` Sergei Ianovich
2013-12-17 19:37             ` Sergei Ianovich
2013-12-17 19:37           ` [PATCH v3 14/21] misc: support for LP-8x4x rotary switch Sergei Ianovich
2013-12-17 19:37             ` Sergei Ianovich
2013-12-17 19:37             ` Sergei Ianovich
2013-12-17 19:37           ` [PATCH v3 15/21] misc: support for LP-8x4x DIP switch Sergei Ianovich
2013-12-17 19:37             ` Sergei Ianovich
2013-12-17 19:37             ` Sergei Ianovich
2013-12-17 19:37           ` [PATCH v3 16/21] misc: support for writing to LP-8x4x EEPROM Sergei Ianovich
2013-12-17 19:37             ` Sergei Ianovich
2013-12-17 19:37             ` Sergei Ianovich
2013-12-17 19:37           ` [PATCH v3 17/21] misc: support for serial slots in LP-8x4x Sergei Ianovich
2013-12-17 19:37             ` Sergei Ianovich
2013-12-17 19:37             ` Sergei Ianovich
2013-12-17 19:37           ` [PATCH v3 18/21] misc: support for parallel " Sergei Ianovich
2013-12-17 19:37             ` Sergei Ianovich
2013-12-17 19:37             ` Sergei Ianovich
2013-12-17 19:37           ` [PATCH v3 19/21] misc: support for I-8041 " Sergei Ianovich
2013-12-17 19:37             ` Sergei Ianovich
2013-12-17 19:37           ` [PATCH v3 20/21] misc: support for I-8042 " Sergei Ianovich
2013-12-17 19:37             ` Sergei Ianovich
2013-12-17 19:37           ` [PATCH v3 21/21] misc: support for I-8024 " Sergei Ianovich
2013-12-17 19:37             ` Sergei Ianovich
2014-04-16 17:13           ` [PATCH v4 00/21] ARM: support for ICP DAS LP-8x4x (with dts) Sergei Ianovich
2014-04-16 17:13             ` Sergei Ianovich
2014-04-16 17:13             ` [PATCH v4 01/21] serial: rewrite pxa2xx-uart to use 8250_core Sergei Ianovich
2014-04-16 17:13               ` Sergei Ianovich
2014-04-16 17:13               ` Sergei Ianovich
2015-01-19 18:08               ` Rob Herring
2015-01-19 18:08                 ` Rob Herring
2015-01-19 18:08                 ` Rob Herring
2014-04-16 17:13             ` [PATCH v4 02/21] ARM: dts: pxa2xx fix compatible strings Sergei Ianovich
2014-04-16 17:13               ` Sergei Ianovich
2014-04-16 17:13               ` Sergei Ianovich
2014-04-16 17:13             ` [PATCH v4 03/21] ARM: dts: fix pxa27x-gpio interrupts Sergei Ianovich
2014-04-16 17:13               ` Sergei Ianovich
2014-04-16 17:13               ` Sergei Ianovich
2014-04-16 17:13             ` [PATCH v4 04/21] ARM: dts: pxa3xx: move declaration to header Sergei Ianovich
2014-04-16 17:13               ` Sergei Ianovich
2014-04-16 17:13             ` [PATCH v4 05/21] ARM: dts: pxa27x: irq init using device tree Sergei Ianovich
2014-04-16 17:13               ` Sergei Ianovich
2014-04-16 17:13             ` [PATCH v4 06/21] ARM: dts: provide DMA config to pxamci on PXA27x Sergei Ianovich
2014-04-16 17:13               ` Sergei Ianovich
2014-04-16 17:13               ` Sergei Ianovich
2014-04-16 17:17               ` [PATCH v4 07/21] ARM: dts: parse DMA config in pxamci Sergei Ianovich
2014-04-16 17:17                 ` Sergei Ianovich
2014-04-16 17:17                 ` [PATCH v4 08/21] ARM: pxa27x: device tree support ICP DAS LP-8x4x Sergei Ianovich
2014-04-16 17:17                   ` Sergei Ianovich
2014-04-16 17:17                   ` Sergei Ianovich
2014-04-17 10:54                   ` Daniel Mack
2014-04-16 17:17                 ` [PATCH v4 09/21] rtc: support DS1302 RTC on " Sergei Ianovich
2014-04-16 17:17                   ` Sergei Ianovich
2014-04-16 17:17                   ` Sergei Ianovich
2014-04-16 17:17                   ` [v4,09/21] " Sergey Yanovich
2015-06-08 12:07                   ` Alexandre Belloni
2015-06-08 12:07                     ` Alexandre Belloni
2015-06-08 12:12                     ` Sergei Ianovich
2015-06-08 12:12                       ` Sergei Ianovich
2015-06-08 12:12                       ` [rtc-linux] " Sergei Ianovich
2014-04-16 17:17                 ` [PATCH v4 10/21] mtd: support BB SRAM " Sergei Ianovich
2014-04-16 17:17                   ` Sergei Ianovich
2014-04-16 17:17                   ` Sergei Ianovich
2014-04-16 17:17                   ` Sergei Ianovich
2014-04-30 17:21                   ` Brian Norris
2014-04-30 17:21                     ` Brian Norris
2014-04-30 17:21                     ` Brian Norris
2014-04-30 17:35                     ` ООО "ЭлектроПлюс"
2014-04-30 17:35                       ` ООО "ЭлектроПлюс"
2014-04-30 17:35                       ` ООО "ЭлектроПлюс"
2015-12-15 18:58                   ` [PATCH v5] " Sergei Ianovich
2015-12-15 18:58                     ` Sergei Ianovich
2015-12-20  3:38                     ` Rob Herring
2015-12-20  3:38                       ` Rob Herring
2015-12-20 10:43                       ` Sergei Ianovich
2015-12-20 10:43                         ` Sergei Ianovich
2015-12-20 10:43                         ` Sergei Ianovich
2016-01-06 23:25                         ` Brian Norris
2016-01-06 23:25                           ` Brian Norris
2016-01-06 23:25                           ` Brian Norris
2016-02-23 18:58                     ` [PATCH v6] " Sergei Ianovich
2016-02-23 18:58                       ` Sergei Ianovich
2016-02-23 19:48                       ` Rob Herring
2016-02-23 19:48                         ` Rob Herring
2016-02-23 19:48                         ` Rob Herring
2016-03-08  0:19                       ` Brian Norris
2016-03-08  0:19                         ` Brian Norris
2016-03-08  0:19                         ` Brian Norris
2014-04-16 17:17                 ` [PATCH v4 11/21] ARM: pxa: support ICP DAS LP-8x4x FPGA irq Sergei Ianovich
2014-04-16 17:17                   ` Sergei Ianovich
2014-04-16 17:17                   ` Sergei Ianovich
2015-12-15 19:26                   ` [PATCH v5] arm: " Sergei Ianovich
2015-12-15 19:26                     ` Sergei Ianovich
2015-12-16 11:54                     ` Marc Zyngier
2015-12-19  4:20                     ` Rob Herring
2015-12-19  4:20                       ` Rob Herring
     [not found]                     ` <20151219035802.GA28424@rob-hp-laptop>
2015-12-19  7:03                       ` Sergei Ianovich
2015-12-19  7:03                         ` Sergei Ianovich
2016-02-27 15:56                     ` [PATCH v6] " Sergei Ianovich
2016-02-27 15:56                       ` Sergei Ianovich
2016-02-27 17:41                       ` Jason Cooper
2016-02-27 17:41                         ` Jason Cooper
2016-02-29  8:29                         ` Marc Zyngier
2016-02-29  8:29                           ` Marc Zyngier
2016-03-03 22:12                       ` Rob Herring
2016-03-03 22:12                         ` Rob Herring
2014-04-16 17:17                 ` [PATCH v4 12/21] serial: support for 16550A serial ports on LP-8x4x Sergei Ianovich
2014-04-16 17:17                   ` Sergei Ianovich
2014-04-16 17:17                   ` Sergei Ianovich
2014-04-16 18:35                   ` One Thousand Gnomes
2014-04-16 18:35                     ` One Thousand Gnomes
2014-04-16 18:35                     ` One Thousand Gnomes
2014-04-16 19:01                     ` Sergei Ianovich
2014-04-16 19:01                       ` Sergei Ianovich
2014-04-16 20:00                       ` One Thousand Gnomes
2014-04-16 20:00                         ` One Thousand Gnomes
2014-04-16 20:32                         ` Sergei Ianovich
2014-04-16 20:32                           ` Sergei Ianovich
2014-04-16 20:32                           ` Sergei Ianovich
2014-04-16 17:17                 ` [PATCH v4 13/21] misc: support for LP-8x4x custom parallel bus Sergei Ianovich
2014-04-16 17:17                   ` Sergei Ianovich
2014-04-16 17:17                   ` Sergei Ianovich
2014-04-16 18:41                   ` One Thousand Gnomes
2014-04-16 18:41                     ` One Thousand Gnomes
2014-04-16 18:41                     ` One Thousand Gnomes
2014-04-16 18:42                     ` Arnd Bergmann
2014-04-16 18:42                       ` Arnd Bergmann
2014-04-16 20:29                       ` One Thousand Gnomes
2014-04-16 20:29                         ` One Thousand Gnomes
2014-04-16 19:53                     ` Sergei Ianovich
2014-04-16 19:53                       ` Sergei Ianovich
2014-04-16 17:17                 ` [PATCH v4 14/21] misc: support for LP-8x4x rotary switch Sergei Ianovich
2014-04-16 17:17                   ` Sergei Ianovich
2014-04-16 17:17                   ` Sergei Ianovich
2014-04-16 17:17                 ` [PATCH v4 15/21] misc: support for LP-8x4x DIP switch Sergei Ianovich
2014-04-16 17:17                   ` Sergei Ianovich
2014-04-16 17:17                   ` Sergei Ianovich
2014-04-16 17:17                 ` [PATCH v4 16/21] misc: support for writing to LP-8x4x EEPROM Sergei Ianovich
2014-04-16 17:17                   ` Sergei Ianovich
2014-04-16 17:17                   ` Sergei Ianovich
2014-04-16 17:17                 ` [PATCH v4 17/21] misc: support for serial slots in LP-8x4x Sergei Ianovich
2014-04-16 17:17                   ` Sergei Ianovich
2014-04-16 17:17                   ` Sergei Ianovich
2014-04-16 17:17                 ` [PATCH v4 18/21] misc: support for parallel " Sergei Ianovich
2014-04-16 17:17                   ` Sergei Ianovich
2014-04-16 17:17                   ` Sergei Ianovich
2014-04-16 17:17                 ` [PATCH v4 19/21] misc: support for I-8041 " Sergei Ianovich
2014-04-16 17:17                   ` Sergei Ianovich
2014-04-16 17:17                 ` [PATCH v4 20/21] misc: support for I-8042 " Sergei Ianovich
2014-04-16 17:17                   ` Sergei Ianovich
2014-04-16 17:17                 ` [PATCH v4 21/21] misc: support for I-8024 " Sergei Ianovich
2014-04-16 17:17                   ` Sergei Ianovich
2014-04-16 18:39                   ` One Thousand Gnomes
2014-04-16 18:39                     ` One Thousand Gnomes
2014-04-16 19:28                     ` Sergei Ianovich
2014-04-16 19:28                       ` Sergei Ianovich
2014-04-16 19:56                       ` One Thousand Gnomes
2014-04-16 19:56                         ` One Thousand Gnomes
2014-04-16 20:06                         ` Sergei Ianovich
2014-04-16 20:06                           ` Sergei Ianovich
2015-12-15 21:04                 ` [PATCH v5] serial: support for 16550A serial ports on LP-8x4x Sergei Ianovich
2015-12-15 21:04                   ` Sergei Ianovich
2015-12-15 21:51                   ` Arnd Bergmann
2015-12-15 21:51                     ` Arnd Bergmann
2015-12-16  8:04                     ` Sergei Ianovich
2015-12-16  8:04                       ` Sergei Ianovich
2015-12-16 10:26                       ` Arnd Bergmann
2015-12-16 10:26                         ` Arnd Bergmann
2015-12-19  8:11                         ` Sergei Ianovich
2015-12-19  8:11                           ` Sergei Ianovich
2015-12-19 21:42                     ` Sergei Ianovich
2015-12-19 21:42                       ` Sergei Ianovich
2015-12-17 14:50                   ` Andy Shevchenko
2015-12-17 14:50                     ` Andy Shevchenko
2016-02-27 16:14                   ` [PATCH v6] " Sergei Ianovich
2016-02-27 16:14                     ` Sergei Ianovich
2016-02-29 10:29                     ` Andy Shevchenko
2016-02-29 10:29                       ` Andy Shevchenko
2016-02-29 13:03                       ` Sergei Ianovich
2016-02-29 13:03                         ` Sergei Ianovich
2016-02-29 14:45                         ` One Thousand Gnomes
2016-02-29 14:45                           ` One Thousand Gnomes
2016-02-29 21:26                     ` [PATCH v7] " Sergei Ianovich
2016-02-29 21:26                       ` Sergei Ianovich
2016-03-01 11:06                       ` Andy Shevchenko
2016-03-01 11:06                         ` Andy Shevchenko
2016-03-01 16:25                         ` Sergei Ianovich
2016-03-01 16:25                           ` Sergei Ianovich
2016-03-01 16:46                           ` Andy Shevchenko
2016-03-01 16:46                             ` Andy Shevchenko
2016-03-01 17:14                             ` Sergei Ianovich
2016-03-01 17:14                               ` Sergei Ianovich
2016-03-01 17:48                               ` Andy Shevchenko
2016-03-01 17:48                                 ` Andy Shevchenko
2016-03-01 18:43                                 ` One Thousand Gnomes
2016-03-01 18:43                                   ` One Thousand Gnomes
2016-03-01 19:28                                 ` Sergei Ianovich
2016-03-01 19:28                                   ` Sergei Ianovich
2016-03-01 19:53                                   ` One Thousand Gnomes
2016-03-01 19:53                                     ` One Thousand Gnomes
2016-03-01 19:54                       ` [PATCH v8] " Sergei Ianovich
2016-03-01 19:54                         ` Sergei Ianovich
2016-03-01 20:08                         ` [PATCH v9] " Sergei Ianovich
2016-03-01 20:08                           ` Sergei Ianovich
2016-03-01 20:23                           ` Andy Shevchenko
2016-03-01 20:23                             ` Andy Shevchenko
2016-03-01 21:25                           ` [PATCH v10] " Sergei Ianovich
2016-03-01 21:25                             ` Sergei Ianovich
2016-03-05  4:26                             ` Rob Herring
2016-03-05  4:26                               ` Rob Herring
2014-04-16 17:39             ` [PATCH v4 00/21] ARM: support for ICP DAS LP-8x4x (with dts) Daniel Mack
2014-04-16 17:39               ` Daniel Mack
2014-04-16 20:59               ` Sergei Ianovich
2014-04-16 20:59                 ` Sergei Ianovich
2014-04-17 10:38                 ` Daniel Mack
2014-04-17 10:38                   ` Daniel Mack
2014-04-17 12:12                   ` Sergei Ianovich
2014-04-17 12:12                     ` Sergei Ianovich
2014-04-17 12:34                     ` Daniel Mack
2014-04-17 12:34                       ` Daniel Mack
2014-04-19 11:59                       ` Arnd Bergmann
2014-04-19 11:59                         ` Arnd Bergmann
2015-12-09 22:28           ` [PATCH v4 0/2] series to support for ICP DAS LP-8x4x (ARM PXA270) Sergei Ianovich
2015-12-09 22:28             ` [PATCH v4 1/2] serial: rewrite pxa2xx-uart to use 8250_core Sergei Ianovich
2015-12-09 22:28               ` Sergei Ianovich
2015-12-09 22:28               ` Sergei Ianovich
2015-12-19 12:45               ` Robert Jarzmik
2015-12-19 12:45                 ` Robert Jarzmik
2015-12-19 12:45                 ` Robert Jarzmik
2015-12-19 13:26                 ` Robert Jarzmik
2015-12-19 13:26                   ` Robert Jarzmik
2015-12-19 13:26                   ` Robert Jarzmik
2015-12-19 18:46                   ` Sergei Ianovich
2015-12-19 18:46                     ` Sergei Ianovich
2015-12-19 19:31                     ` Robert Jarzmik
2015-12-19 19:31                       ` Robert Jarzmik
2015-12-19 19:31                       ` Robert Jarzmik
2015-12-19 20:12                       ` Sergei Ianovich
2015-12-19 20:12                         ` Sergei Ianovich
2015-12-19 23:12                         ` Robert Jarzmik
2015-12-19 23:12                           ` Robert Jarzmik
2015-12-19 23:12                           ` Robert Jarzmik
2015-12-20 11:24                           ` Sergei Ianovich
2015-12-20 11:24                             ` Sergei Ianovich
2015-12-22 19:27                             ` Robert Jarzmik
2015-12-22 19:27                               ` Robert Jarzmik
2015-12-22 19:27                               ` Robert Jarzmik
2015-12-23 18:59               ` [PATCH v5] " Sergei Ianovich
2015-12-23 18:59                 ` Sergei Ianovich
2015-12-23 22:50                 ` kbuild test robot
2015-12-23 22:50                   ` kbuild test robot
2015-12-24 15:15                 ` [PATCH v6] " Sergei Ianovich
2015-12-24 15:15                   ` Sergei Ianovich
2015-12-29 11:06                   ` Heikki Krogerus
2015-12-29 16:50                     ` Robert Jarzmik
2015-12-29 16:50                       ` Robert Jarzmik
2016-02-07  6:22                   ` Greg Kroah-Hartman
2016-02-22  1:56                     ` Sergei Ianovich
2016-02-22  7:17                       ` Robert Jarzmik
2016-02-22  7:17                         ` Robert Jarzmik
2016-09-27 15:47                         ` Robert Jarzmik
2016-09-27 15:47                           ` Robert Jarzmik
2016-09-27 16:12                           ` Greg Kroah-Hartman
2016-09-27 16:24                             ` Robert Jarzmik
2016-09-27 16:24                               ` Robert Jarzmik
2015-12-09 22:28             ` [PATCH v4 2/2] arm: pxa27x: support for ICP DAS LP-8x4x w/ DT Sergei Ianovich
2015-12-09 22:28               ` Sergei Ianovich
2015-12-09 22:28               ` Sergei Ianovich
2015-12-11  2:53               ` Rob Herring
2015-12-11  2:53                 ` Rob Herring
2015-12-11  2:53                 ` Rob Herring
2015-12-15 16:27               ` [PATCH v5 " Sergei Ianovich
2015-12-15 16:27                 ` Sergei Ianovich
2015-12-15 16:27                 ` Sergei Ianovich
2015-12-15 16:32                 ` Arnd Bergmann
2015-12-15 16:32                   ` Arnd Bergmann
2015-12-15 16:32                   ` Arnd Bergmann
2015-12-15 16:42                   ` Sergei Ianovich
2015-12-15 16:42                     ` Sergei Ianovich
2015-12-15 16:42                     ` Sergei Ianovich
2015-12-15 17:02                     ` Arnd Bergmann
2015-12-15 17:02                       ` Arnd Bergmann
2015-12-15 17:02                       ` Arnd Bergmann
2015-12-15 17:24                       ` Sergei Ianovich
2015-12-15 17:24                         ` Sergei Ianovich
2015-12-15 17:24                         ` Sergei Ianovich
2015-12-15 18:06                         ` Robert Jarzmik
2015-12-15 18:06                           ` Robert Jarzmik
2015-12-15 18:06                           ` Robert Jarzmik
2015-12-15 18:50                           ` Sergei Ianovich
2015-12-15 18:50                             ` Sergei Ianovich
2015-12-15 18:50                             ` Sergei Ianovich
2015-12-15 19:21                             ` Arnd Bergmann
2015-12-15 19:21                               ` Arnd Bergmann
2015-12-15 19:21                               ` Arnd Bergmann
2015-12-15 20:01                               ` Robert Jarzmik
2015-12-15 20:01                                 ` Robert Jarzmik
2015-12-15 20:01                                 ` Robert Jarzmik
2015-12-15 20:40                                 ` Arnd Bergmann
2015-12-15 20:40                                   ` Arnd Bergmann
2015-12-15 20:40                                   ` Arnd Bergmann
2015-12-19 12:27                       ` Robert Jarzmik
2015-12-19 12:27                         ` Robert Jarzmik
2015-12-19 12:27                         ` Robert Jarzmik
2015-12-19  7:53                 ` [PATCH] arm: pxa: create a unified defconfig for PXA27X-DT Sergei Ianovich
2015-12-19  7:53                   ` Sergei Ianovich
2013-12-10 12:43     ` [PATCH v2 02/11] arm: pxa27x: support ICP DAS LP-8x4x Linus Walleij
2013-12-10 12:43       ` Linus Walleij
2013-12-10 12:47       ` Sergei Ianovich
2013-12-10 12:47         ` Sergei Ianovich
2013-12-12 19:58         ` Linus Walleij
2013-12-12 19:58           ` Linus Walleij
2013-12-10 12:54       ` Vasily Khoruzhick
2013-12-10 12:54         ` Vasily Khoruzhick
2013-12-12 20:07         ` Linus Walleij
2013-12-12 20:07           ` Linus Walleij
2013-12-10 22:24       ` Dmitry Eremin-Solenikov
2013-12-01  6:26 ` [PATCH 03/11] rtc: support DS1302 RTC on " Sergei Ianovich
2013-12-01  6:26   ` Sergei Ianovich
2013-12-01  6:26 ` [PATCH 04/11] mtd: support BB SRAM " Sergei Ianovich
2013-12-01  6:26   ` Sergei Ianovich
2013-12-01  6:26   ` Sergei Ianovich
2013-12-01  6:26 ` [PATCH 05/11] serial: support for 16550 serial ports on LP-8x4x Sergei Ianovich
2013-12-01  6:26   ` Sergei Ianovich
2013-12-01  6:26   ` Sergei Ianovich
2013-12-02  8:48   ` Heikki Krogerus
2013-12-02  8:48     ` Heikki Krogerus
2013-12-02 11:46     ` Sergei Ianovich
2013-12-02 11:46       ` Sergei Ianovich
2013-12-02 13:53       ` Heikki Krogerus
2013-12-02 13:53         ` Heikki Krogerus
2013-12-02 11:30   ` Russell King - ARM Linux
2013-12-02 11:30     ` Russell King - ARM Linux
2013-12-02 11:39     ` Sergei Ianovich
2013-12-02 11:39       ` Sergei Ianovich
2013-12-02 11:52       ` Russell King - ARM Linux
2013-12-02 11:52         ` Russell King - ARM Linux
2013-12-02 12:01         ` Sergei Ianovich
2013-12-02 12:01           ` Sergei Ianovich
2013-12-01  6:26 ` [PATCH 06/11] misc: support for LP-8x4x custom parallel bus Sergei Ianovich
2013-12-01  6:26   ` Sergei Ianovich
2013-12-01  6:26 ` [PATCH 07/11] misc: support for serial slots in LP-8x4x Sergei Ianovich
2013-12-01  6:26   ` Sergei Ianovich
2013-12-01  6:26 ` [PATCH 08/11] misc: support for parallel " Sergei Ianovich
2013-12-01  6:26   ` Sergei Ianovich
2013-12-01  6:26 ` [PATCH 09/11] misc: support for I-8041 " Sergei Ianovich
2013-12-01  6:26   ` Sergei Ianovich
2013-12-01  6:26 ` [PATCH 10/11] misc: support for I-8042 " Sergei Ianovich
2013-12-01  6:26   ` Sergei Ianovich
2013-12-01  6:26 ` [PATCH 11/11] misc: support for I-8024 " Sergei Ianovich
2013-12-01  6:26   ` Sergei Ianovich

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.